Question about events occured

jerrybp

Chieftain
Joined
May 17, 2010
Messages
20
Hi,
I have problems accessing global events occured and hope someone can help. Basically I only need to know if a specific global event happened somewhere at any point in history, but I can't get it to work.

As I understand things, a player's functions getEventTriggered(itrigger) and getEventOccured(ievent) are the way to find triggered and occured events. The first one tells me if the itrigger trigger has been activated by the player, which however does not necessarily mean the associated event has taken place, so it's useless for me. But the second tells me if ievent has occured to player, and that's what I'm looking for. Right?

The problem is I get a curious behavior when using it. I made the following experiment: I put the code below in EventManager.py, within the OnBeginPlayerTurn function, to monitor what was going on, event-wise. As you can see from the code, every turn I'm going through all possible triggers in the game, see for each if it is Global, and if it is, I check all active players to see if its (first) associated event has occured. If so, I print on screen some data.

Code:
		if pPlayer.isHuman():
			for i in range(gc.getNumEventTriggerInfos()):
				trigger=gc.getEventTriggerInfo(i)
				if trigger.isGlobal():
					for ii in range(gc.getMAX_CIV_PLAYERS()):
						if gc.getPlayer(ii).isAlive():
							ev=gc.getPlayer(ii).getEventOccured(trigger.getEvent(0))
							if (ev != None):
								CyInterface().addImmediateMessage("%s - %s (%s)" %(gc.getPlayer(ii).getName(),trigger.getType(),gc.getEventInfo(trigger.getEvent(0)).getType()),"")

The curious thing is this: I start playing, for a while getting no prints on screen as expected, and then a global event appears to occur to some player I haven't met yet since I get a first print. Something like: "Sitting Bull - EVENTTRIGGER_HYMNS_AND_SCULPTURES (EVENT_HYMNS_AND_SCULPTURES_1)"
So far so good. For the following two or three turns I get, as expected, the same print each turn, confirming what I already know. Good. But then the prints stop. As if the program forgets the event took place. Other global events happen later, I get their prints, but it's the same thing: it keeps printing for only a few turns and then stops.

So basically I find myself unable to determine if a global event ever happened. Ideas?
Thanks in advance.
 
I see nobody else has answered, so it is an interesting problem.

I'm not able to find any other places in python where getEventOccured(i) is used. I have no factual basis for this, but I guess that as long as only one event has occurred to any player, this is fine but as soon as there are two events occurred, it no longer returns a useful value.

You may agree that looping all events, for all players, every turn is not the right architecture because it will take too much runtime. What you want, I think, is a callback which occurs when an event is triggered, passing you the player number and the event number. As far as I can tell there is no such callback. Are you interested/able to modify the C++ code for cvgamecore.dll? It seems like this callback would be a nice addition. In file CvDllPythonEvents.h, you can see a number of functions like reportCityBuilt. These functions are called during turn processing when a certain event happens. Then CvDllPythonEvents.cpp is in charge of formatting and executing a call "up" to python. So you could add CvDllPythonEvents::reportEvent, call it when an event is triggered, and then add code to CvEventManager.py to take an action.

Your python code could simply store this in a global array, so that when your playerturn function executes, it simply looks in the array to see if the event has happened.

If there is a better way to do this, perhaps somebody more knowledgeable than me can comment.
 
Not a solution, but I looked at the code and I have an answer for why it happens.
Apparently events can expire, and then they are removed from the player's list (map, actually) of events that occurred.
Specifically, all events which are not quests - expire after 3 turns.
Other conditions for expiry: A religion or civic based event after the player switched this religion or civic, a city or unit based event after this player lost this unit or city, obsoleted by tech etc.

I think davidlallen's idea for a solution is the way to go, but don't forget to save this information when game is saved.
 
I think davidlallen's idea for a solution is the way to go, but don't forget to save this information when game is saved.

Thanks for investigating. Supporting "save" is an excellent point. It may be better to create a bool array in the game object (in the dll) where this can be stored, rather than messing with pickling in python. There is a pure python solution, with high runtime cost; loop all the players and events as shown, but store the result locally instead of relying on the game to store it for all time; and then pickle the result. I do not think there is a "good" pure python solution.
 
Pickling is hardly called for if all you need is boolean (True/False) values. Because those can be represented by letters (like "1" and "0") in a string.

But doing thing directly in the SDK is of course (almost) aways the best option. Looping through things every turn/event with Python is something I avoid myself and will go to extreme lengths to avoid (while still working with Python).
 
Top Bottom