Exemple #1
0
 def __init__(self, terrain, heuristic):
     self.terrain = Terrain(terrain)
     self.directions = {'N': (0, -1),
                        'E': (1, 0),
                        'S': (0, 1),
                        'W': (-1, 0)}
     self.start_node = Node(self.terrain.get_start_position(), 'N', 0)
     # Push our start position onto the heap
     self.search_heap = SearchHeap(initial=[self.start_node],
                                   g_func=lambda node: node.g,
                                   h_func=heuristic,
                                   goal=self.terrain.get_goal_position())
     self.visited = []
     self.position = list(self.terrain.get_start_position())
     self.facing = 'N'
     self.action_costs = {'forward': lambda cost: -cost,
                          'bash': lambda cost: -3,
                          'turn': lambda cost: -ceil(float(cost)/float(3)),
                          'demolish': lambda cost: -4}
     print "goal position:"
     print self.terrain.get_goal_position()
Exemple #2
0
class Agent(object):
    """
        Class to handle decisions about getting to the goal.

        :param: Terrain - the terrain on which the agent is navigating
        :param: Heuristic - the difficulty level of the heuristic
    """
    def __init__(self, terrain, heuristic):
        self.terrain = Terrain(terrain)
        self.directions = {'N': (0, -1),
                           'E': (1, 0),
                           'S': (0, 1),
                           'W': (-1, 0)}
        self.start_node = Node(self.terrain.get_start_position(), 'N', 0)
        # Push our start position onto the heap
        self.search_heap = SearchHeap(initial=[self.start_node],
                                      g_func=lambda node: node.g,
                                      h_func=heuristic,
                                      goal=self.terrain.get_goal_position())
        self.visited = []
        self.position = list(self.terrain.get_start_position())
        self.facing = 'N'
        self.action_costs = {'forward': lambda cost: -cost,
                             'bash': lambda cost: -3,
                             'turn': lambda cost: -ceil(float(cost)/float(3)),
                             'demolish': lambda cost: -4}
        print "goal position:"
        print self.terrain.get_goal_position()

    def a_star_search(self):
        """A* search for the goal"""
        while self.search_heap.is_not_empty():
            node = self.search_heap.pop()
            # add the node to self.visited to show we visited it
            self.visited.append(node)
            """
            print "current position:"
            print node.position
            print "current direction:"
            print node.direction
            print "node g score:"
            print node.g
            """
            if self.terrain.is_goal_node(node):
                # TODO: make it return the path to the goal
                # as a sequence of nodes
                print "Score of the path:"
                print node.g + 100
                print "Number of actions required to reach the goal:"
                print node.depth
                print "Number of nodes expanded:"
                print len(self.visited)
                break

            for action, neighbor in self.get_search_neighbors(node).iteritems():
                last_time_visited = self.has_been_visited_already(neighbor)
                if last_time_visited is None and self.terrain.node_inside_terrain(neighbor):
                    neighbor.g = self.assign_g_cost(neighbor, node, self.terrain, action)
                    self.search_heap.push(neighbor)

    def get_search_neighbors(self, node):
        """Returns a list of node leaves from the given node."""
        # These things create nodes
        turn_left = Node(position=node.position,
                         direction=self.turn_left(node),
                         depth=node.depth + 1)
        turn_right = Node(position=node.position,
                          direction=self.turn_right(node),
                          depth=node.depth + 1)
        move_forward = Node(position=self.forward(node),
                            direction=node.direction,
                            depth=node.depth + 1)
        bash_and_forward = Node(position=self.bash_and_forward(node),
                                direction=node.direction,
                                depth=node.depth + 1)
        # return the nodes
        return {'turn_left': turn_left,
                'turn_right': turn_right,
                'move_forward': move_forward,
                'bash_and_forward': bash_and_forward}

    def assign_g_cost(self, node, parent, terrain, action):
        if 'turn' in action:
            # Update the g costs of the nodes
            return(parent.g +
                   self.action_costs['turn'](
                           self.terrain.get_cost_from_tuple(
                               node.position)))
        elif action == 'move_forward':
            return parent.g + self.action_costs['forward'](
                                    self.terrain.get_cost_from_tuple(
                                        node.position))
        else:
            return parent.g + self.action_costs['bash'](0) + self.action_costs['forward'](
                                        self.terrain.get_cost_from_tuple(
                                            node.position))

    def forward(self, node):
        """The rules to move forward"""
        new_pos = (node.position[0] + self.directions[node.direction][0],
                   node.position[1] + self.directions[node.direction][1])
        # TODO: Update the score
        return new_pos

    def bash_and_forward(self, node):
        """The rules to bash and move forward"""
        return self.forward(Node(position=self.forward(node),
                                 direction=node.direction,
                                 depth=node.depth + 1))

    def turn_right(self, node):
        """The rules to turn right"""
        dirs = ['N', 'E', 'S', 'W']
        return dirs[(dirs.index(node.direction)+1) % len(dirs)]

    def turn_left(self, node):
        """The rules to turn left"""
        dirs = ['N', 'E', 'S', 'W']
        return dirs[(dirs.index(node.direction)-1) % len(dirs)]

    def has_been_visited_already(self, node):
        """
            Returns None or a Node

            This function will return None if the node has not been
            previously visited OR if the given node is less expensive
            to reach than the previous time we visited that position+direction
            pairing

            :param: Node - the node to check against for having already visited
                           that position + direction pairing
        """
        for visited in self.visited:
            # compare the two nodes
            if visited.is_the_same(node):
                if node.g > visited.g:
                    return visited
        return None