Multidimensional Arrays

johnny_cash

Chieftain
Joined
Aug 4, 2009
Messages
32
Location
los angeles, ca
Hi,

so I'm trying to create some multidimensional arrays in CvCity. I'm having problems initializing and declaring them.

I'm trying to create
Code:
int m_aiBuildingBonusStockChange[GC.getNumBuildingClassInfos()][GC.getNumBonusInfos()]
. I tried using the method in CvInfos for declaring m_ppaiSpecialistYieldChange, however it did not work.

How would I go about properly initializing and declaring my multidimensional array?

when i tried to intialize like this:
Code:
m_aiBuildingBonusStockChange = new int[GC.getNumBuildingClassInfos()][GC.getNumBonusInfos()];

i get this error compiling
Code:
CvCity.cpp|59|error C2440: '=' : cannot convert from 'int (*)[1]' to 'int ** '|

Thanks in advance for any help!
 
Code:
m_aaiBuildingBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
for int iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
{
    m_aaiBuildingBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
}


I added an extra a to your variable name to help you remember it is 2D

If this is in CvInfos, you init during the first readpass with

Code:
pXML->Init2DIntList(&m_aaiBuildingBonusStockChange, GC.getNumBuildingClassInfos(), GC.getNumBonusInfos());
 
I am not familiar with 2d arrays in Civ, but your code does not look quite right. Doesn't your first line allocate an array of ints? You want to allocate an array of pointers. On some machines an int and pointer are the same size, but I think a lot of casting will be involved to use your definition successfully.

Are there existing 2d arrays in Civ which can be used as a model? If not, then using a 2d array means that none of the existing civ infrastructure will work. Perhaps whatever the end goal is, can be achieved with a one dimensional array; then there are plenty of existing models in the Civ code.

EDIT: never mind both points. "new int*" allocates int pointers. And your example uses Init2DIntList, therefore searching for other references of that will find models.
 
It's not a question of allocating a 2-d array. That would be "int a[3][42]"

It's a question of dynamically allocating a 2-d array. It is dynamic because the sizes of the two indicies are not constants - they are only known at run-time. Thus you use the "new" statement, which does not do multidimensional arrays (as far as I know). This is just the equivalent of using a malloc() ot similar function in regular C, which doesn't exactly allow for direct creation of 2-d arrays either.
 
Mmmhh...C is sometimes very limited.
Delphi, Python and visual basic makes it very easy to resize arrays of every dimension, so i didn't understand that problem.

Philosophy alert, but, you say "limited" and I say "closer to the OS". In Python etc, you cannot really tell how much memory you are using. For large applications, this can lead to running out of memory. In C, you have much tighter control so you can be much more efficient. I like Python for small things, but for huge data sets, I'll take C.
 
Yes, C exposes you to the internal memory structures which can be both a blessing and a curse. It's great when you need control but can be very difficult for new students and hobbyists to grasp. A case in point is that this dynamic 2D array you're creating isn't really a 2D array; rather it's an array of pointers to arrays.

Java has this same restriction when dealing with dynamically-sized arrays. In Python, there is no such thing as an array at all, only lists which behave much like arrays. As such it doesn't have multidimensional arrays; instead you use lists of lists.

Note that for C/C++there are libraries (Standard Template Library in C++) which give you access to the same powerful data structures found in Python and Java such as lists, sets, dictionaries (maps), and trees.
 
Thanks for the help/discussion.

So I compile but now I'm unable to place a city in the worldbuilder and if I build a city with a settler I get a CTD. I'm pretty sure this has to do with my "2d" arrays, because this has only begun happening since their implementation.

in CvCity:CvCity() I have
Code:
	m_aaiBuildingBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
	for (int iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		m_aaiBuildingBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
	}

	m_aaiBuildingOverallBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		m_aaiBuildingOverallBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
	}

in ~CvCity()
Code:
	if (m_aaiBuildingBonusStockChange != NULL)
	{
		for(int i=0; i<GC.getNumBuildingClassInfos();i++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange[i]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange);
	}

	if (m_aaiBuildingOverallBonusStockChange != NULL)
	{
		for(int i=0; i<GC.getNumBuildingClassInfos();i++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange[i]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange);
	}

in uninit()
Code:
	if (m_aaiBuildingBonusStockChange != NULL)
	{
		for(int i=0; i<GC.getNumBuildingClassInfos();i++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange[i]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange);
	}

	if (m_aaiBuildingOverallBonusStockChange != NULL)
	{
		for(int i=0; i<GC.getNumBuildingClassInfos();i++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange[i]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange);
	}

and then in reset()
Code:
	int j;
	if (m_aaiBuildingBonusStockChange == NULL)
	{
		m_aaiBuildingBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
		for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			m_aaiBuildingBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
		}
	}

	
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		for (j = 0; j < GC.getNumBonusInfos(); j++)
		{
			m_aaiBuildingBonusStockChange[iI][j] = 0;
		}
	}

	if (m_aaiBuildingOverallBonusStockChange == NULL)
	{
		m_aaiBuildingOverallBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
		for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			m_aaiBuildingOverallBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
		}
	}

	
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		for (j = 0; j < GC.getNumBonusInfos(); j++)
		{
			m_aaiBuildingOverallBonusStockChange[iI][j] = 0;
		}
	}

the purpose of these arrays is to keep track of the bonus production rate of buildings. I would like it to work the same way as the BuildingYieldChange vector.

these are the functions i use to get the data:

Code:
int CvCity::getBuildingBonusStockChange(BuildingClassTypes eBuildingClass, BonusTypes eBonus)
{
	return m_aaiBuildingBonusStockChange != NULL ? m_aaiBuildingBonusStockChange[(int) eBuildingClass][(int) eBonus] : 0;
}

void CvCity::changeBuildingBonusStockChange(BuildingClassTypes eBuildingClass, BonusTypes eBonus, int iChange)
{
	setBuildingBonusStockChange(eBuildingClass, eBonus, getBuildingBonusStockChange(eBuildingClass, eBonus) + iChange);
}

void CvCity::setBuildingBonusStockChange(BuildingClassTypes eBuildingClass, BonusTypes eBonus, int iValue)
{
	m_aaiBuildingBonusStockChange[(int) eBuildingClass][(int) eBonus] = iValue;
}

//overall 

int CvCity::getBuildingOverallBonusStockChange(BuildingClassTypes eBuildingClass, BonusTypes eBonus)
{
	return m_aaiBuildingOverallBonusStockChange != NULL ? m_aaiBuildingOverallBonusStockChange[(int) eBuildingClass][(int) eBonus] : 0;
}

void CvCity::changeBuildingOverallBonusStockChange(BuildingClassTypes eBuildingClass, BonusTypes eBonus, int iChange)
{
	setBuildingOverallBonusStockChange(eBuildingClass, eBonus, getBuildingOverallBonusStockChange(eBuildingClass, eBonus) + iChange);
}

void CvCity::setBuildingOverallBonusStockChange(BuildingClassTypes eBuildingClass, BonusTypes eBonus, int iValue)
{
	m_aaiBuildingOverallBonusStockChange[(int) eBuildingClass][(int) eBonus] = iValue;
}



I'm also open to other, better performance approaches..

Thank you!
 
The array allocation/deallocation code looks fine; just check that you do both in the same places as other arrays are handled. One possible source of a CTD could be a null pointer exception in either of the set() functions. While the get() functions check the array for NULL, the set() functions do not.
 
Do you actually use the get/set functions anywhere yet? If not, the error is in the allocation. I am accustomed to only seeing one of the two pairs of allocate/deallocate that you posted per array. But in reset you check if it is NULL before allocation, so it should be fine I hope.

We don't have full context here, but you may need to be nested in a if !bConstructorCall check for the allocations in reset()
 
In the constructor call's field initializer section, are you initializing both arrays to NULL?

Code:
CvCity::CvCity(...) :
    m_paiBuildings(NULL),
    ...
[B]    m_aaiBuildingBonusStockChange(NULL),
    m_aaiBuildingOverallBonusStockChange(NULL)[/B]
{
    ...
}
 
Do you actually use the get/set functions anywhere yet? If not, the error is in the allocation. I am accustomed to only seeing one of the two pairs of allocate/deallocate that you posted per array. But in reset you check if it is NULL before allocation, so it should be fine I hope.

We don't have full context here, but you may need to be nested in a if !bConstructorCall check for the allocations in reset()

I do use the get/set functions but they are not called until a city with a building exists. I can't even get to placing a city, let alone placing the appropriate building that would use those functions.

It seems like all of the pointer arrays in cvcity are nested in if !bConstructorCall
 
In the constructor call's field initializer section, are you initializing both arrays to NULL?

Code:
CvCity::CvCity(...) :
    m_paiBuildings(NULL),
    ...
[B]    m_aaiBuildingBonusStockChange(NULL),
    m_aaiBuildingOverallBonusStockChange(NULL)[/B]
{
    ...
}

actually no, in the constructor call i have:
Code:
m_aaiBuildingBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
	for (int iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		m_aaiBuildingBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
	}

	m_aaiBuildingOverallBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		m_aaiBuildingOverallBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
	}

and in the destructor
Code:
if (m_aaiBuildingBonusStockChange != NULL)
	{
		for(int i=0; i<GC.getNumBuildingClassInfos();i++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange[i]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange);
	}

	if (m_aaiBuildingOverallBonusStockChange != NULL)
	{
		for(int i=0; i<GC.getNumBuildingClassInfos();i++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange[i]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange);
	}
 
Never mind. I see that CvCity doesn't use field initialization for its arrays.

Pick an existing array and follow the same pattern. Let's try m_paiProjectProduction (totally picked at random).

  1. Constructor: Set the two arrays to NULL. Do not allocate.
  2. reset(): Place allocation inside the "if (!bConstructorCall)" check. Do not check if they are NULL.
  3. Don't forget read() and write().
 
Never mind. I see that CvCity doesn't use field initialization for its arrays.

Pick an existing array and follow the same pattern. Let's try m_paiProjectProduction (totally picked at random).

Constructor: Set the two arrays to NULL. Do not allocate.
reset(): Place allocation inside the "if (!bConstructorCall)" check. Do not check if they are NULL.
Don't forget read() and write().

no dice, i get the same CTD. here is what i have now:

in cvcity() constructor
Code:
	m_aaiBuildingBonusStockChange = NULL;
	m_aaiBuildingOverallBonusStockChange = NULL;

in uninit()
Code:
	SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange);	
	SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange);

in reset() inside the if !bConstructorCall check
Code:
int j;
		
		m_aaiBuildingBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
		for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			m_aaiBuildingBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
		}

	
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			for (j = 0; j < GC.getNumBonusInfos(); j++)
			{
				m_aaiBuildingBonusStockChange[iI][j] = 0;
			}
		}
		
		m_aaiBuildingOverallBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
		for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			m_aaiBuildingOverallBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
		}
		
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			for (j = 0; j < GC.getNumBonusInfos(); j++)
			{
				m_aaiBuildingOverallBonusStockChange[iI][j] = 0;
			}
		}

in read()
Code:
if (m_aaiBuildingBonusStockChange != NULL)
	{
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange[iI]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange[iI]);
	}

	m_aaiBuildingBonusStockChange = new int*[GC.getNumBuildingClassInfos()];

	for (iI = 0; iI<GC.getNumBuildingClassInfos(); iI++)
	{
		m_aaiBuildingBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
		pStream->Read(GC.getNumBonusInfos(), m_aaiBuildingBonusStockChange[iI]);
	}

	if (m_aaiBuildingOverallBonusStockChange != NULL)
	{
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange[iI]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange[iI]);
	}

	m_aaiBuildingOverallBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
	
	for (iI = 0; iI<GC.getNumBuildingClassInfos(); iI++)
	{
		m_aaiBuildingOverallBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
		pStream->Read(GC.getNumBonusInfos(), m_aaiBuildingOverallBonusStockChange[iI]);
	}

in write()
Code:
for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		pStream->Write(GC.getNumBonusInfos(), m_aaiBuildingBonusStockChange[iI]);
	}
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		pStream->Write(GC.getNumBonusInfos(), m_aaiBuildingOverallBonusStockChange[iI]);
	}
 
So I am no longer getting the CTD on building a city. But I am getting a CTD when i call the following functions:

Code:
void CvCity::changeBuildingBonusStockChange(BuildingClassTypes eBuildingClass, BonusTypes eBonus, int iChange)
{
	setBuildingBonusStockChange(eBuildingClass, eBonus, getBuildingBonusStockChange(eBuildingClass, eBonus) + iChange);
}

void CvCity::setBuildingBonusStockChange(BuildingClassTypes eBuildingClass, BonusTypes eBonus, int iValue)
{
	if (m_aaiBuildingBonusStockChange != NULL)
	{
		m_aaiBuildingBonusStockChange[(int) eBuildingClass][(int) eBonus] = iValue;
	}
}

this is how i have the arrays initialized:

in CvCity():
Code:
m_aaiBuildingBonusStockChange = NULL;
	m_aaiBuildingOverallBonusStockChange = NULL;

in uninit():
Code:
if (m_aaiBuildingBonusStockChange != NULL)
	{
		for(int i=0;i<GC.getNumBuildingClassInfos();i++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange[i]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange);
	}
	if (m_aaiBuildingOverallBonusStockChange != NULL)
	{
		for(int i=0;i<GC.getNumBuildingClassInfos();i++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange[i]);
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange);
	}

in reset():
Code:
		int j;
		m_aaiBuildingBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			m_aaiBuildingBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
			for (j = 0; j < GC.getNumBonusInfos(); j++)
			{
				m_aaiBuildingBonusStockChange[iI][j] = 0;
			}
		}
		m_aaiBuildingOverallBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			m_aaiBuildingOverallBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
			for (j = 0; j < GC.getNumBonusInfos(); j++)
			{
				m_aaiBuildingOverallBonusStockChange[iI][j] = 0;
			}
		}

in read():
Code:
if (m_aaiBuildingBonusStockChange != NULL)
	{
		for (iI = 0; iI<GC.getNumBuildingClassInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange[iI]);		
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingBonusStockChange);
	}
	
	m_aaiBuildingBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		m_aaiBuildingBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
		pStream->Read(GC.getNumBonusInfos(), m_aaiBuildingBonusStockChange[iI]);
	}

	if (m_aaiBuildingOverallBonusStockChange != NULL)
	{
		for (iI = 0; iI<GC.getNumBuildingClassInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange[iI]);		
		}
		SAFE_DELETE_ARRAY(m_aaiBuildingOverallBonusStockChange);
	}
	
	m_aaiBuildingOverallBonusStockChange = new int*[GC.getNumBuildingClassInfos()];
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		m_aaiBuildingOverallBonusStockChange[iI] = new int[GC.getNumBonusInfos()];
		pStream->Read(GC.getNumBonusInfos(), m_aaiBuildingOverallBonusStockChange[iI]);
	}

the read code i took from cvinfos for 2d arrays. do i need to delete the arrays before read?

thanks for all of the help!
 
I would check that you're not passing in NO_BUILDINGCLASS or NO_BONUS (both -1) as they will lie outside of the arrays' valid ranges. You can simply do nothing in those cases, but I think it would be indicative of a problem in the calling code.

Once you fix that problem the checks could be changed into asserts (or write them that way to begin with) to keep runtime speed high and still help during development.

Code:
FAssertMsg(eBuildingClass >= 0, "eBuildingClass must be >= 0");
FAssertMsg(eBuildingClass < GC.getNumBuildingClassInfos(), "eBuildingClass must be < GC.getNumBuildingClassInfos()");

And the same for eBonus.
 
I would check that you're not passing in NO_BUILDINGCLASS or NO_BONUS (both -1) as they will lie outside of the arrays' valid ranges. You can simply do nothing in those cases, but I think it would be indicative of a problem in the calling code.

Once you fix that problem the checks could be changed into asserts (or write them that way to begin with) to keep runtime speed high and still help during development.

Code:
FAssertMsg(eBuildingClass >= 0, "eBuildingClass must be >= 0");
FAssertMsg(eBuildingClass < GC.getNumBuildingClassInfos(), "eBuildingClass must be < GC.getNumBuildingClassInfos()");

And the same for eBonus.

Hmm. Even with the check i'm getting the CTD. Does that mean that the right values are being passed to the function but the arrays are still not initialized properly?

the functions are called here:

Code:
void CvCity::doIndustry(BuildingTypes eIndex)
{
	CvBuildingInfo& kBuilding = GC.getBuildingInfo(eIndex);
	int iI;
	int iHighestOrSource = 0;
	BonusTypes eHighestOrBonus = NO_BONUS;
	BuildingClassTypes eBuildingClassIndex = (BuildingClassTypes) kBuilding.getBuildingClassType();
	int iContendingSource;
	int iRate;
	bool bLevelOkay = true;
	int iOldValue, iOldOverallValue;
	
	if (eIndex == NO_BUILDING)
	{
		return;
	}
	
	
	for (iRate = getBuildingOutputRate(eIndex); iRate >= 0; iRate--)
	{
		for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
		{
			if (kBuilding.getYieldInput(iI) > 0)
			{
				if (getYieldRate((YieldTypes) iI) < (iRate*(kBuilding.getYieldInput(iI))))
				{
					bLevelOkay = false;
					break;
				}
			}
		}
		if (bLevelOkay)
		{
			for (iI = 0; iI <GC.getNumBonusInfos(); iI++)
			{
				if (kBuilding.getOrBonusInput(iI) > 0)
				{
					if (getOverallBonusStock((BonusTypes) iI) >= (iRate*(GC.getBuildingInfo(eIndex).getOrBonusInput(iI))))
					{
						bLevelOkay = true;
						break;
					}
					else
					{
						bLevelOkay = false;
					}
				}
			}
		}
		if (bLevelOkay)
		{
			for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
			{
				if (kBuilding.getOrBonusInput(iI) > 0)
				{
					if (getOverallBonusStock((BonusTypes) iI) < (iRate*(GC.getBuildingInfo(eIndex).getAndBonusInput(iI))))
					{	
						bool bLevelOkay = false;
						break;
					}
				}
			}
		}
		if (bLevelOkay == true)
		{
			break;
		}
	}

	setBuildingOutputRate(eIndex, iRate);
			
	for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
	{
		iOldValue = getBuildingYieldChange( eBuildingClassIndex, (YieldTypes) iI);
		if (kBuilding.getYieldOutput(iI) > 0)
		{				
			changeBuildingYieldChange( eBuildingClassIndex, (YieldTypes) iI, -iOldValue + (iRate*kBuilding.getYieldOutput(iI)) );			
			
		}
		if (kBuilding.getYieldInput(iI) > 0)
		{
			changeBuildingYieldChange( eBuildingClassIndex, (YieldTypes) iI, -(iOldValue + (iRate*kBuilding.getYieldInput(iI))) );
		}
	}
	
	for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
	{		
		iOldValue = getBuildingBonusStockChange( eBuildingClassIndex, (BonusTypes) iI);
		iOldOverallValue = getBuildingOverallBonusStockChange( eBuildingClassIndex, (BonusTypes) iI);
		if (kBuilding.getBonusOutput(iI) > 0)
		{
			changeBuildingBonusStockChange( eBuildingClassIndex, (BonusTypes) iI, -iOldValue + (iRate*kBuilding.getBonusOutput(iI)) );
		}
		if (kBuilding.getAndBonusInput(iI) > 0)
		{
			changeBuildingOverallBonusStockChange( eBuildingClassIndex, (BonusTypes) iI, -(iOldOverallValue + (iRate*kBuilding.getAndBonusInput(iI))) );
		}
		if (kBuilding.getOrBonusInput(iI) > 0)
		{
			iContendingSource = getOverallBonusStock((BonusTypes) iI) - (iRate*kBuilding.getOrBonusInput(iI));
			if ( iContendingSource >= iHighestOrSource)
			{
				iContendingSource = iHighestOrSource;
				eHighestOrBonus = (BonusTypes) iI;
				changeBuildingOverallBonusStockChange(eBuildingClassIndex, (BonusTypes) iI, -iOldOverallValue);
			}			
				
		}
	}
	if (eHighestOrBonus != NO_BONUS)
	{
		iOldOverallValue = getBuildingOverallBonusStockChange( eBuildingClassIndex, eHighestOrBonus);
		changeBuildingOverallBonusStockChange(eBuildingClassIndex, eHighestOrBonus, -(iOldOverallValue + (iRate*kBuilding.getOrBonusInput(iI))) );
	
	}
}
 
Top Bottom