Merge pull request 'Przeszukiwanie-stanów-A_star' (#2) from Przeszukiwanie-stanów-A_star into master
Reviewed-on: s481865/Male_zoo#2
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.pyc
|
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"python.analysis.extraPaths": [
|
||||
"./Animals"
|
||||
]
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import pygame
|
||||
from abc import ABC, abstractmethod
|
||||
from abc import abstractmethod
|
||||
|
||||
class Animal:
|
||||
def __init__(self, x, y,name, image, food_image, food, environment, adult=False,):
|
||||
@ -14,29 +14,31 @@ class Animal:
|
||||
self.environment = environment #hot/cold/medium
|
||||
|
||||
def draw(self, screen, grid_size):
|
||||
self.image = pygame.transform.scale(self.image, (grid_size, grid_size))
|
||||
if self.adult:
|
||||
# If adult, draw like AdultAnimal
|
||||
# Jeśli zwierzę jest dorosłe, skaluj obrazek na większy rozmiar
|
||||
new_width = grid_size * 2
|
||||
new_height = grid_size * 2
|
||||
scaled_image = pygame.transform.scale(self.image, (new_width, new_height))
|
||||
screen.blit(scaled_image, (self.x * grid_size, self.y * grid_size))
|
||||
else:
|
||||
# If not adult, draw like normal Animal
|
||||
screen.blit(self.image, (self.x * grid_size, self.y * grid_size))
|
||||
# Jeśli zwierzę nie jest dorosłe, skaluj obrazek na rozmiar jednej kratki
|
||||
scaled_image = pygame.transform.scale(self.image, (grid_size, grid_size))
|
||||
screen.blit(scaled_image, (self.x * grid_size, self.y * grid_size))
|
||||
|
||||
def draw_exclamation(self, screen, grid_size, x, y):
|
||||
exclamation_image = pygame.image.load('images/exclamation.png')
|
||||
exclamation_image = pygame.transform.scale(exclamation_image, (grid_size,grid_size))
|
||||
screen.blit(exclamation_image, (x*grid_size, y*grid_size - grid_size))
|
||||
exclamation_image = pygame.transform.scale(exclamation_image, (int(grid_size * 0.45), int(grid_size * 0.45)))
|
||||
screen.blit(exclamation_image, (x * grid_size, y * grid_size))
|
||||
|
||||
def draw_food(self, screen, grid_size, x, y):
|
||||
scale = 0.45
|
||||
food_image = pygame.image.load(self.food_image)
|
||||
food_image = pygame.transform.scale(food_image, (grid_size,grid_size))
|
||||
screen.blit(food_image, (x*grid_size, y*grid_size + grid_size))
|
||||
|
||||
|
||||
|
||||
if(self.adult):
|
||||
y = y + 1
|
||||
scale = 0.7
|
||||
food_image = pygame.transform.scale(food_image, (int(grid_size * scale), int(grid_size * scale)))
|
||||
screen.blit(food_image, (x * grid_size, (y + 1) * grid_size - int(grid_size * scale)))
|
||||
|
||||
@abstractmethod
|
||||
def feed(self):
|
47
Animals/animals.py
Normal file
@ -0,0 +1,47 @@
|
||||
from elephant import Elephant
|
||||
from giraffe import Giraffe
|
||||
from penguin import Penguin
|
||||
from parrot import Parrot
|
||||
from bear import Bear
|
||||
|
||||
def create_animals():
|
||||
giraffe1 = Giraffe(0, 0, adult=True)
|
||||
giraffe2 = Giraffe(0, 0, adult=True)
|
||||
giraffe3 = Giraffe(0, 0, adult=True)
|
||||
giraffe4 = Giraffe(0, 0)
|
||||
giraffe5 = Giraffe(0, 0)
|
||||
bear1 = Bear(0, 0, adult=True)
|
||||
bear2 = Bear(0, 0, adult=True)
|
||||
bear3 = Bear(0, 0)
|
||||
bear4 = Bear(0, 0)
|
||||
bear5 = Bear(0, 0)
|
||||
penguin1 = Penguin(0, 0)
|
||||
penguin2 = Penguin(0, 0)
|
||||
penguin3 = Penguin(0, 0)
|
||||
penguin4 = Penguin(0, 0)
|
||||
elephant1 = Elephant(0, 0, adult=True)
|
||||
elephant2 = Elephant(0, 0, adult=True)
|
||||
elephant3 = Elephant(0, 0)
|
||||
elephant4 = Elephant(0, 0)
|
||||
elephant5 = Elephant(0, 0)
|
||||
parrot1 = Parrot(0, 0)
|
||||
parrot2 = Parrot(0, 0)
|
||||
parrot3 = Parrot(0, 0)
|
||||
parrot4 = Parrot(0, 0)
|
||||
parrot5 = Parrot(0, 0)
|
||||
|
||||
Animals = [giraffe1, giraffe2, giraffe3, giraffe4, giraffe5,
|
||||
bear1, bear2, bear3, bear4, bear5,
|
||||
elephant1, elephant2, elephant3, elephant4, elephant5,
|
||||
penguin1, penguin2, penguin3, penguin4,
|
||||
parrot1, parrot2, parrot3, parrot4, parrot5]
|
||||
|
||||
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)
|
@ -2,8 +2,6 @@ from animal import Animal
|
||||
import pygame
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
|
||||
class Bear(Animal):
|
||||
def __init__(self, x, y, adult=False):
|
||||
Bear_image = pygame.image.load('images/bear.png')
|
70
agent.py
@ -1,34 +1,66 @@
|
||||
import pygame
|
||||
from state_space_search import is_border, is_obstacle
|
||||
|
||||
class Agent:
|
||||
def __init__(self, x, y, image_path, grid_size):
|
||||
self.x = x
|
||||
self.y = y
|
||||
def __init__(self, istate, image_path, grid_size):
|
||||
self.istate = istate
|
||||
self.x, self.y, self.direction = istate
|
||||
self.grid_size = grid_size
|
||||
self.image= pygame.image.load(image_path)
|
||||
self.image = pygame.transform.scale(self.image, (grid_size, grid_size))
|
||||
|
||||
|
||||
def draw(self, screen):
|
||||
def draw(self, screen, grid_size):
|
||||
# Obróć obrazek zgodnie z kierunkiem
|
||||
if self.direction == 'E':
|
||||
self.image= pygame.image.load('images/agent4.png')
|
||||
elif self.direction == 'S':
|
||||
self.image= pygame.image.load('images/agent1.png')
|
||||
elif self.direction == 'W':
|
||||
self.image= pygame.image.load('images/agent3.png')
|
||||
else: # direction == 'N'
|
||||
self.image= pygame.image.load('images/agent2.png')
|
||||
self.image = pygame.transform.scale(self.image, (grid_size, grid_size))
|
||||
screen.blit(self.image, (self.x * self.grid_size, self.y * self.grid_size))
|
||||
|
||||
def move(self, dx, dy):
|
||||
self.x += dx
|
||||
self.y += dy
|
||||
|
||||
def handle_event(self, event, grid_height,grid_width, animals, blocked_fields):
|
||||
def handle_event(self, event, max_x, max_y, animals, obstacles):
|
||||
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:
|
||||
self.move(0, -1)
|
||||
elif event.key == pygame.K_DOWN and self.y < grid_height - 1 and (self.x, self.y+1) not in blocked_fields:
|
||||
self.move(0, 1)
|
||||
elif event.key == pygame.K_LEFT and self.x > 0 and (self.x-1, self.y) not in blocked_fields:
|
||||
self.move(-1, 0)
|
||||
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)
|
||||
if event.key == pygame.K_UP:
|
||||
self.move('Go Forward', max_x, max_y, obstacles, animals)
|
||||
elif event.key == pygame.K_LEFT:
|
||||
self.move('Turn Left', max_x, max_y, obstacles, animals)
|
||||
elif event.key == pygame.K_RIGHT:
|
||||
self.move('Turn Right', max_x, max_y, obstacles, animals)
|
||||
|
||||
def move(self, action, max_x, max_y, obstacles, animals, goal):
|
||||
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]
|
||||
|
||||
self.istate = (self.x, self.y, self.direction)
|
||||
feed_animal(self, animals, goal)
|
||||
|
||||
def feed_animal(self, animals, goal):
|
||||
goal_x, goal_y = goal
|
||||
if self.x == goal_x and self.y == goal_y:
|
||||
for animal in animals:
|
||||
if self.x == animal.x and self.y == animal.y:
|
||||
if animal.x == goal_x and animal.y == goal_y:
|
||||
if animal.feed() == 'True':
|
||||
animal._feed = 0
|
||||
print(animal.name, "fed with", animal.food)
|
15
constants.py
Normal 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
@ -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)
|
93
enclosure.py
@ -1,14 +1,16 @@
|
||||
import pygame
|
||||
|
||||
|
||||
class Enclosure:
|
||||
def __init__(self, x1, y1, x2, y2, gate, type, imageH, imageV, imageGate):
|
||||
def __init__(self, x1, y1, x2, y2, gate1, gate2, type, imageH, imageV, imageGate):
|
||||
self.x1 = x1 - 1
|
||||
self.y1 = y1 - 1
|
||||
# (x1,y1) - wierzchołek przekątnej
|
||||
self.x2 = x2 - 1
|
||||
self.y2 = y2 - 1
|
||||
# (x2,y2) - 2 wierzchołek przekątnej
|
||||
self.gate = gate
|
||||
self.gate1 = gate1
|
||||
self.gate2 = gate2
|
||||
self.type = type
|
||||
self.imageH = imageH
|
||||
self.imageV = imageV
|
||||
@ -16,64 +18,57 @@ class Enclosure:
|
||||
|
||||
def gatebuild(self, screen, grid_size):
|
||||
self.imageGate = pygame.transform.scale(self.imageGate, (grid_size, grid_size))
|
||||
gate_x, gate_y = self.gate
|
||||
gate_x-=1
|
||||
gate_y-=1
|
||||
rect = pygame.Rect(gate_x * grid_size, gate_y * grid_size, grid_size, grid_size)
|
||||
pygame.draw.rect(screen, (0, 0, 0), rect) # Fill the area with
|
||||
screen.blit(self.imageGate, (gate_x * grid_size, gate_y * grid_size))
|
||||
gate_x1, gate_y1 = self.gate1
|
||||
gate_x2, gate_y2 = self.gate2
|
||||
gate_x1 -= 1
|
||||
gate_y1 -= 1
|
||||
gate_x2 -= 1
|
||||
gate_y2 -= 1
|
||||
rect1 = pygame.Rect(gate_x1 * grid_size, gate_y1 * grid_size, grid_size, grid_size)
|
||||
rect2 = pygame.Rect(gate_x2 * grid_size, gate_y2 * grid_size, grid_size, grid_size)
|
||||
screen.blit(self.imageGate, (gate_x1 * grid_size, gate_y1 * grid_size))
|
||||
screen.blit(self.imageGate, (gate_x2 * grid_size, gate_y2 * grid_size))
|
||||
|
||||
def gateopen(self, blocked):
|
||||
gate_x, gate_y = self.gate
|
||||
gate_x -= 1
|
||||
gate_y -= 1
|
||||
if (gate_x, gate_y) in blocked:
|
||||
blocked.remove((gate_x, gate_y))
|
||||
|
||||
|
||||
|
||||
def draw(self,screen, grid_size , blocked_fields):
|
||||
def draw(self, screen, grid_size):
|
||||
self.imageH = pygame.transform.scale(self.imageH, (grid_size, grid_size))
|
||||
self.imageV = pygame.transform.scale(self.imageV, (grid_size, grid_size))
|
||||
gate_x1, gate_y1 = self.gate1
|
||||
gate_x2, gate_y2 = self.gate2
|
||||
gate_x1 -= 1
|
||||
gate_y1 -= 1
|
||||
gate_x2 -= 1
|
||||
gate_y2 -= 1
|
||||
if self.x1 < self.x2:
|
||||
for i in range(self.x1, self.x2 + 1):
|
||||
if (i, self.y1) != (gate_x1, gate_y1) and (i, self.y1) != (gate_x2, gate_y2):
|
||||
screen.blit(self.imageH, (i * grid_size, self.y1 * grid_size))
|
||||
blocked_fields.add((i, self.y1))
|
||||
if (i, self.y2) != (gate_x1, gate_y1) and (i, self.y2) != (gate_x2, gate_y2):
|
||||
screen.blit(self.imageH, (i * grid_size, self.y2 * grid_size))
|
||||
blocked_fields.add((i, self.y2))
|
||||
if self.y1 < self.y2:
|
||||
for j in range(self.y1, self.y2 + 1):
|
||||
screen.blit(self.imageH, (self.x1 * grid_size, j * grid_size))
|
||||
blocked_fields.add((self.x1, j))
|
||||
screen.blit(self.imageH, (self.x2 * grid_size, j * grid_size))
|
||||
blocked_fields.add((self.x2, j))
|
||||
if self.y1 > self.y2:
|
||||
for j in range(self.y2, self.y1+1):
|
||||
screen.blit(self.imageH, (self.x1 * grid_size, j * grid_size))
|
||||
blocked_fields.add((self.x1, j))
|
||||
screen.blit(self.imageH, (self.x2 * grid_size, j * grid_size))
|
||||
blocked_fields.add((self.x2, j))
|
||||
if self.x1 > self.x2:
|
||||
for i in range(self.x2, self.x1+1):
|
||||
screen.blit(self.imageH, (i * grid_size, self.y1 * grid_size))
|
||||
blocked_fields.add((i, self.y1))
|
||||
screen.blit(self.imageH, (i * grid_size, self.y2 * grid_size))
|
||||
blocked_fields.add((i, self.y2))
|
||||
if self.y1 < self.y2:
|
||||
for j in range(self.y1, self.y2+1):
|
||||
screen.blit(self.imageH, (self.x1 * grid_size, j * grid_size))
|
||||
blocked_fields.add((self.x1, j))
|
||||
screen.blit(self.imageH, (self.x2 * grid_size, j * grid_size))
|
||||
blocked_fields.add((self.x2, j))
|
||||
if self.y1 > self.y2:
|
||||
for j in range(self.y2, self.y1+1):
|
||||
screen.blit(self.imageH, (self.x1 * grid_size, j * grid_size))
|
||||
blocked_fields.add((self.x1, j))
|
||||
screen.blit(self.imageH, (self.x2 * grid_size, j * grid_size))
|
||||
blocked_fields.add((self.x2, j))
|
||||
if (self.x1, j) != (gate_x1, gate_y1) and (self.x1, j) != (gate_x2, gate_y2):
|
||||
screen.blit(self.imageV, (self.x1 * grid_size, j * grid_size))
|
||||
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))
|
||||
|
||||
def create_enclosures():
|
||||
fenceH = pygame.image.load('images/fenceHor.png')
|
||||
fenceV = pygame.image.load('images/fenceVer.png')
|
||||
gate = pygame.image.load('images/gate.png')
|
||||
|
||||
en1 = Enclosure(0, 5, 9, 11, (9, 6), (4, 11), "hot", fenceH, fenceV, gate) # Lewa klatka
|
||||
en2 = Enclosure(13, 0, 29, 3, (16, 3), (27, 3), 'medium', fenceH, fenceV, gate) # Górna klatka
|
||||
en3 = Enclosure(11, 5, 16, 11, (12, 5), (16, 8), 'cold', fenceH, fenceV, gate) # Środkowa klatka
|
||||
en4 = Enclosure(19, 5, 31, 11, (23, 5), (25, 11), 'hot', fenceH, fenceV, gate) # Prawa klatka
|
||||
en5 = Enclosure(4, 13, 28, 16, (12, 13), (20, 13), 'cold', fenceH, fenceV, gate) # Dolna klatka
|
||||
|
||||
Enclosures = [en1, en2, en3, en4, en5]
|
||||
|
||||
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)
|
BIN
images/agent1.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
images/agent2.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
images/agent3.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
images/agent4.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 248 KiB |
BIN
images/bear.png
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 2.3 MiB |
BIN
images/bush.png
Normal file
After Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 12 KiB |
BIN
images/fish.png
Before Width: | Height: | Size: 934 KiB After Width: | Height: | Size: 601 KiB |
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 444 KiB |
BIN
images/meat.png
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 232 KiB |
BIN
images/milk.png
Before Width: | Height: | Size: 288 KiB After Width: | Height: | Size: 460 KiB |
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 2.4 MiB |
BIN
images/puddle.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
167
main.py
@ -1,117 +1,116 @@
|
||||
import random
|
||||
import pygame
|
||||
import sys
|
||||
from elephant import Elephant
|
||||
from giraffe import Giraffe
|
||||
from penguin import Penguin
|
||||
from parrot import Parrot
|
||||
from bear import Bear
|
||||
import sys
|
||||
sys.path.append('./Animals')
|
||||
from animals import create_animals, draw_Animals
|
||||
from agent import Agent
|
||||
from enclosure import Enclosure
|
||||
from enclosure import create_enclosures, draw_enclosures, draw_gates
|
||||
from spawner import Spawner
|
||||
from state_space_search import graphsearch, generate_cost_map
|
||||
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)
|
||||
|
||||
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)
|
||||
const = Constants()
|
||||
init_pygame(const)
|
||||
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')
|
||||
|
||||
|
||||
fences = set()
|
||||
obstacles = set()
|
||||
animals_position = set()
|
||||
terrain_obstacles_position = set()
|
||||
|
||||
|
||||
|
||||
an1 = Parrot(16, 2)
|
||||
an2 = Penguin(8, 6)
|
||||
an3 = Bear(14, 9)
|
||||
old_an2 = Giraffe(18,4, adult=True)
|
||||
old_an1 = Elephant(4, 7, adult=True)
|
||||
an4 = Elephant(4,3)
|
||||
|
||||
Animals = [an1, an2, an3, an4, old_an1, old_an2]
|
||||
|
||||
en1 = Enclosure(1,5,9,11,(9,6),"medium", fenceH, fenceV, gate)
|
||||
en2 = Enclosure(29,3, 13,1,(16,3), 'medium', 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)
|
||||
en5 = Enclosure(4,13, 28,15, (16,13),'cold', fenceH, fenceV, gate)
|
||||
|
||||
|
||||
Enclosures = [en1, en2, en3, en4, en5]
|
||||
|
||||
|
||||
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, fences)
|
||||
|
||||
def draw_gates():
|
||||
for enclosure in Enclosures:
|
||||
enclosure.gatebuild(screen, GRID_SIZE)
|
||||
|
||||
def opengates():
|
||||
for enclosure in Enclosures:
|
||||
enclosure.gateopen(fences)
|
||||
|
||||
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)
|
||||
Animals = create_animals()
|
||||
Enclosures = create_enclosures()
|
||||
Terrain_Obstacles = create_obstacles()
|
||||
|
||||
def spawn_all_animals():
|
||||
for Animal in Animals:
|
||||
spawner1 = Spawner(Animal, Enclosures)
|
||||
spawner1.spawn_animal(fences, animals_position)
|
||||
spawner1 = Spawner(Animal)
|
||||
spawner1.spawn_animal(obstacles, animals_position, Enclosures)
|
||||
|
||||
def spawn_obstacles():
|
||||
for terrain_obstacle in Terrain_Obstacles:
|
||||
spawner2 = Spawner(terrain_obstacle)
|
||||
spawner2.spawn_terrain_obstacles(obstacles, animals_position, terrain_obstacles_position, const.GRID_WIDTH, const.GRID_HEIGHT)
|
||||
|
||||
def generate_obstacles():
|
||||
for en in Enclosures:
|
||||
# Pobierz współrzędne bramy
|
||||
gate_x, gate_y = en.gate1
|
||||
gate_x -= 1
|
||||
gate_y -= 1
|
||||
|
||||
gate_x2, gate_y2 = en.gate2
|
||||
gate_x2 -= 1
|
||||
gate_y2 -= 1
|
||||
|
||||
# Dodaj lewy brzeg prostokąta
|
||||
for y in range(en.y1, en.y2 + 1):
|
||||
if (en.x1, y) != (gate_x, gate_y) and (en.x1, y) != (gate_x2, gate_y2):
|
||||
obstacles.add((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) and (en.x2, y) != (gate_x2, gate_y2):
|
||||
obstacles.add((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) and (x, en.y1) != (gate_x2, gate_y2):
|
||||
obstacles.add((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) and (x, en.y2) != (gate_x2, gate_y2):
|
||||
obstacles.add((x, en.y2))
|
||||
|
||||
return obstacles
|
||||
|
||||
def main():
|
||||
agent = Agent(0, 0, 'images/avatar.png', GRID_SIZE)
|
||||
initial_state = (0, 0, 'S')
|
||||
agent = Agent(initial_state, 'images/agent1.png', const.GRID_SIZE)
|
||||
|
||||
obstacles = generate_obstacles()
|
||||
actions = []
|
||||
clock = pygame.time.Clock()
|
||||
spawned = False
|
||||
|
||||
while True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
agent.handle_event(event, GRID_HEIGHT, GRID_WIDTH, Animals, fences)
|
||||
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:
|
||||
spawn_all_animals()
|
||||
spawn_obstacles()
|
||||
cost_map = generate_cost_map(Animals, Terrain_Obstacles)
|
||||
for animal in Animals:
|
||||
animal._feed = 2 # Ustawienie, aby zwierzę było głodne
|
||||
spawned = True
|
||||
draw_Animals()
|
||||
opengates()
|
||||
agent.draw(screen)
|
||||
|
||||
draw_Animals(Animals, const)
|
||||
draw_Terrain_Obstacles(Terrain_Obstacles, const)
|
||||
agent.draw(const.screen, const.GRID_SIZE)
|
||||
pygame.display.flip()
|
||||
clock.tick(10)
|
||||
|
||||
if actions:
|
||||
action = actions.pop(0)
|
||||
agent.move(action, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, Animals, goal)
|
||||
pygame.time.wait(200)
|
||||
else:
|
||||
animal = random.choice(Animals)
|
||||
goal = (animal.x, animal.y)
|
||||
draw_goal(const, goal)
|
||||
actions = graphsearch(agent.istate, goal, const.GRID_WIDTH, const.GRID_HEIGHT, obstacles, cost_map)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
73
spawner.py
@ -1,44 +1,53 @@
|
||||
import random
|
||||
|
||||
|
||||
class Spawner:
|
||||
def __init__(self, animal, enclosures):
|
||||
self.animal = animal
|
||||
self.enclosures = enclosures
|
||||
def __init__(self, entity):
|
||||
self.entity = entity
|
||||
|
||||
def spawn_animal(self, blocked, taken, enclosures):
|
||||
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
|
||||
enclosure = random.choice(self.enclosures)
|
||||
|
||||
def spawn_animal(self, blocked, taken):
|
||||
possibilities = self.enclosures
|
||||
fitting = []
|
||||
for option in possibilities:
|
||||
if option.type == self.animal.environment:
|
||||
fitting.append(option)
|
||||
enclosure = random.choice(fitting)
|
||||
while True:
|
||||
if enclosure.x1 < enclosure.x2:
|
||||
self.animal.x = random.randint(enclosure.x1, enclosure.x2)
|
||||
if enclosure.y1 < enclosure.y2:
|
||||
self.animal.y = random.randint(enclosure.y1, enclosure.y2)
|
||||
if enclosure.y1 > enclosure.y2:
|
||||
self.animal.y = random.randint(enclosure.y2, enclosure.y1)
|
||||
if enclosure.x1 > enclosure.x2:
|
||||
self.animal.x = random.randint(enclosure.x2, enclosure.x1)
|
||||
if enclosure.y1 < enclosure.y2:
|
||||
self.animal.y = random.randint(enclosure.y1, enclosure.y2)
|
||||
if enclosure.y1 > enclosure.y2:
|
||||
self.animal.y = random.randint(enclosure.y2, enclosure.y1)
|
||||
if self.check(blocked, taken):
|
||||
if self.entity.adult:
|
||||
self.entity.x = random.randint(enclosure.x1+1, enclosure.x2-2)
|
||||
self.entity.y = random.randint(enclosure.y1+1, enclosure.y2-2)
|
||||
else:
|
||||
self.entity.x = random.randint(enclosure.x1+1, enclosure.x2)
|
||||
self.entity.y = random.randint(enclosure.y1+1, enclosure.y2)
|
||||
|
||||
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
|
||||
|
||||
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:
|
||||
self.entity.x = random.randint(0, grid_width - 1)
|
||||
self.entity.y = random.randint(0, grid_height - 1)
|
||||
y = self.entity.y
|
||||
x = self.entity.x
|
||||
if (x, y) not in blocked1 and (x, y) not in blocked2 and (x, y) not in taken:
|
||||
taken.add((self.entity.x, self.entity.y))
|
||||
break
|
||||
|
||||
def check(self, blocked, taken):
|
||||
x = self.animal.x
|
||||
y = self.animal.y
|
||||
x = self.entity.x
|
||||
y = self.entity.y
|
||||
|
||||
if (x,y) in blocked or (x,y) in taken:
|
||||
return False
|
||||
|
||||
if self.entity.adult:
|
||||
|
||||
adult_fields = [(x, y), (x+1,y), (x,y+1), (x+1,y+1)] # Duże zwierze zajmuje 4 pola
|
||||
|
||||
if any(field in taken for field in adult_fields): # Jeśli stawiane zwierze jest dorosłe i jakiekolwiek pole jest zajęte, to nie można postawić zwierzęcia
|
||||
return False
|
||||
|
||||
for field in adult_fields: # Dodaj wszystkie pola zajęte przez duże zwierzę
|
||||
taken.add(field)
|
||||
else:
|
||||
taken.add((x,y))
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
127
state_space_search.py
Normal file
@ -0,0 +1,127 @@
|
||||
from queue import PriorityQueue
|
||||
|
||||
DEFAULT_COST_VALUE = 1
|
||||
|
||||
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, cost_map):
|
||||
fringe = PriorityQueue()
|
||||
explored = set()
|
||||
|
||||
fringe.put((0, (istate, None , None)))
|
||||
|
||||
while not fringe.empty():
|
||||
_, node = fringe.get()
|
||||
state, _, _ = node
|
||||
|
||||
if goaltest(state, goal):
|
||||
return build_action_sequence(node)
|
||||
|
||||
explored.add(state)
|
||||
|
||||
successors = succ(state, max_x, max_y, obstacles)
|
||||
|
||||
for new_state, action in successors:
|
||||
new_node = (new_state, node, action)
|
||||
|
||||
p_new_state = current_cost(node, cost_map) + heuristic(state, goal)
|
||||
|
||||
if not is_state_in_queue(new_state, fringe) and new_state not in explored:
|
||||
fringe.put((p_new_state, new_node))
|
||||
|
||||
elif is_state_in_queue(new_state, fringe):
|
||||
for i, (p_existing_state, (existing_state, _, _)) in enumerate(fringe.queue):
|
||||
if existing_state == new_state and p_existing_state > p_new_state:
|
||||
fringe.queue[i] = (p_new_state, new_node)
|
||||
else:
|
||||
break
|
||||
|
||||
return False
|
||||
|
||||
def is_state_in_queue(state, queue):
|
||||
for _, (s, _, _) in queue.queue:
|
||||
if s == state:
|
||||
return True
|
||||
return False
|
||||
|
||||
def build_action_sequence(node):
|
||||
actions = []
|
||||
while node[1] is not None: # Dopóki nie dojdziemy do korzenia
|
||||
_, parent, action = node
|
||||
actions.append(action)
|
||||
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)
|
||||
|
||||
def current_cost(node, cost_map):
|
||||
cost = 0
|
||||
while node[1] is not None: # Dopóki nie dojdziemy do korzenia
|
||||
_, parent, action = node
|
||||
# Dodaj koszt pola z mapy kosztów tylko jeśli akcja to "Forward"
|
||||
if action == 'Go Forward':
|
||||
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ą
|
||||
|
||||
if action == 'Turn Right' or action == 'Turn Left':
|
||||
cost += DEFAULT_COST_VALUE
|
||||
|
||||
node = parent # Przejdź do rodzica
|
||||
return cost
|
||||
|
||||
def heuristic(state, goal):
|
||||
x, y, _ = state
|
||||
goal_x, goal_y = goal
|
||||
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
|
37
terrain_obstacle.py
Normal file
@ -0,0 +1,37 @@
|
||||
import pygame
|
||||
|
||||
class Terrain_Obstacle:
|
||||
def __init__(self, x, y, type , image):
|
||||
self.x = x - 1
|
||||
self.y = y - 1
|
||||
self.type = type
|
||||
self.image = image
|
||||
|
||||
def draw(self, screen, 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))
|
||||
|
||||
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)
|