Skip to content

InfoArray (cpp)

Nightinggale edited this page Jan 19, 2022 · 1 revision

Purpose

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.

Structure

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.

Data access

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);
}

Adding data to the array

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.

InfoArray vs 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.

Random access

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.

Changing contents

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.

Looping

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.