Dynamic starts development thread

jmerry

Warlord
Joined
Jan 21, 2010
Messages
122
Latest alpha version in post #18

The idea of this modmod is to have civs spawn with map and tech knowledge drawn from their neighbors; this will prevent silly things like America being many techs ahead of everyone at spawn.

Previous discussion, moved from another thread:
Yeah, I was also thinking Python only. :king:

I've started working on functions you could use. This is what I have so far:
Spoiler :
Code:
### dynamic starts within RiseAndFall.py ###

##        def getAreaCivs(self, TL, BR, lExceptions, bMajorOnly, bAIOnly):

##        def makeTechList(self, iCiv, bTraded):

##        def copyTechs(self, iCiv, tTechList, iNumHits, bHuman):

##        def copyWorldMap(self, iReceiver, lProviders, iNumHits, bHuman):
custom.getAreaCivs() returns a list of all the Civs with cities present inside an predefined area. You can use any of the Core/Normal/Broader Areas or any other area, and it also handles exceptions (used to define Core/Normal area).

custom.makeTechList() returns a list containing all the Techs owned by iCiv. I'll look into making it possible to except traded Techs (as Tech brokering isn't allowed in RFC) with bTraded.

custom.copyTechs() takes a tuple list containing several merged Tech lists (above function) as an argument with a target value to determine what Techs iReceiver should get.

custom.copyWorldMap() takes a list of Civs and a target value to determine which map plots should be revealed to iReceiver.


Other functions I'm working on at the moment include:
Spoiler :
Code:
        def foundCity(self, lCity, name, iPopulation, bForce, iCityCulture, iCulture, iUnitType, iNumUnits, iReligion, lBuildings):

        def flipCity(self, tCityPlot, iNewOwner, bOnlyAI, iOldOwner, bAIOnly, bMinorsOnly, bConquest, bKillUnits, iNumGarrison, bConscript):

        def createGarrison(self, iCiv, bHuman, tCityPlot, iNumUnits, bConscript):

        def setBuildings(self, tCityPlot, lBuildings):

        def setGlobalBuilding(self, iCiv, iBuilding):
Any other suggestions are also welcome! :king:
The structure I'd go with:
For techs, three functions in RiseAndFall:
assignNormalTechs(self, iCiv, b600AD)
assignMinimalTechs(self, iCiv, b600AD)
shareTechs(self, iCiv, lNeighbors)
Don't mess with the bTraded flag for the spawn techs; that could create weird prerequisite holes, and drive the world further behind. Since the lists aren't that long, the number known to allow sharing with the new civ should keep to two.

For testing purposes, the human will get techs and maps just like the AI. After all, taking a snapshot at spawn is a very nice way to see what's happening. Final version- well, we'll see.

Oh, and I'm writing code already. I have mucked around quite a bit already and picked up a lot of knowledge.

The neighbor list for this purpose will include dead civs; they still have techs even though they've lost. I'll stick to the standard lists for the most part; just add Arabia to Turkey's list and build a new one for America. The list I'd go with is: any Old World civ with a current city in North or Central America (American victory condition area), the neighbors of those civs, the Aztecs, and the Maya.
 
Isn't it the idea of RFC that some civs start with less techs then others? For example the Khmer start with less techs than china... what about Mali... and the Azteks often have less techs than the mayan...
The defined number of techs at the spawn is important for realism, too, isn't? Like that, the Romans are more likely to found Christianity than the Persians or Carthago.
 
The Khmer will still likely be behind China- they'll just know techs if both China and India know them. (actually, two of three out of China, India, and Japan). Mali? Have you seen their neighbor list? If Carthage and Egypt are already collapsed, there's only Ethiopia to be moderately advanced- which is why I'll likely help them out and add Arabia. Aztecs? Since they only have one neighbor, their start is unchanged.
I'm more worried about civs starting weaker than in the normal game than anything else.

Coding stuff:
Spoiler :

OK, here's my skeleton for the techs and maps:
Intercepting the assignTechs calls:
Code:
	def assignTechs(self, iCiv):
		b600AD = not gc.getPlayer(0).isPlayable()
		bDynamicStart = True //Replace with option later
		if (bDynamicStart):
			self.assignMinimalTechs(iCiv, b600AD)
			lNeighbours = []
			if (iCiv <= iAmerica): //Do American list later. Minors and barbarians get no neighbours
				lNeighbours = con.lNeighbours[iCiv]
			if (iCiv == iTurkey or iCiv == iMali):
				lNeighbours.append(iArabia)
			self.shareTechs(iCiv, lNeighbours)
			self.shareMap(iCiv, lNeighbours)
		else:
			self.assignNormalTechs(iCiv, b600AD)
Replace the assign600ADTechs call with calls to assignTechs for each affected civ (China, Japan, Vikings, Arabia, Ind. 1, Ind. 2, Native, Byzantium). This is done at the beginning of a 600 AD game; no effect on 3000 BC starts.

assignNormalTechs uses the normal list, testing for 600 AD when applicable. assignMinimalTechs is a pruned list, still being built.
shareTechs will give any tech known by two or more neighbours, while shareMap will reveal any map titles known by two or more neighbours.

For the map-based functions, utils.squareSearch looks like a promising base- build a list of plots satisfying some requirement in a rectangle.
 
Well, I've got something that runs; in a test game I just tried, Persia spawned with some map knowledge in Anatolia, the eastern Mediterranean, and the Sinai (India obviously didn't bother exploring westward), as well as techs The Wheel, Agriculture, Hunting, Mysticism, Mining, Pottery, Animal Husbandry, Archery, Polytheism, Masonry, Priesthood, Monotheism, and Bronze Working.
Compared to the normal list, it's up Agriculture and down Fishing, Sailing, Monarchy, and Horseback Riding. Compared to the neighbors, it's exactly even with Babylon; India is up Meditation and down some stuff, Greece is up Writing, Fishing, Sailing, and Metal Casting in exchange for Archery and Priesthood.

Further development depends on getting more of the minimal tech lists done. Enough for today.
 
Oh, I missed this thread entirely. Its good to see that this is becoming reality, so I'll just let you have a go at it then. I'll definitely be using the finished modmod. And using your custom functions as well for my own scenarios and whatnot. :king:

I was actually gonna start making some custom functions for you but you seem to be ok on your own... :goodjob: Just holler if you need any help or anything.

As for the balancing issues and such, I think you're absolutely right about technological research being slower with these dynamic starts. Because the new Techs known to spawning Civs is, in some sense, the motor that drives progress in RFC.

You've actually already hinted at the solution - faster research rates overall. (In my own mod I'm already tinkering with that, but mostly giving larger discounts for known Techs. This would make it easier to catch up, but harder to be the Tech leader. So this could also be a way forward.)
 
Yeah- there aren't really very many hooks for getting at tech costs. Discounts for known techs is just one value in the XML, and that's an obvious adjustment to make. Other than that? Game speed. If I implement the option as a game speed, I can have a different global research rate depending on whether dynamic starts are on.
The thing is, anything global like that completely scrambles the difficulty of the Mayan UHV. Oops.

[Added in edit]
Ah, I found the formula for the "other civs know" discount. Add (XML value)*(number of living civilizations you know that have it)/(number of civilizations in the game) percent, multiplicative with all other bonuses. RFC has 32 civs in the scenario, while the number of contacts you have can be quite small. Unmodified, that means you're getting about 1% per neighbor that knows something, which is completely insignificant.
I think I'll bump that one up from 30 to 300. It'd have to be over 100 to have even as much impact as in a normal game, and the spirit here calls for a strong boost to catching up.
 
Ah, I found the formula for the "other civs know" discount. Add (XML value)*(number of living civilizations you know that have it)/(number of civilizations in the game) percent, multiplicative with all other bonuses. RFC has 32 civs in the scenario, while the number of contacts you have can be quite small. Unmodified, that means you're getting about 1% per neighbor that knows something, which is completely insignificant.
I think I'll bump that one up from 30 to 300. It'd have to be over 100 to have even as much impact as in a normal game, and the spirit here calls for a strong boost to catching up.
Oh, this is very useful for me also! Thanks! :goodjob:
 
I turned the dynamic starts off and ran some autoplays to America, to see what things look like with only the changed known tech discount.
On the first run, England went crazy colonizing, with 7 cities in North America and the Caribbean. Japan conquered the Inca, and China was the monster, in the process of building the Statue of Liberty, Wembley, and the Kremlin.
On the second run, France had 5 cites in North America and the Caribbean, England had 2 in Canada and 2 in South America, Portugal had 2 in Brazil and 2 in West Africa, Japan conquered Oaxaca, and Holland had a city in South Africa. China (collapsed), Japan, Maya (collapsed), Khmer, France, England, Holland, and Turkey all had Astronomy. Awesome - I've never seen multiple colonial powers to that extent before.

That change is definitely in. I'm working on the lists for playable dynamic starts right now.
 
Alpha version available for playtesting!

Make the following changes:
1. In Civ4GlobalDefines.xml, set TECH_COST_TOTAL_KNOWN_TEAM_MODIFIER to 320 rather than 30 (that's an even 10% bonus to your research for each other civ you have contact with that knows that tech). A copy of that file is attached.
2. In RiseAndFall.py, replace the functions assignTechs and assign600ADTechs as follows:
Code:
	def assignTechs(self, iCiv):
		b600AD = not gc.getPlayer(0).isPlayable()
		bDynamicStart = True
		if (bDynamicStart):
			custom.assignMinimalTechs(iCiv, b600AD)
			lNeighbours = []
			if (iCiv < iAmerica):
				lNeighbours = con.lNeighbours[iCiv]
			if (iCiv == iGermany or iCiv == iRussia):
				lNeighbours.append(iGreece)
			if (iCiv == iTurkey or iCiv == iMali):
				lNeighbours.append(iArabia)
			if (iCiv == iAztecs):
				lNeighbours = [iMaya, iInca] #List shouldn't include Spain.
			if (iCiv == iAmerica):
				lNeighbours = custom.getAmericanNeighbours()
			custom.shareTechs(iCiv, lNeighbours, 2)
			custom.shareMap(iCiv, lNeighbours, 2)
		else:
			custom.assignNormalTechs(iCiv, b600AD)
		if (iCiv < con.iNumMajorPlayers):
			self.hitNeighboursStability(iCiv)
and
Code:
	def assign600ADTechs(self): #Assigns starting techs for already spawned civs at 600 AD start
		self.assignTechs(iChina)
		self.assignTechs(iJapan)
		self.assignTechs(iIndependent)
		self.assignTechs(iIndependent2)
		self.assignTechs(iNative)
		self.assignTechs(iCeltia)
Also, include the line
Code:
import Custom
in the preamble and
Code:
custom = Custom.Custom()
among the constants.
I'm not attaching a file for this one, because I'm working with 1.185 as a base and RiseAndFall has changed since then (Persia's spawn, at least).
3. Include the attached Custom.py file, which has the functions called in the preceding. The lists of techs have been moved from their original place in assignTechs and assign600ADTechs to here.

Initial testing is in progress, as I wait for an autoplay to America to play out.

[Edit - Typos (iAztec for iAztecs) found and fixed. Custom.py file updated]
[Edit again - another update. North American neighbors should work now.]
[Last edit - Directions now include the import line.]
 

Attachments

Well, that first run is complete. A bit of a dud for the Americans, as no Europeans had founded anything in the Americas yet. France's first settler galleon was on the way, at least.

[Added in edit]
Final playtest run of the night: England founded New York, Japan conquered the Inca and vassalized the Aztecs, and America knew Sci. Method but not Rifling or Chemistry on spawn. The religion situation is interesting, with no holy city for Judaism (probably Bablyon, razed) or Christianity, Confucianism in Istanbul, and Taoism completely nonexistent.
Oh, and because this needs a teaser of what the new functions can do, the minimap looks like this:
 

Attachments

  • 1775 minimap.jpg
    1775 minimap.jpg
    56.5 KB · Views: 128
I think you forgot to give the instructions about the definition of 'custom' :)
 
Looking good! :goodjob: I'm anticipating the final release. :king: I can't help out with any testing right at this moment, but I'm looking forward to more reports on actual play. Could someone please give this a proper test run?

As your code deals specifically with the dynamic starts, maybe you could call the module DynamicStarts.py or something instead? Because I was thinking about releasing e a set of custom functions for scenario makers in the form av a file called Custom.py, and people might wanna use both... (I know I will.) But I guess I could always rename my own as CustomUtils.py or something (abbreviates to what?)... Or maybe BaldyrUtils.py? :lol:
 
I think you forgot to give the instructions about the definition of 'custom'
Indeed I did- and then I fixed that 30 minutes before your post.

maybe you could call the module...
I've renamed it to DynamicStarts, abbreviated to dyn. That change will be reflected the next time I upload something. Of course, you're free to rename yours as well...

What still needs to be done? I want to make this into a game option, selectable at start. I have no idea how to code that. Other than that, the minimal lists may need to be tweaked.
Current minimal tech lists:
Spoiler :
China: Same as normal lists.
Babylon, India, Egypt: Empty, same as normal lists.
Greece: Same as normal list.
Persia: Mining, Bronze, Mysticism, Wheel, Hunting, Archery, AH.
Carthage: Mining, Bronze, Fishing, Sailing, Wheel, Hunting, AH, HBR.
Rome: Mining, Bronze, Iron, Masonry, Fishing, Sailing, Wheel, Pottery, Writing, Hunting.
Japan: Same as normal lists.
Ethiopia: Same as normal list.
Maya: Same as normal list.
Vikings: Same as normal lists.
Arabia: Mining, Bronze, MC, Machinery, Mysticism, Polytheism, Masonry, Priesthood, Theology, Monarchy, DvR, Fishing, Wheel, Pottery, Writing, Feudalism, Guilds, Hunting, Archery, AH, HBR. Same as normal list for 600 AD start.
Khmer: Mysticism, Masonry, Meditation, Priesthood, Fishing, Wheel, Agriculture, Writing, Math, Construction, Hunting, Archery, AH, HBR. Same as normal list for 600 AD start.
Spain, France, England, Germany, Russia: Mining, Bronze, Iron, Mysticism, Polytheism, Priesthood, Monarchy, Fishing, Sailing, Wheel, Pottery, Agriculture, Writing, Feudalism, Hunting, Archery, AH, HBR. Same as normal list for 600 AD start.
Holland, Portugal: Mining, Bronze, Iron, MC, Machinery, Mysticism, Polytheism, Masonry, Priesthood, Monarchy, Fishing, Sailing, Wheel, Pottery, Agriculture, Writing, Feudalism, Math, Construction, Engineering, Hunting, Archery, AH, HBR.
Mali: Mining, Bronze, Mysticism, Polytheism, Masonry, Monotheism, Theology, Monarchy, DvR, Wheel, Pottery, Writing, Alphabet, Currency, Hunting, Archery, AH, HBR. Same as normal list for 600 AD start.
Inca: Same as normal list.
Mongolia: Mining, Bronze, Iron, MC, Machinery, Mysticism, Polytheism, Meditation, Priesthood, Masonry, Monarchy, Fishing, Wheel, Pottery, Agriculture, Writing, Feudalism, Guilds, Hunting, Archery, AH, HBR.
Aztecs: Mining, Bronze, Mysticism, Polytheism, Masonry, Priesthood, Fishing, Wheel, Pottery, Agriculture, Writing, Mathematics, Calendar, Hunting, Archery.
Turkey: Mining, Bronze, Iron, MC, Machinery, Mysticism, Polytheism, Masonry, Priesthood, Monarchy, Fishing, Sailing, Wheel, Pottery, Agriculture, Writing, Feudalism, Guilds, Gunpowder, Math, Construction, Engineering, Hunting, Archery, AH, HBR.
America: Mysticism, Meditation, Polytheism, Priesthood, Monotheism, Monarchy, CoL, Feudalism, CivS, Guilds, Constitution, Democracy, Fishing, Wheel, Agriculture, Pottery, Sailing, Writing, Math, Alphabet, Calendar, Currency, Philosophy, Paper, Education, Printing, Astronomy, Hunting, Mining, Archery, Masonry, AH, Bronze, Iron, MC, Compass, Machinery, Optics, Gunpowder.

One interesting feature: the tech Europe starts with depends on the older civs in the Mediterranean. If Carthage is crippled early, Spain starts weak. If Rome is crippled early, Spain, France, and England are weakened. If Greece is also crippled, Germany and Russia suffer.
 
One interesting feature: the tech Europe starts with depends on the older civs in the Mediterranean. If Carthage is crippled early, Spain starts weak. If Rome is crippled early, Spain, France, and England are weakened. If Greece is also crippled, Germany and Russia suffer.
This is pretty much the point of the whole exercise, right? :D If there never is a Hellenistic World, the Romans should also have less opportunities for domination. And with no Roman Empire there would be no Frankish or Holy Roman Empire, as we know them.

What about the AD 600 start, then? Because that one assumes that the Classical World is no more. Or do they automatically start off strong because the Classical World is assumed to have reached its pinnacle? Is Byzantium counted in as a neighbor, by the way? Their Tech lever should influence the Arabian and the European Tech levels also, as they are the protectors of the Ancient Lore.

Other than that, its only realistic if the medieval Civs start off less advanced than the Classical forerunners. Do the later European Civs get pretty much all Techs known to the Classical World?
 
Because of the 2-civ threshold, you'll only get less advanced civs if there's one clear tech leader. If Rome is very strong but gives Carthage all of its tech, that will cascade through to all of the Europeans in turn. In a more normal situation, the European civs will get everything that both the Romans and the Vikings know.
The later European civs get the military techs up to Engineering, but the rest depends on their neighbors.

In the 600 AD scenario, everyone that spawns in the first 30 turns has the same techs as in the standard scenario. It's equivalent to having a fairly advanced classical world, already dead. The Byzantines aren't in anybody's neighbor list, and my current tech sharing function would exclude them at the playable check. Still... OK, new version coming.

Installation instructions:
Spoiler :
1. In Civ4GlobalDefines.xml, set TECH_COST_TOTAL_KNOWN_TEAM_MODIFIER to 320 rather than 30 (that's an even 10% bonus to your research for each other civ you have contact with that knows that tech).
2. In RiseAndFall.py, replace the functions assignTechs and assign600ADTechs as follows:
Code:
	def assignTechs(self, iCiv):
		b600AD = not gc.getPlayer(0).isPlayable()
		bDynamicStart = True
		if (bDynamicStart):
			dyn.assignMinimalTechs(iCiv, b600AD)
			lNeighbours = []
			if (iCiv < iAmerica):
				lNeighbours = con.lNeighbours[iCiv]
			if (iCiv == iGermany or iCiv == iRussia):
				lNeighbours.append(iGreece)
			if (b600AD and (iCiv == iArabia or iCiv == iTurkey or iCiv == iGermany or iCiv == iRussia)):
				lNeighbours.append(iCeltia) #Byzantium
			if (iCiv == iTurkey or iCiv == iMali):
				lNeighbours.append(iArabia)
			if (iCiv == iAztecs):
				lNeighbours = [iMaya, iInca] #List shouldn't include Spain.
			if (iCiv == iAmerica):
				lNeighbours = dyn.getAmericanNeighbours()
			dyn.shareTechs(iCiv, lNeighbours, 2)
			dyn.shareMap(iCiv, lNeighbours, 2)
		else:
			dyn.assignNormalTechs(iCiv, b600AD)
		if (iCiv < con.iNumMajorPlayers):
			self.hitNeighboursStability(iCiv)
and
Code:
	def assign600ADTechs(self): #Assigns starting techs for already spawned civs at 600 AD start
		self.assignTechs(iChina)
		self.assignTechs(iJapan)
		self.assignTechs(iIndependent)
		self.assignTechs(iIndependent2)
		self.assignTechs(iNative)
		self.assignTechs(iCeltia)
Also, include the line
Code:
import DynamicStarts
in the preamble and
Code:
dyn = DynamicStarts.DynamicStarts()
among the constants.
3. Include the attached DynamicStarts.py file.


Update: I just noticed that there were changes to starting techs in 1.186 in the changelog. These have been incorporated, so DynamicStarts.py is effectively updated to Rhye's 1.186.
Update 2: Fixed a bug. Spawns should now work fully.
 

Attachments

Yet another new version here. I've added the ability to distinguish between techs on the normal list and techs outside it; a civ spawns with a tech if it's on their minimal list, if it's on their normal list and one neighbor has it, or if two or more neighbors have it. For example, Persia will get Monarchy if Babylon researches it, as just happened in my test game. Previously, they would have needed both Babylon and Greece to research it, which is pretty much impossible. This change should bring average tech levels up closer to where they are in the normal game.

Of course, I made some other changes to compensate. Mali no longer gets to copy Arabia's techs, and the Vikings draw techs (but not map info) from the Mediterranean powers. This gives a chance for all of Europe to be stunted if Rome and Carthage fall apart early. In the 600 AD scenario, Spain counts Byzantium as a neighbor... which conveniently gives them exactly their normal list, once I give Byzantium Machinery and remove Engineering. (Not facing Byzantine Pikemen should also make life easier for the Arabs, although they probably deserve to get their "at war" bonus units as well.)

Behind the scenes, the tech data has been moved out of the body of the functions and into constant lists. Functions have also been renamed.

Installation instructions:
Spoiler :
1. In Civ4GlobalDefines.xml, set TECH_COST_TOTAL_KNOWN_TEAM_MODIFIER to 320 rather than 30 (that's an even 10% bonus to your research for each other civ you have contact with that knows that tech). This is no longer essential due to this version's changes, and I'll consider lowering that value.
2. In RiseAndFall.py, replace the functions assignTechs and assign600ADTechs as follows:
Code:
	def assignTechs(self, iCiv):
		b600AD = not gc.getPlayer(0).isPlayable()
		bDynamicStart = True
		if (bDynamicStart):
			lNeighbours = []
			if (iCiv < con.iNumMajorPlayers):
				lNeighbours = DynamicStarts.lAncestors[iCiv]
			if (b600AD and (iCiv == iArabia or iCiv == iTurkey or iCiv == iSpain or iCiv == iGermany or iCiv == iRussia)):
				lNeighbours.append(iCeltia) #Byzantium
			if (iCiv == iAmerica):
				lNeighbours = dyn.getAmericanNeighbours()
			if (b600AD and iCiv == iKhmer):
				lNeighbours = [] #Khmer get static start in 600 AD, because they spawn too soon after game start.
			dyn.assignDynamicTechs(iCiv, lNeighbours, b600AD)
			if (iCiv == iVikings):
				lNeighbours = [] #Vikings share tech only, no maps.
			dyn.shareMap(iCiv, lNeighbours, 2)
		else:
			dyn.assignStaticTechs(iCiv, b600AD)
		if (iCiv < con.iNumMajorPlayers):
			self.hitNeighboursStability(iCiv)
and
Code:
	def assign600ADTechs(self): #Assigns starting techs for already spawned civs at 600 AD start
		self.assignTechs(iChina)
		self.assignTechs(iJapan)
		self.assignTechs(iIndependent)
		self.assignTechs(iIndependent2)
		self.assignTechs(iNative)
		self.assignTechs(iCeltia)
Also include the line
Code:
import DynamicStarts
in the preamble and
Code:
dyn = DynamicStarts.DynamicStarts()
among the constants.
3. Include the attached DynamicStarts.py file.


Oh, and I'll throw in this picture, mostly because it's pretty and feels right. Persia's map knowledge at spawn:
 

Attachments

I must say, this looks mighty impressive! :king:
 
For the next step, I'd like to make the dynamic starts into an option. Now, it seems that the only options that can be selected at the scenario screen are speed and difficulty. Those tie into way too many things, and I'd have to make a lot of code aware of them. For the actual game options, I can set them in the WB save, but most of the effects are hard-coded in the DLL. I don't think adding options is a possibility without DLL changes, and cannibalizing existing options is dangerous.
Fortunately, I did find one option that can be safely stolen: Unrestricted leaders. It has no impact during gameplay, and you don't get to choose the leader for your civ on the scenario screens.

So, here's how to make dynamic starts optional, starting from the previous build:
Spoiler :
1. Change the line "bDynamicStart = True" to "bDynamicStart = gc.getGame().isOption(GameOptionTypes.GAMEOPTION_LEAD_ANY_CIV)" in RiseAndFall.assignTechs .
2. Make new WB saves adding the line "Option=GAMEOPTION_LEAD_ANY_CIV"; I'd attach them, but the map changed in 1.186.
3. For cosmetic purposes, create a new XML text entry
Code:
	<TEXT>
		<Tag>TXT_KEY_GAME_OPTION_LEAD_ANY_CIV</Tag>
		<English>Dynamic Starts</English>
		<French>Dynamic Starts</French>
		<German>Dynamic Starts</German>
		<Italian>Dynamic Starts</Italian>
		<Spanish>Dynamic Starts</Spanish>
	</TEXT>
, preferably with actual translations. I gave it its own file; this affects the settings screen. Completely optional, of course.


If used in an ongoing game, this update will essentially turn off dynamic starts for all later civs.
 
Back
Top Bottom