Quick question

Loose the self. on this line though:
Code:
	[COLOR="Red"]self.[/COLOR]deactivated = set()
 
Loose the self. on this line though:
Code:
self.deactivated = set()
I have now tested this and whilst it has solved the problem of my Stars/Planets disappearing it is not preventing the unit types from moving outside of the borders. Also there are no error messages generated so there doesn't appear to be any errors in what has been done so far.

Any ideas?
 
The movement restriction seems to be working correctly for the UNITCOMBAT_DESTROYER but not for the UNITCOMBAT_FRIGATE. An unfortunate side effect of the movement restriction is that it is also preventing the Alien/Pirates/Barbarians from moving around the map at least with their UNITCOMBAT_DESTROYER.

Any ideas as to what needs to be amended, added or removed?
 
The movement restriction seems to be working correctly for the UNITCOMBAT_DESTROYER but not for the UNITCOMBAT_FRIGATE. An unfortunate side effect of the movement restriction is that it is also preventing the Alien/Pirates/Barbarians from moving around the map at least with their UNITCOMBAT_DESTROYER.

Any ideas as to what needs to be amended, added or removed?

The issue for drigates vs. destroyers is this code:
Code:
			if eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_FRIGATE"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			if eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_DESTROYER"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			else:
				bRestricted = False
If it is a frigate then it sets bRestricted, but it then checks to see if it is a destroyer. Since it isn't a destroyer it activates the "else" clause which always sets bRestricted = False.

This code needs to be fixed. You can do this in several ways.

One way (fewer changes - in fact, it is just changing an "if" to an "elif"):
Code:
			if eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_FRIGATE"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			[B][COLOR="DarkRed"]elif [/COLOR][/B]eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_DESTROYER"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			else:
				bRestricted = False
Another option is to make a list of all types that should be restricted and check against that list (this has some small advantage in managing the code if changes will ever be made to the list of types to restrict):
Code:
			lRestrict = [gc.getInfoTypeForString("UNITCOMBAT_FRIGATE"),
			             gc.getInfoTypeForString("UNITCOMBAT_DESTROYER")]
			if eUnitCombat in lRestrict:
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			else:
				bRestricted = False

For the barbarian issue, what to do to the code depends on the details of what you want to do. Should barbarians be completely excluded from this, or just some ship unitcombat types excluded for them but other types still restricted?
 
Thanks for the two options on fixing the problem, I'll try them both out and see which one works best for my needs (I may need to have additional UNITCOMBAT types prevented from moving outside of home territory).

For the barbarian issue, what to do to the code depends on the details of what you want to do. Should barbarians be completely excluded from this, or just some ship unitcombat types excluded for them but other types still restricted?
They need to be completely excluded from this code as it should only affect the playable Civ's.
 
They need to be completely excluded from this code as it should only affect the playable Civ's.

You should be able to exclude barbarians from the effect by modifying one line near the beginning of the function to add the barbarian player to the "deactivated" set of players.
Code:
	def unitCannotMoveInto(self,argsList):
		ePlayer, iUnit, iX, iY = argsList
		if ePlayer in self.deactivated:
			return False
		else:
			if gc.getTeam(gc.getPlayer(ePlayer).getTeam()).isHasTech(gc.getInfoTypeForString("TECH_B5_SHIP_CONSTRUCTION")) [B][COLOR="DarkRed"]or gc.getPlayer(ePlayer).isBarbarian()[/COLOR][/B]:
				self.deactivated.add(ePlayer)
You could also get the same effect by specifically checking if the player is the barbarian in the first "if" where it checks the deactivated list, instead of adding it to the list.
 
You should be able to exclude barbarians from the effect by modifying one line near the beginning of the function to add the barbarian player to the "deactivated" set of players.
Code:
	def unitCannotMoveInto(self,argsList):
		ePlayer, iUnit, iX, iY = argsList
		if ePlayer in self.deactivated:
			return False
		else:
			if gc.getTeam(gc.getPlayer(ePlayer).getTeam()).isHasTech(gc.getInfoTypeForString("TECH_B5_SHIP_CONSTRUCTION")) [B][COLOR="DarkRed"]or gc.getPlayer(ePlayer).isBarbarian()[/COLOR][/B]:
				self.deactivated.add(ePlayer)
You could also get the same effect by specifically checking if the player is the barbarian in the first "if" where it checks the deactivated list, instead of adding it to the list.

Thanks God-Emperor, that's a great help, i'll add the amended code tonight and let you know if there are any problems.
 
There is another issue. It needs another line of code so that when adding things to the deactivated set it returns False immediately, like so:

Code:
	def unitCannotMoveInto(self,argsList):
		ePlayer, iUnit, iX, iY = argsList
		if ePlayer in self.deactivated:
			return False
		else:
			if gc.getTeam(gc.getPlayer(ePlayer).getTeam()).isHasTech(gc.getInfoTypeForString("TECH_B5_SHIP_CONSTRUCTION")) or gc.getPlayer(ePlayer).isBarbarian():
				self.deactivated.add(ePlayer)
				[B][COLOR="DarkRed"]return False[/COLOR][/B]
Without it, the first unit that gets tested after researching the tech, or that is a barbarian, may have it's movement restricted once and also maybe get an extraneous entry added to the two dictionaries. Since it is just once it is not a huge issue, but not happening at all is better.
 
This works exactly how I wanted it to. At the moment I am using this code

Code:
if eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_FRIGATE"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			elif eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_DESTROYER"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			else:
				bRestricted = False
Which is only preventing the Frigate & Destroyer classes from moving around. I do need to add the UNITCOMBAT_CARRIER to it as this unit could also be built prior to the restriction ending when the correct tech is researched. Is it as simple as copying this bit

Code:
elif eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_DESTROYER"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
Changing the UNITCOMBAT from DESTROYER to CARRIER and placing it before the last bit of code like this
Code:
if eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_FRIGATE"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			elif eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_DESTROYER"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
                        elif eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_CARRIER"):
				bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
			else:
				bRestricted = False
Would this work as I want it to or would I need some other changes?
 
Yeah, will work.
Although it will look cleaner using "or" rather than so many "if else" statements or adding them to a list as God Emperor suggested
 
There is an issue (or two) with the code.

The question is this: What happens to the dictionary of restricted plots when a star system's borders expand?

The answer is this: Nothing.

Every plot that was restricted is still restricted. It doesn't matter if it is now inside the borders, you still can't move on it if you ever tried to do so before with a ship of the same type.

There is one exception. The data is not saved in the savegame. Therefore if you save the game and then run from the save this starts from scratch each time. This allows all players to recover from any bad restrictions, but this is not exactly a recommended approach.

It would be nice to clear the unitCannotMoveIntoDict, or at least remove all entires for that player, when a star system's borders expand if the player does not yet have the tech that sets them free. But doing so could be a tad tricky, especially since the gameutils are managed by BUG and I'm not sure how to locate the actual instance of the class. So it may be better to just remove the caching of that data. It would be a bit slower, but it would solve the problem. Alternatively the data could be stored someplace more easily accessible, allowing the data to be adjusted in the onCityGrowth event handler. The FinalFrontierEvents event handler class instance is specifically set up to be easy to locate (it adds a variable that holds a pointer to itself to the main BUG event handler when the FinalFrontierEvents class instance is initialized), so that is a good possibility.
 
Every plot that was restricted is still restricted. It doesn't matter if it is now inside the borders, you still can't move on it if you ever tried to do so before with a ship of the same type.

There is one exception. The data is not saved in the savegame. Therefore if you save the game and then run from the save this starts from scratch each time. This allows all players to recover from any bad restrictions, but this is not exactly a recommended approach.

This has been reported on the B5 thread, nice to know it is fixable through the save/reload.

So it may be better to just remove the caching of that data. It would be a bit slower, but it would solve the problem. Alternatively the data could be stored someplace more easily accessible, allowing the data to be adjusted in the onCityGrowth event handler.

Where/how would I go about doing either of these things?
 
Where/how would I go about doing either of these things?

The easiest method is to simply not store the restriction data, just check it each time. This will increase the amount of time it takes on average for each movement check slightly (but reduce the amount of memory used, although in comparison to the amount the game uses it is trivial). Since the restriction is removed once the tech is researched, which is relatively early in the game, the slower code will only be used early in the game when there are only a small number of units so the net effect should be very small.

To do this, remove references to unitCannotMoveIntoDict.

First, well first keep a copy of what you have now...

Second, remove this line that initially defines the variable:
Code:
	unitCannotMoveIntoDict = dict()

Then remove the lines referencing it in the function and defining the key used for the dictionary, and unindent one section of code.

Remove:
Code:
		tKey = ePlayer, eUnitType, iX, iY
		bRestricted = self.unitCannotMoveIntoDict.get(tKey, None)
		if bRestricted == None:
and
Code:
			self.unitCannotMoveIntoDict[tKey] = bRestricted

Then, finally, reduce by one level the indentation of all the code that used to be inside the "if" block for the now removed "if bRestricted == None:" statement .

That ought to do the trick.

The degree to which turn processing is slower will probably be unnoticeably small, and nonexistent once everyone has the tech to remove the restriction.

Edit: By the way, if you were interested in resetting the data on border growth the correct event hander is onCultureExpansion, not the onCityGrowth (which is for population changes) that I mentioned in the earlier post. Population grows, borders expand. Oops.
 
I did not read the whole 6 pages so I am not sure what it is meant to be like.

However, if it is meant to allow the ships to move only within cultural borders, then whether it is onCultureExpansion or onCityGrowth, neither one will be accurate.

OnCultureExpansion only activates when the city reaches the next culture level, but it does not tell you whether the plots themselves have changed ownership. For border cities near to rivals, the plots will change ownership occasionally due to culture ratio, but it is not updated with onCE and certainly not onCG. Thus, even if the plots flipped to yours, the data will not be updated, and the reverse holds true also
 
I did not read the whole 6 pages so I am not sure what it is meant to be like.

However, if it is meant to allow the ships to move only within cultural borders, then whether it is onCultureExpansion or onCityGrowth, neither one will be accurate.

OnCultureExpansion only activates when the city reaches the next culture level, but it does not tell you whether the plots themselves have changed ownership. For border cities near to rivals, the plots will change ownership occasionally due to culture ratio, but it is not updated with onCE and certainly not onCG. Thus, even if the plots flipped to yours, the data will not be updated, and the reverse holds true also

On Final Frontier style maps this is almost never going to be an issue due to the spacing between star systems, certainly not in the early game even on a map with some relatively close star systems. Since the restriction disappears for each player as they get a relatively early tech, the small amounts of overlap (compared to regular BtS maps) that do happen after the borders pop several times doesn't matter. It is even more the case since starting star systems are usually pretty far apart and before you can settle much closer you'll most likely have the tech that removes the restriction (with the restriction in place you have to send out colony ships with no real combat capable escort, which is very risky and therefore not likely to happen very often). So in this case, I think that doing anything more complicated to keep track of it would be unnecessary. It might be desirable to add a check in the code for when a starbase is built to allow movement into the newly controlled area as well, in case it is connect to existing territory, which would allow building corridors of controlled territory between systems to allow movement between them before the restriction removing tech is researched.

But doing without the cached restrictions, as I suggest above, makes it all irrelevant. The restrictions will always be correct since they are always calculated.

By the way, a "work around" for the problem in the current version of B5, for the human player only since there is no way to get the AI to do this, is to simply never try to move the affected ship types outside your borders until you get the restriction removing tech. That way no restrictions will be saved so there will be no problem with residual impassible plots as borders expand.
 
Following the instructions given here...
Quote:
Originally Posted by PsiCorps
Where/how would I go about doing either of these things?

The easiest method is to simply not store the restriction data, just check it each time. This will increase the amount of time it takes on average for each movement check slightly (but reduce the amount of memory used, although in comparison to the amount the game uses it is trivial). Since the restriction is removed once the tech is researched, which is relatively early in the game, the slower code will only be used early in the game when there are only a small number of units so the net effect should be very small.

To do this, remove references to unitCannotMoveIntoDict.

First, well first keep a copy of what you have now...

Second, remove this line that initially defines the variable:

Code:
unitCannotMoveIntoDict = dict()

Then remove the lines referencing it in the function and defining the key used for the dictionary, and unindent one section of code.

Remove:

Code:
tKey = ePlayer, eUnitType, iX, iY
		bRestricted = self.unitCannotMoveIntoDict.get(tKey, None)
		if bRestricted == None:

and

Code:
self.unitCannotMoveIntoDict[tKey] = bRestricted

Then, finally, reduce by one level the indentation of all the code that used to be inside the "if" block for the now removed "if bRestricted == None:" statement .

That ought to do the trick.

The degree to which turn processing is slower will probably be unnoticeably small, and nonexistent once everyone has the tech to remove the restriction.

Edit: By the way, if you were interested in resetting the data on border growth the correct event hander is onCultureExpansion, not the onCityGrowth (which is for population changes) that I mentioned in the earlier post. Population grows, borders expand. Oops.
Assuming I have read everything correctly my new code looks like this
Code:
# start unit movement restriction code

	unitCombatDict = dict()
	deactivated = set()

	def unitCannotMoveInto(self,argsList):
		ePlayer, iUnit, iX, iY = argsList
		if ePlayer in self.deactivated:
			return False
		else:
			if gc.getTeam(gc.getPlayer(ePlayer).getTeam()).isHasTech(gc.getInfoTypeForString("TECH_B5_SHIP_CONSTRUCTION")) or gc.getPlayer(ePlayer).isBarbarian():
				self.deactivated.add(ePlayer)
				return False
		eUnitType = gc.getPlayer(ePlayer).getUnit(iUnit).getUnitType()
		eUnitCombat = self.unitCombatDict.get(eUnitType, None)
		if eUnitCombat == None:
			eUnitCombat = gc.getUnitInfo(eUnitType).getUnitCombatType()
			self.unitCombatDict[eUnitType] = eUnitCombat
		if eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_FRIGATE"):
			bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
		elif eUnitCombat == gc.getInfoTypeForString("UNITCOMBAT_DESTROYER"):
			bRestricted = gc.getMap().plot(iX, iY).getOwner() != ePlayer
		else:
				bRestricted = False
		return bRestricted

# end unit movement restriction code
I'll assume it's correct and test it. If there are any mistakes in what I've done i'm sure the testing will reveal it.
 
Back
Top Bottom