Python Question

JareshInyo

Chieftain
Joined
Oct 20, 2008
Messages
29
I do not know a lot about python (at all) and I just wanted to program one event. The coding is below.



#Federation Headquarters
iFedHead = CvUtil.findInfoTypeNum(gc.getBuildingInfo, gc.getNumBuildingInfos(), "BUILDING_FACTORY")
pEarth = gc.getTeam(gc.getPlayer(0).getTeam())
pVulcan = gc.getPlayer(1).getTeam()
pAndoria = gc.getPlayer(2).getTeam()
pTellar = gc.getPlayer(3).getTeam()
if(iBuildingType == iFedHead):
pEarth.addTeam(pVulcan)
pEarth.addTeam(pAndoria)
pEarth.addTeam(pTellar)

for iPlayer in range(gc.getMAX_PLAYERS()):
pPlayer = gc.getPlayer(iPlayer)

if(pPlayer.isAlive() and pPlayer.isHuman()):
popupInfo = CyPopupInfo()
popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_TEXT)
szBody = localText.getText("TXT_KEY_FOUND_FEDERATION", ())
popupInfo.setText(szBody)
popupInfo.addPopup(iPlayer)



I copied the code from another mod, which forms a 4 civilization team with the first four players in the game (players 0,1,2, and 3) when a specific building is constructed. Can I change the code somehow to make a 4 civilization team of 4 specific civilizations (for example, making the US, England, France, and Germany one team) in any game where those 4 specific civs could have any player number?
 
Not in vanilla BtS, because teams, which are formed ingame, are restricted to 2 players.

Might be different if you set a game up like that, or if you have a worldbuilder file (-> scenario; easy to change that in there, does not involve any Python).
 
I'm using the code in another mod anyway, not vanilla BTS, and I tested it as is - it does form a 4 person team with the first 4 players. I just don't know how to change the code to make it 4 specific civs instead of the first 4. I think I would have to alter the

pEarth =
pVulcan =
pAndoria =
pTellar =

lines since they have functions referring to players 0-3. I would want them to refer to a civilization given its XML Tag or something like that. The four civs won't change from game to game, but their player/team number might. Is this possible?
 
Ah, okay. Replace each of these assignments with this code part (alter variables/names accordingly):
PHP:
for i in range gc.getMAX_CIV_PLAYERS ():
    pPlayer = gc.getPlayer(i)
    if pPlayer.getCivilizationType() ==gc.getInfoTypeForString("CIVILIZATION_GERMANY"):
        pEarth = gc.getPlayer(i)
        break
else:
    return
 
I just tried what you suggested but it didn't work. Did I make an error somewhere? Here is the coding I used:

PHP:
		#Federation Headquarters
		iFedHead = CvUtil.findInfoTypeNum(gc.getBuildingInfo, gc.getNumBuildingInfos(), "BUILDING_FACTORY")
		for i in range gc.getMAX_CIV_PLAYERS ():
			pPlayer = gc.getPlayer(i)
			if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_ROMULAN"):
				pEarth = gc.getPlayer(i)
				break
		else:
			return
		for i in range gc.getMAX_CIV_PLAYERS ():
			pPlayer = gc.getPlayer(i)
			if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_THOLIAN"):
				pVulcan = gc.getPlayer(i)
				break
		else:
			return
		for i in range gc.getMAX_CIV_PLAYERS ():
			pPlayer = gc.getPlayer(i)
			if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_BREEN"):
				pAndoria = gc.getPlayer(i)
				break
		else:
			return	
		for i in range gc.getMAX_CIV_PLAYERS ():
			pPlayer = gc.getPlayer(i)
			if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_GORN"):
				pTellar = gc.getPlayer(i)
				break
		else:
			return
		if(iBuildingType == iFedHead):
			pEarth.addTeam(pVulcan)
			pEarth.addTeam(pAndoria)
			pEarth.addTeam(pTellar)

			for iPlayer in range(gc.getMAX_PLAYERS()):
                                pPlayer = gc.getPlayer(iPlayer)

                                if(pPlayer.isAlive() and pPlayer.isHuman()):
                                        popupInfo = CyPopupInfo()
                                        popupInfo.setButtonPopupType(ButtonPopupTypes.BUTTONPOPUP_TEXT)
                                        szBody = localText.getText("TXT_KEY_FOUND_FEDERATION", ())
                                        popupInfo.setText(szBody)
                                        popupInfo.addPopup(iPlayer)
 
:run: oops, my fault :blush:.
Replace:
PHP:
pEarth = gc.getPlayer(i)

(and the respective other variables) with
PHP:
pEarth = gc.getTeam(gc.getPlayer(i).getTeam())


Oh, and are Python exceptions turned on?

Another thing: That code will currently only work if all civs are present, and will not be executed if one is missing. Not sure if you'd like to have that changed.
 
Besides pEarth, the rest should be pPlayer.getTeam()
 
Oh, and are Python exceptions turned on?

Another thing: That code will currently only work if all civs are present, and will not be executed if one is missing. Not sure if you'd like to have that changed.

I don't know if python exceptions are turned on. How can I tell?

And not all of the civs will be present either - including the 4 civs that are becoming a team. I want any of the four listed civs that are present (in a randomly generated game) to become a team, though the four will usually all be there. How can I code that?

Thanks for the assistance.
 
The various
Code:
        else: 
            return
pars need to be indented one more level. "else" goes with "if", not "for", and needs to be at the same level of indentation.
 
I don't know if python exceptions are turned on. How can I tell?

Go do Documents\My Games\BtS, open the Civilization4.ini, and change (if not already done):
PHP:
; Set to 1 for no python exception popups
HidePythonExceptions = 1

to 0.

And not all of the civs will be present either - including the 4 civs that are becoming a team. I want any of the four listed civs that are present (in a randomly generated game) to become a team, though the four will usually all be there. How can I code that?

Thanks for the assistance.

Okay, you'd need this:
PHP:
pEarth,pVulcan,pAndoria,pTellar = None
iFedHead = CvUtil.findInfoTypeNum(gc.getBuildingInfo, gc.getNumBuildingInfos(), "BUILDING_FACTORY")
for i in range gc.getMAX_CIV_PLAYERS ():
    pPlayer = gc.getPlayer(i)
    if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_ROMULAN"):
        pEarth = gc.getPlayer(i)
    if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_THOLIAN"):
        pVulcan = gc.getPlayer(i)
    if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_BREEN"):
        pAndoria = gc.getPlayer(i)
    if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_GORN"):
        pTellar = gc.getPlayer(i)
if(iBuildingType == iFedHead):         
    if pEarth:
        if pVulcan:
            pEarth.addTeam(gc.getTeam(pVulcan.getTeam()))
        if pAndoria:
            pEarth.addTeam(gc.getTeam(pAndoria.getTeam()))
        if pTellar:
            pEarth.addTeam(gc.getTeam(pTellar.getTeam()))
    elif pVulcan:
        if pAndoria:
            pVulcan.addTeam(gc.getTeam(pAndoria.getTeam()))
        if pTellar:
            pVulcan.addTeam(gc.getTeam(pTellar.getTeam()))
    elif pAndoria:
        if pTellar:
            pAndoria.addTeam(gc.getTeam(pTellar.getTeam()))

That should take care of all possible constellations.

The various
Code:
        else: 
            return
pars need to be indented one more level. "else" goes with "if", not "for", and needs to be at the same level of indentation.

Nope, that's something which I learned from someone else here (I think EmperorFool):
In Python you can attach an else clause to a for loop. That else will be executed in the case the loop does not break anywhere.
Pretty neat in cases where you don't know if or if not something is present in a set. You don't have to check afterwards again, if it has been found or not, you can just add a break in the loop and attach an else.
 
Just 2 comments, pEarth is supposed to be the team, not the player instance.
The for loop for the players can be dumped under the if building is FedHead statement, else the for loop will be activated for each and every building built
 
Oh man, I'm such a bad programmer sometimes. And these are not the only errors *sigh*.

Again:
PHP:
if(iBuildingType == iFedHead):
    pEarth,pVulcan,pAndoria,pTellar = None
    iFedHead = CvUtil.findInfoTypeNum(gc.getBuildingInfo, gc.getNumBuildingInfos(), "BUILDING_FACTORY")
    for i in range gc.getMAX_CIV_PLAYERS ():
        pPlayer = gc.getPlayer(i)
        if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_ROMULAN"):
            pEarth = gc.getTeam(gc.getPlayer(i).getTeam)
        if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_THOLIAN"):
            pVulcan = gc.getTeam(gc.getPlayer(i).getTeam)
        if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_BREEN"):
            pAndoria = gc.getTeam(gc.getPlayer(i).getTeam)
        if pPlayer.getCivilizationType() == gc.getInfoTypeForString("CIVILIZATION_GORN"):
            pTellar = gc.getTeam(gc.getPlayer(i).getTeam)    
    if pEarth:
        if pVulcan:
            pEarth.addTeam(pVulcan.getID())
        if pAndoria:
            pEarth.addTeam(pAndoria.getID())
        if pTellar:
            pEarth.addTeam(pTellar.getID())
    elif pVulcan:
        if pAndoria:
            pVulcan.addTeam(pAndoria.getID())
        if pTellar:
            pVulcan.addTeam(pTellar.getID())
    elif pAndoria:
        if pTellar:
            pAndoria.addTeam(pTellar.getID())
 
Nope, that's something which I learned from someone else here (I think EmperorFool):
In Python you can attach an else clause to a for loop. That else will be executed in the case the loop does not break anywhere.
Pretty neat in cases where you don't know if or if not something is present in a set. You don't have to check afterwards again, if it has been found or not, you can just add a break in the loop and attach an else.
Oh well. That's what I get for not really paying attention to what the code was actually doing and issuing an automatic response formatting problems that happen when posting code to a forum (accidentally losing indentation when posting code happens from time to time, which I assumed happened this time)... If it was moved to be on the "if" in the loop, it would exit the function the first time you hit a civ that wasn't the one being looked for, which would have happened almost immediately and been incorrect behavior. 99% of the time, if there is an "else" right after an "if" statement it should be indented to match the "if" (or one of them, if nested) - just not in this case. Oops.

If I had waited, it would not have been an issue since the new and improved code doesn't even use the "else return" type clauses. :lol:
 
Oh well. That's what I get for not really paying attention to what the code was actually doing

:lol: I know that somehow :D.

and issuing an automatic response formatting problems that happen when posting code to a forum (accidentally losing indentation when posting code happens from time to time, which I assumed happened this time)...

Ah, that makes more sense, because I was fairly sure you'd know about that stuff.

You forgot, I learnt my python from you :D

That's an exaggeration ;) ^^.
 
I used the new code with python exceptions enabled and got this series of exceptions (spaces for blank pop-ups):


Spoiler :
Traceback (most recent call last)
File '<string>", line 1, in ?
File "<string>", line 52, in load_module
File "CvEventInterface", line8, in ?
File "<string>", line 35, in load_module
File "<string>", line 13, in_get_code
File "
CvFinalFrontierEvents
", line
859


for i in range gc.getMAX_CIV_PLAYERS():

















^
Syntax Error
:
invalid syntax

Failed to load python module CvEventInterface



The first "if" is on line 856, so I think the problem is with the "for i in range gc.getMAX_CIV_PLAYERS ():" on line 859. Can you see an error? I used the code posted Jun 04, 2012 08:15 PM.
 
Okay, that fixes the python exceptions on the mod's start up, but there are exceptions when I build the building that triggers the event (which will eventually be a wonder, it's just a factory so it is easy to test). It looked like it wanted me to move the

PHP:
pEarth,pVulcan,pAndoria,pTellar = None 
iFedHead = CvUtil.findInfoTypeNum(gc.getBuildingInfo, gc.getNumBuildingInfos(), "BUILDING_FACTORY")

lines above the "if" statement. Moving them to the top eliminated the python exceptions when the building was built, but now nothing else happens when the building is built either. ?
 
:wallbash: :wallbash: :wallbash: yes, correct, the iFedHead = CvUtil should be above the if clause.
And replace the 4 parts:
PHP:
gc.getPlayer(i).getTeam)

with
PHP:
gc.getPlayer(i).getTeam())


...I should really stick to my principles: Don't post code which you have not tested yourself. Because if you don't, it will never work.
Like it's clearly visible, right?
 
Back
Top Bottom