250 lines
8.8 KiB
Python
250 lines
8.8 KiB
Python
from CrateGlobals import *
|
|
from otp.level import DistributedEntityAI
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
|
|
class DistributedGridAI(DistributedEntityAI.DistributedEntityAI):
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGridAI')
|
|
|
|
def __init__(self, level, entId):
|
|
self.initialized = 0
|
|
DistributedEntityAI.DistributedEntityAI.__init__(self, level, entId)
|
|
self.activeCellList = []
|
|
|
|
def delete(self):
|
|
DistributedEntityAI.DistributedEntityAI.delete(self)
|
|
del self.activeCellList
|
|
|
|
def generate(self):
|
|
DistributedEntityAI.DistributedEntityAI.generate(self)
|
|
|
|
def initializeGrid(self):
|
|
if not self.initialized:
|
|
self.objPos = {}
|
|
self.gridCells = [None] * self.numRow
|
|
for i in xrange(len(self.gridCells)):
|
|
self.gridCells[i] = [None] * self.numCol
|
|
for j in xrange(len(self.gridCells[i])):
|
|
self.gridCells[i][j] = []
|
|
|
|
self.initialized = 1
|
|
return
|
|
|
|
def addActiveCell(self, cell):
|
|
self.activeCellList.append(cell)
|
|
|
|
def getObjPos(self, objId):
|
|
objPos = self.objPos.get(objId, None)
|
|
if objPos:
|
|
row, col = objPos
|
|
if row >= 0 and row < self.numRow and col >= 0 and col < self.numCol:
|
|
return [(col + 1) * self.cellSize, (row + 1) * self.cellSize, 0]
|
|
else:
|
|
self.notify.debug('row/col out of range %s/%s' % (row, col))
|
|
else:
|
|
self.notify.debug("didn't have record of obj")
|
|
return
|
|
|
|
def addObjectByPos(self, objId, pos, width = 1):
|
|
if not self.initialized:
|
|
self.initializeGrid()
|
|
if self.objPos.get(objId, None):
|
|
return 1
|
|
x, y = pos[0], pos[1]
|
|
col = min(int(x / self.cellSize), self.numCol - width)
|
|
row = min(int(y / self.cellSize), self.numRow - width)
|
|
self.notify.debug('attempt add %d at %s, row,col = %d,%d' % (objId,
|
|
pos,
|
|
row,
|
|
col))
|
|
while col >= 0 and col < self.numCol:
|
|
while row >= 0 and row < self.numRow:
|
|
if self.addObjectByRowCol(objId, row, col):
|
|
return 1
|
|
else:
|
|
row += 2
|
|
else:
|
|
row = 0
|
|
col += 2
|
|
|
|
else:
|
|
self.notify.debug('requestObjPos: row/col out of range %s/%s' % (row, col))
|
|
row = min(row, self.numRow)
|
|
row = max(0, row)
|
|
col = min(col, self.numRow)
|
|
col = max(0, col)
|
|
return self.addObjectByRowCol(objId, row, col)
|
|
|
|
return
|
|
|
|
def addObjectByRowCol(self, objId, row, col):
|
|
if row >= 0 and row < self.numRow - 1 and col >= 0 and col < self.numCol - 1:
|
|
self.notify.debug('adding obj %s to grid cell %s,%s' % (objId, row, col))
|
|
self.gridCells[row][col].append(objId)
|
|
self.gridCells[row + 1][col].append(objId)
|
|
self.gridCells[row][col + 1].append(objId)
|
|
self.gridCells[row + 1][col + 1].append(objId)
|
|
self.objPos[objId] = [row, col]
|
|
self.__setChangedActiveCells(onList=[[row, col],
|
|
[row + 1, col],
|
|
[row, col + 1],
|
|
[row + 1, col + 1]], objId=objId)
|
|
return 1
|
|
self.notify.debug("couldn't obj to grid cell %s,%s" % (row, col))
|
|
return 0
|
|
|
|
def removeObject(self, objId):
|
|
objPos = self.objPos.get(objId)
|
|
if not objPos:
|
|
return
|
|
row, col = objPos
|
|
self.notify.debug('removing obj %s from %s, %s' % (objId, row, col))
|
|
self.gridCells[row][col].remove(objId)
|
|
self.gridCells[row + 1][col].remove(objId)
|
|
self.gridCells[row][col + 1].remove(objId)
|
|
self.gridCells[row + 1][col + 1].remove(objId)
|
|
del self.objPos[objId]
|
|
self.__setChangedActiveCells(offList=[[row, col],
|
|
[row + 1, col],
|
|
[row, col + 1],
|
|
[row + 1, col + 1]], objId=objId)
|
|
|
|
def checkMoveDir(self, objId, h):
|
|
if h > 225 and h < 315:
|
|
return self.checkMove(objId, 0, 1)
|
|
elif h > 45 and h < 135:
|
|
return self.checkMove(objId, 0, -1)
|
|
elif h < 45 or h > 315:
|
|
return self.checkMove(objId, 1, 0)
|
|
elif h > 135 and h < 225:
|
|
return self.checkMove(objId, -1, 0)
|
|
|
|
def doMoveDir(self, objId, h):
|
|
if h > 225 and h < 315:
|
|
return self.doMove(objId, 0, 1)
|
|
elif h > 45 and h < 135:
|
|
return self.doMove(objId, 0, -1)
|
|
elif h < 45 or h > 315:
|
|
return self.doMove(objId, 1, 0)
|
|
elif h > 135 and h < 225:
|
|
return self.doMove(objId, -1, 0)
|
|
|
|
def checkPush(self, objId, side):
|
|
if side == 0:
|
|
return self.checkMove(objId, 0, -1)
|
|
elif side == 1:
|
|
return self.checkMove(objId, 0, 1)
|
|
elif side == 2:
|
|
return self.checkMove(objId, -1, 0)
|
|
elif side == 3:
|
|
return self.checkMove(objId, 1, 0)
|
|
|
|
def doPush(self, objId, side):
|
|
if side == 0:
|
|
return self.doMove(objId, 0, -1)
|
|
elif side == 1:
|
|
return self.doMove(objId, 0, 1)
|
|
elif side == 2:
|
|
return self.doMove(objId, -1, 0)
|
|
elif side == 3:
|
|
return self.doMove(objId, 1, 0)
|
|
|
|
def checkMove(self, objId, dRow, dCol):
|
|
objPos = self.objPos.get(objId)
|
|
if not objPos:
|
|
return
|
|
row, col = objPos
|
|
validMove = 1
|
|
if dRow < 0:
|
|
validMove = validMove & self.__isEmpty(row - 1, col) & self.__isEmpty(row - 1, col + 1)
|
|
elif dRow > 0:
|
|
validMove = validMove & self.__isEmpty(row + 2, col) & self.__isEmpty(row + 2, col + 1)
|
|
if dCol < 0:
|
|
validMove = validMove & self.__isEmpty(row, col - 1) & self.__isEmpty(row + 1, col - 1)
|
|
elif dCol > 0:
|
|
validMove = validMove & self.__isEmpty(row, col + 2) & self.__isEmpty(row + 1, col + 2)
|
|
return validMove
|
|
|
|
def doMove(self, objId, dRow, dCol):
|
|
objPos = self.objPos.get(objId)
|
|
if not objPos:
|
|
return 0
|
|
row, col = objPos
|
|
validMove = self.checkMove(objId, dRow, dCol)
|
|
if validMove:
|
|
self.gridCells[row][col].remove(objId)
|
|
self.gridCells[row + 1][col].remove(objId)
|
|
self.gridCells[row][col + 1].remove(objId)
|
|
self.gridCells[row + 1][col + 1].remove(objId)
|
|
newRow = row + dRow
|
|
newCol = col + dCol
|
|
self.gridCells[newRow][newCol].append(objId)
|
|
self.gridCells[newRow + 1][newCol].append(objId)
|
|
self.gridCells[newRow][newCol + 1].append(objId)
|
|
self.gridCells[newRow + 1][newCol + 1].append(objId)
|
|
self.objPos[objId] = [newRow, newCol]
|
|
self.updateActiveCells(objId, row, col, dRow, dCol)
|
|
return validMove
|
|
|
|
def updateActiveCells(self, objId, row, col, dRow, dCol):
|
|
newRow = row + dRow
|
|
newCol = col + dCol
|
|
newCells = [[newRow, newCol],
|
|
[newRow + 1, newCol],
|
|
[newRow, newCol + 1],
|
|
[newRow + 1, newCol + 1]]
|
|
oldCells = [[row, col],
|
|
[row + 1, col],
|
|
[row, col + 1],
|
|
[row + 1, col + 1]]
|
|
onList = []
|
|
offList = []
|
|
for cell in newCells:
|
|
if cell not in oldCells:
|
|
onList.append(cell)
|
|
|
|
for cell in oldCells:
|
|
if cell not in newCells:
|
|
offList.append(cell)
|
|
|
|
self.__setChangedActiveCells(onList, offList, objId)
|
|
|
|
def __setChangedActiveCells(self, onList = [], offList = [], objId = None):
|
|
for cell in self.activeCellList:
|
|
self.notify.debug('onList = %s, offList = %s, cell = %s' % (onList, offList, cell.getRowCol()))
|
|
if cell.getRowCol() in onList:
|
|
cell.b_setState(1, objId)
|
|
elif cell.getRowCol() in offList:
|
|
cell.b_setState(0, objId)
|
|
|
|
def __isEmpty(self, row, col):
|
|
if row < 0 or row >= self.numRow or col < 0 or col >= self.numCol:
|
|
return 0
|
|
if len(self.gridCells[row][col]) > 0:
|
|
return 0
|
|
return 1
|
|
|
|
def printGrid(self):
|
|
if not __debug__:
|
|
return
|
|
for i in xrange(len(self.gridCells)):
|
|
str = ''
|
|
for j in xrange(len(self.gridCells[i])):
|
|
col = self.gridCells[i][j]
|
|
active = 0
|
|
for cell in self.activeCellList:
|
|
if cell.getRowCol() == [i, j]:
|
|
active = 1
|
|
|
|
if len(col) > 0:
|
|
if active:
|
|
str += '[X]'
|
|
else:
|
|
str += ' X '
|
|
elif active:
|
|
str += '[.]'
|
|
else:
|
|
str += ' . '
|
|
|
|
print str + ' : %d' % i
|
|
|
|
print ''
|