Uprzątnięcie i przeorganizowanie kodu na oddzielne pliki

This commit is contained in:
s481832 2024-05-08 11:54:49 +02:00
parent 088956ccb8
commit b18e1e9eeb
16 changed files with 141 additions and 252 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"python.analysis.extraPaths": [
"./Animals"
]
}

View File

@ -1,5 +1,5 @@
import pygame import pygame
from abc import ABC, abstractmethod from abc import 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,):

View File

@ -37,3 +37,11 @@ def create_animals():
parrot1, parrot2, parrot3, parrot4, parrot5] parrot1, parrot2, parrot3, parrot4, parrot5]
return Animals return Animals
def draw_Animals(Animals, const):
for Animal in Animals:
Animal.draw(const.screen, const.GRID_SIZE)
if Animal.feed() == 'True':
Animal.draw_exclamation(const.screen, const.GRID_SIZE, Animal.x, Animal.y)
else:
Animal.draw_food(const.screen,const.GRID_SIZE,Animal.x,Animal.y)

View File

@ -2,8 +2,6 @@ from animal import Animal
import pygame import pygame
from datetime import datetime from datetime import datetime
class Bear(Animal): class Bear(Animal):
def __init__(self, x, y, adult=False): def __init__(self, x, y, adult=False):
Bear_image = pygame.image.load('images/bear.png') Bear_image = pygame.image.load('images/bear.png')

View File

@ -31,8 +31,6 @@ class Agent:
elif event.key == pygame.K_RIGHT: elif event.key == pygame.K_RIGHT:
self.move('Turn Right', max_x, max_y, obstacles, animals) self.move('Turn Right', max_x, max_y, obstacles, animals)
# feed_animal(self, animals)
def move(self, action, max_x, max_y, obstacles, animals, goal): def move(self, action, max_x, max_y, obstacles, animals, goal):
if action == 'Go Forward': if action == 'Go Forward':
new_x, new_y = self.x, self.y new_x, new_y = self.x, self.y

15
constants.py Normal file
View File

@ -0,0 +1,15 @@
import pygame
class Constants:
def __init__(self):
self.BLACK = (0, 0, 0)
self.RED = (255, 0, 0)
self.GRID_SIZE = 50
self.GRID_WIDTH = 30
self.GRID_HEIGHT = 15
self.WINDOW_SIZE = (self.GRID_WIDTH * self.GRID_SIZE, self.GRID_HEIGHT * self.GRID_SIZE)
self.background_image = pygame.transform.scale(pygame.image.load('images/tło.jpg'), self.WINDOW_SIZE)
def init_pygame(const):
pygame.init()
const.screen = pygame.display.set_mode(const.WINDOW_SIZE)

14
draw.py Normal file
View File

@ -0,0 +1,14 @@
import pygame
def draw_goal(const, goal):
x, y = goal
rect = (x * const.GRID_SIZE, y * const.GRID_SIZE, const.GRID_SIZE, const.GRID_SIZE)
pygame.draw.rect(const.screen, const.RED, rect)
pygame.display.flip()
pygame.time.delay(2000)
def draw_grid(const):
for y in range(0, const.GRID_HEIGHT * const.GRID_SIZE, const.GRID_SIZE):
for x in range(0, const.GRID_WIDTH * const.GRID_SIZE, const.GRID_SIZE):
rect = pygame.Rect(x, y, const.GRID_SIZE, const.GRID_SIZE)
pygame.draw.rect(const.screen, const.BLACK, rect, 1)

View File

@ -50,7 +50,6 @@ class Enclosure:
if (self.x2, j) != (gate_x1, gate_y1) and (self.x2, j) != (gate_x2, gate_y2): if (self.x2, j) != (gate_x1, gate_y1) and (self.x2, j) != (gate_x2, gate_y2):
screen.blit(self.imageV, (self.x2 * grid_size, j * grid_size)) screen.blit(self.imageV, (self.x2 * grid_size, j * grid_size))
def create_enclosures(): def create_enclosures():
fenceH = pygame.image.load('images/fenceHor.png') fenceH = pygame.image.load('images/fenceHor.png')
fenceV = pygame.image.load('images/fenceVer.png') fenceV = pygame.image.load('images/fenceVer.png')
@ -65,3 +64,11 @@ def create_enclosures():
Enclosures = [en1, en2, en3, en4, en5] Enclosures = [en1, en2, en3, en4, en5]
return Enclosures return Enclosures
def draw_enclosures(Enclosures, const):
for enclosure in Enclosures:
enclosure.draw(const.screen, const.GRID_SIZE)
def draw_gates(Enclosures, const):
for enclosure in Enclosures:
enclosure.gatebuild(const.screen, const.GRID_SIZE)

267
main.py
View File

@ -1,97 +1,40 @@
from enum import Enum
import random import random
import pygame import pygame
import sys import sys
from animals import create_animals import sys
sys.path.append('./Animals')
from animals import create_animals, draw_Animals
from agent import Agent from agent import Agent
from enclosure import Enclosure, create_enclosures from enclosure import create_enclosures, draw_enclosures, draw_gates
from spawner import Spawner from spawner import Spawner
from state_space_search import graphsearch from state_space_search import graphsearch, generate_cost_map
from terrain_obstacle import Terrain_Obstacle from terrain_obstacle import create_obstacles, draw_Terrain_Obstacles
from constants import Constants, init_pygame
from draw import draw_goal, draw_grid
BLACK = (0, 0, 0) const = Constants()
RED = (255, 0, 0) init_pygame(const)
GRID_SIZE = 50
GRID_WIDTH = 30
GRID_HEIGHT = 15
pygame.init()
WINDOW_SIZE = (GRID_WIDTH * GRID_SIZE, GRID_HEIGHT * GRID_SIZE)
screen = pygame.display.set_mode(WINDOW_SIZE)
pygame.display.set_caption("Mini Zoo") pygame.display.set_caption("Mini Zoo")
background_image = pygame.image.load('images/tło.jpg')
background_image = pygame.transform.scale(background_image, WINDOW_SIZE)
fenceH = pygame.image.load('images/fenceHor.png')
fenceV = pygame.image.load('images/fenceVer.png')
gate = pygame.image.load('images/gate.png')
puddle_image = pygame.image.load('images/puddle.png')
bush_image = pygame.image.load('images/bush.png')
obstacles = set() obstacles = set()
animals_position = set() animals_position = set()
terrain_obstacles_position = set() terrain_obstacles_position = set()
Animals = create_animals() Animals = create_animals()
Enclosures = create_enclosures() Enclosures = create_enclosures()
Terrain_Obstacles = create_obstacles()
puddle1 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle2 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle3 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle4 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle5 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle6 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle7 = Terrain_Obstacle(0,0,'puddle', puddle_image)
bush1 = Terrain_Obstacle(0,0,'bush', bush_image)
bush2 = Terrain_Obstacle(0,0,'bush', bush_image)
bush3 = Terrain_Obstacle(0,0,'bush', bush_image)
bush4 = Terrain_Obstacle(0,0,'bush', bush_image)
bush5 = Terrain_Obstacle(0,0,'bush', bush_image)
Terrain_Obstacles = [puddle1, puddle2, puddle3, puddle4, puddle5, puddle6, puddle7, bush1, bush2, bush3, bush4, bush5]
def draw_grid():
for y in range(0, GRID_HEIGHT * GRID_SIZE, GRID_SIZE):
for x in range(0, GRID_WIDTH * GRID_SIZE, GRID_SIZE):
rect = pygame.Rect(x, y, GRID_SIZE, GRID_SIZE)
pygame.draw.rect(screen, BLACK, rect, 1)
def draw_enclosures():
for enclosure in Enclosures:
enclosure.draw(screen, GRID_SIZE)
def draw_gates():
for enclosure in Enclosures:
enclosure.gatebuild(screen, GRID_SIZE)
def draw_Animals():
for Animal in Animals:
Animal.draw(screen, GRID_SIZE)
if Animal.feed() == 'True':
Animal.draw_exclamation(screen, GRID_SIZE, Animal.x, Animal.y)
else:
Animal.draw_food(screen,GRID_SIZE,Animal.x,Animal.y)
def spawn_all_animals(): def spawn_all_animals():
for Animal in Animals: for Animal in Animals:
spawner1 = Spawner(Animal) spawner1 = Spawner(Animal)
spawner1.spawn_animal(obstacles, animals_position, Enclosures) spawner1.spawn_animal(obstacles, animals_position, Enclosures)
def draw_Terrain_Obstacles():
for terrain_obstacle in Terrain_Obstacles:
terrain_obstacle.draw(screen, GRID_SIZE)
def spawn_obstacles(): def spawn_obstacles():
for terrain_obstacle in Terrain_Obstacles: for terrain_obstacle in Terrain_Obstacles:
spawner2= Spawner(terrain_obstacle) spawner2 = Spawner(terrain_obstacle)
spawner2.spawn_terrain_obstacles(obstacles,animals_position, terrain_obstacles_position, GRID_WIDTH, GRID_HEIGHT) spawner2.spawn_terrain_obstacles(obstacles, animals_position, terrain_obstacles_position, const.GRID_WIDTH, const.GRID_HEIGHT)
obstacles = set()
def generate_obstacles(): def generate_obstacles():
for en in Enclosures: for en in Enclosures:
# Pobierz współrzędne bramy # Pobierz współrzędne bramy
gate_x, gate_y = en.gate1 gate_x, gate_y = en.gate1
@ -124,196 +67,50 @@ def generate_obstacles():
return obstacles return obstacles
cost_map = {}
def generate_cost_map():
adult_animal_cost = 10
baby_animal_cost = 5
puddle_cost = 50
bush_cost = 20
wall_cost = 1000
for animal in Animals:
if animal.adult:
cost_map[(animal.x + 1, animal.y + 1)] = baby_animal_cost
cost_map[(animal.x + 1, animal.y)] = baby_animal_cost
cost_map[(animal.x, animal.y + 1)] = baby_animal_cost
cost_map[(animal.x, animal.y)] = adult_animal_cost
else:
cost_map[(animal.x, animal.y)] = baby_animal_cost
for terrain_obstacle in Terrain_Obstacles:
if terrain_obstacle.type == 'puddle':
cost_map[(terrain_obstacle.x , terrain_obstacle.y )] = puddle_cost
else:
cost_map[(terrain_obstacle.x , terrain_obstacle.y )] = bush_cost
for wall in Walls:
cost_map[wall[0], wall[1]] = wall_cost
# Inne pola z różnym kosztem
# cost_map[(x, y)] = cost_value
# region Fields Tests
available_fields_small = set()
available_fields_large = set()
WHITE = (255,255,255)
GREEN = (0, 255, 0)
YELLOW = (255, 255, 0)
BLACK = (0, 0, 0)
def generate_available_fields():
for enclosure in Enclosures:
for x in range(enclosure.x1 + 1, enclosure.x2):
for y in range(enclosure.y1 + 1, enclosure.y2):
field = (x, y)
if field not in obstacles:
available_fields_small.add(field)
if x < enclosure.x2 - 1 and y < enclosure.y2 - 1:
available_fields_large.add(field)
def draw_fields(fields, color):
for field in fields:
x, y = field
pygame.draw.rect(screen, color, (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE))
def available_fields_tests():
obstacles = generate_obstacles()
while True:
screen.fill(WHITE)
draw_grid()
draw_fields(obstacles, BLACK)
generate_available_fields()
draw_fields(available_fields_small, GREEN)
draw_fields(available_fields_large, YELLOW)
# Odświeżenie ekranu
pygame.display.flip()
# endregion
# region Main Code
def main(): def main():
initial_state = (0,0,'S') initial_state = (0, 0, 'S')
agent = Agent(initial_state, 'images/agent1.png', GRID_SIZE) agent = Agent(initial_state, 'images/agent1.png', const.GRID_SIZE)
obstacles = generate_obstacles() obstacles = generate_obstacles()
actions = [] actions = []
clock = pygame.time.Clock() clock = pygame.time.Clock()
spawned = False spawned = False
while True: while True:
# Manualne poruszanie agentem
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_WIDTH, GRID_HEIGHT, Animals, obstacles) agent.handle_event(event, const.GRID_WIDTH, const.GRID_HEIGHT, Animals, obstacles)
const.screen.blit(const.background_image, (0, 0))
draw_grid(const)
draw_enclosures(Enclosures, const)
draw_gates(Enclosures, const)
screen.blit(background_image,(0,0))
draw_grid()
draw_enclosures()
draw_gates()
if not spawned: if not spawned:
spawn_all_animals() spawn_all_animals()
spawn_obstacles() spawn_obstacles()
generate_cost_map() cost_map = generate_cost_map(Animals, Terrain_Obstacles)
for animal in Animals: for animal in Animals:
animal._feed = 2 # Ustawienie aby zwierzę było głodne animal._feed = 2 # Ustawienie, aby zwierzę było głodne
spawned = True spawned = True
draw_Animals()
draw_Terrain_Obstacles() draw_Animals(Animals, const)
agent.draw(screen, GRID_SIZE) draw_Terrain_Obstacles(Terrain_Obstacles, const)
agent.draw(const.screen, const.GRID_SIZE)
pygame.display.flip() pygame.display.flip()
clock.tick(10) clock.tick(10)
if actions: if actions:
action = actions.pop(0) action = actions.pop(0)
agent.move(action, GRID_WIDTH, GRID_HEIGHT, obstacles, Animals, goal) agent.move(action, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, Animals, goal)
pygame.time.wait(200) pygame.time.wait(200)
else: else:
animal = random.choice(Animals) animal = random.choice(Animals)
goal = (animal.x, animal.y) goal = (animal.x, animal.y)
draw_goal(const, goal)
# --- Zaznaczenie celu --- actions = graphsearch(agent.istate, goal, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, cost_map)
pygame.draw.rect(screen, RED, (animal.x * GRID_SIZE, animal.y * GRID_SIZE, GRID_SIZE, GRID_SIZE))
pygame.display.flip()
pygame.time.delay(2000)
# ------------------------
actions = graphsearch(agent.istate, goal, GRID_WIDTH, GRID_HEIGHT, obstacles, cost_map)
# endregion
Walls = []
# region A* Test
from elephant import Elephant
puddle1 = Terrain_Obstacle(15,8,'puddle', puddle_image)
bush1 = Terrain_Obstacle(15,6,'bush', bush_image)
animal = Elephant(15, 10)
animal1 = Elephant(14, 10)
animal2 = Elephant(13, 10)
animal3 = Elephant(12, 10)
animal4 = Elephant(11, 10)
#Animals = [animal, animal1, animal2, animal3, animal4] *Uncomment to test A*
#Terrain_Obstacles = [puddle1, bush1] *Uncomment to test A*
empty_rows = [5, 7, 9]
def generate_test_walls():
for x in range(4,26):
for y in range(0, 15):
if y not in empty_rows:
Walls.append((x, y))
return Walls
def draw_test_walls():
for wall in generate_test_walls():
pygame.draw.rect(screen, BLACK, (wall[0] * GRID_SIZE, wall[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE))
def a_star_testing():
initial_state = (0, 7, 'E')
agent = Agent(initial_state, 'images/agent1.png', GRID_SIZE)
goal = (29, 7)
actions = []
clock = pygame.time.Clock()
generated = False
while True:
screen.fill(WHITE)
draw_grid()
draw_test_walls()
draw_Terrain_Obstacles()
draw_Animals()
if not generated:
generate_cost_map()
agent.draw(screen, GRID_SIZE)
pygame.draw.rect(screen, RED, (goal[0] * GRID_SIZE, goal[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE))
pygame.display.flip()
clock.tick(10)
if actions:
action = actions.pop(0)
agent.move(action, GRID_WIDTH, GRID_HEIGHT, obstacles, Animals, goal)
pygame.time.wait(100)
else:
actions = graphsearch(agent.istate, goal, GRID_WIDTH, GRID_HEIGHT, obstacles, cost_map)
# endregion
class DebugMode(Enum):
MAIN = 1
AVAILABLE_FIELDS = 2
A_STAR_TESTING = 3
if __name__ == "__main__": if __name__ == "__main__":
debug_mode = DebugMode.MAIN main()
if debug_mode == DebugMode.MAIN:
main()
elif debug_mode == DebugMode.AVAILABLE_FIELDS:
available_fields_tests()
elif debug_mode == DebugMode.A_STAR_TESTING:
a_star_testing()

View File

@ -4,8 +4,6 @@ class Spawner:
def __init__(self, entity): def __init__(self, entity):
self.entity = entity self.entity = entity
def spawn_animal(self, blocked, taken, enclosures): def spawn_animal(self, blocked, taken, enclosures):
self.enclosures = [enclosure for enclosure in enclosures if enclosure.type == self.entity.environment] self.enclosures = [enclosure for enclosure in enclosures if enclosure.type == self.entity.environment]
# Wyrażenie listowe filtrujące tylko te wybiegi, które pasują do środowiska zwierzęcia # Wyrażenie listowe filtrujące tylko te wybiegi, które pasują do środowiska zwierzęcia
@ -19,9 +17,11 @@ class Spawner:
self.entity.x = random.randint(enclosure.x1+1, enclosure.x2) self.entity.x = random.randint(enclosure.x1+1, enclosure.x2)
self.entity.y = random.randint(enclosure.y1+1, enclosure.y2) self.entity.y = random.randint(enclosure.y1+1, enclosure.y2)
if self.check(blocked, taken): if self.check(blocked | {(8,5),(3,10),(15,2),(26,2),(11,4),(15,7),(22,4),(24,10),(11,12),(19,12)}, taken):
break break
def spawn_terrain_obstacles(self, blocked1, blocked2, taken, grid_width, grid_height): def spawn_terrain_obstacles(self, blocked1, blocked2, taken, grid_width, grid_height):
blocked1 = blocked1 | {(8,5),(3,10),(15,2),(26,2),(11,4),(15,7),(22,4),(24,10),(11,12),(19,12)}
while True: while True:
self.entity.x = random.randint(0, grid_width - 1) self.entity.x = random.randint(0, grid_width - 1)
self.entity.y = random.randint(0, grid_height - 1) self.entity.y = random.randint(0, grid_height - 1)
@ -51,4 +51,3 @@ class Spawner:
taken.add((x,y)) taken.add((x,y))
return True return True

View File

@ -89,11 +89,12 @@ def current_cost(node, cost_map):
_, parent, action = node _, parent, action = node
# Dodaj koszt pola z mapy kosztów tylko jeśli akcja to "Forward" # Dodaj koszt pola z mapy kosztów tylko jeśli akcja to "Forward"
if action == 'Go Forward': if action == 'Go Forward':
#if True:
state, _, _ = node state, _, _ = node
cost += cost_map.get(state[:2], DEFAULT_COST_VALUE) # Pobiera koszt przejścia przez dane pole, a jeśli koszt nie jest zdefiniowany to bierze wartość domyślną cost += cost_map.get(state[:2], DEFAULT_COST_VALUE) # Pobiera koszt przejścia przez dane pole, a jeśli koszt nie jest zdefiniowany to bierze wartość domyślną
if action == 'Turn Right' or action == 'Turn Left': if action == 'Turn Right' or action == 'Turn Left':
cost += 1 cost += DEFAULT_COST_VALUE
node = parent # Przejdź do rodzica node = parent # Przejdź do rodzica
return cost return cost
@ -101,3 +102,26 @@ def heuristic(state, goal):
x, y, _ = state x, y, _ = state
goal_x, goal_y = goal goal_x, goal_y = goal
return abs(x - goal_x) + abs(y - goal_y) # Odległość Manhattana do celu return abs(x - goal_x) + abs(y - goal_y) # Odległość Manhattana do celu
def generate_cost_map(Animals, Terrain_Obstacles, cost_map={}):
adult_animal_cost = 15 # Default : 15
baby_animal_cost = 10 # Default : 10
puddle_cost = 50 # Default : 50
bush_cost = 20 # Default : 20
for animal in Animals:
if animal.adult:
cost_map[(animal.x + 1, animal.y + 1)] = adult_animal_cost
cost_map[(animal.x + 1, animal.y)] = adult_animal_cost
cost_map[(animal.x, animal.y + 1)] = adult_animal_cost
cost_map[(animal.x, animal.y)] = adult_animal_cost
else:
cost_map[(animal.x, animal.y)] = baby_animal_cost
for terrain_obstacle in Terrain_Obstacles:
if terrain_obstacle.type == 'puddle':
cost_map[(terrain_obstacle.x , terrain_obstacle.y )] = puddle_cost
else:
cost_map[(terrain_obstacle.x , terrain_obstacle.y )] = bush_cost
return cost_map

View File

@ -1,5 +1,4 @@
import pygame import pygame
from abc import ABC, abstractmethod
class Terrain_Obstacle: class Terrain_Obstacle:
def __init__(self, x, y, type , image): def __init__(self, x, y, type , image):
@ -11,3 +10,28 @@ class Terrain_Obstacle:
def draw(self, screen, grid_size): def draw(self, screen, grid_size):
scaled_image = pygame.transform.scale(self.image, (grid_size, grid_size)) scaled_image = pygame.transform.scale(self.image, (grid_size, grid_size))
screen.blit(scaled_image, (self.x * grid_size, self.y * grid_size)) screen.blit(scaled_image, (self.x * grid_size, self.y * grid_size))
def create_obstacles():
puddle_image = pygame.image.load('images/puddle.png')
bush_image = pygame.image.load('images/bush.png')
puddle1 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle2 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle3 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle4 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle5 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle6 = Terrain_Obstacle(0,0,'puddle', puddle_image)
puddle7 = Terrain_Obstacle(0,0,'puddle', puddle_image)
bush1 = Terrain_Obstacle(0,0,'bush', bush_image)
bush2 = Terrain_Obstacle(0,0,'bush', bush_image)
bush3 = Terrain_Obstacle(0,0,'bush', bush_image)
bush4 = Terrain_Obstacle(0,0,'bush', bush_image)
bush5 = Terrain_Obstacle(0,0,'bush', bush_image)
Terrain_Obstacles = [puddle1, puddle2, puddle3, puddle4, puddle5, puddle6, puddle7, bush1, bush2, bush3, bush4, bush5]
return Terrain_Obstacles
def draw_Terrain_Obstacles(Terrain_Obstacles, const):
for terrain_obstacle in Terrain_Obstacles:
terrain_obstacle.draw(const.screen, const.GRID_SIZE)