2024-04-27 19:50:18 +02:00
|
|
|
from enum import Enum
|
2024-04-12 21:50:11 +02:00
|
|
|
import random
|
2024-03-05 14:36:03 +01:00
|
|
|
import pygame
|
|
|
|
import sys
|
2024-04-27 19:50:18 +02:00
|
|
|
from animals import create_animals
|
2024-03-22 16:59:39 +01:00
|
|
|
from agent import Agent
|
2024-04-27 19:50:18 +02:00
|
|
|
from enclosure import Enclosure, create_enclosures
|
2024-03-24 17:33:58 +01:00
|
|
|
from spawner import Spawner
|
2024-04-12 18:17:30 +02:00
|
|
|
from state_space_search import graphsearch
|
2024-04-26 23:45:06 +02:00
|
|
|
from terrain_obstacle import Terrain_Obstacle
|
2024-03-05 14:36:03 +01:00
|
|
|
|
|
|
|
BLACK = (0, 0, 0)
|
2024-04-27 19:50:18 +02:00
|
|
|
RED = (255, 0, 0)
|
2024-03-05 14:36:03 +01:00
|
|
|
|
2024-04-27 11:45:04 +02:00
|
|
|
GRID_SIZE = 50
|
2024-03-24 14:55:49 +01:00
|
|
|
GRID_WIDTH = 30
|
|
|
|
GRID_HEIGHT = 15
|
2024-03-05 14:36:03 +01:00
|
|
|
|
|
|
|
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")
|
|
|
|
|
2024-03-22 16:59:39 +01:00
|
|
|
|
2024-03-05 14:36:03 +01:00
|
|
|
|
2024-03-22 20:11:58 +01:00
|
|
|
background_image = pygame.image.load('images/tło.jpg')
|
2024-03-05 14:36:03 +01:00
|
|
|
background_image = pygame.transform.scale(background_image, WINDOW_SIZE)
|
2024-03-24 14:55:49 +01:00
|
|
|
fenceH = pygame.image.load('images/fenceHor.png')
|
|
|
|
fenceV = pygame.image.load('images/fenceVer.png')
|
2024-03-24 17:33:58 +01:00
|
|
|
gate = pygame.image.load('images/gate.png')
|
2024-04-26 23:45:06 +02:00
|
|
|
puddle_image = pygame.image.load('images/puddle.png')
|
|
|
|
bush_image = pygame.image.load('images/bush.png')
|
2024-04-16 14:50:06 +02:00
|
|
|
obstacles = set()
|
2024-03-24 17:46:13 +01:00
|
|
|
animals_position = set()
|
2024-04-26 23:45:06 +02:00
|
|
|
terrain_obstacles_position = set()
|
2024-03-23 13:55:16 +01:00
|
|
|
|
2024-04-27 19:50:18 +02:00
|
|
|
Animals = create_animals()
|
|
|
|
Enclosures = create_enclosures()
|
2024-03-24 14:55:49 +01:00
|
|
|
|
2024-04-26 23:45:06 +02:00
|
|
|
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]
|
2024-03-24 14:55:49 +01:00
|
|
|
|
2024-03-05 14:36:03 +01:00
|
|
|
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)
|
|
|
|
|
2024-03-24 17:33:58 +01:00
|
|
|
def draw_enclosures():
|
2024-03-24 14:55:49 +01:00
|
|
|
for enclosure in Enclosures:
|
2024-04-16 14:50:06 +02:00
|
|
|
enclosure.draw(screen, GRID_SIZE)
|
2024-03-24 17:33:58 +01:00
|
|
|
|
|
|
|
def draw_gates():
|
|
|
|
for enclosure in Enclosures:
|
|
|
|
enclosure.gatebuild(screen, GRID_SIZE)
|
|
|
|
|
2024-03-22 17:16:34 +01:00
|
|
|
def draw_Animals():
|
|
|
|
for Animal in Animals:
|
|
|
|
Animal.draw(screen, GRID_SIZE)
|
|
|
|
if Animal.feed() == 'True':
|
2024-03-23 13:55:16 +01:00
|
|
|
Animal.draw_exclamation(screen, GRID_SIZE, Animal.x, Animal.y)
|
|
|
|
else:
|
|
|
|
Animal.draw_food(screen,GRID_SIZE,Animal.x,Animal.y)
|
2024-03-05 14:36:03 +01:00
|
|
|
|
2024-03-24 17:33:58 +01:00
|
|
|
def spawn_all_animals():
|
|
|
|
for Animal in Animals:
|
2024-04-26 23:45:06 +02:00
|
|
|
spawner1 = Spawner(Animal)
|
|
|
|
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():
|
|
|
|
for terrain_obstacle in Terrain_Obstacles:
|
|
|
|
spawner2= Spawner(terrain_obstacle)
|
|
|
|
spawner2.spawn_terrain_obstacles(obstacles,animals_position, terrain_obstacles_position, GRID_WIDTH, GRID_HEIGHT)
|
|
|
|
|
2024-03-24 17:33:58 +01:00
|
|
|
|
2024-04-16 14:50:06 +02:00
|
|
|
obstacles = set()
|
2024-04-12 18:17:30 +02:00
|
|
|
def generate_obstacles():
|
|
|
|
|
|
|
|
for en in Enclosures:
|
|
|
|
# Pobierz współrzędne bramy
|
2024-04-28 22:40:13 +02:00
|
|
|
gate_x, gate_y = en.gate1
|
2024-04-12 18:17:30 +02:00
|
|
|
gate_x -= 1
|
|
|
|
gate_y -= 1
|
2024-04-28 22:40:13 +02:00
|
|
|
|
|
|
|
gate_x2, gate_y2 = en.gate2
|
|
|
|
gate_x2 -= 1
|
|
|
|
gate_y2 -= 1
|
2024-04-12 18:17:30 +02:00
|
|
|
|
|
|
|
# Dodaj lewy brzeg prostokąta
|
|
|
|
for y in range(en.y1, en.y2 + 1):
|
2024-04-28 22:40:13 +02:00
|
|
|
if (en.x1, y) != (gate_x, gate_y) and (en.x1, y) != (gate_x2, gate_y2):
|
2024-04-16 14:50:06 +02:00
|
|
|
obstacles.add((en.x1, y))
|
2024-04-12 18:17:30 +02:00
|
|
|
|
|
|
|
# Dodaj prawy brzeg prostokąta
|
|
|
|
for y in range(en.y1, en.y2 + 1):
|
2024-04-28 22:40:13 +02:00
|
|
|
if (en.x2, y) != (gate_x, gate_y) and (en.x2, y) != (gate_x2, gate_y2):
|
2024-04-16 14:50:06 +02:00
|
|
|
obstacles.add((en.x2, y))
|
2024-04-12 18:17:30 +02:00
|
|
|
|
|
|
|
# Dodaj górny brzeg prostokąta
|
|
|
|
for x in range(en.x1+1, en.x2):
|
2024-04-28 22:40:13 +02:00
|
|
|
if (x, en.y1) != (gate_x, gate_y) and (x, en.y1) != (gate_x2, gate_y2):
|
2024-04-16 14:50:06 +02:00
|
|
|
obstacles.add((x, en.y1))
|
2024-04-12 18:17:30 +02:00
|
|
|
|
|
|
|
# Dodaj dolny brzeg prostokąta
|
|
|
|
for x in range(en.x1+1, en.x2):
|
2024-04-28 22:40:13 +02:00
|
|
|
if (x, en.y2) != (gate_x, gate_y) and (x, en.y2) != (gate_x2, gate_y2):
|
2024-04-16 14:50:06 +02:00
|
|
|
obstacles.add((x, en.y2))
|
2024-04-12 18:17:30 +02:00
|
|
|
|
|
|
|
return obstacles
|
|
|
|
|
2024-04-27 19:50:18 +02:00
|
|
|
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
|
2024-04-16 14:50:06 +02:00
|
|
|
available_fields_small = set()
|
|
|
|
available_fields_large = set()
|
2024-04-27 19:50:18 +02:00
|
|
|
|
|
|
|
WHITE = (255,255,255)
|
|
|
|
GREEN = (0, 255, 0)
|
|
|
|
YELLOW = (255, 255, 0)
|
|
|
|
BLACK = (0, 0, 0)
|
|
|
|
|
2024-04-16 14:50:06 +02:00
|
|
|
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))
|
2024-04-12 18:17:30 +02:00
|
|
|
|
2024-04-27 19:50:18 +02:00
|
|
|
def available_fields_tests():
|
2024-04-16 14:50:06 +02:00
|
|
|
obstacles = generate_obstacles()
|
2024-04-12 18:17:30 +02:00
|
|
|
|
2024-04-16 14:50:06 +02:00
|
|
|
while True:
|
|
|
|
screen.fill(WHITE)
|
2024-04-12 18:17:30 +02:00
|
|
|
|
2024-04-16 14:50:06 +02:00
|
|
|
draw_grid()
|
|
|
|
draw_fields(obstacles, BLACK)
|
2024-04-12 18:17:30 +02:00
|
|
|
|
2024-04-16 14:50:06 +02:00
|
|
|
generate_available_fields()
|
2024-04-12 18:17:30 +02:00
|
|
|
|
2024-04-16 14:50:06 +02:00
|
|
|
draw_fields(available_fields_small, GREEN)
|
|
|
|
draw_fields(available_fields_large, YELLOW)
|
2024-04-12 18:17:30 +02:00
|
|
|
|
2024-04-16 14:50:06 +02:00
|
|
|
# Odświeżenie ekranu
|
|
|
|
pygame.display.flip()
|
2024-04-12 18:17:30 +02:00
|
|
|
# endregion
|
2024-03-10 17:40:26 +01:00
|
|
|
|
2024-04-16 14:50:06 +02:00
|
|
|
# region Main Code
|
2024-03-05 14:36:03 +01:00
|
|
|
def main():
|
2024-04-16 14:50:06 +02:00
|
|
|
initial_state = (0,0,'S')
|
2024-04-12 22:11:58 +02:00
|
|
|
agent = Agent(initial_state, 'images/agent1.png', GRID_SIZE)
|
2024-04-12 18:17:30 +02:00
|
|
|
|
|
|
|
obstacles = generate_obstacles()
|
|
|
|
actions = []
|
2024-03-05 14:36:03 +01:00
|
|
|
clock = pygame.time.Clock()
|
2024-04-12 21:50:11 +02:00
|
|
|
|
|
|
|
spawned = False
|
2024-03-05 14:36:03 +01:00
|
|
|
while True:
|
2024-04-16 14:50:06 +02:00
|
|
|
# Manualne poruszanie agentem
|
2024-03-05 14:36:03 +01:00
|
|
|
for event in pygame.event.get():
|
|
|
|
if event.type == pygame.QUIT:
|
|
|
|
pygame.quit()
|
|
|
|
sys.exit()
|
2024-04-12 18:17:30 +02:00
|
|
|
agent.handle_event(event, GRID_WIDTH, GRID_HEIGHT, Animals, obstacles)
|
2024-03-05 14:36:03 +01:00
|
|
|
|
|
|
|
screen.blit(background_image,(0,0))
|
|
|
|
draw_grid()
|
2024-03-24 17:33:58 +01:00
|
|
|
draw_enclosures()
|
|
|
|
draw_gates()
|
2024-04-12 21:50:11 +02:00
|
|
|
if not spawned:
|
|
|
|
spawn_all_animals()
|
2024-04-26 23:45:06 +02:00
|
|
|
spawn_obstacles()
|
2024-04-26 15:46:02 +02:00
|
|
|
generate_cost_map()
|
2024-04-12 23:11:46 +02:00
|
|
|
for animal in Animals:
|
|
|
|
animal._feed = 2 # Ustawienie aby zwierzę było głodne
|
2024-04-12 21:50:11 +02:00
|
|
|
spawned = True
|
2024-03-24 17:33:58 +01:00
|
|
|
draw_Animals()
|
2024-04-26 23:45:06 +02:00
|
|
|
draw_Terrain_Obstacles()
|
2024-04-12 22:11:58 +02:00
|
|
|
agent.draw(screen, GRID_SIZE)
|
2024-03-05 14:36:03 +01:00
|
|
|
pygame.display.flip()
|
|
|
|
clock.tick(10)
|
2024-04-16 14:50:06 +02:00
|
|
|
|
2024-04-12 18:17:30 +02:00
|
|
|
if actions:
|
|
|
|
action = actions.pop(0)
|
2024-04-27 11:20:59 +02:00
|
|
|
agent.move(action, GRID_WIDTH, GRID_HEIGHT, obstacles, Animals, goal)
|
2024-04-12 18:17:30 +02:00
|
|
|
pygame.time.wait(200)
|
2024-04-16 14:50:06 +02:00
|
|
|
else:
|
|
|
|
animal = random.choice(Animals)
|
2024-04-26 15:46:02 +02:00
|
|
|
goal = (animal.x, animal.y)
|
|
|
|
|
|
|
|
# --- Zaznaczenie celu ---
|
2024-04-27 19:50:18 +02:00
|
|
|
pygame.draw.rect(screen, RED, (animal.x * GRID_SIZE, animal.y * GRID_SIZE, GRID_SIZE, GRID_SIZE))
|
2024-04-26 15:46:02 +02:00
|
|
|
pygame.display.flip()
|
|
|
|
pygame.time.delay(2000)
|
|
|
|
# ------------------------
|
|
|
|
|
|
|
|
actions = graphsearch(agent.istate, goal, GRID_WIDTH, GRID_HEIGHT, obstacles, cost_map)
|
2024-04-16 14:50:06 +02:00
|
|
|
# endregion
|
|
|
|
|
2024-04-27 19:50:18 +02:00
|
|
|
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)
|
2024-04-28 22:40:13 +02:00
|
|
|
#Animals = [animal, animal1, animal2, animal3, animal4] *Uncomment to test A*
|
|
|
|
#Terrain_Obstacles = [puddle1, bush1] *Uncomment to test A*
|
2024-04-27 19:50:18 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2024-03-05 14:36:03 +01:00
|
|
|
if __name__ == "__main__":
|
2024-04-28 22:40:13 +02:00
|
|
|
debug_mode = DebugMode.MAIN
|
2024-04-16 14:50:06 +02:00
|
|
|
|
2024-04-27 19:50:18 +02:00
|
|
|
if debug_mode == DebugMode.MAIN:
|
2024-04-16 14:50:06 +02:00
|
|
|
main()
|
2024-04-27 19:50:18 +02:00
|
|
|
elif debug_mode == DebugMode.AVAILABLE_FIELDS:
|
|
|
|
available_fields_tests()
|
|
|
|
elif debug_mode == DebugMode.A_STAR_TESTING:
|
|
|
|
a_star_testing()
|