-
Notifications
You must be signed in to change notification settings - Fork 39
InfoArray (cpp)
It's a 2D array of ints (technically shorts). It has an arbitrary length (not linked to an xml file) and each index has 1-4 ints, often types linked to xml files (like YieldTypes). What it contains depends on template parameters at the time of declaration.
Use cases are reading arrays from xml and in cases where looping through an array to do something with non-zero values.
Most likely best understood by reading InfoArray-(xml). Regardless of how it's set in xml, C++ access will always be based on the tables.
InfoArray<UnitClassTypes, YieldTypes, int>
Unit Class | Yield | value |
---|---|---|
UNITCLASS_FARMER | YIELD_FOOD | 5 |
UNITCLASS_FARMER | YIELD_LUMBER | 10 |
function | return type | explanation |
---|---|---|
getLength() | int | returns the number of rows, in this case 2 |
get(int iIndex) | UnitClassTypes | returns the contents in the first column in row iIndex |
get1(int iIndex) | YieldTypes | returns the contents in the second column in row iIndex |
get2(int iIndex) | int | returns the contents in the third column in row iIndex |
getUnitClass(int iIndex) | UnitClassTypes | returns the contents in the first column in row iIndex |
getYield(int iIndex) | YieldTypes | returns the contents in the second column in row iIndex |
getInt(int iIndex) | int | returns the contents in the third column in row iIndex |
Looping will most likely look like
for (int iIndex = 0; iIndex < iArray.getLength(); ++i)
{
total += iArray.getInt(iIndex);
}
There are two ways to fill an InfoArray
void CvInfoBase::readXML(InfoArray& kInfo, const char* szTag);
void InfoArray::assignFrom(const EnumMap& em);
Note that template parameters for both InfoArray and EnumMap have been omitted. They have to match or the compiler won't accept it. You can't read BuildTypes from an EnumMap storing TerrainTypes.
Likewise InfoArray can be assigned to EnumMaps too:
void InfoArray::addTo(EnumMap& em, int iChange = 1, const CvCivilizationInfo* pCivInfo = NULL) const;
void copyTo(EnumMap& em) const;
iChange should be 1 or -1, which effectively allows subtraction too. pCivInfo is used to convert UnitClassTypes to UnitTypes and BuildingClassTypes to BuildingTypes while adding. It's not used in any other cases and can usually be left to the default NULL. Adding will add while copy will overwrite what is already in the EnumMap.
In general InfoArray and EnumMap can store the same. The main difference is that InfoArray only stores non-default values while EnumMap stores every single index.
Use EnumMap Reading from a specific point in the array, like specifically requesting the int from (UNITCLASS_FARMER, YIELD_FOOD) works really fast with EnumMaps while InfoArray will likely always be significantly slower. Also unlike EnumMap, InfoArray will first have to search for the index and then read the index. This can take up multiple lines while EnumMap can do it in a single get call.
Use EnumMap InfoArray doesn't offer the ability to change individual values. If you want to change it, you need to overwrite everything in the array with data from an EnumMap. If the data stored in the array has a tendency to often change, then use EnumMap.
Use InfoArray This is where InfoArray really shines. By skipping all combinations with uninteresting values, the number of iterations will drop significantly. If we go back to the <UnitClassTypes, YieldTypes, int> example, an InfoArray would have two iterations to finish a loop through everything. EnumMap would have to do NUM_UNITCLASS_TYPES * NUM_YIELD_TYPES number of iterations to locate all non-zero values. At the time of writing, that's 187*60=11220 iterations to accomplish the same.