[PYTHON] Python Newbie Question

OzzyKP

Emperor
Joined
Dec 16, 2000
Messages
1,827
Location
Washington, DC USA
I'm making my first attempt to do something in Python and... I'm lost.

I'd like to have a worker created, owned by a particular AI civ when a corporation spreads to a city. My hope is to have corporations spread & operate independently, and have them build rail lines on their own.

I have never done anything in Python before (or much coding period), so I'd love some advice & help. This is the best I've come up with:

Code:
    def onCorporationSpread(self, argsList):
        'Corporation Has Spread to a City'
        iCorporation, iOwner, pSpreadCity = argsList
        iRailCorp = gc.getInfoTypeForString('CORPORATION_1')
        player = PyPlayer(iOwner)
    
        if iCorporation == iRailCorp
            CyInterface().addImmediateMessage("Railroad Corp has expanded into your city and will get to work building the rails", "")
            newUnit = playerY.initUnit(gc.getInfoTypeForString('UNIT_WORKER'), UnitAITypes.NO_UNITAI)

At this point I was just hoping to spawn a unit to show that I could make Python do anything at all, I hadn't even begun to worry about assigning it to a certain player. I copy and pasted pieces from other mods, and I've tried it a few different ways, but nothing ever happens. Clearly I'm missing some basic understanding of python.

On the plus side, nothing crashes! It just doesn't do anything.
 
Are you sure that the callback is even triggering ? Which mod (or perhaps "stock" BTS) are you using ?
Heh, im such a newbie I don’t know what your first sentence even means. But no, I’m not sure if anything.

I added this to my Fractured States mod which I don’t think has any other python changes, just XML so far.
 
newUnit = playerY.initUnit

I know more about the geography of the planetary mantle than I do python, but isn't "playerY" wrong; it's declared as just "player" above
 
newUnit = playerY.initUnit

I know more about the geography of the planetary mantle than I do python, but isn't "playerY" wrong; it's declared as just "player" above
Hmm, good question. I don't know, I pulled the code from somewhere but I really don't understand it. You suggest changing "
newUnit = playerY.initUnit(gc.getInfoTypeForString('UNIT_WORKER'), UnitAITypes.NO_UNITAI)" to "
newUnit = PyPlayer.initUnit(gc.getInfoTypeForString('UNIT_WORKER'), UnitAITypes.NO_UNITAI)" ?

I guess I could try the other way around too. *shrug* I'll give it a shot. Dropping the term "declared" means you know more about python than I do, heh, so blind ol' Ozzy will accept your one-eyed advice.
 
yeah give it a try old bean! hope it works then I can nick it. either way round will work I think, "player = PyPlayer(iOwner)" bit is making a thingy* the game recognizes into a quick and easy reference ("player") for you to work with, but you have to keep it consistent.

*this is real computer terminology innit
 
I don't program much in Python, but since no experienced Python modder is answering (anymore) and I see a few problems ... here goes:

There's a colon missing:
if iCorporation == iRailCorp
-->
if iCorporation == iRailCorp:

The indentation has to be tabs only. (It probably is; the forum converts tabs to spaces.)

initUnit indeed needs to be called on the player object:
player.initUnit(...
The documentation string in CyPlayerInterface1.cpp says that the function requires these four arguments
UnitTypes iIndex, plotX, plotY, UnitAITypes iIndex
and that this will
"place Unit at X,Y"
and:
"NOTE: Always use UnitAITypes.NO_UNITAI"
So it would have to be:
player.initUnit(gc.getInfoTypeForString("UNIT_WORKER"), pSpreadCity.getX(), pSpreadCity.getY(), UnitAITypes.NO_UNITAI)

In a quick test, addImmediateMessage briefly showed me an on-screen message but didn't store it in the Event Log. For proper UI support, I'd use (all in one line):
CyInterface().addMessage(iOwner, True, gc.getEVENT_MESSAGE_TIME(), "Railroad Corp has expanded into your city and will get to work building the rails", "", InterfaceMessageTypes.MESSAGE_TYPE_INFO, gc.getUnitInfo(gc.getInfoTypeForString("UNIT_WORKER")).getButton(), gc.getInfoTypeForString("COLOR_WHITE"), pSpreadCity.getX(), pSpreadCity.getY(), True, True)
Several examples for how to use addMessage can be found in EntryPoints\CvRandomEventInterface.py, also for how to load the text from a game text XML file with translations. See the Python API for the (in some cases) self-explanatory argument names.
This will show the message to all human players, but I guess you only want to show it to the city owner if that player happens to be human, so
if iOwner == gc.getActivePlayer().getID():
should be checked beforehand.

For tracing/ debugging, addImmediateMessage could be useful, though easy to miss. Alternatives: CvUtil.pyPrint("hello") or simply print("hello"), which write to PythonDbg.log.
Errors are written to PythonErr.log, provided that LoggingEnabled = 1 is set in My Games\Beyond the Sword\CivilizationIV.ini. (I think that's the only setting needed for Python logs, but I'm not quite sure.) The Logs folder should also be in My Games\Beyond the Sword.

I've tested the above in a BUG-based mod by adding the code to CvEventManager.py (as I think you did too). The recommended way for adding event handlers with BUG is a bit more complicated (through an XML file in BUG's Config folder instead of changing CvEventManager.py), but I haven't really used that myself and it can be changed at some later point.
 
The indentation has to be tabs only. (It probably is; the forum converts tabs to spaces.)
It doesn't need to be tabs but it must be exactly whatever is used for indentation elsewhere in that bit code.

We had a problem where 3 spaces were used for indentation but one of the programmers used tabs which were also 3 spaces on their machine so the code looked fine but the tab size on the player's machine was different so the Python did not work on their machine. It took ages to discover that was the problem :lol:
 
We had a problem where 3 spaces were used for indentation but one of the programmers used tabs which were also 3 spaces on their machine so the code looked fine but the tab size on the player's machine was different so the Python did not work on their machine. It took ages to discover that was the problem :lol:
Notepad++. View->Show Symbols->Show White Space and TAB.

It's not that I turn it on when there is a problem. Instead I never turn it off. Experience have told me it's the best way to save time when hunting annoying bugs like the one mentioned here.
 
Top Bottom