Spawn system

Lets get in a bit of a systematic approach (and I will not implement further stuff in the spawn system until we have reached a consensus).

There are two parts to the spawn system:
One defines where each spawn rule might spawn something.
The other defines when it should spawn.

Currently for each plot from part one an independent check for part two is done.

There would also be the possibility to go top down. First evaluate chances to see what you want to spawn, then find a spawning plot.
Having both variants with each spawn rule selecting one is a possibility as well.
The chance calculation has many possibilities how it can be done as well (and currently it is entirely flat for each possible spawn plot).

So what would you actually want?
 
Right, but how would you apply it? If you just stop spawning in a given turn after <cap> is reached then only the plots considred first will get spawn chances, which just means all spawns will bunch up in whatever subset of plots is processed first. That's why you need 2 passes (or a non-geographically localized enumeration order possibly), so that you can evaluate the want-to-spawns in the first pass then actually spawn a culled set (by striping say) that is not biased to any particular enumeration order. It just makes it more complex (and slower) is all - the original system is simple and intended to be very efficiently implementable since it's an overhead on every turn.

I understand, however, it doesn't distribute evenly as is. On the several new games I started, when Neanderthals spawn from bonuses, they end up grouped in specific areas of the map only. So some Civs have to contend with them and the rest not at all.


Lets get in a bit of a systematic approach (and I will not implement further stuff in the spawn system until we have reached a consensus).

There are two parts to the spawn system:
One defines where each spawn rule might spawn something.
The other defines when it should spawn.

Currently for each plot from part one an independent check for part two is done.

There would also be the possibility to go top down. First evaluate chances to see what you want to spawn, then find a spawning plot.
Having both variants with each spawn rule selecting one is a possibility as well.
The chance calculation has many possibilities how it can be done as well (and currently it is entirely flat for each possible spawn plot).

So what would you actually want?

My goal is to create a more even distribution of Neanderthal spawns. We can leave animals out for now because there are different issues to consider. As I mentioned in my reply to Koshling, when the Neanderthals come out of bonuses, you always (in each game I started on Huge with a large land mass) get a case of Neanderthals being in certain areas of the map only.

With the new Terrain/Feature capability, I tested them spawning simply from "Forest." The distribution was great, but the total number was too much. Even when I set the current density value to 48. Granted, I was testing the extreme case, and I used a Wet map with Raging Barbarians. But if I can get that to feel right, the normal settings will fall in line.

From my understanding of the spawning, it sounds like the system starts from say the 0,0 coordinate and then works along the X or Y axis going through each tile systemically. With a limit, that is why it would create them on just one portion of the map, yes?

So it sounds like what we need is either more than one point of origination for checking (i.e. handle 4 quadrants at the same time) or generate a list of all tiles with forest and then randomly choose X number of those plots based on the number of spawns in the turn.
 
I understand, however, it doesn't distribute evenly as is. On the several new games I started, when Neanderthals spawn from bonuses, they end up grouped in specific areas of the map only. So some Civs have to contend with them and the rest not at all.




My goal is to create a more even distribution of Neanderthal spawns. We can leave animals out for now because there are different issues to consider. As I mentioned in my reply to Koshling, when the Neanderthals come out of bonuses, you always (in each game I started on Huge with a large land mass) get a case of Neanderthals being in certain areas of the map only.

With the new Terrain/Feature capability, I tested them spawning simply from "Forest." The distribution was great, but the total number was too much. Even when I set the current density value to 48. Granted, I was testing the extreme case, and I used a Wet map with Raging Barbarians. But if I can get that to feel right, the normal settings will fall in line.

From my understanding of the spawning, it sounds like the system starts from say the 0,0 coordinate and then works along the X or Y axis going through each tile systemically. With a limit, that is why it would create them on just one portion of the map, yes?

So it sounds like what we need is either more than one point of origination for checking (i.e. handle 4 quadrants at the same time) or generate a list of all tiles with forest and then randomly choose X number of those plots based on the number of spawns in the turn.

If the distribution is fine (with spawn from forest), but you're just getting too many why can't you just increase the iTurns values to lower the rate with the existing system?
 
If the distribution is fine (with spawn from forest), but you're just getting too many why can't you just increase the iTurns values to lower the rate with the existing system?

I plan to test that out tonight. I didn't know what it specifically meant until I read the forum reply from AIAndy this morning. I just wondered why a more intuitive value couldn't be used.

I was a programming hobbyist when I was younger (Basic & Pascal) and then studied for a year at the university. But the uni I went to used Ada :p and that turned me off to it. So I tend to think in those terms for the logic of these sorts of issues, but likely my thinking is a bit outdated compared to Python and C++.
 
I plan to test that out tonight. I didn't know what it specifically meant until I read the forum reply from AIAndy this morning. I just wondered why a more intuitive value couldn't be used.

I was a programming hobbyist when I was younger (Basic & Pascal) and then studied for a year at the university. But the uni I went to used Ada :p and that turned me off to it. So I tend to think in those terms for the logic of these sorts of issues, but likely my thinking is a bit outdated compared to Python and C++.

Programming is still programming, it is just the way you turn the mathematics into code. Programmers don't always make the right choice when exposing stuff to the people who are going to use it. The example in this case is using the name iTurns which is correct for the maths as is having decreasing numbers increase the chance. However it is not intuitive to those not familiar with the math. I have not thought of a better name.
 
Programming is still programming, it is just the way you turn the mathematics into code. Programmers don't always make the right choice when exposing stuff to the people who are going to use it. The example in this case is using the name iTurns which is correct for the maths as is having decreasing numbers increase the chance. However it is not intuitive to those not familiar with the math. I have not thought of a better name.

Naming of the tag is part of it, lack of Annotation / Inclusive Documentation within the XML file, is the other. If there were definitions of the tags included I could have figured it out on my own. Might be worthwhile to include that so anyone modifying the XML will know what those are all for.


What if you linked the Neanderthals to the land formations. We have polar, desert and rocky ones they should in theory spread the Neanderthals across the globe in each zone but not be nearly as numerous as linking them to forests. Since the land formations spawn much less.

I'll give that a try, Hydro. What is the nomenclature for the land formation feature? Is there is a list somewhere?
 
I'll give that a try, Hydro. What is the nomenclature for the land formation feature? Is there is a list somewhere?

Location: Assets/Modules/Resources/NewTerrainFeatures/Landforms

Arid Landforms (Generates in Scrub, Desert and Dunes)
FEATURE_ROCK_FORM1 (1 to 4)
FEATURE_ROCK_ARCH1 (1 to 2)

Rocky Landforms (Generates in Rocky and Barren)
FEATURE_DARK_ROCK_FORM1 (1 to 4)
FEATURE_DARK_ROCK_ARCH1 (1 to 2)

Polar Landforms (Generates in Tundra, Permafrost and Ice)
FEATURE_POLAR_ROCK_FORM1 (1 to 4)
FEATURE_POLAR_ROCK_ARCH1 (1 to 2)

Not sure if you want to use the FORM or the ARCH or both. Just know there are 18 individual ones and 6 of the 3 types.
 
Naming of the tag is part of it, lack of Annotation / Inclusive Documentation within the XML file, is the other. If there were definitions of the tags included I could have figured it out on my own. Might be worthwhile to include that so anyone modifying the XML will know what those are all for.

Doco here
 
Would this work, if i just put in a NEW file and have this? Or what else do i have to do to get it to work, and how?

Spoiler :
Code:
<CivilizationInfo>
			<Type>CIVILIZATION_HUN</Type>
			<Leader>LEADER_HUN_HORDE</Leader>
			<SpawnTech>TECH_CONSTRUCTION</SpawnTech>
			<NumberOfSpawnTech>2</NumberOfSpawnTech>
			<SpawnChance>75</SpawnChance>
			<IsBarbarianCiv>True</IsBarbarianCiv>
            <StartAtCoast>False</StartAtCoast>
            <TotalGold>25</TotalGold>
            <TechPercent>40</TechPercent>	
            <DefaultShips>NONE</DefaultShips>
            <NumberShipsPerCity>0</NumberShipsPerCity>
            <NumberOfCities>1</NumberOfCities>
            <StartX>-1</StartX>
            <StartY>-1</StartY>
            <NumWorkerPerCity>1</NumWorkerPerCity>
            <CapitalCityUnit>UNIT_ATTILA</CapitalCityUnit>
            <NumCapitalUnit>1</NumCapitalUnit>
			<DefaultCityDefender>UNIT_HORSE_ARCHER</DefaultCityDefender>	
            <NumberCityDefendersPerCity>3</NumberCityDefendersPerCity>
            <DefaultSecondUnit>UNIT_HORSEMAN<DefaultSecondUnit>
            <NumberSecondUnit>3</NumberSecondUnit>
		</CivilizationInfo>

Would this work?

Spoiler :
Code:
##SpawnCivUtil
###MODDER READ THIS:
###You do not have to change anything in this file (only if you changed default terrain)
###all changes have to be done in the CvEventManager.
###This file has to be in the same folder like the CvEventManager.py.

from CvPythonExtensions import *
import sys
import pickle
gc = CyGlobalContext()
SpawnCivList = []

def TriggerCiv(iPlayer,iTechType,DataPlotX,DataPlotY):
    PopList = []
    for i in xrange(len(SpawnCivList)):
        Spawned = SpawnACiv(SpawnCivList[i],i,iPlayer,iTechType)
        if Spawned:
            PopList.append(SpawnCivList[i])
    iMaxLoadCiv = len(SpawnCivList)
    bListSpawnedCiv = []
    for j in range(iMaxLoadCiv):
        bListSpawnedCiv.append(SpawnCivList[j].AlreadyTriggered)
    DataPlot = CyMap().plot(DataPlotX,DataPlotY)
    DataPlot.setScriptData(pickle.dumps(bListSpawnedCiv))

    ###obsolete
    #for i in xrange(len(PopList),0,1):
        #SpawnCivList.pop(PopList[i])
        
        
def SpawnACiv(SpawnCiv,ListNum,iPlayer,iTechType):
        ###Test if right tech###
        Tech = SpawnCiv.SpawnTech
        if not iTechType ==gc.getInfoTypeForString(Tech):
                return
        if SpawnCiv.AlreadyTriggered:
                return
        ###test, if right number of civs have tech
        TechCounter=0
        for i in xrange (gc.getMAX_CIV_TEAMS ()):
                Team = gc.getTeam(i)        
                if Team.isHasTech(iTechType):
                        TechCounter=TechCounter+1
                if TechCounter>=SpawnCiv.SpawnTechNumber:
                        break
                
        if not TechCounter>=SpawnCiv.SpawnTechNumber:                        
                return
        SpawningChance = CyGame().getSorenRandNum(100, "HowGoodIsTheChance")
        if SpawningChance>SpawnCiv.SpawnChance:
            SpawnCiv.AlreadyTriggered = True
            return
        ###test, if spawn civ is not already alive                
        for i in xrange (gc.getMAX_CIV_PLAYERS ()):
                pPlayer = gc.getPlayer(i)
                myName = pPlayer.getCivilizationType ()
                otherName = gc.getInfoTypeForString(SpawnCiv.CivString)
                if myName ==otherName:
                        return                
        ###Find a ID for the civ###
        NewID = -1
        for NumCiv in xrange (gc.getMAX_PLAYERS ()):
                PotPlayer = gc.getPlayer(NumCiv)
                if not PotPlayer.isAlive():
                        NewID = NumCiv
                        break
        if NewID ==-1:
                return                
        ###Add Civ to game
        iCiv = gc.getInfoTypeForString(SpawnCiv.CivString)                
        if not str(SpawnCiv.LeaderString)=="-1":
                NewLeaderID=gc.getInfoTypeForString(SpawnCiv.LeaderString)
        if str(SpawnCiv.LeaderString)=="-1":      
                       
            CurCiv = gc.getCivilizationInfo(iCiv)                        
            NumLeaders = CurCiv.getNumLeaders ()
            dice = gc.getGame().getMapRand()
            LeaderNum = dice.get(NumLeaders , "OracleSayMeTheLeader" )
            LeaderCounter=0
            for iLeaders in range(gc.getNumLeaderHeadInfos ()):
                if CurCiv.isLeaders(iLeaders):                    
                    if NumLeaders==1:
                        NewLeaderID =iLeaders
                        break
                    else:                        
                        if LeaderCounter==LeaderNum:
                            NewLeaderID=iLeaders
                            break
                        LeaderCounter=LeaderCounter+1
        CyGame().addPlayer(NewID,NewLeaderID,iCiv)
        NewPlayer = gc.getPlayer(NewID)
        NewTeam = gc.getTeam(NewPlayer.getTeam())
        NewTeamID = NewTeam.getID()

        ###from an old version, may be reactived later, you never
        ###now; declareWar is custom function in this file, not used
        ###at the moment
        ### function testIfBarb is current version
        #declareWar(NewID,SpawnCiv)
        #if SpawnCiv.bBarb==True:
                #MaxCivs = gc.getMAX_CIV_TEAMS()
                #for i in xrange (MaxCivs):
                    #if i==NewTeamID:continue
                    #NewTeam.setPermanentWarPeace(i,True)        
        maxX = CyMap().getGridWidth ()
        maxY = CyMap().getGridHeight ()
        iTundra = gc.getInfoTypeForString("TERRAIN_TUNDRA")
        iDesert = gc.getInfoTypeForString("TERRAIN_DESERT")
        iSnow = gc.getInfoTypeForString("TERRAIN_SNOW")
        NumSetCities = 0
        Counter=0
        NewPlayer.setGold(SpawnCiv.Gold)
        if SpawnCiv.SpawnX>-1 and SpawnCiv.SpawnY>-1:
            if SpawnCiv.SpawnX<CyMap().getGridWidth () and SpawnCiv.SpawnY<CyMap().getGridHeight ():
                pPlot = CyMap().plot(SpawnCiv.SpawnX,SpawnCiv.SpawnY)
                if not pPlot.isCity():
                    numUnits = pPlot.getNumUnits ()
                    for iUnits in xrange(numUnits):
                        pUnit = pPlot.getUnit(iUnits)
                        UnitX = pUnit.getX()
                        UnitY = pUnit.getY()
                        NewPlot = CyMap().plot(UnitX+1,UnitY+1)
                        if not NewPlot.isNone() and not NewPlot.isCity():
                            pUnit.setXY(UnitX+1,UnitY+1,True,True,True)
                        elif not CyMap().plot(UnitX-1,UnitY-1).isNone() and not CyMap().plot(UnitX-1,UnitY-1).isCity():
                            pUnit.setXY(UnitX-1,UnitY-1,True,True,True)
                        elif not CyMap().plot(UnitX+1,UnitY-1).isNone() and not CyMap().plot(UnitX+1,UnitY-1).isCity():
                            pUnit.setXY(UnitX+1,UnitY-1,True,True,True)
                        elif not CyMap().plot(UnitX-1,UnitY+1).isNone() and not CyMap().plot(UnitX-1,UnitY+1).isCity():
                            pUnit.setXY(UnitX-1,UnitY+1,True,True,True)                            
                            
                    NewPlayer.initCity(SpawnCiv.SpawnX,SpawnCiv.SpawnY)
                    NumSetCities = NumSetCities+1
                    AddTechToPlayer(iPlayer,NewID,SpawnCiv.TechPercent)
                    AddUnitsToCity(SpawnCiv.SpawnX,SpawnCiv.SpawnY,NewID,SpawnCiv)
                
        while NumSetCities <SpawnCiv.NumCities:
                EndangeredPlot = []
                CrapPlot = []
                SetCity = False
                Counter=Counter+1
                Endangered = False
                if Counter>100:return
                if Counter>SpawnCiv.NumCities:return
                for iX in xrange (maxX):
                        for iY in xrange(maxY):
                                pPlot = CyMap().plot(iX,iY)
                                if pPlot.isWater() or pPlot.isImpassable():
                                        continue
                                if pPlot.isOwned():
                                        continue
                                if pPlot.isUnit():
                                        continue                      
                                if SpawnCiv.bCoast:
                                        if not pPlot.isCoastalLand ():
                                                continue                                        
                                if (pPlot.getTerrainType ()==iDesert) or(pPlot.getTerrainType()==iSnow)or(pPlot.getTerrainType()==iTundra):
                                        CrapPlot.append([pPlot.getX(),pPlot.getY()])                                                
                                        continue
                                if pPlot.isAdjacentOwned ():
                                        continue                                
                                
                                IsCity = checkCity(iX,iY)
                                if IsCity:continue
                                for iXLoop in xrange(iX - 2, iX + 3, 1):
                                        for iYLoop in xrange(iY - 2, iY + 3, 1):
                                                TempPlot = CyMap().plot(iXLoop,iYLoop)                                                        
                                                if TempPlot.isOwned() or TempPlot.isUnit():
                                                        EndangeredPlot.append([pPlot.getX(),pPlot.getY()])
                                                        Endangered = True
                                                        break
                                if (Endangered == False):
                                        NewPlayer.initCity(iX,iY)
                                        NumSetCities = NumSetCities+1
                                        SetCity = True
                                        AddTechToPlayer(iPlayer,NewID,SpawnCiv.TechPercent)
                                        AddUnitsToCity(iX,iY,NewID,SpawnCiv)                                                
                                        break
                                
                if SetCity ==False:
                        if len(EndangeredPlot)>0:
                                iRandPlot = CyGame().getSorenRandNum(len(EndangeredPlot), 'EndangeredPlot')
                                RandPlot = EndangeredPlot[iRandPlot]
                                CityX=RandPlot[0]
                                CityY=RandPlot[1]
                                NewPlayer.initCity(CityX,CityY)
                                NumSetCities = NumSetCities+1
                                AddTechToPlayer(iPlayer,NewID,SpawnCiv.TechPercent)
                                AddUnitsToCity(CityX,CityY,NewID,SpawnCiv)                                        
                        elif len(CrapPlot)>0:
                                iRandPlot = CyGame().getSorenRandNum(len(CrapPlot), 'Crap Plot')
                                RandPlot = EndangeredPlot[iRandPlot]
                                CityX=RandPlot[0]
                                CityY=RandPlot[1]
                                NewPlayer.initCity(CityX,CityY)
                                NumSetCities = NumSetCities+1
                                AddTechToPlayer(iPlayer,NewID,SpawnCiv.TechPercent)
                                AddUnitsToCity(CityX,CityY,NewID,SpawnCiv)
        if SetCity == True:
                AddUnitsToCapital(NewID,SpawnCiv)
                SpawnCiv.AlreadyTriggered = True 
        return True

###function should be obsolete
###not used at the moment
### function testIfBarb is current version
def declareWar(iPlayer,SpawnCiv):
        if SpawnCiv.bBarb==True:
                NewPlayer = gc.getPlayer(iPlayer)
                TeamID = NewPlayer.getTeam()
                NewTeam = gc.getTeam(TeamID)
                for i in xrange(gc.getMAX_CIV_TEAMS ()):
                        if i==TeamID:continue
                        NewTeam.declareWar(i,False,WarPlanTypes.WARPLAN_TOTAL)
                        CurTeam = gc.getTeam(i)
                        CurTeam.declareWar(TeamID,False,WarPlanTypes.WARPLAN_TOTAL)
                for i in range(gc.getMAX_CIV_PLAYERS()):
                        if i==iPlayer:continue
                        NewPlayer.AI_setAttitudeExtra(i,-999)
                        CurPlayer = gc.getPlayer(i)
                        CurPlayer.AI_setAttitudeExtra(iPlayer,-999)

                                
                                        
def AddTechToPlayer(iPlayer,iNewPlayer,TechPercent):
        pPlayer = gc.getPlayer(iPlayer)
        pTeam = gc.getTeam(pPlayer.getTeam())
        NewPlayer = gc.getPlayer(iNewPlayer)
        NewTeam = gc.getTeam(NewPlayer.getTeam())
        TechPercent = float(TechPercent)/100
        TotalTechCounter=0
        GridWidth=0
        for i in xrange(gc.getNumTechInfos ()):
                if pTeam.isHasTech(i):
                    TotalTechCounter=TotalTechCounter+1
                    CurTech= gc.getTechInfo(i)
                    if CurTech.getGridX()>GridWidth:
                        GridWidth=CurTech.getGridX()
        TotalTechCounter=int(TotalTechCounter*TechPercent)
        TempTechCounter=0
        #CyInterface().addMessage(0,False,15,CyTranslator().getText(str(TotalTechCounter),()),'',0,'Art/Interface/Buttons/General/happy_person.dds',ColorTypes(44), 1, 1, True,True)
        for j in xrange(GridWidth):
                for i in xrange(gc.getNumTechInfos ()):
                        CurTech= gc.getTechInfo(i)                                       
                        if pTeam.isHasTech(i):
                            if CurTech.getGridX()==j:
                                NewTeam.setHasTech(i,True,iNewPlayer,False,False)
                                TempTechCounter=TempTechCounter+1
                                if TempTechCounter>=TotalTechCounter:
                                    break
                if TempTechCounter>=TotalTechCounter:
                        break
                                
                                
def AddUnitsToCapital(iNewID,SpawnCiv):
        pPlayer = gc.getPlayer(iNewID)
        Capital = pPlayer.getCapitalCity()
        iX = Capital.getX()
        iY = Capital.getY()
        if SpawnCiv.CapitalUnit !="NONE" and SpawnCiv.CapitalUnit !=-1:
            if SpawnCiv.NumberCapitalUnit>0:
                for i in xrange(SpawnCiv.NumberCapitalUnit):
                    pPlayer.initUnit( gc.getInfoTypeForString(SpawnCiv.CapitalUnit), iX,iY, UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION )        
    
def AddUnitsToCity(iX,iY,iNewPlayer,SpawnCiv):
        NewPlayer = gc.getPlayer(iNewPlayer)
        if SpawnCiv.NumWorker>0:
                for i in xrange(SpawnCiv.NumWorker):
                        NewPlayer.initUnit( gc.getInfoTypeForString("UNIT_WORKER"), iX,iY, UnitAITypes.UNITAI_WORKER, DirectionTypes.NO_DIRECTION )
        pCity = CyMap().plot(iX,iY).getPlotCity()
        if SpawnCiv.DefenderUnit !="NONE":
            if SpawnCiv.DefenderUnit=="-1":
                Defender = pCity.getConscriptUnit ()
            else:
                Defender = gc.getInfoTypeForString(SpawnCiv.DefenderUnit)
            if SpawnCiv.NumberDefenderUnit>0:
                for i in xrange(SpawnCiv.NumberDefenderUnit):
                    NewPlayer.initUnit( Defender, iX,iY, UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION )
        if SpawnCiv.SecondUnit !="NONE":
            if SpawnCiv.SecondUnit=="-1":
                Second = pCity.getConscriptUnit ()
            else:
                Second = gc.getInfoTypeForString(SpawnCiv.SecondUnit)
            if SpawnCiv.NumSecondUnit>0:
                for i in xrange(SpawnCiv.NumSecondUnit):
                    NewPlayer.initUnit( Second, iX,iY, UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION )                
        if pCity.isCoastal(20):
                if ((not SpawnCiv.Ships=="-1")and(not SpawnCiv.Ships=="NONE")) and (not SpawnCiv.NumberShips<1):
                        ThisShip = SpawnCiv.Ships
                        CurShip = gc.getInfoTypeForString(ThisShip)
                        NumShip = SpawnCiv.NumberShips                        
                        for i in xrange(NumShip):
                                NewPlayer.initUnit( CurShip, iX,iY, UnitAITypes.NO_UNITAI, DirectionTypes.NO_DIRECTION )
                                
                        
def checkCity(iX,iY):
        for iXLoop in xrange(iX - 2, iX + 3, 1):
                for iYLoop in xrange(iY - 2, iY + 3, 1):
                        TempPlot = CyMap().plot(iXLoop,iYLoop)
                        if TempPlot.isCity():return True
        return False
        
def ReadMyFile(MyFile,DataPlotX,DataPlotY):
        del SpawnCivList[:]
        for CurString in MyFile.readlines():        
                if "CIVILIZATION_" in CurString:
                        CurCiv = SpawningCiv()
                        CurCiv.CivString = CutString(CurString)
                elif "Leader" in CurString:
                        CurCiv.LeaderString = CutString(CurString)
                elif "TECH_" in CurString:
                        CurCiv.SpawnTech = CutString(CurString)
                elif "NumberOfSpawnTech" in CurString:
                        CurCiv.SpawnTechNumber = int(CutString(CurString))
                elif "SpawnChance" in CurString:
                        CurCiv.SpawnChance = float(CutString(CurString))
                elif "IsBarbarianCiv" in CurString:
                        CuttedString = CutString(CurString)                                
                        CurCiv.bBarb = bool(eval(CuttedString))
                elif "StartAtCoast" in CurString:
                        CuttedString = CutString(CurString)                               
                        CurCiv.bCoast = bool(eval(CuttedString))
                elif "TotalGold" in CurString:
                        CurCiv.Gold = int(CutString(CurString))
                elif "TechPercent" in CurString:
                        CurCiv.TechPercent =int(CutString(CurString))                        
                elif "DefaultShips" in CurString:
                        CurCiv.Ships = CutString(CurString)
                elif "NumberShipsPerCity" in CurString:
                        CurCiv.NumberShips = int(CutString(CurString))
                elif "NumberOfCities" in CurString:
                        CurCiv.NumCities = int(CutString(CurString))
                elif "StartX" in CurString:
                        CurCiv.SpawnX = int(CutString(CurString))
                elif "StartY" in CurString:
                        CurCiv.SpawnY = int(CutString(CurString))                        
                elif "NumWorkerPerCity" in CurString:
                        CurCiv.NumWorker = int(CutString(CurString))
                elif "CapitalCityUnit" in CurString:
                        CurCiv.CapitalUnit = CutString(CurString)
                elif "NumCapitalUnit" in CurString:
                        CurCiv.NumberCapitalUnit = int(CutString(CurString))                        
                elif "DefaultCityDefender" in CurString:
                        CurCiv.DefenderUnit = CutString(CurString)
                elif "NumberCityDefendersPerCity" in CurString:
                        CurCiv.NumberDefenderUnit = int(CutString(CurString))
                elif "DefaultSecondUnit" in CurString:
                        CurCiv.SecondUnit = CutString(CurString)
                elif "NumberSecondUnit" in CurString:
                        CurCiv.NumSecondUnit = int(CutString(CurString))
                        SpawnCivList.append(CurCiv)
        AddCivAlreadySpawnedInfo(SpawnCivList,DataPlotX,DataPlotY)
        
def AddCivAlreadySpawnedInfo(SpawnCivList,DataPlotX,DataPlotY):
        DataPlot = CyMap().plot(DataPlotX,DataPlotY)
        bListSpawnedCiv = pickle.loads(DataPlot.getScriptData ())
        iMaxLoadCiv = len(SpawnCivList)
        if len(bListSpawnedCiv)>0:
            for i in range (iMaxLoadCiv):
                SpawnCivList[i].AlreadyTriggered = bListSpawnedCiv[i]

def TestIfBarb(iTeamX,iHasMetTeamY):
        if iTeamX == iHasMetTeamY:
            return False
        TeamOne = gc.getTeam(iTeamX)
        TeamTwo = gc.getTeam(iHasMetTeamY)
        pPlayerOne = gc.getPlayer(TeamOne.getLeaderID())
        pPlayerTwo = gc.getPlayer(TeamTwo.getLeaderID())
        iLenSpawnCiv = len(SpawnCivList)
        for i in range(iLenSpawnCiv):
            if SpawnCivList[i].bBarb:
                if (gc.getInfoTypeForString(SpawnCivList[i].CivString)== pPlayerOne.getCivilizationType () ):                
                    TeamOne.declareWar(iHasMetTeamY,False,WarPlanTypes.WARPLAN_TOTAL)
                    TeamOne.setPermanentWarPeace(iHasMetTeamY,True)
                elif (gc.getInfoTypeForString(SpawnCivList[i].CivString)== pPlayerTwo.getCivilizationType () ):
                    TeamTwo.declareWar(iTeamX,False,WarPlanTypes.WARPLAN_TOTAL)
                    TeamTwo.setPermanentWarPeace(iTeamX,True)           
                                                                            
def CutString(string):
        string = str(string)        
        string = string.strip()        
        string = string[2:-1]
        BeginPos=-1
        EndPos = -1                
        for i in xrange(len(string)):
                if string[i]==">":
                        BeginPos=i                                
                elif string[i]=="<":
                        EndPos=i                                
                        break
        else:
                return "-1"
        NewString = string[BeginPos+1:EndPos]        
        return str(NewString)

class SpawningCiv:
        def __init__(self):
                self.CivString = 0
                self.LeaderString = 0
                self.SpawnTech = 0
                self.SpawnTechNumber = 0
                self.SpawnChance = 0
                self.bCoast = 0
                self.Ships = 0
                self.NumberShips = 0
                self.bBarb = 0
                self.NumCities = 0
                self.SpawnX = 0
                self.SpawnY = 0
                self.CapitalUnit = 0
                self.NumberCapitalUnit = 0                
                self.DefenderUnit = 0
                self.NumberDefenderUnit = 0
                self.NumWorker=0
                self.Gold = 0
                self.SecondUnit=0
                self.NumSecondUnit=0
                self.TechPercent=0
                self.AlreadyTriggered = False
 
@Koshling

This value in the spawn file:

rateOverrideDefineName - name of a global define value which can be used to adjust the spawn rate - it is a percentage and can be any value from 0 upwards (set to 100 in what I have pushed). Higher numbers imply more spawns, with 100 being the pure XML-defined rate - I put this in to give players an easy way to adjust the overall setting

Currently has a setting as follows:

<rateOverrideDefineName>NEANDERTHAL_SPAWN_MODIFIER</rateOverrideDefineName>

Would I just erase NEANDERTHAL_SPAWN_MODIFIER and put in a percent value? Or is this a variable defined elsewhere?
 
@Koshling

This value in the spawn file:



Currently has a setting as follows:



Would I just erase NEANDERTHAL_SPAWN_MODIFIER and put in a percent value? Or is this a variable defined elsewhere?

Don't use that to tune the mod. It's intended as an end-user override so people with different taste can tune everything up/down easily - it refers to a define in the global defines (its the name of the global define variable that contains the overriding value). The global defines are all in assets/xml/...GlobalDefines.xml
 
Don't use that to tune the mod. It's intended as an end-user override so people with different taste can tune everything up/down easily - it refers to a define in the global defines (its the name of the global define variable that contains the overriding value). The global defines are all in assets/xml/...GlobalDefines.xml

Ah. Gotcha. Thanks. :)
 
If the distribution is fine (with spawn from forest), but you're just getting too many why can't you just increase the iTurns values to lower the rate with the existing system?

Reporting back on this...

The Forest spawn in wave 1 was still too much with a fairly high iTurns setting. I've instead got it down to using some other Features, which are common, but not AS common as Forest. The two waves that follow change their spawning points to mix things up a bit.

In my test, 50% of the AI civs have survived 80% of the Neanderthal waves (on Raging), which is a whole lot better than it was before. However, expansion is at a complete halt since no one can leave their borders nor improve tiles around the capitals. :lol:
 
Reporting back on this...

The Forest spawn in wave 1 was still too much with a fairly high iTurns setting. I've instead got it down to using some other Features, which are common, but not AS common as Forest. The two waves that follow change their spawning points to mix things up a bit.

In my test, 50% of the AI civs have survived 80% of the Neanderthal waves (on Raging), which is a whole lot better than it was before. However, expansion is at a complete halt since no one can leave their borders nor improve tiles around the capitals. :lol:

YES< i just started a NEW game, with the CURRENT SVN, an this is happening, nobody is expanding, well hardly at all, i am at turn 500 and the largest civ has only 3 cities, something is terribly wrong here:sad::eek:
 
YES< i just started a NEW game, with the CURRENT SVN, an this is happening, nobody is expanding, well hardly at all, i am at turn 500 and the largest civ has only 3 cities, something is terribly wrong here:sad::eek:

I haven't pushed any Neanderthal spawn changes to the SVN. With the settings in there, a few Civs may get attacked by Neanderthals, the rest will likely be left alone.

But it takes awhile to move beyond Slingers and Clubmen, which is necessary to start being aggressive against Neanderthals. I was approaching year 6000 or so BC and still didn't have Stone Axemen or Spearmen (Marathon game). I don't think even Raging Barbs is meant to equal 4000 years of turtling in the cities.
 
I haven't pushed any Neanderthal spawn changes to the SVN. With the settings in there, a few Civs may get attacked by Neanderthals, the rest will likely be left alone.

But it takes awhile to move beyond Slingers and Clubmen, which is necessary to start being aggressive against Neanderthals. I was approaching year 6000 or so BC and still didn't have Stone Axemen or Spearmen (Marathon game). I don't think even Raging Barbs is meant to equal 4000 years of turtling in the cities.

I think the ADDITION of the Neanderthals, PLUS the spawning of the NEW animals system is causing this, my map was completely FULL of barbarian(s) each and almost every tile:eek::eek::sad: While i LIKE this, most wont, cause, they will just go and raid thier enemies and poof game over before you hit Medieval Era.
 
I think the ADDITION of the Neanderthals, PLUS the spawning of the NEW animals system is causing this, my map was completely FULL of barbarian(s) each and almost every tile:eek::eek::sad:

Regular barbarians are not spawned using the new system. Only Neanderthals and animals. If your map is full of (regular) barbs it must have some other cause (as far as I know no chnages have been made for regular barbs for many months)
 
Regular barbarians are not spawned using the new system. Only Neanderthals and animals. If your map is full of (regular) barbs it must have some other cause (as far as I know no changes have been made for regular barbs for many months)

Nope NOT regular barb, infact i dont see any of them, but maybe 10 and i am at turn 500. Bad use of words i guess, i was referring to Neanderthals and Animals, sorry.
 
Top Bottom