[Map Script] PerfectWorld2.py

@Gekko
Will do this merge once I loose my first perfect world game to the AI which won't be long now :) This perfect world is very low on corn. This could make it difficult for corps that use corn. I'm not sure why exactly.....Could be just bad luck?
Cheers.
 
How can it be a perfect world without yellow kernels of deliciousness!? How!? HOW!?

But yeah, it does seem to be a bit low on corn.
 
I've merged glider's PerfectWorldDCM and Dr. S's tree mod. I have no idea if both of these are working correctly together, but I've generated a few maps and it works (tree options show up and work on the custom game screen, and it seems to take glider1's changes into account). I've never used python before, I just opened up winmerge and tried to get everything together. No code is my own, it's all cephalo's with glider1 and Dr s's enhancements.
 

Attachments

  • PerfectWorld2_ForestDCM.zip
    216.3 KB · Views: 173
Is there anywhere in the map script to modify the amount of resources placed on the map? I'd like to increase it.

In the bonus placer (search the script for BonusPlacer), i've found some ways to do that. None is very satisfying, but as I don't know how to code the functions needed, i have nothing else to propose.
First, you have to remove or decrease the limits of proximity for the bonuses, in def CanPlaceBonusAt, by comenting out these lines or changing their code (here's a modified version)
Code:
       #Make sure there are no bonuses of the same class (but a different type) nearby:
        if classInfo != None:
            if mc.BtS or mc.Warlords: #Ugh, annoying version difference
                iRange = classInfo.getUniqueRange()
            else:
                iRange = classInfo.getUniqueRange #<--attribute for vanilla
                
            for dx in range(-iRange,iRange+1):
                for dy in range(-iRange,iRange+1):
                    loopPlot = self.plotXY(x,y,dx,dy)
                    if loopPlot >= 1:
                        if areaID == loopPlot.getArea():
                            if plotDistance(x, y, loopPlot.getX(), loopPlot.getY()) <= 2:
                                eOtherBonus = loopPlot.getBonusType(TeamTypes.NO_TEAM)
                                if eOtherBonus != BonusTypes.NO_BONUS:
                                    if gc.getBonusInfo(eOtherBonus).getBonusClassType() == bonusInfo.getBonusClassType():
                                        return False
        #Make sure there are no bonuses of the same type nearby:
        iRange = bonusInfo.getUniqueRange()
        for dx in range(-iRange,iRange+1):
            for dy in range(-iRange,iRange+1):
                loopPlot = self.plotXY(x,y,dx,dy)
                if loopPlot >= 1:
                    if areaID == loopPlot.getArea():
                        if plotDistance(x, y, loopPlot.getX(), loopPlot.getY()) <= 2:
                            eOtherBonus = loopPlot.getBonusType(TeamTypes.NO_TEAM)
                            if eOtherBonus != BonusTypes.NO_BONUS:
                                if eOtherBonus == eBonus:
                                    return False
If you remove them, the bonuses will be placed in clusters.
Then, you can increase the number of bonuses in the functions
- def AddBonuses, by duplicating these lines
Code:
for order in range(numBonuses):
            for i in range(numBonuses):
                bonusInfo = gc.getBonusInfo(self.bonusList[i].eBonus)
                if bonusInfo.getPlacementOrder() == order:
                    self.AddBonusType(self.bonusList[i].eBonus)#Both unique and non-unique bonuses
- def CalculateNumBonusesToAdd, by changing the calcul of these lines (dividing by less than 100)
Code:
        players = game.countCivPlayersAlive() *bonusInfo.getPercentPerPlayer()/100
        bonusCount = baseCount * (landTiles + players)/100
        bonusCount = max(1,bonusCount)
This method is more precise than the other, but increase first the number of strategic and sea resources. Using the first and then reducing bonusCount, on the contrary, increase land food resources more than other types; but then as only some of the food resources are available on each continent, and as they are appearing in different areas (plains for wheat and cows, grasslands for pigs, rice and corn), increasing the number of food resources can produce inequalities between the different areas of a continent if it has, for example, only the grassland ones.

[edit] oh, I just found a way to obtain a more balanced map :
Spoiler :
 
can anyone who's comfortable with python confirm that BobtheTerrible's merge works exactly as it should? I had already done that merge myself since it looked easy and it does seem to work fine, but one never knows, you know :p
 
@Burned
Nicely balanced Burned!!!

@Gekk
Ok, lost this game against the AI on perfect world. Somehow I do not understand how to use all the trees properly in the early game. Now that I am disgraced having lost to the AI, I'll work on a new perfect world script over next few days. Most interesting will be Burn's discoveries on resource placement. I suspect that all I will do is up the corn a bit, so that the corporations that need it like Standard Ethanol, have a bit more of a go. It has to be a fine adjustment though. I'm thinking of comparing resource placement with the "tectonics" map, which seems to be the only BTS vanilla map that was updated in the last patch. I think it has dealt with resource placement for corporations a bit better, but not sure.

@Bob the Terrible
Thanks for the merging work Bob.

Cheers.
 
Another way to increase the number of food ressources is to disable the separation of different types between continents. Looks like the original script simply removes the bonuses of a type associated with another continent instead of replacing them with others.
I don't understand why, but the way to do that seems to be to change these lines in def PlotCanHaveBonus so that at one point at least the returned value is True instead of False
Code:
        if plot.isHills() == True:
            if bonusInfo.isHills() == False:
                return False
        if plot.isFlatlands() == True:
            if bonusInfo.isFlatlands() == False:
                return False
        if bonusInfo.isNoRiverSide() == True:
            if plot.isRiverSide() == True:
                return False
 
If you turn on logging, (which you can do by editing some lines at the end of CivilizationIV.ini), PerfectWorld will very kindly write out a bunch of info to the file PythonDbg.log and you can see what's going on with the bonuses. For example:

Trying to place 4 of BONUS_WHEAT
Successfully placed 4 of BONUS_WHEAT

Trying to place 8 of BONUS_RICE
Successfully placed 8 of BONUS_RICE

Trying to place 12 of BONUS_PIG
Successfully placed 12 of BONUS_PIG

Trying to place 4 of BONUS_DEER
Successfully placed 4 of BONUS_DEER

Trying to place 12 of BONUS_COW
Could not place 8 of BONUS_COW

Trying to place 11 of BONUS_SHEEP
Could not place 8 of BONUS_SHEEP

Trying to place 2 of BONUS_BANANA
Successfully placed 2 of BONUS_BANANA

Trying to place 13 of BONUS_CORN
Could not place 11 of BONUS_CORN

I don't think that willy-nilly increasing the bonuses or decreasing the spacing is the right way to fix up the bonus placement. What's going on with the corn is that when the corn is placed after the wheat/rice, there may be almost no place to put it. If the wheat bonuses (which there are not very many of) land on the largest land mass, then there won't be much room left for the corn (because PW respects the Civ rule that some types of bonuses should be on their own landmass). That's what happened with the map that corresponded to the log above---the wheat and rice were on the big land masses, so there was no place to put the corn except on one small island.

One way to moderate this would be to relax the one-bonus-per-type-per-landmass restriction as discussed above. You can do this by commenting out the following code:

Code:
#         if bIgnoreArea == False and bonusInfo.isOneArea() == True:
#             areaID = plot.getArea()
#             areaFound = False
#             for i in range(len(self.bonusList)):
#                 if self.bonusList[i].eBonus == eBonus:
#                     areaList = self.bonusList[i].areaList
#                     for n in range(len(areaList)):
#                         if areaList[n] == areaID:
#                             areaFound = True
#                             break
#                     if areaFound == True:
#                         break
#             if areaFound == False:
#                 return False

This has the disadvantage (or advantage, I guess, to some) of making the resource placement much more like the factory maps.

A better way to do it would be to assign discrete areas for different resources whose size was based on the number of resources, rather than doing it landmass by landmass. So corn, wheat, and rice wouldn't be intermixed, but some resources wouldn't get crowded out (almost) completely.
 
Unlike the stock routine, the order that the bonuses are placed should be randomized, so you should see maps where corn will dominate rice, rather than vice versa. Wheat doesn't really compete with the others. Most of the bonus code comes right from the SDK though, I only made minor modifications to it. The reason why you often see cows with sheep on the stock maps is because of the starting plot normalization routine just places random food.
 
cephalo, I don't understand your comment about the wheat. Are you saying that wheat and corn can (or should) coexist on the same landmass in your script? Because that doesn't seem to be my experience, and it seems in line from what I can grok from CIV4BonusInfos.xml. (But maybe my testing/observations are deficient.) In the map that was generated with that log file above (with only 2 out of 13 corn being placed), one large landmass had only wheat and one had only rice. Corn was relegated to one small island.
 
Wow a great script. Congrats! But I am having troubles when I play hotseat multiplayer games with my friends. All grasslands with some rivers. Singleplayer works perfectly.

I had the same issue when I played LAN game (it was with 4 human players, no IA).

Note: The original Perfectworld map works properly in LAN game.

Excellent job for single player, congratulations.

I hope you'll find a solution to make it work properly with multiplayer games, as it is the best map generator I've ever seen.
 
cephalo, I don't understand your comment about the wheat. Are you saying that wheat and corn can (or should) coexist on the same landmass in your script? Because that doesn't seem to be my experience, and it seems in line from what I can grok from CIV4BonusInfos.xml. (But maybe my testing/observations are deficient.) In the map that was generated with that log file above (with only 2 out of 13 corn being placed), one large landmass had only wheat and one had only rice. Corn was relegated to one small island.

Wheat and corn can coexist on the same continent if they have to, and since wheat appears on plains and corn on grass, they shouldn't get in each others way as much as rice and corn would. Each resource will generally pick the continent with the most left over space to place it. (actually I think I placed a penalty for same class resources on the same continent. I wrote this code more than a year ago, so my memory is a bit fuzzy.)

In the example you mention, it is possible that the corn was not able to be placed on it's chosen continent, but only on it's 'extra' island. Since it was placed however, it did not invoke the emergency placement code that will ignore the rules to place one.
 
What do you mean by "left over space"? I never see wheat and corn on the same continent. I've attached some screenshots of a map that has only three corns, all on small islands. On the main continent, wheat is the only grain, even though there seems to be plenty of grassland to place corn. This particular map failed to place 10 out of 13 corn.
 

Attachments

  • p1.jpg
    p1.jpg
    120 KB · Views: 361
  • p2.jpg
    p2.jpg
    155.2 KB · Views: 377
  • p3.jpg
    p3.jpg
    150.4 KB · Views: 332
What do you mean by "left over space"? I never see wheat and corn on the same continent. I've attached some screenshots of a map that has only three corns, all on small islands. On the main continent, wheat is the only grain, even though there seems to be plenty of grassland to place corn. This particular map failed to place 10 out of 13 corn.

Well, because of the spacing rules in the BonusClassInfo file, every time you place a wheat resource, you take up 10x10 plots where no other grain can be placed. So, it doesn't really take much to completely fill up a continent. I believe the number that it tries to place is based on the whole map, not just by continent. It's kindof a separate process that decides how much you are going to try to place, versus where you can actually place them when the time comes.

In the screen shots you showed me, you have a large continent, a smaller one, and then an even smaller Australia type continent. You've got wheat on the largest one and corn on the smallest, I imagine the middle one has rice? In this case, I would say that the smallest continent is probably the best place for the corn. I like it actually because it makes this smaller continent more desireable. Whoever takes the effort to settle here will get an extra grain type on a continent you could probably otherwise ignore.
 
Well, because of the spacing rules in the BonusClassInfo file, every time you place a wheat resource, you take up 10x10 plots where no other grain can be placed. So, it doesn't really take much to completely fill up a continent. I believe the number that it tries to place is based on the whole map, not just by continent. It's kindof a separate process that decides how much you are going to try to place, versus where you can actually place them when the time comes.

Right, but if you look at the screen shots, you'll see that it's not failing to place the corn because of any 10x10 region due to rice or wheat. There's not a single bonus grain tile in the entire middle screenshot. And if you look at the first screen shot, you'll see a large grassland area in the northeast with no grain. It's not placing the corn for some reason other than nearby grains. As far as I can tell from looking at maps, once you have wheat on a continent, you'll never have corn (unless placed by the emergency placer).
 
Right, but if you look at the screen shots, you'll see that it's not failing to place the corn because of any 10x10 region due to rice or wheat. There's not a single bonus grain tile in the entire middle screenshot. And if you look at the first screen shot, you'll see a large grassland area in the northeast with no grain. It's not placing the corn for some reason other than nearby grains. As far as I can tell from looking at maps, once you have wheat on a continent, you'll never have corn (unless placed by the emergency placer).

Yeah, There is actually a penalty involved in the continent choosing phase as well anytime there is a bArea resource in the same class already on the continent. That part is my doing. I really wanted same class resources separate, because back in the days before the penalty, I was seeing whole continents devoid of luxuries and other important resources, and I wanted every continent to have something unique to offer.

In the screenshots, if that small continent hadn't been there, it probably would have appeared on the main continent in the grassland area you mentioned. It can only choose one major continent however, and it chose the smaller one.

Why do you prefer that food bonuses be spread over the map evenly? In the case of grassland, you can get more out of it by placing a cottage than you can with developing a food bonus there, as long as you have access to one of a bonus, you really don't need more until corporations enter the picture, but then it doesn't matter what balance of bonuses you have only how many.
 
Top Bottom