Advanced Diplomacy 2

You have CvSelectionGroup.cpp as part of your C++ changed files directory but I dont see any code in there related to Advanced Diplomacy. Am I missing something?


Edit: You also have duplicate XML files for CIV4TechInfos.xml and CIV4TechnologiesSchema.xml
 
I've been working on the share enemy code and receive a CTD whenever I contact a civ. It CTD at handicap in the C++. I'm not too good with these long string of getTeam(get....
Maybe someone can take a look and help out"

Code:
int CvPlayerAI::AI_getShareEnemyAttitude(PlayerTypes ePlayer) const
{
	int iAttitude;
	iAttitude = 0;

	if (!atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
	{
		if (GET_TEAM(getTeam()).AI_shareEnemy(GET_PLAYER(ePlayer).getTeam()))
		{
			iAttitude += 1;
		}
	}

	return iAttitude;
}
bool CvTeamAI::AI_shareEnemy(TeamTypes eTeam) const
{
	int iI, iK;

	for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
	{
		if (GET_TEAM((TeamTypes)iI).isAlive() && !GET_TEAM((TeamTypes)iI).isMinorCiv())
		{
			if ((iI != getID()) && (iI != eTeam) && (eTeam != getID()))
			{
				if (GET_TEAM(eTeam).AI_getAttitude((TeamTypes)iI) < ATTITUDE_CAUTIOUS) 
				{
					if (AI_getAttitude((TeamTypes)iI) < ATTITUDE_CAUTIOUS)
					{
						return true;
					}
				}
			}
		}
	}

	return false;
}
 
Not very good myself at that but it looks like you have a misplaced parenthesis in the first function:

Code:
	if (!atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
 
Not exactly sure, it is in one of those two functions. I receive an unhandled exception. I think the error I made is that I didn't write a check for GET_TEAM(eTeam).isAlive().
Do I need just another if statement for that?

I adapted some of the code from the shared war C++ and some from Advanced Diplomacy.
 
Isn't Ai_getAttitude supposed to take in player ID as input rather than team ID.
Also, I believe it is a player function too rather than a team function.
 
Not exactly sure, it is in one of those two functions. I receive an unhandled exception.

Compile and run a debug DLL and it will tell you exactly what line is causing the trouble.

Isn't Ai_getAttitude supposed to take in player ID as input rather than team ID.
Also, I believe it is a player function too rather than a team function.

Both CvTeamAI and CvPlayer have AI_getAttitude functions.
 
Here's the attachment for the changed C++ files for shareenemy. Just search for shareenemy. It is a part of Adv Diplo 2.5 so you'll need to put the debug or regular dll into the Adv Diplo 2.5 folder to test.
 

Attachments

  • SharedEnemy.7z
    2.7 MB · Views: 253
I wont have time to run this myself, but if you can replicate this error while running the debug DLL (you might have to run it from the compiler), it should tell you which line the crash is occurring on, at which point I can probably give you a better idea of what the real problem might be.
 
I've rewritten the two functions to call on CvPlayer.cpp instead of the Team function:

Code:
bool CvPlayerAI::AI_SharedEnemy(PlayerTypes ePlayer) const
{
	int iI;
	int iK;

	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive() && !GET_PLAYER((PlayerTypes)iI).isMinorCiv())
		{
			if (GET_TEAM(getTeam()).isHasMet((GET_PLAYER((PlayerTypes)iI).getTeam())))
			{
				if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isHasMet((GET_PLAYER((PlayerTypes)iI).getTeam())))
				{
					if (GET_TEAM(getTeam()).isHasMet((GET_PLAYER(ePlayer).getTeam())))
					{
						if (GET_PLAYER(ePlayer).isAlive() && !GET_PLAYER(ePlayer).isMinorCiv())
						{
							if ((iI != ePlayer) && (iI != getID()) && (getID() != ePlayer))
							{
								[COLOR="Blue"]if (GET_PLAYER(ePlayer).AI_getAttitude((PlayerTypes)iI) < ATTITUDE_CAUTIOUS) [/COLOR]
								{
									if (GET_TEAM(getTeam()).isHasMet((GET_PLAYER((PlayerTypes)iI).getTeam())))
									{
										if (AI_getAttitude((PlayerTypes)iI) < ATTITUDE_CAUTIOUS)
										{
											return true;
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}

	return false;
}

int CvPlayerAI::AI_getSharedEnemyAttitude(PlayerTypes ePlayer) const
{
	int iAttitude;
	iAttitude = 0;

	if (!atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
	{
		if (AI_SharedEnemy(GET_PLAYER(ePlayer).getID()))
		{
			iAttitude += 1;
		}
	}

	return iAttitude;
}

I've highlighted in blue what causes the CTD. Now, the game doesn't crash when I meet a civ, but only when another civ meets another AI civ.
 
One more question. When meeting a leader, there is a list of trades on both sides of the screen. Some trades have nodes with a header (such as trading techs, war, etc.). The embassy trade also has that header. I can't figure out where the code in C++ is for that and how to get rid of it.
 
I've highlighted in blue what causes the CTD. Now, the game doesn't crash when I meet a civ, but only when another civ meets another AI civ.

I cant see anything that seems wrong. But the fact that it's crashing implies that some invalid data is getting in there somehow. It might actually be that the crash is on the next line since I dont see a check to make sure that the team IDs arent the same. Hard to tell. You should probably Debug from within the compiler, and then the crash will drop you back into the compiler where you can look at the local variables and such to see if anything seems amiss.

I would also suggest for ease of reading and for ease of debugging that you use some variables in place of the multiple calls to the same functions. For example, you can add this line:

Code:
TeamTypes eTeam = GET_PLAYER((PlayerTypes)iI).getTeam();

and then use eTeam in the rest of the function instead of the whole "GET_PLAYER((PlayerTypes)iI).getTeam()" so this line,

Code:
if (GET_TEAM(getTeam()).isHasMet((GET_PLAYER((PlayerTypes)iI).getTeam())))

would instead read

Code:
if (GET_TEAM(getTeam()).isHasMet(eTeam))

You could do that for multiple variables and the code would be simpler to read. It would also allow you to mouseover the eTeam variable when debugging and get all the info you need in regards to which team it is referring to.


One more question. When meeting a leader, there is a list of trades on both sides of the screen. Some trades have nodes with a header (such as trading techs, war, etc.). The embassy trade also has that header. I can't figure out where the code in C++ is for that and how to get rid of it.

Dont know about this. I looked into it once a while back and had no luck.
 
A couple of things that I spotted are:

AI_getSharedEnemyAttitude
-------------------------------------
You don't check whether ePlayer is alive, this is a potential CTD.

You have:
PHP:
GET_PLAYER(ePlayer).getID()
This will actually just return you ePlayer so it is very inefficient

The function will only ever return a 1 or a 0 so there is no real need for the iAttitude variable. Maybe this would be better returning a bool rather than an int to make it clearer to understand.

As AI_SharedEnemy returns a boolean you can use that directly to determine the return value.

PHP:
int CvPlayerAI::AI_getSharedEnemyAttitude(PlayerTypes ePlayer) const
{
	if (GET_PLAYER(ePlayer).isAlive && !atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
	{
		return AI_sharedEnemy(ePlayer) ? 1 : 0;
	}
}

AI_SharedEnemy
---------------------
I would rename this as AI_sharedEnemy as the convention is to use a lowercase as the first character after the underscore (remember to make the change in CvPlayerAI.h as well).

You have quite a few checks inside the for loop that do not use the loop variables so will be called multiple times when they only need to be called once. These should be pulled out of the loop and tested first.

You have the following test twice:
PHP:
if (GET_TEAM(getTeam()).isHasMet((GET_PLAYER((PlayerTypes)iI).getTeam())))

For readability it can be easier to reverse the logic of code so that you do not have deeply nested if statements. This is just a matter of style, but can make code easier to follow at times.

Tholal is also correct in that using some more variables can improve readability.

I have just rearranged what you had written taking the above into account which gives the following:

PHP:
bool CvPlayerAI::AI_sharedEnemy(PlayerTypes ePlayer) const
{
	if (getID() == ePlayer)
		return false;

	CvPlayer& kPlayer = GET_PLAYER(ePlayer);

	if (!kPlayer.isAlive())
		return false;

	if (kPlayer.isMinorCiv())
		return false;

	if (!GET_TEAM(getTeam()).isHasMet(kPlayer.getTeam()))
		return false;


	for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
	{
		if ((iI == ePlayer) || (iI == getID()))
			continue;

		CvPlayer &kLoopPLayer = GET_PLAYER((PlayerTypes)iI);

		if (!kLoopPLayer.isAlive())
			continue;

		if (kLoopPLayer.isMinorCiv())
			continue;

		if (!GET_TEAM(getTeam()).isHasMet(kLoopPLayer.getTeam()))
			continue;

		if (!GET_TEAM(kPlayer.getTeam()).isHasMet(kLoopPLayer.getTeam()))
			continue;

		if (kPlayer.AI_getAttitude((PlayerTypes)iI) < ATTITUDE_CAUTIOUS) 
		{
				if (AI_getAttitude((PlayerTypes)iI) < ATTITUDE_CAUTIOUS)
				{
					return true;
				}
		}
	}

	return false;
}

All of my comments above may be very nice, but they don't explain how the line you highlighted would cause a CTD, however it may be easier to spot what is causing the issue when you step through the code.
 
Good thoughts. I'll rewrite the functions with the tweaks you suggested. Hopefully, it should then work.

In addition, two lines about the blue highlight of my re-written functions I have a check for ePlayer.isAlive.

Where did I write this: GET_PLAYER(ePlayer).getID()
I must be missing something.
 
Where did I write this: GET_PLAYER(ePlayer).getID()

PHP:
int CvPlayerAI::AI_getSharedEnemyAttitude(PlayerTypes ePlayer) const
{
	int iAttitude;
	iAttitude = 0;

	if (!atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
	{
===>	if (AI_SharedEnemy(GET_PLAYER(ePlayer).getID()))  <=== 
		{
			iAttitude += 1;
		}
	}

	return iAttitude;
}

Also noticed that there are some additional checks I could add and a missing return value. My updated code would be:

PHP:
int CvPlayerAI::AI_getSharedEnemyAttitude(PlayerTypes ePlayer) const
{
	CvPlayer& kPlayer = GET_PLAYER(ePlayer);
	if (kPlayer == NULL)
	{
		return 0;
	}
	
	if (GET_PLAYER(ePlayer).isAlive && !atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
	{
		return AI_sharedEnemy(ePlayer) ? 1 : 0;
	}
	
	return 0;
}

and

PHP:
bool CvPlayerAI::AI_sharedEnemy(PlayerTypes ePlayer) const
{
	if (getID() == ePlayer)
		return false;

	CvPlayer& kPlayer = GET_PLAYER(ePlayer);
		
	if (kPlayer == NULL)
		return false;

	if (!kPlayer.isAlive())
		return false;

	if (kPlayer.isMinorCiv())
		return false;

	if (!GET_TEAM(getTeam()).isHasMet(kPlayer.getTeam()))
		return false;


	for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
	{
		if ((iI == ePlayer) || (iI == getID()))
			continue;

		CvPlayer &kLoopPLayer = GET_PLAYER((PlayerTypes)iI);

		if (!kLoopPLayer.isAlive())
			continue;

		if (kLoopPLayer.isMinorCiv())
			continue;

		if (!GET_TEAM(getTeam()).isHasMet(kLoopPLayer.getTeam()))
			continue;

		if (!GET_TEAM(kPlayer.getTeam()).isHasMet(kLoopPLayer.getTeam()))
			continue;

		if (kPlayer.AI_getAttitude((PlayerTypes)iI) < ATTITUDE_CAUTIOUS) 
		{
				if (AI_getAttitude((PlayerTypes)iI) < ATTITUDE_CAUTIOUS)
				{
					return true;
				}
		}
	}

	return false;
}
 
Top Bottom