Small Python Issue.

The Capo

godless Heathen
Joined
Jan 29, 2001
Messages
9,302
Location
Washington, DC
Hey, I'm working on this mod and I am in the process of playtesting it and getting rid of bugs, but there is one I don't know how to fix. It looks like its simple though, but I don't have a lot of python experience. Anyway the problem seems to arise with the AI either building, or deciding to build, an Inquisitor unit. Here is the Python error message;

file "CvGameInterface", line 180, in AI_chooseProduction
file "CVGameUtils", line 269, in AI_chooseProduction

TypeError: 'NoneType' object is not callable

Alright, well in the mod I am using I don't have a CvGameInterface.py file, so I assume that refers to the vanilla BtS file. Here is the code surrounding and including line 180:

Code:
def AI_chooseProduction(argsList):
	'AI chooses city production'
	#CvUtil.pyPrint( "CvGameInterface.AI_chooseProduction" )
	return gameUtils().AI_chooseProduction(argsList)

In my mod this is the code I have surrounding and including line 180 in the CvGameUtils.py file:

Code:
		if not iStateReligion == -1 :
			#if gc.getPlayer( iOwner ).getStateReligion( ) >= 0:
			if pCity.canTrain( iTaoInq, 0, 0 ) or pCity.canTrain( iConInq, 0, 0 ) or pCity.canTrain( iJudInq, 0, 0 ) or pCity.canTrain( iHinInq, 0, 0 ) or pCity.canTrain( iBudInq, 0, 0 ) or pCity.canTrain( iIslInq, 0, 0 ) or pCity.canTrain( iChrInq, 0, 0 ) or pCity.canTrain( iOlyInq, 0, 0 ) or pCity.canTrain( iAseInq, 0, 0 ) or pCity.canTrain( iVooInq, 0, 0 ) or pCity.canTrain( iShiInq, 0, 0 ) or pCity.canTrain( iZorInq, 0, 0 ) or pCity.canTrain( iRaaInq, 0, 0 ) or pCity.canTrain( iTolInq, 0, 0 ):
				lUnits = PyPlayer( pPlayer.getID( ) ).getUnitList( )
				for iUnit in range( len( lUnits) ):
					# if there are any Inquisitors, don't Build one
					if pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iJudInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iChrInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iIslInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iHinInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iBudInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iConInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iTaoInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iOlyInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iAseInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iVooInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iShiInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iZorInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iRaaInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iTolInq:
						return False
				if self.getRandomNumber( 2 ) == 0:
					iInqVersions = { "1": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iJudInq, -1, False, False, False, True ), "2": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iChrInq, -1, False, False, False, True ), "3": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iIslInq, -1, False, False, False, True ), "4": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iHinInq, -1, False, False, False, True ), "5": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iBudInq, -1, False, False, False, True ), "6": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iConInq, -1, False, False, False, True ), "7": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iTaoInq, -1, False, False, False, True ), "8": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iOlyInq, -1, False, False, False, True ), "9": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iAseInq, -1, False, False, False, True ), "10": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iVooInq, -1, False, False, False, True ), "11": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iShiInq, -1, False, False, False, True ), "12": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iZorInq, -1, False, False, False, True ), "13": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iRaaInq, -1, False, False, False, True ), "14": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iTolInq, -1, False, False, False, True )}
					iInqVersions.get( pPlayer.getStateReligion( ), ) ()
					return True
		return False

Line 269 in this (the one in question) is the line that says:

Code:
					iInqVersions.get( pPlayer.getStateReligion( ), ) ()

Can anybody help me with this?
 
First things first.

'NoneType' object is not callable​

"NoneType" refers to Python's builtin special value "None". You can assign this value to a variable.

a = None​

and it is the value returned by a function if it doesn't return some other value

Code:
def getX():
    print 2

a = getX()

In both examples, a has the special value None.

"is not callable" means that you are treating a value (in this case the special value "None") as a callable function (like getX in my second example) by putting parenthesis after it. "getX" is a callable function; "getX()" actually calls that function.

Looking at the problem line again

iInqVersions.get( pPlayer.getStateReligion( ), ) ()

we see that you are calling the function get() on iInqVersions (a dictionary you created on the line above). The comma is ignored since you do not pass in a parameter after it, so essentially you are using pPlayer.getStateReligion() as the key in the dictionary and then treating the value returned from it as a function by trying to call it.

The problem is that the values in the dictionary are the return results from the various pushOrder() calls. Yes, the line that builds the dictionary actually performs all those pushOrder() calls, and I suspect that pushOrder() doesn't actually have a return value.

Also, you must drop the quotes around the numbers since getStateReligion() returns a number. So this is also a problem. The lookup in the dictionary will never find a value (strings are not numbers), and all the values are None anyway.

I think what you're trying to do is choose which pushOrder() call to make, and in this case what you want is something like this (noticing that the unit type is the only thing that differs between all the pushOrder() calls):

Code:
iInqVersions = {
    1: iJudInq,
    2: iChrInq,
    ...
    14: iTolInq,
}
eReligion = pPlayer.getStateReligion()
if eReligion in iInqVersions:
    eUnit = iInqVersions[eReligion]
    gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, eUnit, -1, False, False, False, True )
else:
    # unknown religion

The if test is defensive coding to catch bugs and allow your mod to be graceful when it breaks. :)
 
I don't get it, so what am I supposed to replace with what?

Replace these two lines

Code:
iInqVersions = ...
iInqVersions.get( ...

with the code I posted above. However, drop the last two lines of my code: the "else" line and the comment after it. Also, make sure to indent it to the same level as the lines surrounding it as appropriate.
 
Okay, I am going to attempt to get you straight here. I have no idea what I am doing, so sorry if I am being annoying. So there is a part that says this...

Code:
					iInqVersions = { "1": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iJudInq, -1, False, False, False, True ), "2": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iChrInq, -1, False, False, False, True ), "3": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iIslInq, -1, False, False, False, True ), "4": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iHinInq, -1, False, False, False, True ), "5": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iBudInq, -1, False, False, False, True ), "6": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iConInq, -1, False, False, False, True ), "7": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iTaoInq, -1, False, False, False, True ), "8": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iOlyInq, -1, False, False, False, True ), "9": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iAseInq, -1, False, False, False, True ), "10": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iVooInq, -1, False, False, False, True ), "11": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iShiInq, -1, False, False, False, True ), "12": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iZorInq, -1, False, False, False, True ), "13": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iRaaInq, -1, False, False, False, True ), "14": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iTolInq, -1, False, False, False, True )}

Now, you want me to make it say this?

Code:
					iInqVersions = { "1": iJudInq,
                                                                                     "2": iChrInq,                                                                                       
.......
                                                                                      "14": iTolInq,
                                                                                       }

?

That's it?

Then this part in the CvGameUtils file I have this:

Code:
		if not iStateReligion == -1 :
			#if gc.getPlayer( iOwner ).getStateReligion( ) >= 0:
			if pCity.canTrain( iTaoInq, 0, 0 ) or pCity.canTrain( iConInq, 0, 0 ) or pCity.canTrain( iJudInq, 0, 0 ) or pCity.canTrain( iHinInq, 0, 0 ) or pCity.canTrain( iBudInq, 0, 0 ) or pCity.canTrain( iIslInq, 0, 0 ) or pCity.canTrain( iChrInq, 0, 0 ) or pCity.canTrain( iOlyInq, 0, 0 ) or pCity.canTrain( iAseInq, 0, 0 ) or pCity.canTrain( iVooInq, 0, 0 ) or pCity.canTrain( iShiInq, 0, 0 ) or pCity.canTrain( iZorInq, 0, 0 ) or pCity.canTrain( iRaaInq, 0, 0 ) or pCity.canTrain( iTolInq, 0, 0 ):
				lUnits = PyPlayer( pPlayer.getID( ) ).getUnitList( )
				for iUnit in range( len( lUnits) ):
					# if there are any Inquisitors, don't Build one
					if pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iJudInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iChrInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iIslInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iHinInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iBudInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iConInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iTaoInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iOlyInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iAseInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iVooInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iShiInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iZorInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iRaaInq or pPlayer.getUnit( lUnits[ iUnit ].getID( ) ).getUnitType( ) == iTolInq:
						return False
				if self.getRandomNumber( 2 ) == 0:
					iInqVersions = { "1": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iJudInq, -1, False, False, False, True ), "2": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iChrInq, -1, False, False, False, True ), "3": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iIslInq, -1, False, False, False, True ), "4": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iHinInq, -1, False, False, False, True ), "5": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iBudInq, -1, False, False, False, True ), "6": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iConInq, -1, False, False, False, True ), "7": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iTaoInq, -1, False, False, False, True ), "8": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iOlyInq, -1, False, False, False, True ), "9": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iAseInq, -1, False, False, False, True ), "10": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iVooInq, -1, False, False, False, True ), "11": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iShiInq, -1, False, False, False, True ), "12": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iZorInq, -1, False, False, False, True ), "13": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iRaaInq, -1, False, False, False, True ), "14": gc.getMap( ).plot( pCity.getX( ), pCity.getY( ) ).getPlotCity( ).pushOrder( OrderTypes.ORDER_TRAIN, iTolInq, -1, False, False, False, True )}
					iInqVersions.get( pPlayer.getStateReligion( ), ) ()
					return True
		return False

And you want me to replace the part that says iInqVersions.get(pPlayer.getStateReilgion( ), ) () With what?

This?

Code:
					iInqVersions.get( pPlayer.getStateReligion( )  ) ()

Because that's what it looks like you are saying, and it doesn't look like it makes sense. So I probably misunderstand you entirely.
 
Replace the entire second block of code that you posted with this:

Code:
		inqUnitIDs = (
			iJudInq,
			iChrInq,
			iIslInq,
			iHinInq,
			iBudInq,
			iConInq,
			iTaoInq,
			iOlyInq,
			iAseInq,
			iVooInq,
			iShiInq,
			iZorInq,
			iRaaInq,
			iTolInq,
		)
		if not iStateReligion == -1 :
			for iInqUnit in iInqUnitIDs:
				if pCity.canTrain( iInqUnit, False, False ):
					break
			else:
				# cannot train any inquisitors
				return False
			lUnits = PyPlayer( pPlayer.getID( ) ).getUnitList( )
			for pUnit in lUnits:
				# if there are any Inquisitors, don't Build one
				if pUnit.getUnitType( ) in inqUnitIDs:
					return False
			if self.getRandomNumber( 2 ) == 0:
				iInqUnit = iInqUnitIDs[ pPlayer.getStateReligion( ) ]
				pCity.pushOrder( OrderTypes.ORDER_TRAIN, iInqUnit, -1, False, False, False, True )
				return True
		return False
 
Oh, you didn't mean literally put the numbers there. Sorry I'm totally ******ed when it comes to this stuff. Unfortunately I have to play a game all the way up to Theology just to see if it works properly.

But I REALLY appreciate you taking the time to help me out with this, even if I seem annoying or idiotic, its a huge help and there is a large number of people who are waiting on this mod that I can thank you on behalf of as well.

Oh yeah, sorry, when you say "second block of text" you mean in my first post the second cell I posted right?
 
I put replaced my code in post 1, cell two, with your code and I got a python error pop up that said:

file "CvGameInterface", line 180, in AI_chooseProduction
file "CvGameUtils", line 276, in AI_choose Production

NameError: global name 'iInqUnitIDs' is not defined
 
file "CvGameInterface", line 180, in AI_chooseProduction
file "CvGameUtils", line 276, in AI_choose Production

NameError: global name 'iInqUnitIDs' is not defined

No worries, glad to help. The more information you can provide up front, the better I can help. In this case, which line is 276?

Luckily, I can see the error I created. I named the list of inquisitor unit IDs "inqUnitIDs" but referred to it as "iInqUnitIDs". Change all cases of the latter with the former.

Code:
		inqUnitIDs = (
			iJudInq,
			iChrInq,
			iIslInq,
			iHinInq,
			iBudInq,
			iConInq,
			iTaoInq,
			iOlyInq,
			iAseInq,
			iVooInq,
			iShiInq,
			iZorInq,
			iRaaInq,
			iTolInq,
		)
		if not iStateReligion == -1 :
			for iInqUnit in inqUnitIDs:
				if pCity.canTrain( iInqUnit, False, False ):
					break
			else:
				# cannot train any inquisitors
				return False
			lUnits = PyPlayer( pPlayer.getID( ) ).getUnitList( )
			for pUnit in lUnits:
				# if there are any Inquisitors, don't Build one
				if pUnit.getUnitType( ) in inqUnitIDs:
					return False
			if self.getRandomNumber( 2 ) == 0:
				iInqUnit = inqUnitIDs[ pPlayer.getStateReligion( ) ]
				pCity.pushOrder( OrderTypes.ORDER_TRAIN, iInqUnit, -1, False, False, False, True )
				return True
		return False
 
So far there are no python errors, which is good.

Although everytime I've randomly checked the WB it doesn't seem any of the AI is building Inquisitors, although that could be based on a few things;

1) There really isn't much religious overlap by enemies, which means they may not have a reason to build them. Although this overlap could be due to Inquisitors.

2) Inquisitors require a cathedral, and many nations (not all though) don't have music yet.

3) While I haven't seen inquisitors "in the field," they get destroyed upon mission completion, which is inconclusive.

But despite that no erros, so I want to thank you for helping me.
 
Top Bottom