Need Help on Exposing to Python

Cybah

Emperor
Joined
Jun 22, 2007
Messages
1,481
CyCity.h

PHP:
	bool isWeLoveTheKingDay() const;
	void setWeLoveTheKingDay(bool bWeLoveTheKingDay);

CyCity.cpp

PHP:
bool CyCity::isWeLoveTheKingDay()
{
	return m_pCity ? m_pCity->isWeLoveTheKingDay() : false;
}

void CyCity::setWeLoveTheKingDay(bool bNewValue)
{
	if (m_pCity)
		m_pCity->setWeLoveTheKingDay(bNewValue);
}

On compiling I get this error:

PHP:
1>CyCity.cpp(2261) : error C2511: 'bool CyCity::isWeLoveTheKingDay(void)' : overloaded member function not found in 'CyCity'

What is missing/wrong?

I want to get access through python.
 
NotSoGood is right, you need to add it to CyCityInterface1, but the error you are getting is caused by something else. You are declaring the function as "bool isWeLoveTheKingDay() const" but you are defining it as "bool CyCity::isWeLoveTheKingDay()". You need to add " const" to the end of your function definition so that definition and declaration match.
 
I have copied and pasted and editied. *shame on me* What does "const" mean? Do I need it? Should not I remove it on declaration?
 
I don't understand. For which reasons do you need a function that does not change anything?
 
For whatever reasons, I get the WLTKD Event (or the message at least) twice every round - for only 1 city. Here is my code:


CyCityInterface1:
PHP:
		.def("isWeLoveTheKingDay", &CyCity::isWeLoveTheKingDay, "bool ()")
		.def("setWeLoveTheKingDay", &CyCity::setWeLoveTheKingDay, "void (bool bNewValue)")


PHP:
	def onBeginPlayerTurn(self, argsList):
		'Called at the beginning of a players turn'
		iGameTurn, iPlayer = argsList

## Test Start ##
		pPlayer = gc.getPlayer(iPlayer)
		iTestTrait = CvUtil.findInfoTypeNum(gc.getTraitInfo,gc.getNumTraitInfos(),'TRAIT_INDUSTRIOUS')
		
		if pPlayer.hasTrait(iTestTrait) and pPlayer.isAlive():

        		pIndCity, iter = pPlayer.firstCity(false)  
        		while(pIndCity):  
            			iIndCityOwner = pIndCity.getOwner()  
            			if not pIndCity.isNone() and iIndCityOwner == pPlayer.getID():
							## test
							pIndCity.setWeLoveTheKingDay(true)
							## test 
 
                              
				pIndCity, iter = pPlayer.nextCity(iter, false)

## Test End ##

attachment.php




even twice with this instead of the code above:

PHP:
	def onCityDoTurn(self, argsList):
		'City Production'
		pCity = argsList[0]
		iPlayer = argsList[1]
		pPlayer = gc.getPlayer(iPlayer)

## test start ##
		pCity.setWeLoveTheKingDay(true)
## test end ##

there must still be a mistake in sdk. :( or is this normal behavior on WLTKD?
 
In your first code example, unless the forum has changed your indentation, you are lucky the code completes at all. The line "pIndCity, iter = pPlayer.nextCity(iter, false)" is indented incorrectly, and it falls outside the loop. So the iteration is never updated, and it "should" loop infinitely. Also, I am not sure it matters, but when I put a list on the left hand side of an assignment, I put it in parentheses: "(pIndCity, iter) = pPlayer.nextCity(iter, false)". Try adding the parentheses and adding one level of indentation.

In your second code example, I am not too familiar with onCityDoTurn. Some routines, in particular AI_update, may be called many times in one turn for the same unit. If AI_update returns false, and the unit has movement points left, it will be called again on the same unit. Are you sure that the game only calls onCityDoTurn once? Does it need a return code?
 
the forum has changed the indentation or I made a mistake when removing not needed lines of the original code. This original code works correctly. But for whatever reasons, WLTKD message will appear 2 times when adding the WLTKD code, the whole event will appear 2 times at once (sound 2x, fireworks 2x, message 2x).


In your second code example, I am not too familiar with onCityDoTurn. Some routines, in particular AI_update, may be called many times in one turn for the same unit. If AI_update returns false, and the unit has movement points left, it will be called again on the same unit. Are you sure that the game only calls onCityDoTurn once? Does it need a return code?

PHP:
	def onCityDoTurn(self, argsList):
		'City Production'
		pCity = argsList[0]
		iPlayer = argsList[1]
		pPlayer = gc.getPlayer(iPlayer)

## test start ##
		pCity.setWeLoveTheKingDay(true) <--- 2 times
		if pCity.isWeLoveTheKingDay():
			pCity.changePopulation(10) <--- 1 time
## test end ##

this works. population will only get 10 points, not 20. therefore, it's called once. only the event (setWeLoveTheKingDay) will happen 2 times.
 
I looked into the sdk code for setWeLoveTheKingDay. Unless your mod has made some changes to this function, I do not see any way it can print the message twice. I see that CvCity::doTurn calls your onCityDoTurn python, but regardless of that, it does all of its own stuff. So setWLTKD() will be *called* twice. But since it only takes action if the input value is different from the stored value, this should not make the message happen twice.

Is it possible that you are seeing this behavior because your python causes it one turn, and the normal random number behavior causes it on a second turn?

If you take a blank mod with no changes from BTS at all, and add only your sdk changes and python, do you still see this behavior? I am not sure what other mods you may have in place, perhaps there is a bad interaction.
 
One thing that could affect is that if you use spaces instead of tabs, you have some effects because your part uses spaces and the rest tabs.
I don't know if it could cause things like this though.
 
There are no spaces in my original file. The python code is correct.

Is it possible that you are seeing this behavior because your python causes it one turn, and the normal random number behavior causes it on a second turn?

no, the normal random event can only happen on city size > 7 and other conditions.


this is so strange. i did no change to the WLTKD sdk, I just exposed it to python and was trying it ingame.

i've cheated a pop30 city and the normal random event will only show up once per round.
 
Post your updated C++ code. I also don't see any reason for it to fire the message twice.

You should be using True and False with capital first letters. CvPythonExtensions defines the lowercase versions as 1 and 0 respectively. While this is okay for most uses, best to use the real Python constants. I doubt this is the problem, but you should remove all possibilities.

Also, replace all your uses of CvUtil.findInfoTypeNum() with gc.getInfoTypeForString(). It's significantly faster and easier to type since you don't have to give it the getXXXInfo function name or the total number of items:

Code:
iTestTrait = [B][COLOR="Red"]gc.getInfoTypeForString[/COLOR][/B]('TRAIT_INDUSTRIOUS')
 
No changed behavior with True instead of true. Does WLTKD last more than 1 round? X_x

---

iTestTrait = gc.getInfoTypeForString('TRAIT_INDUSTRIOUS')

or

iTestTrait = gc.getInfoTypeForString("TRAIT_INDUSTRIOUS") ?

---

CyCityInterface1.cpp

PHP:
		.def("getLiberationPlayer", &CyCity::getLiberationPlayer, "int ()")
		.def("liberate", &CyCity::liberate, "void ()")

		.def("isWeLoveTheKingDay", &CyCity::isWeLoveTheKingDay, "bool ()")
		.def("setWeLoveTheKingDay", &CyCity::setWeLoveTheKingDay, "void (bool bNewValue)")
		;
}

CyCity.h

PHP:
	int getLiberationPlayer(bool bConquest);
	void liberate(bool bConquest);

	bool isWeLoveTheKingDay();
	void setWeLoveTheKingDay(bool bWeLoveTheKingDay);

	bool AI_avoidGrowth();
	bool AI_isEmphasize(int iEmphasizeType);
	int AI_countBestBuilds(CyArea* pArea);
	int AI_cityValue();

	std::string getScriptData() const;
	void setScriptData(std::string szNewValue); 

private:
	CvCity* m_pCity;
};

#endif	// CyCity_h


CyCity.cpp

PHP:
void CyCity::liberate(bool bConquest)
{
	if (m_pCity)
	{
		m_pCity->liberate(bConquest);
	}
}

bool CyCity::isWeLoveTheKingDay()
{
    	return m_pCity ? m_pCity->isWeLoveTheKingDay() : false;
}

void CyCity::setWeLoveTheKingDay(bool bNewValue)
{
    	if (m_pCity)
        	m_pCity->setWeLoveTheKingDay(bNewValue);
}


No changes to other sdk files.
 
Dunno why, but with this code:

PHP:
	def onCityDoTurn(self, argsList):
		'City Production'
		pCity = argsList[0]
		iPlayer = argsList[1]
		pPlayer = gc.getPlayer(iPlayer)

## test start ##
 		if gc.getGame().getGameTurn() % 3 == 0:
			pCity.setWeLoveTheKingDay(True)
		## if pCity.isWeLoveTheKingDay():
			## pCity.changePopulation(10)
## test end ##

the WLTKD will be even more than every third round. what the f*** ?
 
Single or double quotes there doesn't matter. You can Google the difference in the Python docs to learn the difference.

What do you mean exactly by "more than every third turn"? Does it give you the message twice every third turn as I'd expect given the current behavior we're seeing, or does it do something weird like on all even turns?

Is it possible that you have registered this event more than once?

WLTKD is checked every turn. If you look at CvCity::doTurn() you'll see that it is canceled if it doesn't pass the random check the next turn.
 
What do you mean with event? There is no other python code with setWeLoveTheKingDay in my files if that's what you mean. There will be no event/message when removing those lines at def onCityDoTurn.

I mean, it seems that the event will happen every second round twice. Even "gc.getGame().getGameTurn() % 3" is not working correctly. You can see the rounds in the upper right and the event will not only appear on 3/6/9/12/15....

When it happens, I always get it twice in that round. The second WLTKD event will appear some seconds after the first.

Berlin is celebrating WLTKD.
.
.
.
Berlin is celebrating WLTKD.

Hard to explain and I doubt anybody can help me without trying it out. :-/
 
try

if not pCity.isWeLoveTheKingDay():
pCity.setWeLoveTheKingDay(true)
 
onCityDoTurn() is your event handler for the CityDoTurn event. I'm asking if you have registered it in your config XML twice:

Code:
<event type="CityDoTurn" function="onCityDoTurn"/>
...
<event type="CityDoTurn" function="onCityDoTurn"/>

I doubt it, but it never hurts to double-check.

The delay between messages is normal. This keeps 20 messages from spamming to your screen all at once with their sounds jumbled together.

You should add some calls to BugUtil.alert() in onCityDoTurn() to help see what's going on:

Code:
BugUtil.alert("Turn %d, mod 3: %d", gc.getGame().getGameTurn(), gc.getGame().getGameTurn() % 3))
if gc.getGame().getGameTurn() % 3 == 0:
    BugUtil.alert("love: %s", pCity.isWeLoveTheKingDay())
    pCity.setWeLoveTheKingDay(True)
    BugUtil.alert("new love: %s", pCity.isWeLoveTheKingDay())
 
Back
Top Bottom