[MAP] Premade map to mapscript converter

xyx

Chieftain
Joined
Aug 7, 2013
Messages
48
I needed this myself and was somewhat perplexed that noone seems to have created this in a way in needed this, sooo....

This script creates a (deterministic) mapscript from the currently displayed map, so you get an exact copy of a map and can use it as a regular mapscript. Everything on the map is preserved, including goody huts, but excluding other improvements, cities, and units.

This allows you to convert any predefined map (aka worldbuilder save aka scenario) or any other map for that matter to a mapscript and thus select the leaders and civilizations you like, use, partly use, or ignore the starting locations, leave or randomize bonuses and/or goody huts. If you always wanted to play a premade earth map (or wanted to replay a random map) with different leaders, different civs, a different number of civs, or different bonus distributions, this may be for you.

The script should work with any mod (though I did only limited testing). There's limited crossmod support, but don't expect this to work when trying to convert a map made with a mod that changes terrain, bonuses, features, or civilizations to another mod.

Usage
  • Put savemap.py file into Assets\Python
  • Start a game or open a worlbuilder save
  • open the python console (in cheatmode)
  • enter: "import savemap"
  • enter: "savemap.savemap()" or "savemap.savemap(x)" where x a number.
The mapscript gets stored as "civ4mapX.py" in "~Documents\My Games\Beyond The Sword\PublicMaps" (you can change this by setting a different pathname in savemap.py).

If you play with a mod, copy the created mapscript to the "private maps" folder in your mod directory, it won't work otherwise. You may rename the mapscript to your liking.

To play, just start a regular or custom game (do not open a scenario) and choose the created map. Pick the civs and leaders to your liking. You have the following options:

Starting Positions
  • "Use Fixed Starting Locations": Assigns each civ to its defined starting position. If there is no starting position defined for particular civ, place it at another predefined location (if available). If there are more civs than starting position, place the unassigned civ somewhere else. So, if you play with Rome and England (but without Mali) on a map with starting positions for Rome and Mali (but none for England): Rome gets placed on Rome, England gets placed (a) on an unused defined starting location (such as Mali) or, if no location is left, (b) somewhere else.
  • "Use Fixed Starting Locations, but assign Civs at Random": Assigns each civ at random to a predefined starting position. If there are more civs than starting position, place the unassigned civ somewhere else. So Greece might get the position of Zulu and Zulu might get the position of France and so on.
  • "Ignore Fixed Locations": Civs get placed wherever they fit, predefined starting locations are ignored.
Bonuses
  • "Use fixed Bonuses": Places bonuses as defined in the map
  • "Randomize Bonuses": Bonuses are placed at random, predefined bonus locations are ignored.
Goody Huts
  • "Use fixed Goody Huts": Places Goody Huts as defined in the map
  • "Randomize Goody Huts": Goody Huts are placed at random, predefined Goody Huts are ignored.
Note that the "Map Size" option is ignored, as the generated map will always be an exact copy of the initial map.

As a teaser, see the saveMap_AccurateEarth script, which is a mapscript (for BTS) created from the Accurate Earth Map (132 x 64). If you pick the same 12 civs as defined in the Accurate Earth premade map (American, Aztec, Chinese, Egyptian, English (in South Africa), French (in Southeast Asia), Greek, Incan, Indian, Malinese, Mongolian, Persian), these will appear at their appropriate starting locations ("Fixed Starting") or randomly distributed across starting positions ("Fixed Starting with Random Assignment") or placed entirely at random ("Ignore Fixed"). If you swap one Civ (say, America) with another one (say, Spain), the latter will appear at the location of the first one (if using "Fixed Starting"). If you add additional civs, they will be placed wherever they fit. Bonuses will either appear as defined in the Accurate Earth map ("Fixed Bonuses") or are placed randomly ("Randomize Bonuses").

Finally a note on starting locations:
When run at gamestart, the script attempts to determine starting locations by obtaining the plot coordinates of the first settler of each civ. If there's no settler or when the script is run after the first game turn, the script resorts to the predefined starting locations. Always using the predefined starting location won't work reliably when civs are moved through the world builder. Unfortunately, the settler method is also somewhat unreliable in this case. The script prints the found settler (or starting location) of each civ to the console, so it makes sense to check whether all civs have been found. If something goes wrong, it might help to save and reload the wb file.

This is a modification of tywiggins save map script: https://apolyton.net/forum/civilization-iv/civilization-iv-creation/165900-python-save-map which somehow seems to have been forgotten.
 

Attachments

  • accurateEarth.JPG
    accurateEarth.JPG
    340.8 KB · Views: 377
  • saveMap.7z
    16.7 KB · Views: 177
Last edited:
Thanks for posting this.

For multiplayer support, Python's RNG may have to be seeded by MapRand like it's done here in the PerfectWorld script.
Looks like the converter should work past turn 0, at least if one disables the Settler search after turn 0.
A sparser data structure (list of pairs) for feature variety, rivers and improvements would be nice; should cut the file size in half. But maybe not worth the trouble.
(All rather unimportant nitpicks.)

I have a mind to integrate savemap into AdvCiv but don't know if I'll find the time. With a DLL that exposes the "Change Player" mod component to Python, one could have an option that overrides the civ and leader selection from the Custom Game screen with the civs and leaders from the original map. It would also be nice to store the name of the original map script, the original game options and custom map options in the script file; at least as a comment. Since I'm already including that info in the first replay message (CvReplayInfo::addSettingsMsg), that shouldn't be difficult to implement. And I'd like to assign a hotkey to the savemap function through the BUG config files, perhaps Alt+Shift+M (Alt+M is Reminder, Ctrl+Shift+M is AI Auto Play: "Move all units").
 
Thanks for your feedback, makes perfect sense. I updated the script so that it should be multiplayer safe, prints some map information, works beyond the first game turn, and uses a more reasonable data structure (thanks for this, I actually just copied that part from tywiggins script and did not really think about it).

Would be nice to see this integrated in AdvCiv, in particular a hotkey would come handy.
 
Last edited:
I'm glad that I've asked; thanks for taking up my thinly veiled requests. :p I'll include the script in AdvCiv 0.97. Don't know if I'll implement the "original players" option by then, but the BUG/AdvCiv integration is done: Git commit

Edit: It's a bit unfortunate that the saved map script can't be immediately selected after returning to the main menu. I suppose that can't be helped; I'm not aware of any function that would cause the EXE to rescan the file system for Python modules. (The reload upon editing+saving a previously loaded Python file also doesn't seem to cover newly added files.)

Edit (May): I've released AdvCiv 0.97 with savemap. link (download database)
 
Last edited:
Great to see this included in AdvCiv. So my script is actually obsolete by now, since I'd recommend anyone to play AdvCiv anyway :)

Don't know if I'll implement the "original players" option by then

Just being curious: I thought the custom game screen is hidden in the exe? How do you plan to make it such that the civs being selected get predetermined?
 
Great to see this included in AdvCiv. So my script is actually obsolete by now, since I'd recommend anyone to play AdvCiv anyway :)
:borg:
Just being curious: I thought the custom game screen is hidden in the exe? How do you plan to make it such that the civs being selected get predetermined?
I'd like to use CvPlayer::changeCiv and changeLeader (from the Change Player mod included in BBAI/AdvCiv) based on data loaded from the map script once the game has started (before showing the Dawn-of-Man screen). The selection on the Custom Game screen would then be ignored, and, if the player wants to know before starting the game who the original the players were, he or she will have to open the map script file. (If the map description text lists the players, then the info will also be available through "Play Now".)

I think one can use e.g. CvInitCore::setLeader to change the information that the Custom Game screen displays, but I don't think one can bring the screen to update itself at the proper times. If the goal is just to dsiplay the original players somewhere – I've recently noticed that the "Full of Resources" script shows a popup upon being selected on the Custom Game screen. Apparently, one can also show a popup when a particular option selection changes. Or one could list the player names as part of the description text of the "original players" option selection, maybe using multiple redundant selections for extra space. E.g.
Players: [Custom]
[Original: Alexander, Bismarck, Huayna Capac]
[... Joao II, Washington, Mansa Musa]​

Sounds a bit tedious to implement, so I probably won't bother.
 
I agree, that sounds a too complicated for the benefit.
 
Top Bottom