Ejemplo n.º 1
0
    def paint(self):
        """ Paints the player and its aim indicator on the screen.
            Also paints the targets for the aimed at tile if it has any.
        """
        super(Player, self).paint()

        if self.removing_tile:
            if g.in_map(*self.get_aim_tile()) and g.get_img(*self.get_aim_tile()).destroy is not None:
                aim = "remove_aim"
            else:
                aim = "remove_aim_fail"
        else:
            aim = "aim"
        x = ((self.last_aim_tile[0]*c.TILE_SIZE) +
             (c.TILE_SIZE - g.images[aim].get_size()[0]) / 2)
        y = ((self.last_aim_tile[1]*c.TILE_SIZE) +
             (c.TILE_SIZE - g.images[aim].get_size()[1]) / 2)
        g.screen.blit(g.images[aim].get(), (x, y))

        # When you aim at a factory, display the set targets for that tile
        if g.in_map(*self.last_aim_tile) and g.get_img(*self.last_aim_tile).factory_output:
            x, y = self.last_aim_tile
            if g.map[x][y].good_targets:
                for good_target in list(g.map[x][y].good_targets.values()):
                    g.screen.blit(g.images["tile_target_aim"].get(),
                                  (good_target[0]*c.TILE_SIZE +
                                   (c.TILE_SIZE - g.images["tile_target_aim"].get_size()[0]) / 2,
                                   good_target[1]*c.TILE_SIZE +
                                   (c.TILE_SIZE - g.images["tile_target_aim"].get_size()[1]) / 2))
            # Show the direction the selected launcher tile is shooting
            if type(g.map[x][y]) == tiles.LauncherTile and g.map[x][y].shoot_direction != (0, 0):
                g.screen.blit(g.images["tile_target_aim"].get(),
                              ((g.map[x][y].shoot_direction[0]+x)*c.TILE_SIZE +
                               (c.TILE_SIZE - g.images["tile_target_aim"].get_size()[0]) / 2,
                              ((g.map[x][y].shoot_direction[1]+y)*c.TILE_SIZE +
                               (c.TILE_SIZE - g.images["tile_target_aim"].get_size()[1]) / 2)))
Ejemplo n.º 2
0
    def goods_pathfind(self, target_goods):
        """ Finds a path from the start tile, (the current tile of the entity) to the nearest factory tile that
            can recieve the passed-in goods type.
            "goods" should be a string with the type of goods that the entity will be carrying.

            returns True if a suitable tile was found and False if no suitable tile was found
        """

        start = self.get_tile()
        # The open_dict and closed_dict both follow the format:
        # (key_x, key_y): [g, (came_from_x, came_from_y)]
        # This is a simplified version of the pathfind function. It doesn't use heuristics because it doesn't
        # know where to go yet. It only uses the G value, which is the distance to the tile it came from.
        if type(start) != tuple:
            raise Exception("Value given by self.get_tile() to PathingEntity.goods_pathfind() is not tuple")

        # The open dictionary is a dictionary keeping the currently checkable tiles
        # The starting tile is identified as not having a came_from-tuple.
        open_dict = {start: [0]}
        # The closed dictionary is a dicionary keeping the currently checked tiles
        closed_dict = {}

        current = None
        while len(open_dict.keys()) > 0:
            lowest_value = None
            # Get the lowest value
            for key in open_dict.keys():
                value = open_dict[key][0]
                if lowest_value is None:
                    lowest_value = value
                    current = key
                elif value < lowest_value:
                    lowest_value = value
                    current = key
            # Move current from the open dictionary to the closed one
            closed_dict[current] = open_dict[current]
            del open_dict[current]

            # If we're done here
            done = False
            deliver_tiles = []
            # This code block makes sure the items are delivered to the tile next to the tile instead of diagonally

            if (g.in_map(current[0]+1, current[1]) and
                    g.get_img(current[0]+1, current[1]).factory_input):
                deliver_tiles.append((current[0]+1, current[1]))
            elif (g.in_map(current[0]-1, current[1]) and
                    g.get_img(current[0]-1, current[1]).factory_input):
                deliver_tiles.append((current[0]-1, current[1]))
            elif (g.in_map(current[0], current[1]+1) and
                    g.get_img(current[0], current[1]+1).factory_input):
                deliver_tiles.append((current[0], current[1]+1))
            elif (g.in_map(current[0], current[1]-1) and
                    g.get_img(current[0], current[1]-1).factory_input):
                deliver_tiles.append((current[0], current[1]-1))
            if deliver_tiles:
                for deliver_tile in deliver_tiles:
                    try:
                        for good_name in list(g.map[deliver_tile[0]][deliver_tile[1]].requests.keys()):
                            if good_name == target_goods:
                                if g.map[deliver_tile[0]][deliver_tile[1]].requests[target_goods] > 0:
                                    done = True
                                    g.map[deliver_tile[0]][deliver_tile[1]].requests[target_goods] -= 1
                                    break  # Break out of the goods for loop, not the entire while loop
                        if done:
                            break
                    except AttributeError:
                        pass

            if done is True:
                full_path = []
                self.deliver_tile = deliver_tile
                try:
                    while current != start:
                        full_path.append(current)
                        current = closed_dict[current][1]
                except:
                    print(closed_dict)
                    print(full_path)
                    # Trying to understand the heisenbug! D:
                    import pdb, sys
                    e, m, tb = sys.exc_info()
                    pdb.post_mortem(tb)

                full_path.reverse()
                self.path = full_path
                self.next_target_tile()
                self.home_tile = self.get_tile()
                return True

            # Move through all neighbours
            for i in range(current[0]-1, current[0]+2):
                for j in range(current[1]-1, current[1]+2):
                    neighbour = (i, j)
                    if 0 <= neighbour[0] < len(g.map) and 0 <= neighbour[1] < len(g.map[0]):

                        # Get the G score, the cost to go back to the start
                        if neighbour[0] == current[0]:
                            if neighbour[1] == current[1]:
                                continue
                            else:
                                g_score = closed_dict[current][0] + 10
                        else:
                            if neighbour[1] == current[1]:
                                g_score = closed_dict[current][0] + 10
                            else:
                                # Make sure the pathfinding doesn't try to go through blocks diagonally.
                                if (g.get_img(neighbour[0], current[1]).collides and
                                        g.get_img(current[0], neighbour[1]).collides):
                                    # If the blocks on either side of the diagonal walk is collidable, skip this one
                                    if neighbour not in closed_dict:
                                        closed_dict[neighbour] = None
                                    continue

                                # If it can travel diagonally, give it a cost of the square root of two.
                                g_score = closed_dict[current][0] + 14

                        if c.IMAGES[g.map[neighbour[0]][neighbour[1]].type].collides is False or neighbour == start:
                        # Check if this neighbour can be added the the open_dict and do so if so
                            if neighbour not in closed_dict.keys():
                                if neighbour not in open_dict.keys() or g_score < open_dict[neighbour][0]:
                                    open_dict[neighbour] = [g_score, current]
                        else:
                            if neighbour not in closed_dict.keys() and neighbour not in open_dict.keys():
                                closed_dict[neighbour] = None
        self.path = []
        self.stop_moving()
        return False
Ejemplo n.º 3
0
    def pathfind(self, end):
        """ Finds a path from start to end tiles using A* algorithm
            "start" and "end" are tuples with x and y coordinates of a tile

            returns True if it succeded and False if it couldn't find a path
        """
        start = self.get_tile()
        # The open_dict and closed_dict both follow the format:
        # (key_x, key_y): [f, g, h, (came_from_x, came_from_y)]
        # F, G and H. G is the length to the start tile, H is the Heuristics
        # estimate of the distance to the end tile and F = G + H
        if type(start) != tuple or type(end) != tuple:
            raise Exception("Value passed to PathingEntity.pathfind() is not tuple")

        # The open dictionary is a dictionary keeping the currently checkable tiles
        # The starting tile is identified as not having a came_from-tuple.
        open_dict = {start: [self._heuristic_cost_estimate(start, end), 0,
                             self._heuristic_cost_estimate(start, end)]}
        # The closed dictionary is a dicionary keeping the currently checked tiles
        closed_dict = {}

        current = None
        while len(open_dict.keys()) > 0:
            lowest_value = None
            # Get the lowest value
            for key in open_dict.keys():
                value = open_dict[key][0]
                if lowest_value is None:
                    lowest_value = value
                    current = key
                else:
                    if value < lowest_value:
                        lowest_value = value
                        current = key
            # Move current from the open dictionary to the closed one
            closed_dict[current] = open_dict[current]
            del open_dict[current]

            # If we're done here
            deliver_tile = None
            if g.get_img(*end).collides and current != end:
                # Find a tile next to the target tile to stand on if it collides
                if (g.in_map(current[0] + 1, current[1]) and
                        (current[0] + 1, current[1]) == end):
                    deliver_tile = (current[0] + 1, current[1])
                elif (g.in_map(current[0] - 1, current[1]) and
                        (current[0] - 1, current[1]) == end):
                    deliver_tile = (current[0] - 1, current[1])
                elif (g.in_map(current[0], current[1] + 1) and
                        (current[0], current[1] + 1) == end):
                    deliver_tile = (current[0], current[1] + 1)
                elif (g.in_map(current[0], current[1] - 1) and
                        (current[0], current[1] - 1) == end):
                    deliver_tile = (current[0], current[1] - 1)
            elif current == end:
                deliver_tile = current

            if deliver_tile is not None:
                # closed_dict[current]
                full_path = []
                while current != start:
                    full_path.append(current)
                    current = closed_dict[current][3]
                full_path.reverse()
                self.deliver_tile = deliver_tile
                self.path = full_path
                self.next_target_tile()
                return True

                # # Old version
                # if done is True:
                #     full_path = []
                #     self.deliver_tile = deliver_tile
                #     while len(closed_dict[current]) > 1:
                #         full_path.append(current)
                #         current = closed_dict[current][1]
                #     full_path.reverse()
                #     self.path = full_path
                #     self.next_target_tile()
                #     self.home_tile = self.get_tile()
                #     return

            # Move through all neighbours
            for i in range(current[0]-1, current[0]+2):
                for j in range(current[1]-1, current[1]+2):
                    neighbour = (i, j)
                    if 0 <= neighbour[0] < len(g.map) and 0 <= neighbour[1] < len(g.map[0]):

                        # Get the G score, the cost to go back to the start
                        if neighbour[0] == current[0]:
                            if neighbour[1] == current[1]:
                                continue
                            else:
                                g_score = closed_dict[current][1] + 10
                        else:
                            if neighbour[1] == current[1]:
                                g_score = closed_dict[current][1] + 10
                            else:
                                # Make sure the pathfinding doesn't try to go through blocks diagonally.
                                if (g.get_img(neighbour[0], current[1]).collides and
                                        g.get_img(current[0], neighbour[1]).collides):
                                    # If the blocks on either side of the diagonal walk is collidable, skip this one
                                    closed_dict[neighbour] = None
                                    continue

                                # If it can travel diagonally, give it a cost of the square root of two.
                                g_score = closed_dict[current][1] + 14

                        if c.IMAGES[g.map[neighbour[0]][neighbour[1]].type].collides is False:
                            # Check if this neighbour can be added the the open_dict and do so if so
                            if neighbour not in closed_dict.keys():
                                if neighbour not in open_dict.keys() or g_score < open_dict[neighbour][1]:
                                    h_score = self._heuristic_cost_estimate(neighbour, end)
                                    f_score = g_score + h_score
                                    open_dict[neighbour] = [f_score, g_score, h_score, current]
                        else:
                            closed_dict[neighbour] = None
        self.path = []
        self.stop_moving()
        return False