1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

[Map Script] PerfectWorld2.py

Discussion in 'Civ4 - Map Scripts' started by cephalo, Feb 17, 2009.

  1. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    damn it, nvm

    forgot a :
     
  2. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    My version of this mapscript (only starting position enhancement changed):
    PerfectWorld2f
     
  3. stagnate

    stagnate Warlord

    Joined:
    Sep 28, 2003
    Messages:
    274
    cephalo, do I understand correctly that you do all starting position placement in your code now?

    Since PW can leave pretty dramatic differences in starting positions, I thought that would be something good to expose as an option. Let the player choose whether to get the best or worst spot, and/or choose between a spot with good expansion vs a spot with a lot of bonus resources.

    The starting spot drives the style of play and difficulty, so it'd help to be able to tweak those knobs in addition to overall difficulty.

    Any thoughts?
     
  4. adiuvat

    adiuvat Chieftain

    Joined:
    Feb 21, 2010
    Messages:
    7
    Thanks for making this great map script. After playing with it a while, the only thing I really didn't like was the way resources tend to cluster. Some clustering is really good. Coming across a plain with 7 wine resources, representing ALL the wine on the map, not so good. So I put in a governer:

    Spoiler :
    def AddBonusType(self,eBonus,plotIndexList):
    gc = CyGlobalContext()
    gameMap = CyMap()
    featureForest = gc.getInfoTypeForString("FEATURE_FOREST")
    #first get bonus/area link
    for i in range(gc.getNumBonusInfos()):
    if self.bonusList.eBonus == eBonus:
    bonus = self.bonusList
    bonusInfo = gc.getBonusInfo(eBonus)

    print "AddBonusType for %(bt)s, cbc=%(cb)d dbc=%(db)d" % {"bt":bonusInfo.getType(), \
    "cb":bonus.currentBonusCount,"db":bonus.desiredBonusCount}

    if bonus.currentBonusCount >= bonus.desiredBonusCount:
    print "AddBonusType retfalse1 currentBonusCount=%(cb)d, desiredBonusCount=%(db)d" % {"cb":bonus.currentBonusCount,"db":bonus.desiredBonusCount}
    return False

    bonusPlaced = False
    #now add bonuses
    for i in range(len(plotIndexList)):
    index = plotIndexList
    plot = gameMap.plotByIndex(index)
    x = plot.getX()
    y = plot.getY()
    if self.CanPlaceBonusAt(plot,eBonus,False,False):


    print "AddBonusType:CanPlaceBonusAt for %(bt)s" % {"bt":bonusInfo.getType()}


    #temporarily remove any feature
    featureEnum = plot.getFeatureType()
    if featureEnum == featureForest:
    featureVariety = plot.getFeatureVariety()
    plot.setFeatureType(FeatureTypes.NO_FEATURE,-1)
    #place bonus
    plot.setBonusType(eBonus)
    bonusPlaced = True
    bonus.currentBonusCount += 1
    #restore the feature if possible
    if featureEnum == featureForest:
    if bonusInfo == None or bonusInfo.isFeature(featureEnum) or (bonusInfo.getTechReveal() != TechTypes.NO_TECH):
    plot.setFeatureType(featureEnum,featureVariety)
    groupRange = bonusInfo.getGroupRange()

    #NEW CODE
    #added/maxAdd: avoid grouping ALL the resources of a type together.
    #it's annoying to find 6 wines together and nowhere else on the map.
    added = 0
    maxAdd = PRand.randint(0,2);
    print "AddBonusType maxadd for %(bt)s = %(ma)d" % {"bt":bonusInfo.getType(),"ma":maxAdd}

    for dx in range(-groupRange,groupRange + 1):
    for dy in range(-groupRange,groupRange + 1):
    #NEW CODE
    if(added >= maxAdd):
    break
    if bonus.currentBonusCount < bonus.desiredBonusCount:
    loopPlot = self.plotXY(x,y,dx,dy)
    if loopPlot != None:
    if loopPlot.getX() == -1:
    raise ValueError, "plotXY returns invalid plots plot= %(x)d, %(y)d" % {"x":x,"y":y}
    if self.CanPlaceBonusAt(loopPlot,eBonus,False,False):
    if PRand.randint(0,99) < bonusInfo.getGroupRand():

    #NEW CODE
    added += 1
    #temporarily remove any feature
    featureEnum = loopPlot.getFeatureType()
    if featureEnum == featureForest:
    featureVariety = loopPlot.getFeatureVariety()
    loopPlot.setFeatureType(FeatureTypes.NO_FEATURE,-1)
    #place bonus
    loopPlot.setBonusType(eBonus)
    bonus.currentBonusCount += 1
    #restore the feature if possible
    if featureEnum == featureForest:
    if bonusInfo == None or bonusInfo.isFeature(featureEnum) or (bonusInfo.getTechReveal() != TechTypes.NO_TECH):
    loopPlot.setFeatureType(featureEnum,featureVariety)
    if bonusPlaced:
    break
    return bonusPlaced


    Since the forum killed off the indentations, I recommend going to the #NEW CODE sections and just writing in the new code yourself, if you want to try this out.. Enjoy!
     
  5. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    Actually the indentation is all there, you just need you wrap code tags around it if you want them to display on the forum.
    Anyway, thx for that, the insane clustering sometimes annoyed me too sometimes.
    But you are limiting placement by a random number from 0 to 2? I think 1-3 resources per cluster should be allowed, and what's the point of placing 0 resources anyway? (Or did I read something wrong there..)

    Spoiler :
    Code:
    def AddBonusType(self,eBonus,plotIndexList):
            gc = CyGlobalContext()
            gameMap = CyMap()
            featureForest = gc.getInfoTypeForString("FEATURE_FOREST")
            #first get bonus/area link
            for i in range(gc.getNumBonusInfos()):
                if self.bonusList[i].eBonus == eBonus:
                    bonus = self.bonusList[i]
            bonusInfo = gc.getBonusInfo(eBonus)
                    
            print "AddBonusType for %(bt)s, cbc=%(cb)d dbc=%(db)d" % {"bt":bonusInfo.getType(), \
            "cb":bonus.currentBonusCount,"db":bonus.desiredBonusCount}        
    
            if bonus.currentBonusCount >= bonus.desiredBonusCount:
                print "AddBonusType retfalse1 currentBonusCount=%(cb)d, desiredBonusCount=%(db)d" % {"cb":bonus.currentBonusCount,"db":bonus.desiredBonusCount}
                return False
    
            bonusPlaced = False
            #now add bonuses
            for i in range(len(plotIndexList)):
                index = plotIndexList[i]
                plot = gameMap.plotByIndex(index)
                x = plot.getX()
                y = plot.getY()
                if self.CanPlaceBonusAt(plot,eBonus,False,False):
                
                
                    print "AddBonusType:CanPlaceBonusAt for %(bt)s" % {"bt":bonusInfo.getType()}        
                
                
                    #temporarily remove any feature
                    featureEnum = plot.getFeatureType()
                    if featureEnum == featureForest:
                        featureVariety = plot.getFeatureVariety()
                        plot.setFeatureType(FeatureTypes.NO_FEATURE,-1)
                    #place bonus
                    plot.setBonusType(eBonus)
                    bonusPlaced = True
                    bonus.currentBonusCount += 1
                    #restore the feature if possible
                    if featureEnum == featureForest:
                        if bonusInfo == None or bonusInfo.isFeature(featureEnum) or (bonusInfo.getTechReveal() != TechTypes.NO_TECH):
                            plot.setFeatureType(featureEnum,featureVariety)
                    groupRange = bonusInfo.getGroupRange()
                    
                    #NEW CODE
                    #added/maxAdd: avoid grouping ALL the resources of a type together.
                    #it's annoying to find 6 wines together and nowhere else on the map.
                    added = 0
                    maxAdd = PRand.randint(0,2);
                    print "AddBonusType maxadd for %(bt)s = %(ma)d" % {"bt":bonusInfo.getType(),"ma":maxAdd}        
     
                    for dx in range(-groupRange,groupRange + 1):
                        for dy in range(-groupRange,groupRange + 1):
                           #NEW CODE
                            if(added >= maxAdd):
                                break
                            if bonus.currentBonusCount < bonus.desiredBonusCount:
                                loopPlot = self.plotXY(x,y,dx,dy)
                                if loopPlot != None:
                                    if loopPlot.getX() == -1:
                                        raise ValueError, "plotXY returns invalid plots plot= %(x)d, %(y)d" % {"x":x,"y":y}
                                    if self.CanPlaceBonusAt(loopPlot,eBonus,False,False):
                                        if PRand.randint(0,99) < bonusInfo.getGroupRand():
    
                                            #NEW CODE
                                            added += 1
                                            #temporarily remove any feature
                                            featureEnum = loopPlot.getFeatureType()
                                            if featureEnum == featureForest:
                                                featureVariety = loopPlot.getFeatureVariety()
                                                loopPlot.setFeatureType(FeatureTypes.NO_FEATURE,-1)
                                            #place bonus
                                            loopPlot.setBonusType(eBonus)
                                            bonus.currentBonusCount += 1
                                            #restore the feature if possible
                                            if featureEnum == featureForest:
                                                if bonusInfo == None or bonusInfo.isFeature(featureEnum) or (bonusInfo.getTechReveal() != TechTypes.NO_TECH):
                                                    loopPlot.setFeatureType(featureEnum,featureVariety)
                if bonusPlaced:
                    break
            return bonusPlaced
     
  6. adiuvat

    adiuvat Chieftain

    Joined:
    Feb 21, 2010
    Messages:
    7
    That's additional resources; the first is already placed. Basically I wanted no more than three together at a time. Easy enough to tweak that number if you want more. So far with that tweak I've been satisfied with every map.
     
  7. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    oh, additional .. perfect then, thank you very much. :D
     
  8. cephalo

    cephalo Deity

    Joined:
    Jul 26, 2007
    Messages:
    2,058
    Location:
    Missouri, USA
    Actually, clustering is supposed to happen for luxuries. I'm using the same algorithm as the default in this regard. The reason why you don't see it so much on the factory maps is that the terrain is kindof randomly splattered and not contiguous, preventing those resources from clustering like they're supposed to.

    This clustering is meant to promote trade rather than self sufficiency. You may not be used to it but I find that it makes for better gameplay. If you find a 'wine country' like you mentioned someone else is like to have the same thing for dye or silk. It's all good.
     
  9. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    Fact remains that resources simply don't cluster on stock maps the way they do on yours, all resources in a single area just doesn't happen. And we all know AIs underpreform everywhere that doesn't behave like standard, and of course human warmongers don't like it either.

    But you have a point, maybe increasing maxAdd to PRand.randint(1,(maxplayers+1)/2) is better, allowing clustering but not single-clusters for all resources of one type.
     
  10. cephalo

    cephalo Deity

    Joined:
    Jul 26, 2007
    Messages:
    2,058
    Location:
    Missouri, USA
    I have found that the AI knows very well what to do with extra luxury resources. I kept this in since the early days of PW1, and I love it. It's not that common to find everything in one cluster, but when you do, it's lot's of fun to find a nice jackpot once in a while. I think it's perfectly valid and only adds to the fun. I see no negative consequences.

    For strategic resources, players need to control their own so clustering is very bad. For luxuries, I think that allowing players to have monopolies is very historical and immersive.
     
  11. Fuyu

    Fuyu Emperor

    Joined:
    Nov 5, 2009
    Messages:
    1,225
    Location:
    Austria
    Then we agree to disagree. again
     
  12. adiuvat

    adiuvat Chieftain

    Joined:
    Feb 21, 2010
    Messages:
    7
    I like to play maps with ten or more civs, so having 2 or 3 civs control a resource is reasonable. When it comes to something like wine or gold, no one nationality of people had a lock on it in ancient times.. and there's still enough enforced scarcity with the governer I installed to make trading mandatory. YMMV.
     
  13. doctorfrog

    doctorfrog Chieftain

    Joined:
    May 28, 2009
    Messages:
    16
    I'm starting to play using this map script, and I'm looking forward to some of the uniqueness it has. Cephalo, do you intend to continue updating this script, or do you consider it to be finished? I'd really like to see some more in-game-gui generation options, and an easy way to toggle the resource sweetening that seems to be a little controversial (personally, I'm willing to try it, but on the outset, I don't like it).

    Also, if you explain within the comments portion of the script, and the script's description in the database, some of your philosophy regarding placement, massive deserts, and other questions that pop up repeatedly in this thread, you might not have to answer the same questions over and over, and maybe encourage a little more like-mindedness.

    But mainly, I hope you keep tweaking the script and maybe make modifying it that much easier for noobs. I've read the descriptions, and very few of them make sense to me. Maybe, if you're not willing/able to make these options tweakable in the game setup GUI, can you offer in the script comments suggestions for alternative settings, and their likely consequences? ie. "Set the following to 0.8 to reduce the number of trees to sparse, or to 0.9 if you want lots of trees. Default is 0.85."
     
  14. cephalo

    cephalo Deity

    Joined:
    Jul 26, 2007
    Messages:
    2,058
    Location:
    Missouri, USA
    I would say that trying to make a map script for all Civ-players is kindof like writing a song for all music-lovers. It's not likely to be succesful. Ulitmately, I think it's best for me to be true to my own sensibilities and make a map in the way that I think is ideal.

    I think that I will probably have at least one more version before Civ5 comes out, and I think it deserves to have a revamp of the comments portion. This map has gone through a great deal of evolution, and a few of the comments are just plain outdated. It get's more complicated when there are two or more variables that interact with each other. For example I think there are two variables that together control the amount of trees. Sometimes things end up alot more complicated than I intended.

    I agree with you that the comments are a mess right now, and I would hate to leave the last version in such a state.
     
  15. The Capo

    The Capo godless Heathen

    Joined:
    Jan 29, 2001
    Messages:
    9,302
    Location:
    Washington, DC
    If you make another version is there any way you could put an option in for the amount of islands? (i.e. no islands, few islands, some islands, islands, many islands etc.) Or their size (i.e. small, medium, large, small continents, mixed)? I think they sometimes add a new dimension to the game, and make naval superiority more important.

    EDIT: And to be clear, I mean islands as opposed to the continents. So there would be continents, but this function controls the islands.
     
  16. Tholal

    Tholal Emperor

    Joined:
    May 19, 2009
    Messages:
    1,676
    Just wanted to chime in and say this is my favorite mapscript. I don't mind the resource clusters, and I also agree that it seems more natural that way and encourages resource trading (something I rarely do on most maps because I usually already have one of everything).

    The only thing that sometimes bothers me is the propensity for most continents to have a large desert area in the center. I like the tactical and strategic impact it has on the game, but I wouldn't mind seeing it occasionally replaced with a massive plains area (ala the Great Plains in the US) or vast jungle (ala the Amazon). These would still have a similar impact on strategy, but it would also add a little more variety to the maps generated.
     
  17. The Capo

    The Capo godless Heathen

    Joined:
    Jan 29, 2001
    Messages:
    9,302
    Location:
    Washington, DC
    I agree on all counts (this is the only script I play with). I have seen large swaths of jungle, but as far as plains or foretsts (for example) I have to agree with Tholal.
     
  18. glider1

    glider1 Deity

    Joined:
    May 29, 2006
    Messages:
    2,870
    Location:
    Where animals hop not run
    me too :) Thanks Ceph.

    Cheers
     
  19. doctorfrog

    doctorfrog Chieftain

    Joined:
    May 28, 2009
    Messages:
    16
    I hope I'm coming across correctly: what I mean to say is that, like many, I kind of looked sideways at the maps that this script generated and liked them for their beauty, but kind of scratched my head as to how things were placed. It wasn't until I read your reasoning in this thread that I understood why things appeared the way they did. It really makes a lot of sense, and seems to compliment gameplay rather than break it. If you mention this is in the script description and/or readme file, others would grasp this right off as well.

    BTW, I also only play Noble, and can't get myself to play at AI-cheat difficulties. I'm happy as a clam that you seem to also play this way, since it means that the script has been tested according to the way I play, rather than how someone who has memorized the entire tech tree and has minmax strategies for all their favorite leaders plays. :crazyeye:

    I'm also glad that there'll be one more rev. This is a very interesting script that attempts to do some pretty impressive things, and I really like it. Kudos! :goodjob:
     
  20. Tascani

    Tascani Chieftain

    Joined:
    Feb 21, 2009
    Messages:
    31
    This mapscript is awesome.
    Firaxis should hire you Cephalo :D
     

Share This Page