From 520efb84ead29802408c876f3e3c10be98f6e84b Mon Sep 17 00:00:00 2001 From: eugenep Date: Sat, 24 Apr 2021 01:44:57 +0200 Subject: [PATCH] Try to implement to A* Co-authored-by: Sebastian Piotrowski Co-authored-by: Marcin Matoga Co-authored-by: Ladislaus3III --- astar.py | 335 +++++++++++++++++++++++++++ astar2.py | 542 ++++++++++++++++++++++++++++++++++++++++++++ astar2_document.txt | 98 ++++++++ goal_map.txt | 12 +- images/puddle.bmp | Bin 0 -> 16522 bytes images/robot2.bmp | Bin 0 -> 16522 bytes main.py | 13 +- map.txt | 12 +- sprites.py | 19 +- todo.txt | 270 ++++++++++++++++++++++ 10 files changed, 1285 insertions(+), 16 deletions(-) create mode 100644 astar.py create mode 100644 astar2.py create mode 100644 astar2_document.txt create mode 100644 images/puddle.bmp create mode 100644 images/robot2.bmp create mode 100644 todo.txt diff --git a/astar.py b/astar.py new file mode 100644 index 0000000..89f1642 --- /dev/null +++ b/astar.py @@ -0,0 +1,335 @@ +import heapq +from os import path +from settings import * + + +class Problem: + def __init__(self, initial, goal): + self.initial = initial + self.goal = goal + + def actions(self, state): + moves = [] + if self.turn_left(state): + moves.append('Left') + if self.turn_right(state): + moves.append('Right') + if self.move_forward(state): + moves.append('Forward') + + # print(moves) + return moves + + def turn_left(self, state): + return True + + def turn_right(self, state): + return True + + def move_forward(self, state): + + a_row = 0 + a_column = 0 + + for row in range(MAP_SIZE): + for column, pos in enumerate(state[row]): + if pos == ">": + a_row = row + a_column = column + + if a_column == MAP_SIZE-1: + return False + elif state[a_row][a_column+1] == '.': + return True + elif state[a_row][a_column+1] == 'p': + return True + return False + if pos == "<": + a_row = row + a_column = column + + if a_column == 0: + return False + elif state[a_row][a_column-1] == '.': + return True + return False + + if pos == "v": + a_row = row + a_column = column + + if a_row == MAP_SIZE-1: + return False + elif state[a_row+1][a_column] == '.': + return True + return False + if pos == "^": + a_row = row + a_column = column + + if row == 0: + return False + elif state[a_row-1][a_column] == '.': + return True + return False + + def turn_me_or_move(self, state, do_it): + + temp_map = [list(item) for item in state] + + # print(temp_map) + + #a_row = 0 + #a_column = 0 + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == ">": + a_row = row + a_column = column + #print("a_row:" + str(a_row)) + #print("a_column" + str(a_column)) + + if(do_it == 'Left'): + temp_map[a_row][a_column] = "^" + if(do_it == 'Right'): + temp_map[a_row][a_column] = 'v' + if(do_it == 'Forward'): + temp_map[a_row][a_column] = '.' + temp_map[a_row][a_column+1] = '>' + return temp_map + + if pos == "<": + a_row = row + a_column = column + if(do_it == 'Left'): + temp_map[a_row][a_column] = 'v' + if(do_it == 'Right'): + temp_map[a_row][a_column] = '^' + if(do_it == 'Forward'): + temp_map[a_row][a_column] = '.' + temp_map[a_row][a_column-1] = '<' + return temp_map + if pos == "v": + a_row = row + a_column = column + if(do_it == 'Left'): + temp_map[a_row][a_column] = '>' + if(do_it == 'Right'): + temp_map[a_row][a_column] = '<' + if(do_it == 'Forward'): + temp_map[a_row][a_column] = '.' + temp_map[a_row+1][a_column] = 'v' + return temp_map + if pos == "^": + a_row = row + a_column = column + if(do_it == 'Left'): + temp_map[a_row][a_column] = '<' + if(do_it == 'Right'): + temp_map[a_row][a_column] = '>' + if(do_it == 'Forward'): + temp_map[a_row][a_column] = '.' + temp_map[a_row-1][a_column] = '^' + return temp_map + return temp_map + + def result(self, state, action): + new_state = [] + + if action == 'Left': + new_state = self.turn_me_or_move(state, 'Left') + elif action == 'Right': + new_state = self.turn_me_or_move(state, 'Right') + elif action == 'Forward': + new_state = self.turn_me_or_move(state, 'Forward') + + super_new_state = tuple(map(tuple, new_state)) + + return super_new_state + + def goal_test(self, state): + if self.goal == state: + return True + return False + + def path_cost(self, c, state1, action, state2, in_puddle1, in_puddle2): + + + return c+1 + + # funkcja heurystyki + def h(self, node): + node_row = node.row + node_column = node.column + + + + +class Node: + def __init__(self, state, parent=None, action=None, path_cost=0): + """Create a search tree Node, derived from a parent by an action.""" + self.state = state + self.parent = parent + self.action = action + self.path_cost = path_cost + + self.in_puddle = False + + #self.row = row + #self.column = column + + def __repr__(self): + return "".format(self.state) + + def expand(self, problem): + """List the nodes reachable in one step from this node.""" + return [self.child_node(problem, action) + for action in problem.actions(self.state)] + + def child_node(self, problem, action): + next_state = problem.result(self.state, action) + next_node = Node(next_state, self, action, problem.path_cost(self.path_cost, self.state, action, next_state, in_puddle)) + return next_node + + def where_am_i(self): + temp_map = [list(item) for item in state] + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == ">" or pos == "<" or pos == "^" or pos == "v": + self.row = row + self.column = column + + + + + + + + def __eq__(self, other): + return isinstance(other, Node) and self.state == other.state + + def __hash__(self): + # We use the hash value of the state + # stored in the node instead of the node + # object itself to quickly search a node + # with the same state in a Hash Table + return hash(self.state) + + +class PriorityQueue: + """A Queue in which the minimum (or maximum) element (as determined by f and + order) is returned first. + If order is 'min', the item with minimum f(x) is + returned first; if order is 'max', then it is the item with maximum f(x). + Also supports dict-like lookup.""" + + def __init__(self, order='min', f=lambda x: x): + self.heap = [] + if order == 'min': + self.f = f + elif order == 'max': # now item with max f(x) + self.f = lambda x: -f(x) # will be popped first + else: + raise ValueError("Order must be either 'min' or 'max'.") + + def append(self, item): + """Insert item at its correct position.""" + heapq.heappush(self.heap, (self.f(item), item)) + + def extend(self, items): + """Insert each item in items at its correct position.""" + for item in items: + self.append(item) + + def pop(self): + """Pop and return the item (with min or max f(x) value) + depending on the order.""" + if self.heap: + return heapq.heappop(self.heap)[1] + else: + raise Exception('Trying to pop from empty PriorityQueue.') + + def __len__(self): + """Return current capacity of PriorityQueue.""" + return len(self.heap) + + def __contains__(self, key): + """Return True if the key is in PriorityQueue.""" + return any([item == key for _, item in self.heap]) + + def __getitem__(self, key): + """Returns the first value associated with key in PriorityQueue. + Raises KeyError if key is not present.""" + for value, item in self.heap: + if item == key: + return value + raise KeyError(str(key) + " is not in the priority queue") + + def __delitem__(self, key): + """Delete the first occurrence of key.""" + try: + del self.heap[[item == key for _, item in self.heap].index(True)] + except ValueError: + raise KeyError(str(key) + " is not in the priority queue") + heapq.heapify(self.heap) + + +class Astar: + @staticmethod + def best_first_graph_search(problem, f, display=False): + """Search the nodes with the lowest f scores first. + You specify the function f(node) that you want to minimize; for example, + if f is a heuristic estimate to the goal, then we have greedy best + first search; if f is node.depth then we have breadth-first search. + There is a subtlety: the line "f = memoize(f, 'f')" means that the f + values will be cached on the nodes as they are computed. So after doing + a best first search you can examine the f values of the path returned.""" + #f = memoize(f, 'f') + node = Node(problem.initial) + # PriorityQueue ma przechowywac g+h + frontier = PriorityQueue('min', f) + frontier.append(node) + explored = set() + while frontier: + node = frontier.pop() + if problem.goal_test(node.state): + if display: + print(len(explored), "paths have been expanded and", + len(frontier), "paths remain in the frontier") + return node + explored.add(node.state) + for child in node.expand(problem): + if child.state not in explored and child not in frontier: + frontier.append(child) + elif child in frontier: + if f(child) < frontier[child]: + del frontier[child] + frontier.append(child) + return None + + @staticmethod + def loadMap(map_name=''): + maze = [] + map_folder = path.dirname(__file__) + with open(path.join(map_folder, map_name), 'rt') as f: + for line in f: + maze.append(line.rstrip('\n')) + + #print(maze) + return maze + + @staticmethod + def run(): + initial_map = tuple(map(tuple, Astar.loadMap('map.txt'))) + goal_map = tuple(map(tuple, Astar.loadMap('goal_map.txt'))) + problem = Problem(initial_map, goal_map) + + #BFS.print_node_state(initial_map) + #BFS.print_node_state(goal_map) + + result = Astar.breadth_first_graph_search(problem) + print(result) + return result + #print(BFS.print_node_state(result)) diff --git a/astar2.py b/astar2.py new file mode 100644 index 0000000..f067005 --- /dev/null +++ b/astar2.py @@ -0,0 +1,542 @@ +from os import path +import heapq + +from settings import * +from sprites import Direction + + +class PlanRoute(): + """ The problem of moving the Hybrid Wumpus Agent from one place to other """ + + def __init__(self, initial, goal, allowed, puddles=None, dimrow=None): + """ Define goal state and initialize a problem """ + self.initial = initial + self.goal = goal + self.dimrow = dimrow + self.goal = goal + self.allowed = allowed + self.puddles = puddles + + def actions(self, state): + """ Return the actions that can be executed in the given state. + The result would be a list, since there are only three possible actions + in any given state of the environment """ + + possible_actions = ['Forward', 'Left', 'Right'] + x, y = state.get_location() + orientation = state.get_orientation() + + # Prevent Bumps + if x == 1 and orientation == 'LEFT': + if 'Forward' in possible_actions: + possible_actions.remove('Forward') + if y == 1 and orientation == 'DOWN': + if 'Forward' in possible_actions: + possible_actions.remove('Forward') + if x == self.dimrow and orientation == 'RIGHT': + if 'Forward' in possible_actions: + possible_actions.remove('Forward') + if y == self.dimrow and orientation == 'UP': + if 'Forward' in possible_actions: + possible_actions.remove('Forward') + + return possible_actions + + def result(self, state, action): + """ Given state and action, return a new state that is the result of the action. + Action is assumed to be a valid action in the state """ + x, y = state.get_location() + #proposed_loc = list() + proposed_loc = [] + + # Move Forward + if action == 'Forward': + if state.get_orientation() == 'UP': + proposed_loc = [x, y + 1] + elif state.get_orientation() == 'DOWN': + proposed_loc = [x, y - 1] + elif state.get_orientation() == 'LEFT': + proposed_loc = [x - 1, y] + elif state.get_orientation() == 'RIGHT': + proposed_loc = [x + 1, y] + else: + raise Exception('InvalidOrientation') + + # Rotate counter-clockwise + elif action == 'Left': + if state.get_orientation() == 'UP': + state.set_orientation('LEFT') + elif state.get_orientation() == 'DOWN': + state.set_orientation('RIGHT') + elif state.get_orientation() == 'LEFT': + state.set_orientation('DOWN') + elif state.get_orientation() == 'RIGHT': + state.set_orientation('UP') + else: + raise Exception('InvalidOrientation') + + # Rotate clockwise + elif action == 'Right': + if state.get_orientation() == 'UP': + state.set_orientation('RIGHT') + elif state.get_orientation() == 'DOWN': + state.set_orientation('LEFT') + elif state.get_orientation() == 'LEFT': + state.set_orientation('UP') + elif state.get_orientation() == 'RIGHT': + state.set_orientation('DOWN') + else: + raise Exception('InvalidOrientation') + + if tuple(proposed_loc) in self.allowed: + state.set_location(proposed_loc[0], [proposed_loc[1]]) + + return state + + def goal_test(self, state): + """ Given a state, return True if state is a goal state or False, otherwise """ + + return state.get_location() == self.goal.get_location() + + def path_cost(self, c, state1, action, state2): + """Return the cost of a solution path that arrives at state2 from + state1 via action, assuming cost c to get up to state1. If the problem + is such that the path doesn't matter, this function will only look at + state2. If the path does matter, it will consider c and maybe state1 + and action. The default method costs 1 for every step in the path.""" + + if action == "Forward" or action == "Left" or action == "Right": + + + x1, y1 = state1.get_location() + location1 = tuple([x1, y1]) + x2, y2 = state2.get_location() + location2 = tuple([x1, y1]) + + + if location2 in self.puddles: + return c + 1 + if location1 == location2 and state1 in self.puddles: + return c + 1 + return c + + def h(self, node): + """ Return the heuristic value for a given state.""" + + # Manhattan Heuristic Function + x1, y1 = node.state.get_location() + x2, y2 = self.goal.get_location() + + return abs(x2 - x1) + abs(y2 - y1) + + +class Node: + def __init__(self, state, parent=None, action=None, path_cost=0): + """Create a search tree Node, derived from a parent by an action.""" + self.state = state #AgentPosition? + self.parent = parent + self.action = action + self.path_cost = path_cost + + def __repr__(self): + return "".format(self.state) + + def solution(self): + """Return the sequence of actions to go from the root to this node.""" + return [node.action for node in self.path()[1:]] + + + def expand(self, problem): + """List the nodes reachable in one step from this node.""" + return [self.child_node(problem, action) + for action in problem.actions(self.state)] + + def child_node(self, problem, action): + + next_state = problem.result(self.state, action) + next_node = Node(next_state, self, action, problem.path_cost( + self.path_cost, self.state, action, next_state)) + print(problem.path_cost( + self.path_cost, self.state, action, next_state)) + return next_node + + def __eq__(self, other): + return isinstance(other, Node) and self.state == other.state + + def __hash__(self): + # We use the hash value of the state + # stored in the node instead of the node + # object itself to quickly search a node + # with the same state in a Hash Table + return hash(self.state) + + def path(self): + """Return a list of nodes forming the path from the root to this node.""" + node, path_back = self, [] + while node: + path_back.append(node) + node = node.parent + return list(reversed(path_back)) + + +class AgentPosition: + def __init__(self, x, y, orientation): + self.X = x + self.Y = y + self.orientation = orientation + + def get_location(self): + return self.X, self.Y + + def set_location(self, x, y): + self.X = x + self.Y = y + + def get_orientation(self): + return self.orientation + + def set_orientation(self, orientation): + self.orientation = orientation + + def __eq__(self, other): + if (other.get_location() == self.get_location() and + other.get_orientation() == self.get_orientation()): + return True + else: + return False + + def __hash__(self): + return hash((self.X, self.Y, self.orientation)) + + +class SweeperAgent: + def __init__(self, dimensions=None): + self.dimrow = dimensions + self.current_position = None + self.orientation = "" + self.initial = set() + self.goal = set() + self.allowed_points = set() + self.puddle_points = set() + + + def where_am_i(self): + temp_map = [list(item) for item in SweeperAgent.loadMap("map.txt")] + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == ">" or pos == "<" or pos == "^" or pos == "v": + self.row = row + self.column = column + + return row, column + + # add orientation + + def where_to_go(self): + temp_map = [list(item) for item in SweeperAgent.loadMap("goal_map.txt")] + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == ">" or pos == "<" or pos == "^" or pos == "v": + self.row = row + self.column = column + + return row, column + + @staticmethod + def set_allowed(allowed_points): + temp_map = [list(item) for item in SweeperAgent.loadMap('map.txt')] + + a_row = 0 + a_column = 0 + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == "." or pos == 'p' or pos == '>' or pos == '<' or pos == 'v' or pos == '^': + a_row = row + a_column = column + location = tuple([a_row, a_column]) + allowed_points.add(location) + + @staticmethod + def set_puddles(puddle_points): + temp_map = [list(item) for item in SweeperAgent.loadMap('map.txt')] + + a_row = 0 + a_column = 0 + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == "p" : + a_row = row + a_column = column + location = tuple([a_row, a_column]) + puddle_points.add(location) + + + @staticmethod + def get_goal(): + temp_map = [list(item) for item in SweeperAgent.loadMap('goal_map.txt')] + + a_row = 0 + a_column = 0 + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == '>' or pos == '<' or pos == 'v' or pos == '^': + a_row = row + a_column = column + return a_row, a_column + + + @staticmethod + def set_initial(initial): + temp_map = [list(item) for item in SweeperAgent.loadMap('map.txt')] + + a_row = 0 + a_column = 0 + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == '>' or pos == '<' or pos == 'v' or pos == '^': + a_row = row + a_column = column + location = tuple([a_row, a_column]) + initial.add(location) + + + + + @staticmethod + def set_orientation(): + temp_map = [list(item) for item in SweeperAgent.loadMap('map.txt')] + + orientation = "" + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == ">": + orientation = "RIGHT" + if pos == "<": + orientation = "LEFT" + if pos == "^": + orientation = "UP" + if pos == "v": + orientation = "DOWN" + + return orientation + + @staticmethod + def set_goal_orientation(): + temp_map = [list(item) for item in SweeperAgent.loadMap('goal_map.txt')] + + orientation = "" + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == ">": + orientation = "RIGHT" + if pos == "<": + orientation = "LEFT" + if pos == "^": + orientation = "UP" + if pos == "v": + orientation = "DOWN" + + return orientation + + + @staticmethod + def run(self): + self.orientation = SweeperAgent.set_orientation() + goal_orientation = SweeperAgent.set_goal_orientation() + #SweeperAgent.set_initial(self.initial) + #SweeperAgent.set_goal(self.goal) + SweeperAgent.set_allowed(self.allowed_points) + SweeperAgent.set_puddles(self.puddle_points) + + x, y = self.where_am_i() + x1, y1 = SweeperAgent.get_goal() + + agent_position = AgentPosition(x, y, self.orientation) + goal_position = AgentPosition(x1, y1, goal_orientation) + + self.plan_route(agent_position, goal_position, self.allowed_points, self.puddle_points) + + + + """print("allowed: ") + print("(row, column)") + print(sorted(self.allowed_points)) + print("puddles:") + print(sorted(self.puddle_points)) + print("initial:") + print(self.initial) + print("goal:") + print(self.goal) + print("orientation:") + print(self.orientation)""" + + + def plan_route(self, current, goals, allowed, puddles): + problem = PlanRoute(current, goals, allowed, puddles) + return SweeperAgent.astar_search(problem, problem.h).solution() + #return SweeperAgent.astar_search(problem, problem.h) + + + + + + """TODO""" + # liczenie kosztów + # + + @staticmethod + def loadMap(map_name=''): + maze = [] + map_folder = path.dirname(__file__) + with open(path.join(map_folder, map_name), 'rt') as f: + for line in f: + maze.append(line.rstrip('\n')) + + # print(maze) + return maze + + @staticmethod + def astar_search(problem, h=None): + """A* search is best-first graph search with f(n) = g(n)+h(n). + You need to specify the h function when you call astar_search, or + else in your Problem subclass.""" + # h = memoize(h or problem.h, 'h') + return SweeperAgent.best_first_graph_search(problem, lambda n: n.path_cost + h(n)) + #return best_first_graph_search(problem) + + @staticmethod + #def best_first_graph_search(problem, f, display=False): + def best_first_graph_search(problem, f, display=True): + """Search the nodes with the lowest f scores first. + You specify the function f(node) that you want to minimize; for example, + if f is a heuristic estimate to the goal, then we have greedy best + first search; if f is node.depth then we have breadth-first search. + There is a subtlety: the line "f = memoize(f, 'f')" means that the f + values will be cached on the nodes as they are computed. So after doing + a best first search you can examine the f values of the path returned.""" + # f = memoize(f, 'f') + + """TODO""" + # Zaimplementować klasę Node dla Astar + + history = [] + + node = Node(problem.initial) + frontier = PriorityQueue('min', f) + frontier.append(node) + explored = set() + while frontier: + node = frontier.pop() + if problem.goal_test(node.state): + if display: + print(len(explored), "paths have been expanded and", len(frontier), "paths remain in the frontier") + return node + explored.add(node.state) + for child in node.expand(problem): + if child.state not in explored and child not in frontier: + frontier.append(child) + elif child in frontier: + if f(child) < frontier[child]: + del frontier[child] + frontier.append(child) + return None + + + +class PriorityQueue: + """A Queue in which the minimum (or maximum) element (as determined by f and + order) is returned first. + If order is 'min', the item with minimum f(x) is + returned first; if order is 'max', then it is the item with maximum f(x). + Also supports dict-like lookup.""" + + def __init__(self, order='min', f=lambda x: x): + self.heap = [] + if order == 'min': + self.f = f + elif order == 'max': # now item with max f(x) + self.f = lambda x: -f(x) # will be popped first + else: + raise ValueError("Order must be either 'min' or 'max'.") + + def append(self, item): + """Insert item at its correct position.""" + heapq.heappush(self.heap, (self.f(item), item)) + + def extend(self, items): + """Insert each item in items at its correct position.""" + for item in items: + self.append(item) + + def pop(self): + """Pop and return the item (with min or max f(x) value) + depending on the order.""" + if self.heap: + return heapq.heappop(self.heap)[1] + else: + raise Exception('Trying to pop from empty PriorityQueue.') + + def __len__(self): + """Return current capacity of PriorityQueue.""" + return len(self.heap) + + def __contains__(self, key): + """Return True if the key is in PriorityQueue.""" + return any([item == key for _, item in self.heap]) + + def __getitem__(self, key): + """Returns the first value associated with key in PriorityQueue. + Raises KeyError if key is not present.""" + for value, item in self.heap: + if item == key: + return value + raise KeyError(str(key) + " is not in the priority queue") + + def __delitem__(self, key): + """Delete the first occurrence of key.""" + try: + del self.heap[[item == key for _, item in self.heap].index(True)] + except ValueError: + raise KeyError(str(key) + " is not in the priority queue") + heapq.heapify(self.heap) + + +class Test: + @staticmethod + def run(): + + allowed_points = set() + puddle_points = set() + + initial = set() + goal = set() + + orientation = SweeperAgent.set_orientation() + + SweeperAgent.set_initial(initial) + SweeperAgent.set_goal(goal) + + SweeperAgent.set_allowed(allowed_points) + SweeperAgent.set_puddles(puddle_points) + + + + print("allowed: ") + print("(row, column)") + print(sorted(allowed_points)) + print("puddles:") + print(sorted(puddle_points)) + print("initial:") + print(initial) + print("goal:") + print(goal) + print("orientation:") + print(orientation) \ No newline at end of file diff --git a/astar2_document.txt b/astar2_document.txt new file mode 100644 index 0000000..7f3ae8f --- /dev/null +++ b/astar2_document.txt @@ -0,0 +1,98 @@ + + +class PlanRoute + + actions(state) przyjmuje mape? state + zwraca możliwe akcje agenta + + result(state, action) mapa? state, action(string) + + tworzy listę możliwych ruchów w liście proposed_loc + sprawdza, czy współrzędne w proposed_loc znajdują się w zbiorze allowed + + ustawia kierunek agenta oraz nowe położenie na mapie + zwraca state + + goal_test(state) przyjmuje state + sprawdza czy stan docelowy zgadza się ze stanem obecnym + zwraca wartość True lub False + + path_cost(c, state1, action, state2) + ocenia nowy koszt po zmianie stanu + zwraca nowy koszt + + def h(node) funkcja heurystyki, przyjmuje objekt klasy node + + przypisuje zmiennym x i y wartość współrzędnych + za pomocą funkcji get_location() + + mamy xy dla stanu obecnego + mamy xy dla stanu docelowego + + zwraca ogległość + + +class Node + + expand(problem) przyjmuje klasę problem + + tworzy węzły potomne na podstawie możliwych akcji + + zwraca listę węzłów potomnych + + child_node(problem, action) przyjmuje problem oraz akcję + tworzy węzeł potomny na podstawie otzymanej akcji + + zwraca węzeł potomny + + +class AgentPosition + + get_location + zwraca dwie zmienne: X i Y + + set_location + ustawia zmienne: X i Y + + get_orientation: + zwraca kierunek + + set_orientation: + ustawia kierunek + + + +class SweeperAgent - najbardziej tajemnicza klasa, bo do końca nie wiadomo co ma robić + + where_am_i() - niby ma zwracać położenie agenta na planszy + + set_allowed(allowed_points) + ustawia listę dostępnych miejsc na mapie + + set_puddles(puddle_points) + ustawia listę obecnych kałuż + + set_goal(goal) + ustawia punkt docelowy + + set_initial(initial) + ustawia punkt początkowy + + set_orientation() + ustawia kierunek + + plan_route() - czarna magia A* (∩ ͝ ° ͜ʖ͡° )⊃━☆゚ + + load_map() - ładowanie mapy + + astar_search() a* + + +class PriorityQueue - jakaś kolejka priorytetowa + + + + + + + diff --git a/goal_map.txt b/goal_map.txt index f32dcbe..a02a693 100644 --- a/goal_map.txt +++ b/goal_map.txt @@ -1,7 +1,7 @@ ....... -###.... -....... -....... -...###. -...#^#. -....... \ No newline at end of file +###.ppp +....p.. +....p.p +...###p +...#^#p +......p \ No newline at end of file diff --git a/images/puddle.bmp b/images/puddle.bmp new file mode 100644 index 0000000000000000000000000000000000000000..60f80d0d7f3090dce2f6a56b99ffa3ef6c95de56 GIT binary patch literal 16522 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 literal 0 HcmV?d00001 diff --git a/main.py b/main.py index 5e1804e..48b1044 100644 --- a/main.py +++ b/main.py @@ -7,7 +7,7 @@ from grid import * from settings import * from sprites import * from graphsearch import * - +from astar2 import * class Game: @@ -32,6 +32,7 @@ class Game: self.all_sprites = pg.sprite.Group() self.walls = pg.sprite.Group() self.mines = pg.sprite.Group() + self.puddles = pg.sprite.Group() for row, tiles in enumerate(self.map_data): for col, tile in enumerate(tiles): if tile == '2': @@ -42,6 +43,8 @@ class Game: Grenade(self, col, row) if tile == "#": Wall(self, col, row) + if tile == 'p': + Puddle(self, col, row) if tile == '>': self.player = Player(self, col, row, Direction.Right.name) if tile == '^': @@ -49,7 +52,7 @@ class Game: if tile == '<': self.player = Player(self, col, row, Direction.Left.name) if tile == 'v': - self.player = Player(self, col, row. Direction.Down.name) + self.player = Player(self, col, row, Direction.Down.name) def run(self): @@ -105,6 +108,12 @@ class Game: player_moves = BFS.run() self.graph_move(player_moves) self.wentyl_bezpieczenstwa = 1 + if event.key == pg.K_F4 and self.wentyl_bezpieczenstwa == 0: + print("test1") + agent = SweeperAgent() + SweeperAgent.run(agent) + # Test.run() + def graph_move(self, moves): diff --git a/map.txt b/map.txt index 1bc40f2..d3d7564 100644 --- a/map.txt +++ b/map.txt @@ -1,7 +1,7 @@ .>..... -###.... -....... -....... -...###. -...#.#. -....... \ No newline at end of file +###.ppp +....p.. +....p.p +...###p +...#.#p +......p \ No newline at end of file diff --git a/sprites.py b/sprites.py index 2ca7817..38c55dc 100644 --- a/sprites.py +++ b/sprites.py @@ -11,8 +11,8 @@ class Player(pg.sprite.Sprite): pg.sprite.Sprite.__init__(self, self.groups) self.game = game #self.image = pg.Surface((TILESIZE, TILESIZE)) - self.image = pg.image.load('images/robot.bmp') - self.baseImage = pg.image.load('images/robot.bmp') + self.image = pg.image.load('images/robot2.bmp') + self.baseImage = pg.image.load('images/robot2.bmp') #self.image.fill(YELLOW) self.image = pg.transform.scale(self.image, (TILESIZE, TILESIZE)) self.baseImage = pg.transform.scale(self.image, (TILESIZE, TILESIZE)) @@ -272,4 +272,19 @@ class Wall(pg.sprite.Sprite): self.rect.x = self.x * TILESIZE self.rect.y = self.y * TILESIZE +class Puddle(pg.sprite.Sprite): + def __init__(self, game, x, y): + self.groups = game.all_sprites, game.puddles + pg.sprite.Sprite.__init__(self, self.groups) + self.game = game + self.image = pg.image.load('images/puddle.bmp') + self.image = pg.transform.scale(self.image, (TILESIZE, TILESIZE)) + self.rect = self.image.get_rect() + self.x = x + self.y = y + + def update(self): + self.rect.x = self.x * TILESIZE + self.rect.y = self.y * TILESIZE + \ No newline at end of file diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000..985ccda --- /dev/null +++ b/todo.txt @@ -0,0 +1,270 @@ +todo: + + ________________ + |'-.--._ _________: + | / | __ __\ + | | _ | [\_\= [\_\ + | |.' '. \.........| + | ( <) ||: :|_ + \ '._.' | :.....: |_(o + '-\_ \ .------./ + _ \ ||.---.|| _ + / \ '-._|/\n~~\n' | \ + (| []=.--[===[()]===[) | + <\_/ \_______/ _.' /_/ + /// (_/_/ + |\\ [\\ + ||:| | I| + |::| | I| + ||:| | I| + ||:| : \: + |\:| \I| + :/\: ([]) + ([]) [| + || |\_ + _/_\_ [ -'-.__ + <] \> \_____.> + \__/ + + + __...------------._ + ,-' `-. + ,-' `. + ,' ,-`. + ; `-' `. + ; .-. \ + ; .-. `-' \ + ; `-' \ + ; `. + ; : + ; | + ; ; + ; ___ ; + ; ,-;-','.`.__ | + _..; ,-' ;`,'.`,'.--`. | + ///; ,-' `. ,-' ;` ;`,','_.--=: / + |'': ,' : ;` ;,;,,-'_.-._`. ,' IT'S A TRAP!!! + ' : ;_.-. `. :' ;;;'.ee. \| / + \.' _..-'/8o. `. : :! ' ':8888) || / + ||`-'' \\88o\ : : :! : :`""' ;;/ + || \"88o\; `. \ `. `. ;,' + /) ___ `."'/(--.._ `. `.`. `-..-' ;--. + \(.="""""==.. `'-' `.| `-`-..__.-' `. `. + | `"==.__ ) ) ; + | || `"=== ' .' .' + /\,,|||| | | \ .' .' + | |||'|' |'|' \| .' _.' \ + | |\' | | || || .' .' \ + ' | \ ' |' . ``-- `| || .' .' \ + ' | ' | . ``-.._ | ; .' .' `. + _.--,;`. . -- ...._,' .' .' `.__ + ,' ,'; `. . --..__..--'.' .' __/_\ + ,' ; ; | . --..__.._.' .' ,' `. + / ; : ; . -.. _.' _.' / ` + / : `-._ | . _.--' _.' | +/ `. `--....--'' _.' | + `._ _..-' | + `-..____...-'' | + | + | + + .-. + |_:_| + /(_Y_)\ +. ( \/M\/ ) + '. _.'-/'-'\-'._ + ': _/.--'[[[[]'--.\_ + ': /_' : |::"| : '.\ + ': // ./ |oUU| \.' :\ + ': _:'..' \_|___|_/ : :| + ':. .' |_[___]_| :.':\ + [::\ | : | | : ; : \ + '-' \/'.| |.' \ .;.' | + |\_ \ '-' : | + | \ \ .: : | | + | \ | '. : \ | + / \ :. .; | + / | | :__/ : \\ + | | | \: | \ | || + / \ : : |: / |__| /| + | : : :_/_| /'._\ '--|_\ + /___.-/_|-' \ \ + '-' + + +.-.__ \ .-. ___ __ +|_| '--.-.-( \/\;;\_\.-._______.-. +(-)___ \ \ .-\ \;;\( \ \ \ + Y '---._\_((Q)) \;;\\ .-\ __(_) + I __'-' / .--.((Q))---' \, + I ___.-: \| | \'-'_ \ + A .-' \ .-.\ \ \ \ '--.__ '\ + | |____.----((Q))\ \__|--\_ \ ' + ( ) '-' \_ : \-' '--.___\ + Y \ \ \ \(_) + I \ \ \ \, + I \ \ \ \ + A \ \ \ '\ + | \ \__| ' + \_:. \ + \ \ \ + \ \ \ + \_\_| + + .==. + ()''()-. + .---. ;--; / + .'_:___". _..'. __'. + |__ --==|'-''' \'...; + [ ] :[| |---\ + |__| I=[| .' '. + / / ____| : '._ + |-/.____.' | : : +snd /___\ /___\ '-'._----' + + + ___ |\________/) + [_,_]) \ / \| + /|=T=|] / __ __\ + |\ " // |_ 9 p ]\ + ||'-'/--. / /\ =| \|\ \ + /|| <\/> |\ | '._, @ @)<_) + | |\ | | \.__/(_;_) + | . H | | : '='| + | | _H__/ _| : | + \ '.__ \ / ; '; + __'-._(_}==.' : ; + (___| /-' | :. : + [.-' \ | \ \ ; : + .-' | | | | ": + / |==| \ \ / \_ + / [ | '._\_ -._ \ + / \__) __.- \ \ )\\ + / | /.' >>) + | \ |\ | + | .' '-. | \ / + | / / / / / + snd | / + + + ._,. + "..-..pf. + -L ..#' + .+_L ."]# + ,'j' .+.j` -'.__..,.,p. + _~ #..<..0. .J-.``..._f. + .7..#_.. _f. .....-..,`4' + ;` ,#j. T' .. ..J....,'.j` + .` .."^.,-0.,,,,yMMMMM,. ,-.J...+`.j@ + .'.`...' .yMMMMM0M@^=`""g.. .'..J..".'.jH + j' .'1` q'^)@@#"^".`"='BNg_...,]_)'...0- + .T ...I. j" .'..+,_.'3#MMM0MggCBf....F. + j/.+'.{..+ `^~'-^~~""""'"""?'"``'1` + .... .y.} `.._-:`_...jf + g-. .Lg' ..,..'-....,'. + .'. .Y^ .....',].._f + ......-f. .-,,.,.-:--&` + .`...'..`_J` + .~......'#' + '..,,.,_]` + .L..`..``. + + + + ,ooo888888888888888oooo, + o8888YYYYYY77iiiiooo8888888o + 8888YYYY77iiYY8888888888888888 + [88YYY77iiY88888888888888888888] + 88YY7iYY888888888888888888888888 + [88YYi 88888888888888888888888888] + i88Yo8888888888888888888888888888i + i] ^^^88888888^^^ o [i + oi8 i o8o i 8io + ,77788o ^^ ,oooo8888888ooo, ^ o88777, + 7777788888888888888888888888888888877777 + 77777888888888888888888888888888877777 + 77777788888888^7777777^8888888777777 + ,oooo888 ooo 88888778888^7777ooooo7777^8887788888 ,o88^^^^888oo + o8888777788[];78 88888888888888888888888888888888888887 7;8^ 888888888oo^88 + o888888iii788 ]; o 78888887788788888^;;^888878877888887 o7;[]88888888888888o + 88888877 ii78[]8;7o 7888878^ ^8788^;;;;;;^878^ ^878877 o7;8 ]878888888888888 + [88888888887888 87;7oo 777888o8888^;ii;;ii;^888o87777 oo7;7[]8778888888888888 + 88888888888888[]87;777oooooooooooooo888888oooooooooooo77;78]88877i78888888888 + o88888888888888 877;7877788777iiiiiii;;;;;iiiiiiiii77877i;78] 88877i;788888888 + 88^;iiii^88888 o87;78888888888888888888888888888888888887;778] 88877ii;7788888 +;;;iiiii7iiii^ 87;;888888888888888888888888888888888888887;778] 888777ii;78888 +;iiiii7iiiii7iiii77;i88888888888888888888i7888888888888888877;77i 888877777ii78 +iiiiiiiiiii7iiii7iii;;;i7778888888888888ii7788888888888777i;;;;iiii 88888888888 +i;iiiiiiiiiiii7iiiiiiiiiiiiiiiiiiiiiiiiii8877iiiiiiiiiiiiiiiiiii877 88888 +ii;;iiiiiiiiiiiiii;;;ii^^^;;;ii77777788888888888887777iii;; 77777 78 +77iii;;iiiiiiiiii;;;ii;;;;;;;;;^^^^8888888888888888888777ii;; ii7 ;i78 +^ii;8iiiiiiii ';;;;ii;;;;;;;;;;;;;;;;;;^^oo ooooo^^^88888888;;i7 7;788 +o ^;;^^88888^ 'i;;;;;;;;;;;;;;;;;;;;;;;;;;;^^^88oo^^^^888ii7 7;i788 +88ooooooooo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 788oo^;; 7;i888 +887ii8788888 ;;;;;;;ii;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;^87 7;788 +887i8788888^ ;;;;;;;ii;;;;;;;oo;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,, ;;888 +87787888888 ;;;;;;;ii;;;;;;;888888oo;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,;i788 +87i8788888^ ';;;ii;;;;;;;8888878777ii8ooo;;;;;;;;;;;;;;;;;;;;;;;;;;i788 7 +77i8788888 ioo;;;;;;oo^^ooooo ^7i88^ooooo;;;;;;;;;;;;;;;;;;;;i7888 78 +7i87788888o 7;ii788887i7;7;788888ooooo7888888ooo;;;;;;;;;;;;;;oo ^^^ 78 +i; 7888888^ 8888^o;ii778877;7;7888887;;7;7788878;878;; ;;;;;;;i78888o ^ +i8 788888 [88888^^ ooo ^^^^^;;77888^^^^;;7787^^^^ ^^;;;; iiii;i78888888 +^8 7888^ [87888 87 ^877i;i8ooooooo8778oooooo888877ii; iiiiiiii788888888 + ^^^ [7i888 87;; ^8i;;i7888888888888888887888888 i7iiiiiii88888^^ + 87;88 o87;;;;o 87i;;;78888788888888888888^^ o 8ii7iiiiii;; + 87;i8 877;77888o ^877;;;i7888888888888^^ 7888 78iii7iii7iiii + ^87; 877;778888887o 877;;88888888888^ 7ii7888 788oiiiiiiiii + ^ 877;7 7888888887 877i;;8888887ii 87i78888 7888888888 + [87;;7 78888888887 87i;;888887i 87ii78888 7888888888] + 877;7 7788888888887 887i;887i^ 87ii788888 78888888888 + 87;i8 788888888888887 887ii;;^ 87ii7888888 78888888888 + [87;i8 7888888888888887 ^^^^ 87ii77888888 78888888888 + 87;;78 7888888888888887ii 87i78888888 778888888888 + 87;788 7888888888888887i] 87i78888888 788888888888 + [87;88 778888888888888887 7ii78888888 788888888888 + 87;;88 78888888888888887] ii778888888 78888888888] + 7;;788 7888888888888888] i7888888888 78888888888' + 7;;788 7888888888888888 'i788888888 78888888888 + 7;i788 788888888888888] 788888888 77888888888] + '7;788 778888888888888] [788888888 78888888888' + ';77888 78888888888888 8888888888 7888888888] + 778888 78888888888888 8888888888 7888888888] + 78888 7888888888888] [8888888888 7888888888 + 7888 788888888888] 88888888888 788888888] + 778 78888888888] ]888888888 778888888] + oooooo ^88888^ ^88888^^^^^^^^8888] + 87;78888ooooooo8o ,oooooo oo888oooooo + [877;i77888888888] [;78887i8888878i7888; + ^877;;ii7888ii788 ;i777;7788887787;778; + ^87777;;;iiii777 ;77^^^^^^^^^^^^^^^^;; + ^^^^^^^^^ii7] ^ o88888888877iiioo + 77777o [88777777iiiiii;;778 + 77777iii 8877iiiii;;;77888888] + 77iiii;8 [77ii;778 788888888888 + 7iii;;88 iii;78888 778888888888 + 77i;78888] ;;;;i88888 78888888888 + ,7;78888888 [;;i788888 7888888888] + i;788888888 ;i7888888 7888888888 + ;788888888] i77888888 788888888] + ';88888888' [77888888 788888888] + [[8ooo88] 78888888 788888888 + [88888] 78888888 788888888 + ^^^ [7888888 77888888] + 88888888 7888887 + 77888888 7888887 + ;i88888 788888i + ,;;78888 788877i7 + ,7;;i;777777i7i;;7 + 87778^^^ ^^^^87778 + ^^^^ o777777o ^^^ + o77777iiiiii7777o + 7777iiii88888iii777 + ;;;i7778888888877ii;; + Imperial Stormtrooper [i77888888^^^^8888877i] + (Standard Shock Trooper) 77888^oooo8888oooo^8887] + [788888888888888888888888] + 88888888888888888888888888 + ]8888888^iiiiiiiii^888888] + iiiiiiiiiiiiiiiiiiiiii + ^^^^^^^^^^^^^ +