コード例 #1
0
ファイル: test_logger.py プロジェクト: stephengroat/syslog-ng
def test_logger_file_handler_disabled(tc_unittest):
    temp_file = tc_unittest.get_temp_file()
    logger = Logger("UnitTest",
                    temp_file,
                    logging.DEBUG,
                    use_console_handler=True,
                    use_file_handler=False)
    logger.info("TestMessage")
    assert temp_file.exists() is False
コード例 #2
0
ファイル: test_logger.py プロジェクト: stephengroat/syslog-ng
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()
コード例 #3
0
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
コード例 #4
0
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
コード例 #5
0
ファイル: soldier.py プロジェクト: Z0neNp/ai_game
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)