Merge pull request 'bfs' (#19) from bfs into master

Reviewed-on: #19
This commit is contained in:
Paweł Felcyn 2023-04-22 18:08:26 +02:00
commit 675df76bfe
12 changed files with 214 additions and 27 deletions

View File

@ -3,4 +3,5 @@ from enum import Enum
class AgentActionType (Enum): class AgentActionType (Enum):
MOVE_FORWARD = 0 MOVE_FORWARD = 0
TURN_LEFT = 1 TURN_LEFT = 1
TURN_RIGHT = 2 TURN_RIGHT = 2
UNKNOWN = None

7
agentOrientation.py Normal file
View File

@ -0,0 +1,7 @@
from enum import Enum
class AgentOrientation (Enum):
UP = 0
RIGHT = 1
DOWN = 2
LEFT = 3

10
agentState.py Normal file
View File

@ -0,0 +1,10 @@
from agentOrientation import AgentOrientation
from typing import Tuple
class AgentState:
orientation: AgentOrientation
position: Tuple[int, int]
def __init__(self, position: Tuple[int, int], orientation: AgentOrientation) -> None:
self.orientation = orientation
self.position = position

89
bfs.py Normal file
View File

@ -0,0 +1,89 @@
from agentState import AgentState
from typing import Dict, Tuple
from gridCellType import GridCellType
from agentActionType import AgentActionType
from agentOrientation import AgentOrientation
from queue import Queue
from turnCar import turn_left_orientation, turn_right_orientation
class Succ:
state: AgentState
action: AgentActionType
def __init__(self, state: AgentState, action: AgentActionType) -> None:
self.state = state
self.action = action
def find_path_to_nearest_can(startState: AgentState, grid: Dict[Tuple[int, int], GridCellType]) -> list[AgentActionType]:
q: Queue[list[Succ]] = Queue()
visited: list[AgentState] = []
startStates: list[Succ] = [Succ(startState, AgentActionType.UNKNOWN)]
q.put(startStates)
while not q.empty():
currently_checked = q.get()
visited.append(currently_checked[-1].state)
if is_state_success(currently_checked[-1].state, grid):
return extract_actions(currently_checked)
successors = succ(currently_checked[-1].state)
for s in successors:
already_visited = False
for v in visited:
if v.position[0] == s.state.position[0] and v.position[1] == s.state.position[1] and s.state.orientation == v.orientation:
already_visited = True
break
if already_visited:
continue
if is_state_valid(s.state, grid):
new_list = currently_checked.copy()
new_list.append(s)
q.put(new_list)
return []
def extract_actions(successors: list[Succ]) -> list[AgentActionType]:
output: list[AgentActionType] = []
for s in successors:
if s.action != AgentActionType.UNKNOWN:
output.append(s.action)
return output
def succ(state: AgentState) -> list[Succ]:
result: list[Succ] = []
result.append(Succ(AgentState(state.position, turn_left_orientation(state.orientation)), AgentActionType.TURN_LEFT))
result.append(Succ(AgentState(state.position, turn_right_orientation(state.orientation)), AgentActionType.TURN_RIGHT))
state_succ = move_forward_succ(state)
if state_succ != None:
result.append(move_forward_succ(state))
return result
def move_forward_succ(state: AgentState) -> Succ:
position = get_next_cell(state)
if position == None:
return None
return Succ(AgentState(position, state.orientation), AgentActionType.MOVE_FORWARD)
def get_next_cell(state: AgentState) -> Tuple[int, int]:
if state.orientation == AgentOrientation.UP:
if state.position[1] - 1 < 1:
return None
return (state.position[0], state.position[1] - 1)
if state.orientation == AgentOrientation.DOWN:
if state.position[1] + 1 > 27:
return None
return (state.position[0], state.position[1] + 1)
if state.orientation == AgentOrientation.LEFT:
if state.position[0] - 1 < 1:
return None
return (state.position[0] - 1, state.position[1])
if state.position[0] + 1 > 27:
return None
return (state.position[0] + 1, state.position[1])
def is_state_success(state: AgentState, grid: Dict[Tuple[int, int], GridCellType]) -> bool:
next_cell = get_next_cell(state)
return grid[next_cell] == GridCellType.GARBAGE_CAN
def is_state_valid(state: AgentState, grid: Dict[Tuple[int, int], GridCellType]) -> bool:
return grid[state.position] == GridCellType.STREET_HORIZONTAL or grid[state.position] == GridCellType.STREET_VERTICAL

View File

@ -13,6 +13,7 @@ class GameContext:
_cell_size: int = 30 _cell_size: int = 30
city = None city = None
grid: Dict[Tuple[int, int], GridCellType] = {} grid: Dict[Tuple[int, int], GridCellType] = {}
dust_car = None
def __init__(self) -> None: def __init__(self) -> None:
self._init_grid() self._init_grid()

View File

@ -2,23 +2,4 @@ import pygame
from gameContext import GameContext from gameContext import GameContext
def handle_game_event(event, game_context: GameContext): def handle_game_event(event, game_context: GameContext):
dust_car_movement(event, game_context) pass
return
def dust_car_movement(event, game_context:GameContext):
if event.type != pygame.KEYDOWN:
return
(width, height) = game_context.dust_car_pil.size
if event.key == pygame.K_LEFT:
pygame.draw.rect(game_context.canvas, (0, 0, 0), (game_context.dust_car_position_x, game_context.dust_car_position_y, width, height))
game_context.dust_car_position_x -= game_context.dust_car_speed
elif event.key == pygame.K_RIGHT:
pygame.draw.rect(game_context.canvas, (0, 0, 0), (game_context.dust_car_position_x, game_context.dust_car_position_y, width, height))
game_context.dust_car_position_x += game_context.dust_car_speed
elif event.key == pygame.K_UP:
pygame.draw.rect(game_context.canvas, (0, 0, 0), (game_context.dust_car_position_x, game_context.dust_car_position_y, width, height))
game_context.dust_car_position_y -= game_context.dust_car_speed
elif event.key == pygame.K_DOWN:
pygame.draw.rect(game_context.canvas, (0, 0, 0), (game_context.dust_car_position_x, game_context.dust_car_position_y, width, height))
game_context.dust_car_position_y += game_context.dust_car_speed
game_context.canvas.blit(game_context.dust_car_pygame, (game_context.dust_car_position_x, game_context.dust_car_position_y))

View File

@ -1,6 +1,7 @@
from typing import List, Tuple from typing import List, Tuple
from agentOrientation import AgentOrientation
from garbage import RecognizedGarbage from garbage import RecognizedGarbage
from gameContext import GameContext
class GarbageTruck: class GarbageTruck:
position: Tuple[int, int] position: Tuple[int, int]
@ -9,8 +10,9 @@ class GarbageTruck:
glass: List[RecognizedGarbage] glass: List[RecognizedGarbage]
bio: List[RecognizedGarbage] bio: List[RecognizedGarbage]
mixed: List[RecognizedGarbage] mixed: List[RecognizedGarbage]
truckSpritePath = 'imgs/dust_car.png' orientation: AgentOrientation = AgentOrientation.RIGHT
def __init__(self, position: List[int, int]) -> None:
def __init__(self, position: Tuple[int, int]) -> None:
self.position = position self.position = position
self.paper = [] self.paper = []
self.plastic_and_metal = [] self.plastic_and_metal = []
@ -33,4 +35,16 @@ class GarbageTruck:
self.bio.append(RecognizedGarbage) self.bio.append(RecognizedGarbage)
elif RecognizedGarbage.garbage_type == 5: elif RecognizedGarbage.garbage_type == 5:
self.mixed.append(RecognizedGarbage) self.mixed.append(RecognizedGarbage)
def render(self, game_context: GameContext) -> None:
path = None
if self.orientation == AgentOrientation.LEFT:
path = 'imgs/dust_car_left.png'
elif self.orientation == AgentOrientation.RIGHT:
path = 'imgs/dust_car_right.png'
elif self.orientation == AgentOrientation.UP:
path = 'imgs/dust_car_up.png'
elif self.orientation == AgentOrientation.DOWN:
path = 'imgs/dust_car_down.png'
game_context.render_in_cell(self.position, path)

View File

@ -4,4 +4,5 @@ class GridCellType(Enum):
NOTHING = 0 NOTHING = 0
STREET_VERTICAL = 1 STREET_VERTICAL = 1
STREET_HORIZONTAL = 2 STREET_HORIZONTAL = 2
GARBAGE_CAN = 3 GARBAGE_CAN = 3
VISITED_GARBAGE_CAN = 4

10
main.py
View File

@ -3,6 +3,8 @@ from gameEventHandler import handle_game_event
from gameContext import GameContext from gameContext import GameContext
from startup import startup from startup import startup
from PIL import Image from PIL import Image
from agentActionType import AgentActionType
from movement import move_dust_car
pygame.init() pygame.init()
@ -17,6 +19,14 @@ game_context.dust_car_pygame = pygame.image.frombuffer(dust_car_pil.tobytes(), d
game_context.canvas = canvas game_context.canvas = canvas
startup(game_context) startup(game_context)
# test = [AgentActionType.MOVE_FORWARD, AgentActionType.MOVE_FORWARD, AgentActionType.MOVE_FORWARD,
# AgentActionType.MOVE_FORWARD, AgentActionType.MOVE_FORWARD, AgentActionType.MOVE_FORWARD,
# AgentActionType.MOVE_FORWARD, AgentActionType.TURN_RIGHT, AgentActionType.MOVE_FORWARD,
# AgentActionType.MOVE_FORWARD, AgentActionType.MOVE_FORWARD, AgentActionType.MOVE_FORWARD,
# AgentActionType.MOVE_FORWARD, AgentActionType.MOVE_FORWARD, AgentActionType.MOVE_FORWARD,
# AgentActionType.TURN_LEFT, AgentActionType.MOVE_FORWARD]
# move_dust_car(test, game_context)
exit = False exit = False

48
movement.py Normal file
View File

@ -0,0 +1,48 @@
from agentActionType import AgentActionType
import time
from turnCar import turn_left_orientation, turn_right_orientation
from garbageTruck import GarbageTruck
from typing import Tuple, Dict
from gridCellType import GridCellType
from gameContext import GameContext
from agentOrientation import AgentOrientation
import pygame
def move_dust_car(actions: list[AgentActionType], game_context: GameContext) -> None:
for action in actions:
street_position = game_context.dust_car.position
has_to_render_street = False
if action == AgentActionType.TURN_LEFT:
game_context.dust_car.orientation = turn_left_orientation(game_context.dust_car.orientation)
elif action == AgentActionType.TURN_RIGHT:
game_context.dust_car.orientation = turn_right_orientation(game_context.dust_car.orientation)
elif action == AgentActionType.MOVE_FORWARD:
game_context.dust_car.position = calculate_next_position(game_context.dust_car)
has_to_render_street = True
game_context.dust_car.render(game_context)
if has_to_render_street:
if game_context.grid[street_position] == GridCellType.STREET_HORIZONTAL:
game_context.render_in_cell(street_position, "imgs/street_horizontal.png")
elif game_context.grid[street_position] == GridCellType.STREET_VERTICAL:
game_context.render_in_cell(street_position, "imgs/street_vertical.png")
pygame.display.update()
time.sleep(0.5)
def calculate_next_position(car: GarbageTruck) -> Tuple[int, int]:
if car.orientation == AgentOrientation.UP:
if car.position[1] - 1 < 1:
return None
return (car.position[0], car.position[1] - 1)
if car.orientation == AgentOrientation.DOWN:
if car.position[1] + 1 > 27:
return None
return (car.position[0], car.position[1] + 1)
if car.orientation == AgentOrientation.LEFT:
if car.position[0] - 1 < 1:
return None
return (car.position[0] - 1, car.position[1])
if car.position[0] + 1 > 27:
return None
return (car.position[0] + 1, car.position[1])

View File

@ -4,12 +4,18 @@ from PIL import Image
import pygame import pygame
from typing import Tuple, List from typing import Tuple, List
from street import Street, StreetType from street import Street, StreetType
from garbageTruck import GarbageTruck
def startup(game_context: GameContext): def startup(game_context: GameContext):
render_background(game_context) render_background(game_context)
game_context.city = create_city() game_context.city = create_city()
game_context.city.render_city(game_context) game_context.city.render_city(game_context)
game_context.canvas.blit(game_context.dust_car_pygame, (game_context.dust_car_position_x, game_context.dust_car_position_y)) car = create_dust_car(game_context)
car.render(game_context)
game_context.dust_car = car
def create_dust_car(game_context: GameContext) -> GarbageTruck:
return GarbageTruck((3, 3))
def render_background(game_context: GameContext): def render_background(game_context: GameContext):
bg_img = Image.open("imgs/background.jpg") bg_img = Image.open("imgs/background.jpg")

19
turnCar.py Normal file
View File

@ -0,0 +1,19 @@
from agentOrientation import AgentOrientation
def turn_left_orientation(orientation: AgentOrientation) -> AgentOrientation:
if orientation == AgentOrientation.DOWN:
return AgentOrientation.RIGHT
if orientation == AgentOrientation.LEFT:
return AgentOrientation.DOWN
if orientation == AgentOrientation.UP:
return AgentOrientation.LEFT
return AgentOrientation.UP
def turn_right_orientation(orientation: AgentOrientation) -> AgentOrientation:
if orientation == AgentOrientation.DOWN:
return AgentOrientation.LEFT
if orientation == AgentOrientation.LEFT:
return AgentOrientation.UP
if orientation == AgentOrientation.UP:
return AgentOrientation.RIGHT
return AgentOrientation.DOWN