Slow down mid game (in regard to) STM2 conversion

cpt.tripps.2012

Warlord
Joined
May 25, 2012
Messages
176
So I've been noticing that around mid game there is a major slow down. I think this is related to all the planets being colonized. In my star trek mod planets are colonized a bit faster and the game is a bit longer so the overrides for building the attack sqauds and such aren't kicking in yet.

I think I need to add a bit of code so that once all the planets are colonized the AI stops building colony ships and deletes any wondering colony units that might be futility searching for a planet and otherwise uselessly eating up processing power.

I figured since you know the code better then I do you might be able to come up with a good game plan for this.

Thoughts?
 
I have been pondering this... (Probably would go better if I got the mod, which I haven't yet.)

Have you checked via worldbuilder to see if the AI has a bunch of colony ships sitting around? In FFP once all the star systems are settled it stops building them, except perhaps one or two spares. Unless you have ST specific Python to make it build more, there is nothing in the Python about colony ships. It forces the occasional extra construction ship, but does nothing regarding colony ships.

FFP has a fairly gradual slowdown - it does not hit any sudden wall where turns take a lot longer. This makes me think it is one of two things:
1) ST specific Python
2) Starbases

Since I have not grabbed ST-II, I don't know about the first one. AS for the second one, I'm not sure if it is a good candidate or not since it does not cause this problem in regular FFP.

In FFP the tech to build starbases comes fairly early, so it usually starts to try to build them before it has explored all of the map. When does the tech to build them come in ST-II? Is it, perhaps, shortly before the great slowdown? How about the tech which enables construction ships (since you need them too)?

Again in FFP, there are two types of bases which have different positioning algorithms. The standard starbase and the "other base" (which is used by the sensor station). TO some extent this difference does not matter since each of these checks involves scanning the entire map, plot by plot, and if it has ever seen that plot and the plot does not already belong to someone else and is not not on top of damaging features or nebula then it evaluates that location, which involves looping over all the plots in a 5x5 area centered on that plot. That is a lot of plot lookups on big maps once all the territory has been explored. So if the slowdown is happening around the time the AIs start having the techs that allow starbase (or "other base") construction and producing construction ships then this could be it.

The main thing that reduces the amount of checking is that each AI will only ever have 1 construction ship trying to build a base of some sort. If one has already been designated to be the base builder, then it stops checking until there isn't (which happens when the designated construction ship is destroyed, including building a base since that kills the construction ship). Also, as the game progresses the settling of new systems and expanding borders will actually reduce the amount of checking so each check will go quicker. And there is the cost. In FFP it costs a fair chunk of change to build a starbase (and half as much to build a sensor station). This can also slow the rate. This is why it has not been a big problem in FFP as the game progresses.

Since version 1.8 it will also sometimes decide not to check and it can eventually stop entirely. It used to always check, if there was not already a base being built (or a construction ship heading to the selected location). As per the comments in doConstructionShipAI, now if there is no construction ship already selected to build a base of some sort then the chance of not checking to see if this one should build a type of base has a chance of N in X where N is the number of bases of this type already built and X is is 10 + (2 * map size) [map size: duel = 0, tiny = 1, small = 2, standard = 3, large = 4, huge = 5]. It checks this for each build type that can produce a station but evaluates each one not skipped before checking the next, and stops checking the rest of them as soon as one of them hits this random chance (in FFP there are only 2 types, so if it hits the chance for the first type then it will check neither, but if it hits the chance for the second type then it will have already evaluated the first type and decided not to build one either due to the cost or due to not being able to find a place with a high enough rating to do so).

Because of all this, I'm not sure that this can be the cause. Each AI will only ever be trying to build 1 base, and as long as the construction ship that is the designated builder exists it won't check for another. If your game has a more pirate/barbarian activity than FFP (which would be a lot - FFP gets some complaints about having too many) the designated station building construction ships might be getting killed off more than in FFP which would make it check again as some as it has a construction ship that is not doing anything. Also, if you are packing in many more civilizations than FFP on a map it could also slow things down more than FFP, since each civ wants to build them.

All that said, there is an optimization which I can see in the evaluation code for the regular starbase. As it stands now, it evaluates the plot and then zeros out the value if the plot is on a bad feature. This condition should be checked before looping over all the plots in the 5x5 area to gather info about them and the entire plot skipped if the plot has a bad feature (so no checking the 5x5 area). This could speed things up a bit since there are usually a lot of plots with bad features. Oddly, the "other" base location code already does it this way.

This is the newly revised function (the change is the code with the comment that starts "post v1.81"). It will be in the FFP 1.82 patch (due out eventually - no set date yet).
Code:
	def findBestResourcePlot(self, iPlayer=-1, bCheckForVisibility=false):
		
		pBestPlot = -1
		iBestValue = -1
		
		pPlayer = -1
		iTeam = -1
		if (iPlayer >= 0):
			pPlayer = gc.getPlayer(iPlayer)
			iTeam = pPlayer.getTeam()
		
		printd("\n    Checking for best plot to build a Starbase \n")
		
		for iPlotLoop in range(CyMap().numPlots()):
			pLoopPlot = CyMap().plotByIndex(iPlotLoop)
#			printd("Checking value of plot at %d, %d" %(pLoopPlot.getX(), pLoopPlot.getY()))
			
			# If we're supposed to be checking for a player's visibility then only check this plot if it's revealed
			if (bCheckForVisibility):
				if (not pLoopPlot.isRevealed(iTeam, false)):
					continue

			# CP - Check the plot being rated to see if it already belongs to someone else.
			iPlotOwner = pLoopPlot.getOwner()
			if ((iPlotOwner != -1) and (iPlotOwner != iPlayer)):
				continue
		
			# Post v1.81: moved this check to here - why loop over nearbby pltos if this one is bad?
			#	Instead of zeroing out the value, just skip the check.
			# Don't build anywhere except in empty space & asteroids
			if (pLoopPlot.getFeatureType() != -1 and pLoopPlot.getFeatureType() != gc.getInfoTypeForString('FEATURE_FOREST')):
				continue
					
			iDistanceFromCapital = CyMap().getGridWidth()
			
			if (pPlayer.getCapitalCity()):
				iDistanceFromCapital = CyMap().calculatePathDistance(pPlayer.getCapitalCity().plot(), pLoopPlot)
			
			# Don't look too far away (performance, more than anything)
			iMaxRange = max(CyMap().getGridWidth() / 2, 60)
			if (iDistanceFromCapital > 0 and iDistanceFromCapital < iMaxRange):
				
				# Will be a value between 0 and the width of the map * 100, e.g. 64 * 100 (6400)
				iDistanceValueMod = (CyMap().getGridWidth() * 100) / iDistanceFromCapital
				iDistanceValueMod = math.sqrt(iDistanceValueMod) * 10
				
				iPlotValue = 0
				iNumBonuses = 0
				
				for iXSearchLoop in range(pLoopPlot.getX()-2, pLoopPlot.getX()+3):
					for iYSearchLoop in range(pLoopPlot.getY()-2, pLoopPlot.getY()+3):
						pSearchPlot = CyMap().plot(iXSearchLoop, iYSearchLoop)
						
						# Don't search unseen plots in range of the one we're looking at either
						if (bCheckForVisibility):
							if (not pSearchPlot.isRevealed(iTeam, false)):
								continue
						
						# Bonus present?
						if (pSearchPlot.getBonusType(iTeam) != -1):
							# Bonus unowned?
							if (pSearchPlot.getOwner() == -1):
								iNumBonuses += 1

						#Build starbases close to solar systems (for defensive purposes) -- TC01
						if pSearchPlot.isCity():
							if pSearchPlot.getPlotCity().getOwner() == iPlayer:
								iPlotValue += 700		#Too much?

						#Build starbases near wormholes (since AI doesn't get Wormholes) -- TC01
						if pSearchPlot.getFeatureType() != -1:
							if gc.getFeatureInfo(pSearchPlot.getFeatureType()).getTargetWormholeType() != -1:
								iPlotValue += 700
							
						#If other starbases are present in radius, no starbase -- TC01
						for iUnit in range(pSearchPlot.getNumUnits()):
							pOtherStarbase = pSearchPlot.getUnit(iUnit)
							if pOtherStarbase.isStarbase():
								iPlotValue = 0
								iNumBonuses = 0
								break

				if (iNumBonuses > 0):
					iBonusValueMod = ((1280 / 3) * iNumBonuses)
					iPlotValue += iDistanceValueMod + iBonusValueMod
					printd("      Plot value for (%d, %d) is %d: Distance: %d, Bonus: %d" %(pLoopPlot.getX(), pLoopPlot.getY(), iPlotValue, iDistanceValueMod, iBonusValueMod))
					
				# Little extra bonus for being in Asteroids (defense)
				if (pLoopPlot.getFeatureType() == gc.getInfoTypeForString('FEATURE_FOREST')):
					iPlotValue += 50		#15
					
				# If this plot has the most resources in range from what we've found
				if (iPlotValue > iBestValue):
					iBestValue = iPlotValue
					pBestPlot = pLoopPlot
			
		return [pBestPlot, iBestValue]
 
I'm putting out a new release this weekend so hold off on downloading it. The version out now uses STM1 as a base and the new one coming out uses FFP 1.81 as a base.

One of the tings I discovered is when the DLL takes over it completely chugs. But when the CvAI.py is running the show it flies! So What I've been trying to do this week is to let the Py run the show when ever possible, which is good during the start of the game, but towards the end there isn't really any script yet to tell the AI to go for a victory, wonders, Science, Culture, ect.

If I can successfully add that stuff in, then who needs the DLL, right?

Bases are much more important in STM2 so perhaps I will make two base builders (since there is usually 3 or 4 constructs per civ going at any given time). Also Resources are super important for building things, so that will be something I need to take into account with the constructs.

Because STM2 is a longer game with more science, units, ect. I am going to have to take into account map size (like you said), as well as the era of game play.

It is alot to take in, but I've made huge strides with the code and I look forward to you taking a look at it when I release it this weekend. I think what I've done is pretty amazing considering two weeks ago I never used python before!

Thanks again for all your help. I don't think I would have gotten this far with out it.
 
Top Bottom