Limit unit construction by number of available resources

Xyth

History Rewritten
Joined
Jul 14, 2004
Messages
4,106
Location
Aotearoa
Starting a thread here to continue a discussion in a couple of other threads - how to limit the number of units built by the number of strategic resources available.

Baldyr and God Emperor posted this code which I imagine could be adapted:

Code:
def canTrain(self,argsList):
		pCity = argsList[0]
		eUnit = argsList[1]
		bContinue = argsList[2]
		bTestVisible = argsList[3]
		bIgnoreCost = argsList[4]
		bIgnoreUpgrades = argsList[5]
		#city cap code with variable limits:
		iDefault = 3
		dLimits = {	gc.getInfoTypeForString('UNITCLASS_ARCHER') : 4,
				gc.getInfoTypeForString('UNITCLASS_CAVALRY') : 0.3334
				} # add things to this dictionary that should not use the default value
		eUnitClass = gc.getUnitInfo(eUnit).getUnitClassType()
		pOwner = gc.getPlayer(pCity.getOwner())
		iNumUnits = pOwner.getUnitClassCountPlusMaking(eUnitClass)
		iNumCities = pOwner.getNumCities()
		if eUnitClass in dLimits :
			fUnitLimit = dLimits[eUnitClass]
		else:
			fUnitLimit = iDefault
		iLimit = int(iNumCities * fUnitLimit)
		return iNumUnits < iLimit

I had a browse through the Python API for useful functions and found this one:

&#8226; CyCity.getNumBonuses (BonusType iBonus)

I'm not sure if this is just resources in city radius or via the network too. CyCity.hasBonus (BonusType iBonus) seems to be via the network so hopefully its counterpart is too. When I get some decent time I'll have a go at rewriting God Emperor's code.

It would be nice though to not have to maintain a 'list' in the code though so what I'm wondering is whether it's possible in Python to effectively 'look up' a unit's xml file for the necessary information - in this case <BonusType>, <PrereqBonuses> and <bPrereqBonuses>. I had a brief search through the Python API but didn't find anything obvious. Is something like this possible?
 
It would be nice though to not have to maintain a 'list' in the code though so what I'm wondering is whether it's possible in Python to effectively 'look up' a unit's xml file for the necessary information - in this case <BonusType>, <PrereqBonuses> and <bPrereqBonuses>. I had a brief search through the Python API but didn't find anything obvious. Is something like this possible?
What you need is the CvUnitInfo class, namely CvUnitInfo.getPrereqAndBonus() and CvUnitInfo.getPrereqOrBonuses() but I'm not entirely sure how they work.

You will need a CvUnitInfo instance to use with those methods, and for this you use CyGlobalContext.getUnitInfo().
 
The list in there, dList, is to allow different unit classes to have different limits. There is nothing in the XML that could really be used for this in that X per-city limit case.

For your resource based limit, should tanks have the same iron based limit as swordsmen? I would think that unit of a tanks uses a LOT more iron than a unit of swordsmen. On the other hand, a modern mine also produces a lot more iron than classical era mine, so perhaps it evens out. However in such a case the lone swordsman sitting in some city for the last 3000 years would block a tank from being built if they both use the same amount (even if they don't, it still might block it since that small amount for the swordsman might be just enough to leave you short for another tank).

For some resource related usage count the iPower, or iCombat and iAirCombat, ratings might be good. (Swordsman iPower and iCombat are 6, tank iPower is 30 and iCombat is 28 so based off iPower a tank would use 5 times as much. If a single iron mine gave 60, that would be good for 10 swordsmen or 2 tanks.)

Add yes, I know tanks don't actually require iron, just oil. But they probably should. Consider the ironclad if you prefer.

An adjustment you will need to do is that you will have to loop through all unit classes and add up the current counts for every unit class that needs the same resources as the unit being checked, rather than just checking the count of the current unit. If different units can have different usage requirements then each needs to be multiplied by the relevant cost to get the total current resource usage.

It is also complicated by units that have the "or" type relation from the PrereqBonuses. Macemen can use copper or iron. You want to build a knight. Knights need iron. If you have only an iron the macemen must be using it too. If you have both iron and copper, are the macemen using only the copper or are there too many? What about the spearmen who also need copper or iron? It seems to me that you have to loop over all the unit classes more than once. The first time through you keep counts for resources consumed by units that require one specific resource. Then you have to do a pass and figure out which resource the existing units of a type are using when they cane use more than one - the spearmen use half the copper, leaving half for macemen and any excess macemen are therefore using iron, thus reducing the amount available for Knights.

There are always issues to consider for things like this. Here is another one:

It gets weirder when cities are cut off from the trade network. Say some barbarian pillages the road between your only two cities. Your capital has an iron mine. Your second city has copper. You already have enough axemen and spearmen to use 1.5 mines worth of iron or copper (since both can use either iron or copper). You suddenly find that in your capitol, which has a mine's worth of iron, not only can you not build any spearmen or axemen, you also can't build any swordsmen. You have 1 mine worth of iron but the total of axes and spears in your civilization uses more than that. In the other city you also can't build any swordsmen since it has no iron. But you also can't build any more axemen or spearmen there since it has only 1 mines worth of the required resource types too, but there are 1.5 mines worth of units that can use its resource already in existence.

The issue there is the global count of unit vs. the local count of resources. How come each city is trying to support every unit with the resources it alone has access to? Shouldn't the capital with its iron mine be supporting some units allowing the second city to still build more to defend itself? After all, between the 2 of them they have 2 mines worth of resources even if they are not connected via a trade route. Because of this issue what you may want is a total resource count, not the number of them that are currently connected to this one city. I'm not sure if that number is available via a single function call. There is a CyPlayer.countOwnedBonuses() that might do the trick. If that doesn't do it (I didn't check the SDK to see what it does), you may have to loop over all your cities and categorize which trade network they are part of, then add the counts for each trade network. Every interconnected city should have the same list of resources (OK - not in the late game: corporations that produce resources only add them to the local city, those don't propagate; more complications...) so you can probably make a list of all your cities then start with the first and add its count to the total, then remove it from the city list and also every city in the list that it's CyCity.isConnectedTo() function says it is connected to. With any luck there may be a better way, like CyPlayer.countOwnedBonuses() which may do something a lot like this already (and it would probably take corporation produced resources into account toom if this is what it does).

At this point, this Python solution may be a tad unwieldy (and sluggish).

An alternative to this whole thing is to wait for the mod that The Lopez is working on, the City Resource Stockpiling mod, that has resource plots actually produce some number of resource units each turn. The resource units can be accumulated in the city with the plot, or probably the closest city for those not in a BFC, and distributed in various ways around your empire - some automatic and some manual. Producing things then also consumes resource units.
 
Yeah, i like the idea a lot, but like God-Emperor said, in Civ4 this features involves on a lot of complications, You need to better define and plan what the mod should be about.
One thing though, something as this should be implemented( most of it) in the DLL, since it would be heavily used and is supposed to be a player variable.

Also like God-Emperor said, TheLopez resource stockpiling mod could be useful even if it's just bits of it or just a simplified version of it. I know he's also having problems with the overall scope of resources, there is just a lot of things to consider.

Compared to the way resources of Civ4 works, Civ5 is just really simplified.
 
Back
Top Bottom