Add A* integration with world, tile cost and get_tile_cost func

This commit is contained in:
Adam Szpilkowski 2022-05-16 18:59:54 +02:00
parent 0ecf105330
commit 1d45722aa5
4 changed files with 53 additions and 51 deletions

56
main.py
View File

@ -24,7 +24,7 @@ def main():
goals = [(3, 3), (7, 7), (0, 0)]
end_cords = goals[0]
start_dir = tractor.curr_direction
path = BFSSearcher().search(start_cords, end_cords, start_dir)
# path = BFSSearcher().search(start_cords, end_cords, start_dir)
run = True
while run:
@ -33,21 +33,26 @@ def main():
world.draw_lines(screen)
tractor.draw(screen)
# print(path)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if path:
action = path.pop(0)
tractor.update(action)
else:
if len(goals) > 1:
start_cord = goals.pop(0)
end_cords = goals[0]
start_dir = tractor.curr_direction
path = BFSSearcher().search(start_cord, end_cords, start_dir)
# if path:
# action = path.pop(0)
# tractor.update(action)
# else:
# if len(goals) > 1:
# start_cord = goals.pop(0)
# end_cords = goals[0]
# start_dir = tractor.curr_direction
# path = BFSSearcher().search(start_cord, end_cords, start_dir)
while goals:
goal = goals.pop(0)
path = a_star(world, start_cords, goal)
start_cords = goal
print(path)
pygame.time.wait(settings.freeze_time)
pygame.display.update()
@ -55,29 +60,4 @@ def main():
if __name__ == '__main__':
# inicjalizacja array z zerami
rows = 10
cols = 10
field = np.zeros((rows, cols), dtype=int)
# tworzenie ścian w array
for i in range(0, 9):
field[1, i] = 1
field[2, 8] = 1
field[3, 8] = 1
field[3, 7] = 1
field[3, 6] = 1
print(field)
start = (0, 0)
goals = [(2, 7)]
while goals:
goal = goals.pop(0)
path = a_star(field, start, goal)
print(path)
# main()
main()

View File

@ -4,7 +4,7 @@ from pygame.sprite import Sprite
class Tile(Sprite):
""" Class to represent single board tile """
def __init__(self, type, row_id, col_id, image, rect):
def __init__(self, type, row_id, col_id, image, rect, cost):
super().__init__()
self.type = type
self.row_id = row_id
@ -12,6 +12,7 @@ class Tile(Sprite):
self.position = (row_id, col_id)
self.image = image
self.rect = rect
self.cost = cost
self.plant = None
self.hydration = 0
self.fertilizer = None

View File

@ -1,3 +1,5 @@
import world
class Node:
def __init__(self, x, y): # inicjalizacja węzła
self.x = x
@ -8,31 +10,30 @@ class Node:
self.f_cost = 0
self.h_cost = 0
def create_neighbours(self,
world_map): # tworzenie sąsiadów i sprawdzanie czy nie wykraczają poza macierz i czy nie są przeszkodą
if self.x - 1 >= 0 and world_map[self.x - 1, self.y] != 1:
def create_neighbours(self, field: world): # tworzenie sąsiadów i sprawdzanie czy nie wykraczają poza macierz i czy nie są przeszkodą
if self.x - 1 >= 0 and field.world_data[self.x - 1][self.y] != 0:
self.neighbours.append([self.x - 1, self.y])
if self.x + 1 < world_map.shape[0] and world_map[self.x + 1, self.y] != 1:
if self.x + 1 < len(field.world_data) and field.world_data[self.x + 1][self.y] != 0:
self.neighbours.append([self.x + 1, self.y])
if self.y + 1 < world_map.shape[1] and world_map[self.x, self.y + 1] != 1:
if self.y + 1 < len(field.world_data[0]) and field.world_data[self.x][self.y + 1] != 0:
self.neighbours.append([self.x, self.y + 1])
if self.y - 1 >= 0 and world_map[self.x, self.y - 1] != 1:
if self.y - 1 >= 0 and field.world_data[self.x][self.y - 1] != 0:
self.neighbours.append([self.x, self.y - 1])
def calculate_h_cost(self, goal):
self.h_cost = abs(self.x - goal.x) + abs(self.y - goal.y)
def a_star(world_map, start, goal): # algorytm zwraca ścieżkę którą ma przebyć agent
def a_star(field: world, start, goal): # algorytm zwraca ścieżkę którą ma przebyć agent
# tworzenie dictionary składającego się z nodeów
node_dict = {}
for i in range(len(world_map)):
for j in range(len(world_map[0])):
for i in range(len(field.world_data)):
for j in range(len(field.world_data[0])):
node_dict[i, j] = Node(i, j)
# przypisanie startu i celu do zmiennej
@ -57,7 +58,7 @@ def a_star(world_map, start, goal): # algorytm zwraca ścieżkę którą ma prz
closed_list.append(current)
# stworzenie listy z możliwymi opcjami
current.create_neighbours(world_map)
current.create_neighbours(field)
# sprawdzenie celu
if current == goal:
@ -91,3 +92,16 @@ def a_star(world_map, start, goal): # algorytm zwraca ścieżkę którą ma prz
path.reverse()
return path
# def path_to_action(path: list): # funkcja zmieniająca ścieżkę nodeów na instrukcję dla agenta
# vector_list = []
# action_list = []
#
# # tmp_direction = agent_direction
# # iteracja przez wszystkie pary elementów żeby obliczyć wektory ruchu
# for i in range(len(path) - 1):
# tmp_vector = [(path[i+1][0] - path[i][0]), (path[i+1][1] - path[i][1])]
# vector_list.append(tmp_vector)
#
# return vector_list

View File

@ -30,13 +30,15 @@ class World:
if tile == 1:
img = pygame.transform.scale(self.dirt_image, (self.settings.tile_size, self.settings.tile_size))
type = 'dirt'
cost = 0
elif tile == 0:
img = pygame.transform.scale(self.rock_image, (self.settings.tile_size, self.settings.tile_size))
type = 'rock'
cost = 100
img_rect = img.get_rect()
img_rect.x = col_count * self.settings.tile_size
img_rect.y = row_count * self.settings.tile_size
tile = Tile(type, row_count, col_count, img, img_rect)
tile = Tile(type, len(self.world_data) - row_count - 1, col_count, img, img_rect, cost)
self.tiles.add(tile)
col_count += 1
row_count += 1
@ -49,4 +51,9 @@ class World:
pygame.draw.line(screen, (255, 255, 255), (0, line * self.settings.tile_size),
(self.settings.screen_width, line * self.settings.tile_size))
pygame.draw.line(screen, (255, 255, 255), (line * self.settings.tile_size, 0),
(line * self.settings.tile_size, self.settings.screen_height))
(line * self.settings.tile_size, self.settings.screen_height))
def get_tile_cost(self, x, y):
for tile in self.tiles:
if tile.position == (x, y):
return tile.cost