View Full Version : [Map Script] PerfectWorld.py
cephalo Aug 23, 2007, 04:54 PM Hi Folks!
This file has been superceded by PerfectWorld2, which you can get from
this thread. (http://forums.civfanatics.com/showthread.php?t=310891) The original PerfectWorld map script is available below for those who prefer it to the new one.
This map script for Warlords or BtS and most mods based on Civ4 generates a random, earth-like map, usually with a 'New World' with no starting locations that can only be reached with ocean going technology. Landforms are created using a random heightfield and a plate tectonic scheme. Climate is simulated using the interaction between the landforms and geostrophic winds. Though great pains are taken to semi-accurately simulate landforms and climate, the goal must be to make unpredictible, beautiful looking maps that are fun to play on.
Download the original version of PerfectWorld here from the bottom of this thread. (http://forums.civfanatics.com/attachment.php?attachmentid=204217&stc=1&d=1234918958)
To use this map, put it in your Civilization 4\PublicMaps folder, not in your My Documents\My Games\Civilization 4\PublicMaps folder.
-- Map Options --
New World Rules:
Start in Old World(Default): Reserves some continents to act as a new world
Start Anywhere: Disables the new world functionality
Pangaea Rules:
Break Pangaeas(Default): Breaks up Pangaeas with a simulated meteor shower (really big meteors)
Allow Pangaeas: Allow pangaeas to exist. Keep in mind that this will likely eliminate any 'New World' as well.
-- Summary of creation process: --
First, a random heightfield is created using midpoint displacement. The resulting altitudes are then modified by a plate tectonics scheme that grows random plates and raises the altitudes near the plate borders to create mountain ranges and island chains.
In generating the plot types from a heightmap, I had found that using peaks for high altitude and land for less altitude created large clusters of peaks, surrounded by a donut of hills, surrounded again by a donut of land. This looked absolutely terrible for Civ, so I made it such that peaks and hills are determined by altitude *differences* rather than by absolute altitude. This approach looks much better and more natural.
The terrain generator gives the other needed visual cues to communicate altitude. Since air temperature gets colder with altitude, the peaks will be plots of ice and tundra, even near the equator, if the altitude is high enough. Prevailing winds, temperature and rainfall are all simulated in the terrain generator. You will notice that the deserts and rainforests are where they should be, as well as rain shadows behind mountain ranges.
Rivers and lakes are also generated from the heightmap and follow accurate drainage paths, although with such a small heightmap some randomness needs to be thrown in to prevent rivers from being merely straight lines.
Map bonuses are placed following the XML Rules but slightly differently than the default implimentation to better accomodate this map script.
I've always felt that the most satisfying civ games are the ones that provide a use for those explorers and caravels. Though the map generator does not explicitly create a 'New World', it will take advantage of any continents that can serve that purpose. No starting locations will be placed on these continents. Therefore, the likelyhood of a significant new world is very high, but not guaranteed. It might also come in the form of multiple smaller 'New Worlds' rather than a large continent.
Enjoy!
Here are some screenshots to illustrate some of the features of PerfectWorld.
Here is a typical example of a standard sized map overview.
http://forums.civfanatics.com/attachment.php?attachmentid=170608&stc=1&d=1204769766
From the same map as above, here is a valley near the equator. Notice how the terrain and features subtly communicate altitude. The hot jungle lowlands are kindof snaking through some higher, and slightly colder, altitudes.
http://forums.civfanatics.com/attachment.php?attachmentid=170607&stc=1&d=1204769766
From the same map again, here is a nice coastline. This continent is part of the 'New World' so no starting places were put here.
http://forums.civfanatics.com/attachment.php?attachmentid=170606&stc=1&d=1204769766
Here is an overview of a huge sized map. It looks like this world found itself on the wrong side of some very large meteors in the distant past. Meteors are used to break up pangaeas which naturally interfere with the new world functionality, but if you happen to like pangaeas, you can turn this option off with the many tuning variables at the beginning of the script.
http://forums.civfanatics.com/attachment.php?attachmentid=170610&stc=1&d=1204769766
From the huge map now, another example of altitude affecting the terrain. This northern peninsula has a ridge of tundra which, along with the direction of the rivers, helps create an illusion of altitude.
http://forums.civfanatics.com/attachment.php?attachmentid=170611&stc=1&d=1204769766
Here is an example on the huge map how resources are placed. I captured a junction of three continents to show that, to encourage trading, different continents have different resource sets. One continent has wheat and pigs, another cows and corn, and the other sheep and rice. These resources are designed in the XML to avoid appearing on the same continent, and this rule is respected when starting plots are normalized also.
http://forums.civfanatics.com/attachment.php?attachmentid=170609&stc=1&d=1204769766
Version History
1.13 - Fixed a bug where starting on a goody hut would crash the game. Prevented start plots from being on mountain peaks. Changed an internal distance calculation from a straight line to a path distance, improving start locations somewhat. Created a new tuning variable called DesertLowTemp. Since deserts in civ are intended to be hot deserts, this variable will prevent deserts from appearing near the poles where the desert texture clashes horribly with the tundra texture.
1.12 - Found a small bug in the bonus placer that gave bonuses a minimum of zero, this is why duel size maps were having so much trouble.
1.11 - limited the features mixing with bonuses to forests only. This eliminates certain undesireable effects like floodplains being erased by or coinciding with oil or incense, or corn appearing in jungle.
1.10 - Wrapped all map constants into a class to avoid all those variables being loaded up when PW is not used. Also this makes it a little easier to change them programatically. Added two in-game options, New World Rules and Pangaea Rules. Added a tuning variable that allows bonuses with a tech requirement to co-exist with features, so that the absence of those features does not give away their location.
1.09 - Fixed a starting placement bug introduced in 1.07. Added a tuning variable to turn off 'New world' placement.
1.08 - Removed the hemispheres logic and replaced it with a simulated meteor shower to break up pangeas. Added a tuning variable to allow pangeas.
1.07 - Placing lakes and harbors after river placement was not updating river crossings. Resetting rivers after lake placement should solve this. Fixed a small discrepancy between Python randint and mapRand to make them behave the same way. Bonuses of the same bonus class, when forced to appear on the same continent, were sometimes crowding each other off the map. This was especially problematic on the smaller maps. I added some additional, less restrictive, passes to ensure that every resource has at least one placement unless the random factors decide that none should be placed. Starting plot normalization now will place food if a different bonus can not be used due to lack of food. Changed heightmap generation to more likely create a new world.
1.06 - Overhauled starting positions and resource placement to better suit the peculiarities of PerfectWorld
1.05 - Fixed the Mac bug and the multi-player bug.
1.04a - I had unfairly slandered getMapRand in my comments. I had stated
that the period was shortened unnecessarily, which is not the case.
1.04 - Added an option to use the superior Python random number generator or the getMapRand that civ uses. Made the number of rivers generated tunable. Fixed a bug that prevented floodplains on river corners. Made floodplains in desert tunable.
1.03a - very minor change in hope of finding the source of a multi-player glitch.
1.03 - Improved lake generation. Added tuning variables to control some new features. Fixed some minor bugs involving the Areamap filler and fixed the issue with oasis appearing on lakes. Maps will now report the random seed value that was used to create them in the PythonDbg file, so they can be easily re-created for debugging purposes.
1.02 - Fixed a bug in the way desert placement was calculated. This also required a readjustment of the default values.
1.01 - Added some global tuning variables for easier customization. Fixed some minor bugs that caused deserts to get out of control sometimes.
Sine Nomen Aug 23, 2007, 05:19 PM This is fantastic, especially the way climates are generated. I got so tired of playing on maps with jungle and desert splattered randomly across the same latitudes that I pretty much stopped playing except for on maps that I've created. :) The only place where I think it needs work is the shape of the continents - they're a bit web-like and all seem to snake together. Also, having Sahara-like deserts that don't fade into grassland after three tiles is wonderful, but some of these deserts might be a little *too* big. If the way they're generated is based on the shape of the continent (this is great!), having some different options for continent generation might be helpful. Nercury's Planet Generator script does a good job of creating realistically-formed continents - if you could incorporate that with your wonderful climate generator code the script would be, well, perfect. Good work!
cephalo Aug 23, 2007, 07:52 PM Yeah, 'perfect' is quite a boast. I called it 'PerfectWorld' because I wanted to make a map that was my ideal for a good Civ game. It's not really perfect just yet.
About those large deserts; I had also thought that there might be a little too much desert with the current setup. However, the real world is mostly plains and desert. Rainforests and lush farmlands are actually somewhat rare. In game terms, having an abundance of the drier climates makes the grasslands alot more valueable for food production, while the dry interors will naturally have many of the important mineral resources. After some playtesting I decided to keep it.
Also, bringing in more rain is tricky lol. The only things that are controlled by lattitude are the prevailing winds and initial temperature. Tweaking certain variables by a few tenths of a percent makes the world a gigantic jungle. :blush: I tweaked and tweaked until most of the maps were balanced lol. If, for example, all the continents end up in the rain zones at the equator and +/- 60 degrees, then even now the world is mostly rainforest. It's a big 'what if' scenario.
LDiCesare Aug 24, 2007, 09:21 AM I must try it! Great to see someone else tried a generator like this. A pity your thumbnails are so small, I can't visualize the results until I've tried it myself.
cephalo Aug 24, 2007, 10:23 AM I would suggest that before anyone commits to a game, generate a few maps and use the console command 'game.toggledebugmode' to make sure it's to your liking. Perhaps I can put together a better screenshot when I get home.
TheLastOne36 Aug 24, 2007, 04:08 PM is this only for vanilla?
cephalo Aug 24, 2007, 08:22 PM is this only for vanilla?
I do not own the expansions yet, so I'm not actually sure what additional requirements they have regarding map scripts. It may work fine for all I know.
cephalo Aug 24, 2007, 08:36 PM Here are some more detailed screen shots of a typical map result. The one on the left is the main 'Old World' area where people start.
The middle one is an overview of the 'New World' continents with no starting areas.
The picture on the right is a close up example of a valley in the northern rainy lattitudes. The icy and tundra area to the north west is what high altitude looks like. It takes a little imagination to see it that way, but it looks fairly natural, especially since rivers tend to lead away from these areas.
LDiCesare Aug 26, 2007, 10:57 AM This script works fine with the expansions. I didn't check if the feature generator makes it compatible with all mods, but it's perfectly usable with regular BtS.
I'll make a few comments if I may:
I think the deserts tend to get overboard quite easily. Very often I see huge deserts and almost no usable land in the most part of a continent, despite one or two lakes in the middle of the continent, which only generate a single plain nearby. It's very hard to tune unfortunately.
The rivers generated are gorgeous. Very nice work. I'm probably going to rewrite my own rivers along the same lines if I can find the time.
I also think there are too few hills with regards the number of peaks generated.
Nice job overall. :goodjob:
cephalo Aug 27, 2007, 09:30 AM A word of warning in regards to river generation. Even though the generateTerrain overridable function wants a list of terrains with (0,0) in the NW corner, the plots in CvMap are arranged with (0,0) in the SW corner! Jeez, it took me days to figure out why my rivers were running backwards. With this being a random map generator, I was oblivious to the fact that I was looking at my maps upside down. :lol:
Seven05 Aug 28, 2007, 08:26 PM The maps generated with this script are very nice, especially the terrain distribution which itself is fantastic.
My only complaint so far is that the use of tundra & ice to simulate high altitude frequently has some 'unpleasant' results like a single tile of ice between peaks and jungles.
If you're accepting any 'wish lists' it would be very nice to have more control in the game. In particular the ability to control continents touching the poles, tundra/ice simulating high altitude and overall temperature & 'roughness' of the world. Nercury's planet generator has excellent controls and great results for landmasses.
Anyway, great work! :)
cephalo Sep 01, 2007, 07:11 PM Ok, so I'm on vacation visiting family and showing my brother in law my map script. The first thing out of his mouth is, "Wow, look at all that desert." When I get back I'll make a fully tunable version.
I also have to do something about those starting areas. It's basically the default with no new world placement, and that really only works with roundish continents. Sometimes you can be placed on a snaky peninsula that goes through the arctic, and the game thinks you're on the best continent so it's ok. I'll have to work on it some more.
Seven05 Sep 02, 2007, 10:33 AM I have done some tweaking that I'd be happy to share with you, mainly with the player starting positions and removing the tundra/ice simulating altitude. To 'fix' the player starts what I did is re-write the entire section to that it first checks to see if the map has a single huge landmass, if it does that becomes the old world and everything else is the new world. If it's not a single huge landmass it makes the largest landmass the new world, the second largest the old world and then continues to add to the old world until the total old world size is 60% of the total land. What happens most often with that change is the players start out in smaller clusters on different continents, normally 2-4 civs per landmass (except on the pangea-like worlds). I was going to add a latitude check to add some weight to staring closer to the equator but I don't think it really needs anything else from what I've seen in my countless test builds.
Anyway, if you'd like I can post the code for that to save you some trouble.
As for customization options it would be nice to have some control over the frequency of rivers (especially in deserts), overall temperature, overall rainfall and the 'roughness' of maps.
Asthetically, the only thing that could be improved is the long straight mountain ranges as they can look pretty bad when you end up with a straight line of 10+ peaks. Creating some channels in the snakey continents to break them up into multiple continents would be a nice feature too but not really critical.
Seven05 Sep 03, 2007, 12:34 AM So I've been playing around with this a bit to tweak it more to my liking and figured I should at least share the code in case you find it helpful.
The first is my re-write of getNewWorldID(), it should be pretty self-explanatory:
def getNewWorldID(self):
nID = 0
continentList = list()
for a in self.areaList:
if a.water == False:
continentList.append(a)
totalLand = 0
for c in continentList:
totalLand += c.size
print totalLand
#sort all the continents by size, largest first
continentList.sort(key=operator.attrgetter('size') ,reverse=True)
print ''
print "All continents"
print self.PrintList(continentList)
#First, make sure we don't have a single huge landmass, if we
#do, that will be the old world
oldWorldSize = 0
if float(continentList[0].size)/float(totalLand) > 0.50:
oldWorldSize += continentList[0].size
del continentList[0]
else:
#second largest continent is 'Old World' giving us a larger 'new world'
#to explore and forcing the game to split player starts up into smaller
#groups on the remaining landmasses if possible
oldWorldSize += continentList[1].size
del continentList[1]
#if the remaining continents are large enough we can continue
#if not we can just call everything else 'new world'
if float(oldWorldSize)/float(totalLand) < 0.50:
biggestNewWorld = continentList[0]
del continentList[0]
for n in range(len(continentList)):
oldWorldSize += continentList[0].size
del continentList[0]
if float(oldWorldSize)/float(totalLand) > 0.60:
break
#add back the biggestNewWorld continent
continentList.append(biggestNewWorld)
#get ID for the next continent, we will use this ID for 'New World'
#designation
nID = continentList[0].ID
del continentList[0] #delete to avoid unnecessary overwrite
#now change all the remaining continents to also have nID as their ID
for i in range(self.mapHeight*self.mapWidth):
for c in continentList:
if c.ID == self.areaMap[i]:
self.areaMap[i] = nID
return nID
The next is some 'noise' generation. This is kind of dirty but it does the trick and would be easy to impliment as an optional process. I simply added two passes to the end of GenerateHeightField(). The intention was to break up the landmasses a little more, particularly near the poles. It needs some work though as it ends up adding a lot of peaks on most maps. I did it here, before all of your other processing to help conceal the 'noise' effect a little better. Since this takes place before PerformTectonics() you still get the really good landmass shapes and natural looking terrain distribution. In fact, it tends to create some very nice island chains on larger maps.
#Now a quick 'noise' pass that is biased to add more land near the equator and
#subtract more away from the equator
for y in range(0,self.mapHeight,1):
addBias = 1 - (abs((self.mapHeight * 0.5) - y) / (self.mapHeight * 0.5))
subBias = abs((self.mapHeight * 0.5) - y) / (self.mapHeight * 0.5)
for x in range(0,self.mapWidth,1):
i = self.GetIndex(x,y)
rand = random()
if rand < 0.2:
self.map[i] += random() * addBias * 0.5
elif rand > 0.7:
self.map[i] -= random() * subBias
#Finally a smoothing pass. The effect is stronger and more frequent near
#the equator.
for y in range(0,self.mapHeight,1):
bias = 1 - (abs((self.mapHeight * 0.5) - y) / (self.mapHeight * 0.5))
for x in range(0,self.mapWidth,1):
i = self.GetIndex(x,y)
avg = 0.0
if random() > bias:
for yy in range(y - 1,y + 2,1):
for xx in range(x - 1,x + 2,1):
ii = self.GetIndex(xx,yy)
avg += self.map[ii]
avg = avg/8
if avg < self.map[i]:
self.map[i] -= abs(avg - self.map[i]) * ((1.0 + bias) / 2)
Hope some of that helps. :)
cephalo Sep 07, 2007, 07:30 AM Well seven05, the first change you made basically changes the desired size of the old world from .60 to .50. You can accomplish the same thing probably by just changing that one hardcoded constant. Keep in mind that in this continent designation, coast is considered land, so when you generate a world with .25 landmass vs. water, you are almost always going to get a large continent bigger than .50.
The second change with the added noise just makes it noisier than the noise that comes with the heightfield generation. I can't remember all the places where I added noise to different aspects of the map generator, but the result has been continents of any size along with small islands dotting the seas here and there. That's noisy enough isn't it? Also, what's wrong with having land near the poles? In the real world after all, some of the largest continents come right up against the ice.
Next week I'm to change quite a few things and add alot of tunable variables like desert/plains/hills/peaks percentages and put them right at the beginning of the script as globals. So instead of saying "no rain = desert" I'm going to say 'no rain compared to the rest of the world = desert'. That way if the continents form mostly in the desert lattitudes they won't all be desert.
Rael Sep 07, 2007, 12:48 PM Well, first of all congratulations on your excellent map script. It's the best one I've ever used.
Secondly, I agree with Seven05 that there's too much land around the poles. CIV map is a rectangle which can't represent the Earth surface accurately. The equatorial zones end up shrinked and polar zones are stretched. To balance things out more ocean should be added around the poles to keep the tundra-rainforest ratio correct and create more earthlike maps (for example Rhye stretched the oceans near the poles to balance his Earth map).
I'm looking forward to the changes you want to make. I would also like to have an option to customize the number of continents and islands.
Rael
Seven05 Sep 07, 2007, 04:27 PM Well seven05, the first change you made basically changes the desired size of the old world from .60 to .50.
Well, it's a little more than that :) You know your old method, the first check for 50% is simply to optimize the process since if it finds that than that continent is the old world and everything else is assumed to be the new world without stepping further into the process. The biggest change is in cases where you don't have one dominant landmass, in that case the largest is the new world and then the remaining continents are used to define the old world until the old world consists of at least 50% of the available land. On standard maps the difference between 50-60% is so small it doesn't matter, however on large and huge maps it makes quite a difference in player starting positions. From my experience (and with my noise changes) typical maps consist of two larger continents and anywhere from 1-3 smaller continents (continents being landmasses seperated by ocean). The next most frequent result is a single huge continent with some scattered islands and maybe a single additional small continent (room for 3-4 cities). Maybe one out of every ten maps gives me multiple continents of relatively equal size. Anyway, in all but the pangea style worlds the end result has the players more spread out over multiple continents whereas your original code preferred to put most of them on a single landmass.
The second change with the added noise just makes it noisier than the noise that comes with the heightfield generation. I can't remember all the places where I added noise to different aspects of the map generator, but the result has been continents of any size along with small islands dotting the seas here and there. That's noisy enough isn't it? Also, what's wrong with having land near the poles? In the real world after all, some of the largest continents come right up against the ice.
The noise (and smoothing pass) is biased by latitude so it's easy to tune the results. With my current settings the result is more subtractive noise near the poles which tends to break up large landmasses near the poles and replace them with scattered islands. The smoothing pass, being more prominent near the equator, has the effect of reducing the number of small islands away from the poles. So combined, it's not simply more noise, it's more noise near the poles and less noise near the equator. Adjusting the values used can create anything ranging from scattered islands everywhere to huge polar landmasses and equatorial islands. I chose to use noise to keep the landmasses interesting rather than simply applying a linear add/subtract pass.
It's not so much a matter of wanting NO land near the poles as much as it is a matter of preventing large landmasses near the poles. Having massive amounts of tundra/ice increases the chance of civs starting in those regions which can severely cripple them. While it's a fun start for a human player against AI opponents it makes for an exceptionally easy game if it's the AI that gets stuck there instead.
Next week I'm to change quite a few things and add alot of tunable variables like desert/plains/hills/peaks percentages and put them right at the beginning of the script as globals. So instead of saying "no rain = desert" I'm going to say 'no rain compared to the rest of the world = desert'. That way if the continents form mostly in the desert lattitudes they won't all be desert.
I'm looking forward to those changes :) I'll have to grab some in game screenshots showing some of the hidden potential of using your mapscript. In particular is the ability to apply different versions of grass, plains and deserts based on temperature which makes the maps look absolutely incredible.
cephalo Sep 08, 2007, 02:09 PM I'll have to grab some in game screenshots showing some of the hidden potential of using your mapscript. In particular is the ability to apply different versions of grass, plains and deserts based on temperature which makes the maps look absolutely incredible.
Wow, that sounds like fun.
Ok, I'm going to do this in two passes. First, I'm going to do the tunable stuff and publish it, since I can do it fairly quickly and easily. Then I'm going to work really hard on making those starting locations alot better.
The difficulty with placing starting locations is that much of the value depends on the starting locations of other civs, which are not necessarily known at the time of placement. You might think the guy with first pick has the best location, but that can be ruined by someone else being placed between him and the rest of his continent. A fine starting location can end up being a terrible one. You can fix that perhaps, but can you do it without ruining someone else's and ending up in an endless process?
I have some ideas on how to do this but it will be some work. I can create a value map with the values of each tile, then I can do some simultanious seed fills to find out what territory is likely to be claimed first and make adjustments in passes until everyone is within a certain value tolerance.
I really don't mind having a lot of unusable tiles on a map. I like large ice fields and large deserts and too much ocean. I think it adds a sense of adventure to the game. However, for that to work the starting areas have to take that into account so that one guy isn't getting the desert half of a good continent while his opponent gets all the grassland.
Seven05 Sep 09, 2007, 07:04 AM I really don't mind having a lot of unusable tiles on a map. I like large ice fields and large deserts and too much ocean. I think it adds a sense of adventure to the game. However, for that to work the starting areas have to take that into account so that one guy isn't getting the desert half of a good continent while his opponent gets all the grassland.
That will definately be the tough part although in most cases the start positions haven't been too bad in my games. I've adjusted a lot of things though, both in your mapscript and with the mod that we use.
What is probably the best part of this map script is that the worlds created are 'tactically interesting.' The mountain ranges not only make sense and look good but they create natural obstacles rather than just being some randomly scattered peaks. The deserts are really good as well and create a good natural barrier to expansion, almost like oceans on land. It's really cool to see how the game evolves too, what was poor land early in the game can quickly become critical as resources are revealed.
Speaking of resources, if you write your own resource script make sure it's optional :) Right now this is working out very well of us with the combination of climate based terrain and resources restricted by terrain. For instance I have hot, temperate and cool plains so I can have a resource only appear on hot plains. Just like your script made the world look better by not banding terrain strictly by latitude this makes resource placement much more interesting.
Nercury Sep 11, 2007, 07:42 PM This map script caught my attention at once :). Nice job!
CIV map is a rectangle which can't represent the Earth surface accurately. The equatorial zones end up shrinked and polar zones are stretched. To balance things out more ocean should be added around the poles to keep the tundra-rainforest ratio correct and create more earthlike maps
I don't exactly know how landmasses are generated, but i guess it may be possible to randomly sink some land-heavy areas which are near poles to achieve that.
cephalo Sep 11, 2007, 09:48 PM Version 1.01 is posted!
Ok, I added some global tuning variables at the beginning of the file for easier customization. Be careful though, the slightest changes can have drastic climate altering, seismic results!
Changing the rainfall levels for different terrain types from hard coded values to percentages changed the character of the maps generated quite a bit, but I think most of you will prefer this way of doing it. Interestingly, the larger the continents get the more the deserts begin to break up and become scattered across plains. Since large continents tend to get less rain across the middle, and deserts are now limited by a percentage of the map, they are naturally spread more thinly. On pangea type worlds that happen occasionally this can look very strange.
I also slightly changed the dimensions of the 'large' size map so that the heightmap is generated on a finer grain. This prevents it from generating so many pangeas.
Give it a shot!
MrPopov Sep 12, 2007, 09:04 PM occasionally I get some maps that end up with virtually no desert (less than 5% of land tiles) and instead endless plains (with no trees). Any idea what causes this and what values I can adjust to reduce this?
I, like you, enjoy "seas" of deserts on larger landmasses, but this script will 2 out of 5 maps create this plains version instead of the typical map.
cephalo Sep 13, 2007, 07:52 AM occasionally I get some maps that end up with virtually no desert (less than 5% of land tiles) and instead endless plains (with no trees). Any idea what causes this and what values I can adjust to reduce this?
I, like you, enjoy "seas" of deserts on larger landmasses, but this script will 2 out of 5 maps create this plains version instead of the typical map.
This kind of thing can happen when there is a landmass that is very large. The problem is that the rain has to come from the ocean, carried by winds. When there are large areas of next to no rain, the percent finder for desert and plains has to come up with a threshold that in this case might not be accurate enough due to the very small amounts involved. I used to get this alot on 'large' size maps, so I changed the size slightly so that it tends to generate smaller continents.
I still need to do some testing, but I suspect that I might be using a float somewhere where I need a double. I'm not exactly sure what causes this, but I noticed it happens on some map sizes more than others.
As for a suggestion, you might try lowering the LandPercent variable and play on the next larger size map. Changing the DesertPercent might just give you all desert instead of all plains.
Edit: Ok, I figured it out. How this works is, the rain map is normalized to be between 0.0 and 1.0. The problem is, rainfall at the ocean is set to 0.0. That means that the lowest rainfall on land might be well above 0.0, and closer to the desert threshold and thus having a high likelyhood of being plains. The model assumes that 0.0 will be the least rainfall which is not always the case. I'll have a fix shortly.
Seven05 Sep 13, 2007, 11:18 AM Edit: Ok, I figured it out. How this works is, the rain map is normalized to be between 0.0 and 1.0. The problem is, rainfall at the ocean is set to 0.0. That means that the lowest rainfall on land might be well above 0.0, and closer to the desert threshold and thus having a high likelyhood of being plains. The model assumes that 0.0 will be the least rainfall which is not always the case. I'll have a fix shortly.
Yay, a new version to play with :)
As for the deserts, with your original version all I did to 'fix' them was work with the highest rainfall since I remembered seeing where you reset all of the ocean rainfall to zero. Here's the code from the previous version with my quick hack in it (in GenerateTerrainMap()):
#initialize terrainMap with OCEAN
for i in range(0,hm.mapHeight*hm.mapWidth):
self.terrainMap.append(self.OCEAN)
if highestRainfallMM < rm.rainMap[i]:
highestRainfallMM = rm.rainMap[i]
highestRainfallMM *= 12000 #highest average rainfall possible in mm
The result is that I still get some good sized desert areas on 'normal' maps with multiple continents but it's a bit more forgiving on maps with large continents. The hack is a bit over-simplified though and one area with high rainfall will effectively increase the likelyhood of deserts on the rest of the map.
I'll have to grab the update and play around with it after work, hopefully I can just drop my climate based terrain changes right in. ;)
I've had some incredible games with these maps, the terrain is absolutely fabulous. Unlike typical random maps the climate makes sense and adds a whole new layer of strategy to the game, especially if you find yourself blocked off by large mountain ranges or unihabitable spans of desert. AI expansion has also been generally slower in my games and for once it makes sense when they settle a bit away from their existing cities. I guess I would say the maps are earth-like in the way grass/plains/deserts/mountains/hills are distributed but still random enough in shape to keep them interesting between different games.
cephalo Sep 13, 2007, 11:22 AM Ok, 1.02 is published!
Wow, what a difference now that I don't have to explain away the fact that the map was all plains! I can say with confidence that the settings you choose for deserts etc. will give the expected results now.
Next on the agenda are those lakes. For one thing, any time you see a one square lake it's a bug. I tried to eliminate those, but I did it in a somewhat clumsy manner. I'm going to make the size of lakes proportional to the total river lengths flowing into them. Right now I'm seeing alot of instances where you have the Nile, and the Amazon, AND the Mississipi flowing into the same 3 square lake. I'm not comfortable with that.
cephalo Sep 13, 2007, 01:27 PM seven05, there are some changes that will affect what you were doing. Check out the FindValueFromPercent function. What it does is return a threshold such that the given percentage of the total map will be above or below the return value. This allows for easy tuning of anything that you want to set as percentages. If you need a calculation more complex than greater or less than, then you can prepare a map of pre-calculated values. This is how I tuned peaks and hills.
Anything that depends on rainfall is a good choice for this method, since rainfall can vary widely from map to map, and this can provide consistency.
Temperature related stuff is still absolute, since temperature is so heavily dependant on lattitude and maintains it's own form of constistency.
Seven05 Sep 13, 2007, 10:42 PM seven05, there are some changes that will affect what you were doing. Check out the FindValueFromPercent function. What it does is return a threshold such that the given percentage of the total map will be above or below the return value. This allows for easy tuning of anything that you want to set as percentages. If you need a calculation more complex than greater or less than, then you can prepare a map of pre-calculated values. This is how I tuned peaks and hills.
Cool, thanks for the heads up. I won't have time to mess with it until this weekend though. And you tuned the peaks and hills? I'll have to see what that gives me now :)
For your lakes & rivers, one thing I did was change way you remove lakes. Originally, all you did was change the plot from 'ocean' to 'land' without altering the heightmap. Since the flowmap was based on the heightmap it appeared to creat a LOT of lakes, especially in the larger continents where a big lake or several lakes had been cleaned up. Since the temp/rain map would cause those same areas to be deserts I thought it was a bit odd having a large desert full of lakes. Anyway, all I did was go into the lake cleanup code and add a line to set the heightmap for each plot to sealevel where it changed the plot type to land (I think I had to change the main code to cleanup lakes before generating the flowmap too but I don't recall). That appeared to have an impact on the number of rivers and small lakes. Since it was still appearing to almost prefer deserts for river placement (making them some of the most fertile areas, which I thought was a bit odd) I also made a slight adjustment to the river generation code to make it unlikely to even try to create a river if the plot rainfall was below the desert threshold. A typical map for me now has very few, if any, lakes in deserts and only a couple of desert rivers. Unfortunately there are also very few rivers altogether since most of them were in the deserts.
cephalo Sep 13, 2007, 11:42 PM I think one of the reasons that rivers often turned up in deserts was because deserts tend to happen on the widest parts of continents where there might be little rain per square, but lot's of squares to contribute to the watershed. Since there is no evaporation figured in, the water just keeps running.
It didn't bother me too much because it definately does make those areas more useful, and the first version of the map had soooo much desert. I'm going to try to do something more sensible with the lakes and rivers. However, if you google maps the Nevada desert near Reno, you'll see alot of similar lakes that act as evaporation pans. :)
Seven05 Sep 14, 2007, 10:12 PM Well, that was easy :)
I just used the global ForestTemp & JungleTemp to add in the 'climate based terrain' in about 60 seconds. So far it's working well, I just need to play around with the global values for personal preferences. Any plans to put in in-game options to control those values?
Also, I'm not sure if you're aware of this, the mapscript isn't entirely MP compatible. When you use it the players will all be out of sync and upon reconnecting their civs will be in a different starting plot. The workaround is to start with appropriate AI players and have the other players join once the map has been created and take over the AI civs.
cephalo Sep 15, 2007, 09:53 AM Well, that was easy :)
I just used the global ForestTemp & JungleTemp to add in the 'climate based terrain' in about 60 seconds. So far it's working well, I just need to play around with the global values for personal preferences. Any plans to put in in-game options to control those values?
Also, I'm not sure if you're aware of this, the mapscript isn't entirely MP compatible. When you use it the players will all be out of sync and upon reconnecting their civs will be in a different starting plot. The workaround is to start with appropriate AI players and have the other players join once the map has been created and take over the AI civs.
I'm not sure yet what values people will really want to change from game to game. I put them in so that people can adjust things to their ideal of a perfect world.
I have no clue what the requirements are for MP. Do you know of a script that handles this well that I can study? What's the issue? Do players choose their starting locations? I've never even played MP.
Right now I'm trying to improve lake generation, and in the process I found an occasional bug in my area generator that I use for starting placement and lake filling. It is going to be a nightmare to track this down because it works fine for most maps. I need to impliment a way to save maps in Python so I can debug with the same test map, otherwise there's no way to know if I fixed it or if it's just a different map.
Seven05 Sep 15, 2007, 11:52 PM I'm not sure yet what values people will really want to change from game to game. I put them in so that people can adjust things to their ideal of a perfect world.
Sea level, climate (rainfall & temps) and peak/hill percentage would be some good basic options.
I have no clue what the requirements are for MP. Do you know of a script that handles this well that I can study? What's the issue? Do players choose their starting locations? I've never even played MP.
I'm not 100% certain what causes it to go out-of-sync. It may be the long initialization time or the use of 'random' rather than the mp-safe 'dice' function. Players don't chose their starting location, but if they're in the game when you generate the map they'll see themselves in one place and after re-connecting to get back in sync they'll be somewhere else entirely. This leads me to believe it's a problem somewhere in the starting plot function. Most of the other map scripts I've tried worked without a problem, one I know works fine in MP is Nercury's 'Planet generator' which you can grab from the forum here.
LDiCesare Sep 17, 2007, 04:03 AM I need to impliment a way to save maps in Python so I can debug with the same test map, otherwise there's no way to know if I fixed it or if it's just a different map.
Why don't you just set the seed of the random number generator?
cephalo Sep 17, 2007, 08:24 AM Why don't you just set the seed of the random number generator?
I'll try that first. Hopefully, I was consistent in which random generator I used :crazyeye: .
I have to do most of my work in a place where I don't have access to civ, so I probably used random() until the end of the process.
cephalo Sep 17, 2007, 02:04 PM I'm not 100% certain what causes it to go out-of-sync. It may be the long initialization time or the use of 'random' rather than the mp-safe 'dice' function. Players don't chose their starting location, but if they're in the game when you generate the map they'll see themselves in one place and after re-connecting to get back in sync they'll be somewhere else entirely. This leads me to believe it's a problem somewhere in the starting plot function. Most of the other map scripts I've tried worked without a problem, one I know works fine in MP is Nercury's 'Planet generator' which you can grab from the forum here.
I found this in the CvMapScriptInterface file:
* normalizeStartingPlotLocations() # This function only matters if any teams of more than one civ (aka permanent alliances) exist at game launch. This function works to group team members together as best it can. If you hardwire any start plots for specific players and don't want the game to mess with them, shuffing them around, then you need to override (disable) this function.
Could this be what is happening? Once I start the assignStartingPlots, I only use the dice for randoms.
Also, my findStartingPlot function is completely dependant on my assignStartingPlots, so if it's called separately it won't work the same way. Ew, I would hope they would not do that but they might.
MrPopov Sep 17, 2007, 08:58 PM I have noticed sometimes with lake generation in deserts, an oasis will be inside the lake. This has only happened once and I was fooling around in the world builder so I cannot be 100% certain I didn't place it accidentally. I know this is vague but I will keep my eyes open for it if I see it again.
cephalo Sep 18, 2007, 07:02 AM I have noticed sometimes with lake generation in deserts, an oasis will be inside the lake. This has only happened once and I was fooling around in the world builder so I cannot be 100% certain I didn't place it accidentally. I know this is vague but I will keep my eyes open for it if I see it again.
Yeah, that will be fixed in the next version. The problem is that I'm using my own terrain tracking to decide where to place them but I didn't update my terrain when I made the lake, so my feature generater thinks the lake is still desert.
Seven05 Sep 18, 2007, 07:58 AM Could this be what is happening? Once I start the assignStartingPlots, I only use the dice for randoms.
Also, my findStartingPlot function is completely dependant on my assignStartingPlots, so if it's called separately it won't work the same way. Ew, I would hope they would not do that but they might.
We don't run team games so if by 'This function only matters if any teams of more than one civ (aka permanent alliances) exist at game launch' they mean the normalize functions only runs if you have teams then that definately isn't the problem.
MrPopov Sep 18, 2007, 09:05 AM I've played a team game using this map script. We got an Oout of sync on game launch, but when he reconnected, he was in the same spot.
cephalo Sep 18, 2007, 09:09 AM We don't run team games so if by 'This function only matters if any teams of more than one civ (aka permanent alliances) exist at game launch' they mean the normalize functions only runs if you have teams then that definately isn't the problem.
Yuck, I'll have to tackle this for 1.04. Nercury's map uses the default implimentation BTW, which would be fine except I need to screen out the new world. As far as I can see though, I'm using a very similar routine that is in the DLL. I can't imagine why a new starting location would be calculated on reconnect.
Seven05, do you have your civ set up to make a Python debug log? There are some print statements in the findStartingPlot function that might indicate whether it's being recalled after the initial placement. If it's re-calling the default procedure in the DLL though, nothing would show up.
cephalo Sep 18, 2007, 09:24 AM What do you guys think of floodplains? Right now I have them only in the desert and if there is a river there is always a floodplain. Maybe that's fine.
Seven05 Sep 18, 2007, 04:28 PM Seven05, do you have your civ set up to make a Python debug log? There are some print statements in the findStartingPlot function that might indicate whether it's being recalled after the initial placement. If it's re-calling the default procedure in the DLL though, nothing would show up.
I will enable the log and post some results for you next time we hook up for a game, probably Saturday.
As for the floodplains, I've had to modify it for myself (three types of desert in my mod). From a gameplay standpoint I think the only case outside of deserts that makes sense would be tundra since tundra is about as useless as desert unless you're lucky enough to have some trees. If you place them on plains/grassland they quickly overpower the normal food resources, or worse yet- they make cottage spam even more potent.
Anyway, I think as a 'pure' mapscript you should avoid any fundamental gameplay changes.
cephalo Sep 19, 2007, 07:39 PM 1.03 is now published. The visible changes are somewhat small, but I had found many, many bugs that needed to be dealt with.
Lakes are now generated proportional to the river lengths flowing into them, and that proportion is tunable. There is also a tunable evaporation penalty for lakes created in the desert. Lakes that are one square in size are now legal, but no lake may exist such that removing one land square will connect it to the ocean, because any such lake will already be thus connected to form a harbor. So if you see such a lake, know that this map is behaving illegally.
Also, if you happen to be a modder with some Python saavy, each map will report in the PythonDbg file a seed value that is used to start the random number generator. So if you happen to find a map breaking the law, you can report them with this ID number.
Enjoy!
cephalo Sep 19, 2007, 08:15 PM Next up will definately be starting areas. One of the problems I see with having fair starting areas is, that I've noticed that in single player, AI civs are very good a getting into stone cold stalemates. Perhaps fair starting areas are really only desireable in multiplayer?
With the default implimentation, some civs get really, really bad starting areas that no amount of bonuses can fix. Also, sometimes people can start on their own fairly large continent and if it happens to be the player, then the game is way too easy. There's definately alot of room for improvement here.
seven05, how often have you seen that MP bug on my map? Do you think it could just be some one time glitch unrelated to the map? Before I work too hard, I had better get a handle on that.
Seven05 Sep 19, 2007, 08:36 PM Very good results so far with the 1.03 fixes :)
We experienced the mp bug every time we tried to start a game with this mapscript, using another mapscript works fine as does starting the game and generating the map before the other players join.
cephalo Sep 20, 2007, 07:05 AM Very good results so far with the 1.03 fixes :)
We experienced the mp bug every time we tried to start a game with this mapscript, using another mapscript works fine as does starting the game and generating the map before the other players join.
First, I want to say thanks for all the helpful comments. I'm wondering if you have time on your next MP game, can you try to generate a map with the starting plot functions commented out? That will cause the default functions to be used and if it's stable then that tells me if I can concentrate wholly on my starting functions in finding the problem. assignStartingPlots and findStartingPlot are the only ones needing to be eliminated for this test.
cephalo Sep 20, 2007, 12:45 PM I've noticed something that might cause the MP problem. There is a function called CvPlayer.setStartingPlot and also one called CvPlot.setStartingPlot. My script only uses the CvPlayer version, maybe I need both? I'll try both, and after testing it tonight to make sure it won't crash the map I'll publish it. SmartMap uses both.
Seven05 Sep 20, 2007, 02:53 PM First, I want to say thanks for all the helpful comments. I'm wondering if you have time on your next MP game, can you try to generate a map with the starting plot functions commented out? That will cause the default functions to be used and if it's stable then that tells me if I can concentrate wholly on my starting functions in finding the problem. assignStartingPlots and findStartingPlot are the only ones needing to be eliminated for this test.
No problem, thank you for the script! :)
I can do that quick check for you this weekend, if it does nothing I'll enable the log as well per your previous request.
cephalo Sep 20, 2007, 04:37 PM Ok, I just published 1.03a. This change is mostly for seven05 in hopes of finding the MP bug.
I noticed that in the dll, CvPlayer.setStartingPlot does not update the m_bStartingPlot member in CvPlot, so here's to hoping that this is important and might fix the problem.
Seven05 Sep 20, 2007, 09:32 PM Well now I feel special :)
I still can't test it until Saturday though, but I'll keep you posted.
Seven05 Sep 21, 2007, 11:15 AM Here's a quick one for you, I've been running this for some time. I adjusted it to force all players to start on the coast, otherwise a non-coastal start would typically mean starting one or two plots in from the coast since the landmasses are generally too thin to really start you in the middle of all land. It applies to all players, human and AI alike and also help prevent somebody starting in the middle of a large desert (although they can still start surrounded by mostly desert).
def findStartingPlot(playerID,bestArea):
gc = CyGlobalContext()
gameMap = CyMap()
player = gc.getPlayer(playerID)
player.AI_updateFoundValues(True)
iRange = player.startingPlotRange()
iPass = 0
while (true):
iBestValue = 0
pBestPlot = None
for iX in range(gameMap.getGridWidth()):
for iY in range(gameMap.getGridHeight()):
pLoopPlot = gameMap.plot(iX, iY)
if (pLoopPlot.getArea() != bestArea):
continue
if (pLoopPlot.getLatitude() >= 75):
continue
val = pLoopPlot.getFoundValue(playerID)
if val > iBestValue:
valid = True
for iI in range(gc.getMAX_CIV_PLAYERS()):
if (gc.getPlayer(iI).isAlive()):
if (iI != playerID):
if gc.getPlayer(iI).startingPlotWithinRange(pLoopPlot , playerID, iRange, iPass):
valid = False
break
#Only allow coastal starting plots
pWaterArea = pLoopPlot.waterArea()
if (pWaterArea.isNone()):
valid = false
valid = not pWaterArea.isLake()
if valid:
iBestValue = val
pBestPlot = pLoopPlot
if pBestPlot != None:
return gameMap.plotNum(pBestPlot.getX(), pBestPlot.getY())
print "player", playerID, "pass", iPass, "failed"
iPass += 1
if iPass > 100:
return -1
return -1
cephalo Sep 21, 2007, 02:41 PM Here's a quick one for you, I've been running this for some time. I adjusted it to force all players to start on the coast, otherwise a non-coastal start would typically mean starting one or two plots in from the coast since the landmasses are generally too thin to really start you in the middle of all land. It applies to all players, human and AI alike and also help prevent somebody starting in the middle of a large desert (although they can still start surrounded by mostly desert).
Once I lock down the MP bug I'm going to give starting plots a big overhaul with some tunable options. I want to find some way to give all players on a continent somewhat equal opportunity to all the good stuff it has. I suppose everyone likes to start on the coast, but I had a very fun game recently starting completely land locked on all sides in the middle of the desert. Luckily the starting plot normalizer gave me lots of marble so I could culture flip a coastal city with my wonders.
Coast only starts is a good option to provide though. I would also like to provide an option for different levels of fairness, including completely random and totally unfair. Also, maybe an option for different qualities of starting locations aside from fairness, like everyone with a bad, medium, or best starting location. It might be fun for players to have to look for the best areas instead of just owning them at the beginning.
I plan to go nuts with the starting location stuff.
Rael Sep 22, 2007, 02:34 AM I think this script is getting even better with each new release. Good job:)
However, there are two small glitches that bothered me right from the first version. One is the number of rivers and flood plains in the deserts. They make the poorest parts of map the best for settling. I don't usually get Sahara-like deserts with no cities around. I realize there are seasonal rivers on deserts but they shouldn't be treated as regular rivers.
The second glitch is in the screenshot. The rvier delta looks ugly and the x-marked tiles has no river on it (in regular map scripts it's always a river-tile). o-marked tile should also be flood plain.
Desert rivers without flood plains should also be generated just like in regular scripts. For example the upper parts of a desert river could have no flood plains.
cephalo Sep 22, 2007, 10:03 AM I think this script is getting even better with each new release. Good job:)
However, there are two small glitches that bothered me right from the first version. One is the number of rivers and flood plains in the deserts. They make the poorest parts of map the best for settling. I don't usually get Sahara-like deserts with no cities around. I realize there are seasonal rivers on deserts but they shouldn't be treated as regular rivers.
The second glitch is in the screenshot. The rvier delta looks ugly and the x-marked tiles has no river on it (in regular map scripts it's always a river-tile). o-marked tile should also be flood plain.
Desert rivers without flood plains should also be generated just like in regular scripts. For example the upper parts of a desert river could have no flood plains.
I have noticed that the delta glitch only happens to me when I regenerate the map without starting a new game. Other weird stuff happens also like floating resources and goody huts. It never happens to me the first time I generate the map. I wonder if some map finalization function needs to be called that isn't in some cases. Are you regenerating the map at all? The fix that works for me is to save your game, exit to the main menu and reload.
Also, in making floodplains, there's a function called CvPlot.isRiverSide. Basically I just make every desert square that answers 'true' to that function a floodplain. So it's very simplistic. I was thinking maybe I should tone that down, but it won't be trivial.
Rael Sep 22, 2007, 02:51 PM That was a regenerated map, but I think that even though it's only a display bug it's caused by the fact that the x-marked tile is not counted as river tile while it should be. I noticed it because I wanted to build a levee in the city placed on such tile and I couldn't. It doesn't happen always but when a river flows into a lake it's pretty common
cephalo Sep 22, 2007, 06:40 PM That was a regenerated map, but I think that even though it's only a display bug it's caused by the fact that the x-marked tile is not counted as river tile while it should be. I noticed it because I wanted to build a levee in the city placed on such tile and I couldn't. It doesn't happen always but when a river flows into a lake it's pretty common
You're right, that's definately a bug. I'll have to fix that. It must be that even though isNOfRiver and isWOfRiver are both false, the riverID still needs to be set to give the corners fresh water. Thanks for being persistant about insisting that it was a bug.
Seven05 Sep 23, 2007, 08:40 AM I come bearing sad news :(
The MP bug still exists. That is if I host a game and you join while I'm in the staging room when we create the map we will be OOS (out of sync) and when you re-connect you're starting city will be somewhere very different.
Worse yet, I neglected to enable logging while we were going through trying to resolve a few other mod issues.
cephalo Sep 23, 2007, 10:14 AM I come bearing sad news :(
The MP bug still exists. That is if I host a game and you join while I'm in the staging room when we create the map we will be OOS (out of sync) and when you re-connect you're starting city will be somewhere very different.
Worse yet, I neglected to enable logging while we were going through trying to resolve a few other mod issues.
Did you have a chance to comment out the starting plot code? That's the thing that I needed most.
cephalo Sep 23, 2007, 11:42 AM That was a regenerated map, but I think that even though it's only a display bug it's caused by the fact that the x-marked tile is not counted as river tile while it should be. I noticed it because I wanted to build a levee in the city placed on such tile and I couldn't. It doesn't happen always but when a river flows into a lake it's pretty common
Hey Rael, I have a question for you. What are the stated requirements for a levee? I only use vanilla at this time, so it's hard for me to test things properly. In vanilla, on other map scripts, there would be no fresh water on the x-marked tile if that lake there was ocean instead of a lake. Did they change the rules for Warlords etc?
I have no idea why that graphical glitch upon regenerating is there, other maps don't have that problem. Why it is fixed upon reload is also a mystery to me.
MrPopov Sep 23, 2007, 08:41 PM requirements for levee is next to a river. A fresh water lake won't do it for you. The dutch dike on the other hand I believe can be built either next to a river, or coastal (since it also adds +1 hammer to water tiles).
BTW I really love the map script!!
cephalo Sep 24, 2007, 06:41 AM requirements for levee is next to a river. A fresh water lake won't do it for you. The dutch dike on the other hand I believe can be built either next to a river, or coastal (since it also adds +1 hammer to water tiles).
BTW I really love the map script!!
Thanks! One more quick question, when you use a different old map script with BtS, like Terra for example, will Raels x-marked square meet the requirement for a river? Or, does that only happen in the newer BtS map scripts?
Rael Sep 24, 2007, 10:03 AM Yes, they're always rivers, at least in all (old and new) scripts in BtS (don't know about Vanilla)
cephalo Sep 24, 2007, 12:29 PM Yes, they're always rivers, at least in all (old and new) scripts in BtS (don't know about Vanilla)
The function that determines river crossings and thus river plots is called updateRiverCrossings in the SDK dll. I'll post the code.
void CvPlot::updateRiverCrossing(DirectionTypes eIndex)
{
CvPlot* pNorthEastPlot;
CvPlot* pSouthEastPlot;
CvPlot* pSouthWestPlot;
CvPlot* pNorthWestPlot;
CvPlot* pCornerPlot;
CvPlot* pPlot;
bool bValid;
FAssertMsg(eIndex >= 0, "eTeam is expected to be non-negative (invalid Index)");
FAssertMsg(eIndex < NUM_DIRECTION_TYPES, "eTeam is expected to be within maximum bounds (invalid Index)");
pCornerPlot = NULL;
bValid = false;
switch (eIndex)
{
case DIRECTION_NORTH:
pPlot = plotDirection(getX_INLINE(), getY_INLINE(), DIRECTION_NORTH);
if (pPlot != NULL)
{
bValid = pPlot->isNOfRiver();
}
break;
case DIRECTION_NORTHEAST:
pCornerPlot = plotDirection(getX_INLINE(), getY_INLINE(), DIRECTION_NORTH);
break;
case DIRECTION_EAST:
bValid = isWOfRiver();
break;
case DIRECTION_SOUTHEAST:
pCornerPlot = this;
break;
case DIRECTION_SOUTH:
bValid = isNOfRiver();
break;
case DIRECTION_SOUTHWEST:
pCornerPlot = plotDirection(getX_INLINE(), getY_INLINE(), DIRECTION_WEST);
break;
case DIRECTION_WEST:
pPlot = plotDirection(getX_INLINE(), getY_INLINE(), DIRECTION_WEST);
if (pPlot != NULL)
{
bValid = pPlot->isWOfRiver();
}
break;
case DIRECTION_NORTHWEST:
pCornerPlot = plotDirection(getX_INLINE(), getY_INLINE(), DIRECTION_NORTHWEST);
break;
default:
FAssert(false);
break;
}
if (pCornerPlot != NULL)
{
pNorthEastPlot = plotDirection(pCornerPlot->getX_INLINE(), pCornerPlot->getY_INLINE(), DIRECTION_EAST);
pSouthEastPlot = plotDirection(pCornerPlot->getX_INLINE(), pCornerPlot->getY_INLINE(), DIRECTION_SOUTHEAST);
pSouthWestPlot = plotDirection(pCornerPlot->getX_INLINE(), pCornerPlot->getY_INLINE(), DIRECTION_SOUTH);
pNorthWestPlot = pCornerPlot;
if ((pSouthWestPlot != NULL) && (pNorthWestPlot != NULL))
{
if (pSouthWestPlot->isWOfRiver() && pNorthWestPlot->isWOfRiver())
{
bValid = true;
}
}
if ((pNorthEastPlot != NULL) && (pNorthWestPlot != NULL))
{
if (pNorthEastPlot->isNOfRiver() && pNorthWestPlot->isNOfRiver())
{
bValid = true;
}
}
if ((eIndex == DIRECTION_NORTHEAST) || (eIndex == DIRECTION_SOUTHWEST))
{
if ((pNorthEastPlot != NULL) && (pNorthWestPlot != NULL))
{
if (pNorthEastPlot->isNOfRiver() && pNorthWestPlot->isWOfRiver())
{
bValid = true;
}
}
if ((pSouthWestPlot != NULL) && (pNorthWestPlot != NULL))
{
if (pSouthWestPlot->isWOfRiver() && pNorthWestPlot->isNOfRiver())
{
bValid = true;
}
}
}
else
{
FAssert((eIndex == DIRECTION_SOUTHEAST) || (eIndex == DIRECTION_NORTHWEST));
if (pNorthWestPlot != NULL)
{
if (pNorthWestPlot->isNOfRiver() && pNorthWestPlot->isWOfRiver())
{
bValid = true;
}
}
if ((pNorthEastPlot != NULL) && (pSouthWestPlot != NULL))
{
if (pNorthEastPlot->isNOfRiver() && pSouthWestPlot->isWOfRiver())
{
bValid = true;
}
}
}
}
if (isRiverCrossing(eIndex) != bValid)
{
m_abRiverCrossing[eIndex] = bValid;
changeRiverCrossingCount((isRiverCrossing(eIndex)) ? 1 : -1);
}
}
Basically, in order to consider diagonal motion a river crossing, you need two river lengths. According to this code, and correct me if I'm wrong because this is not a simple issue and I may very well be misreading this code, crossing diagonally across the mouth of a river is *not* considered a river crossing, although it really should be considered one.
In vanilla, I was able to verify this behavior on other maps. The CvPlot::isRiver() function checks to count of all river crossings that are precomputed by the above. Diagonal from a river mouth does not create fresh water, which means the CvPlot::isRiver() function returns false. Here's the code for CvPlot::isFreshWater().
bool CvPlot::isFreshWater() const
{
CvPlot* pLoopPlot;
int iDX, iDY;
if (isWater())
{
return false;
}
if (isImpassable())
{
return false;
}
if (isRiver())
{
return true;
}
for (iDX = -1; iDX <= 1; iDX++)
{
for (iDY = -1; iDY <= 1; iDY++)
{
pLoopPlot = plotXY(getX_INLINE(), getY_INLINE(), iDX, iDY);
if (pLoopPlot != NULL)
{
if (pLoopPlot->isLake())
{
return true;
}
if (pLoopPlot->getFeatureType() != NO_FEATURE)
{
if (GC.getFeatureInfo(pLoopPlot->getFeatureType()).isAddsFreshWater())
{
return true;
}
}
}
}
}
return false;
}
The thing is, if they changed the rules for BtS, why would my map behave differently than other older maps like Terra? Did they publish new versions for the old map scripts? I gues the obvious solution for me would be to go out and buy BtS but I'm sooooo broke.
JP Vieira Sep 24, 2007, 12:41 PM very interesting
cephalo Sep 24, 2007, 07:01 PM 1.04 is available. This is a pretty big update. No starting location stuff yet. Made the number of rivers in the world tunable. Also added a tuner for how quickly floodplains are made in desert rivers. Fixed the bug where floodplains weren't appearing on river corners. I still haven't been able to figure out why my river graphics get wonky when the map is regenerated without going back to the main menu. Saving and reloading should fix that.
I added an option to use either Python's random number generator or the one given by the getMapRand function. Interestingly, the character of the maps generated by each randomizer is very different from the other. The Python generator is vastly superior with 53 bit precision. The Civ rands packs a 32 bit rand into a 16 bit integer. Call me crazy, but I think the Python random creates much more organic looking maps. They both generate random maps, but the difference is like looking at paisley compared to looking at plaid. Switch back and forth to see for yourself.
I actually have alot of experience randomly generating stuff, it's been a hobby of mine for a long time. Psuedo-random numbers are a very weird science. It's shockingly easy to accidently find your processes 'in tune' with an otherwise highly random generator, making it completely un-random for the particular thing you are trying to use it for. One time I was making a heightmap for a project of mine, and I discovered that one of the variables I was randomizing was always an even number, never an odd. Very strange! I switched to a different generator and the problem went away. When you're creating fractal art such as these maps are, you can't skimp on your random generator.
The only good thing about the getMapRand is that hopefully, Seven05's MP bug will go away! Seven05, set the UsePythonRandom variable to 'False'. If that doesn't fix the MP bug, I don't think I have the skills to fix it.
Rael Sep 25, 2007, 11:36 AM I looked at the same part of code in BtS and it's a bit different. That's the reason for all the misunderstanding. Anyway, great update, congratulations:goodjob:
cephalo Sep 25, 2007, 11:46 AM I looked at the same part of code in BtS and it's a bit different. That's the reason for all the misunderstanding. Anyway, great update, congratulations:goodjob:
Someday I'll get BtS, and try to go for better compatibility.
MrPopov Sep 25, 2007, 11:58 AM I want to share a few screenshots from your map script that shows why I love this so much. The first shows a very interesting coast. It is evident that your tectonics method formed a ridge where the island formed.
http://forums.civfanatics.com/uploads/96168/PW1.jpg
The second image shows a very fertile area with a large lake. Almost every map has a lot of character and it makes it fun to explore.
http://forums.civfanatics.com/uploads/96168/PW2.jpg
BTW If you want I could send you some .py of some BTS map scripts if you want to compare, or is that a no no?
cephalo Sep 25, 2007, 12:50 PM Thanks for the compliments MrPopov. Ahh, smell those pine trees on the wind. Sometimes the best thing about Civilization is being away from it.
:lol: :lol: :lol: :crazyeye:
Do you know of another map script that generates it's own rivers for BtS? Most map scripts use the default river generator in some way.
Seven05 Sep 25, 2007, 09:35 PM Did you have a chance to comment out the starting plot code? That's the thing that I needed most.
Wow, it hasn't been easy to connect to CF lately... anyway, yes we went OOS even with all of your starting plot functions commented out, although I neglected to have them re-connect to see if they ended up in a different plot.
As for the rivers, none of the official BTS scripts use custom river generation.
LDiCesare Sep 26, 2007, 02:39 AM Do you know of another map script that generates it's own rivers for BtS? Most map scripts use the default river generator in some way.
There's mine (Tectonics) which generates rivers 'backwards' (from sea to source). The river code is a bit of a mess that I'd change if I weren't so lazy, but you can always look at it.
cephalo Sep 26, 2007, 06:51 AM There's mine (Tectonics) which generates rivers 'backwards' (from sea to source). The river code is a bit of a mess that I'd change if I weren't so lazy, but you can always look at it.
How does your script work with BtS LDiCesare? Can you build a levee on Raels x-marked square in his screenshot? Another less permanent, but still annoying problem I'm having with the delta graphics only happens on lakes that have rivers going into them. Since you don't have that particular combo of features, I guess it just doesn't come up on yours. I studied yours quite a bit while learning the ropes. Thanks for all your hard work.
Wow, it hasn't been easy to connect to CF lately... anyway, yes we went OOS even with all of your starting plot functions commented out, although I neglected to have them re-connect to see if they ended up in a different plot.
As for the rivers, none of the official BTS scripts use custom river generation.
Try turning off the Python randoms in the future, I can't imagine what else it could be.
cephalo Sep 26, 2007, 08:56 AM So I've got my starting plot code all torn to pieces right now and I need some advice. This should take a couple of weeks I imagine because I'm generating starting plots in a completely different way and there's bound to be obstacles I can't even imagine right now.
In normal map scripts that come with the game, the climates are strewn about in a highly random way that makes most land masses fairly homogenous. You can be sure that wherever you start, you are never too far away from some productive map squares, and you have a good chance that you will have first dibs on some good land.
On my map script, continents have good parts and bad parts. If you start on some tiny grassland penninsula connected to a vast desert, many of your descendents might be eating sand beetles for a thousand years before they find another patch of green, and it might all be occupied by someone who started closer to the good lands.
Take the following scenario, lets say we have a continent where we would like to place two players. The continent has an area of grassland on one end, but the rest is hard scrabble desert with some scattered plains. You can build cities there to be sure, and there's some valueable resources, but you wouldn't want to start there.
Here's the big question, is it ok to start the two players in the grassland fairly close to each other, facing possible war in the warrior stage? Starting them any other way would be hugely unfair, as one player would likely place a city or two in the productive area before the other even knew where to look. Right now, I'm thinking that if I place them near each other with equal access to the continents value, it would be ok. Keep in mind that this scenario can also happen on very large continents with 4 or 5 civs.
How important is starting distance, and why is it important?
Seven05 Sep 26, 2007, 09:34 AM Here's an off-the-wall idea...
Evaluate the 'value' of entire areas (landmasses) before defining old/new world areas. Things to consider for establishing a value would be peaks (no value), desert without flood plains (very low value), features (trees=good, jungle=bad) and so on. Then, once you have a value per landmass, and you know the size of the landmass you can calculate the average value per tile and space the players out according to that. So a large landmass with a low value per tile would have fewer players than a smaller landmass with a higher value per tile. You could also ensure that the 'old world' is a better overall landmass than the 'new world' or the other way around if you prefer.
For final plot selection there are a few things to consider. First, since the game will generate additional bonuses around starting plots and the advantage of starting on a coast with clams/crabs/fish is HUGE in the early game due to their commerce AND food bonus a coastal start doesnt need as much 'good' land in the area as a non-coastal start. Second, hills are nice for production but only if you also have enough food, so a starting position with a food bonus or two and multiple hills is very good while a start position with hills and only production bonuses is not as good. Starting in, or even close to tundra can be very rough as that likely means the majority of your territory will be useless until you get lumbermills up and running. Rivers are critical in deserts & plains, but not as important in grasslands or hilly areas.
Now the one thing that would be really nice, but I'm not sure if it's even possible, would be to place civs based on their starting techs. So if a civ has fishing, for one example, they should always start on a coast.
The inequality of starting plots is a big part of what makes the game fun, but it's also a big part of what makes the game frustrating. An in-game option for 'balanced' or 'wild' starting locations would be nice to have.
Edit: Missed the last question about starting distance :)
Starting distance is very important for a few different reasons. Nearby neighbors can be a threat if they're agressive or cornered with nowhere else to go. Nearby neighbors are a boon otherwise, the advantage of open borders and somebody to trade techs with is pretty big. So more important that the actual distance is the ability to establish contact and trade early. Of course if you start alone on a good landmass you'll do just fine, but the AI in the same situation may be crippled depending on which leader it is.
And, very quickly, since I'm a C++ guy, not a python guy... how do I turn off the python random?
LDiCesare Sep 26, 2007, 09:37 AM How does your script work with BtS LDiCesare? Can you build a levee on Raels x-marked square in his screenshot?
I should test but I think I probably can't. The lake plot is water and has no reason to have a river on its border, whereas I suppose in BtS, there may be a river hidden below the lake. Maybe world editing the tile to change it to grass would show a river?
Furthermore, one must be careful with the default scripts, as they add lakes and rivers after player placement, and the code being called late can cause some artefacts (like desert rivers with no floodplains).
cephalo Sep 26, 2007, 09:41 AM I'm particularly interested in ending this occurance as well.
X = Land, O = Starting Plot
............
...XOXXXOX..
..XX.....XX.
.XXXX.......
.XXXXXX.....
XXXXXXXX....
.XXXXX......
............
I see this alot on my map and it must stop. I think I know how to prevent it.
cephalo Sep 26, 2007, 09:54 AM I should test but I think I probably can't. The lake plot is water and has no reason to have a river on its border, whereas I suppose in BtS, there may be a river hidden below the lake. Maybe world editing the tile to change it to grass would show a river?
Furthermore, one must be careful with the default scripts, as they add lakes and rivers after player placement, and the code being called late can cause some artefacts (like desert rivers with no floodplains).
I think you might be able to actually. I'm big on text graphics today so I'll show you what I mean. I'm talking about corners across river mouths.
X = Land, x = non river intersection, r = river
XxX......
xxx......
XxXxX....
rrrrrr...
XxXxXxX..<---River Here?
I have disabled the normalize functions that add lakes and rivers, so they all should be added in a way that I intended.
cephalo Sep 26, 2007, 10:04 AM And, very quickly, since I'm a C++ guy, not a python guy... how do I turn off the python random?
The latest version has a global variable that I made just for you. It's called UsePythonRandom, and you can set it to 'False'. ;)
Seven05 Sep 26, 2007, 10:35 AM Right... just saw 1.04 and read that (follow by a quietly whispered, oh crap) :)
khuxtable Sep 26, 2007, 05:08 PM I'm running Civ IV on a Mac (PPC). When I try PerfectWorld, even version 1.04a, I get no elevations. I get small lakes and some forestation, but the world is all grasslands and two-square-long rivers.
Any ideas?
-K
MrPopov Sep 26, 2007, 07:39 PM as far as starting location goes. I agree with Seven in that starting too close (ie warrior combat close) is bad. It just encourages the player to rush and can dictate the flow of the rest of the game to unfavorable results.
On the other hand though, unfavorable starts can end up being a very fun game with a unique and exciting story. It's hard to pin down the best solution but IMHO if someone wants a truly balanced game for competitive MP or HOF reasons, that's what the vanilla scripts are for. However if it is something you think you can tackle, add some options for it for things like balanced starting plots, new world/old world, etc. so if we want a random map still we can have it :)
cephalo Sep 26, 2007, 10:49 PM I'm running Civ IV on a Mac (PPC). When I try PerfectWorld, even version 1.04a, I get no elevations. I get small lakes and some forestation, but the world is all grasslands and two-square-long rivers.
Any ideas?
-K
Can you post a screenshot? The only time I've had that happen is when the script crashed in the middle of map creation. This map script is starting to become something of a beast, and it wouldn't surprise me if some machines on the lower end of things might not work well. Does the same thing happen every time? Do you get an error message? Also, try generating a duel size map first and work your way up. That might tell you if you have some kind of problem with computer resources.
Sto Sep 27, 2007, 07:57 AM You should ask AlanH for mac compatibility in this thread (http://forums.civfanatics.com/showthread.php?t=198619) . The bug occur probably with operator.attrgetter .
Tcho !
cephalo Sep 27, 2007, 08:15 AM You should ask AlanH for mac compatibility in this thread (http://forums.civfanatics.com/showthread.php?t=198619) . The bug occur probably with operator.attrgetter .
Tcho !
Thanks for the tip! Yikes, so Mac civ is using Python 2.3? Ouch. I'll try to work that in.
Seven05 Sep 27, 2007, 10:02 AM And you thought the MP side was a pain ;D
I have finally tweaked & tuned the script almost to my own version of perfection, or more accurately to better work with my mod. The climate based terrain works like a charm, incidentally I saw you tried adding some noise to the rain to break up the banding, add that noise to the temperature map instead and you'll solve the banding without messing up the climate too much. Altitude based terrain is probably going in soon, not a big deal but since the data is there, why not use it? :)
I have a couple of issues I'd like to adjust a bit more, but I need your help since I don't fully understand how you're doing a couple things.
First, and most important to me, is desert rivers & lakes. Ideally, I would like to remove every lake that is surrounded by desert and disallow any rivers through desert terrain that don't terminate at the ocean. Is there a good way to trace a river backwards or would it be better to modify the flowmap before rivers are even generated?
The next thing I'd like to do is reduce the frequency of large inland seas. I don't want to simply fill them all in with land though. It would be ideal if I could fill some in, force channels out from others and if a channel is created plot out a few small islands inside the sea.
Both of these would help a bit with the overall gameplay in my mod. The deserts are critical since I use them to hold the majority of the key strategic resource (oil, iron and copper) and I only allow desert cities to be built on the coast or tiles with fresh water. The large number of lakes & rivers in the desert makes it too easy to gain access to all of the resources. The inland sea issue is more for strategic importance and to give the AI a helping hand since it doesn't understand that building a massive fleet of warships won't help them if they can't go anywhere.
Also, I don't know if you would want it or not but I added a few simple steps to the tectonics code so the generator has a chance of creating 'typical perfect world' maps, pangea maps (with no land at the poles) or mixed continents. And I added an oceanic divide to the initial heightmap generation to help ensure that there is some ocean separating the landmasses. Of course I kept everything random so you really have no clue what you're getting yourself into since thats the way I like to play.
Anyway, thanks again for the incredible script and the continued updates. I'll keep you posted on the MP issue when I have a chance to test it again.
cephalo Sep 27, 2007, 10:43 AM You're in for alot of work Seven05. I'll try to answer your questions.
Getting rid of desert rivers will also get rid of the lakes. The final riverMap in the RiverMap class is just like the flowMap, but with all non rivers set to rm.O. Any rm.L(Lake or Pit) you find you can check to see if it's in the desert, and if so you can follow the river backwards and erase each river length by setting it to O. No lake will be generated without the river there, when you see a lake without one, it's because the lake ate the river that caused it.
The large inland seas come from either the river system making a huge lake or else because one plate sunk below all the surrounding plates. In the first case, you can set LakeSizePerRiverLength to a smaller value. In the second case, you might increase the size tolerance for the initial lake filling, but you might end up with a very large swath of land if you go too far with that. The makeHarbor function will cause ocean to invade lakes to a degree of one map square. You might try to extend it to be more invasive.
The difficulty with some of this stuff you want to do is that on this map, the heightmap is the law of the land. Rain will go downhill, even if that is the middle of your continent, and the larger the continent, the more likely this will happen.
jmm Sep 27, 2007, 11:03 AM Great script, however I found a problem around the poles.
Sometimes the unpassable territory is overwritten by tundra or ice.
U=Unpassable t=tundra P=Peak w=water (ocean)
UUUUUUttPtUUUUUU
wwwwwttttttwwww
wwwwwttppwwwww
wwwwwttwwwwww
In addition sometimes the starting positions are on those small areas and the AI just builds a city in the top row, cutting the workable area to half and with only low value terrains, there is no much hope for the AI.
There is another noteworthy side-effect, there is a large number of resources put on the first row (copper, iron and uranium)
cephalo Sep 27, 2007, 12:14 PM Great script, however I found a problem around the poles.
Sometimes the unpassable territory is overwritten by tundra or ice.
U=Unpassable t=tundra P=Peak w=water (ocean)
UUUUUUttPtUUUUUU
wwwwwttttttwwww
wwwwwttppwwwww
wwwwwttwwwwww
In addition sometimes the starting positions are on those small areas and the AI just builds a city in the top row, cutting the workable area to half and only low value terrain.
There is another noteworthy side-effect, there is a large number of resources put on the first row (copper, iron and uranium)
Is the top row unpassable? I guess I never really checked that. The starting positions are going to be revamped. I'm right now neck deep in the craziest, hopefully Mac compatible, starting plot code the world has ever seen. Will it work? Is it even feasable? Nobody knows.
The resource code is all default placement. I have been forbidden to touch that as such things are supposed to be handled in the XML.
I remember the night I first published version 1.0. I said, "Ahhhhh, I'm finally finished!" Don't worry, If I can't fix the starting code, I can at least create Santa Claus as that civs UU.
Seven05 Sep 27, 2007, 02:35 PM Is the top row unpassable?
No, but it is typically impassable Ice. I adjusted the terrain generation script to always force that top and bottom row as water myself, mainly for asthetic reasons.
The resource code is all default placement. I have been forbidden to touch that as such things are supposed to be handled in the XML.
You can actually do a bit without breaking the XML rules. The problem comes from non-standard resources, if you write custom resource placement any mod that adds custom resources won't be able to use your script. Of course you've already 'broken' custom features so it really shouldn't matter :)
I remember the night I first published version 1.0. I said, "Ahhhhh, I'm finally finished!"
Famous last words :)
Seven05 Sep 27, 2007, 02:45 PM You're in for alot of work Seven05. I'll try to answer your questions.
Getting rid of desert rivers will also get rid of the lakes. The final riverMap in the RiverMap class is just like the flowMap, but with all non rivers set to rm.O. Any rm.L(Lake or Pit) you find you can check to see if it's in the desert, and if so you can follow the river backwards and erase each river length by setting it to O. No lake will be generated without the river there, when you see a lake without one, it's because the lake ate the river that caused it.
Forgive me since I'm not looking at the code right now, but is it easy to track the flowmap (like knowing which adjacent plot to check/modify). I remember bits of it vaguely, like the L and O parts, isn't the rest N,S,E,W? If so is it a matter of saying, "ok, this plot is a W so if I go one plot E I'm tracking the flow 'upstream'."
The large inland seas come from either the river system making a huge lake or else because one plate sunk below all the surrounding plates. In the first case, you can set LakeSizePerRiverLength to a smaller value. In the second case, you might increase the size tolerance for the initial lake filling, but you might end up with a very large swath of land if you go too far with that. The makeHarbor function will cause ocean to invade lakes to a degree of one map square. You might try to extend it to be more invasive.
Didn't you drop the code to clean up lakes, or is it just hidden now? The makeHarbor function is working very well right now, the problem is that I seem to have a bit of luck in getting seas surrounded by land that is two tiles thick, perhaps a quick change to the horbor code is all I need. Is that executed before or after the area lists are generated? If it's after it should be a simple matter to identify inland seas but if it's before I can work directly with the heightmap... Gah! :)
The difficulty with some of this stuff you want to do is that on this map, the heightmap is the law of the land. Rain will go downhill, even if that is the middle of your continent, and the larger the continent, the more likely this will happen.
Yeah, I tried some basic 'evaporation' code, but I wasn't happy with the results since it affected all of the rivers. Although I suppose I could run a check after the terrain is generated but before the rivers are to only apply evaporation in desert squares (I was using temperature & rainfall data before). The again, maybe my evaporation code was just flawed :)
cephalo Sep 27, 2007, 03:25 PM Forgive me since I'm not looking at the code right now, but is it easy to track the flowmap (like knowing which adjacent plot to check/modify). I remember bits of it vaguely, like the L and O parts, isn't the rest N,S,E,W? If so is it a matter of saying, "ok, this plot is a W so if I go one plot E I'm tracking the flow 'upstream'."
Yes, the riverMap works that way also. Keep in mind that when you go backwards, each plot might branch off to tributaries, so you'll have to put them on some kind of stack for deletion later. For each plot you think, "ok, who of my four neighbors is flowing into me?" If the answer is nobody, then you are done with that branch of river. Drastic stuff! Maybe theres a better way. Remember that the latest version allows you to control floodplain generation, so maybe you can render those rivers and lakes impotent.
Didn't you drop the code to clean up lakes, or is it just hidden now? The makeHarbor function is working very well right now, the problem is that I seem to have a bit of luck in getting seas surrounded by land that is two tiles thick, perhaps a quick change to the horbor code is all I need. Is that executed before or after the area lists are generated? If it's after it should be a simple matter to identify inland seas but if it's before I can work directly with the heightmap... Gah! :) I fill lakes right at the beginning during heightmap generation, with the idea that they will be recreated via the river system. The Areamap class that you speak of is general purpose, if you learn how to use it you can do something on your own concerning areas. I use it for several different things.
Yeah, I tried some basic 'evaporation' code, but I wasn't happy with the results since it affected all of the rivers. Although I suppose I could run a check after the terrain is generated but before the rivers are to only apply evaporation in desert squares (I was using temperature & rainfall data before). The again, maybe my evaporation code was just flawed :) I have an idea. Find the following code:
#Create average rainfall map so that each intersection is an average
#of the rainfall from rm.rainMap
for y in range(hm.mapHeight):
for x in range(hm.mapWidth):
i = hm.GetIndex(x,y)
avg = 0.0;
for yy in range(y,y-2,-1):
for xx in range(x,x+2):
ii = hm.GetIndex(xx,yy)
avg += rm.rainMap[ii]
avg = avg/4.0
self.averageRainfallMap[i] = avg
see what happens when you square 'avg'.
Change
self.averageRainfallMap[i] = avg
to
self.averageRainfallMap[i] = avg * avg
This might eliminate desert rivers altogether. If so you can try some other tweak on this value. This will steepen the curve, and if all rivers become diminished you can pump up the RiverThreshold global.
khuxtable Sep 27, 2007, 11:08 PM Here's a screen shot of a duel-sized map. I play on a 23" monitor at 1280x800. I can go up to 1920x1200, but then I'd need to move the monitor closer or put on my glasses. I'm lazy.
This isn't a low-end Mac. It's one of the last non-Intel Macs made. It has two dual core 2.5GHz G5 processors and 2GB of RAM. The graphics card is a GeForce 7800GT driving a digital Mac LCD monitor. I've got plenty of RAM. This is basically a server-class machine. It's my development system.
BTW, I'm a programmer, but not a Python programmer. I normally write in Java, C++, or Perl and develop database applications, so this is a bit out of my line, but I can probably learn to read Python. I've got a book.
I've never really felt like the Mac ports are that great, but they're what I can get. I do have a 2.4GHz P4 mobile Dell laptop sitting around the house, but I gave my Windows CivIV away to a friend.
Oh, I play with the Blue Marble textures, so they'll look a bit different from the standard textures.
Thanks,
-K
Seven05 Sep 27, 2007, 11:21 PM I have an idea. Find the following code:
see what happens when you square 'avg'.
This might eliminate desert rivers altogether. If so you can try some other tweak on this value. This will steepen the curve, and if all rivers become diminished you can pump up the RiverThreshold global.
That actually works very well, except I had to reduce the RiverThreshold, not increase it. At 2.0 and above I would have maybe a single river on the entire map, at 1.0 there were more but they were all 1-2 tiles at most, at 0.2 it's very good (for my taste) with plenty of rivers around the map and only a few scarce rivers in the desert. At any rate, that's certainly a more effecient method rather than cycling through the entire map another three of four times to trace rivers :)
I had the chance to test it in MP except I was running into a problem. When setting it to not use python random the map was flat grassland, no water, hills, peaks or anything but grassland and a bunch of long rivers. I have a feeling the mapRand isn't precise enough for the changes I put into the heightmap. Next time I get a chance I'll load up an un-modified version of your script with the python random disabled.
khuxtable Sep 27, 2007, 11:27 PM You should ask AlanH for mac compatibility in this thread (http://forums.civfanatics.com/showthread.php?t=198619) . The bug occur probably with operator.attrgetter .
Tcho !
Well, your "full of resources" scripts work fine... I've been using them for months with no problems.
I read through the thread and didn't notice any references to operator.attrGettr. What does it do? What should we be doing instead? The script definitely uses it, I think four times. Twice with 'size' and once with 'ID', and once with 'altitude'.
-K
Sto Sep 28, 2007, 02:12 AM I read through the thread and didn't notice any references to operator.attrGettr. What does it do? What should we be doing instead? The script definitely uses it, I think four times. Twice with 'size' and once with 'ID', and once with 'altitude'.
You can try that waiting for cephalo update ( windows use python 2.4 and Mac use python 2.3 where operator.attrGettr is not defined ) :
#self.areaList.sort(key=operator.attrgetter('size' ),reverse=True)
tpList = [ [ item.size , item ] for item in self.areaList ]
tpList.sort()
tpList.reverse()
self.areaList = [ item[1] for item in tpList ]
#continentList.sort(key=operator.attrgetter('size' ),reverse=True)
tpList = [ [ item.size , item ] for item in continentList ]
tpList.sort()
tpList.reverse()
continentList = [ item[1] for item in tpList ]
#continentList.sort(key=operator.attrgetter('ID'), reverse=True)
tpList = [ [ item.ID , item ] for item in continentList ]
tpList.sort()
tpList.reverse()
continentList = [ item[1] for item in tpList ]
#lakeNeighbors.sort(key=operator.attrgetter('altit ude'),reverse=False)
tpList = [ [ item.altitude , item ] for item in lakeNeighbors ]
tpList.sort()
lakeNeighbors = [ item[1] for item in tpList ]
For cephalo , if you want to know if you're running into a MAC OS and use a global ( because this method is not very fast compare to operator.attrGettr )
if (sys.platform == 'darwin'): MacOS = True
Tcho !
cephalo Sep 28, 2007, 07:07 AM I've never really felt like the Mac ports are that great, but they're what I can get. I do have a 2.4GHz P4 mobile Dell laptop sitting around the house, but I gave my Windows CivIV away to a friend.
Oh, I play with the Blue Marble textures, so they'll look a bit different from the standard textures.
-K
I understand the problem now khuxtable, it will be fixed in the next version. I just have to strip out all Python 2.4isms.
I had the chance to test it in MP except I was running into a problem. When setting it to not use python random the map was flat grassland, no water, hills, peaks or anything but grassland and a bunch of long rivers. I have a feeling the mapRand isn't precise enough for the changes I put into the heightmap. Next time I get a chance I'll load up an un-modified version of your script with the python random disabled.
It's an ok random generator, what you are seeing is a map crash. If you use any randoms yourself, be sure to use PWRand. Hopefully it's not a crash that I just failed to test for.
cephalo Sep 28, 2007, 07:15 AM You can try that waiting for cephalo update ( windows use python 2.4 and Mac use python 2.3 where operator.attrGettr is not defined ) :
#self.areaList.sort(key=operator.attrgetter('size' ),reverse=True)
tpList = [ [ item.size , item ] for item in self.areaList ]
tpList.sort()
tpList.reverse()
self.areaList = [ item[1] for item in tpList ]
#continentList.sort(key=operator.attrgetter('size' ),reverse=True)
tpList = [ [ item.size , item ] for item in continentList ]
tpList.sort()
tpList.reverse()
continentList = [ item[1] for item in tpList ]
#continentList.sort(key=operator.attrgetter('ID'), reverse=True)
tpList = [ [ item.ID , item ] for item in continentList ]
tpList.sort()
tpList.reverse()
continentList = [ item[1] for item in tpList ]
#lakeNeighbors.sort(key=operator.attrgetter('altit ude'),reverse=False)
tpList = [ [ item.altitude , item ] for item in lakeNeighbors ]
tpList.sort()
lakeNeighbors = [ item[1] for item in tpList ]
For cephalo , if you want to know if you're running into a MAC OS and use a global ( because this method is not very fast compare to operator.attrGettr )
if (sys.platform == 'darwin'): MacOS = True
Tcho !
Thanks Sto, I'll be using the crazy 'lambda' thing from the Python Wiki. So
lakeNeighbors.sort(key=operator.attrgetter('altitu de'),reverse=False)
will be
lakeNeighbors.sort(lambda x,y:cmp(x.altitude,y.altitude))
I'm not too concerned about time, I figure that you only have to generate it once per game, and a good map is worth the wait.
khuxtable Sep 28, 2007, 10:51 PM Thanks Sto, I'll be using the crazy 'lambda' thing from the Python Wiki. So
lakeNeighbors.sort(key=operator.attrgetter('altitu de'),reverse=False)
will be
lakeNeighbors.sort(lambda x,y:cmp(x.altitude,y.altitude))
I'm not too concerned about time, I figure that you only have to generate it once per game, and a good map is worth the wait.
I just wanted to say that sto's changes worked for me. Thanks, Sto!
I understand what a crazy lambda thing is from my lisp and perl background. Have fun!
-K (for Kathryn)
cephalo Sep 29, 2007, 09:04 AM I just wanted to say that sto's changes worked for me. Thanks, Sto!
-K (for Kathryn)
Good news!
Update coming soon. The new starting code works great, except for dropping people into the ocean once in a while. Hopefully, I'll have a publish this weekend.
Seven05 Sep 30, 2007, 12:27 AM It's an ok random generator, what you are seeing is a map crash. If you use any randoms yourself, be sure to use PWRand. Hopefully it's not a crash that I just failed to test for.
No idea here... I double checked and every check for a random value that I use is using your PWRand.random() or PWRand.randint(). Anyway, setting it to use the map rand vs. the python rand does the trick in MP games- no more OOS issues when using your base script.
cephalo Sep 30, 2007, 06:49 AM No idea here... I double checked and every check for a random value that I use is using your PWRand.random() or PWRand.randint(). Anyway, setting it to use the map rand vs. the python rand does the trick in MP games- no more OOS issues when using your base script.
Excellent!
As for your map crash, if you enable the Python error messages you should get a popup explaining why it crashed. I don't remember how to set that up, because I set mine up years ago. Also, if you have logs enabled you can check PythonErr.log.
cephalo Sep 30, 2007, 12:51 PM Ok, I had to go back to the drawing board for my starting area enhancements, so I made a mini-publish to eliminate the Mac bug and the multi-player bug. Seven05, Sto showed me how to detect a network game, so you shouldn't have to fool with UsePythonRandom anymore.
My starting area finder was interesting. I calculate a list of all the best possible city starts on a continent and made a table of the path distances between them all for easy lookups. This makes it easy to evaluate the value of each starting city when all players are placed. Then, I did an exhaustive search of every possible combination of city plots and starting locations for a fair result. The results are *exactly* fair. The processing time takes, on a small continent with a couple players just a few seconds. On a large 'pangea' type continent with 200 cities and 13 players I estimate the processing time to be about 1,000 years(not an exaggeration). Since people only live to around 80 or 90 years old, you can see that this technique is not entirely feasable.....*cry*:cry:
Even if they make some kind of medical breakthrough, by that time you could probably just pick up a copy of Civ 102 and play the world war 7 scenario, which would probably be waaaay better. :old:
I will not give up! I have a cunning plan!:wallbash:
khuxtable Sep 30, 2007, 04:24 PM My starting area finder was interesting. I calculate a list of all the best possible city starts on a continent and made a table of the path distances between them all for easy lookups. This makes it easy to evaluate the value of each starting city when all players are placed. Then, I did an exhaustive search of every possible combination of city plots and starting locations for a fair result. The results are *exactly* fair.
Yeah, that's an NP complete algorithm. It has nasty scaling. I suggest some shortcuts.
-K
cephalo Sep 30, 2007, 06:30 PM Yeah, that's an NP complete algorithm. It has nasty scaling. I suggest some shortcuts.
-K
Here's a shorthand explanation of the problem.
1's are starting locations, and digits are possible cities on a continent.
111110000000000000000000000000000000000000000
I know the distance between each city, and I can use that to determine which starting location is closest to what cities. I also know the local value of each city, that way I can add the value of each city to the starting location that claims it by virtue of distance. I'm trying to avoid some starting locations being blocked into a bad peninsula like what I had posted earlier.
Any time I move one of those 1's, I have no idea how to predict how the value of the the other 1's will end up. I tried simply improving the 1 that had the worst value, but curing his problem was highly likely to ruin someone else's starting position. Stepping through a subset of the possibilities sometimes worked, but if the algorithm completed in failure I ended up with little better than random starting locations.
So I made this nifty little algorithm that slid the little bits like an abacus to every possible location exactly once. It was fun to watch it spin through the combinations. The problem is that every time you add a digit the time factor goes up about 20%, and each time you add a 1 it almost doubles. So unless you're using tiny maps with 4 players, worst-case behavior is a game breaker.
I didn't get a chance to actually test how often worst-case behavior happens, I would think that the larger the problem the more combinations that satisfy fairness would arise, but I can't count on that. I could set an iteration limit, but if that limit is reached then you've waited 10 minutes for bad starting locations that could have been better placed any old way.
It's a tough problem.
khuxtable Sep 30, 2007, 08:17 PM So I made this nifty little algorithm that slid the little bits like an abacus to every possible location exactly once. It was fun to watch it spin through the combinations. The problem is that every time you add a digit the time factor goes up about 20%, and each time you add a 1 it almost doubles. So unless you're using tiny maps with 4 players, worst-case behavior is a game breaker.
Do you have any algorithm books? Your problem is roughly equivalent to the "traveling salesman" problem, which is a canonical example of an NP complete problem, that is, one which has no polynomial time solutions, only exponential ones.
You're going to have to settle for less than optimal to get it to finish in quadratic time or better.
I'll check some texts I have lying around the house. I know some of my old books got moldy in a flood a few years back, but I think I have an algorithm book.
-K
cephalo Sep 30, 2007, 10:52 PM Do you have any algorithm books? Your problem is roughly equivalent to the "traveling salesman" problem, which is a canonical example of an NP complete problem, that is, one which has no polynomial time solutions, only exponential ones.
You're going to have to settle for less than optimal to get it to finish in quadratic time or better.
I'll check some texts I have lying around the house. I know some of my old books got moldy in a flood a few years back, but I think I have an algorithm book.
-K
I have another value system I could use that is more easily searchable, but does not eliminate the peninsula problem. I can use that for searching, and then also use the above evaluation method with a loose tolerance as a final check to make sure someone's not getting an extremely bad deal.
I can evaluate each city by getting the value of all other cities diminished by both distance and by the number of players to reflect competition. So the value added to a start location reflects the likelyhood that you will be able to grab that city. It's not as good, because in a way it assumes you will have open borders with all your neighbors and don't mind having a divided empire who's communication can be severed on the whim of other players. However, it is also a trivial search that might help me eliminate alot of legwork and still evaluate things the first way.
I need some searchable evaluation method that is strongly related to claiming by distance.
Seven05 Sep 30, 2007, 11:08 PM Some degree of inequality would be ideal, 'perfect fairness' would eliminate a good part of what makes Civ games fun (for me anyway). I think the best solution is to try to eliminate the worse case scenarios and leave everything that is acceptable alone even if it isn't perfect.
A good solution may be to simply re-write the 'bonus' placement around starting cities to ensure that each start has a roughly equal number of food, commerce and production potential. The current solution for starting area bonuses is poor, you either have something very good or very bad, seldom anything in between. Now, if you can already evalute starting plots compared to potential city placement all you really need to do is balance that with resource in the immediate area. A very good starting location (relative to future cities) can have few, if any bonuses in the area. A very bad starting location (relative to future cities) can have better resources. The best resources would be ones that you can access with 'tier 1' techs, so gold, silver, corn, wheat, crabs, clams, fish, etc. Resources that require calendar are nice later but if thats all you get to start with you're off to a rough start.
Starting on a small peninsula, blocked in by a close neighbor is not entirely bad. Even if you only have room for two cities you can do well if your starting city is strong, especially with easy access to copper and/or iron. Starting with nobody close but surrounded by desert and/or tundra (jungle to an extent) is probably worse since you'll have a very hard time fighting your way out of that mess.
So anyway... if your code says a starting plot is ideal, remove some resources. If you code says it's horrible, add (or change existing) some better resources. Rather than trying to make them all ideal just average them out.
cephalo Oct 02, 2007, 07:13 AM I suppose that if I'm confident in my evaluation of map fairness, I don't necessarily have to limit myself to starting locations in juicing up places with bonuses. Of course, such a scheme would have to be optional.
Seven05 Oct 02, 2007, 09:03 AM Civ already does that, you just need to overrride it so you can manipulate it better ;)
cephalo Oct 02, 2007, 09:10 AM Civ already does that, you just need to overrride it so you can manipulate it better ;)
Really? I had only noticed what they placed in the immediate starting location areas.
I'm going to take a few days to study the proper ways to add resources. Yeah, I broke features, but I don't have to break bonuses too. :p
Also, my fairness evaluator relies heavily on getFoundValue. I suppose I should really get familiar with how it works.
Seven05 Oct 02, 2007, 06:53 PM It is only in the 'fat cross' of the starting plot, but that's the part that's critical in most games since a strong first city can carry a couple of weak ones into the mid-game. Likewise a weak first city needs a strong second and/or third city for the civ to do well. So by taking what you find to be a good spot and removing bonuses from there while taking a poor spot and adding bonuses should average them all out nicely.
For instance let's say you have three starting plots selected:
1) Small peninsula with room for three or four cities
2) Larger section of a continent with average terrain, room for around six or seven cities.
3) Lots of available land with room for several cities and early access to a second continent.
To even things out all you need to do is make sure the plot 3 doesn't get many (if any) resources, definately none of the good food & commerce ones like crabs, fish or clams (maybe move them away from the coast too). Then, take plot 1 and give it some extra bonuses and make sure its on the coast (of the main water area). Plot 2 can be left alone. Since plot 1 will have access to better resources the city built there will be better than the cities built on plot 2 or plot 3, plot 3 should be the worst of them. Since so much of the game is dependant on early expansion and growth the player at plot 1 should have an equal chance as the players at plots 2 and 3 because of the added resources. After all, a city with clams is basically getting one plot with a town on it without having to wait for the town to grow, a floodplain with a farm on it and a health bonus all wrapped up into one. If it has two or three clams, it's that much better.
cephalo Oct 03, 2007, 08:19 AM The AI_foundValue assigns yield values at the following ratio:
food = 10
production = 40
commerce = 20
Do you guys agree with that ratio in determining value?
Because of some of the things that AI_foundValue does to the values in relation to other starting postions, like multiplying them if they are isolated, etc. I need to make my own value function to keep things consistent for normalization. Do you guys think I should try to evaluate the different yields against one another, or should I equalize them separately?
Separating them can guarantee fairness, but maybe it's more fun to pit one guys high production against another players high commerce and force them to use an appropriate strategy.
Seven05 Oct 03, 2007, 10:07 AM That's a tough one... I'd have to play around with different values to see the effects in game. I would also try separating them, although pitting high commerce vs. high production would be fun not all civs are set to properly deal with ever case due to their starting techs and traits. A financial leader, for instance will have higher commerce if they're simply on the coast and a civ without mining as a starting tech will need several turns before they can take advantage of any production bonuses.
Seven05 Oct 04, 2007, 08:19 PM FYI: PerfectWorld.py is 100% compatible with BTS 3.13 :)
I didn't expect it not to be but I figured I'd let you know just in case.
cephalo Oct 05, 2007, 07:24 AM FYI: PerfectWorld.py is 100% compatible with BTS 3.13 :)
I didn't expect it not to be but I figured I'd let you know just in case.
There's still that question regarding river rules. Where can you place a levy on other maps? See the above related posts about diagonal river mouths.
Turambar1337 Oct 05, 2007, 03:57 PM I registered just to log on and say that i think your map script is great, and that i play with it all the time.
i do have one question, does it take a while for you guys to generate maps as well? i noticed this one takes longer than other map scripts.
Seven05 Oct 06, 2007, 12:48 AM Yeah, it's a bit more complicated than most and doesn't use the standard map generation code. I'm in the process of moving large parts of it into my DLL to speed it up myself but it's not ready yet.
cephalo Oct 06, 2007, 04:24 PM I registered just to log on and say that i think your map script is great, and that i play with it all the time.
i do have one question, does it take a while for you guys to generate maps as well? i noticed this one takes longer than other map scripts.
Yeah this thing is a beast, and it's only going to get worse. :satan:
I've been working my butt off this weekend, and I've just discovered that the astar pathfinder that civ uses doesn't always find a path like one would expect. When two plots are fairly close to one another, with nothing in between that I can see, sometimes it reports no path. Since my starting plot finder requires to know the path length between possible cities, I'm not sure what to do. I can implement an a-star pathfinder in python, but I sure as heck don't want to.
cephalo Oct 06, 2007, 04:43 PM Here's a head scratcher. I just learned that if CyMap.calculatePathDistance can't find a path between start and destination, you can usually find one from destination to start. :crazyeye:
Hopefully that will solve my problem. Do I need to understand why? Naaaah.
Elhoim Oct 08, 2007, 10:41 PM Great Script! I really love the continents and mountain ranges shapes, but I have two small complaints:
- Too much forests.
- Because of the forests there is HUGE lack of agricultural bonuses.
cephalo Oct 09, 2007, 08:24 AM Great Script! I really love the continents and mountain ranges shapes, but I have two small complaints:
- Too much forests.
- Because of the forests there is HUGE lack of agricultural bonuses.
Thanks for the compliment. The thing about those forests though, is that they look so darn beautiful. They really did a nice job of making them mesh together in a natural way. It's very nice to have a wilderness feel before an area becomes settled. I confess I didn't really consider the gameplay changes.
I just figured if an area has enough rain to consider placing a jungle, then even in the temperate zone there should be a forest there unless someone chops it down.
I'll see what I can do about those ag. bonuses, I'm reworking my starting plot and normalization code and I may have to do something about bonuses in general. I also would like an option of dividing some resources between the old and new worlds.
Do I need to understand why? Naaaah.
Famous last words. It looks like CvPlot::getPathDistance returns the correct value only about 90% of the time. I'm not sure what it's intended use is. It's possible that some of the map data it needs is not initialized during map creation, but when it fails it really messes up my starting plot code. Unfortunately it's hard to research because the Astar code is not part of the DLL. I've implimented Astar a few times so I can do it in python, but it will delay the next publish if it comes to that.
I wonder at what point this script is going to be just too demanding in resources or processing time. I guess I'll just keep going till I hit the wall.
Seven05 Oct 09, 2007, 10:20 AM The thing about those forests though, is that they look so darn beautiful. They really did a nice job of making them mesh together in a natural way. It's very nice to have a wilderness feel before an area becomes settled. I confess I didn't really consider the gameplay changes.
All I did to address this for myself is add some random variance when placing features:
elif rm.rainMap[i] > terr.desertThreshold + (PWRand.random() * 0.1):#forest
I left the 'jungle' part alone so there are still large forest regions. Did you already have something like that though? I can't remember as I've had my head burried in the DLL code for a while now. Anyway, I haven't had too much trouble with excessive forests, especially on the plains which tend to be almost barren.
cephalo Oct 11, 2007, 07:53 AM Hi guys,
I'm still working hard on the new update. I've been running alot of experiments regarding starting locations and bonus normalization and I think I have settled on one of my more simple solutions. Basically I decide who goes on what continent, find a series of possible locations for cities and eliminate most of them according to value, then I place the players on that continent on these remaining locations that are furthest away from everyone else on the continent.
That works pretty well, but there is still some unfairness there. I have noticed that trying to make a bad location into a good one with bonuses can't be done without getting rediculous with the bonuses. Bonuses are good, but ultimately nothing beats a town on green. I've been trying to subtley boost the territory near the weaker start positions so I don't have to make the map look like a garbage dump. Watching 10 fish do syncronized swimming is pleasantly hypnotizing during a late night programming session and almost makes me want to put on 'Blue Danube Waltz', but I just can't do that to my maps.
Placing bonuses strictly according to the rules in the XML is alot of work, but I'm almost done with it. I've noticed that the default normalization process does not respect the bArea flag, and I think that on a map with a new world that becomes more important. I'll try to separate the normalization process with bonus placement process so they can both be cut out if needed by some modder. Actually the only modder I know using this map is Seven05, so I'm talking about him. ;) :lol:
Anyway, I still have alot of work to do for the next update, so it will be another week or so maybe.
Seven05 Oct 11, 2007, 10:16 AM Hey :)
Actually, don't worry about accomidating me at all. Any change you make that I don't like I just won't use or I'll change as needed. My version is now quite different that yours, about the only thing that is entirely unchanged is your comment block at the top. I'm also in the process of converting large portions of it into the DLL to speed things up (without breaking the other maps even though they really won't work for my mod anyway).
The people to worry about are the 'normal' people using a mod and your script, not the modders themselves (we like to change things).
Elhoim Oct 11, 2007, 02:59 PM Thanks for the compliment. The thing about those forests though, is that they look so darn beautiful. They really did a nice job of making them mesh together in a natural way. It's very nice to have a wilderness feel before an area becomes settled. I confess I didn't really consider the gameplay changes.
I just figured if an area has enough rain to consider placing a jungle, then even in the temperate zone there should be a forest there unless someone chops it down.
I'll see what I can do about those ag. bonuses, I'm reworking my starting plot and normalization code and I may have to do something about bonuses in general. I also would like an option of dividing some resources between the old and new worlds.
Yeah, the resources in general seemed a little off. Looking forward to the new version, and keep up the good work!
cephalo Oct 12, 2007, 08:17 AM Yeah, the resources in general seemed a little off. Looking forward to the new version, and keep up the good work!
There are two problems with resource placement that I have found. The obvious one is that the function CyPlot:canHaveResource returns false if there are trees in the way and that resource does not specifically allow them. The other problem is that the ag resources are considered 'unique' and only to be placed on the continent with the most space divided by the number of other unique resources already on that continent. Since the continents in this script are so highly variable, you never see any ag resources on the smaller islands and continents.
I need trees to move out of the way for resource placement, and also I need to designate multiple areas for unique resources to insure their is always enough room
cephalo Oct 12, 2007, 09:11 PM I just picked up BtS today! :clap: :clap:
Um.... This might delay the next map release. :mischief:
cephalo Oct 17, 2007, 03:36 PM Ok, just published a huuuge update.
Starting positions are much improved, and bonuses are placed somewhat differently than the default way to better suit this map script. That sounds pretty subtle, but this update was a huge amount of work both in research time and in debugging and even in just raw typing. It was worth it though, I think this update will enhance gameplay quite a bit.
Here's a wordy wordy explaination of what I did:
The default bonus placement procedure had some problems with PerfectWorld. In the XML, some bonuses are not placed according to how many players there are, but by how much suitable land exists for that bonus. If there are relatively few tiles that will allow such a bonus, the procedure will not try to make the most of the available room, but will simply lower the number of bonuses that it wants to place!
For example, wheat requires plains. If you have 200 plains tiles the calculated wheat to place might be 10 or so, but if you only have 100 plains you still might easily have room for that same 10 wheat, but the calculated need will only be 5 wheat. In the case of wheat, the need for it is calculated by the number of suitable tiles, not the need of the number of players. Players do not need wheat, the plains tiles need wheat. This is something I was unaware of when I made this map script.
The problem that this created for PerfectWorld was that this script really likes trees, and the basic function to determine if a resource is placeable will block any resource that does not explicitly allow trees. The solution for this was not only to rewrite that basic function to give precedence to resources over trees, but also to rewrite all procedures that relied on that function!
:sad:
Another enhancement that I made was regarding bonuses tagged with bArea=1. The default way is to choose one continent for this bonus. This is fine, but since PerfectWorld's landforms are so unpredictable, it left alot of little islands and such with no area bonuses. What I do here is to assign bonuses to one main continent with the most room, and then also to any continents that are most agreeable to that resources requirements and are most free from other one-area bonuses. This works very well to boost the importance of some of those smaller islands. Each landmass will likely have something that someone is missing.
For starting locations, I first assign each player to their respective continents according to the value on the continent. Then I make a list of the best places on the continent for cities. Then for each player on that continent I place them in those city places that are farthest away from other starting plots.
For normalizaton, I look at the value of each starting location, not just locally, but also what territory the player has the best access to. The normalizer will give a starting location up to 5 bonuses to help even things out. Bonuses will be placed according to the rules in the XML except in regard to spacing. PerfectWorld knows what bonuses are allowed on what continents and will give only those. The default normalizer ignores spacing and also the bArea flag. Keeping resources to their proper continents and islands insures opportunities for trade and less self-sufficiency. On this map, you could actually name your city 'Pigville' or 'Cowtown' and know exactly where in the world it is most likely to be. :)
Give it a try and tell me what you think.
Elhoim Oct 17, 2007, 08:58 PM Great! I'm going to try it now. :)
Elhoim Oct 20, 2007, 04:44 PM Pretty nice. The only thing it's lacking is some good rivers. In a standard map there were too few or too short, making farms a rare sight.
cephalo Oct 21, 2007, 08:17 AM Pretty nice. The only thing it's lacking is some good rivers. In a standard map there were too few or too short, making farms a rare sight.
If you prefer more rivers, you can adjust that with one of the tuning variables at the beginning of the script.
Rivers on this map require either lots of rain or lots of runoff space. The northern and southern rainy zones, because they are exaggerated in size, will likely be the source of some of your biggest rivers. There should also be many rivers near the equator. This map is different I suppose in that it is quite difficult to find spots for an ideal city. I think I like that though...
Caradoc Oct 24, 2007, 04:06 PM Your landmass generation is superb -- just what I've always wanted. The program ran slow, however, on my dual-quad/1GB system, and when I went back to the Main Menu to create a second map, it crashed.
I would beg you to provide more options, even beyond climate and sea level, which seem to be set to Temperate/Medium at the moment. I'd like to have control over the amount of each type of terrain, so I could have more hills and less tundra for instance. I'd also like the option of populating the map with animals and barbarians at the start.
jmm Oct 25, 2007, 06:56 AM You can always edit the script. There are several options at the beginning of the script that allow you to change the amount of terrain types (among other things)
I agree on having more in-game options will make things easier, fortunately its quite easy to edit the script and add them.
For instance I added an option to select the Random Generator (Civ 4 or Python). That took me around 5 minutes.
SevenSpirits Oct 27, 2007, 04:36 AM Wow, this is amazing! I can't give you enough props.
For the starting location plots, I'm not sure what the food=10, commerce=20 really ends up meaning (I'm sure it's not valuing commerce twice as much as food), but I would suggest valuing food even higher than they do. For one thing, your maps are less "nice" in that they have less food (more desert and plains). For another, real civilizations usually emerged where there was lots of extra food, so it really makes sense.
cephalo Oct 27, 2007, 09:28 AM Wow, this is amazing! I can't give you enough props.
For the starting location plots, I'm not sure what the food=10, commerce=20 really ends up meaning (I'm sure it's not valuing commerce twice as much as food), but I would suggest valuing food even higher than they do. For one thing, your maps are less "nice" in that they have less food (more desert and plains). For another, real civilizations usually emerged where there was lots of extra food, so it really makes sense.
Thanks! and yes, those values are the default way the game values each tile. However, there are also multipliers given if a tile can support itself.
There is one small bug left that I have found on this map. The start plot normalizer randomly chooses whether to boost your commerce, production or food depending on your relative starting plot quality to other civs. Occasionally you'll be placed in a spot with not enough food to work but a few tiles, and in compensation you get lot's of rocks. We all love rocks, but they aren't much good if you can't work em. Boosting the value of food in the script might help aleviate that, and also makes sense since any tile that feeds itself can have a cottage which is the most powerful improvement in the game. I'll try to fix that normalization problem in the future.
SevenSpirits Oct 27, 2007, 01:18 PM I tried changing a couple of things about the starting location choice and got very pleasing results, so I thought I'd share them. I changed several things, and my guess is that some of the changes are totally useless, but something seems better anyway.
-Changed food value to 30 from 10. Food really is very good.
-Multiplied city value by 1.2 if next to fresh water. I was getting lots of starts with no fresh water, and the health bonus is important. The default map scripts tend to add rivers and lakes for you to compensate.
-Further multiplied city value by 1.2 if next to a river. (Rivers are pretty nice to have.)
-Changed coast multiplier to 1.3, down from 2.0. I do not think it's important to have your capital on the coast. Personally I would rather have it inland in most cases.
-Commented out the section where you subtract out the feature yields if it thinks there should be a feature-eating improvement there. The reason is that I wanted to penalize jungle and reward forest in your first city, and this was a pretty elegant way to do it. Jungle in the capital sucks, and I was getting too much of it. It looked like there was already something to do with removing jungle but it sure wasn't enough.
I was really pleased with the result. I looked at 14 start locations and they all seemed fine. Before, I noticed a couple times where every single land tile in the BFC was jungle. That sucks. Also, it seemed to overvalue hills before. I think that's gone too.
cephalo Oct 28, 2007, 08:07 PM -Commented out the section where you subtract out the feature yields if it thinks there should be a feature-eating improvement there. The reason is that I wanted to penalize jungle and reward forest in your first city, and this was a pretty elegant way to do it. Jungle in the capital sucks, and I was getting too much of it. It looked like there was already something to do with removing jungle but it sure wasn't enough.
Careful with that, on PerfectWorld the jungle areas quickly become the real hotspots once you get iron working. You can do alot worse than start in jungle on this map.
I was really pleased with the result. I looked at 14 start locations and they all seemed fine. Before, I noticed a couple times where every single land tile in the BFC was jungle. That sucks. Also, it seemed to overvalue hills before. I think that's gone too.
Hmm, that shouldn't happen. I should have a function in there that removes jungle in all the space immediately next to the city, that should be fine for the time it takes you to get ironworking. If you're seeing jungle in every square, that must be a bug. Let me know if you see it again.
SevenSpirits Oct 28, 2007, 08:37 PM Yeah, I saw the code that takes out the jungles, and it's now worked for me every time but twice. I managed to get the problem where the jungle stays there once more by accident, by - I am pretty sure - messing up some python code. I think it ran into a problem that made it unable to place everyone and so it did some sort of default placement. The weird thing is that the first time I got it, I hadn't touched the file. That would imply there is a really rare bug in there. I wouldn't worry about it.
I agree that jungle is reasonable as long as it doesn't completely surround you. When I had the bug, I had to doubt my prospects at reaching Ironworking fast enough by working two coast tiles.
SlightlyMad Oct 29, 2007, 07:09 PM I'm really loving the climate regions of this map script. The default behavior is really awful, and it's always bothered me. I only have two things that would make this script better for me:
1) Is there any good way to reduce the number of rivers, particularly in the desert? Reducing the RiverThreshold value seems to help slightly, but mostly just makes them shorter. I'd much prefer a few long and twisting rivers over what I'm seeing, which is a river almost every tile, going 2-3 tiles in from the coast. I can accept this sort of thing a little more in the jungle, but it seems to really cover the desert with rivers, which is odd since as far as I can tell from the script, rivers are created from rainfall and deserts are created from a lack thereof.
2) Is it possible to reduce the "grain" of the landmasses? By that I mean, I'd rather have larger, blobbier continents than the snaky island chains the script tends to generate. I've tried increasing the LandPercent variable, and that does help a bit, but it's too much land.
Any suggestions to get me started on these things? I'm currently playing with the chunk size calculations for the latter, but I haven't gotten very far on the former.
SlightlyMad Oct 29, 2007, 07:42 PM Ha! I just had an embarrasing breakthrough. The riverthreshold comment says "A higher value creates more rivers over the entire map", but looking at the code I discovered the opposite to be true. It turns out that most of my above complaints about rivers were due to me lowering that value and in fact just making it worse.
I've also changed the divisor in the targetSize calculation in the FindIdealChunkSize method from 4 to 2. It's still a blobbier than I like, but it seems less grainy than the default behavior. I'm only testing on small maps though, and since the math is based so heavily on map size, I'm thinking it might look even better to me when I try huge (which takes about 10-20 minutes to generate on my computer).
SevenSpirits Oct 29, 2007, 11:55 PM Does anyone else think it would be cool to give the script an Earth-based heightfield and see what it spits out?
cephalo Oct 30, 2007, 10:32 AM 1) Is there any good way to reduce the number of rivers, particularly in the desert? Reducing the RiverThreshold value seems to help slightly, but mostly just makes them shorter. I'd much prefer a few long and twisting rivers over what I'm seeing, which is a river almost every tile, going 2-3 tiles in from the coast. I can accept this sort of thing a little more in the jungle, but it seems to really cover the desert with rivers, which is odd since as far as I can tell from the script, rivers are created from rainfall and deserts are created from a lack thereof.
This is a difficult problem since the rivers are generated from the hightmap. The only way to have longer rivers would be to have them go uphill sometimes, which is not really in line with this map script. Another problem is, the civ graphics do not allow river outflows from a lake, and since lakes can't overflow, rivers end when they hit them instead of continuing. The reason that rivers appear often in the desert is because deserts are often on the very largest continents, where there might be little rain, but the watershed is huge. Just imagine them as small rivers. I've gotten used to the way the system works and I like it. It does help to break up what can sometimes be a very large desert.
2) Is it possible to reduce the "grain" of the landmasses? By that I mean, I'd rather have larger, blobbier continents than the snaky island chains the script tends to generate. I've tried increasing the LandPercent variable, and that does help a bit, but it's too much land.
The easiest way to do that would be to change the dimensions of each map size. Extending one dimension so that it can be divided by 4 instead of 8 will have the effect you want.
SlightlyMad Oct 30, 2007, 10:55 AM Thanks cephalo, I ended up starting a game on a huge map last night, and it felt like I was playing an entirely different game! The exploration period was simply wonderful, these maps are truly a work of art, the likes of which the Civilization franchise has sadly not seen before.
I bumped the river threshold up a bit (I think I settled on 2.8, up from the default 2.0, IIRC), and bumped the floodplain threshold up a bit as well (I noticed I didn't have to do this much, as the increased river threshold is used as a multiplier with the floodplain threshold in the calculations). This ended up with very close to perfect rivers for me. For gameplay reasons, I'd like longer rivers, but these look very realistic. There were still a few rivers in the desert, but only the biggest had floodplains, so that's fine with me.
I also did something a little unorthodox and enabled floodplains on grass, plains, and tundra. They're extremely rare, as I set them to only check for a chance if no trees or jungles were generated, and the climate where the rainfall is right for no fauna but a floodplain is very rare. So far, it's only been in plains bordering the desert. I also bumped up the oasis chance to 12% from 8% so desert woludn't be completely barren without much floodplains.
I did however notice another minor complaint, when horses and other such resources are placed in the middle of the forest, there's a clearing. I gather that this is because there are so many forests and jungles on your map, so there otherwise wouldn't be much place to put them? I'd really rather decrease the fauna a bit and relegate such resources to only occurring in open spaces. It really gives the human an unfair advantage this way, as when I see a clearing in the middle of the forest I know to put a city near it. Ironically, the AI can't cheat in this way despite many peoples' claims to the contrary.
edit: Here's a nice little article from the straight dope that talks about how the great plains happened http://www.straightdope.com/columns/050708.html. I point this out because your script seems to put forests anywhere with enough rainfall, but in reality there should be some randomness to it that creates non-forested regions where it could otherwise support them. I may experiment with adding a deforestation routine to the map that goes through and clears off some large blobs of forest or jungle after they're generated.
cephalo Oct 30, 2007, 12:09 PM edit: Here's a nice little article from the straight dope that talks about how the great plains happened http://www.straightdope.com/columns/050708.html. I point this out because your script seems to put forests anywhere with enough rainfall, but in reality there should be some randomness to it that creates non-forested regions where it could otherwise support them. I may experiment with adding a deforestation routine to the map that goes through and clears off some large blobs of forest or jungle after they're generated.
Thanks for the nice compliment. The only time that forests are guaranteed is when the rainfall level reaches the 'rainforest' threshold, yet is too cold to be jungle. Otherwise they are randomly generated depending on rainfall. I really like the way it looks, (see some discussions above in this thread) and when you look at real areas with lots and lots of rain, there really are always trees there. The problem with so many trees though (see above for a detailed discussion) is that certain resources are severely restricted by them, so I had to give resources the right of way over trees. I know the clearings that you speak of, occasionally there is indeed nothing there! ;)
SlightlyMad Oct 30, 2007, 12:45 PM Hmmm, good point I guess. Even though I still stand by the example of the great plains as a more randomness-based area, it may be beyond the scope or requirements of such a model. I was doing a bit of research on biomes, and found a really neat map: http://www.worldbiomes.com/biomes_map.htm
When I compare that with the PerfectWorld maps, I think the main issue that's bothering me may just be too much moisture. Looking at Africa and even South America, savanna and grassland really dominates. I feel like a pw script of earth would fill them with jungle and forests.
I think I may be able to hack it to leave larger areas of low moisture surrounding the deserts by modifying this section:
if rm.rainMap[i] > terr.plainsThreshold*1.5:#jungle
if tm.tempMap[i] > JungleTemp:
if terr.terrainMap[i] == terr.PLAINS:
plot.setFeatureType(featureForest,FORESTLEAFY)
else:
plot.setFeatureType(featureJungle,0)
elif tm.tempMap[i] > ForestTemp:
plot.setFeatureType(featureForest,FORESTLEAFY)
elif tm.tempMap[i] > TundraTemp:
plot.setFeatureType(featureForest,FORESTEVERGREEN)
elif tm.tempMap[i] > IceTemp:
plot.setFeatureType(featureForest,FORESTSNOWY)
elif rm.rainMap[i] > terr.desertThreshold:#forest
if rm.rainMap[i] > PWRand.random() * terr.plainsThreshold * 1.5:
if tm.tempMap[i] > ForestTemp:
plot.setFeatureType(featureForest,FORESTLEAFY)
elif tm.tempMap[i] > TundraTemp:
plot.setFeatureType(featureForest,FORESTEVERGREEN)
elif tm.tempMap[i] > IceTemp * 0.8:
plot.setFeatureType(featureForest,FORESTSNOWY)
Instead of reusing the plains and desert thresholds, I can make separate forest and jungle thresholds that are slightly higher. If I'm not mistaken, this should allow for more forest on grassland, and open plains. Combined with the random deviation in plot choosing that I see is already present, this should allow for larger savanna areas surrounding the deserts.
cephalo Oct 30, 2007, 12:54 PM When I compare that with the PerfectWorld maps, I think the main issue that's bothering me may just be too much moisture. Looking at Africa and even South America, savanna and grassland really dominates. I feel like a pw script of earth would fill them with jungle and forests.
The first version of PW was more realistic in terms of relative rainfall, but the result was that there was soooo much desert and plains. It wasn't really working well for civ, and everyone wanted it to be adjustable so I changed it from an absolute calculation to a relative one so the map could be manipulated by percentages.
SlightlyMad Oct 30, 2007, 01:05 PM Ah okay, I get it. So the issue is that while I do have direct control over how much plains and desert the map has with your variables, I don't have direct control over how much fauna covers those base terrain. It looks like if I add in a couple more thresholds for Forest and Jungle though, I can satisfy this desire.
edit: By the way, is there any reason you prefer to set the variables in code rather than provide in-game settings? I'd be happy to send you the code to do so if it's just a matter of not having gotten around to it yet.
edit 2: And it looks like, if I feel comfortable that I've restored enough plains, I should be able to just add the CyPlot:canHaveResource check you mentioned before to the CanPlaceBonusAt method, right? Or if I feel a little fancier, I may actually have the AddBonusType method run two passes, one with the check and one without, but only if the first pass couldn't place them all.
cephalo Oct 30, 2007, 02:24 PM Ah okay, I get it. So the issue is that while I do have direct control over how much plains and desert the map has with your variables, I don't have direct control over how much fauna covers those base terrain. It looks like if I add in a couple more thresholds for Forest and Jungle though, I can satisfy this desire.
edit: By the way, is there any reason you prefer to set the variables in code rather than provide in-game settings? I'd be happy to send you the code to do so if it's just a matter of not having gotten around to it yet.
edit 2: And it looks like, if I feel comfortable that I've restored enough plains, I should be able to just add the CyPlot:canHaveResource check you mentioned before to the CanPlaceBonusAt method, right? Or if I feel a little fancier, I may actually have the AddBonusType method run two passes, one with the check and one without, but only if the first pass couldn't place them all.
The thing about the resource XML is that the desired number of some resources are calculated by how much available terrain there is, so if you allow the forests to block them you'll only get a small amount, even if there's room for plenty. So if half of your plains tiles are covered in forest, the XML rules will only try to place half the number of wheat bonuses than other wise. So if you want enough bonuses without removing forest, you would need two different functions for calculating numbers and then for actual placement.
SlightlyMad Oct 30, 2007, 02:53 PM Yeah, I'm just talking about adding a first pass in addition to your bonus placement, that works the same except it additionally has the CyPlot:canHaveResource check. That would leave the total number of resources the same (since your CalculateNumBonusesToAdd is still used), but would cluster them in non-forested areas where possible. I think this will allow for much more balanced maps with more plains, as the bonus resources will make up for the lack of forests and rivers in these regions.
If there's simply not enough unforested area to place all of a resource, it can make a second pass where it places them in forest clearings. I would also like to make these clearings a little bigger though. I do see that there's random chances of clearings anywhere in a forest, but the forest growth routines in-game will fill these in very quickly. Adding a routine instead that runs after forests are placed and makes random 2-3 tile clearings would be more subtle (and making the resource clearings 2-3 tiles to match).
Nkot Nov 02, 2007, 11:29 PM I don't post very oftern, but I just want to say that this is a very good map script (I only use it). I wholeheartedly recommend it to anyone who wants a realistic planet generated. Thought the author should know that there are plenty of people like me that fully support this script even though the forums don't show it. Keep up the good work.
On a side not, I do have one recommendation. It seems that in all the maps I've played, there are relatively few individual health resources (besides seafood). What I mean is there is only like 1 wheat on the entire map. However, I must admit that I play on small or tiny maps so it could just be that I need to play on a larger map.
Anyway, really nice script. It just keeps getting better and better.
Rael Nov 03, 2007, 05:52 AM I think I found the solution to the problem of short rivers. I replaced
self.averageRainfallMap[i] = avg
with
self.averageRainfallMap[i] = sqrt(avg * avg * avg)
and changed RiverThreshold from 2.0 to 0.06
There were less rivers and lakes in general but they were longer. The script produced some interesting rivers like the one on the first screenshot but occasionally I had some strange results (second screenshots). The other problem is that there were no floodplains no matter how low the FloodplainThreshold was (I had to make every desert river tile a floodplain).
SevenSpirits Nov 03, 2007, 02:37 PM I've been tweaking this script for myself. One notable change I made was to how you distribute the initial peaks. The way you do it now favors putting more peaks in the southernmost locations, because it loops through them from south to north.
I recommend replacing the loop starting with "allPeaksPlaced = False" with this one.
xGridPoints = self.mapWidth/self.chunkSize
yGridPoints = self.mapHeight/self.chunkSize -1 #we want to skip 0
while peaksPlaced < numberOfPeaks:
randomX = int(xGridPoints * PWRand.random())
randomY = int(yGridPoints * PWRand.random()) + 1
i = self.GetIndex(randomX*self.chunkSize,randomY*self. chunkSize)
if self.map[i] == 0.0:
self.map[i] = 1.0
peaksPlaced += 1
I also changed the tectonic section in my script so that colliding plates don't always both go up. I based how they interact on their IDs. If the IDs are 1 apart, they both go up a lot. If they are 2 or 3 apart, they both go down a lot. If they are more than that apart, the lower one goes down and the higher one goes up. I changed this because I thought making trenches would be useful in avoiding pangaeas. I'm not sure how much difference it makes, but I like it.
I also made a lot of changes to to starting locations that I'm really happy with, but that will take a while to format more nicely for you.
cephalo Nov 05, 2007, 07:30 AM On a side not, I do have one recommendation. It seems that in all the maps I've played, there are relatively few individual health resources (besides seafood). What I mean is there is only like 1 wheat on the entire map. However, I must admit that I play on small or tiny maps so it could just be that I need to play on a larger map.
I tried very hard to fix that in the last patch. The XML rules are very strict regarding those resources. They must be very far apart from one another and also far apart from same class resources like corn, and only exist on one continent. I kept the distance rule but also chose a few other continents to place them on in a way that preserved the spirit of that rule. Still, PW's landforms are so variable that sometimes there just isn't any any room on the smaller maps for all the resources that should be placed. No matter what sized map, wheat still will not allow placement within 5 squares of any other crop. That's alot of real estate on a duel sized map.
There were less rivers and lakes in general but they were longer. The script produced some interesting rivers like the one on the first screenshot but occasionally I had some strange results (second screenshots). The other problem is that there were no floodplains no matter how low the FloodplainThreshold was (I had to make every desert river tile a floodplain).Looks like you're adding a curve to the resulting rainfall map used to create rivers. That's a cool idea, it helps to simulate an evaporation factor that is missing. It should be very easy to fix the floodplains to follow that so you don't need a floodplain at every river tile. It's a double float so you can make it very small if need be. Floodplains are generated from the drainage map.
I've been tweaking this script for myself. One notable change I made was to how you distribute the initial peaks. The way you do it now favors putting more peaks in the southernmost locations, because it loops through them from south to north.Yeah, looking back I don't why I did it that way. Your way should work better. I have also had some complaints regarding the amount of land at the poles. It might be nice to eliminate the bottom row as well as the top row from consideration.
Right now I'm neck deep in a totally different map script, and I'm kinda excited about it. I will come back here and update PW when I get a chance. I'm not abandoning it.
SlightlyMad Nov 05, 2007, 10:10 PM Oh wow, I know this is sort of cheating, but I just figured out how to apply my hemispheres logic to this script. It's not perfect, but it's really quite cool.
Seven05 Nov 06, 2007, 10:04 AM Nice to see I'm not the only person getting a lot of enjoyment out of hacking Cephalo's script to pieces :)
I'd definately be interested in seeing some of the changes you've come up with, and I'd be happy to share my own. I'm particularly interested in SevenSpirits' (no relation BTW :) ) plate tectonics modification and SlighlyMad's hemisphere logic, even if it's not perfect :)
I have modifide plate creation to make landmass generation highly unpredictable (not always the same number of plates, not always even distribution) and reduce landmasses at the poles (pre-sinking of plates that 'touch' the top & bottom rows of the map). I've added climate based terrain (quite a bit more to that than just the mapscript though) and a bunch of other very minor tweaks.
GoodGame Nov 06, 2007, 07:03 PM Reading this just triggered a thought.
How about a chance that some of your rivers are actually underground rivers, rather than Nile-esque rivers? And related, perhaps the underground rivers have a chance of seeding 1-tile oasis and lake tiles?
This is a difficult problem since the rivers are generated from the hightmap. The only way to have longer rivers would be to have them go uphill sometimes, which is not really in line with this map script. Another problem is, the civ graphics do not allow river outflows from a lake, and since lakes can't overflow, rivers end when they hit them instead of continuing. The reason that rivers appear often in the desert is because deserts are often on the very largest continents, where there might be little rain, but the watershed is huge. Just imagine them as small rivers. I've gotten used to the way the system works and I like it. It does help to break up what can sometimes be a very large desert.
SlightlyMad Nov 06, 2007, 08:21 PM Here's the code I modified for hemisphere logic. Like I said, it's not at all perfect, and there's probably a much better way to do it, but it was a simple hack. I only implemented it for the height map, not the techtonics, as I ran into some problems there, and I sort of like it this way better since it's much less predictable. It's not a perfect split all of the time, but it is enough of the time for me. It also doesn't work with Duel maps, as it loses too much from the split, and there's not enough space to place all the peaks.
This is just a modification of SevenSpirits' code, above:
xGridPoints = (self.mapWidth/self.chunkSize) - 2
yGridPoints = (self.mapHeight/self.chunkSize) - 1 #we want to skip 1 around each side
if xGridPoints < 5:
errorString = "Map too small"
raise ValueError,errorString
#print "peak bounds: " + str(xGridPoints) + "," + str(yGridPoints)
while peaksPlaced < numberOfPeaks:
randomX = int(xGridPoints * PWRand.random()) + 1
randomY = int(yGridPoints * PWRand.random()) + 1
#print "trying peak " + str(randomX) + "," + str(randomY)
if (randomX < ((xGridPoints / 2) - 1) or randomX > ((xGridPoints / 2) + 1)):
i = self.GetIndex(randomX*self.chunkSize,randomY*self. chunkSize)
#print "accepted"
if self.map[i] == 0.0:
self.map[i] = 1.0
peaksPlaced += 1
#print "placed " + str(peaksPlaced) + " of " + str(numberOfPeaks)
Seven05 Nov 07, 2007, 12:41 PM Interesting, I took a completely different approach and 'carved' two random canyon-like paths up the heightmap by adding this pass after the 'midpoint displacement' passes. It's random enough to be hard to predict and it can create things like an inverted 'Y' or an 'X' pattern. At the same time is runs a subtractive noise over the entire heightmap with the effect being stronger closer to the poles. This helps break-up landmasses away from the equator without removing them completely. Being pre-tectonics it's not blatantly obvious so having your code before tectonics isn't really a bad thing.
long1 = PWRand.randint(0,self.mapWidth)
long2 = long1 + (self.mapWidth * 0.5)
if long2 > self.mapWidth:
long2 = long2 - self.mapWidth
for y in range(0,self.mapHeight,1):
biasPole = abs((self.mapHeight * 0.5) - y) / (self.mapHeight * 0.5)
long1 = PWRand.randint(long1 - 1,long1 + 1)
long2 = PWRand.randint(long2 - 1,long2 + 1)
for x in range(0,self.mapWidth,1):
i = self.GetIndex(x,y)
if PWRand.random() < biasPole:
self.map[i] *= PWRand.random() * 0.5 + 0.25
if x == long1 or x == long2:
for xx in range(x - 6,x + 6,1):
#Subtractive noise along simulated oceanic canyons
ii = self.GetIndex(xx,y)
if abs(xx - x) < 1:
self.map[ii] = 0
elif abs(xx - x) < 4:
self.map[ii] *= PWRand.random() * 0.5
else:
self.map[ii] *= PWRand.random()
SlightlyMad Nov 07, 2007, 12:49 PM Ooh, that's a much more interesting approach! I guess the purpose of mine was specifically to be more predictable, although in practice it isn't really anyways, and I'm noticing that it sometimes creates a pangea on one side and just scattered islands on the other (sort of like big & small).
A more interesting approach might be to take your "canyon carving" code, but have it work from a set start and end point, while making the path between them randomized. This would add more predictability to the split, while still avoiding perfectly straight lines.
edit: wait a second, that's more or less exactly what you're doing there, isn't it? I have to play with this more tonight!
SevenSpirits Nov 07, 2007, 01:56 PM I am very amused right now. :lol:
The day before discovering this map script, I was trying to mod Big and Small so that rather than use the more predictable hemispheres logic for making multiple continents (like Hemispheres does, obviously, not Big and Small itself), it would create a more random and unpredictable water barrier from north to south. Basically, the same idea as the underwater canyons here, but modifying actual terrain types (land -> water) instead of a heightmap.
I finally got it to work and it was pretty ugly. So I decided to come here and see if there were any good map scripts that could satisfy my hunger. What do you know!
I'm going to try out both of these modifications.
Seven05 Nov 07, 2007, 01:59 PM The start & end points are random, it picks one start (long1) then puts the second point 50% of the mapwitdh away them works it's way up the map shifting the x point +/- 1. So the only known factor is that you'll have two starting points evenly spaced, God only knows how they'll end up though :)
Where you used hemispheres here, I used them (sort of) in the plate tectonics. I place more plates initially then randomly select one region of the map and loop through those plots removing 25% of the plates. This results in less detailed plates in part of the map which can then translate to large landmasses or large oceans. But I also did this in a random fashion so sometimes it doesn't create any extra plates and doesn't remove any. The regions themselves are staggered blocks of tiles of various sizes so as not to create a 'big and small' type of map every time, sometimes the 'big' plates are in the center of the map, sometimes they're off in a corner. Unfortunately, it's a little sloppy and needs some tweaking, here's the code though if you want to play with it. This is the entire PerformaTectonics() function and include the polar plates code I worte to reduce landmasses near the poles a little:
def PerformTectonics(self):
self.plateMap = array('i')
doneMap = array('b') #use a little extra memory to speed this operation up
#initialize map with zeros
for i in range(0,self.mapHeight*self.mapWidth):
self.plateMap.append(0)
doneMap.append(False)
#seed plates
randomPlates = PWRand.randint(3,5)
numberOfPlates = self.mapWidth / randomPlates
randomRegions = True
topGap = int(self.mapHeight * (1.0 - self.polarGap * 0.5))
botGap = int(self.mapHeight * self.polarGap)
#The regions work by defining their portion of the map and removing plates
#in those regions.
#Default plate placement
for x in range(1,numberOfPlates + 1):
i = PWRand.randint(0,self.mapWidth*self.mapHeight - 1)
if self.plateMap[i] == 0:
self.plateMap[i] = x
if randomRegions == True:
regionSelect = PWRand.randint(1,3)
if regionSelect < 2:
#Western Region
iSouthY = int(botGap)
iNorthY = int(topGap) - 1
iHeight = iNorthY - iSouthY + 1
iWestX = int(self.mapWidth * 0.1)
iEastX = int(self.mapWidth * 0.4) - 1
iWidth = iEastX - iWestX + 1
elif regionSelect < 3:
#Eastern Region
iSouthY = int(botGap)
iNorthY = int(topGap) - 1
iHeight = iNorthY - iSouthY + 1
iWestX = int(self.mapWidth * 0.6)
iEastX = int(self.mapWidth * 0.9) - 1
iWidth = iEastX - iWestX + 1
else:
#Equatorial Region
iSouthY = int(self.mapHeight * 0.40)
iNorthY = int(self.mapHeight * 0.60) - 1
iHeight = iNorthY - iSouthY + 1
iWestX = 0
iEastX = self.mapWidth - 1
iWidth = iEastX - iWestX + 1
for y in range(iSouthY,iNorthY):
for x in range(iWestX,iEastX):
i = self.GetIndex(x,y)
if self.plateMap[i] != 0 and PWRand.random() < 0.25:
self.plateMap[i] = 0
#grow plates
doneMapFull = False
while not doneMapFull:
doneMapFull = True
for y in range(0,self.mapHeight):
for x in range(0,self.mapWidth):
i = self.GetIndex(x,y)
if self.plateMap[i] != 0 and doneMap[i] == False:
up = self.GetIndex(x,y-1)
down = self.GetIndex(x,y+1)
left = self.GetIndex(x-1,y)
right = self.GetIndex(x+1,y)
done = True
if self.plateMap[up] == 0:
done = False
if PWRand.random() < .5:
self.plateMap[up] = self.plateMap[i]
if self.plateMap[down] == 0:
done = False
if PWRand.random() < .5:
self.plateMap[down] = self.plateMap[i]
if self.plateMap[left] == 0:
done = False
if PWRand.random() < .5:
self.plateMap[left] = self.plateMap[i]
if self.plateMap[right] == 0:
done = False
if PWRand.random() < .5:
self.plateMap[right] = self.plateMap[i]
if done == True:
doneMap[i] = True
else:
doneMapFull = False
#Stagger the plates somewhat to add interest
for iPlate in range(1,numberOfPlates + 1):
polarPlate = False
#Bottom of map
for y in range (0,botGap):
for x in range(0,self.mapWidth):
i = self.GetIndex(x,y)
if self.plateMap[i] == iPlate:
polarPlate = True
#Top of map
for y in range (0,topGap):
for x in range(0,self.mapWidth):
i = self.GetIndex(x,y)
if self.plateMap[i] == iPlate:
polarPlate = True
adjPlate = PWRand.random() * 0.5 + 0.5
for i in range(0,self.mapHeight*self.mapWidth):
if self.plateMap[i] == iPlate:
if polarPlate == False:
self.map[i] += adjPlate
else:
self.map[i] -= adjPlate
#Now that the plates are grown, we must decide how the plate boundaries
#will effect our map. Basically, plots away from plate boundaries will
#cause some sinking, while plots closer to them while rise. After
#multiplying, the main heightmap will be re-normalized.
sinkValue = 1.5
peakValue = 2.0
searchRadius = 4
self.influMap = array('d')
#initialize map with sinkValue
for i in range(0,self.mapHeight*self.mapWidth):
self.influMap.append(sinkValue)
for y in range(self.mapHeight):
for x in range(self.mapWidth):
distance = self.FindDistanceToPlateBoundary(x,y,searchRadius)
i = self.GetIndex(x,y)
if distance == 0.0:
#not found in search radius
self.influMap[i] = sinkValue
else:
self.influMap[i] = self.GetInfluFromDistance(sinkValue,peakValue,sear chRadius,distance)
#next step is to multiply the influence map by the original heightmap
for y in range(self.mapHeight):
for x in range (self.mapWidth):
i = self.GetIndex(x,y)
self.map[i] *= self.influMap[i]
return
As you can see it's a work in progress, I've reduce and simplified the regions to three (east, west and equatorial) to make them more obvious in testing. I'd have to dig up the region code with more complex regions when I get home, it's burried there somewhere. I've had mixed results with this, the 'polar plates' code works very well but the regions have been giving me almost too much variety ranging from really crappy results to really, really good results.
Edit: Quick note, I have self.polarGap defined in the heightmap generation, you can replace them with values around 0.2 or define it yourself. COme to think of it, I think those values were used in my other code from the previous post... nope, nevermind :)
SlightlyMad Nov 07, 2007, 06:54 PM Ah yes, I see now. It starts them halfway across the map from each other, but their progress from there on is randomized, which allows for the "X" or "Y" formations.
I guess my issue is that, when I wrote the Hemispheres script, one goal was to make each continent equal in landmass. Otherwise you end up condemning the civs on the smaller landmass to technological inferiority.
I'll go ahead and give your code a shot, though. The hemispheres logic has always been a hack to me, and I think a more elegant solution is possible here.
Seven05 Nov 07, 2007, 09:22 PM You can change the code so they mirror each other very easily by changing this:
long1 = PWRand.randint(long1 - 1,long1 + 1)
long2 = PWRand.randint(long2 - 1,long2 + 1)
To something more like this:
long1 = PWRand.randint(long1 - 1,long1 + 1)
long2 = long1 + int(self.mapWidth * 0.5)
I don't think you need to check if Long2 is 'within' the map width since GetIndex handles wrapping itself. With a little more work you can keep them independant but enforce a minimum and maximum difference.
SlightlyMad Nov 07, 2007, 09:34 PM I'm actually relatively pleased with the results on huge maps, without your techtonics code. The techtonics code makes pangeas too often, so I took it out. On huge maps, since there's so much more area, the canyon code tends to be a more uniform distribution, and still plenty random. Since the land area is normalized across the map and techtonics are random anyways, it wouldn't help much to create an even split.
Ultimately, I might end up refactoring a bit more so the height map and techtonics placement are actually done twice, once per hemisphere, so it's basically creating 2 maps and joining them together, much like the hemispheres script does.
alireza1354 Nov 08, 2007, 06:44 AM THIS IS BY FAR THE BEST MAPGENERATOR EVER!!!!
O my God what cool maps!!!!!!!!
cephalo Nov 08, 2007, 07:03 AM I'm actually relatively pleased with the results on huge maps, without your techtonics code. The techtonics code makes pangeas too often, so I took it out. On huge maps, since there's so much more area, the canyon code tends to be a more uniform distribution, and still plenty random. Since the land area is normalized across the map and techtonics are random anyways, it wouldn't help much to create an even split.
Ultimately, I might end up refactoring a bit more so the height map and techtonics placement are actually done twice, once per hemisphere, so it's basically creating 2 maps and joining them together, much like the hemispheres script does.
The plate tectonics are largely responsible for the mountain ranges though, you wouldn't want to lose that I would think. There is a place where I stagger the heights of the plates, you might want to play around with that and decide some other way to stagger them.
Seven05 Nov 08, 2007, 08:36 AM The plate tectonics are largely responsible for the mountain ranges though, you wouldn't want to lose that I would think. There is a place where I stagger the heights of the plates, you might want to play around with that and decide some other way to stagger them.
Yep, making one slight change to my altered tectonics code (in the staggering) makes Pangea maps all but impossible without disrupting the mountains. Also, the tectonics code can produce some very good island chains and clusters, with small island chains being a continuation of a mountain range on the landmass nearby. IMO the tectonics are crucial to making good maps and changes in that section of the code have the biggest impact. By 'forcibly disrupting' the default tectonics code I can encourage the map to disperse the landmasses differently. The number of plates on the map (or any part of the map) has a big impact on the 'detail' of the landmass coastlines in that area with fewer plates resulting in less detail. You can enhance this effect with additional noise or smoothing passes on the underlying height map.
Anyway, the result I've been trying to achieve is a little bit of diversity in the landmasses. Or more consistent diversity (if that makes any sense) since I like to discover new worlds that are different than the old world in many ways.
So, if you curious about the 'simple change' I mentioned above here it is, just replace these lines:
for i in range(0,self.mapHeight*self.mapWidth):
if self.plateMap[i] == iPlate:
if polarPlate == False:
self.map[i] += adjPlate
else:
self.map[i] -= adjPlate
With this:
for i in range(0,self.mapHeight*self.mapWidth):
if self.plateMap[i] == iPlate:
if polarPlate == False and PWRand.random() < 0.5:
self.map[i] += adjPlate
else:
self.map[i] -= adjPlate
That will change it so non-polar plates can rise or lower instead of always rising. There are some other ways to do it, but I went with adding and subtracting rather than multiplying so it has a 'better' effect. I thought I had fixed this before posting it last time but apparently not :)
Seven05 Nov 08, 2007, 08:51 AM You know, I have one other change you guys might like too. I don't like the land tiles touching the north and south map edges (looks ugly IMO) but I do like the land mixing in with the ice features near the ice caps. This makes it difficult to circumnavigate early in the game and gives the subs a tactical advantage later in the game. In fact, I've had some cool maps where a coastal city or two are locked in by the ice that later turn into my primary submarine production cities.
It's difficult to force the landmasses away from the ice caps without creating pangea maps so I incorporated a trick. When placing terrain types any land tile that is colder than the ice threshold is converted to coast. It's as simple as this:
if tm.tempMap[i] < IceTemp + (PWRand.random() * 0.1):
if PolarLand == False:
hm.plotMap[i] = hm.OCEAN
rm.rainMap[i] = 0.0
self.terrainMap[i] = self.COAST
else:
self.terrainMap[i] = self.ICE
You'll have to repeat that code three times, once for each rainfall threshold (< desert, < plains and the last 'else' at the end). If you still want some 'ice' on the land you can blend it in with the tundra, I thought it looked fine without it so I left land 'ice' out completely. You can also remove the check for PolarLand, I put that in so that one day I could add in-game map options :)
SlightlyMad Nov 08, 2007, 10:32 AM The plate tectonics are largely responsible for the mountain ranges though, you wouldn't want to lose that I would think. There is a place where I stagger the heights of the plates, you might want to play around with that and decide some other way to stagger them.
Yeah, I was referring to Seven05's tectonics code that removes plates in one region of the map. I found that this code tended to create a pangea too often. I'm actually really liking the maps made with your default techtonics and his canyon digging in the height map. Still not exactly perfect, but very close.
Seven05 Nov 08, 2007, 11:44 AM That's been my eternal struggle... still not exactly perfect but so very close. :)
All things considered, I've been really happy with the results. Interestingly enough though, I don't get pangea worlds too often. What I get insted of pangea worlds are several landmasses that are only seperated by coast, not ocean (hense my ocean canyon code). But, just as often as I get them I get nicely dispersed and seperate landmasses with some scattered islands.
What I would really like to change is the tendancy to have all N-S continents or all E-W continents. My maps always look like they're stretched in one direction or the other.
Another thing I'd like to work out is shifting players around so their starting position is appropriate for the civ. Ethnic clusters would also be cool to add but I'm not sure I could accomplish both at the same time. Some examples would be ensuring civs like the Vikings, Dutch and Portugese start on costal tiles, the Celts start in hilly areas, etc...
SlightlyMad Nov 08, 2007, 12:20 PM Interestingly enough though, I don't get pangea worlds too often. What I get insted of pangea worlds are several landmasses that are only seperated by coast, not ocean (hense my ocean canyon code). But, just as often as I get them I get nicely dispersed and seperate landmasses with some scattered islands.
Yeah, you're right actually, I still think of those as pangeas, since the gameplay effect is mostly the same. I think the reason is that the reduction of plates in one reagion means the plates in the others grow larger and are more likely to connect. I might experiment a bit with altering the techtonics placement so it chooses 2-4 locations to add clusters of plates, rather than each plate scattering randomly.
Another thing I'd like to work out is shifting players around so their starting position is appropriate for the civ. Ethnic clusters would also be cool to add but I'm not sure I could accomplish both at the same time. Some examples would be ensuring civs like the Vikings, Dutch and Portugese start on costal tiles, the Celts start in hilly areas, etc...
Yeah, I played with the script in the other thread here that does that, and I ultimately didn't like the results. I think it was really along the right track though, and I'd like to alter the PW placement scripts with some of the ideas.
Basically, my thought is to keep the starting plot selection code as it is, but then add extra logic where it assigns them to the players. Each art style would have weighted factors, and a few individual civs would as well, so you could increase the chance of UU and UB relevant positions, and also take into account starting techs (give fishing civs seafood, mining civs hills, etc.).
I think the logic would work something like this:
Create a set of starting position "buckets" by art style
Iterate through starting locations
Get a relative terrain value for each art style
Place into the bucket with the highest art style
Iterate buckets
Iterate positions in this bucket
Iterate the other items in this bucket
Add to a relative proximity value
Add terrain value to this value
Iterate other buckets
Iterate items in this bucket
Add to a relative proximity value for this bucket
Add terrain value for bucket to this value
Compare values of this bucket to other buckets
If greater, switch buckets
Iterate buckets
Check number of players for this bucket
If too many, take lowest combined value items, and and put them in a "bone pile"
Iterate buckets
If extra spaces, pull greatest value items from bone pile
Iterate players
Iterate positions
Generate values based on terrain for this civ
Assign civ highest valued terrain in their bucket
That's off the top of my head, at least. I'm sure it could be more elegant and efficient. I'd have to make terrain and proximity value functions, since they're done over and over again. It shouldn't be much of a performance hit, since the starting positions pool is already narrowed down.
Ideally, it should group by art style, sort of like culturally linked starts did in Civ3, and then give each civ for that style the most logical start within.
The proximity function would also work better if it took water and mountains into account. For simplicity, it might work well to just draw a straight line, and add a total value based on the terrain (maybe flat=1,hill=1.5,mountain=3,coast=3,ocean=5), which would mostly confine cultures to a single continent, but still allow them on nearby islands or continents to an extent (think Japan).
Seven05 Nov 08, 2007, 01:03 PM Yeah, that'll be a project in and of itself... so I'll save it for last. Also, with some minor tweaking here before I go off to work I think I have hit on landmasses that I like. I've attached a couple of screenshots from my last test builds. Unfortunately I can't just upload the file, well I could but it wouldn't be usable for most people since I have edited a lot of it specifically for my mod, in particular I have climate based terrains so that entire block of code would have to be skipped and as a result I don't use altitude based temperature adjustments the same way Cephalo did (I apply them while assigning terrains, not directly to the temperature map).
Next up is getting rid of those straight lined jungles that plague about half of my maps.
Seven05 Nov 08, 2007, 10:40 PM Found a little bug in AddBonusType.
You have:
if self.CanPlaceBonusAt(plot,eBonus,False,False) and y > 1 and y < self.mapHeight - 2:
But it should read:
if self.CanPlaceBonusAt(plot,eBonus,False,False) and y > 1 and y < hm.mapHeight - 2:
At least the debug log is complaining about it with:
AttributeError: BonusPlacer instance has no attribute 'mapHeight'
It doesn't happen all the time, in fact before updating my resources and changing the bNormalize on several of them from 1 to 0, I never got this error. Anyway, it's easy to fix.
cephalo Nov 09, 2007, 06:43 AM Found a little bug in AddBonusType.
You have:
if self.CanPlaceBonusAt(plot,eBonus,False,False) and y > 1 and y < self.mapHeight - 2:
But it should read:
if self.CanPlaceBonusAt(plot,eBonus,False,False) and y > 1 and y < hm.mapHeight - 2:
At least the debug log is complaining about it with:
AttributeError: BonusPlacer instance has no attribute 'mapHeight'
It doesn't happen all the time, in fact before updating my resources and changing the bNormalize on several of them from 1 to 0, I never got this error. Anyway, it's easy to fix.
I can't find this code in the latest version. It looks like someone is trying to avoid resources being placed on the edge of the map, but that's something that never bothered me.
Seven05 Nov 09, 2007, 08:24 AM I can't find this code in the latest version. It looks like someone is trying to avoid resources being placed on the edge of the map, but that's something that never bothered me.
Hmm... maybe that was me... oops :)
Elandal Nov 10, 2007, 02:49 AM Regarding resource placement here's an excerpt from PythonDbg.log:
trying to place 18 of BONUS_RICE
Could not place 11 of BONUS_RICE
trying to place 29 of BONUS_SHEEP
Could not place 19 of BONUS_SHEEP
trying to place 22 of BONUS_PIG
Could not place 16 of BONUS_PIG
trying to place 20 of BONUS_CORN
Could not place 14 of BONUS_CORN
trying to place 9 of BONUS_BANANA
Could not place 1 of BONUS_BANANA
trying to place 6 of BONUS_DYE
Could not place 3 of BONUS_DYE
It seems that several health / food resources were not placed. Does this mean that the map has fewer of these resources than normally expected on the map of this size (large)? As all other resources were fully placed, could be that food and health is more of an issue on PW maps than on other maps?
cephalo Nov 10, 2007, 08:57 AM It seems that several health / food resources were not placed. Does this mean that the map has fewer of these resources than normally expected on the map of this size (large)? As all other resources were fully placed, could be that food and health is more of an issue on PW maps than on other maps?
There are two steps to placement that are used with the default method. First you decide how many are to be placed, then you decide where to place them. The quantity of ag resources are decided in relation to how many suitable tiles exist on the map. Most of them want 16 suitable tiles per resource. Once you get down to actually placing them however, the rules are different, and rather more restrictive. They cannot be placed within 5 tiles of any other same class resource. Each placement gobbles up a huge amount of real-estate, disproportionally so on the duel and tiny sized maps, but dats da rulz.
Adding to the problem is that the resources are placed in order. I randomize the order, but you will still get perhaps all the corn placed before any wheat has the chance, or vice versa. If they need to be placed on the same continent, then one of them is going to win over the other. They are designed to prefer different continents, if possible, and that's not always possible.
The only thing I'm doing differently to the default placement rules is that I am preventing features from blocking a resource, and also allowing them on more than one continent. One not so nice result of this is that you sometimes see corn in jungle areas. I figured that was an ok trade-off as now there are many more ag resources on the map than there were.
There are two reasons I believe that this placement method is still somewhat problematic with PW. One is that the landforms are much more unpredictable. The bArea rules seem to assume that there are 2 or 3 large bulbous continents with plenty of room for several of a unique bonus. Second, since terrains are normally very randomly scattered, instead of being in their proper place according to climate conditions, you probably have a much higher chance of seeing more plains 5 tiles away from a placement spot since the area being filled up is not a huge clump of plains, but random plains/grassland/desert.
In my testing, I found that only duel sized maps sometimes went without any of a particular resource, usually there was at least one. Not that surprising since any placement eats up half the map.
Elandal Nov 11, 2007, 01:48 AM Error in starting a new game.
PythonErr.Log:
Traceback (most recent call last):
File "PerfectWorld", line 3207, in generateTerrainTypes
File "PerfectWorld", line 1554, in generateContinentMap
File "PerfectWorld", line 804, in getNewWorldID
File "PerfectWorld", line 1013, in PrintList
File "CvUtil", line 108, in write
RuntimeError: unidentifiable C++ exception
ERR: Python function generateTerrainTypes failed, module PerfectWorld
Traceback (most recent call last):
File "PerfectWorld", line 3466, in assignStartingPlots
File "PerfectWorld", line 2104, in SetStartingPlots
File "PerfectWorld", line 2263, in setupOldWorldAreaList
AttributeError: TerrainMap instance has no attribute 'newWorldID'
ERR: Python function assignStartingPlots failed, module PerfectWorld
Do you need save file or is the error message enough?
I didn't bother playing that map in case this has an effect other than that there simply is no "new world".
Elandal Nov 11, 2007, 07:50 AM The stock map starting location normalizer modifies terrain where needed so that the starting location only has "good" terrain (grassland, plains, floodplains) not any of the "bad" types (desert, tundra, snow - all have FP<2), as well as removing jungle. PerfectWorld doesn't modify terrain, and limits jungle removal to one ring (three in stock normalizer).
Is this intended behaviour? If so, how does the normalizer count the starting location value so that it's within something (80%?) of best starting location? Simply by adding resources to push tile values up?
cephalo Nov 11, 2007, 08:56 AM Error in starting a new game.
PythonErr.Log:
Traceback (most recent call last):
File "PerfectWorld", line 3207, in generateTerrainTypes
File "PerfectWorld", line 1554, in generateContinentMap
File "PerfectWorld", line 804, in getNewWorldID
File "PerfectWorld", line 1013, in PrintList
File "CvUtil", line 108, in write
RuntimeError: unidentifiable C++ exception
ERR: Python function generateTerrainTypes failed, module PerfectWorld
Traceback (most recent call last):
File "PerfectWorld", line 3466, in assignStartingPlots
File "PerfectWorld", line 2104, in SetStartingPlots
File "PerfectWorld", line 2263, in setupOldWorldAreaList
AttributeError: TerrainMap instance has no attribute 'newWorldID'
ERR: Python function assignStartingPlots failed, module PerfectWorld
Do you need save file or is the error message enough?
I didn't bother playing that map in case this has an effect other than that there simply is no "new world".
I don't know what caused the first error, I think I have seen that before once in a while and I have not been able to investigate the cause. Why would it sometimes not be able to print a list in the debug log? Anyway that also causes the second error. I would imagine that map would be messed up in some way, if the terrain is correct then it's probably using the default starting code which will not respect the new world.
The stock map starting location normalizer modifies terrain where needed so that the starting location only has "good" terrain (grassland, plains, floodplains) not any of the "bad" types (desert, tundra, snow - all have FP<2), as well as removing jungle. PerfectWorld doesn't modify terrain, and limits jungle removal to one ring (three in stock normalizer).
Is this intended behaviour? If so, how does the normalizer count the starting location value so that it's within something (80%?) of best starting location? Simply by adding resources to push tile values up?
I worked my butt off trying to make starting locations as fair as possible, and the end result contains remnants of many failed experiments.:blush: I really don't like changing the terrain and features on the starting area because I think it looks terrible, and is a permanent ugly scar on the map. My normalizer will use bonuses to even things out as much as possible, and it works pretty well except sometimes it neglects to put enough food. I'll need to fix it when I have a chance. I also didn't like the way the default jungle remover completely denuded all the visible jungle in a starting area. One ring is enough to get you to iron working, and after that you have a great commerce generating city.
Elandal Nov 11, 2007, 09:38 AM I agree that not modifying the terrain makes for more beautiful map. I've had starts with lots of tundra, while desert starts usually have several floodplains that make them more useful (although health is immediate and grave problem in that case). Usually these can be used only as civ kickoffs - they send some settling parties out and palace will later be moved.
I'm not so sure about one ring only with jungle removal. It causes health trouble (so hacking more jungle than needed for improvements may be required), it grows over other tiles (twice as fast as forest), and when jungle is removed you're left with bare earth - great as it is there's no chopping speedup in the early expansion. I've had several grassland / forest starts as well and the grassland below jungle is no better than grassland below coniferious forest - unless jungle is sprinkled with higher concentrations of resources.
Of course neither of these problems is big - I can always regenerate the map if I want to.
Is there any guide to reading mapscripts? I have quickly scanned through some, but not sure about where to start with them if I want to look specifically for starting location assignment and normalization for example.
cephalo Nov 11, 2007, 09:54 AM Is there any guide to reading mapscripts? I have quickly scanned through some, but not sure about where to start with them if I want to look specifically for starting location assignment and normalization for example.
Most map scripts use the default procedures for most of their functionality. Only insane people try to replace everything. :blush:
The best place to get the 'official' way of particular map scripting tasks is in the SDK. Also, make sure to look at CvMapScriptInterface.py. That explains alot.
Seven05 Nov 11, 2007, 04:21 PM Funny thing is those are alot fo the issues I had with the base game that Cephalo's script finally gave me a means to overcome. The biggest thing for me is the climate based terrain, for instance instead of simply one type of grassland I have three; hot, temperate and cool. This gives me very specific control over features and resources such as jungles on hot grass only (during map creation) or corn on cool and temperate grass but not hot grass. With the way climates are generated by Perfect World resource distribution is far better than the old terrain & lattitude method even before his updated change. Unfortunately it's a complicated change that involves several different files. The cool part is that with this script we have access to more than simple plot types, areas and lattitudes so the ability to generate other terrain types based on altitude, rainfall and temperature opens up a lot of possibilities. With a little effort these map attributes can also be used to modifiy resource placement. Imagine if corn and wheat would only appear at sealevel +/- 10%, gems on plate boundries or whatever else you can dream up.
Sanchez Nov 11, 2007, 09:59 PM Is the link in the OP the most up to date copy? Because the file is quite a bit older than the post recent posts in this thread.
What is the status of start area normalization?
Props on all the great work, guys!
Seven05 Nov 12, 2007, 02:43 PM 1.06 is the most recent version and it's the file in the original post. It has the normilization code for starting positions in it and they work fairly well. And just for clarification this is all Cephalo's work, there are just a few of us that like to change his script to suit our own tastes.
SevenSpirits Nov 12, 2007, 10:12 PM Ever wondered what happens when you plug real earth altitude data into PerfectWorld? The answer is here. :)
I found a reasonable relief map of the world, converted it to a grayscale image of size 144x80, and used it in the script to initialize the height values of each plot. After adding a tiny bit of fractal noise (20% as strong as the earth data), the map of course was run through the usual wind, rain, and temperature functions and the terrain was all generated. I've tweaked the image a bit and the PerfectWorld parameters a lot to make it seem pretty reasonable. Here's an example start using that derivative script, with the following settings:
-Huge map (144x80)
-Emperor difficulty
-Normal speed
-Aggressive AI
-Raging Barbs
It should be pretty fun to play out. If you want a save with different settings, I can take requests. I don't want to post the script itself yet because it's still changing every few hours. ;)
Elandal Nov 15, 2007, 09:56 AM River placement seems problematic, as some river mouths not only look ugly but also leave diagonal normally river (but not riverside) tile without access to the river.
I can redraw the river mouth in worldbuilder so that it gets better graphics and also gives proper river access to possible diagonal tile, but obviously I can't do that for games I want to play.
All problematic river mouths I've seen have been of the wide mouth type (as again seen in the attachment below).
cephalo Nov 15, 2007, 10:05 AM River placement seems problematic, as some river mouths not only look ugly but also leave diagonal normally river (but not riverside) tile without access to the river.
I can redraw the river mouth in worldbuilder so that it gets better graphics and also gives proper river access to possible diagonal tile, but obviously I can't do that for games I want to play.
All problematic river mouths I've seen have been of the wide mouth type (as again seen in the attachment below).
I think I have finally figured out why this happens. First of all, this only happens when you 'regenerate' the map after starting a game, and the easiest way to fix it is to save and reload.
I think what is happening is that since my lakes are caused by rivers, and the addLakes function is called after addRivers, the placing of rivers before lakes requires some redrawing of rivers that is not happening in this case. Placing lakes after rivers is designed for lakes that are not connected to rivers in any way. The fix for this will be a big job however, I'm not sure when I will have time for it.
Elandal Nov 15, 2007, 11:16 AM So regenerate causes initialization to be different from what it would be from clean game startup? That must be a bit annoying to work around :(
Save & reload seemed to work indeed - so with workaround available it's not a big deal.
Elandal Nov 18, 2007, 04:31 PM The problem with river mouths is more than just graphical. This picture is after save & reload so graphical issue was fixed, still showing that the river mouth corners don't get fresh water and river commerce as they should.
The two tiles marked with black dots should be river corners, getting fresh water and commerce, possibly flood plain overlay (although this is just a bonus - standard map scripts just add floodplain to all desert river tiles).
cephalo Nov 18, 2007, 10:23 PM The problem with river mouths is more than just graphical. This picture is after save & reload so graphical issue was fixed, still showing that the river mouth corners don't get fresh water and river commerce as they should.
The two tiles marked with black dots should be river corners, getting fresh water and commerce, possibly flood plain overlay (although this is just a bonus - standard map scripts just add floodplain to all desert river tiles).
They should definately be fresh water, especially since there's a freshwater lake right there. The floodplains require a river crossing, which I guess is not happening there. I guess that when the rivers are placed those lakes don't exist yet and the engine isn't designed to handle that scenario. It thinks you can just go around the end and not cross a river. Are there any map scripts that have rivers flowing into freshwater lakes?
Victorvanwavere Nov 19, 2007, 03:14 PM Hey Cephalo,
I like your script, it generates some great maps.
I would however request a version that spreads the starting civs more evenly.
How would one make that tweak? (I realize you specifically made it so that certain areas are abandoned).
Also, why don’t you add the feature of few, normal & lots of resources?
Great work.
Elandal Nov 19, 2007, 04:08 PM I'm quite sure Big'n'Small and Hemispheres (the maps I mainly used in BTS) do that. However, this isn't limited to lakes. I founded a city where a river flowed to sea, and the diagonal tile didn't have fresh water. No screenie or save from that though - I'll try to remember it when it comes up next time.
Elandal Nov 21, 2007, 04:03 PM As starting location terrain is not modified in normalization but rather resources added, sometimes things go awry. I don't think four stones in capitol is all that good method in normalizing the location :)
Would it be possible to make sure that when adding resources, the same resource isn't added multiple times? A bit more diversity might make this look good.
alireza1354 Nov 22, 2007, 07:30 AM How come the giant and gigantic settings only produce grassland maps?
SevenSpirits Nov 22, 2007, 11:49 AM How come the giant and gigantic settings only produce grassland maps?
Those must be additional options enabled by a mod you're using, and the map script isn't expecting them.
If you open up the map script and search for "huge" you will see the list of maptype-to-dimension mappings. Maybe if you add your own giant and gigantic information it will work?
Seven05 Nov 22, 2007, 12:28 PM Ok, so now that I've changed most of the mapscript to create maps adjusted for my mod I was still facing one annoyance- players starting on really small 'continents' The problem was the way the new world was defined, it would go through the list of continents sorted by ID and keep adding them to the old world until the old world total land size was better than 60% of the total land. The problem was that there were frequently small continents mixed into the list, too small for a decent start (often as small as 9 tiles). My solution is to enforce a minimum continent size which scales based on the amount of available land.
Below is the entire 'getNewWorldID' function, most of it is unchanged from Cephalo's original code. The important part comes in after the two largest continents are assigned. Since I didn't comment the code I'll walk through it first...
After the largest and second largest continents are assigned to the old world and new world respectively we take the remaining list and sort it by continent ID rather than size (this is Cephalo's code) which helps with variety. Next we determine the minimum old world continent size, making sure it is at least 12 tiles (for smaller maps) but otherwise 2.5% of the total land. Then we evaluate each continent in the list, note that I didn't use a ranged loop here, doing so can throw an index out of bounds error since we're deleting items from the list as we go. Anyway, we step through the list and evaluate each continent, if it's larger than the minimum old world continent size it gets added to the old world. This continues until the old world uses at least 60% of the total available land or we run out of continents. If the old world is big enough with a single continent the entire process is skipped.
If you have logging enabled you can review the entire process in the log file. Anyway, here's the code:
def getNewWorldID(self):
nID = 0
continentList = list()
for a in self.areaList:
if a.water == False:
continentList.append(a)
totalLand = 0
for c in continentList:
totalLand += c.size
print totalLand
#sort all the continents by size, largest first
continentList.sort(lambda x,y:cmp(x.size,y.size))
continentList.reverse()
print ''
print "All continents"
print self.PrintList(continentList)
#now remove a percentage of the landmass to be considered 'Old World'
oldWorldSize = 0
#biggest continent is automatically 'Old World'
oldWorldSize += continentList[0].size
del continentList[0]
#get the next largest continent and temporarily remove from list
#add it back later and is automatically 'New World'
biggestNewWorld = continentList[0]
del continentList[0]
#sort list by ID rather than size to make things
#interesting and possibly bigger new worlds
continentList.sort(lambda x,y:cmp(x.ID,y.ID))
continentList.reverse()
oldWorldMinSize = max(12,totalLand * 0.025)
idealOldWorldSize = int(totalLand * 0.60)
oldWorldPercent = float(oldWorldSize)/float(totalLand)
print "Ideal Old World total size is %(w)2d" % {"w":idealOldWorldSize}
print "Current Old World size is %(w)2d" % {"w":oldWorldSize}
if oldWorldSize < idealOldWorldSize:
print "Minimum Old World continent size is %(w)2d" % {"w":oldWorldMinSize}
print "There are %(c)2d continents in the list." % {"c":len(continentList)}
o = len(continentList) - 1
n = 0
while n < o:
if oldWorldPercent > 0.60:
print "Old world continent selection complete, total size is %(t)2d" % {"t":oldWorldSize}
break
print "Evaluating %(c)2d, ID is %(d)2d." % {"c":n,"d":continentList[n].ID}
if continentList[n].size > oldWorldMinSize:
oldWorldSize += continentList[n].size
oldWorldPercent = float(oldWorldSize)/float(totalLand)
print "Adding continent %(c)2d to old world, total size is now %(t)2d" % {"c":continentList[n].ID,"t":oldWorldSize}
del continentList[n]
#decrease the list length (o) by one to prevent going out of bounds
#do not incriment the current count (n) here since that list item was removed
o -= 1
else: #incriment the counter if no continent was removed from the list
n += 1
#add back the biggestNewWorld continent
continentList.append(biggestNewWorld)
#what remains in the list will be considered 'New World'
print "New World Continents"
print self.PrintList(continentList)
#get ID for the next continent, we will use this ID for 'New World'
#designation
nID = continentList[0].ID
del continentList[0] #delete to avoid unnecessary overwrite
#now change all the remaining continents to also have nID as their ID
for i in range(self.mapHeight*self.mapWidth):
for c in continentList:
if c.ID == self.areaMap[i]:
self.areaMap[i] = nID
return nID
SevenSpirits Nov 24, 2007, 05:42 PM Here is the version of PerfectWorld I use. I tried to mark all the changes carefully, and here is a list of them:
I. PLATES
1) Changed tectonics so that some plates go down instead of up.
2) Added additional height variation to plates.
3) Fewer plates.
II. START POSITIONS
1) Improved city valuation (in my opinion)
2) Made city "boosting" algorithm weaker and subtler (E.g. you are less likely to end
up with four stone resources and no food.)
3) Changed player distribution algorithm so that it values quality of location more,
and being as far away from others as possible less.
III. PLOT TYPES
1) Made small tweaks to some thresholds based on personal preference.
2) Removed Flood Plains' ability to spawn in very cold areas.
3) If a Flood Plain or Oasis would spawn on a hill, that hill is converted to a plains hill.
IV. RIVERS
1) Rivers are based on normalized square of rainfall, resulting in longer rivers.
2) Rivers like to flow towards the sea more, and can overcome small valleys to accomplish this.
I think the changes I made to starting city placement are a definite improvement. The other ones might just be personal preference.
Note: I can't attach a .py file. You will have to rename this to have a .py extension if you want to try it out.
Seven05 Nov 25, 2007, 10:47 AM I'l definately have to take a look at your changes to the starting plots, thanks for posting that. What ever happened to your attempts at loading an image for the initial heightmap?
Dancing Hoskuld Nov 29, 2007, 01:37 PM Those must be additional options enabled by a mod you're using, and the map script isn't expecting them.
If you open up the map script and search for "huge" you will see the list of maptype-to-dimension mappings. Maybe if you add your own giant and gigantic information it will work?
I tried this and it did not work. Still end up with wall to wall grasslands.
On another note is it possible to make the additional resources placed with the starting city rellevant to the starting techs? I have yet to see a starting position where I can use aggriculture makes me wonder how my people learned it.:lol:
cephalo Nov 29, 2007, 05:05 PM I tried this and it did not work. Still end up with wall to wall grasslands.
This script has rather strict dimension limits. Specifically, the map must be evenly divisible, in Width and in Height, by a power of two that is at least mapWidth/16. It will throw a Python Exception if the size doesn't meet that criteria. Also keep in mind that the 'cell' size or whatever is 4x4 map squares I think. Any time you get wall to wall grassland it means the map script crashed.
PW is not the fastest map script on the block. Maps bigger than huge seems like it would take forever to generate. Also, this script is kindof a memory hog, I think Civ puts limits to how much memory is available to Python and there were some past versions of PW were I hit that limit with Huge sized maps. Good luck.
MrPopov Dec 04, 2007, 11:26 PM Ever wondered what happens when you plug real earth altitude data into PerfectWorld? The answer is here. :)
I found a reasonable relief map of the world, converted it to a grayscale image of size 144x80, and used it in the script to initialize the height values of each plot. After adding a tiny bit of fractal noise (20% as strong as the earth data), the map of course was run through the usual wind, rain, and temperature functions and the terrain was all generated. I've tweaked the image a bit and the PerfectWorld parameters a lot to make it seem pretty reasonable. Here's an example start using that derivative script, with the following settings:
-Huge map (144x80)
-Emperor difficulty
-Normal speed
-Aggressive AI
-Raging Barbs
It should be pretty fun to play out. If you want a save with different settings, I can take requests. I don't want to post the script itself yet because it's still changing every few hours. ;)
This is a fun idea! Thanks for the upload I am enjoying this map and would like to see more!
Seven05 Dec 11, 2007, 10:49 PM I finally released my mod if anyone's curious about what Cephalo's script can do with a little bit of creativity in the terrain types. :)
Maybe some of the praise I sang about this map script will make Cephalo famous too...
cephalo Dec 12, 2007, 02:42 PM I finally released my mod if anyone's curious about what Cephalo's script can do with a little bit of creativity in the terrain types. :)
Maybe some of the praise I sang about this map script will make Cephalo famous too...
Cool, I've been waiting for this. Hopefully I'll have time this weekend to try it out. Thanks again for all your help in ironing out the bugs.
SevenSpirits Dec 17, 2007, 05:54 PM I just had an interesting idea on how to improve continent shapes. That idea is to sink coastal tiles.
The premise is that big, round continents have a smaller percent of coastal tiles than long, skinny, winding ones. I like the former shape better. By eliminating coastal tiles, you eliminate land tiles mostly from the latter type. Of course, to compensate you have to up the land tile % first.
Another side effect this has is that it will tend to separate continents by wider strips of water, making them unreachable by galley. (There is still plenty of land reachable by galley though. Remember we're adding more land, and some of the long continents are going to be broken apart into galley-reachable islands.) Because we're now artificially separating continents, we can up the land percent even more.
Here is the base method you need to add to HeightMap:
def FloodCoast(self, minOrthogonals, minTotalAdjacents, chance):
#Each land plot orthogonal to at least <minOrthogonals> water plots and
#adjacent to at least <minTotalAdjacents> water plots becomes water
#with probability <chance>.
floodMap = array('d')
for i in range(0,self.mapHeight*self.mapWidth):
floodMap.append(self.OCEAN)
for y in range(self.mapHeight):
for x in range(self.mapWidth):
i = self.GetIndex(x,y)
if self.plotMap[i] != self.OCEAN:
adjCount = 0
orthCount = 0
for yy in range(y-1,y+2):
for xx in range(x-1,x+2):
ii = self.GetIndex(xx,yy)
if self.plotMap[ii] == self.OCEAN:
adjCount += 1
if xx==x or yy==y:
orthCount += 1
if(orthCount <= minOrthogonals or adjCount <= minTotalAdjacents or chance <= PWRand.random()):
floodMap[i] = self.plotMap[i]
self.plotMap = floodMap
There's a lot of ways to use this; here's what I'm trying right now. It's pretty arbitrary.
Instead of
self.GenerateFinalPlotTypes()
self.FillInLakes()
I have
self.GenerateFinalPlotTypes()
self.FloodCoast(1,1,.10)
self.FillInLakes()
self.FloodCoast(2,2,.9)
self.FloodCoast(1,2,.25)
self.FloodCoast(2,5,.9)
self.FloodCoast(1,2,.35)
I also upped the land percent to .38 and I'm using my modifications to the tectonics that allow plate boundaries to be lowered instead of raised. Finally I removed the initial random peaks (1s) from the heightmap generation. I just leave everything initially at zero before the midpoint displacement.
I'll try to post some screenshots soon.
Seven05 Dec 17, 2007, 08:43 PM Just when I think I'm happy with my current version you go and come up with more ideas... :)
Freakwave Dec 18, 2007, 09:02 AM Hi,
I learned of this great map script through seven05's world piece mod. This script is totally different from what ive seen in vannilla. Looking at some maps i thought id try and tone down the desert area. I did this by decreasing the desert percent by 0.1 and increasing the plainspercent by 0.1. Doing this i found that the desert area was a bit too little in comparison to your latest build. Should i look at other factors?
I found that, imo, the desert area a bit too big. I dont know if maybe increasing the number of oasis entice the ai to found some cities in the desert since now they wont even though there is incense to be found in abundance.
Also some civs like the spanish start too close to colder climates. This i found on large map 18 civs. moreover they were my neighbours (me as korea)
I plugged this mapscript into the total realism mod and it works, all extra resouces also are seeded.
Seven05 Dec 18, 2007, 10:06 AM Some of those results (like the civ starting positions) are specific to my mod, not the map script :)
I answered you in my mod thread but I'll answer you here for the benfit of evrybody else. The changes to the thresholds need to be very small, 0.1 is a big change so you can try adjusting it in 0.01 incriments or something a little bigger like 0.025. The problem that you'll run into is that the deserts are based on the continent shapes & sizes so different maps will produce different results even with the same settings. So make sure you try any changes out on several maps, not just one :)
There are also settings for rain noise and smoothing below all of the threshold values. I tend to agree with Cephalo's comments in the code that increasing those negates the climate effect to a degree, however a very small change in rain noise can help break up the desert with scattered plains tiles. Currently I have those values set to:
RainNoise = .2
RainSmoothingFactor = .02
You can try changing them to .25 and .025 respectively.
For those of you using the 'stock' PerfectWorld.py script you'll want even lower numbers, I've modified the rain code slightly since I relocated the temperature change with altitude code so I needed stronger noise for any effect at all.
Freakwave Dec 20, 2007, 04:11 AM Hmm yes too many mods to keep apart.. :D
ill test some maps to find out what works :goodjob:
cephalo Dec 21, 2007, 09:39 AM Ok, version 1.07 coming soon.
I fixed the problem with the funky river mouths! Placing lake tiles after removing rivers did not update the river crossing count stored in CvPlot. This problem affected not only lakes but also any harbors I may have created with the lake system. I tried removing rivers after placing lakes but that didn't work, so I replaced the affected rivers after lake placement and that solved the problem.
I also took steps to ensure that at least one resource of each type is placed on a map, and I did this carefully to minimize the violation of the XML rules which are very strict for a reason.
The next thing I want to do for this update is solve the problem of boosting resources without having enough food to utilize the added resources. No food is a worse thing than the the 1.06 version currently recognizes. I looked at the changes to city evaluation made by SevenSpirits, and I agree with many of issues that I saw in his code, but I'm not sure if I identified them all.
To summarize, some starting locations do not have enough food. It is impossible to completely eliminate the possiblility of a completely desert or tundra start, because sometimes the major continents end up very inhospitable. I can add fish, I can add commerce and production. Is that OK as long as I can add enough fish? That's the only problem that I'm seeing with 1.06 is that it adds resources to a starting city that can't be used. What other issues are there?
SevenSpirits Dec 22, 2007, 02:13 PM I actually ended up not using my last code to "flood" the coasts after all. I think I was getting lucky with my results because I don't like what it's doing now.
However, I did write two other functions for Heightmap which I am liking a lot. One is a simple aesthetic one that shifts the entire map sideways so as little land as possible lies on the seam imposed by the map being rectangular. The only drawback of this is that when you get Calendar it gives you a tiny bit of extra information.
The second one is more interesting. It figures out the areas in the ocean where, if there was land, that land would not be reachable by galley from existing land. It then slightly raises those tiles - causing some of them to become land. I use it after determining the sea level but before generating the plot types, so this results in more land overall without any additional connectivity and no more risk of making a large supercontinent. Some screenshots are attached of large maps using both of these changes. For these I have LandPercent at .27; it could probably stand to be a little lower.
I think it makes the world a bit less realistic but I like how it ends up playing a lot. There's just so much more interesting land to explore.
The code to raise level of oceans. Call by putting self.RaiseOceanAreas() right after self.FindSeaLevel().
def RaiseOceanAreas(self):
#init ocean map to be 1 at every water space
oceanMap = array('i')
for i in range(0,self.mapHeight*self.mapWidth):
oceanMap.append(0)
csea = 0
cland = 0
ctot = 0
for y in range(1,self.mapHeight-1):
for x in range(0,self.mapWidth):
i = self.GetIndex(x,y)
if self.map[i] <= self.seaLevel:
oceanMap[i] = 1
# mapString = ""
# for y in range(0,self.mapHeight):
# for x in range(0,self.mapWidth):
# i = self.GetIndex(x,y)
# if oceanMap[i] == 1:
# mapString += "."
# else:
# mapString += "X"
# mapString += "\n"
# print "Ocean Map"
# print mapString
#shrink it, now it's only ocean spaces
oceanMap = self.ShrinkOceanAreaBits(oceanMap, 1)
#again, now there's a buffer of ocean tiles
oceanMap = self.ShrinkOceanAreaBits(oceanMap, 1)
#one more time for a buffer for any land we create
outerOceanMap = oceanMap
oceanMap = self.ShrinkOceanAreaBits(oceanMap, 1)
#now some random shrinkage
oceanMap = self.ShrinkOceanAreaBits(oceanMap, .4)
oceanMap = self.ShrinkOceanAreaBits(oceanMap, .4)
oceanMap = self.ShrinkOceanAreaBits(oceanMap, .4)
if self.mapWidth >= 88:
oceanMap = self.ShrinkOceanAreaBits(oceanMap, .3)
if self.mapWidth >= 104:
oceanMap = self.ShrinkOceanAreaBits(oceanMap, .3)
if self.mapWidth >= 128:
oceanMap = self.ShrinkOceanAreaBits(oceanMap, .3)
# mapString = ""
# for y in range(0,self.mapHeight):
# for x in range(0,self.mapWidth):
# i = self.GetIndex(x,y)
# if oceanMap[i] == 1:
# mapString += "."
# else:
# mapString += "O"
# mapString += "\n"
# print "Ocean Map after shrinking"
# print mapString
innerOceanMap = self.ShrinkOceanAreaBits(oceanMap, 1)
#OK, now it's safe to raise the ocean up!
for y in range(self.mapHeight):
for x in range(self.mapWidth):
i = self.GetIndex(x,y)
if innerOceanMap[i] == 1:
self.map[i] = self.map[i] + .4
elif oceanMap[i] == 1:
self.map[i] = (self.map[i] + self.seaLevel)/2.0 + .2
elif outerOceanMap[i] == 1:
self.map[i] = self.seaLevel - .01
def ShrinkOceanAreaBits(self, map, chance):
#Each 'True' adjacent to at least one 'False' becomes a 'False' with probability <chance>
newMap = array('i')
for i in range(0,self.mapHeight*self.mapWidth):
newMap.append(0)
for y in range(self.mapHeight):
for x in range(self.mapWidth):
i = self.GetIndex(x,y)
if map[i] == 1:
newMap[i] = 1
if (chance == 1) or (chance > PWRand.random()):
for yy in range(y-1,y+2):
if newMap[i] == 0:
break
for xx in range(x-1,x+2):
ii = self.GetIndex(xx,yy)
if map[ii] == 0:
newMap[i] = 0
break
return newMap
The code to realign the map so less land is on the international date line. Use by calling self.ShiftLandToMiddle() after self.FillInLakes().
def ShiftLandToMiddle(self):
bestColumn = -1
bestColumnSeaTileCount = -1
for x in range(self.mapWidth):
columnSeaTileCount = 0
for y in range(self.mapHeight):
i = self.GetIndex(x,y)
if self.plotMap[i] == self.OCEAN:
columnSeaTileCount += 1
if columnSeaTileCount > bestColumnSeaTileCount:
bestColumnSeaTileCount = columnSeaTileCount
bestColumn = x
elif (columnSeaTileCount == bestColumnSeaTileCount) and (PWRand.random() < .25):
bestColumn = x
if bestColumn <= 0:
return
newPlotMap = array('i')
#initialize map with 0CEAN
for i in range(0,self.mapHeight*self.mapWidth):
newPlotMap.append(self.OCEAN)
newMap = array('d')
#initialize map with zeros
for i in range(0,self.mapHeight*self.mapWidth):
newMap.append(0.0)
for x in range(self.mapWidth):
xprime = x - bestColumn - 1
for y in range(self.mapHeight):
i = self.GetIndex(x,y)
iprime = self.GetIndex(xprime,y)
newPlotMap[iprime] = self.plotMap[i]
newMap[iprime] = self.map[i]
self.map = newMap
self.plotMap = newPlotMap
cephalo Dec 26, 2007, 10:41 PM Ok, 1.07 is released.
I fixed the river bug.
Added some stuff to the resource placer so that resources are guaranteed to appear unless random factors don't allow them.
Maps will now be more likely to have a new world.
The starting plot normalizer has been improved so that non-food resources aren't placed that can't be used. Food will be placed instead.
Let me know if you run into any bugs or problems.
Seven05 Dec 26, 2007, 11:28 PM Yay, more merging work :)
It'll probably be a week or two before I can get this into my mod and test it. I'll let you know if I run into any problems, of course once I start changing things...
cephalo Dec 27, 2007, 07:56 AM The only thing about this new version that is less than ideal is the way I increased the new world frequency. I simply sank the middle of the map in the X direction so that a vertical line in the middle is diminished somewhat. This works well to divide up the world east/west, but why can't the new world be south? or north? or northwest?
I felt that I was getting a 'coastal pangea' far too often. Usually, the map would be fine except for some island chain coastally connecting several major continents. I would prefer to find a way to analyze the shape of those large masses and pinch them off in the middle in the least noticible way.
Seven05 Dec 27, 2007, 10:10 AM Ah... Ok, I'll leave that bit out then since I use a simple pair of 'canyons' and carve them out of the heightmap before applying plate tectonics. They're random so I don't get obvious straight lines or anything like that and you can almost see them with my new 'deep ocean' terrain :)
I also have an optimized sea level finder, typically it's done in 2-3 passes with more accurate results than your original method.
I think the only way to ensure you have good continental seperation is to generate the heightmap like the default scripts generate landmasses. So select a number of regions on the map and build the land up within each region leaving a buffer of zero height plots between each region. You won't be able to use simple midpoint displacement though or you'll end up with square-ish continents frequently so you'll need some sort of fractal ridge generator. Perhaps something like an overlay layer similar to the plate generation that you use would also work, so generate the base heightmap first, then a second layer of continental shapes. When I first found your script I had played around with that, I generated plots using the default fractal world and then used them for the continental shapes by parsing the plot map and subtracting from the heightmap on every plot that was ocean. It was way too slow though since I was effectively generating two maps.
Oh, and if you're curious what an extra shade of ocean terrain can do for a map, here's a screenshot that shows the effect well on the minimap.
http://forums.civfanatics.com/attachment.php?attachmentid=165797&d=1197744108
cephalo Dec 27, 2007, 10:31 AM Oh, and if you're curious what an extra shade of ocean terrain can do for a map, here's a screenshot that shows the effect well on the minimap.
http://forums.civfanatics.com/attachment.php?attachmentid=165797&d=1197744108
Yeah, I noticed that when I was messing around with your mod. It does look very nice. Hey, didn't you once say that you were using multiple grassland/plains types? I didn't notice that in there. Did you decide against it for some reason?
Seven05 Dec 27, 2007, 10:50 AM They're all there, it's just subtle. I have three climate variations (warm, temperate and cool) of most terrain types but the different between either warm & temperate or cool & temperate isn't glaring so they blend fairly well. That screenshot only shows the warm climate so it's not a good example. The only thing I haven't worked out in a way that looks good is altitude based terrains (other than the deep ocean). Unfortunately the map resolution is just too coarse to make anything look good consistantly.
Your script has made a bunch of cool things possible too. With the climate info being used to generate the terrains I have been able to work up a somewhat realistic global warming effect that actually warms the terrain. I've also been able to enforce global warming related weather events occuring in propper climates. Its kind of funny, the maps look awesome with my modified PerfectWorld script, and then you run one of the standard maps and it just looks... bleh. Even with the new terrain kinda-sorta supported in the standard scripts they just can't compete.
Thorn Jan 01, 2008, 06:12 PM I love this map script. Is there any way to get it to work with mods? :(
cephalo Jan 02, 2008, 07:54 AM I love this map script. Is there any way to get it to work with mods? :(
In theory, the only mods it won't work with are one's that use custom feature types or custom terrain types.
Seven05 Jan 02, 2008, 08:17 AM If you can't get it to work with a mod check the mod's ini file and see if public maps are enabled. Assuming you have the mapscript in the right place (Civ4 directory/Public Maps, NOT in your my documents folder) it should work fine for most mods.
Wolfshanze Jan 02, 2008, 08:23 AM I love this map script. Is there any way to get it to work with mods? :(
I love it too... works just fine in my mod.
Thorn Jan 02, 2008, 03:07 PM Assuming you have the mapscript in the right place (Civ4 directory/Public Maps, NOT in your my documents folder) it should work fine for most mods.
Oops, wrong directory was indeed the problem. I should know better. :blush:
Thanks for the help guys. Everything's working ok now! :D
cephalo Jan 02, 2008, 10:29 PM I just published 1.08.
I really did not like the way I divided the world into two different hemispheres in 1.07. It made every map kindof similar and predictable. I replaced it with a simulated meteor shower that knocks out the bottlenecks on pangaea type continents. This way is better because the maps are less regular and more organic like they were pre-1.07. The effect is usually subtle, but sometimes you can discern a distinct impact crater. This looks cool and should give your Civ citizens reason to speculate how the dinosaurs died out.
Also I added a tuning variable to turn this feature off for those who do like pangaeas.
SevenSpirits Jan 02, 2008, 11:07 PM self.castMeteorUponTheEarth(x,y)
print "The age of dinosours has come to a cataclysmic end."
Awesome. :)
cephalo Jan 03, 2008, 07:12 AM Awesome. :)
:) My first 'easter egg'.
MrPopov Jan 04, 2008, 02:29 AM Is there a section of code or something I can comment out to remove the "new world" restriction?
I am looking at the continent id code and am a bit lost. I'm not much of a programmer but it seems like I might be able to do something here that will either comment out the new world code, or just assign the new world to the smallest continent (like a 1 tile island).
cephalo Jan 04, 2008, 07:33 AM Is there a section of code or something I can comment out to remove the "new world" restriction?
I am looking at the continent id code and am a bit lost. I'm not much of a programmer but it seems like I might be able to do something here that will either comment out the new world code, or just assign the new world to the smallest continent (like a 1 tile island).
I should probably have that as an option. Stay tuned.
There will be another update as I have discovered a problem with my start plot evaluation. I am counting all the food that a city can produce as if it can grow to full size, when in some cases, it can't. If a player starts on all tundra the evaluator sees a city with 20 food, which is impossible since the city can't grow past 2. I had a quick fix that really worked well; I set the value of non self-supporting plots to zero (fine for starting area calculation), but this solution caused a huge avoidance of the coast, which also produce only one food unless you have a lighthouse. Rather than assume that a lighthouse is in the mod, or perhaps not something better, I'm going to take a couple of days to add a proper buildingInfo loop to check the yield changes.
Osymandias Jan 04, 2008, 09:51 AM This mapscript looks superb and i think it's great to play on it, but unfortunately it won't work for me.
Everytime i try it i get a map full of grassland with rivers. There aren't any other features besides a little forest around the startingplots of the civs.
See screenshots.
I have the mapscript in BtS-Root/PublicMaps, but it also didn't work in the CustomAssets-PublicMaps.
My Machine:
AMD Athlon XP 3000+
2GB Ram
What could cause the problem?
cephalo Jan 04, 2008, 11:25 AM This mapscript looks superb and i think it's great to play on it, but unfortunately it won't work for me.
Everytime i try it i get a map full of grassland with rivers. There aren't any other features besides a little forest around the startingplots of the civs.
See screenshots.
I have the mapscript in BtS-Root/PublicMaps, but it also didn't work in the CustomAssets-PublicMaps.
My Machine:
AMD Athlon XP 3000+
2GB Ram
What could cause the problem?
That's a map crash. I think the map has to go in Civ4/PublicMaps and not BtS/PublicMaps.
SevenSpirits Jan 04, 2008, 11:36 AM I should probably have that as an option. Stay tuned.
There will be another update as I have discovered a problem with my start plot evaluation. I am counting all the food that a city can produce as if it can grow to full size, when in some cases, it can't. If a player starts on all tundra the evaluator sees a city with 20 food, which is impossible since the city can't grow past 2. I had a quick fix that really worked well; I set the value of non self-supporting plots to zero (fine for starting area calculation), but this solution caused a huge avoidance of the coast, which also produce only one food unless you have a lighthouse. Rather than assume that a lighthouse is in the mod, or perhaps not something better, I'm going to take a couple of days to add a proper buildingInfo loop to check the yield changes.
That's a good idea. I want to suggest three things:
1) Cache the list of buildings that affect plot yields so you don't have to loop through every building for every plot.
2) Take era into account. Dikes should not be a big factor in an ancient era start.
3) Take uniqueness into account. Moai Statues do not always get built in the capital, because there is only one of them. I would recommend not counting national/world wonders or projects at all.
About setting the value of non-self-sustaining plots to zero: is this before or after improvements? If it's before, you're going to value a 1f/6h/6c tile as zero. If it's after, that tile's value depends hugely on whether it decides to farm it or not.
Maybe we need to do food, commerce and production separately? You basically need a lot of food and some production, whereas commerce is gravy.
cephalo Jan 04, 2008, 12:12 PM That's a good idea. I want to suggest three things:
1) Cache the list of buildings that affect plot yields so you don't have to loop through every building for every plot.
2) Take era into account. Dikes should not be a big factor in an ancient era start.
3) Take uniqueness into account. Moai Statues do not always get built in the capital, because there is only one of them. I would recommend not counting national/world wonders or projects at all.
About setting the value of non-self-sustaining plots to zero: is this before or after improvements? If it's before, you're going to value a 1f/6h/6c tile as zero. If it's after, that tile's value depends hugely on whether it decides to farm it or not.
Maybe we need to do food, commerce and production separately? You basically need a lot of food and some production, whereas commerce is gravy.
All good points. Caching relevant buildings will allow a more thorough check and speed things up a great deal. I've done some initial research and the buildingInfo stuff is extremely complex. I hope I don't hit any snags. For example, some buildings require multiple techs, which might mean multiple eras. The xml has one prereq tech, then a separate list of techs (see Grocer). I hope that there aren't too many convoluted data structures like that out there. Also, with UB's added in Warlords, I might have trouble making this work with vanilla, since I don't want UB's involved in this calculation.
I'm not too worried about missing the occasional 'sweet spot' like 1f/6h/6c. I've come to believe that finding starting positions is a matter of avoiding really bad ones rather than finding the best ones. Missing something basic like lighthouse/coast will not work unfortunately. After improvements, bonuses and starting era compliant buildings are factored in, I'm thinking that excluding non-self-supporting plots can only improve things.
SevenSpirits Jan 04, 2008, 12:33 PM One problem with this is you're going to value hills as zero unless you count windmills (which are unbuildable early, and also might not be in the mod). Having some hills for production is usually very important.
Another interesting issue I ran into earlier with the script is when I was using a mod where Serfdom gave +1h to Farms. The script proceeded to value farms as if they were always 1f/1h, which is very high. (IIRC, the 1f is the bonus from Biology - I don't think it was counting the 1f from irrigation. This would mean if someone plays a mod that doesn't go up to that age, farms would be treated as worthless, and there would be no way to up the food count of a tile, thus making all plains worth zero. I may be wrong and it still treated freshwater tiles as being +1f from farms, however.)
Osymandias Jan 05, 2008, 04:00 AM That's a map crash. I think the map has to go in Civ4/PublicMaps and not BtS/PublicMaps.
Ah, that's an option i haven't thought of. I will try it and report. Thanks :goodjob:
/edit: No, it still don't work. :(
cephalo Jan 05, 2008, 12:02 PM Ah, that's an option i haven't thought of. I will try it and report. Thanks :goodjob:
/edit: No, it still don't work. :(
Are you using any mods that have custom terrain types(like "lava") or something? Are you using a Mac? Can you make a duel size map?
Osymandias Jan 05, 2008, 02:32 PM I use the Blue-Marble-Mod, which is just a terrain-textures mod and some python-modcomps.
I run a PC, Athlon XP 3000+, 2GB RAM, WinXP SP2.
I will try a duell-size map.
/edit: No :(
But at least there are some lakes :D
cephalo Jan 05, 2008, 05:32 PM I use the Blue-Marble-Mod, which is just a terrain-textures mod and some python-modcomps.
I run a PC, Athlon XP 3000+, 2GB RAM, WinXP SP2.
I will try a duell-size map.
/edit: No :(
But at least there are some lakes :D
Is anyone else having a map crash problem? There's a way to turn on python error popups in the CivilizationIV.ini file that is in your myDocuments/games/BtS directory. Set HidePythonExceptions to '0' and that should pop up with the reason the map is crashing. In the same file you might enable the logging system as well to see how far the script is getting.
cephalo Jan 05, 2008, 06:16 PM 1.09 is published.
The trouble I was having with the avoidance of the coast was due to a bug introduced in 1.07 that was assigning the value of only one plot and then multiplying it by the CoastalCityValueBonus variable. I had turned that variable up to 10.0 and it was still avoiding the coast, so I knew something was broken. :lol: Python let me use an old variable name since scope is not an issue. I swear so many of the things that scripting languages try to do for you to make things supposedly easier just end up introducing bugs. Type checking, etc. is a good thing, not a bad thing!
Once that was fixed, I suddenly had alot more control over my starting plot results and rather than worry about building effects and stuff, I just made a rule that if food + production + commerce < 3, then the plot has no value. This solved the problem of lots of tundra being an option for a starting plot and so I am very happy with it. I generated lots of maps and I was unable to find even one bad starting plot. Unless I made a recent mistake, this should be a good final version for PerfectWorld.
Also I added an option to turn off the 'New World' placement rules.
Osymandias Jan 06, 2008, 12:05 PM Is anyone else having a map crash problem? There's a way to turn on python error popups in the CivilizationIV.ini file that is in your myDocuments/games/BtS directory. Set HidePythonExceptions to '0' and that should pop up with the reason the map is crashing. In the same file you might enable the logging system as well to see how far the script is getting.
Just tested with version 1.09.
On startup of BtS i get an errormessage that the mapscript cannot load. -> See screenshot
The Pythonerror-Log is also attached.
cephalo Jan 06, 2008, 03:12 PM Just tested with version 1.09.
On startup of BtS i get an errormessage that the mapscript cannot load. -> See screenshot
The Pythonerror-Log is also attached.
Ok, 'random' is the random number generator that python uses. I wonder why it would not be able to import the random module. Could there be a naming conflict with the modcomps you are using? What directory exactly are you putting PerfectWorld.py in? What happens if you run plain old BtS?
Make sure the map is not in the My Documents\My Games\Civilization 4\PublicMaps folder, but the Civilization 4\PublicMaps folder.
Osymandias Jan 07, 2008, 03:25 AM I tried it with an empty/deleted BtS-CustomAssets and it also didn't work :(
I placed it into Civ4-Root/PublicMaps.
This really is a mystery for me....
Elandal Jan 07, 2008, 06:29 AM I have the map in "My Documents\My Games\Beyond the Sword\PublicMaps" which is quite unlike instructed, but it still works fine. Of course this way it wouldn't be found for Warlords or Vanilla, but I don't have Warlords installed currently and don't play vanilla, so doesn't matter to me.
cephalo Jan 07, 2008, 07:37 AM I tried it with an empty/deleted BtS-CustomAssets and it also didn't work :(
I placed it into Civ4-Root/PublicMaps.
This really is a mystery for me....
Make sure you have no other copies in any other folder. What civ does when it initializes Python is it collects all the scripts and runs them all. It does not wait til they are needed. I discovered this when I had a test .py script that went into an endless loop, it completely prevented Civ from starting. I think it searches for standard Python modules in a directory relative to where the map is found, and it doesn't do that properly for all locations that it's possible to put a map. Somewhere on this forum is the answer, but I can't remember all the stuff I've seen. It's definately something simple though.
Osymandias Jan 08, 2008, 07:42 AM Ok, yesterday i tried x combinations of empty customassets and places where to put the mapscript, but nothing helped.
I deleted the customassets of all 3 civ-versions one after another till all 3 where empty: failure
I placed it one after another in vanilla/publicmaps, warlords/publicmaps and bts/publicmaps: failure
I tried it with the publicmaps in my games/bts/publicmaps: failure
I tried everything with the newest version i downloaded before i started to test it.
I can't say what is going on....i know it's a problem on my machine (at least it seems that i'm the only one where it will not work), but i can't figure out what exactly.
I don't think it has anything to do with it, but i'm running the german version of win and civ. This is the last thing that i can think of why it coul not work.
This really bugs me. I also think it's simple, but those are as always the worse to find.
cephalo Jan 08, 2008, 08:19 AM Ok, yesterday i tried x combinations of empty customassets and places where to put the mapscript, but nothing helped.
I deleted the customassets of all 3 civ-versions one after another till all 3 where empty: failure
I placed it one after another in vanilla/publicmaps, warlords/publicmaps and bts/publicmaps: failure
I tried it with the publicmaps in my games/bts/publicmaps: failure
I tried everything with the newest version i downloaded before i started to test it.
I can't say what is going on....i know it's a problem on my machine (at least it seems that i'm the only one where it will not work), but i can't figure out what exactly.
I don't think it has anything to do with it, but i'm running the german version of win and civ. This is the last thing that i can think of why it coul not work.
This really bugs me. I also think it's simple, but those are as always the worse to find.
Hmmm... When you say 'failure', you mean it's always that same exact error message correct? And also you removed the script from all those directories where it didn't work right? Do a windows search and eliminate all other copies of PerfectWorld.py. If civ gets a hold of the wrong one first it will probably fail.
Osymandias Jan 08, 2008, 12:56 PM Yes, everytime the same error message on startup after the intro but before the mainmenu screen.
I did a windows search at the very first and it found only the one script which i just downloaded before that. I moved the file to the other directories i tried, so it was always only this one file on my whole pc.
cephalo Jan 08, 2008, 01:51 PM Yes, everytime the same error message on startup after the intro but before the mainmenu screen.
I did a windows search at the very first and it found only the one script which i just downloaded before that. I moved the file to the other directories i tried, so it was always only this one file on my whole pc.
There might be one more issue to try. I believe that Civ has a cache of some sort where it won't reprocess the python files if it thinks they haven't changed. I think you hold shift while starting civ (or something like that) I haven't tried this myself.
I found this hint form LDiCesere's tectonics map script instructions:
"Usage: Put it in PublicMaps and hold shift to clear the cache the first time you want to run the game if you get errors with the map file."
Sorry to put you to so much trouble, but it's worth it if you get it working! I promise!
Edit: here's something I found in my CivilizationIV.ini file. My cache is disabled.
; Disable caching of file system (may slow initialization)
DisableFileCaching = 1
Osymandias Jan 09, 2008, 02:23 AM I did that most on the beginning of the testings, but now you say it i don't know if i tried it when i had the script in bts/publicmaps.
I will try to disable the cache when i'm at home today.
I appreciate your effort to help me :)
Thanks
cephalo Jan 09, 2008, 07:31 AM I did that most on the beginning of the testings, but now you say it i don't know if i tried it when i had the script in bts/publicmaps.
I will try to disable the cache when i'm at home today.
I appreciate your effort to help me :)
Thanks
Just to be certain, put it in Civ4/PublicMaps just because that's where mine is and it works for me. Then you can move it if you wish. Other map scripts might work in BtS/PublicMaps, but most don't import Python modules I don't think.
Osymandias Jan 09, 2008, 08:26 AM I got it! :D
Finally (10 minutes ago) i got it!
It was the simplest thing i could imagine that caused this problem. But one after another. At first i tried the cache-thing with no effect. Then i thought "okay, last try, now i move every other mapscript out of the root-publicmaps directories into neutral ones, one after another. I started with the bts/publicmaps and moved every mapscript in it into a neutral directory with no effect, then i tried the vanilla-publicmaps and bamm, it worked! A great light bulb moment :D
Then i moved every mapscript back and started BtS. I did this with the first 5 and then i read it in the neutral directory: random.py!
It seems that i copied aeons ago a mapscript with the name random.py into the vanilla/publicmaps directory and that caused the problem with your script. I renamed it and now everything works fine :D
See screenshot.
I want to thank you all for possible solutions and excuse me for my clumsiness :blush:
:goodjob:
I have the mapscript in BtS/PublicMaps and it seems that it works perfect now.
cephalo Jan 09, 2008, 09:19 AM I got it! :D
Finally (10 minutes ago) i got it!
It was the simplest thing i could imagine that caused this problem. But one after another. At first i tried the cache-thing with no effect. Then i thought "okay, last try, now i move every other mapscript out of the root-publicmaps directories into neutral ones, one after another. I started with the bts/publicmaps and moved every mapscript in it into a neutral directory with no effect, then i tried the vanilla-publicmaps and bamm, it worked! A great light bulb moment :D
Then i moved every mapscript back and started BtS. I did this with the first 5 and then i read it in the neutral directory: random.py!
It seems that i copied aeons ago a mapscript with the name random.py into the vanilla/publicmaps directory and that caused the problem with your script. I renamed it and now everything works fine :D
See screenshot.
I want to thank you all for possible solutions and excuse me for my clumsiness :blush:
:goodjob:
I have the mapscript in BtS/PublicMaps and it seems that it works perfect now.
Great! Dang, now I have to remember that my map script is incompatible with any other map script that happens to be named 'random'.
Have fun!
Edit: Hopefully, nobody decides to make a map script named 'Math.py' :)
Woody1 Jan 09, 2008, 11:27 AM Very cool map script. I'm not sure why you say it has to be placed in the Program Files area, though. I stuck the script under My Documents\...\Beyond The Sword\PublicMaps and it works fine. Was your restriction just for early versions of the script?
Anyway, I like the maps it creates. The only issue I find is the the resources tend to be very clustered and often limited to a single continent. Not sure if that's the intent, or just a consequence of the maps being more "smooth" than the standard maps.
|
|