fixed a_Star algorithm

This commit is contained in:
piowyg 2021-04-26 18:46:56 +02:00
parent 37dc6d5595
commit 6a08195fe0
7 changed files with 72 additions and 40 deletions

View File

@ -1,8 +1,9 @@
import os import os
import pygame as pg import pygame as pg
from ap_mine import APMine
from image import Image from image import Image
from tile import Tile
main_path = os.path.dirname(os.getcwd()) main_path = os.path.dirname(os.getcwd())
@ -53,14 +54,14 @@ for name in [
DEBUG_FIELD = [ DEBUG_FIELD = [
[1, 11, 1, 1, 1, 1, 1, 1, 1, 1], [Tile(1, 1), Tile(11, 20), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1)],
[1, 1, 1, 1, 4, 1, 1, 1, 1, 1], [Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(4, 1, APMine()), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1)],
[11, 1, 1, 1, 11, 4, 1, 1, 1, 1], [Tile(11, 20), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(11, 20), Tile(4, 0, APMine()), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1)],
[4, 1, 1, 1, 11, 1, 1, 4, 1, 1], [Tile(4, 0, APMine()), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(11, 20), Tile(1, 1),Tile(1, 1), Tile(4, 0, APMine()), Tile(1, 1),Tile(1, 1)],
[1, 1, 1, 1, 1, 1, 1, 11, 1, 1], [Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(11, 20), Tile(1, 1), Tile(1, 1)],
[1, 1, 1, 1, 1, 1, 1, 11, 4, 1], [Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(11, 20), Tile(4, 0, APMine()), Tile(1, 1)],
[1, 1, 1, 1, 1, 1, 1, 11, 1, 1], [Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(1, 1), Tile(11, 20), Tile(1, 1), Tile(1, 1)],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [Tile(1, 1) for _ in range(10)],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [Tile(1, 1) for _ in range(10)],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [Tile(1, 1) for _ in range(10)],
] ]

View File

@ -8,10 +8,10 @@ from tilesFactory import TilesFactory
def generate_field() -> List[List[Tile]]: def generate_field() -> List[List[Tile]]:
tiles_factory = TilesFactory() tiles_factory = TilesFactory()
tiles_list = tiles_factory.get_tiles_list() tiles_list = tiles_factory.get_tiles_list()
return [choices(tiles_list, weights=[10, 10, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2], k=10) for _ in range(10)] return [choices(tiles_list, weights=[10, 10, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], k=10) for _ in range(10)]
class Environment: class Environment:
def __init__(self, field: List[List[Tile]] = None): def __init__(self, field: List[List[Tile]] = None):
self.field = field if field else generate_field() self.field = generate_field()
self.mine_count = sum(sum(1 for tile in row if tile.mine) for row in self.field) self.mine_count = sum(sum(1 for tile in row if tile.mine) for row in self.field)

View File

@ -1,13 +1,11 @@
from typing import Tuple
import pygame as pg import pygame as pg
from agent import Agent from agent import Agent
from game_ui import GameUi from game_ui import GameUi
from const import ICON, IMAGES from const import ICON, IMAGES
from environment import Environment from environment import Environment
from search_algoritms.BFS import breadth_first_search from search_algoritms.BFS import breadth_first_search, breadth_first_search_for_a_star
from src.search_algoritms.a_star import a_star, nearest_bomb from src.search_algoritms.a_star import a_star
from tilesFactory import TilesFactory from tilesFactory import TilesFactory
@ -64,21 +62,21 @@ def main():
elif event.type == pg.KEYDOWN: elif event.type == pg.KEYDOWN:
if event.key == pg.K_t: if event.key == pg.K_t:
print('Starting to clear the sector') print('Starting to clear the sector')
#while env.mine_count: while env.mine_count:
print('-'*20) print('-'*20)
#path, actions = breadth_first_search(env.field, agent.x, agent.y, agent.direction) #path, actions = breadth_first_search(env.field, agent.x, agent.y, agent.direction)
#xd: Tuple[int,int] = Tuple[agent.x, agent.y] path, actions = a_star (env.field, agent.x, agent.y, agent.direction,
path, actions = a_star(env.field, agent.x, agent.y, agent.direction, nearest_bomb((agent.x, agent.y), env.field)) breadth_first_search_for_a_star (env.field, agent.x, agent.y,
if not path and not env.field[agent.y][agent.x].mine: agent.direction))
print('Unable to find path, rocks are in the way') if not path and not env.field[agent.y][agent.x].mine:
break print('Unable to find path, rocks are in the way')
print(f'Path{path}') break
print(f'Actions:{actions}') print(f'Path{path}')
for action in actions: print(f'Actions:{actions}')
pg.fastevent.post(pg.event.Event(pg.KEYDOWN, {'key': action})) for action in actions:
pg.fastevent.post(pg.event.Event(pg.KEYDOWN, {'key': action}))
pg.fastevent.post(pg.event.Event(pg.KEYDOWN, {'key': pg.K_SPACE})) pg.fastevent.post(pg.event.Event(pg.KEYDOWN, {'key': pg.K_SPACE}))
handle_keys(env, agent, game_ui, factory) handle_keys(env, agent, game_ui, factory)
print('Sector clear') print('Sector clear')
else: else:
pg.fastevent.post(event) pg.fastevent.post(event)

View File

@ -26,3 +26,25 @@ def breadth_first_search(field: List[List[Tile]], start_x: int, start_y: int, st
node_queue.put(neighbour_node) node_queue.put(neighbour_node)
return False, False return False, False
def breadth_first_search_for_a_star(field: List[List[Tile]], start_x: int, start_y: int, start_direction: int):
explored = []
node_queue = queue.Queue()
node_queue.put(Node(start_x, start_y, start_direction))
while not node_queue.empty():
node = node_queue.get()
if field[node.y][node.x].mine:
return node.x, node.y
explored.append(node)
for x, y, direction, action in successor(field, node.x, node.y, node.direction):
neighbour_node = Node(x, y, direction, node, action)
node_queue_list = node_queue.queue
if neighbour_node in explored or neighbour_node in node_queue_list:
continue
node_queue.put(neighbour_node)
return False, False

View File

@ -1,11 +1,10 @@
from operator import itemgetter
from typing import List, Tuple from typing import List, Tuple
from ap_mine import APMine from ap_mine import APMine
from at_mine import ATMine from at_mine import ATMine
from src.node import Node from src.node import Node
from src.tile import Tile from src.tile import Tile
from .helpers import successor, get_path_actions, calculate_priority from .helpers import successor, get_path_actions_a_star, calculate_priority
def a_star(field: List[List[Tile]], start_x: int, start_y: int, start_direction: int, goal: Tuple[int, int]): def a_star(field: List[List[Tile]], start_x: int, start_y: int, start_direction: int, goal: Tuple[int, int]):
@ -17,8 +16,8 @@ def a_star(field: List[List[Tile]], start_x: int, start_y: int, start_direction:
# przy get wyciąga element z najniższą wartością priorytetu # przy get wyciąga element z najniższą wartością priorytetu
if (node.x, node.y) == goal: if (node.x, node.y) == goal:
return get_path_actions(node) return get_path_actions_a_star(node, field)
explored.append(node) explored.append(node)
for x, y, direction, action in successor(field, node.x, node.y, node.direction): for x, y, direction, action in successor(field, node.x, node.y, node.direction):
neighbour_node = Node(x, y, direction, node, action) neighbour_node = Node(x, y, direction, node, action)
@ -48,4 +47,4 @@ def nearest_bomb(a: Tuple[int, int], field: List[List[Tile]]):
min = distance min = distance
min_x = x min_x = x
min_y = y min_y = y
return (min_x, min_y) return min_x, min_y

View File

@ -28,7 +28,7 @@ def successor(field: List[List[Tile]], x: int, y: int, direction: int):
return neighbours return neighbours
def get_path_actions(node: Node): def get_path_actions(node: Node, field: List[List[Tile]]):
path = [] path = []
actions = [] actions = []
while node.parent: while node.parent:
@ -37,6 +37,18 @@ def get_path_actions(node: Node):
node = node.parent node = node.parent
return path[::-1], actions[::-1] return path[::-1], actions[::-1]
def get_path_actions_a_star(node: Node, field: List[List[Tile]]):
path = []
actions = []
while node.parent:
path.append((node.x, node.y))
print(field[node.y][node.x], field[node.y][node.x].weight, node.x, node.y, field[node.y][node.x].mine)
if field[node.y][node.x].mine:
actions.append(32)
actions.append(node.action)
node = node.parent
return path[::-1], actions[::-1]
def cost(field: List[List[Tile]], node): def cost(field: List[List[Tile]], node):
return 1 if (node.parent.x, node.parent.y) == (node.x, node.y) else field[node.y][node.x].weight return 1 if (node.parent.x, node.parent.y) == (node.x, node.y) else field[node.y][node.x].weight

View File

@ -10,9 +10,9 @@ class TilesFactory:
img = IMAGES[number] img = IMAGES[number]
if img.mine_type: if img.mine_type:
module = import_module(f'{img.mine_type.lower()}_mine') module = import_module(f'{img.mine_type.lower()}_mine')
return Tile(number, 1, getattr(module, f'{img.mine_type}Mine')()) return Tile(number, 0, getattr(module, f'{img.mine_type}Mine')())
else: else:
return Tile(number, 1) if 'grass' in img.name else Tile(number, 20) return Tile(number, 5) if 'grass' in img.name else Tile(number, 30)
def get_tiles_list(self) -> List[Tile]: def get_tiles_list(self) -> List[Tile]:
return [self.create_tile(i) for i in range(13)] return [self.create_tile(i) for i in range(13)]