improving a_star algorithm

This commit is contained in:
piowyg 2021-04-25 21:32:43 +02:00
parent b46ebc9b3e
commit 7e61c61116
11 changed files with 110 additions and 20 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -22,10 +22,13 @@ for name, val in {
'grass_02_mineAT_01': 1, 'grass_02_mineAT_01': 1,
'grass_02_mineAP_02': 1, 'grass_02_mineAP_02': 1,
'grass_02_mineAP_03': 1, 'grass_02_mineAP_03': 1,
'mud_01':0,
'mud_02':1
}.items(): }.items():
IMAGES.append( IMAGES.append(
Image( Image(
val, val,
name,
pg.image.load( pg.image.load(
main_path + '/images/Tiles/' + name + ".png" main_path + '/images/Tiles/' + name + ".png"
), ),

View File

@ -8,7 +8,7 @@ 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], k=10) for _ in range(10)] return [choices(tiles_list, weights=[10, 10, 4, 4, 4, 4, 4, 4, 4, 4, 4,2,2], k=12) for _ in range(12)]
class Environment: class Environment:

View File

@ -1,10 +1,12 @@
import string
from typing import Union from typing import Union
from pygame import image from pygame import image
class Image: class Image:
def __init__(self, parent: int, img: image, mine_type: Union[str, None]): def __init__(self, parent: int, name: string, img: image, mine_type: Union[str, None]):
self.parent = parent self.parent = parent
self.img = img self.img = img
self.mine_type = mine_type self.mine_type = mine_type
self.name = name

View File

@ -1,3 +1,5 @@
from typing import Tuple
import pygame as pg import pygame as pg
from agent import Agent from agent import Agent
@ -5,6 +7,7 @@ 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
from src.search_algoritms.a_star import a_star, nearest_bomb
from tilesFactory import TilesFactory from tilesFactory import TilesFactory
@ -64,6 +67,8 @@ def main():
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, nearest_bomb((agent.x, agent.y), env.field))
if not path and not env.field[agent.y][agent.x].mine: if not path and not env.field[agent.y][agent.x].mine:
print('Unable to find path, rocks are in the way') print('Unable to find path, rocks are in the way')
break break

View File

@ -1,8 +1,8 @@
import queue import queue
from typing import List from typing import List
from node import Node from src.node import Node
from tile import Tile from src.tile import Tile
from .helpers import successor, get_path_actions from .helpers import successor, get_path_actions

View File

@ -1,14 +1,15 @@
from typing import List, Tuple from typing import List, Tuple
from operator import itemgetter from operator import itemgetter
from node import Node from src.node import Node
from tile import Tile from src.tile import Tile
from .helpers import successor, get_path_actions from .helpers import successor, get_path_actions, calculate_priority
from ..mine import Mine
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]):
explored = [] explored = []
node_queue: List[Tuple[int, Node]] = [(1, Node(start_x, start_y, start_direction))] node_queue: List[Tuple[int, Node]] = [(field[start_x][start_y].weight, Node(start_x, start_y, start_direction))]
# do kolejki dodawać krotke (priorytet, obiekt) # do kolejki dodawać krotke (priorytet, obiekt)
while node_queue: while node_queue:
@ -21,14 +22,36 @@ def a_star(field: List[List[Tile]], start_x: int, start_y: int, start_direction:
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)
neighbour_priority = calculate_priority(node, goal) neighbour_priority = calculate_priority(field, node, goal)
if neighbour_node not in explored and all(neighbour_node not in queue_tuple for queue_tuple in node_queue): if neighbour_node not in explored and all(neighbour_node not in queue_tuple for queue_tuple in node_queue):
node_queue.append((neighbour_priority, neighbour_node)) node_queue.append((neighbour_priority, neighbour_node))
node_queue = sorted(node_queue, key=itemgetter(0)) node_queue = sorted(node_queue, key=itemgetter(0))
elif (index := [ elif (index := [
index for index, queue_tuple in enumerate(node_queue) if neighbour_priority > queue_tuple[0] index for index, queue_tuple in enumerate(node_queue) if neighbour_priority > queue_tuple[0] and neighbour_node == queue_tuple[1]
][0]): ]):
node_queue[index] = (neighbour_priority, neighbour_node) print(index)
node_queue[index[0]] = (neighbour_priority, neighbour_node)
node_queue = sorted(node_queue, key=itemgetter(0)) node_queue = sorted(node_queue, key=itemgetter(0))
return False, False return False, False
def heuristic(a: Tuple[int, int], b: Tuple[int, int]):
(x1,y1) = a
(x2,y2) = b
return abs(x1 - x2) + abs(y1 - y2)
def nearest_bomb(a: Tuple[int, int],field: List[List[Tile]]):
min = 20
min_x = 0
min_y = 0
for x in range(10):
for y in range(10):
if issubclass(Mine,field[x][y].mine.__class__):
distance = abs(a[0] - x) + abs(a[1] - y)
if distance < min:
min = distance
min_x = x
min_y = y
return (min_x, min_y)

View File

@ -1,9 +1,31 @@
from typing import List from typing import List, Tuple
import pygame as pg import pygame as pg
from tile import Tile from src.node import Node
from node import Node from src.tile import Tile
def successor(field: List[List[Tile]], x: int, y: int, direction: int):
"""
kody klawiszy:
:a -> 97
:d -> 100
:w -> 119
"""
neighbours = []
coord = 'x' if direction in (1, 3) else 'y'
shift = -1 if direction in (0, 3) else 1
neighbours.append((x, y, (direction - 1) % 4, pg.K_a))
neighbours.append((x, y, (direction + 1) % 4, pg.K_d))
if coord == 'x' and 0 <= x + shift <= 9 and field[y][x + shift].number not in (2, 3):
neighbours.append((x + shift, y, direction, pg.K_w))
elif coord == 'y' and 0 <= y + shift <= 9 and field[y + shift][x].number not in (2, 3):
neighbours.append((x, y + shift, direction, pg.K_w))
return neighbours
def successor(field: List[List[Tile]], x: int, y: int, direction: int): def successor(field: List[List[Tile]], x: int, y: int, direction: int):
@ -36,3 +58,37 @@ def get_path_actions(node: Node):
actions.append(node.action) actions.append(node.action)
node = node.parent node = node.parent
return path[::-1], actions[::-1] return path[::-1], actions[::-1]
def successor_priority(field: List[List[Tile]], x: int, y: int, direction: int):
"""
kody klawiszy:
:a -> 97
:d -> 100
:w -> 119
"""
neighbours = []
coord = 'x' if direction in (1, 3) else 'y'
shift = -1 if direction in (0, 3) else 1
neighbours.append((x, y, (direction - 1) % 4, pg.K_a))
neighbours.append((x, y, (direction + 1) % 4, pg.K_d))
if coord == 'x' and 0 <= x + shift <= 9 and field[y][x + shift].number not in (2, 3):
neighbours.append((x + shift, y, direction, pg.K_w))
elif coord == 'y' and 0 <= y + shift <= 9 and field[y + shift][x].number not in (2, 3):
neighbours.append((x, y + shift, direction, pg.K_w))
return neighbours
def cost(field: List[List[Tile]], node):
return field[node.x][node.y].weight
def calculate_priority(field: List[List[Tile]], node, goaltest: Tuple[int, int]):
return cost(field, node) + heuristic(node, goaltest)
def heuristic(a, b):
return abs(a.x - b[0]) + abs(a.y - b[1])

View File

@ -5,6 +5,7 @@ from at_mine import ATMine
class Tile: class Tile:
def __init__(self, number: int, mine: Union[None, APMine, ATMine] = None): def __init__(self, number: int,weight: int, mine: Union[None, APMine, ATMine] = None):
self.number = number self.number = number
self.mine = mine self.mine = mine
self.weight = 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, getattr(module, f'{img.mine_type}Mine')) return Tile(number, 1, getattr(module, f'{img.mine_type}Mine'))
else: else:
return Tile(number, None) return Tile(number, 1, None) if img.name.find('grass') else Tile(number,3, None)
def get_tiles_list(self) -> List[Tile]: def get_tiles_list(self) -> List[Tile]:
return [self.create_tile(i) for i in range(11)] return [self.create_tile(i) for i in range(13)]