Weird python error with the flag/TeamAI.h

NotSoGood

Emperor
Joined
Jan 25, 2009
Messages
1,077
Location
Finland
I have added a new ideology system mainly just by copying the religion parts. I have built the dll without errors, and even the game loading goes fine without errors. But when I start a new game, I get infinite ammount of those python errors in the first screenshot. I tried using debug dll with VC attached and got a different error. See second screen.
I haven't changed anything in CvMainInterface that could cause the crash. Here's part of python logs
Spoiler :
Code:
Traceback (most recent call last):

  File "CvScreensInterface", line 717, in forceScreenRedraw

  File "CvMainInterface", line 706, in redraw

  File "CvMainInterface", line 1190, in updateFlag

RuntimeError: unidentifiable C++ exception
ERR: Python function forceScreenRedraw failed, module CvScreensInterface
Here's the function that is failing in python's oppinion with line 1190 in red
Spoiler :
Code:
	def updateFlag( self ):

		if ( CyInterface().getShowInterface() != InterfaceVisibility.INTERFACE_HIDE_ALL and CyInterface().getShowInterface() != InterfaceVisibility.INTERFACE_MINIMAP_ONLY and CyInterface().getShowInterface() != InterfaceVisibility.INTERFACE_ADVANCED_START ):
			screen = CyGInterfaceScreen( "MainInterface", CvScreenEnums.MAIN_INTERFACE )
			xResolution = screen.getXResolution()
			yResolution = screen.getYResolution()
			[COLOR="Red"]screen.addFlagWidgetGFC( "CivilizationFlag", xResolution - 288, yResolution - 138, 68, 250, gc.getGame().getActivePlayer(), WidgetTypes.WIDGET_FLAG, gc.getGame().getActivePlayer(), -1)[/COLOR]

The assert mentions CvTeamAI.h which I havent touched. Line 22 in red
Spoiler :
Code:
class CvTeamAI : public CvTeam
{

public:

	CvTeamAI();
	virtual ~CvTeamAI();

#ifdef _USRDLL
	// inlined for performance reasons, only in the dll
	static CvTeamAI& getTeam(TeamTypes eTeam)
	{
		[COLOR="Red"]FAssertMsg(eTeam != NO_TEAM, "eTeam is not assigned a valid value");[/COLOR]
		FAssertMsg(eTeam < MAX_TEAMS, "eTeam is not assigned a valid value");
		return m_aTeams[eTeam]; 
	}
#endif
	DllExport static CvTeamAI& getTeamNonInl(TeamTypes eTeam);

	static void initStatics();
	static void freeStatics();
I know there might be many places where the problem is, but does anyone have ideas how to narrow the search?
 
You may get many asserts from other modders' sdk code. This assert may be a false alarm. Click "ignore always", you may get one or two other asserts after this, keep clicking "ignore always". Eventually you should get to the same python errors. These asserts come even earlier in initialization than your first screen redraw (which is presumably where the python error is coming from.)

Then roll back to a dll with all the base mods you started with, but none of your own changed code, and start a game. Do you get the same asserts? Then ignore the asserts and focus on the python error. If you get different asserts with your code, then you should probably start by fixing the asserts you caused. When you get one, click "debug" and you should see your call stack.

Unfortunately I don't know specifically what causes your python error. It is a general error which says, somewhere along the line, some python code made a call to a C++ function and passed the wrong number/type of arguments.
 
You may get many asserts from other modders' sdk code. This assert may be a false alarm. Click "ignore always", you may get one or two other asserts after this, keep clicking "ignore always". Eventually you should get to the same python errors. These asserts come even earlier in initialization than your first screen redraw (which is presumably where the python error is coming from.)
I clicked ignore always and got lots of asserts that had somthing to with team or player. I attached few screen shots, but there was many others. But eventually I got to the same point where I got those python errors.

Then roll back to a dll with all the base mods you started with, but none of your own changed code, and start a game. Do you get the same asserts? Then ignore the asserts and focus on the python error. If you get different asserts with your code, then you should probably start by fixing the asserts you caused. When you get one, click "debug" and you should see your call stack.
Do you mean a dll without my new ideology system? Luckily I had backup dll on my computer. :D I tested it and didn't get the same python error neither the asserts. So is there actually something passing a null to the function in CvTeamAI.h? Why would there be a getTeam function in CvTeamAI? It's only in the header file not in cpp. So is there something different in this function?
 
OK, good. Now we know that the asserts are caused by your code. These are occuring before the python error. It is likely (but not guaranteed) that if you can find and fix the assert errors, the python errors will stop.

In your CvTeamAI.h spoiler you showed a line in red. This line, you did not change. But, it is warning you that whichever routine is calling getTeam is passing in an invalid value. What you need to do in the debugger is get the calling stack when this is happening, and investigate the calling routine to see why it is doing the wrong thing.

How familiar are you with C++ debugging? If you are not familiar, this may be a tough problem. If the code you added is calling getTeam, it may be easier to put print statements just before the calls, to print the value you are passing into a file. Then you can look in the file afterwards. But using the debugger is faster.
 
did you do a complete recompile after adding Support for your new XML file to the DLL? If you forget to do that you can get really strange errors.
 
did you do a complete recompile after adding Support for your new XML file to the DLL? If you forget to do that you can get really strange errors.
I don't remember anymore, but I recompiled it now and got the same assert.

OK, good. Now we know that the asserts are caused by your code. These are occuring before the python error. It is likely (but not guaranteed) that if you can find and fix the assert errors, the python errors will stop.

In your CvTeamAI.h spoiler you showed a line in red. This line, you did not change. But, it is warning you that whichever routine is calling getTeam is passing in an invalid value. What you need to do in the debugger is get the calling stack when this is happening, and investigate the calling routine to see why it is doing the wrong thing.

How familiar are you with C++ debugging? If you are not familiar, this may be a tough problem. If the code you added is calling getTeam, it may be easier to put print statements just before the calls, to print the value you are passing into a file. Then you can look in the file afterwards. But using the debugger is faster.
Well, unfortunately I'm not too familiar with it. Do you know any quides for it or can you teach me?
I attached a screenshot of VC when debugging. Does that give any help?
One thing that confuses me, is why there is so many getTeams? In the screenshot there is atleast three of them.
 
I think I got the idea how to debug. It required lots of trying, but i think I know where it fails. It seems to be between these lines
Code:
void CvGameAI::AI_updateAssignWork()
{
	int iI;

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iI);
		[COLOR="Red"]if (GET_TEAM(kLoopPlayer.getTeam()).isHuman() && kLoopPlayer.isAlive())[/COLOR]
		{
			kLoopPlayer.AI_updateAssignWork();
		}
	}
}
Code:
#ifdef _USRDLL
	// inlined for performance reasons, only in the dll
	static CvTeamAI& getTeam(TeamTypes eTeam)
	{
		[COLOR="red"]FAssertMsg(eTeam != NO_TEAM, "eTeam is not assigned a valid value");[/COLOR]
		FAssertMsg(eTeam < MAX_TEAMS, "eTeam is not assigned a valid value");
		return m_aTeams[eTeam]; 
	}
#endif
In getTeam VC shows that some function is passing a -1 as eTeam. It took closer look GET_PLAYER and it seems to be correct. So is GET_TEAM(kLoopPlayer.getTeam()) passing the null or did I do everything wrong?

EDIT: I think I was right. I debugged to get kLoopPlayer.getTeam() value, and it is passing -1. See screenshot. But why?
 
Wow, that first block of code is in the unmodded game! It definitely needs to check if each player is alive before calling getTeam() as that will return -1 if the player was never alive. Plus it shouldn't tell dead players to reassign their citizens. How does this not throw asserts for everyone?

Edit: Oh, I see it is checking isAlive(). It needs to reverse the checks:

Code:
void CvGameAI::AI_updateAssignWork()
{
	int iI;

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iI);
		if ([B][COLOR="Red"]kLoopPlayer.isAlive() && [/COLOR][/B]GET_TEAM(kLoopPlayer.getTeam()).isHuman())
		{
			kLoopPlayer.AI_updateAssignWork();
		}
	}
}

Edit2: I see that it is not called anywhere in the SDK. Did you add a call to this function in your code?

Edit3: WTF is this function doing? It's telling human teams only to update their working citizens! I guess AI teams will have their citizens always up-to-date. Whatever!
 
Wow, that first block of code is in the unmodded game! It definitely needs to check if each player is alive before calling getTeam() as that will return -1 if the player was never alive. Plus it shouldn't tell dead players to reassign their citizens. How does this not throw asserts for everyone?

Edit: Oh, I see it is checking isAlive(). It needs to reverse the checks:

Code:
void CvGameAI::AI_updateAssignWork()
{
	int iI;

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iI);
		if ([B][COLOR="Red"]kLoopPlayer.isAlive() && [/COLOR][/B]GET_TEAM(kLoopPlayer.getTeam()).isHuman())
		{
			kLoopPlayer.AI_updateAssignWork();
		}
	}
}

Edit2: I see that it is not called anywhere in the SDK. Did you add a call to this function in your code?

Edit3: WTF is this function doing? It's telling human teams only to update their working citizens! I guess AI teams will have their citizens always up-to-date. Whatever!

I don't get why I get assert only after I added my ideology system. And what DLL are you using? In the DLL I have this in CvGame.cpp
Spoiler :
Code:
void CvGame::update()
{
	PROFILE("CvGame::update");

	if (!gDLL->GetWorldBuilderMode() || isInAdvancedStart())
	{
		sendPlayerOptions();

		// sample generic event
		CyArgsList pyArgs;
		pyArgs.add(getTurnSlice());
		CvEventReporter::getInstance().genericEvent("gameUpdate", pyArgs.makeFunctionArgs());

		if (getTurnSlice() == 0)
		{
			gDLL->getEngineIFace()->AutoSave(true);
		}

		if (getNumGameTurnActive() == 0)
		{
			if (!isPbem() || !getPbemTurnSent())
			{
				doTurn();
			}
		}

		updateScore();

		updateWar();

		updateMoves();

		updateTimers();

		updateTurnTimer();

		[COLOR="Red"]AI_updateAssignWork();[/COLOR]

		testAlive();

		if ((getAIAutoPlay() == 0) && !(gDLL->GetAutorun()) && GAMESTATE_EXTENDED != getGameState())
		{
			if (countHumanPlayersAlive() == 0)
			{
				setGameState(GAMESTATE_OVER);
			}
		}

		changeTurnSlice(1);

		if (NO_PLAYER != getActivePlayer() && GET_PLAYER(getActivePlayer()).getAdvancedStartPoints() >= 0 && !gDLL->getInterfaceIFace()->isInAdvancedStart())
		{
			gDLL->getInterfaceIFace()->setInAdvancedStart(true);
			gDLL->getInterfaceIFace()->setWorldBuilder(true);
		}
	}
}
But I'll try swaping their places.

And the function does seem pretty pointless.
 
Ah, VS didn't detect its usage because it is a virtual function (declared in CvGame but implemented in CvGameAI). Were you running a debug DLL without your changes? You will only see asserts when running a debug DLL.
 
Were you running a debug DLL without your changes? You will only see asserts when running a debug DLL.

Yes.
I'm currently rebuilding the debug dll with the changed line you suggested. Slow computer... :cry:

EDIT: Got pass that assert but got another with CvPlot::updateFog()
Code:
void CvPlot::updateFog()
{
	//PROFILE_FUNC();

	if (!GC.IsGraphicsInitialized())
	{
		return;
	}

	[COLOR="Red"]FAssert(GC.getGameINLINE().getActiveTeam() != NO_TEAM);[/COLOR]

	if (isRevealed(GC.getGameINLINE().getActiveTeam(), false))
	{
		if (gDLL->getInterfaceIFace()->isBareMapMode())
		{
			gDLL->getEngineIFace()->LightenVisibility(getFOWIndex());
		}
		else
...
This drives me nuts. Asserts after asserts. :mad:
But I noticed that doesn't that flag code in the OP use getActiveTeam? The assert few posts above uses getTeam and this one getActiveTeam. They all have something to do with teams! :eek: Any ideas?
 
I once had the exact same problem when I merged something that had not much to do with teams (but lots of hacks here and there that can cause a bug like this). I ended up to rewrite the code I wanted to merge and the problem never happened again. I suggest you go back to a stable version of your dll and then redo all your changes and possible also post them here in a thread so someone can take a look at them.
 
The active team is the player sitting at the computer. In a single player game, it is always the single human player. In a multiplayer LAN/INTERNET game, it is the human player that owns each machine (i.e. on my machine it's me and your machine it's you). In a HOTSEAT game, it switches as each human takes their turn. Even in a PITBOSS game I think it has a valid value, but I'm not sure about that.

The only time it is NO_TEAM is when there is no game active! What is the code that you're merging, and how is it breaking the game so completely?:crazyeye:
 
I once had the exact same problem when I merged something that had not much to do with teams (but lots of hacks here and there that can cause a bug like this). I ended up to rewrite the code I wanted to merge and the problem never happened again. I suggest you go back to a stable version of your dll and then redo all your changes and possible also post them here in a thread so someone can take a look at them.
I'm not too fond of adding the code again. It took hours and days of work. And I have changes in 279 different places. :cry:

The only time it is NO_TEAM is when there is no game active! What is the code that you're merging, and how is it breaking the game so completely?:crazyeye:
I don't understand that either. All I have done is copyed most of the religion parts to create a new system for ideologies. I chaged few and added few things, recompiling currently.

EDIT: No, still got bunch of asserts with getTeam or getActiveTeam. :dunno: Does anyone have ideas how could I hunt down the source of this error without staring from begining?
 
From the asserts you have posted, it seems that something you did has made a big change in the order of operations at the start of the game. If you can't trace upwards from the asserts to find out what you changed, the only other thing to do is start with smaller changes. It is frustrating, I agree. But programmers with years of experience start small and build. Add one small thing. Does it work? Add a second small thing. Does the first thing still work? Now test the second thing. This is how big projects get done.
 
I'm not too fond of adding the code again. It took hours and days of work. And I have changes in 279 different places. :cry:
do you have a backup from a few days ago when the problem wasn't around? Else try to comment all changes you did related to your last project.
 
I started to redo the ideology system and now I've managed to get the civilopedia to work. But, do you have any suggestions what should I do next? Mayby add what happens when you discover the tech the ideology requires?
 
If you list out all the things you need to do, we can perhaps give some direction on which to do first. I'm talking high-level here, so "each ideology has a single prereq tech" is a good start.
 
Ok, I'm not sure what all things I need to do but I think here's most of them:
  • create the screen for ideologies (done)
  • let players have ideologies (done)
  • display player's ideology (done partly)
  • add effects to ideologies (started)
  • let players choose/convert ideologies (done)
  • add a popup when discovering the tech that ideology requires (done)
  • change attitudes with leaders' having different ideologies
  • AI code with choosing the ideologies
  • spreading ideologies (started)
  • "prefered ideology" tag in leaderheadinfos
That's all that comes in my mind. Do I have to add anything else and what order should I add them?
 
Top Bottom