def test_logger_error_level(tc_unittest): temp_file = tc_unittest.get_temp_file() logger = Logger("UnitTest", temp_file, logging.ERROR) logger.info("InfoMessage") logger.debug("DebugMessage") logger.error("ErrorMessage") assert " - UnitTest - INFO - InfoMessage" not in temp_file.read_text() assert " - UnitTest - ERROR - ErrorMessage" in temp_file.read_text() assert " - UnitTest - DEBUG - DebugMessage" not in temp_file.read_text()
class Astar(): """ - edges is List<Edge> - last_analyzed is Boolean - log is Logger - nodes is List<Node> - pq is PriorityNodes - solved is Boolean - start is Node - target is Node """ def __init__(self, nodes, edges): self._log = Logger() self._nodes = nodes self._edges = edges self._last_analyzed = None self._solved = False self._start = None self._target = None self._pq = None self.resetAlgorithm() self._log.debug( "Astar", "Init Object -- {} Nodes -- {} Edges".format( len(nodes), len(edges))) @property def last_analyzed(self): return self._last_analyzed @property def solved(self): return self._solved @property def start(self): return self._start @property def target(self): return self._target def nextIteration(self): current = self._pq.pop() self._last_analyzed = current if current.state == NodeState.TARGET: self._solved = True return if not current.state == NodeState.START: current.state = NodeState.BLACK for node in current.neighbours: if node.state == NodeState.BLACK: continue edge = self._edgeBy(current, node) if edge == None: self._log.info("Astar", "EXPECTED AN EDGE, BUT NONE WAS RETURNED") exit(1) left_to_target = self._target.cell.point.distance(node.cell.point) manhattan_value = current.manhattan + left_to_target + edge.cost if node.state == NodeState.WHITE or node.state == NodeState.TARGET: node.manhattan = manhattan_value node.parent = current node.state = NodeState.GRAY self._emplace(node.cell.point) elif node.state == NodeState.GRAY or node.state == NodeState.TARGET: if node.manhattan > manhattan_value: node.manhattan = manhattan_value node.parent = current if self._target == node: self._solved = True return def nextIterationNeighbourPriority(self): current = self._pq.pop() if not self._last_analyzed == None: is_neighbour = current.isNeighbour(self._last_analyzed) if not is_neighbour or not self._last_analyzed.isNeighbour( current): return if current == None: self._target = None return self._last_analyzed = current if current.state == NodeState.TARGET: self._solved = True return if not current.state == NodeState.START: current.state = NodeState.BLACK for node in current.neighbours: if node.state == NodeState.BLACK: continue edge = self._edgeBy(current, node) if edge == None: self._log.info("Astar", "EXPECTED AN EDGE, BUT NONE WAS RETURNED") exit(1) left_to_target = self._target.cell.point.distance(node.cell.point) manhattan_value = current.manhattan + left_to_target + edge.cost if node.state == NodeState.WHITE or node.state == NodeState.TARGET: node.manhattan = manhattan_value node.parent = current node.state = NodeState.GRAY self._emplace(node.cell.point) elif node.state == NodeState.GRAY or node.state == NodeState.TARGET: if node.manhattan > manhattan_value: node.manhattan = manhattan_value node.parent = current if self._target == node: self._solved = True return def noOptionsLeft(self): if not self._target == None: return self._pq.empty() return False def noSolution(self): return self._pq.empty() def resetLastAnalysed(self): self._last_analyzed = None def resetManhattan(self): for node in self._nodes: node.resetManhattan() def resetParents(self): for node in self._nodes: node.resetParent() def resetPriorityQueue(self): self._pq = PriorityNodes() def resetSolved(self): self._solved = False def resetStart(self): self._start = None def resetStates(self): for node in self._nodes: node.resetState() def resetTarget(self): self._target = None def resetAlgorithm(self): self.resetSolved() self.resetStates() self.resetManhattan() self.resetPriorityQueue() self.resetParents() self.resetStart() self.resetTarget() self.resetLastAnalysed() def updateNodeToStateStartBy(self, cell): self._updateStateOf(cell.point, NodeState.START) self._updateManhattanOf(cell.point, 0) self._emplace(cell.point) self._start = self._nodeByCoordinate(cell.point) def updateNodeToStateTargetBy(self, cell): self._updateStateOf(cell.point, NodeState.TARGET) self._target = self._nodeByCoordinate(cell.point) def _edgeBy(self, node, neighbour): for edge in self._edges: if edge.src.cell.point == node.cell.point and edge.dst.cell.point == neighbour.cell.point: # self._log.debug("Astar", "Returning the edge {}".format(str(edge))) return edge if edge.dst.cell.point == node.cell.point and edge.src.cell.point == neighbour.cell.point: # self._log.debug("Astar", "Returning the edge {}".format(str(edge))) return edge return None def _emplace(self, coord): node = self._nodeByCoordinate(coord) self._pq.insert(node) def _nodeByCoordinate(self, coord): for node in self._nodes: if node.cell.point == coord: return node return None def _updateManhattanOf(self, coord, val): current = self._nodeByCoordinate(coord) current.manhattan = val def _updateStateOf(self, coord, val): node = self._nodeByCoordinate(coord) node.state = val
class Maze: """ - edges is List<Edge> - log is Logger - map is List<List<Cell>> - nodes is List<List<Nodes>> - rooms is List<Room> """ def __init__(self, height, width, rooms_count): self._log = Logger() self._log.debug("Maze", "Object Init") self._initMap(height, width) self._markWalls() self._initRooms(rooms_count) self._initNodes() self._initEdges() self._connectRooms() self._teams = [] @property def edges(self): return self._edges @property def rooms(self): return self._rooms @property def teams(self): return self._teams def height(self): return len(self._map) def placeBox(self, box): # TODO # validate the box exists # place randomly box in one of the rooms pass def placePackage(self, package): room = self._randomRoom() free_cell = self._randomFreeFloorCell(room) free_cell.obj = package def placeTeam(self, team): room = self._roomWithoutSoldiers() if room == None: self._log.info("Maze", "NO ROOM FOR TEAM PLACEMENT") exit(1) for soldier in team.soldiers: self._mapSoldierToCell(soldier, room) self._teams.append(team) def uniqueNodesSharedCells(self): result = [] for row in self._map: for cell in row: if cell.isPassable(): result.append(Node(cell)) for node in result: for other in result: if node.cell.point.distance(other.cell.point) == 1: node.addNeighbour(other) return result def updateTeamsState(self): to_remove = [] for team in self._teams: if team.isEmpty(): to_remove.append(team) for team in to_remove: self._teams.remove(team) def width(self): return len(self._map[0]) def _cellBy(self, point): for row in self._map: for cell in row: if cell.point == point: return cell return None def _connectRooms(self): self._log.debug("Maze", "Connect {} Rooms".format(len(self.rooms))) nodes = [] connected = dict() for room in self._rooms: connected[room] = [] for row in self._nodes: for node in row: nodes.append(node) astar = Astar(nodes, self._edges) for room in self._rooms: for other in self._rooms: if not room == other and not other in connected[room]: self._log.debug( "Maze", "Connecting room center {} to room center {}".format( str(room.center.point), str(other.center.point))) astar.resetAlgorithm() astar.updateNodeToStateStartBy(room.center) astar.updateNodeToStateTargetBy(other.center) while not astar.solved: if astar.noSolution(): self._log.info( "Maze", "NO PATH WAS FOUND BETWEEN THE ROOMS") exit(1) astar.nextIteration() target = astar.target if target == None or target.parent == None: self._log.info( "Maze", "EXPECTED A PATH, BUT NONE WAS RETURNED") exit(1) self._markPathAndEntrances(target) connected[room].append(other) connected[other].append(room) def _initEdges(self): self._edges = [] i = 1 while i < len(self._nodes): j = 1 while j < len(self._nodes[i]): node = self._nodes[i][j] if i - 1 >= 0: self._registerNeighbours(node, self._nodes[i - 1][j]) if j - 1 >= 0: self._registerNeighbours(node, self._nodes[i][j - 1]) if j + 1 < len(self._nodes[i]): self._registerNeighbours(node, self._nodes[i][j + 1]) if i + 1 < len(self._nodes): self._registerNeighbours(node, self._nodes[i + 1][j]) j += 1 i += 1 self._log.info("Maze", "Init -- {} Edges".format(str(len(self._edges)))) def _initMap(self, height, width): self._log.info("Maze", "Init Map -- {} x {} Cells".format(height, width)) result = [] i = 0 while i < height: row = [] j = 0 while j < width: row.append(Cell(CellType.SPACE, i, j)) j += 1 result.append(row) i += 1 self._map = result def _initNodes(self): result = [] for row in self._map: row_of_nodes = [] for cell in row: row_of_nodes.append(Node(cell)) result.append(row_of_nodes) self._nodes = result self._log.info( "Maze", "Init -- {} x {} Nodes".format(str(self.height()), str(self.width()))) def _initRoom(self): max_size = self.height() - 1 height = self._roomHeight(max_size) width = self._roomWidth(max_size) result = Room(height, width, self._roomCenter(height, max_size, width, max_size)) return result def _initRooms(self, count): self._log.info("Maze", "Init {} Rooms".format(count)) seed() result = [] while count > 0: candidate = self._initRoom() if self._roomSizeIllegal(candidate): continue rooms_overlap = False i = 0 while i < len(result) and not rooms_overlap: rooms_overlap = self._roomsOverlap(result[i], candidate) if rooms_overlap: break i += 1 if rooms_overlap: continue else: self._markFloor(candidate) result.append(candidate) count -= 1 self._rooms = result def _mapSoldierToCell(self, soldier, room): self._log.debug("Maze", "Map Soldier to Cell") for cell in room.floor: if cell.isTraversable(): soldier.at = cell cell.obj = soldier return def _markFloor(self, room): i = int(room.center.point.x - room.width / 2) while i < int(room.center.point.x + room.width / 2): j = int(room.center.point.y - room.height / 2) while j < int(room.center.point.y + room.height / 2): cell = self._map[i][j] cell.kind = CellType.FLOOR room.appendCell(cell) j += 1 i += 1 def _markPathAndEntrances(self, target): last_cell = None while not target.parent == None: cell = self._cellBy(target.cell.point) if cell == None: self._log.info( "Maze", "EXPECTED A CELL OBJECT FOR PATH MARK, GOT NONE") exit(1) if cell.kind == CellType.SPACE: cell.kind = CellType.PATH if not last_cell == None: if last_cell.kind == CellType.FLOOR and cell.kind == CellType.PATH: last_cell.kind = CellType.ENTRANCE elif cell.kind == CellType.FLOOR and last_cell.kind == CellType.PATH: cell.kind = CellType.ENTRANCE last_cell = cell target = target.parent def _markWalls(self): self._log.debug("Maze", "Mark Walls") for row in self._map: next_cell = row[0] next_cell.kind = CellType.WALL next_cell = row[self.width() - 1] next_cell.kind = CellType.WALL for c in self._map[0]: c.kind = CellType.WALL for c in self._map[self.height() - 1]: c.kind = CellType.WALL def _randomFreeFloorCell(self, room): seed() while True: cell_index = randint(0, len(room.floor) - 1) cell = room.floor[cell_index] if cell.isFloor() and cell.isEmpty(): neighbour = room.cellBy(cell.point.x + 1, cell.point.y) if not neighbour == None and not cell.isEmpty(): continue neighbour = room.cellBy(cell.point.x + 1, cell.point.y + 1) if not neighbour == None and not cell.isEmpty(): continue neighbour = room.cellBy(cell.point.x + 1, cell.point.y - 1) if not neighbour == None and not cell.isEmpty(): continue neighbour = room.cellBy(cell.point.x, cell.point.y + 1) if not neighbour == None and not cell.isEmpty(): continue neighbour = room.cellBy(cell.point.x, cell.point.y - 1) if not neighbour == None and not cell.isEmpty(): continue neighbour = room.cellBy(cell.point.x - 1, cell.point.y) if not neighbour == None and not cell.isEmpty(): continue neighbour = room.cellBy(cell.point.x - 1, cell.point.y - 1) if not neighbour == None and not cell.isEmpty(): continue neighbour = room.cellBy(cell.point.x - 1, cell.point.y + 1) if not neighbour == None and not cell.isEmpty(): continue return cell def _randomRoom(self): seed() room_index = randint(0, len(self._rooms) - 1) return self._rooms[room_index] def _registerNeighbours(self, node, other): node.addNeighbour(other) self._edges.append( Edge(node, other, node.cell.point.distance(other.cell.point))) def _roomCenter(self, height, max_height, width, max_width): y = int(1 + (height / 2) + randint(0, max_height) % (max_height - height - 2)) x = int(1 + (width / 2) + randint(0, max_width) % (max_width - width - 2)) result = self._map[x][y] return result def _roomHeight(self, size): result = 7 + randint(0, size) % (size / 5) return int(result) def _roomWidth(self, size): return self._roomHeight(size) def _roomsOverlap(self, room, other): result = False vertical_dist = abs(room.center.point.x - other.center.point.x) horizontal_dist = abs(room.center.point.y - other.center.point.y) h_overlap = room.height / 2 + other.height / 2 > horizontal_dist - 4 v_overlap = room.width / 2 + other.width / 2 > vertical_dist - 4 result = h_overlap and v_overlap return result def _roomSizeIllegal(self, room): cx = room.center.point.x cy = room.center.point.y height = room.height width = room.width if (cx + width / 2 > self.width() - 3) or (cx - width / 2 < 2): return True if (cy + height / 2 > self.height() - 3) or (cy - height / 2 < 2): return True return False def _roomWithoutSoldiers(self): for room in self._rooms: hasSoldiers = False for cell in room.floor: if cell.kind == CellType.FLOOR and isinstance( cell.obj, Soldier): hasSoldiers = True break if not hasSoldiers: return room return None def __str__(self): result = "" rows = self.height() - 1 while rows >= 0: cells = self.width() - 1 while cells >= 0: result += str(self._map[rows][cells]) + "|" cells -= 1 result = result + "\n" rows -= 1 return result
class Soldier: count = 1 max_stuck = 3 """ - astar is Astar - at is Cell - bullets is List<Bullet> - came_from is Cell - edges is List<Edge> - grenades is List<Grenade> - health is Integer - id is Integer - max_health is Integer - nodes is List<Node> - rooms is List<Room> - state is SoldierState - stuck is Integer - team_id is Integer - visual_state is SoldierVisualState """ def __init__(self, max_health, team_id): self._astar = None self._at = None self._bullets = [] self._came_from = None self._edges = None self._grenades = [] self._health = max_health self._id = Soldier.count Soldier.count += 1 self._log = Logger() self._max_health = max_health self._nodes = None self._rooms = None self._state = SoldierState.DISCOVERING self._stuck = 0 self._team_id = team_id self._visual_state = None self._log.debug("Soldier #{}".format(str(self._id)), "Object Initialization") @property def at(self): return self._at @property def id(self): return self._id @property def health(self): return self._health @property def team_id(self): return self._team_id @property def rooms(self): return self._rooms @at.setter def at(self, val): self._at = val @rooms.setter def rooms(self, val): self._rooms = val def blownWithGrenade(self, grenade): self._log.debug( "Soldier #{}".format(str(self._id)), "Blown with a Grenade with damage {}".format(str(grenade.damage))) updated_health = self._health - grenade.damage if updated_health < 0: self._health = 0 else: self._health = updated_health self._visual_state = SoldierVisualState.BLOWN_WITH_GRENADE def initAstar(self, nodes, edges): self._nodes = nodes self._edges = edges self._astar = Astar(self._nodes, self._edges) def nextMove(self): self._stuck = 0 self._log.debug("Soldier #{}".format(str(self._id)), "Next Move") if self._lookNearbyAndThrowGrenade(): return if self._lookAtCellsAndShoot(): return while True and self._stuck < Soldier.max_stuck: if self._astar.target == None: self._noExistingTargetFlow() if self._astar.noOptionsLeft(): self._noOptionsLeftFlow() self._stuck += 1 self._astar.nextIterationNeighbourPriority() last_analyzed = self._astar.last_analyzed if last_analyzed.cell.isEmpty(): if self.mapTo(last_analyzed): break else: if self._haveSpottedSoldier(last_analyzed): self._spottedSoldierFlow(last_analyzed) break elif self._haveSpottedHealthPackage(last_analyzed): if self._isLookingForHealth(): self._spottedHealthPackageFlow(last_analyzed) break elif self._haveSpottedBulletPackage(last_analyzed): if self._isLookingForBullets(): self._spottedBulletPackageFlow(last_analyzed) break elif self._haveSpottedGrenadePackage(last_analyzed): if self._isLookingForGrenades(): self._spottedGrenadePackageFlow(last_analyzed) break if self._astar.solved: self._astar.resetAlgorithm() self._resetState() def mapTo(self, to): at = self._nodeBy(self._at) if at.isNeighbour(to) or to.isNeighbour(at): if to.cell.isTraversable(): self._log.debug( "Soldier #{}".format(str(self._id)), "Moving from {} to {}".format(str(at.cell.point), str(to.cell.point))) self._at.removeObj() to.cell.obj = self self._at = to.cell return True return False def removeFromGame(self): self._at.removeObj() def resetAstar(self): self._astar.resetSolved() self._astar.resetStates() self._astar.resetManhattan() self._astar.resetPriorityQueue() self._astar.resetParents() self._astar.resetTarget() def resetVisualState(self): self._visual_state = None def shareTargetWith(self, other): target = self.target() self.resetAstar() other.resetAstar() self.updateAstarStart() other.updateAstarStart() self.updateAstarTarget(target.cell) other.updateAstarTarget(target.cell) self._log.debug( "Soldier #{}".format(str(self._id)), "Shared Target {} with Soldier #{}".format(str(target.cell.point), str(other.id))) def shotWith(self, bullet): self._log.debug( "Soldier #{}".format(str(self._id)), "Shot with Bullet with damage {}".format(str(bullet.damage))) updated_health = self._health - bullet.damage if updated_health < 0: self._health = 0 else: self._health = updated_health self._visual_state = SoldierVisualState.SHOT_AT def showVisualState(self): return not self._visual_state == None def start(self): return self._astar.start def target(self): return self._astar.target def updateAstarStart(self): self._astar.updateNodeToStateStartBy(self._at) def updateAstarTarget(self, cell): self._astar.updateNodeToStateTargetBy(cell) def _areNoBullets(self): return len(self._bullets) == 0 def _areNoGrenades(self): return len(self._grenades) == 0 def _bulletPackage(self): room = self._currentRoom() if room == None: return None for cell in room.floor: if cell.containsBulletPackage(): return cell return None def _enemySoldierAt(self): for room in self._rooms: for cell in room.floor: if cell.containsSoldier(): if not self._teamMates(cell.obj): return cell return None def _friendlySoldierAt(self): for room in self._rooms: for cell in room.floor: if cell.containsSoldier(): if self._teamMates(cell.obj): return cell return None def _grenadePackage(self): room = self._currentRoom() if room == None: return None for cell in room.floor: if cell.containsGrenadePackage(): return cell return None def _lookAtCellsAndShoot(self): self._log.debug( "Soldier #{}".format(str(self._id)), "Looking for a Possible Enemy to Shoot At in the Room") if self._areNoBullets(): self._log.debug("Soldier #{}".format(str(self._id)), "No Bullets left") return False room = self._currentRoom() if room == None: self._log.debug("Soldier #{}".format(str(self._id)), "Not in a Room") return False return self._shootIfPossible(room, self._at.point.x, self._at.point.y) def _lookNearbyAndThrowGrenade(self): self._log.debug("Soldier #{}".format(str(self._id)), "Looking for a Possible Enemy to throw a Grenade at") if self._areNoGrenades(): self._log.debug("Soldier #{}".format(str(self._id)), "No Grenades left") return False room = self._currentRoom() if room == None: self._log.debug("Soldier #{}".format(str(self._id)), "Not in a Room") return False return self._throwGrenadeIfPossible(room, self._at.point.x, self._at.point.y) def _currentRoom(self): result = None for room in self._rooms: if room.partOfRoom(self._at): result = room break return result def _isLookingForBullets(self): return self._state == SoldierState.LOOKING_FOR_BULLETS def _isLookingForGrenades(self): return self._state == SoldierState.LOOKING_FOR_GRENADES def _isLookingForHealth(self): return self._state == SoldierState.LOOKING_FOR_HEALTH def _isNoAmmunition(self): return self._areNoBullets() and self._areNoGrenades() def _nodeBy(self, cell): for node in self._nodes: if node.cell.samePosition(cell): return node def _noExistingTargetFlow(self): self._log.debug("Soldier #{}".format(self._id), "No Existing Target") self._pickTarget() def _noOptionsLeftFlow(self): self._log.debug( "Soldier #{}".format(self._id), "Reaching Target {} is not possible".format( str(self.target().cell.point))) self._astar.resetAlgorithm() self._state = SoldierState.DISCOVERING target = self._randomCellAtRoom() self._came_from = self._at self._astar.updateNodeToStateStartBy(self._at) self._astar.updateNodeToStateTargetBy(target) self._log.debug("Soldier #{}".format(self._id), "The picked target is {}".format(str(target.point))) def _haveSpottedBulletPackage(self, node): at = self._nodeBy(self._at) if at.isNeighbour(node) or node.isNeighbour(at): return node.cell.containsBulletPackage() return False def _haveSpottedGrenadePackage(self, node): at = self._nodeBy(self._at) if at.isNeighbour(node) or node.isNeighbour(at): return node.cell.containsGrenadePackage() return False def _haveSpottedHealthPackage(self, node): at = self._nodeBy(self._at) if at.isNeighbour(node) or node.isNeighbour(at): return node.cell.containsHealthPackage() return False def _haveSpottedSoldier(self, node): at = self._nodeBy(self._at) if at.isNeighbour(node) or node.isNeighbour(at): if not self._at.point == node.cell.point: return node.cell.containsSoldier() return False def _healthPackage(self): for room in self._rooms: for cell in room.floor: if cell.containsHealthPackage(): return cell return None def _pickTarget(self): target = None self._decideOnState() if self._state == SoldierState.LOOKING_FOR_HEALTH: self._log.debug("Soldier #{}".format(str(self._id)), "Looking for a Health Package") target = self._healthPackage() if target == None: self._state = SoldierState.DISCOVERING if self._state == SoldierState.LOOKING_FOR_BULLETS: self._log.debug("Soldier #{}".format(str(self._id)), "Looking for a Bullets Package") target = self._bulletPackage() if target == None: self._state = SoldierState.DISCOVERING if self._state == SoldierState.LOOKING_FOR_GRENADES: self._log.debug("Soldier #{}".format(str(self._id)), "Looking for a Grenades Package") target = self._grenadePackage() if target == None: self._state = SoldierState.DISCOVERING if self._state == SoldierState.DISCOVERING: self._log.debug("Soldier #{}".format(str(self._id)), "Looking for the next Room to Discover") target = self._randomRoomCenter() self._came_from = self._at self._astar.updateNodeToStateStartBy(self._at) self._astar.updateNodeToStateTargetBy(target) self._log.debug("Soldier #{}".format(self._id), "The picked target is {}".format(str(target.point))) def _randomCellAtRoom(self): result = None seed() room_index = randint(0, len(self._rooms) - 1) room = self._rooms[room_index] while result == None: cell_index = randint(0, len(room.floor) - 1) cell = room.floor[cell_index] if cell.isTraversable(): result = cell return result def _randomRoomCenter(self): result = None seed() while result == None: room_index = randint(0, len(self._rooms) - 1) room = self._rooms[room_index] if self._came_from == None: result = room.center elif not room.partOfRoom(self._came_from): result = room.center return result def _resetState(self): self._state = SoldierState.DISCOVERING def _reverseTarget(self): self._log.debug("Soldier #{}".format(str(self._id)), "Reversing the Target") start = self.start() self._astar.resetAlgorithm() self._astar.updateNodeToStateStartBy(self._at) self._astar.updateNodeToStateTargetBy(start.cell) def _shootAt(self, other): self._log.debug("Soldier #{}".format(str(self._id)), "Shooting at Enemy #{}".format(str(other.id))) bullet = self._bullets.pop() other.shotWith(bullet) def _shootIfPossible(self, room, x, y): increment_x = x + 1 while True: look_at = room.cellBy(increment_x, y) if look_at == None: break if not look_at.isEmpty(): if look_at.containsSoldier(): other = look_at.obj if not self._teamMates(other): self._shootAt(other) return True break increment_x += 1 increment_y = y + 1 while True: look_at = room.cellBy(x, increment_y) if look_at == None: break if not look_at.isEmpty(): if look_at.containsSoldier(): other = look_at.obj if not self._teamMates(other): self._shootAt(other) return True break increment_y += 1 decrement_x = x - 1 while True: look_at = room.cellBy(decrement_x, y) if look_at == None: break if not look_at.isEmpty(): if look_at.containsSoldier(): other = look_at.obj if not self._teamMates(other): self._shootAt(other) return True break decrement_x -= 1 decrement_y = y - 1 while True: look_at = room.cellBy(x, decrement_y) if look_at == None: break if not look_at.isEmpty(): if look_at.containsSoldier(): other = look_at.obj if not self._teamMates(other): self._shootAt(other) return True break decrement_y += 1 return False def _spottedEnemyFlow(self, other): if other._at.isPath(): if self._isNoAmmunition() or self._isLowHealth(): self._reverseTarget() else: if not self._areNoGrenades(): self._throwGrenadeAt(other) else: self._shootAt(other) def _spottedFriendFlow(self, other): if other._at.isPath(): if not self.target(): other.shareTargetWith(self) else: self.shareTargetWith(other) def _spottedBulletPackageFlow(self, node): self._log.debug("Soldier #{}".format(str(self._id)), "Spotted a Bullet Package") for bullet in node.cell.obj.units: self._bullets.append(bullet) if self._areNoBullets(): self._log.info( "Soldier #{}".format(str(self._id)), "Bullets can not be empty after picking a Bullet Package") exit(1) node.cell.removeObj() self._astar.resetAlgorithm() self._resetState() self._log.debug("Soldier #{}".format(str(self._id)), "Used a Bullets Package") def _spottedGrenadePackageFlow(self, node): self._log.debug("Soldier #{}".format(str(self._id)), "Spotted a Grenades Package") for grenade in node.cell.obj.units: self._grenades.append(grenade) if self._areNoGrenades(): self._log.info( "Soldier #{}".format(str(self._id)), "Grenades can not be empty after picking a Grenade Package") exit(1) node.cell.removeObj() self._astar.resetAlgorithm() self._resetState() self._log.debug("Soldier #{}".format(str(self._id)), "Used a Grenades Package") def _spottedHealthPackageFlow(self, node): self._log.debug("Soldier #{}".format(str(self._id)), "Spotted a Health Package") restored_health = self._health + node.cell.obj.restore if restored_health > self._max_health: self._health = self._max_health else: self._health = restored_health node.cell.removeObj() self._resetState() self._astar.resetAlgorithm() self._log.debug("Soldier #{}".format(str(self._id)), "Used a Health Package") def _spottedSoldierFlow(self, node): other = node.cell.obj if self._teamMates(other): self._log.debug("Soldier #{}".format(str(self._id)), "Spotted a Friend #{}".format(str(other.id))) self._spottedFriendFlow(other) else: self._log.debug("Soldier #{}".format(str(self._id)), "Spotted an Enemy #{}".format(str(self._id))) self._spottedEnemyFlow(other) def _teamMates(self, other): return self._team_id == other.team_id def _throwGrenadeAt(self, other): self._log.debug( "Soldier #{}".format(str(self._id)), "Throwing Grenade at the Enemy #{}".format(str(other.id))) grenade = self._grenades.pop() other.blownWithGrenade(grenade) def _throwGrenadeIfPossible(self, room, x, y): increment_x = x + 1 while increment_x < x + 3: look_at = room.cellBy(increment_x, y) if look_at == None: break if not look_at.isEmpty(): if look_at.containsSoldier(): other = look_at.obj if not self._teamMates(other): self._throwGrenadeAt(other) return True break increment_x += 1 increment_y = y + 1 while increment_y < y + 3: look_at = room.cellBy(x, increment_y) if look_at == None: break if not look_at.isEmpty(): if look_at.containsSoldier(): other = look_at.obj if not self._teamMates(other): self._throwGrenadeAt(other) return True break increment_y += 1 decrement_x = x - 1 while decrement_x < x - 3: look_at = room.cellBy(decrement_x, y) if look_at == None: break if not look_at.isEmpty(): if look_at.containsSoldier(): other = look_at.obj if not self._teamMates(other): self._throwGrenadeAt(other) return True break decrement_x -= 1 decrement_y = y - 1 while decrement_y < y - 3: look_at = room.cellBy(x, decrement_y) if look_at == None: break if not look_at.isEmpty(): if look_at.containsSoldier(): other = look_at.obj if not self._teamMates(other): self._throwGrenadeAt(other) return True break decrement_y += 1 return False def __str__(self): if self._visual_state == SoldierVisualState.SHOT_AT: return "!" if self._visual_state == SoldierVisualState.BLOWN_WITH_GRENADE: return "?" return str(self._id)