Mega-error in python *python guru's please help*

Paasky

Good News Everyone!
Joined
Nov 19, 2003
Messages
2,062
Location
Vantaa, Finland
If you want to re-create the error you must download my WWII europe mod (2megs, click on the sig) and then download the attached events.py.


As for the problem: Upon loading civ with wwii europe, the game gives a huge bunch of errors. They are:
File "CvEventInterface", line 26, in onEvent (this comes 16 times)
File "CvEventManager", line 170, in handleEvent
AttributeError:
CvWWIIsfnbEvents instance has no attribute 'EventHandlerMap'

Then it just begins from the start, but the eventinterface comes only once. This goes on for such a long tme, I have no idea when it stops.

Line 26 in EventInterface contains:
Code:
24 def onEvent(argsList):
25 	'Called when a game event happens - return 1 if the event was consumed'
26	return getEventManager().handleEvent(argsList)

Line 170 in EventManager contains:
Code:
170		if self.EventHandlerMap.has_key(tag):
171			fxn = self.EventHandlerMap[tag]
172			ret = fxn(argsList[1:idx])
173		return ret

As for what's causing it: The file worked perfectly until I added a piece of code taken from an older, made for civ4, python file.

The purpose of the code is to simulate winter, by changing terrain to snow & back randomly. The plots are divided into 4 'sectors', each of them have different possibilities of snow depending on the week. For example, on week 5 the possibility of snow in Iceland is 100%, while in hungary it is 90%.

The code is in 3 parts:
In def __init__(self):
Code:
		self.sector1 = { '52,39':'TUNDRA','53,39':'TUNDRA',etc}
		self.sector1week = { 1:100, 9:90, etc }
		self.sector2 = { '39,34':'GRASS','40,34':'GRASS',etc}
		self.sector2week = { 1:100, 7:90, etc }
		self.sector3 = { '20,22':'GRASS','21,22':'GRASS',etc}
		self.sector3week = { 1:100, 5:90, etc }
		self.sector4 = { '20,21':'GRASS',etc}
		self.sector4week = { 1:100, 3:90, etc }
These are where certain plots of the map are stored, and the possibility of snow on any particular week. (I used etc as the same sort of stuff goes on for a looooooong time. Check the attached file for the complete code)

In def onBeginGameTurn(self, argslist):
Code:
		self.week = (iGameTurn % 48) + 1 
		self.snowcheck(self.sector1, self.sector1week)
		self.snowcheck(self.sector2, self.sector2week)
		self.snowcheck(self.sector3, self.sector3week)
		self.snowcheck(self.sector4, self.sector4week)
This part sends the different sectors & weeks into the actual terrain-changing code.

In def snowcheck(self, sector, sectorweek):
Code:
		loopcount = 1
		weekcheck = self.week
		chance = 0
		while loopcount:
			try: #If we can find the week stored exit the loop. If not we check the week before.
				chance = sectorweek[weekcheck]
				loopcount = 0
			except:
				loopcount = 1 #Just in case.
				if weekcheck == 0:
					weekcheck = 48
				else:
					weekcheck -= 1
					
		for i in sector.keys():
			coord = string.split(i, ",") #Splits the string into ["x", "y"]
			if CyGame().getSorenRandNum(101, 'snow making!') <= chance: #If the snow chance exceeds the random number make snow.
				CyMap().plot(int(coord[0]), int(coord[1])).setTerrainType(gc.getInfoTypeForString('TERRAIN_SNOW'), True, True)
			else: #If the snow chance is lower than the random num return it to original terrain.
				terrain = gc.getInfoTypeForString('TERRAIN_' + sector[i])
				CyMap().plot(int(coord[0]), int(coord[1])).setTerrainType(terrain, True, True)
This part then changes the terrain of the plots to TERRIAN_SNOW or back to the original TERRIAN_ (found in the sectors)

The code used to work perfectly in civ4, but for some reason it now gives this strange error. Does anyone have any idea how to fix it?
 

Attachments

I've got this kind of error when there is a syntax error in the event manager ..

Howewer the log is not a great help in this case , like the pop up error as i can see .

Tcho ! :)

Edit : Perhaps string.split(i, ",") should be i.split(",")
 
Same error with i.split(",").

I did find the EventHandlerMap from warlords' eventmanager (a huge block of differnt self. stuff) and copy-pasted it into my eventmanager. Now the game started without any errors, but stuck on Initializing when I tried to load the scenario.


The strange thing is that the code works without a hitch in civ4. I just tried it, added the python files into a new mod, loaded it, and opened the africa scenario. Also, if I use the previous wwii events, everything there works.
Maybe one of the commands used in civ4 has been changed by someone who thought we would have things too easy?
 
I think I found something. Now I don't have a clue what these mean, so could someone please help on this:

The original code for a random number is
Code:
CyGame().getSorenRandNum(101, 'snow making!')

Now, I took a look in here: http://civilization4.net/files/modding/PythonAPI/ and found this under CyGame:
Code:
CyRandom getSorenRand()

Then, under CyRandom:
Code:
INT get(INT usNum, STRING pszLog)

Now, if I wanted a number from 0-100, how would I do it? would the original work? How would you do it?
EDIT: I tried CyGame().getSorenRand(101, 'snow making!') instead of the old CyGame().getSorenRandNum(101, 'snow making!'), but got the same errors.




Also, does
Code:
CyMap().plot(int(coord[0]), int(coord[1]))
actually work properly? All other plots in the wwii events.py file are done like this:
Code:
CyMap().plot(60,17)
 
For the random number , that should work . In fact when using a lot of time getSorenRandNum() , i use to do like this :

Code:
	dice=gc.getGame().getSorenRand()
        randNum=dice.get(101,'log name')

that return a number between 0 and 100 . This is just a shortcut , i think that both should work .

For the coords , that should work also , but try to check coord to see if there is not a none value like coord=["","12","67"] ... but there is no reason that this work with civ4 and not with warlords .

Does all the rest of the code works with Warlords ?

Does this function is launch on the initialization of the scenario ?
 
Yes, everything worked fine until I added this piece of code into the file. And still does with the old wwii events file.

Well, the data is stored in def __init__ and the snowcheck itself is done in def onBeginGameTurn. And when I added the big chunk that is EventHandlerMap, I added it into __init__. But shouldn't everything found in the default eventmanager be loaded even though I've added a new event.py file?

But I think the problem here is with something that has been changed from civ4. I ould try to re-write the code, but it would just get very messy :p I don't really know know python, I just copy-paste stuff :D

If the error was in either the data storage, indentation, or something like that, the error would be something intelligent, and it would give the line. But this just says that the variable 'EventHandlerMap' doesn't exist.

I just noticed something! Civ4 does not even have an EventManager.py! How come?




EDIT: Nevermind all that. I startged commenting out certain areas, and I know what causes the error: If the def __init__(self) is there at all. I commented out everything except that line, and I got the same error. I'll download FfH, and see what I could do to fix it.
 
I don't understand all with class , i 've never used it (not needed in mapscripting)

i notice that this is missing at the beginning of onBeginGameTurn :
Code:
		iGameTurn = argsList[0]

Try that , and if this is not enough i will send you a file to separate your work from the original file and check where there is a disfunction .

Tcho !
 
You can try that :

1 _ add the attached file in asset / python folder of the mod.

2 _ add that at the beginning of the event manager :

Code:
import snowCheck

3 _ add that at the beginning of onBeginGameTurn() :

Code:
		iGameTurn = argsList[0]
		snowCheck.snowCheck(iGameTurn)

Tcho !
 
I don't know , i've use it for an example for my work ... do you try the solution above ? it should resolve the init problem and separate your work from the original work ... easily to fix .

Tcho !
 
So, the error is that the object CvWWIIsfnbEvents doesn't own something called EventHandlerMap.

You should really copy/paste the complete error message.

Second, do you understand how functions and objects work?

Python is structured based on indentation. The word "def" starts a function. So in your example, line 26 was in the function called "onEvent".

The "parameters" or "arguements" to a function (the data passed into the function) are listed in the brackets after the function name.

So, using ^, | , \ and - characters to pretend to be arrows:
Code:
def onEvent(argsList):
^    ^         ^
|    |         \--<arguements or parameters
|    \----< name of the function
\----< def means we are DEFining a function

Python allows multiple arguements or parameters to be passed in, seperated by commas. The definition describes how many parameters or arguements the function expects.

The word "class" starts an object definition. Objects can contain functions.

When you call a function that is part of a class definition, you can do it like this:

Code:
class_instance.function_name( blahblahblah )

Python does a bit of magic, and turns this into:
Code:
function_name( class_instance, blahblahblah )
Ie, the part before the dot (.) gets moved into the part in the brackets after the function name as the first parameter.

...

So why all these lesson? Well, the "self" parameter is the traditional name you give the instance of the class that your function is contained in.

So to understand what is going on, you want to figure out what function and what class your errors are occuring in.

If self.EventHandlerMap doesn't exist, it is because your class doesn't create the EventHandlerMap before the function is called. A traditional place to create data structures (like EventHandlerMap) to be stored in the function is in the __init__ function (it is also known as the constructor, because is constructs the class).

...

So what is going on is that someone probably modified the onEvent function in a previous version to use an EventHandler object. This EventHandler object meant that they didn't have to hand-code in the onEvent function every part of their mod that wanted to handle "Events" -- instead, when a mod component wanted to handle an event, it just had to register itself with the EventHandler, and it would automatically be asked whenever an Event happened. :)
 
If I had an example on how other mods made their def __init__ work, I could do it myself. For now I've copy-pasted them into onGameStart & onLoadGame, which effectively does the same thing.


I can't really show entire error, as it consists of atleast 30 error messages in windows. You can recreate the error easily, just read the 1st line in the 1st post.
I also haven't touched any other file except wwii events.py (& added the command to load that file into CvEventInterface.py), And the exact same files work in civ4. It's some new fancy thing in warlords that nneds to be done if you add def __init__ into your events.py file.
 
You say that you added your own def __init__ function in your event manager, if you did you would get alot of errors because the entire events dictionary is not being loaded (Am I correct).
 
Yes, but I downloaded one mods patch, and it didn't have all of the 50+ lines of code after def __init__ found in the default eventmanager.
I think something has to be added into CvEventInterface, but I haven't bothered downloading over 200mb just to find out what it is.
 
Yes, I could fish for you. I thought I'd teach you how to do it, because I like teaching more than I like fishing.

A good utility to have for doing things like modifying python files is windiff:
Microsoft advanced user tools for XP.

it will tell you in a GUI what changes have been made to a file -- it lets you compare two versions of a file side-by-side, with the differences highlighted.

Good luck solving your problem.

/bye
 
I actually use Notepad++. It perhaps hasn't got that many toys in it, but it's simple to use, knows every code language you can think of (and I've added civ4wbs files into it's code database) and colorcodes them all.

Seeing as I've found a workaround, this thread is no longer needed.
Thankyou everybody for the help, maybe the next person with this problem can find this useful :)
 
Back
Top Bottom