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_mineAP_02': 1,
'grass_02_mineAP_03': 1,
'mud_01':0,
'mud_02':1
}.items():
IMAGES.append(
Image(
val,
name,
pg.image.load(
main_path + '/images/Tiles/' + name + ".png"
),

View File

@ -8,7 +8,7 @@ from tilesFactory import TilesFactory
def generate_field() -> List[List[Tile]]:
tiles_factory = TilesFactory()
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:

View File

@ -1,10 +1,12 @@
import string
from typing import Union
from pygame import 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.img = img
self.mine_type = mine_type
self.name = name

View File

@ -1,3 +1,5 @@
from typing import Tuple
import pygame as pg
from agent import Agent
@ -5,6 +7,7 @@ from game_ui import GameUi
from const import ICON, IMAGES
from environment import Environment
from search_algoritms.BFS import breadth_first_search
from src.search_algoritms.a_star import a_star, nearest_bomb
from tilesFactory import TilesFactory
@ -64,6 +67,8 @@ def main():
while env.mine_count:
print('-'*20)
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:
print('Unable to find path, rocks are in the way')
break

View File

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

View File

@ -1,14 +1,15 @@
from typing import List, Tuple
from operator import itemgetter
from node import Node
from tile import Tile
from .helpers import successor, get_path_actions
from src.node import Node
from src.tile import Tile
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]):
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)
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)
for x, y, direction, action in successor(field, node.x, node.y, node.direction):
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):
node_queue.append((neighbour_priority, neighbour_node))
node_queue = sorted(node_queue, key=itemgetter(0))
elif (index := [
index for index, queue_tuple in enumerate(node_queue) if neighbour_priority > queue_tuple[0]
][0]):
node_queue[index] = (neighbour_priority, neighbour_node)
index for index, queue_tuple in enumerate(node_queue) if neighbour_priority > queue_tuple[0] and neighbour_node == queue_tuple[1]
]):
print(index)
node_queue[index[0]] = (neighbour_priority, neighbour_node)
node_queue = sorted(node_queue, key=itemgetter(0))
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
from tile import Tile
from node import Node
from src.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):
@ -36,3 +58,37 @@ def get_path_actions(node: Node):
actions.append(node.action)
node = node.parent
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:
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.mine = mine
self.weight = weight

View File

@ -10,9 +10,9 @@ class TilesFactory:
img = IMAGES[number]
if img.mine_type:
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:
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]:
return [self.create_tile(i) for i in range(11)]
return [self.create_tile(i) for i in range(13)]