[Map Script] PerfectWorld2.py

@Cephalo
This meteor thing is really difficult
Yeah I can imagine! Trying to get the continents looking "natural" would not be easy. Sometimes I wonder if tectonic plate simulation might be away forward? Start with a random fluctuation of "matter" on a bare map, conglomerate the "matter" into a heap, then move the heaps toward the centre of the map at different velocities and create elevation differences at the points where they collide using Newtonian equations, then add water to form continents? Sounds simple. Yeah right.

@PTM
Thanks for the info on start location. The revdcm version doesn't change any of that code. Only solution for now is to play the RevDCM mod below with the default number of civilizations and let the barbarian code spawn new civilizations over time. Works well. Note that the perfect world script in the RevDCM download is not as up to date as the one on this forum.

Cheers.
 
This meteor thing is really difficult. I need another week to think it through. At present its an equal mix of: "works beautifully", "doesn't work", and "destroys the whole world with meteors". I know it's possible to get this right, but I need to start thinking out of the box.

Perhaps instead of the meteor striking the ground and removing tiles, it could strike the ground and push all the tiles away from it? So you wouldn't risk destroying the world, you'd just move it around a lot
 
Perhaps instead of the meteor striking the ground and removing tiles, it could strike the ground and push all the tiles away from it? So you wouldn't risk destroying the world, you'd just move it around a lot

Well, at this juncture there are no tiles per say, only measures of altitude. The tiles come only after the climate has been generated.

I have a few promising ideas to try yet that might work perfectly.
 
I did it!! Hey, I have a rather exciting story to tell about how I solved this problem. Well, maybe it's not that exciting and I'm just nerdy. Anyway, the problem is just how does one break a pangaea continent with a minimal number of meteors programmatically? Basically you want to detect where the thinnest choke points are and throw a meteor at them, hoping to divide the big continent into two.

In PW1 I found chokepoints by drawing a circle around a point, and checked each square in the circles progression for water on opposite points on the circle and also land on opposite points. Then I sorted all the choke points I found by distance to the geographic center of the continent, pick the one closest to the center and put my meteor there. This method worked ok, but there were many meteors that were thrown unnecessarily at the exterior limbs of continents. The center of a continent was not always close to the place where the meteors needed to go. In worst case scenarios much of the land was destroyed before a satisfactory division of continents appeared. In PW1 all this happend after climate generation so the large oceans created by the meteors had no effect on the climate. Fortunately, I was able to tune certain variables so that the meteor scheme worked pretty well almost all the time. The continent shapes in PW1 just happened to avoid worst case behavior mostly by luck.

When I tried to apply this scheme to PW2, I ran into some problems. First of all, I really wanted any oceans created to effect the climate properly, and that meant that I had to throw the meteors before I generated the climate. That meant that I had to work with the heightmap on a different size than the final map, so I could not use 'coast' tiles to test if I had really broken the pangaea or not. Further complicating the situation was the new toroidal option. It is much harder to break up a pangaea that can connect in every direction. I initially just turned the meteor code off when using toroidal, because it failed more times than it worked.

When you look at a pangaea map, the human eye can instantly see where the meteors need to go, so why couldn't I make it happen programatically? It was driving me nuts. So last week I googled and wikepediad and googled again, and I found an interesting article about something called 'betweeness centrality'. After looking further I found an efficient algorithm, invented by Ulrik Brandes, for determining betweeness centrality over a network. But hold on, finding betweeness centrality involves calculating all shortest paths from each continent square to every other continent square. Obviously that's way too much processing overhead, and it was because I tried it anyway just to see what the results would be like. I let the computer run all night and it still wasn't finished, so I never even got to see if I was on to something.

All was not lost though! I decided to drastically cut the processing time by approximating the continent shape at a much lower resolution, and with four connected neighbors instead of eight. So instead of evaluating the paths to every continent square, I was evaluating every 5th one in the x and y directions. So instead of my network looking like this:
Code:
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
It looked like this:
Code:
X...X...
........
........
X...X...
........
Each 'X' is a neighbor of the nearest X.

This reduced the proccessing time enough to be faster than the old way, and it works perfectly without fail. I still have some minor polishing but hopefully the new version will be released tonight. It even works on toroidal!
 
Ok, it's up! Give it a try.

I changed the way bonus placement is done so that bonuses are placed individually instead of all of one type at once. This virtually eliminates the crowding problems when you increase the amount of resources placed. Also there's a variable now to increase bonuses called BonusBonus.
 
Do you think "betweeness centrality" can be used to make the actual AI understand choke points better?

In terms of a gameplay chokepoint, where there's only one square of passage, calculating the betweeness centrality is probably overkill. There are some cheaper ways to evaluate those kind of chokepoints.

I did those for tower placement on the Erebus.py mapscript for Fall from Heaven.
 
Ok, it's up! Give it a try.

I changed the way bonus placement is done so that bonuses are placed individually instead of all of one type at once. This virtually eliminates the crowding problems when you increase the amount of resources placed. Also there's a variable now to increase bonuses called BonusBonus.

Where is it? Is it the PerfectWorld.py download in your sig?

EDIT: Never mind, I got it. But I still want to know how to change the dimensions back to the 2:1 ratio.
 
In terms of a gameplay chokepoint, where there's only one square of passage, calculating the betweeness centrality is probably overkill. There are some cheaper ways to evaluate those kind of chokepoints.

I did those for tower placement on the Erebus.py mapscript for Fall from Heaven.

I was thinking more like "If we block these 4 here tiles with culture, other civs cannot expand down this here peninsula without open borders," or "We can make the most efficient use of our military at this 3-tile chokepoint and prevent a land advance into the rest of our territory."
 
Where is it? Is it the PerfectWorld.py download in your sig?

EDIT: Never mind, I got it. But I still want to know how to change the dimensions back to the 2:1 ratio.

Oh yeah, I promised detailed instructions. Set the mc.hmHeight and mc.hmWidth variables to multiples of 16 with a 2:1 ratio for your largest map size. Add +1 if the map does not wrap in that direction. By default the XWrap variable is False, so you want the x direction to be +1. My recommendation is 161:80. (16 * 10 + 1 = 161, and 16 * 5 = 80) The new wrapping settings will handle the needed +1 or -1 for flat and toroidal automatically.

Then change the entries in getGridSize function to a 2:1 ratio. Multiply these values by 4 to get the actual map dimensions. These can be anything you want except the largest one cannot be larger than hmHeight and hmWidth. (The heightmap only shrinks, it doesn't grow, so the final maps must be the same size or smaller)
 
I was thinking more like "If we block these 4 here tiles with culture, other civs cannot expand down this here peninsula without open borders," or "We can make the most efficient use of our military at this 3-tile chokepoint and prevent a land advance into the rest of our territory."

Yeah, I think as a pre-processing step you can quantify an areas importance in a traffic sense. The problem is that the algorithm I mentioned gets slow really fast. I was able to strip it down with a scant approximation, but that's because close counts with meteors kinda like with horse-shoes and hand grenades. Even so, you can see that it does add considerable processing time. (Sorry everyone!)

Fortunately, once the game starts the map usually doesn't change much, so you would only have to calculate it once.
 
simply awesome job on the new version. it's almost unbelievable how good it is :lol:

I did notice an oddity though, check attached screenshot. map is small size, break pangeas, cylindrical wrap. notice the straight line of desert very near to the south pole.

aside from that, toroidal works perfectly! having a strip of ice cut the map in two looks terrible though. Seven05 made the ice more likely to clump in the central section of the map in his ErebusContinent mapscript, and it looks great, you should check that out ;) it even changes the climate slightly near the pole, so that the central section of the map is colder ( snow ) , and it gets progressively hotter as you move to the left/right ( snow -> tundra ) . it looks really realistic, aside from the fact that there's only one pole instead of two of course :D

actually, this should probably work nicely even with cylindrical and flat wraps.

last thing: jungles seem kinda uncommon, increasing their number a little bit couldn't hurt. glider1's version had overdone that imho, but something between his and what we have now should work nicely.

THANK YOU! :goodjob:
 
[to_xp]Gekko;7931501 said:
last thing: jungles seem kinda uncommon, increasing their number a little bit couldn't hurt. glider1's version had overdone that imho, but something between his and what we have now should work nicely.

THANK YOU! :goodjob:

For the next version I'll introduce some erosion. The problem with jungle right now is that the land tends to leap out of the ocean where the high altitude is too cold to support jungle. There are almost no near sea level flatlands on most maps.
 
Wow, the results of this mapscript are astonishing! Good work cephalo.
What would be additionally nice is a numbergenerator in the main menu of Civ, so that i can input a number for this map and if it's a good map, i can use this map in different sizes etc. by just typing its number. I hope you know what i mean.
 
I didn't notice any errors in the PythonErr.log file in Vanilla.

I did notice this in PythonDbg.log:

Code:
No room at all found for BONUS_DRAMA!!!

No room at all found for BONUS_MUSIC!!!

No room at all found for BONUS_MOVIES!!!

That doesn't quite seem right, but I would like to have a map with bonus movies on it.
 
Creativity and imagination at work. Great stuff Cephalo! This proves to me that "nerdy" computer science is still an art form. And an excellent question by BobTheT about whether this algorithm could be used by the AI. I wish Cephalo could contribute to a better AI project. I'm sure Jdog and Yakk would enjoy it!!
Cheers.
 
Not to be a nag, Cephalo, but your instructions weren't really detailed enough.

Oh yeah, I promised detailed instructions. Set the mc.hmHeight and mc.hmWidth variables to multiples of 16 with a 2:1 ratio for your largest map size. Add +1 if the map does not wrap in that direction. By default the XWrap variable is False, so you want the x direction to be +1. My recommendation is 161:80. (16 * 10 + 1 = 161, and 16 * 5 = 80) The new wrapping settings will handle the needed +1 or -1 for flat and toroidal automatically.

I ctrl-f'd the script for mc.hmHeight and mc.hmWidth, but I can't find the place where they're defined with numerical values. I tried defining them in a place that I felt might work, but I ended up getting a total grassland map.

This was the section I changed.

Code:
        mc.hmWidth = newWidth
        mc.hmHeight = newHeight
        self.heightMap = newHeightMap

I don't know what line no. this is on, but you'll find where I'm talking about by ctrl-f'ing it. You don't even have to do the whole thing; the first line gives one result.

Anyway, I changed it to:

Code:
        #mc.hmWidth = newWidth
        #mc.hmHeight = newHeight
        mc.hmWidth = 161
        mc.hmHeight = 80
        self.heightMap = newHeightMap

Apparently, this was wrong.

Then change the entries in getGridSize function to a 2:1 ratio. Multiply these values by 4 to get the actual map dimensions. These can be anything you want except the largest one cannot be larger than hmHeight and hmWidth. (The heightmap only shrinks, it doesn't grow, so the final maps must be the same size or smaller)

Again, I'm not sure what you mean. Will it work if I change this

Code:
		WorldSizeTypes.WORLDSIZE_DUEL:		(12,8),
		WorldSizeTypes.WORLDSIZE_TINY:		(16,10),
		WorldSizeTypes.WORLDSIZE_SMALL:		(22,14),
		WorldSizeTypes.WORLDSIZE_STANDARD:	(26,16),
		WorldSizeTypes.WORLDSIZE_LARGE:		(32,20),
		WorldSizeTypes.WORLDSIZE_HUGE:		(36,24)

...to this?

Code:
		WorldSizeTypes.WORLDSIZE_DUEL:		(16,8),
		WorldSizeTypes.WORLDSIZE_TINY:		(20,10),
		WorldSizeTypes.WORLDSIZE_SMALL:		(28,14),
		WorldSizeTypes.WORLDSIZE_STANDARD:	(32,16),
		WorldSizeTypes.WORLDSIZE_LARGE:		(40,20),
		WorldSizeTypes.WORLDSIZE_HUGE:		(48,24)

I can't be sure this works at the moment because of the first step not working.
 
@Ramesses, the first set of lines you want to change is

Code:
#Height and Width of main climate and height maps. This does not
#reflect the resulting map size. Both dimensions( + 1 if wrapping in
#that dimension = False) must be evenly divisble by self.hmMaxGrain
self.hmWidth = 144
self.hmHeight = 97

So if you want a 2:1 aspect ratio, you could make these 192 and 97. Then your second set of changes would be appropriate.
 
@Ramesses, the first set of lines you want to change is

Code:
#Height and Width of main climate and height maps. This does not
#reflect the resulting map size. Both dimensions( + 1 if wrapping in
#that dimension = False) must be evenly divisble by self.hmMaxGrain
self.hmWidth = 144
self.hmHeight = 97

So if you want a 2:1 aspect ratio, you could make these 192 and 97. Then your second set of changes would be appropriate.

Well I tried doing 160 and 81 before, which should have been just as effective, but I don't believe that actually did anything. I do have several versions though, so it is possible I didn't have the right combination of changes. I'll check and see if this works.

EDIT: Hooray, it works. Thanks for your help.
 
Top Bottom