improving a_star algorithm
This commit is contained in:
parent
b46ebc9b3e
commit
7e61c61116
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 |
@ -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"
|
||||
),
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
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)
|
@ -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])
|
||||
|
@ -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
|
||||
|
@ -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)]
|
||||
|
Loading…
Reference in New Issue
Block a user