Quick question

Ok, the attached files appear to work on my installation. There was a another mistake in my code but I sorted it out and I got the code to work with a O.D.P. unit. The debug messages I added to see what really happened with the code revealed that the unitCannotMove callup is done some 20 times for each attempted unit movement, so clearly all the extra catching code should be worth the effort as to avoid unwanted lag. :p

I'll leave the code for you to test in a real game situation - I merely added units with the World Builder and tried to move them in and out of borders.
 

Attachments

  • UnitMovementRestriction.zip
    22.7 KB · Views: 29
OK, tried playing normally, everything was going fine until turn 152 when i got a CtD. Barbs start arriving on turn 150 so i think there may be a problem with this, going to go back and try it again and see if it's a repeatable CtD.

Edit, yep the crash is repeatable playing under normal conditions. What you've done does work when tested but seems to be causing a new problem when the raiders(barbs) appear.
 
No exceptions for the CTD? If it happens again, you might wanna upload your PythonDbg.log and we'll see what has going on at the time of the crash. Provided that you've enabled logging or whatever is needed for the debug messages to appear.
 
The logs are in My Documents/My Games/Beyond the Sword/Logs (near the saved game files, which are over in Saves instead of Logs). The exact names like "My Documents" may vary slightly depending on Windows version (Windows 7 just calls it "Documents"). Alternatively, inside the Beyond the Sword installation folder (same folder that holds the Mods folder for it) there are a number of shortcuts including one called "_Civ4Logs" which will take you to the right place if you use it.

The logging settings are in CivilizationIV.ini in My Games/Beyond the Sword. This file also has a shortcut in the BtS install folder called "_Civ4Config". In there it has a section starting with [DEBUG]. In that section, the main thing is that you want to make sure that LoggingEnabled = 1.
 
Any luck? The movement limitation thing is working, at least? Try disabling it and run a auto-save where the game is bound to crash, just to make sure the cause isn't any of my work. :p
 
The logs are in My Documents/My Games/Beyond the Sword/Logs (near the saved game files, which are over in Saves instead of Logs). The exact names like "My Documents" may vary slightly depending on Windows version (Windows 7 just calls it "Documents"). Alternatively, inside the Beyond the Sword installation folder (same folder that holds the Mods folder for it) there are a number of shortcuts including one called "_Civ4Logs" which will take you to the right place if you use it.

The logging settings are in CivilizationIV.ini in My Games/Beyond the Sword. This file also has a shortcut in the BtS install folder called "_Civ4Config". In there it has a section starting with [DEBUG]. In that section, the main thing is that you want to make sure that LoggingEnabled = 1.
Thanks God-Emperor.:blush:
 
Any luck? The movement limitation thing is working, at least? Try disabling it and run a auto-save where the game is bound to crash, just to make sure the cause isn't any of my work.
I'll let you know when i've had the time to do the testing, hopefully sometime saturday.

Edit:Following the above instructions for finding the PythonDbg file i've attached the file from the last time it crashed. If i get any further CtD's i'll upload them.
 
I currently have no handle on this issue, and I only have about 20 minutes at my disposal today.

Looking at the Debud Log supplied it doesn't say much of nothing. So I think I need to add my own debug messages into the script, so that we can follow exactly what happens with the code once the Barbarians spawn. At best, it might provide a clue into exactly what causes the crash.
 
Code:
# start unit movement restriction code

	unitCannotMoveIntoDict = dict()
	unitCombatDict = dict()
[COLOR="Red"]	bDebug = True # change to False once done debugging[/COLOR]

	def unitCannotMoveInto(self,argsList):
		ePlayer, iUnit, iX, iY = argsList
		eUnitType = gc.getPlayer(ePlayer).getUnit(iUnit).getUnitType()
		tKey = ePlayer, eUnitType, iX, iY
		bRestricted = self.unitCannotMoveIntoDict.get(tKey, None)
[COLOR="Red"]		if bDebug:
			print ("debug: unitCannotMoveInto()", tKey)
			print "bRestricted = " + str(bRestricted)
			print unitCannotMoveIntoDict[/COLOR]
		if bRestricted == None:
			eUnitCombat = self.unitCombatDict.get(eUnitType, None)
			if eUnitCombat == None:
				eUnitCombat = gc.getUnitInfo(eUnitType).getUnitCombatType()
				self.unitCombatDict[eUnitType] = eUnitCombat
			if eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_DEFENCE"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			else:
				bRestricted = False
			self.unitCannotMoveIntoDict[tKey] = bRestricted
[COLOR="Red"]		if bDebug:
			print "return " + str(bRestricted)[/COLOR]
		return bRestricted

# end unit movement restriction code
Now, try to recreate the crash with this additional code in place. When you succeed, post the Debug Log and there should be tons of debug messages printed up till the actual crash.

Also, I could easily misspelled some line above. Since I will be away for the next day or so, try to figure any typos out yourself. Those should result in a syntax error and the traceback supplied by the exception will list the actual line and possibly even the bit of code in question.
 
I was thinking. It is conceivable that some unit info XML is causing the issue. This would possibly happen if there is something irregular about the unit type/class, that makes some Python method invocation crash the game, even if the unit info is being parser alright at startup.

An example would be a unit type with no or illegal UnitCombatType, if that was possible to load as far as the XML is concerned.

Clues would be supplied by the debug code I posted above.
 
OK, I've playtested it now, fortunately I had no crashes at all when the Barbs(Raiders) arrived the only thing I did find worrying was that it took 2 and a half minutes for the AI to complete it's turns. Is there any way of speeding this up?
 
Yeah, did you read the comment line?
bDebug = True # change to False once done debugging
Because the game takes forever to print out all those debug messages into the log.
 
Try disabling the movement restriction code or better yet disable the callback entirely in the XML. Because then we at least know that it is the Python that is causing it.
 
Thinking about the issue further, it would be possible to make the script pass some basic checks before processing the whole rest of the code. Like if the unit movement restriction is really only restricted to some players - because only those players have access to those types of units - it would be possible to exclude any other player's units. This would, in theory, speed things up by eliminating the need to check for UnitCombatTypes and accessing the cache dictionary for possible matches.

Furthermore, there is probably no need to fetch the index number of UNITCOMBAT_DEFENCE every single time the code is executed. If you figure out what the corresponding integer value is, then it would be possible to get rid of one method invocation entirely.

Finally, you could try the earlier code I posted - without the additional "caching" stuff. Because that relies on accessing data in a dictionary - and I have no idea how fast something like that actually is. Because if accessing a dictionary that is quickly growing is slower than to run the basic code, then its actually hurting more than its helping. :p

The simpler version would look something like this:
Code:
	def unitCannotMoveInto(self,argsList):
		ePlayer, iUnit, iX, iY = argsList
		if gc.getUnitInfo(gc.getPlayer(ePlayer).getUnit(iUnit).getUnitType()).getUnitCombatType() == gc.getInfoTypeForString("UNITCOMBAT_DEFENCE"):
			return gc.getMap().plot(iX, iY).getOwner() != ePlayer
Once you can tell which version is faster in actual gameplay, it would be possible to add more catching with additional dictionaries, like storing the UnitCombatTypes of CyUnit instances, or the owners of CyPlot instances. This would cut back on a whole lot of methods being invoked during a player's turn.

So, in summary: Yeah, it would probably be possible to make the code more efficient. You just need to figure out what approach is working better first - then we can optimize that one.
 
Have you had any time/luck with further testing?
 
Top Bottom