EmperorFool
Deity
BTW, can you post more context? I always wonder what's above when I see a dangling "elif" all by itself. And yes, you still need to address the pUnit2Type problem.
BTW, can you post more context? I always wonder what's above when I see a dangling "elif" all by itself. And yes, you still need to address the pUnit2Type problem.
def onUnitMove(self, argsList):
'unit move'
pPlot,pUnit,pOldPlot = argsList
player = PyPlayer(pUnit.getOwner())
unitInfo = PyInfo.UnitInfo(pUnit.getUnitType())
# Mine Warfare Mod
# Naval
iUnitNavalMine = gc.getInfoTypeForString("UNIT_NAVAL_MINE")
iUnitNavalMineField = gc.getInfoTypeForString("UNIT_NAVAL_MINE_FIELD")
iUnitNuclearNavalMine = gc.getInfoTypeForString("UNIT_NUCLEAR_NAVAL_MINE")
iUnitNavalMineSweeper = gc.getInfoTypeForString("UNIT_NAVAL_MINE_SWEEPER")
# Land
iUnitLandMine = gc.getInfoTypeForString("UNIT_LAND_MINE")
iUnitLandMineField = gc.getInfoTypeForString("UNIT_LAND_MINE_FIELD")
iUnitNuclearLandMine = gc.getInfoTypeForString("UNIT_NUCLEAR_LAND_MINE")
iUnitLandMineSweeper = gc.getInfoTypeForString("UNIT_LAND_MINE_SWEEPER")
# Combat Units
iArmorUnits = gc.getInfoTypeForString("UNITCOMBAT_ARMOR")
iHelicopterUnits = gc.getInfoTypeForString("UNITCOMBAT_HELICOPTER")
iAirUnits = gc.getInfoTypeForString("UNITCOMBAT_AIR")
iMineWarfare = gc.getInfoTypeForString("UNITCOMBAT_MINE_WARFARE")
CombatList = [
iArmorUnits,
iHelicopterUnits,
iAirUnits,
iMineWarfare
]
MasterMineList = [
iUnitNavalMine,
iUnitNavalMineField,
iUnitNuclearNavalMine,
iUnitLandMine,
iUnitLandMineField,
iUnitNuclearLandMine
]
MineList = [
iUnitNavalMine,
iUnitLandMine,
]
MineFieldList = [
iUnitNavalMineField,
iUnitLandMineField
]
SweeperList = [
iUnitNavalMineSweeper,
iUnitLandMineSweeper
]
FoundMine = False
MineBlownup = False
UnitBlownup = False
UnitsBlownup = False
AIRemoveMine = False
iCount = 0
for iUnitLoop in range (pPlot.getNumUnits()):
pUnit1 = pPlot.getUnit(iUnitLoop)
pUnit1Type = pUnit1.getUnitType()
# Is this a mine?
if (pUnit1Type in MasterMineList):
FoundMine = True
break
if FoundMine:
for iUnitLoop in range (pPlot.getNumUnits()):
pUnit2 = pPlot.getUnit(iUnitLoop)
pUnit2Type = pUnit2.getUnitType()
pUnit2CombatType = pUnit2.getUnitCombatType()
if pUnit2Type != -1:
info = gc.getUnitInfo(pUnit2Type)
if (info != -1):
iTech = info.getPrereqAndTech()
if iTech != -1:
iEra = gc.getTechInfo(iTech).getEra()
else:
iEra = 0
else:
iMaxEra = -1
if pUnit1.getOwner() != pUnit2.getOwner():
# is pUnit2 a Sweeper?
if (pUnit2Type in SweeperList):
if gc.getPlayer(pUnit2.getOwner()).isHuman( ):
CyAudioGame().Play2DSound("AS2D_SHIP_RED_ALERT")
CyInterface().addImmediateMessage("You have discovered an enemy mine!", "")
break
else:
# AI removes the Mine.
UnitName = pUnit1.getName()
AIRemoveMine = True
break
[COLOR="Red"][B]elif not (pUnit2Type in CombatList):[/B][/COLOR]
# pUnit2 is not a Sweeper.
if (pUnit1Type in MineList):
# Blow up the one unit.
UnitName = pUnit2.getName()
pUnit2.kill( -1, -1 )
UnitBlownup = True
MineBlownup = True
break
elif (pUnit1Type in MineFieldList):
if not (pUnit2Type in MasterMineList):
if MineWarfare.RandumChanceToDestroyUnit(pPlot, pUnit2, iEra):
pUnit2.kill( 0, -1 )
iCount = iCount + 1
UnitsBlownup = True
else:
UnitsBlownup = False
if AIRemoveMine:
CyInterface().addImmediateMessage("Your " + str(UnitName) + " was removed by a Minesweeper" , "")
# Destroy the Mine.
CyAudioGame().Play2DSound("AS2D_SHIP_LOAD_MINE")
pUnit1.kill( 0, -1 )
if UnitBlownup:
CyEngine().triggerEffect(gc.getInfoTypeForString("EFFECT_EXPLOSION_LARGE_001"), pPlot.getPoint())
CyAudioGame().Play2DSound("AS2D_LAND_MINE_EXPLOSION")
CyInterface().addImmediateMessage("An enemy " + str(UnitName) + " was blown up by your mine!", "")
if MineBlownup:
# Destroy the Mine.
pUnit1.kill( 0, -1 )
if UnitsBlownup:
CyEngine().triggerEffect(gc.getInfoTypeForString("EFFECT_EXPLOSION_LARGE_001"), pPlot.getPoint())
CyAudioGame().Play2DSound("AS2D_LAND_MINE_EXPLOSION")
CyInterface().addImmediateMessage("One or more units were blown up by your mine field!", "")
# Mine Warfare Mod
if (not self.__LOG_MOVEMENT):
return
if player and unitInfo:
CvUtil.pyPrint('Player %d Civilization %s unit %s is moving to %d, %d'
%(player.getID(), player.getCivilizationName(), unitInfo.getDescription(),
pUnit.getX(), pUnit.getY()))
elif not (pUnit2[B][COLOR="Red"]Combat[/COLOR][/B]Type in CombatList):
elif not ([COLOR="red"]pUnit2Type[/COLOR] in CombatList):
elif not ([COLOR="Red"]pUnit2CombatType[/COLOR] in CombatList):
Okay, thanks. BTW, third time: change that red line to this:
Code:elif not (pUnit2[B][COLOR="Red"]Combat[/COLOR][/B]Type in CombatList):
You really should move the construction of all those lists outside of the onUnitMove() function to improve performance. You are building and destroying those lists every time a unit moves!I would say to move them to the __init__() function, but I don't recall if they will work there. CvEventManager is created early on in the initialization cycle--probably before that stuff is ready.
You really should move the construction of all those lists outside of the onUnitMove() function to improve performance. You are building and destroying those lists every time a unit moves!I would say to move them to the __init__() function, but I don't recall if they will work there. CvEventManager is created early on in the initialization cycle--probably before that stuff is ready.
class CvEventManager:
def __init__(self):
...
[B]self.unitTypeList[/B] = [ blah blah blah]
...
def onUnitBuilt(self, argsList):
...
if iUnitType in [B]self.unitTypeList[/B]:
...
If you move them to __init__() you must put "self." in front of them all when creating and using them. This places them as variables of the CvEventManager object itself (self).
Code:class CvEventManager: def __init__(self): ... [B]self.unitTypeList[/B] = [ blah blah blah] ... def onUnitBuilt(self, argsList): ... if iUnitType in [B]self.unitTypeList[/B]: ...
If you were using BUG you could put all this into a module-level init() function that BUG would call as your mod starts up.
iDistance = CyMap().calculatePathDistance(pUnitPlot, pLoopPlot)
if iDistance > 0 and iDistance < iMaxRange:
Problem is the command fails to return anything but -1 for Ocean plots. Looking at the rules for this command; If a mine has just been built in a city, is the city considered a land plot? If so, how can I get around this rule?
I can't even look at the A* path-finding code to verify that this is correct since it's in the EXE.Go with The_J's suggestion by looping over all plots around the city and getting the path for each one that is water and in the same area (or maybe skip this check) and pick the one with the shortest path. Or just pick the first water tile's distance.
Loop through all the plots adjacent to the city looking for one that's not a fresh-water lake.
def doPreAI_NavalMinePlacement(pUnit):
FoundCoastalPlot = False
iOwner = pUnit.getOwner()
AIpPlayer = gc.getPlayer(iOwner)
iX = pUnit.getX()
iY = pUnit.getY()
pUnitPlot = CyMap().plot(iX, iY)
# Make sure this is an AI Player
if not AIpPlayer.isHuman():
for iiX in range(iX-1, iX+1, 1):
for iiY in range(iY-1, iY+1, 1):
pAdjacentPlot = CyMap().plot(iiX,iiY)
if pAdjacentPlot.isNone() == False:
iTerrain = pAdjacentPlot.getTerrainType()
if iTerrain == gc.getInfoTypeForString("TERRAIN_COAST"):
if not pAdjacentPlot.isFreshWater():
if not hasFriendlyMine(pAdjacentPlot, iOwner):
FoundCoastalPlot = True
CoastalPlot = pAdjacentPlot
break
if FoundCoastalPlot:
pUnit.getGroup().pushMission(MissionTypes.MISSION_MOVE_TO, CoastalPlot.getX( ), CoastalPlot.getY( ), 0, False, True, MissionAITypes.NO_MISSIONAI, pUnit.plot(), pUnit)
#CyInterface().addImmediateMessage("Found Coastal Plot", "")
CyInterface().addImmediateMessage("Moved the Mine!", "")
Two things.
1) Instead of pAdjacentPlot.isFreshWater() you should probably be using pAdjacentPlot.isLake().
2) By checking to see if there is already a friendly mine on the plot, you can apparently make it impossible for the new mine to leave the city. For example, say the city is at the end of one of those 1 tile wide estuaries (so the city only has 1 ocean tile adjacent to it). You deliberately place a mine there (it is probably a good place for one). Your algorithm will no longer move a new mine out of the city. You need to differentiate between an unarmed mine and armed mines: even if you can only have one armed mine on a plot doesn't mean you shouldn't be able to move unarmed mines through that plot.
for iiX in range(iX-1, iX+2):
for iiY in range(iY-1, iY+2):
I just noticed something:
In the iiX and iiY loops, the range() function is wrong. You need to increase the upper end of the range by 1 since range(i,j,1) includes i but not j, it stops at j-1. The second argument is not the highest value or the count of the number of values, it is the value which makes the generator stop producing numbers if the next one would be greater than or equal to it.
So you need
You can leave the ",1" off the end since that is the default.Code:for iiX in range(iX-1, iX+2): for iiY in range(iY-1, iY+2):
Using range(3) is the same as range(0,3,1), they both produce the numbers 0, 1, and 2 but not 3. Using range(1,3) is the same as range(1,3,1), they both produce the numbers 1 and 2 but not 3.
def doPreAI_NavalMinePlacement(pUnit):
FoundCoastalPlot = False
iOwner = pUnit.getOwner()
AIpPlayer = gc.getPlayer(iOwner)
iX = pUnit.getX()
iY = pUnit.getY()
pUnitPlot = CyMap().plot(iX, iY)
# Make sure this is an AI Player
if not AIpPlayer.isHuman():
for iiX in range(iX-1, iX+2):
for iiY in range(iY-1, iY+2):
pAdjacentPlot = CyMap().plot(iiX,iiY)
if pAdjacentPlot.isNone() == False:
# LoopPlot must be unowned or owned by the AI Player
if (pAdjacentPlot.getOwner() == -1) or (pAdjacentPlot.getOwner() == iOwner):
# Make sure this is not a city.
if not pAdjacentPlot.isCity():
iTerrain = pAdjacentPlot.getTerrainType()
if iTerrain == gc.getInfoTypeForString("TERRAIN_COAST"):
if not pAdjacentPlot.isLake():
FoundCoastalPlot = True
CoastalPlot = pAdjacentPlot
break
if FoundCoastalPlot:
break
if FoundCoastalPlot:
pUnit.getGroup().pushMission(MissionTypes.MISSION_MOVE_TO, CoastalPlot.getX( ), CoastalPlot.getY( ), 0, False, True, MissionAITypes.NO_MISSIONAI, pUnit.plot(), pUnit)
CyInterface().addImmediateMessage("Moved the Mine!", "")