Implementacja przeszukiwania stanów przez BFS
This commit is contained in:
parent
ffa6f97771
commit
75e597b3c6
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
__pycache__/enclosure.cpython-311.pyc
Normal file
BIN
__pycache__/enclosure.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
__pycache__/spawner.cpython-311.pyc
Normal file
BIN
__pycache__/spawner.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/state_space_search.cpython-311.pyc
Normal file
BIN
__pycache__/state_space_search.cpython-311.pyc
Normal file
Binary file not shown.
64
agent.py
64
agent.py
@ -1,34 +1,62 @@
|
|||||||
import pygame
|
import pygame
|
||||||
|
from state_space_search import is_border, is_obstacle
|
||||||
|
|
||||||
class Agent:
|
class Agent:
|
||||||
def __init__(self, x, y, image_path, grid_size):
|
def __init__(self, istate, image_path, grid_size):
|
||||||
self.x = x
|
self.istate = istate
|
||||||
self.y = y
|
self.x, self.y, self.direction = istate
|
||||||
self.grid_size = grid_size
|
self.grid_size = grid_size
|
||||||
self.image = pygame.image.load(image_path)
|
self.image_original = pygame.image.load(image_path)
|
||||||
self.image = pygame.transform.scale(self.image, (grid_size, grid_size))
|
self.image_original = pygame.transform.scale(self.image_original, (grid_size, grid_size))
|
||||||
|
self.image = self.image_original
|
||||||
|
|
||||||
|
|
||||||
def draw(self, screen):
|
def draw(self, screen):
|
||||||
|
# Obróć obrazek zgodnie z kierunkiem
|
||||||
|
if self.direction == 'E':
|
||||||
|
self.image = pygame.transform.rotate(self.image_original, -90)
|
||||||
|
elif self.direction == 'S':
|
||||||
|
self.image = pygame.transform.rotate(self.image_original, 180)
|
||||||
|
elif self.direction == 'W':
|
||||||
|
self.image = pygame.transform.rotate(self.image_original, 90)
|
||||||
|
else: # direction == 'N'
|
||||||
|
self.image = self.image_original
|
||||||
|
|
||||||
screen.blit(self.image, (self.x * self.grid_size, self.y * self.grid_size))
|
screen.blit(self.image, (self.x * self.grid_size, self.y * self.grid_size))
|
||||||
|
|
||||||
def move(self, dx, dy):
|
def handle_event(self, event, max_x, max_y, animals, obstacles):
|
||||||
self.x += dx
|
|
||||||
self.y += dy
|
|
||||||
|
|
||||||
def handle_event(self, event, grid_height,grid_width, animals, blocked_fields):
|
|
||||||
if event.type == pygame.KEYDOWN:
|
if event.type == pygame.KEYDOWN:
|
||||||
if event.key == pygame.K_UP and self.y > 0 and (self.x, self.y-1) not in blocked_fields:
|
if event.key == pygame.K_UP:
|
||||||
self.move(0, -1)
|
self.move('Go Forward', max_x, max_y, obstacles)
|
||||||
elif event.key == pygame.K_DOWN and self.y < grid_height - 1 and (self.x, self.y+1) not in blocked_fields:
|
elif event.key == pygame.K_LEFT:
|
||||||
self.move(0, 1)
|
self.move('Turn Left', max_x, max_y, obstacles)
|
||||||
elif event.key == pygame.K_LEFT and self.x > 0 and (self.x-1, self.y) not in blocked_fields:
|
elif event.key == pygame.K_RIGHT:
|
||||||
self.move(-1, 0)
|
self.move('Turn Right', max_x, max_y, obstacles)
|
||||||
elif event.key == pygame.K_RIGHT and self.x < grid_width - 1 and (self.x+1, self.y) not in blocked_fields:
|
|
||||||
self.move(1, 0)
|
|
||||||
|
|
||||||
for animal in animals:
|
for animal in animals:
|
||||||
if self.x == animal.x and self.y == animal.y:
|
if self.x == animal.x and self.y == animal.y:
|
||||||
if animal.feed() == 'True':
|
if animal.feed() == 'True':
|
||||||
animal._feed = 0
|
animal._feed = 0
|
||||||
print(animal.name, "fed with", animal.food)
|
print(animal.name, "fed with", animal.food)
|
||||||
|
|
||||||
|
def move(self, action, max_x, max_y, obstacles):
|
||||||
|
if action == 'Go Forward':
|
||||||
|
new_x, new_y = self.x, self.y
|
||||||
|
if self.direction == 'N':
|
||||||
|
new_y -= 1
|
||||||
|
elif self.direction == 'E':
|
||||||
|
new_x += 1
|
||||||
|
elif self.direction == 'S':
|
||||||
|
new_y += 1
|
||||||
|
elif self.direction == 'W':
|
||||||
|
new_x -= 1
|
||||||
|
|
||||||
|
# Sprawdź, czy nowe położenie mieści się w granicach kraty i nie jest przeszkodą
|
||||||
|
if is_border(new_x, new_y, max_x, max_y) and not(is_obstacle(new_x, new_y, obstacles)):
|
||||||
|
self.x, self.y = new_x, new_y
|
||||||
|
|
||||||
|
elif action == 'Turn Left':
|
||||||
|
self.direction = {'N': 'W', 'W': 'S', 'S': 'E', 'E': 'N'}[self.direction]
|
||||||
|
|
||||||
|
elif action == 'Turn Right':
|
||||||
|
self.direction = {'N': 'E', 'E': 'S', 'S': 'W', 'W': 'N'}[self.direction]
|
@ -1,6 +1,7 @@
|
|||||||
import pygame
|
import pygame
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
class Animal:
|
class Animal:
|
||||||
def __init__(self, x, y,name, image, food_image, food, environment, adult=False,):
|
def __init__(self, x, y,name, image, food_image, food, environment, adult=False,):
|
||||||
self.x = x - 1
|
self.x = x - 1
|
||||||
|
BIN
images/agent.png
Normal file
BIN
images/agent.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 133 KiB |
BIN
images/avatar_old.png
Normal file
BIN
images/avatar_old.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 248 KiB |
92
main.py
92
main.py
@ -8,6 +8,8 @@ from bear import Bear
|
|||||||
from agent import Agent
|
from agent import Agent
|
||||||
from enclosure import Enclosure
|
from enclosure import Enclosure
|
||||||
from spawner import Spawner
|
from spawner import Spawner
|
||||||
|
from state_space_search import succ
|
||||||
|
from state_space_search import graphsearch
|
||||||
|
|
||||||
BLACK = (0, 0, 0)
|
BLACK = (0, 0, 0)
|
||||||
|
|
||||||
@ -44,10 +46,11 @@ an4 = Elephant(4,3)
|
|||||||
|
|
||||||
Animals = [an1, an2, an3, an4, old_an1, old_an2]
|
Animals = [an1, an2, an3, an4, old_an1, old_an2]
|
||||||
|
|
||||||
|
# Enclosure (lewy_górny_x, lewy_górny_y, prawy_dolny_x, prawy_dolny_y, brama, klimat, fenceH, fenceV, gate_obrazek)
|
||||||
en1 = Enclosure(1,5, 9,11, (9,6),"medium", fenceH, fenceV, gate)
|
en1 = Enclosure(1,5, 9,11, (9,6),"medium", fenceH, fenceV, gate)
|
||||||
en2 = Enclosure(29,3, 13,1,(16,3), 'medium', fenceH, fenceV, gate)
|
en2 = Enclosure(13,1, 29,3, (16,3), 'medium', fenceH, fenceV, gate)
|
||||||
en3 = Enclosure(11,5, 16,11, (12,5),'cold', fenceH, fenceV, gate)
|
en3 = Enclosure(11,5, 16,11, (12,5),'cold', fenceH, fenceV, gate)
|
||||||
en4 = Enclosure(19,11, 30,5, (25,5),'hot', fenceH, fenceV, gate)
|
en4 = Enclosure(19,5, 30,11, (25,5),'hot', fenceH, fenceV, gate)
|
||||||
en5 = Enclosure(4,13, 28,15, (16,13),'cold', fenceH, fenceV, gate)
|
en5 = Enclosure(4,13, 28,15, (16,13),'cold', fenceH, fenceV, gate)
|
||||||
|
|
||||||
|
|
||||||
@ -85,18 +88,89 @@ def spawn_all_animals():
|
|||||||
spawner1 = Spawner(Animal, Enclosures)
|
spawner1 = Spawner(Animal, Enclosures)
|
||||||
spawner1.spawn_animal(fences, animals_position)
|
spawner1.spawn_animal(fences, animals_position)
|
||||||
|
|
||||||
|
def generate_obstacles():
|
||||||
|
obstacles = []
|
||||||
|
|
||||||
|
for en in Enclosures:
|
||||||
|
# Pobierz współrzędne bramy
|
||||||
|
gate_x, gate_y = en.gate
|
||||||
|
gate_x -= 1
|
||||||
|
gate_y -= 1
|
||||||
|
|
||||||
|
# Dodaj lewy brzeg prostokąta
|
||||||
|
for y in range(en.y1, en.y2 + 1):
|
||||||
|
if (en.x1, y) != (gate_x, gate_y):
|
||||||
|
obstacles.append((en.x1, y))
|
||||||
|
|
||||||
|
# Dodaj prawy brzeg prostokąta
|
||||||
|
for y in range(en.y1, en.y2 + 1):
|
||||||
|
if (en.x2, y) != (gate_x, gate_y):
|
||||||
|
obstacles.append((en.x2, y))
|
||||||
|
|
||||||
|
# Dodaj górny brzeg prostokąta
|
||||||
|
for x in range(en.x1+1, en.x2):
|
||||||
|
if (x, en.y1) != (gate_x, gate_y):
|
||||||
|
obstacles.append((x, en.y1))
|
||||||
|
|
||||||
|
# Dodaj dolny brzeg prostokąta
|
||||||
|
for x in range(en.x1+1, en.x2):
|
||||||
|
if (x, en.y2) != (gate_x, gate_y):
|
||||||
|
obstacles.append((x, en.y2))
|
||||||
|
|
||||||
|
return obstacles
|
||||||
|
|
||||||
|
# region Obstacles Tests
|
||||||
|
# WHITE = (255,255,255)
|
||||||
|
# TRANSPARENT_BLACK = (0, 0, 0, 128) # Półprzezroczysty czarny
|
||||||
|
# def draw_obstacles(obstacles):
|
||||||
|
# for obstacle in obstacles:
|
||||||
|
# x, y = obstacle
|
||||||
|
# pygame.draw.rect(screen, TRANSPARENT_BLACK, (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE))
|
||||||
|
|
||||||
|
# def main():
|
||||||
|
# obstacles = generate_obstacles() # Załóżmy, że masz funkcję generate_obstacles, która generuje listę przeszkód
|
||||||
|
|
||||||
|
# # Pętla główna
|
||||||
|
# running = True
|
||||||
|
# while running:
|
||||||
|
# # Obsługa zdarzeń
|
||||||
|
# for event in pygame.event.get():
|
||||||
|
# if event.type == pygame.QUIT:
|
||||||
|
# running = False
|
||||||
|
|
||||||
|
# # Czyszczenie ekranu
|
||||||
|
# screen.fill(WHITE)
|
||||||
|
|
||||||
|
# # Rysowanie przeszkód
|
||||||
|
# draw_obstacles(obstacles)
|
||||||
|
|
||||||
|
# # Odświeżenie ekranu
|
||||||
|
# pygame.display.flip()
|
||||||
|
|
||||||
|
# # Wyjście z Pygame
|
||||||
|
# pygame.quit()
|
||||||
|
|
||||||
|
# endregion
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
agent = Agent(0, 0, 'images/avatar.png', GRID_SIZE)
|
initial_state = (1,1,'W')
|
||||||
|
agent = Agent(initial_state, 'images/agent.png', GRID_SIZE)
|
||||||
|
|
||||||
|
obstacles = generate_obstacles()
|
||||||
|
|
||||||
|
actions = []
|
||||||
|
spawn_all_animals()
|
||||||
|
actions = graphsearch(agent.istate, (an1.x, an1.y), GRID_WIDTH, GRID_HEIGHT, obstacles)
|
||||||
|
# actions = graphsearch(agent.istate, (25,1), GRID_WIDTH, GRID_HEIGHT, obstacles)
|
||||||
|
|
||||||
clock = pygame.time.Clock()
|
clock = pygame.time.Clock()
|
||||||
spawned = False
|
|
||||||
while True:
|
while True:
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
agent.handle_event(event, GRID_HEIGHT, GRID_WIDTH, Animals, fences)
|
agent.handle_event(event, GRID_WIDTH, GRID_HEIGHT, Animals, obstacles)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -104,14 +178,16 @@ def main():
|
|||||||
draw_grid()
|
draw_grid()
|
||||||
draw_enclosures()
|
draw_enclosures()
|
||||||
draw_gates()
|
draw_gates()
|
||||||
if not spawned:
|
|
||||||
spawn_all_animals()
|
|
||||||
spawned = True
|
|
||||||
draw_Animals()
|
draw_Animals()
|
||||||
opengates()
|
opengates()
|
||||||
agent.draw(screen)
|
agent.draw(screen)
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
clock.tick(10)
|
clock.tick(10)
|
||||||
|
|
||||||
|
if actions:
|
||||||
|
action = actions.pop(0)
|
||||||
|
agent.move(action, GRID_WIDTH, GRID_HEIGHT, obstacles)
|
||||||
|
pygame.time.wait(200)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
60
state_space_search.py
Normal file
60
state_space_search.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
def is_border(x, y, max_x, max_y):
|
||||||
|
return 0 <= x < max_x and 0 <= y < max_y
|
||||||
|
|
||||||
|
def is_obstacle(x, y, obstacles):
|
||||||
|
return (x, y) in obstacles
|
||||||
|
|
||||||
|
def succ(current_state, max_x, max_y, obstacles):
|
||||||
|
successors = []
|
||||||
|
x, y, direction = current_state
|
||||||
|
|
||||||
|
# Akcja: Do przodu
|
||||||
|
direction_x, direction_y = {'N': (0, -1), 'E': (1, 0), 'S': (0, 1), 'W': (-1, 0)}[direction] # Słownik przesunięć w zależności od kierunku
|
||||||
|
new_x, new_y = x + direction_x, y + direction_y
|
||||||
|
|
||||||
|
if is_border(new_x, new_y, max_x, max_y) and not(is_obstacle(new_x, new_y, obstacles)):
|
||||||
|
successors.append(((new_x, new_y, direction), 'Go Forward'))
|
||||||
|
|
||||||
|
# Akcja: Obrót w lewo
|
||||||
|
left_turns = {'N': 'W', 'W': 'S', 'S': 'E', 'E': 'N'} # Słownik kierunków po obrocie w lewo
|
||||||
|
successors.append(((x, y, left_turns[direction]), 'Turn Left'))
|
||||||
|
|
||||||
|
# Akcja: Obrót w prawo
|
||||||
|
right_turns = {'N': 'E', 'E': 'S', 'S': 'W', 'W': 'N'} # Słownik kierunków po obrocie w prawo
|
||||||
|
successors.append(((x, y, right_turns[direction]), 'Turn Right'))
|
||||||
|
|
||||||
|
return successors
|
||||||
|
|
||||||
|
def graphsearch(istate, goal, max_x, max_y, obstacles):
|
||||||
|
fringe = [{"state": istate, "parent": None, "action": None}]
|
||||||
|
explored = set()
|
||||||
|
|
||||||
|
while fringe:
|
||||||
|
elem = fringe.pop(0)
|
||||||
|
state = elem["state"]
|
||||||
|
|
||||||
|
if goaltest(state, goal):
|
||||||
|
return build_action_sequence(elem)
|
||||||
|
|
||||||
|
explored.add(state)
|
||||||
|
|
||||||
|
successors = succ(state, max_x, max_y, obstacles)
|
||||||
|
|
||||||
|
for new_state, action in successors:
|
||||||
|
if new_state not in fringe and new_state not in explored:
|
||||||
|
fringe.append({"state": new_state, "parent": elem, "action": action})
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def build_action_sequence(node):
|
||||||
|
actions = []
|
||||||
|
while node["parent"]:
|
||||||
|
actions.append(node["action"])
|
||||||
|
node = node["parent"]
|
||||||
|
actions.reverse()
|
||||||
|
return actions
|
||||||
|
|
||||||
|
def goaltest(state, goal):
|
||||||
|
x, y, _ = state
|
||||||
|
goal_x, goal_y = goal
|
||||||
|
return (x,y) == (goal_x, goal_y)
|
Loading…
Reference in New Issue
Block a user