Another Python Error Message...

The Capo

godless Heathen
Joined
Jan 29, 2001
Messages
9,302
Location
Washington, DC
Hey guys, I really appreciate the help I got for my last python error but apparently I have another one that is related to it. It also involves the inquisitor unit. Anyway here is what the message said...

file "CvGameInterface", line 185, in AI_unitUpdate
file "CvGameUtils", line 313, in AI_unitUpdate
file "CvGameUtils", line 545, in doInquisitorCore_AI

RuntimeError: unidentifiable C++ exception


The last error I had was the AI deciding to build the Inquisitor, and it is confirmed that they do build them (there was a Zulu Inquisitor in Ulundi), the difference between this python error and the last one is that I don't really know what the error is referring to. So if someone could tell me what exactly this error is that would be helpful. Anyway, here is the code. Starting with CvGameInterface.py, which is the vanilla BtS file. These are lines 182 through 185:

Code:
def AI_unitUpdate(argsList):
	'AI moves units - return 0 to let AI handle it, return 1 to say that the move is handled in python '
	#CvUtil.pyPrint( "CvGameInterface.AI_unitUpdate" )
	return gameUtils().AI_unitUpdate(argsList)

And here lines 311 through 315 in the CvGameUtils.py, which is in the mod so I can edit this file:

Code:
		if not gc.getPlayer( iOwner ).isHuman( ):
			if pUnit.getUnitType( ) == iTaoInq or pUnit.getUnitType( ) == iConInq or pUnit.getUnitType( ) == iBudInq or pUnit.getUnitType( ) == iHinInq or pUnit.getUnitType( ) == iJudInq or pUnit.getUnitType( ) == iIslInq or pUnit.getUnitType( ) == iChrInq or pUnit.getUnitType( ) == iOlyInq or pUnit.getUnitType( ) == iAseInq or pUnit.getUnitType( ) == iVooInq or pUnit.getUnitType( ) == iShiInq or pUnit.getUnitType( ) == iZorInq or pUnit.getUnitType( ) == iRaaInq or pUnit.getUnitType( ) == iTolInq:
				self.doInquisitorCore_AI( pUnit )
				return True
		return False

And finally lines 539 through 551 of CvGameUtils.py:

Code:
		#Checks religion percents
		lReligions = [ ]
		bestReligionPercent = 0
		iBestReligion = -1
		for iReligionLoop in range(gc.getNumReligionInfos( )):
			iReligionLevel = gc.getGame().calculateReligionPercent(iReligionLoop)
			if iReligionLevel > gc.getGame().calculateReligionPercent(iStateReligion):
				lReligions.append( iReligionLoop )
			if (iReligionLoop != iStateReligion):
				religionPercent = gc.getGame().calculateReligionPercent(iReligionLoop)
				if (religionPercent > bestReligionPercent):
					bestReligionPercent = religionPercent
					iBestReligion = iReligionLoop

Basically in the mod I have fourteen religions, although the extra seven are only available in the 'choose religion' game option. For each religion there is a different Inquisitor, and here is a list of the inquisitors in the python files (in this case CvGameUtils.py, lines 293 through 309):

Code:
	def AI_unitUpdate(self,argsList):
		pUnit = argsList[0]
		iOwner = pUnit.getOwner( )
		iTaoInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_TAOIST_INQUISITOR" )
		iConInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_CONFUCIAN_INQUISITOR" )
		iBudInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_BUDDHIST_INQUISITOR" )
		iHinInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_HINDU_INQUISITOR" )
		iJudInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_JEWISH_INQUISITOR" )
		iChrInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_CHRISTIAN_INQUISITOR" )
		iIslInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_ISLAMIC_INQUISITOR" )
		iOlyInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_OLYMP_INQUISITOR" )
		iAseInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_ASEN_INQUISITOR" )
		iVooInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_VOODOO_INQUISITOR" )
		iShiInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_SHINTO_INQUISITOR" )
		iZorInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_ZORO_INQUISITOR" )
		iRaaInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_RA_INQUISITOR" )
		iTolInq = CvUtil.findInfoTypeNum( gc.getUnitInfo, gc.getNumUnitInfos(), "UNIT_TOLTEC_INQUISITOR" )

Anyway there is the information, if anyone sees why this issue is arising, or at least what it is dealing with please let me know. Thank you for your time.
 
Unidentifiable C++ exception typically means that an assertion failed. Assertions are checks put into the C++ code that enforce a particular state by "dying" if that state is violated.

Here is the problem line

Code:
if iReligionLevel > gc.getGame().calculateReligionPercent(iStateReligion)

My bet is that iStateReligion is NO_RELIGION (-1) in this case, and that calculateReligionPercent() doesn't allow it. It makes no sense for the "no religion" to have a spread percentage.

I guess that you want to evaluate all religions if the player has no state religion at the time. To do this, change lines 545 and 546 to this:

Code:
			if iStateReligion == -1 or iReligionLevel > gc.getGame().calculateReligionPercent(iStateReligion):
				lReligions.append( iReligionLoop )
 
Unidentifiable C++ exception typically means that an assertion failed. Assertions are checks put into the C++ code that enforce a particular state by "dying" if that state is violated.

i think there is a problem with your code. im playing a game and I have a state religion and theocracy civic and non-state religions just spammed in all my cities. time to remove the 'fix'.
 
I have a state religion and theocracy civic and non-state religions just spammed in all my cities.

Theocracy only blocks the spread of non-state religions by foreign missionaries. It may also block natural spread as well, but I can't say for sure. You are always free to spread any religion within your own empire.
 
CvCity::doReligion() blocks natural spread under theocracy-type civics. However, that behavior can be overridden by the Python doReligion() function and so could be different even under a non-SDK mod. I'm not really sure how modifieda4's post pertains to this topic though??
 
CvCity::doReligion() blocks natural spread under theocracy-type civics. However, that behavior can be overridden by the Python doReligion() function and so could be different even under a non-SDK mod. I'm not really sure how modifieda4's post pertains to this topic though??

I was pointing out that I implemented some code in this thread and then noticed a game behaviour which is wrong.

I believe theology blocks natrual and missionary spread of non-state religions.

In any case, in one turn all my cities got a non-state religion spread. Basically akin to a "religion bomb".

In the many hours of play (more like months, lol) I have never seen this happen. I attribute this to the code change.

Got it? :confused:
 
i think there is a problem with your code. . . . time to remove the 'fix'.

Then perhaps you can be more specific? What part of the code did you add, and how did you modify it from what's here? What is "the fix"?
 
My fix was to avoid a C++ exception. I suspect that the fix only allowed you to make it to more broken code that you would "avoid" by having the game crash. :D I didn't work on the original mod--just posted a drive-by bugfix.

If you remove the fix and load a save from the turn before, does it work or crash?
 
My fix was to avoid a C++ exception. I suspect that the fix only allowed you to make it to more broken code that you would "avoid" by having the game crash. :D I didn't work on the original mod--just posted a drive-by bugfix.

If you remove the fix and load a save from the turn before, does it work or crash?

funny thing is i never have gotten a python error or a crash before even though I have the inquisitor code in my mod.

And you make a good point, perhaps the faulty code was protecting EVEN more faulty code from executing, which your code 'fixed'.

and yes, removing the fix and reloading a saved game 'works' like before.
 
Well, I have implemented this fix in the latest Inquisition from OrionVeteran, and the python error is gone. I have not seen any weird behaviour yet - but then again, I have only run a handful of testgames.
 
Keep in mind that my fix doesn't take into account the intent of the surrounding code. It only stops you from passing in -1 as a state religion, which is invalid. The following fix would be equally ignorant of the purpose of the code, so maybe it's better:

Code:
if iStateReligion != -1 and iReligionLevel > gc.getGame().calculateReligionPercent(iStateReligion):
	lReligions.append( iReligionLoop )

The difference is what happens when the player has no state religion. My original fix would places all religions into the list in that case whereas this new fix results in an empty list.

What is the function that contains this code supposed to do? How is the list used after the block of code you posted? This is where descriptive code comments (and there may be comments, so more importantly context ;)) really help.
 
Keep in mind that my fix doesn't take into account the intent of the surrounding code. It only stops you from passing in -1 as a state religion, which is invalid. The following fix would be equally ignorant of the purpose of the code, so maybe it's better:

Code:
if iStateReligion != -1 and iReligionLevel > gc.getGame().calculateReligionPercent(iStateReligion):
	lReligions.append( iReligionLoop )

The difference is what happens when the player has no state religion. My original fix would places all religions into the list in that case whereas this new fix results in an empty list.

What is the function that contains this code supposed to do? How is the list used after the block of code you posted? This is where descriptive code comments (and there may be comments, so more importantly context ;)) really help.

when i get some spare time i might dig into the code a little bit :)
 
when i get some spare time i might dig into the code a little bit :)

Perhaps post the full function for context and a brief description of what it's supposed to do.
 
Perhaps post the full function for context and a brief description of what it's supposed to do.

Find the religion with the highest percentage

Code:
#Checks religion percents
lReligions = [ ]
bestReligionPercent = 0
iBestReligion = -1
for iReligionLoop in range(gc.getNumReligionInfos( )):
	iReligionLevel = gc.getGame().calculateReligionPercent(iReligionLoop)
	#if iReligionLevel > gc.getGame().calculateReligionPercent(iStateReligion):
	[COLOR="Red"]if iStateReligion != -1 or iReligionLevel > gc.getGame().calculateReligionPercent(iStateReligion):[/COLOR]
		lReligions.append( iReligionLoop )
	if (iReligionLoop != iStateReligion):
		religionPercent = gc.getGame().calculateReligionPercent(iReligionLoop)
		if (religionPercent > bestReligionPercent):
			bestReligionPercent = religionPercent
			iBestReligion = iReligionLoop

Is this the best way to run this check?

Orion Veteran :cool:
 
I only have a couple minutes here, so I skimmed the code quickly. I think you want to change the red line

Code:
if iStateReligion != -1 or iReligionLevel > gc.getGame().calculateReligionPercent(iStateReligion):

to use ==. Currently is says, "if they have a state religion or iReligionLevel > the state religion's percent", but if the first clause fails, it means they have no state religion, so the second clause will break.

Code:
if iStateReligion == -1 or iReligionLevel > gc.getGame().calculateReligionPercent(iStateReligion):

This adds each religion to the list if they have no state religion or the religion's percent is greater than the state's percent.

The part that tracks the best percent looks correct at a glance. You are calculating the loop religion's percent twice in the loop, and you are checking the state religion against itself, so this can be rewritten a little better (not tested):

Code:
#Checks religion percents
#will contain all non-state religions with a percent higher than the state's percent
#or all religions if there is no state religion
lReligions = [ ]
iBestReligionLevel = -1
iBestReligion = -1
if iStateReligion == -1:
	iStateReligionLevel = -1
else:
	iStateReligionLevel = gc.getGame().calculateReligionPercent(iStateReligion)
for iReligionLoop in range(gc.getNumReligionInfos( )):
	if iReligionLoop != iStateReligion:
		iReligionLevel = gc.getGame().calculateReligionPercent(iReligionLoop)
		if iReligionLevel > iStateReligionLevel:
			lReligions.append( iReligionLoop )
			if religionPercent > bestReligionPercent:
				iBestReligionLevel = iReligionLevel
				iBestReligion = iReligionLoop
 
Top Bottom