diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..331511a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "python.analysis.extraPaths": [ + "./path_alghoritms", + "./path_algorithms" + ] +} \ No newline at end of file diff --git a/__pycache__/astar.cpython-310.pyc b/__pycache__/astar.cpython-310.pyc new file mode 100644 index 0000000..f96716a Binary files /dev/null and b/__pycache__/astar.cpython-310.pyc differ diff --git a/__pycache__/bfs.cpython-310.pyc b/__pycache__/bfs.cpython-310.pyc index 079bba1..b4cdcb1 100644 Binary files a/__pycache__/bfs.cpython-310.pyc and b/__pycache__/bfs.cpython-310.pyc differ diff --git a/__pycache__/config.cpython-310.pyc b/__pycache__/config.cpython-310.pyc index 30e5ecf..1c88cee 100644 Binary files a/__pycache__/config.cpython-310.pyc and b/__pycache__/config.cpython-310.pyc differ diff --git a/__pycache__/main.cpython-310.pyc b/__pycache__/main.cpython-310.pyc index 50fc8eb..030511e 100644 Binary files a/__pycache__/main.cpython-310.pyc and b/__pycache__/main.cpython-310.pyc differ diff --git a/__pycache__/map_add_ons.cpython-310.pyc b/__pycache__/map_add_ons.cpython-310.pyc index 5e59ca2..3a7d0f2 100644 Binary files a/__pycache__/map_add_ons.cpython-310.pyc and b/__pycache__/map_add_ons.cpython-310.pyc differ diff --git a/__pycache__/node.cpython-310.pyc b/__pycache__/node.cpython-310.pyc new file mode 100644 index 0000000..f6fa81c Binary files /dev/null and b/__pycache__/node.cpython-310.pyc differ diff --git a/astar.py b/astar.py new file mode 100644 index 0000000..8892695 --- /dev/null +++ b/astar.py @@ -0,0 +1,64 @@ +from config import * +import heapq + +class Astar(): + + def __init__(self,game): + + self.g = game + + # Define the movement directions (up, down, left, right) + self.directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] + + def heuristic(self,a, b): + # Calculate the Manhattan distance between two points + return abs(b[0] - a[0]) + abs(b[1] - a[1]) + + def get_successors(self,position): + # Get the neighboring cells that can be traversed + successors = [] + for direction in self.directions: + neighbor = (position[0] + direction[0], position[1] + direction[1]) + if 0 <= neighbor[0] < TILE_SIZE and 0 <= neighbor[1] < TILE_SIZE and self.g.obstacles[neighbor[0]][neighbor[1]] == False: + successors.append(neighbor) + return successors + + def print_path(self,came_from, current,path): + # Recursively print the path from the start to the current position + if current in came_from: + path = self.print_path(came_from, came_from[current],path) + path.append(self.g.bfs.get_cell_number(current[0]*TILE_SIZE,current[1]*TILE_SIZE)) + print("Budowanie ścieżki: ",path) + return path + + def a_star(self,start, goal,path): + open_set = [] + heapq.heappush(open_set, (0, start)) # Priority queue with the start position + came_from = {} + g_scores = {start: 0} # Cost from start to each position + f_scores = {start: self.heuristic(start, goal)} # Total estimated cost from start to goal through each position + + while open_set: + _, current = heapq.heappop(open_set) + + if current == goal: + # Goal reached, print the path + path = self.print_path(came_from, goal,path) + return path + + for successor in self.get_successors(current): + # Calculate the cost to move from the current position to the successor + cost = self.g.cell_costs[successor[0]][successor[1]] + tentative_g_score = g_scores[current] + cost + + if successor not in g_scores or tentative_g_score < g_scores[successor]: + # Update the cost and priority if it's a better path + came_from[successor] = current + g_scores[successor] = tentative_g_score + f_scores[successor] = tentative_g_score + self.heuristic(successor, goal) + heapq.heappush(open_set, (f_scores[successor], successor)) + # No path found + print("No path found.") + + + diff --git a/bfs.py b/bfs.py index 6a8f198..160cdc5 100644 --- a/bfs.py +++ b/bfs.py @@ -41,7 +41,7 @@ class Bfs(): def get_cell_number(self,x, y): #zamienia koordynaty na numer kratki cell_number = None - cell_number =(x // TILE_SIZE) + (NUM_ROWS * (( y// TILE_SIZE))) + cell_number =(x // TILE_SIZE) + (ROWS * (( y// TILE_SIZE))) return cell_number def get_possible_moves(self,cell_number): @@ -66,28 +66,28 @@ class Bfs(): def get_up_cell(self,cell_number): - cell_row_number = cell_number // NUM_ROWS + cell_row_number = cell_number // ROWS if (cell_row_number - 1 < 0): return None else: - return (cell_number - NUM_ROWS) + return (cell_number - ROWS) def get_right_cell(self,cell_number): - cell_column_number = cell_number % NUM_ROWS - if (cell_column_number + 1 >= NUM_ROWS): + cell_column_number = cell_number % ROWS + if (cell_column_number + 1 >= ROWS): return None else: return (cell_number + 1) def get_down_cell(self,cell_number): - cell_row_number = cell_number // NUM_ROWS - if (cell_row_number + 1 >= NUM_ROWS): + cell_row_number = cell_number // ROWS + if (cell_row_number + 1 >= ROWS): return None else: - return (cell_number + NUM_ROWS) + return (cell_number + ROWS) def get_left_cell(self,cell_number): - cell_column_number = cell_number % NUM_ROWS + cell_column_number = cell_number % ROWS if (cell_column_number - 1 < 0): return None else: @@ -103,17 +103,17 @@ class Bfs(): if(from_cell - 1 == to_cell): return True - if(from_cell - NUM_ROWS == to_cell): + if(from_cell - ROWS == to_cell): return True - if(from_cell + NUM_ROWS == to_cell): + if(from_cell + ROWS == to_cell): return True return False def get_coordinates(self,cell_to_move): #zamienia numer kratki na koordynaty - cell_row_number = cell_to_move // NUM_ROWS - cell_column_number = cell_to_move % NUM_ROWS + cell_row_number = cell_to_move // ROWS + cell_column_number = cell_to_move % ROWS y = cell_row_number * TILE_SIZE x = cell_column_number * TILE_SIZE diff --git a/config.py b/config.py index ccfd4da..8454bb0 100644 --- a/config.py +++ b/config.py @@ -3,7 +3,8 @@ WIDTH, HEIGHT = 832, 832 TILE_SIZE = 64 BLACK = ((0,0,0)) WHITE = ((255,255,255)) -NUM_ROWS = WIDTH//TILE_SIZE AGENT_LAYER = 2 FLOWER_LAYER = 1 -GRASS_LAYER = 3 \ No newline at end of file +GRASS_LAYER = 3 +ROWS = HEIGHT // TILE_SIZE +COLS = WIDTH // TILE_SIZE \ No newline at end of file diff --git a/main.py b/main.py index 21d2aaf..61bc9a7 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,13 @@ + import pygame from config import * from agent import * from map_add_ons import * from mobs import * from bfs import * -from heapq import * from nn import * +from astar import * + class Game: @@ -15,7 +17,7 @@ class Game: self.SCREEN = pygame.display.set_mode((WIDTH, HEIGHT)) self.running = True self.clock = pygame.time.Clock() - + self.BACKGROUND_IMG= pygame.image.load("./pozostale_zdjecia/podloze.jpg") self.BACKGROUND = pygame.transform.scale(self.BACKGROUND_IMG,(64,64)) @@ -26,6 +28,12 @@ class Game: self.bfs = Bfs(self) self.nn = NeuralN() + self.astar = Astar(self) + + self.cell_costs = [[1 for _ in range(TILE_SIZE)] for _ in range(TILE_SIZE)] + self.obstacles = [[False for _ in range(TILE_SIZE)] for _ in range(TILE_SIZE)] + + def new(self): # tworzy się nowa sesja grania @@ -42,23 +50,25 @@ class Game: self.agent = Agent(self,1,1) self.archer_ork = Archer_ork(self,10,10) + self.obstacles[10][10] = True self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.archer_ork.x,self.archer_ork.y)) self.infantry_ork = Infantry_ork(self,10,4) + self.obstacles[10][4] = True self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.infantry_ork.x,self.infantry_ork.y)) self.sauron = Sauron(self, 1, 10) + self.obstacles[1][10] = True self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.sauron.x,self.sauron.y)) self.flower = Health_flower(self, 8,2) - - self.grass = Grass(self,0,2) - self.grass = Grass(self,1,2) - self.grass = Grass(self,0,3) - self.grass = Grass(self,1,3) - self.grass = Grass(self,0,4) - self.grass = Grass(self,1,4) - cost_cell_1000=[13,26,27,40] + + for y in range (2,5): + for x in range (2): + self.grass = Grass(self,x,y) + self.cell_costs[x][y] = 5 + for y in range(5): self.rock = Rocks(self,3,y) + self.obstacles[3][y] = True self.bfs.wall_cells.append(self.bfs.get_cell_number(self.rock.x,self.rock.y)) @@ -71,6 +81,15 @@ class Game: if event.type == pygame.QUIT: self.running = False pygame.quit() + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_SPACE: + self.start_pos = (self.agent.x//TILE_SIZE, self.agent.y//TILE_SIZE) + self.goal_pos = (self.flower.x//TILE_SIZE, self.flower.y//TILE_SIZE) + self.path = [] + self.move_agent(self.astar.a_star(self.start_pos, self.goal_pos,self.path)) + + + if event.type == pygame.MOUSEBUTTONDOWN: mouse_presses = pygame.mouse.get_pressed() if mouse_presses[0]: @@ -78,7 +97,7 @@ class Game: x = self.sauron.x y = self.sauron.y mob_image = self.sauron.SAURON_IMG - while True: #do poprawienia poprawne rozpoznawanie póki co nie będzie działać dobrze + while True: #do poprawienia poprawne rozpoznawanie póki co nie będzie działać dobrze, program się będzie zawieszać prediction = self.prediction_road(x,y,mob_image) if prediction == "SAURON": x = self.infantry_ork.x @@ -162,114 +181,9 @@ class Game: self.update() self.map() - grass_cells = [] - -cols, rows = 13,12 -def get_circle(x,y): - return (x * TILE_SIZE + TILE_SIZE//2, y* TILE_SIZE + TILE_SIZE//2), TILE_SIZE//4 -def get_rect(x,y): - return x*TILE_SIZE +1, y* TILE_SIZE +1, TILE_SIZE -2, TILE_SIZE -2 -''' -def get_next_nodes(x,y): - check_next_node = lambda x, y:True if 0<= x < cols and 0<=y < rows else False - ways =[-1,0],[0,-1],[1,0],[0,1] - return [(grid[y + dy][x + dx], (x + dx, y + dy)) for dx, dy in ways if check_next_node(x + dx, y + dy)] -''' -def get_neighbours(x, y): - check_neighbour = lambda x, y: True if 0 <= x < cols and 0 <= y < rows else False - ways = [-1, 0], [0, -1], [1, 0], [0, 1] - return [(grid[y + dy][x + dx], (x + dx, y + dy)) for dx, dy in ways if check_neighbour(x + dx, y + dy)] -def heuristic(a, b): - return abs(a[0] - b[0]) + abs(a[1] - b[1]) -def dijkstra(start, goal, graph): - queue = [] - heappush(queue, (0, start)) - cost_visited = {start: 0} - visited = {start: None} - - while queue: - cur_cost, cur_node = heappop(queue) - if cur_node == goal: - break - - neighbours = graph[cur_node] - for neighbour in neighbours: - neigh_cost, neigh_node = neighbour - new_cost = cost_visited[cur_node] + neigh_cost - - if neigh_node not in cost_visited or new_cost < cost_visited[neigh_node]: - priority = new_cost + heuristic(neigh_node, goal) - heappush(queue, (priority, neigh_node)) - cost_visited[neigh_node] = new_cost - visited[neigh_node] = cur_node - return visited -grid =['2229222222222', - '2229222222222', - '9929222222222', - '9929222222222', - '9929222222222', - '2222222222222', - '2222222222222', - '2222222222222', - '2222222222222', - '2222222222222', - '2222222222222', - '2222222222222' - ] -grid = [[int(char) for char in string ] for string in grid] - - -graph ={} -for y, row in enumerate(grid): - for x, col in enumerate(row): - graph[(x, y)] = graph.get((x, y), []) + get_neighbours(x, y) -#print("graph 2 0",graph[(2,0)]) - -start = (1,1) -goal =(0,5) -queue =[] -heappush(queue, (0,start)) -cost_visited = {start:0} -visited = {start: None} -goall=1 -while goall==1: - if queue: - visited=dijkstra(start,goal,graph) - goall=0 - -path=[] -path_head, path_segment = goal, goal -while path_segment: - # print("path_segment: ",path_segment) - - path_segment =visited[path_segment] - path.append(path_segment) -#print("path_head",path_head) -path.pop(len(path)-1) -path.reverse() -path_true=[] -bfss =Bfs(Game) - - -for i in path: - z=str(i) - #print("Z:",z) - x=z[1] - y=z[4] - x=int(x)*64 - y=int(y)*64 - a=bfss.get_cell_number(x,y) - path_true.append(a) -#print("path:",path) -#print("path_true:",path_true) -#bfss.move_agent(path_true) - - - - - g = Game() g.new() + while g.running: g.main() diff --git a/map_add_ons.py b/map_add_ons.py index c53cdde..1ccf826 100644 --- a/map_add_ons.py +++ b/map_add_ons.py @@ -50,8 +50,6 @@ class Grass(pygame.sprite.Sprite): self.rect.x = self.x self.rect.y = self.y - self.cost = 10 - self._layer = GRASS_LAYER class Health_flower(pygame.sprite.Sprite):