Python Help please

ZeroRange

Chieftain
Joined
Dec 26, 2004
Messages
39
Location
DeKalb
I need some Python help, I really don't know how to program it and I'm trying to get this to work. It's a bit of code that gives a certain Tech when open borders is set up between to Civs or War is declared. I already made the Tech Smallpox, XML is 1000% easier than python.

Spoiler :
def onBeginPlayerTurn(self, argsList):
iGameTurn, iPlayer = argsList
player = gc.getPlayer(iPlayer)
cutOut = False
for iTeam in range(gc.getMAX_TEAMS()):
oTeam = gc.getTeam(iTeam)
eTeam = gc.getTeam(player.getTeam())
if ( oTeam.isHasTech(iSmallpox) and oTeam.isOpenBorders(iTeam) == True):
for i in range(player.):
self.giveTech(iSmallpox, oTeam)
else:
for i in range(player.):
return
 
...erm, am i right, that only 1 special tech is given? Everytime?

You have to assign the integer-value for iSmallpox.
Try at the beginning
PHP:
iSmallpox = gc.getInfoTypeForString( 'TECH_SMALLPOX' )

(or however you called your tech exactly)

edit:
and change self.giveTech to eTeam.setHasTech(iSmallpox,true,oTeam,false,true)
 
I tried, it didn't work. Everyone is starting with the Smallpox Tech I want a few Civ's to start with it and everyone else gets it when they open borders with someone with it. I feel like I made some sort of logic error here.
 
Change your [spoiler][/spoiler] tags to [code][/code], or at least use both sets [spoiler][code][/code][/spoiler]. I am curious what you are doing at the very end of the function where you seem to cycle over all players, returning each time. Which since return stops the entire function, will actually just choose the first player, then stop everything. Though looking closer that isn't even true, you should just get an error for doing an "i in range player." since I don't know what values i will wind up with from such a thing.
 
Following your suggestions and some experimentation I made this,
Code:
             def onBeginPlayerTurn(self, argsList):
                iGameTurn, iPlayer = argsList
                player = gc.getPlayer(iPlayer)
                cutOut = False
                for iTeam in range(gc.getMAX_TEAMS()):
                        iSMALLPOX = gc.getInfoTypeForString( 'TECH_SMALLPOX' )
                        oTeam = gc.getTeam(iTeam)
                        eTeam = gc.getTeam(player.getTeam())
                        if ( oTeam.isHasTech(iSMALLPOX) and oTeam.isHasOpenBorders(eTeam) == True): player.HasTech(iSMALLPOX,True,oTeam,False,True)
                        else: player.HasTech(iSMALLPOX,False,oTeam,False,True)
It gives everyone the Tech Smallpox. I think My logic is messed up and "HasOpenBorders" is giving to everyone because no matter what kind of changes I make everyone still starts with Smallpox.

In the Desert War mod they use similar language as a Helper.
Spoiler :
Code:
def giveTech( self, iTech, iPlayer ):
		"""Gives advance iTech to iPlayer."""
		iTeam = gc.getPlayer(iPlayer).getTeam()
		gc.getTeam(iTeam).setHasTech(iTech, True, 0, False, False)
I don't know enough about this to say if making a helper (giveTech?) would really help.
 
Define iSMALLPOX before you do the loop, since you never re-define it. same with eTeam.

player.HasTech...? Should be player.setHasTech. Odd that it would work with that command at all.

Otherwise it seems to be fairly correct. Though you shouldn't say (iSMALLPOX,False,oTeam,False,True). You should use (iSMALLPOX,False,iPlayer,False,True)


Whichever player you identify in that spot has their research progress for this tech set to 0 and gains any bonuses the tech might give (free units and whatnot)
 
I made the changes, Same Thing, everyone starts with Smallpox.

Code:
def onBeginPlayerTurn(self, argsList):
                iGameTurn, iPlayer = argsList
                player = gc.getPlayer(iPlayer)
                iSMALLPOX = gc.getInfoTypeForString( 'TECH_SMALLPOX' )
                oTeam = gc.getTeam(iTeam)
                eTeam = gc.getTeam(player.getTeam())
                cutOut = False
                for iTeam in range(gc.getMAX_TEAMS()):
                        iSMALLPOX = gc.getInfoTypeForString( 'TECH_SMALLPOX' )
                        oTeam = gc.getTeam(iTeam)
                        eTeam = gc.getTeam(player.getTeam())
                        if ( oTeam.isHasTech(iSMALLPOX) and oTeam.isHasOpenBorders(eTeam) == True): player.setHasTech(iSMALLPOX,True,oTeam,False,True)
                        else: player.setHasTech(iSMALLPOX,False,iplayer,False,True)
 
As I can see in the last version of your code there is a lot of redundant code lines besides some that are not needed in the first place:

Code:
onBeginPlayerTurn(self, argsList):
                iGameTurn, iPlayer = argsList
                player = gc.getPlayer(iPlayer)
                iSMALLPOX = gc.getInfoTypeForString( 'TECH_SMALLPOX' )
                eTeam = gc.getTeam(player.getTeam())

                for iTeam in range(gc.getMAX_TEAMS()):
                        oTeam = gc.getTeam(iTeam)
                        if (oTeam.isHasOpenBorders(eTeam)):
                                if( oTeam.isHasTech(iSMALLPOX):
                                         eTeam.setHasTech(iSMALLPOX,False,iPlayer,False,True)
                                         break

edit: forgot to change the setHasTech call. I copied the new one from xienwolf. (I didn't check this one myself). I revised code logic so accuracy of function arguments should be checked against API.

All civs end up having the tech because you do give them the tech no matter what in your original code.

edit2: going back to python API I found no setHasTech for CyPlayer class but it is defined for CyTeam. The API documentation is not complete but using the team makes more sense (otherwise why you pass the player ID as an argument to the function).
 
Kalimakhus, I wanted the Tech (Smallpox) to spread only through open borders and do so automatically. I'm starting to think its not possible and I need to find another way.

I tested your code, which is much easier to understand then mine thanks for the help, and it gave the Tech to everyone first turn.

Spoiler :
(You missed a ")" third line from the bottom.)
 
The line

Code:
eTeam = gc.getTeam(player.getTeam())

assigns the CyTeam of the player to eTeam. However, you pass eTeam to isHasOpenBorders() which wants a TeamTypes (int) here:

Code:
if (oTeam.isHasOpenBorders(eTeam)):

Note: The "e" prefix typically denotes an int enumeration (TeamTypes in this case). Above it you use iPlayer instead of ePlayer, so I'd stick with i for now. Also, it helps to put adjectives in your variable names when you have multiple objects of the same type.​

This would cause an error if isHasOpenBorders() was the function's name. However, it's isOpenBorders() (no Has).

Finally, in the call to setHasTech() you are passing False as the parameter for bNewValue. This would result in taking away SP.

All this doesn't explain why SP is being passed to all players given that the function will not do anything. I wonder what happens if you remove this code entirely. I suspect you are assigned SP to all teams somewhere else.

Here's my untested version:

Code:
onBeginPlayerTurn(self, argsList):
        iGameTurn, iPlayer = argsList
        player = gc.getPlayer(iPlayer)
        iSMALLPOX = gc.getInfoTypeForString( 'TECH_SMALLPOX' )
        iTeam = player.getTeam()
        oTeam = gc.getTeam(iTeam)

        if not oTeam.isHasTech(iSMALLPOX):
                for iLoopTeam in range(gc.getMAX_TEAMS()):
                        if iLoopTeam != iTeam:
                                oLoopTeam = gc.getTeam(iLoopTeam)
                                if oLoopTeam.isAlive() and not oLoopTeam.isBarbarian() and oTeam.isOpenBorders(iLoopTeam):
                                        if oLoopTeam.isHasTech(iSMALLPOX):
                                                 oTeam.setHasTech(iSMALLPOX, True, iPlayer, False, True)
                                                 break

All of the above points out the importance of looking at the log files. Logs/PythonErr.log should show you the stack traces from Python where the problem occurs. You can't always depend on watching what happens in the game. Also, you still need to figure out what is granting SP to everyone because the code in this thread isn't doing it.
 
Xienwolf, theres an XML line to Disable Techs, it was used on the desert war mod,
Spoiler :
<iTradeRoutes>0</iTradeRoutes>
<iHealth>0</iHealth>
<iHappiness>0</iHappiness>
<iFirstFreeTechs>0</iFirstFreeTechs>
<iAsset>8</iAsset>
<iPower>0</iPower>
<bRepeat>0</bRepeat>
<bTrade>0</bTrade>
<bDisable>0</bDisable>
<bGoodyTech>0</bGoodyTech>
<bExtraWaterSeeFrom>0</bExtraWaterSeeFrom>


The cost is set to 9999 also, I thought the game couldn't auto-Grant a Tech.

EmperorFool, I'm Isolating my tech in a new mod to troubleshoot, I'll get back to you on that ASAP. I gave it the SP removal (Else) to see if the program needed a logical way out to, I thought that was causing the everyone gets SP. I actually want it to give permenent effects. How do I look at Logs/PythonErr.log ?
 
Kalimakhus, I wanted the Tech (Smallpox) to spread only through open borders and do so automatically. I'm starting to think its not possible and I need to find another way.

I tested your code, which is much easier to understand then mine thanks for the help, and it gave the Tech to everyone first turn.

Spoiler :
(You missed a ")" third line from the bottom.)

First, sorry for the missing ")". The code however can never give the tech to everybody so I also believe that something else in your files either xml or python causes the tech to be given to everybody. Emperor Fool is a much better python programmer than myself and his code is much better. I only think that checking for the player to be alive is redundant as once a player is dead open borders agreements are canceled so it might be enough to check for open borders. Also under normal circumstances barbarians won't have open borders with any team (unless it is changed by some mod) so the check for the player to be barbarian can also be skippend IMO.
 
You guys were right I reinstalled Warlords and the problem went away! I'm going to test further to make sure the code works and repost. Thanks! No more programing in the A.M. for me.
 
I only think that checking for the player to be alive is redundant as once a player is dead open borders agreements are canceled so it might be enough to check for open borders. Also under normal circumstances barbarians won't have open borders with any team (unless it is changed by some mod) so the check for the player to be barbarian can also be skippend IMO.

I agree that they are probably redundant. However, all the original Python code does these checks, and I don't like making assumptions about code I haven't written. Thus it's just a habit for me to add those checks (defensive programming). If they were expensive calls, I'd think twice about adding them.

How do I look at Logs/PythonErr.log ?

The Logs folder is in your "My Games/Beyond the Sword" folder. If there is no PythonErr.log file (not the one with the 2 in it), turn on logging in the CivilizationIV.ini file by changing LoggingEnabled from 0 to 1:

Code:
LoggingEnabled = [B]1[/B]
 
My Late night/early morning mistake was changing the Techinfo XML line for Era to None, it didn't cause it to crash but it made everyone start with the Tech.

I enabled logging and was hoping for it to work, it didn't. This is what the log said;
that I'm sure is from this code the rest of it looks like routine functions.
Code:
  File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

About 20% of the log
Spoiler :

Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

File "CvEventInterface", line 23, in onEvent

File "CvEventManager", line 214, in handleEvent

File "CvEventManager", line 393, in onBeginPlayerTurn

File "ModFunctions", line 191, in onBeginPlayerTurn

AttributeError: 'CyTeam' object has no attribute 'isHasOpenBorders'
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):
 
Yes, all civs auto-start with any tech from previous Eras. Problem is, you ALSO automatically move INTO any era for a tech which you gain. So to avoid auto-starting with the tech on advanced start games, I would say set it to ERA_FUTURE. But then you need to start your function by checking which era the player is in right now, then if you do grant them smallpox, force them back into their original era.


And yeah, all of those errors you posted are just as EF said, you just need to ditch the "Has" portion of the command.
 
I ditched the "Has" and this is the log,

Code:
ArgumentError: Python argument types in
    CyTeam.isOpenBorders(CyTeam, CyTeam)
did not match C++ signature:
    isOpenBorders(class CyTeam {lvalue}, int)
ERR: Python function onEvent failed, module CvEventInterface
Traceback (most recent call last):

Code I tried
Code:
        def onBeginPlayerTurn(self, argsList):
                iGameTurn, iPlayer = argsList
                player = gc.getPlayer(iPlayer)
                iSMALLPOX = gc.getInfoTypeForString( 'TECH_SMALLPOX' )
                eTeam = gc.getTeam(player.getTeam())

                for iTeam in range(gc.getMAX_TEAMS()):
                        oTeam = gc.getTeam(iTeam)
                        if (oTeam.isOpenBorders(eTeam)):
                                if( oTeam.isHasTech(iSMALLPOX)):
                                         eTeam.setHasTech(iSMALLPOX,False,iPlayer,False,True)
                                         break

I looks like it thinks its getting code similar to "isOpenBorders(Team,oTeam)" It wants code that's similar to is OpenBorders(Team, Integer). I'll experiment with this. However, This would be the second ErrLog I've looked at so I might be wrong. I'm going to give it a shot. I'll post if I make it work

Edit: Adding an integer doesn't work
 
xienwolf is right. The formal signature of a C++ member (i.e. belongs to a class) function always has an implied pointer to the object itself. In this case a pointer to oTeam is passed implicitly as the first argument. The second integer argument is the ID of the team you want to check if oTeam has open borders with.
 
Back
Top Bottom