297 lines
12 KiB
Python
297 lines
12 KiB
Python
import pygame
|
|
from collections import deque
|
|
from classes.cell import Cell
|
|
import prefs
|
|
import heapq
|
|
|
|
class Agent:
|
|
def __init__(self, x, y, cells, baseScore=0):
|
|
self.sprite = pygame.image.load("sprites/BartenderNew64.png").convert_alpha()
|
|
self.sprite = pygame.transform.scale(self.sprite, (prefs.CELL_SIZE, prefs.CELL_SIZE))
|
|
self.current_cell = cells[x][y]
|
|
self.moved=False
|
|
self.last_move_time = pygame.time.get_ticks()
|
|
self.last_interact_time = pygame.time.get_ticks()
|
|
self.last_update_time = pygame.time.get_ticks()
|
|
self.cells = cells
|
|
self.score = baseScore
|
|
self.multiplier = 1
|
|
self.direction = 0
|
|
self.directionPOM = 0
|
|
self.xPOM = x
|
|
self.yPOM = y
|
|
self.g_scores = {}
|
|
|
|
self.textures = [
|
|
pygame.image.load("sprites/BartenderNew64.png").convert_alpha(),
|
|
pygame.image.load("sprites/AgentLewo.png").convert_alpha(),
|
|
pygame.image.load("sprites/AgentTyl.png").convert_alpha(),
|
|
pygame.image.load("sprites/AgentPrawo.png").convert_alpha()
|
|
]
|
|
|
|
def move_up(self):
|
|
if pygame.time.get_ticks()-self.last_move_time > 125 and self.current_cell.Y > 0 and not self.cells[self.current_cell.X][self.current_cell.Y-1].blocking_movement:
|
|
self.current_cell = self.cells[self.current_cell.X][self.current_cell.Y-1]
|
|
self.moved=True
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
|
|
def move_down(self):
|
|
if pygame.time.get_ticks()-self.last_move_time > 125 and self.current_cell.Y < prefs.GRID_SIZE-1 and not self.cells[self.current_cell.X][self.current_cell.Y+1].blocking_movement:
|
|
self.current_cell = self.cells[self.current_cell.X][self.current_cell.Y+1]
|
|
self.moved=True
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
|
|
def move_left(self):
|
|
if pygame.time.get_ticks()-self.last_move_time > 125 and self.current_cell.X > 0 and not self.cells[self.current_cell.X-1][self.current_cell.Y].blocking_movement:
|
|
self.current_cell = self.cells[self.current_cell.X-1][self.current_cell.Y]
|
|
self.moved=True
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
|
|
def move_right(self):
|
|
if pygame.time.get_ticks()-self.last_move_time > 125 and self.current_cell.X < prefs.GRID_SIZE-1 and not self.cells[self.current_cell.X+1][self.current_cell.Y].blocking_movement:
|
|
self.current_cell = self.cells[self.current_cell.X+1][self.current_cell.Y]
|
|
self.moved=True
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
|
|
def update(self, surface):
|
|
surface.blit(self.sprite, (self.current_cell.X * prefs.CELL_SIZE,
|
|
self.current_cell.Y * prefs.CELL_SIZE))
|
|
|
|
current_update_time = pygame.time.get_ticks()
|
|
# różnca czasu między wyoływaniami, używa do uniezależnienia od ilości wywołań funkcji
|
|
delta_time = ((current_update_time - self.last_update_time)/1000)
|
|
self.increase_multiplier(-(1 / 16) * delta_time)
|
|
|
|
|
|
|
|
self.last_update_time = current_update_time
|
|
|
|
def increase_score(self, amount):
|
|
self.score += amount * round(self.multiplier,2)
|
|
print("Agent score changed from {} to {} (multiplied by {}!)".format(self.score - amount, self.score, round(self.multiplier,2)))
|
|
|
|
def increase_multiplier(self, amount):
|
|
self.multiplier += amount
|
|
if self.multiplier > 2:
|
|
self.multiplier = 2
|
|
print("Agent score changed from {} to {}".format(self.multiplier , self.multiplier + amount if self.multiplier + amount <= 2 else 2))
|
|
return
|
|
if self.multiplier < 1:
|
|
self.multiplier = 1
|
|
|
|
def moveto(self,x,y):
|
|
if not self.cells[x][y].blocking_movement:
|
|
self.current_cell = self.cells[x][y]
|
|
self.moved=True
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
print("Agent moved to x,y: ",x,y)
|
|
else:
|
|
print("Agent cannot move to this direction")
|
|
|
|
|
|
def bfs(self, start, target, cells):
|
|
queue = deque([(start,[])])
|
|
visited = set()
|
|
|
|
while queue:
|
|
current, path = queue.popleft()
|
|
if current==target:
|
|
return path + [current]
|
|
|
|
if current in visited:
|
|
continue
|
|
|
|
visited.add(current)
|
|
|
|
for neighbor in self.get_neighbors(current, cells):
|
|
queue.append((neighbor, path + [current]))
|
|
|
|
return None
|
|
|
|
def get_neighbors(self, cell, cells):
|
|
neighbors = []
|
|
x, y = cell.X, cell.Y
|
|
if x > 0 and not cells[x-1][y].blocking_movement:
|
|
neighbors.append(cells[x-1][y])
|
|
if x < prefs.GRID_SIZE - 1 and not cells[x+1][y].blocking_movement:
|
|
neighbors.append(cells[x+1][y])
|
|
if y > 0 and not cells[x][y-1].blocking_movement:
|
|
neighbors.append(cells[x][y-1])
|
|
if y < prefs.GRID_SIZE - 1 and not cells[x][y+1].blocking_movement:
|
|
neighbors.append(cells[x][y+1])
|
|
|
|
return neighbors
|
|
|
|
#oddaje tablice punktow jako sciezke agenta
|
|
def convert_to_coordinates(self, shortest_path):
|
|
coordinates = [(cell.X, cell.Y) for cell in shortest_path]
|
|
return coordinates
|
|
|
|
#Wyjmuje pierwsze koordynaty do ruszenia agenta a potem usuwa go z listy
|
|
def pop_first_coordinates(self, coordinates):
|
|
if coordinates:
|
|
x, y = coordinates.pop(0)
|
|
return x, y
|
|
else:
|
|
print("Lista współrzędnych jest pusta.")
|
|
return None, None
|
|
|
|
|
|
#Funkcja pomocnicza dla watku bo chcemy zeby agent poruszal sie ale zeby to normalnie wygladalo
|
|
def sciezkaAgenta(self, agent, path):
|
|
x,y = self.pop_first_coordinates(path)
|
|
if x is not None and y is not None:
|
|
agent.moveto(x,y)
|
|
|
|
|
|
def rotate_left(self):
|
|
if pygame.time.get_ticks()-self.last_move_time > 125:
|
|
self.direction +=1
|
|
if self.direction==4:
|
|
self.direction=0
|
|
self.sprite = self.textures[self.direction]
|
|
self.sprite = pygame.transform.scale(self.sprite, (prefs.CELL_SIZE, prefs.CELL_SIZE))
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
print(self.direction)
|
|
|
|
def rotate_right(self):
|
|
if pygame.time.get_ticks()-self.last_move_time > 125:
|
|
self.direction-=1
|
|
if self.direction==-1:
|
|
self.direction=3
|
|
self.sprite = self.textures[self.direction]
|
|
self.sprite = pygame.transform.scale(self.sprite, (prefs.CELL_SIZE, prefs.CELL_SIZE))
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
print(self.direction)
|
|
|
|
|
|
def move_direction(self):
|
|
if self.direction == 0 and pygame.time.get_ticks()-self.last_move_time > 125 and self.current_cell.Y < prefs.GRID_SIZE-1 and not self.cells[self.current_cell.X][self.current_cell.Y+1].blocking_movement:
|
|
self.current_cell = self.cells[self.current_cell.X][self.current_cell.Y+1]
|
|
self.moved=True
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
if self.direction == 1 and pygame.time.get_ticks()-self.last_move_time > 125 and self.current_cell.X > 0 and not self.cells[self.current_cell.X-1][self.current_cell.Y].blocking_movement:
|
|
self.current_cell = self.cells[self.current_cell.X-1][self.current_cell.Y]
|
|
self.moved=True
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
|
|
if self.direction == 2 and pygame.time.get_ticks()-self.last_move_time > 125 and self.current_cell.Y > 0 and not self.cells[self.current_cell.X][self.current_cell.Y-1].blocking_movement:
|
|
self.current_cell = self.cells[self.current_cell.X][self.current_cell.Y-1]
|
|
self.moved=True
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
|
|
if self.direction == 3 and pygame.time.get_ticks()-self.last_move_time > 125 and self.current_cell.X < prefs.GRID_SIZE-1 and not self.cells[self.current_cell.X+1][self.current_cell.Y].blocking_movement:
|
|
self.current_cell = self.cells[self.current_cell.X+1][self.current_cell.Y]
|
|
self.moved=True
|
|
self.last_move_time=pygame.time.get_ticks()
|
|
|
|
|
|
|
|
def get_possible_moves(self):
|
|
possible_moves = []
|
|
|
|
if self.directionPOM == 0: # Patrzy w dół
|
|
possible_moves.append((0, 'left'))
|
|
possible_moves.append((0, 'right'))
|
|
if self.yPOM < prefs.GRID_SIZE - 1 and not self.cells[self.xPOM][self.yPOM + 1].blocking_movement:
|
|
possible_moves.append((self.directionPOM, 'forward'))
|
|
elif self.directionPOM == 1: # Patrzy w lewo
|
|
possible_moves.append((1, 'left'))
|
|
possible_moves.append((1, 'right'))
|
|
if self.xPOM > 0 and not self.cells[self.xPOM - 1][self.yPOM].blocking_movement:
|
|
possible_moves.append((self.directionPOM, 'forward'))
|
|
elif self.directionPOM == 2: # Patrzy w górę
|
|
possible_moves.append((2, 'left'))
|
|
possible_moves.append((2, 'right'))
|
|
if self.yPOM > 0 and not self.cells[self.xPOM][self.yPOM - 1].blocking_movement:
|
|
possible_moves.append((self.directionPOM, 'forward'))
|
|
elif self.directionPOM == 3: # Patrzy w prawo
|
|
possible_moves.append((3, 'left'))
|
|
possible_moves.append((3, 'right'))
|
|
if self.xPOM < prefs.GRID_SIZE - 1 and not self.cells[self.xPOM + 1][self.yPOM].blocking_movement:
|
|
possible_moves.append((self.directionPOM, 'forward'))
|
|
|
|
return possible_moves
|
|
|
|
def calculate_priority(self, el):
|
|
return el[0]
|
|
|
|
def bfs2(self, target_x, target_y):
|
|
visited = set()
|
|
self.directionPOM = self.direction
|
|
start_state = (self.current_cell.X, self.current_cell.Y, self.directionPOM)
|
|
#print(start_state)
|
|
queue = []
|
|
heapq.heappush(queue, (0,(start_state, [], 0)))
|
|
while queue:
|
|
_, que = heapq.heappop(queue)
|
|
state, actions, gscore = que
|
|
self.xPOM, self.yPOM, self.directionPOM = state
|
|
if self.xPOM == target_x and self.yPOM == target_y:
|
|
return actions
|
|
|
|
if (self.xPOM, self.yPOM, self.directionPOM) in visited:
|
|
continue
|
|
|
|
visited.add((self.xPOM, self.yPOM, self.directionPOM))
|
|
|
|
possible_moves = self.get_possible_moves()
|
|
for new_direction, action in possible_moves:
|
|
new_x, new_y = self.xPOM, self.yPOM
|
|
new_actions = actions + [action]
|
|
|
|
if action == 'left':
|
|
new_direction = (self.directionPOM + 1) % 4
|
|
elif action == 'right':
|
|
new_direction = (self.directionPOM - 1) % 4
|
|
else: # forward
|
|
if self.directionPOM == 0:
|
|
new_y += 1
|
|
elif self.directionPOM == 1:
|
|
new_x -= 1
|
|
elif self.directionPOM == 2:
|
|
new_y -= 1
|
|
else: # direction == 3
|
|
new_x += 1
|
|
|
|
if 0 <= new_x < prefs.GRID_SIZE and 0 <= new_y < prefs.GRID_SIZE \
|
|
and not self.cells[new_x][new_y].blocking_movement:
|
|
new_state = (new_x, new_y, new_direction)
|
|
|
|
if (action == 'left' or action == 'right') :
|
|
gscore = gscore + 1
|
|
else:
|
|
gscore = gscore + self.cells[new_x][new_y].waga
|
|
|
|
f_score = gscore + self.heuristic((new_x,new_y), (target_x,target_y))
|
|
|
|
heapq.heappush(queue, (f_score, (new_state, new_actions, gscore)))
|
|
|
|
|
|
return []
|
|
|
|
def heuristic(self, current, target):
|
|
# Manhattan distance heuristic
|
|
dx = abs(current[0] - target[0])
|
|
dy = abs(current[1] - target[1])
|
|
return dx + dy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|