AI_getAttitude() Infinite Loop

LyTning94

Dragonborn
Joined
Nov 10, 2010
Messages
397
Location
Skyrim
I have a certain function I added in CvPlayerAI that is called by AI_getAttitudeVal() and, in effect, does the following:

If player A has fulfilled certain conditions toward player B, and player C is furious toward player B, then player A suffers an attitude penalty toward player C. It is similar to "You have traded with our worst enemies".

My problem is that I used this code:

Code:
if (eEnemy != getID())
{
	if (AI_getAttitude(eEnemy) == ATTITUDE_FURIOUS)
	{
		...
	}
}

but when AI_getAttitude() is called, it in turn calls AI_getAttitudeVal(), which calls the function I added, which then calls AI_getAttitude() again, which then calls AI_getAttitudeVal() again, and it continues to repeat itself until I get a stack overflow error.

Any ideas on how to fix this?
 
What exactly does the getAttitudeValue code look like, and what does it do? (It might be that your function uses some other function that uses the attitude value being called, which would make the loop.) It certainly seems possible that a function that both uses and effects an attitude would create an infinite loop, though I may just not be understanding the problem very well, and you'll need more useful help.
 
Exactly. My function calls AI_getAttitude() in the code I posted, and AI_getAttitude() calls AI_getAttitudeVal(). Since my function is called by AI_getAttitudeVal(), this is what is causing the loop. What I'm trying to figure out is how to produce the same effect without calling AI_getAttitude() in my function or somehow preventing the loop from occuring.
 
Perhaps creating a new value, or several new values, for what the getAttributeVal function produces, than have the second function use the value rather than the function itself. (Which in my theory, would simply use a stored value and that's it, rather than creating the infinite loop.) Am not sure exactly how you would do this without having fiddled with diplomacy yet, but presumably you'd use something similar to how standard relations are handled.
 
I thought of that, but if I add a value which equals the value of AI_getAttitudeVal(), then I'm going to have the same problem when I try and assign the value, since AI_getAttitudeVal() calls my function.

The only thing I can think of right now is to create a whole new function which is identical to AI_getAttitudeVal(), except that it does not call my function. I could then call this in my function instead of using the existing function. The only problem with this is that, using my previous scenario:

If player A has fulfilled certain conditions toward player B, and player C is furious toward player B, then player A suffers an attitude penalty with player C. Then if player D has fulfilled the same conditions toward player A, it would follow that player D suffers an attitude penalty with player C if player C is furious toward player A. The problem is that this attitude of player C toward player A (in blue) would not include the penalty mentioned above (in red). Hopefully you just followed me. ;)

This most probably wouldn't be relevant in most situations, and I'm guessing the scenario just mentioned won't happen very often, but I would like to find another way to do it. Then again, I'm not sure if any other way is even possible, so...:dunno:
 
On the separate value: I was thinking of using a value like the various "M_isomething" values used through these DLL files, which is than updated something like once a turn, or changed once after certain diplomatic events occur. (Though this isn't exactly what you are looking for)

If player A has fulfilled certain conditions toward player B, and player C is furious toward player B, then player A suffers an attitude penalty with player C. Then if player D has fulfilled the same conditions toward player A, it would follow that player D suffers an attitude penalty with player C if player C is furious toward player A. The problem is that this attitude of player C toward player A (in blue) would not include the penalty mentioned above (in red). Hopefully you just followed me.

This most probably wouldn't be relevant in most situations, and I'm guessing the scenario just mentioned won't happen very often, but I would like to find another way to do it. Then again, I'm not sure if any other way is even possible, so...

To me, the issue here seems to be in the math rather than the code itself, though others with more experience in this sort of thing may have other tricks. Since the function effects its own input, and effectively gets iterated over and over, it will end up possibly creating a long, or possibly infinite series, no matter how you do it if the updates are done as you describe.

My best guess would be to try and work out mathematically (by hand, spreadsheets, etc.) what tends to happen under a variety of conditions to the relations between factions, than try and work from this to create single updates, rather than trying ot update, input, update, etc. as you are doing now. (Of course, there might be some other tricks you can use that I'm just completely missing.)

(Hopefully my own response made sense. :) )
 
Just thought of another possibility this morning:

While the function runs through the diplomatic relations with the various civilizations, have it store whether the relations have changed. Than, if any of the relations change, have the functions run again. If none changed, have it stop in some way. I'm not sure how to do this exactly without seeing your code (and might take some time even if I do), but it might go something like:

Overall:
(Whatever you've done with the overall function)
Create "check' value, set it to zero

1. Function checks for furious relations, plus checks for other condition
2. Function changes diplomatic relations
3. add 1 to the "check" value

When the function goes through the possible relations, see if the check value is equal to zero. If it is, these final diplomatic relations are the final ones. If not, run through the values again.


I'm not sure (as mentioned) if this exactly fits how your code is organized, but hopefully it gives you a useful idea.
 
I think you lost me in your last post. You might have to explain in a little more detail. Anyway, I was thinking some more about the value idea and I think it might be possible. I would have to use an array (probably a two-dimensional one) to hold all the attitudes of each player toward each other player. I could use something like this:

Code:
m_AttitudeVals[MAX_PLAYERS][MAX_PLAYERS];

and then in CvPlayer::doTurn():

Code:
for (int i = 0; i < GC.getInitCore().getNumDefinedPlayers(); i++)
{
	if (i != getID())
	{
		m_AttitudeVals[getID()][i] = GET_PLAYER(getID()).AI_getAttitudeVal((PlayerTypes)i);
	}
}

and finally in my function write:

Code:
if (eEnemy != getID())
{
	if (m_AttitudeVals[getID()][eEnemy] <= -10)  // The equivalent of being furious, I believe
	{
		...
	}
}

Do you think this would work?
 
Top Bottom