62 lines
1.5 KiB
Python
62 lines
1.5 KiB
Python
|
|
from abc import ABC, abstractmethod
|
||
|
|
from typing import Optional
|
||
|
|
from models import Cell, Maze
|
||
|
|
|
||
|
|
|
||
|
|
class Player:
|
||
|
|
|
||
|
|
def __init__(self, start_cell: Cell):
|
||
|
|
self.current_cell = start_cell
|
||
|
|
|
||
|
|
def move_to(self, new_cell: Cell) -> None:
|
||
|
|
self.current_cell = new_cell
|
||
|
|
|
||
|
|
|
||
|
|
class Command(ABC):
|
||
|
|
|
||
|
|
@abstractmethod
|
||
|
|
def execute(self) -> bool:
|
||
|
|
pass
|
||
|
|
|
||
|
|
@abstractmethod
|
||
|
|
def undo(self) -> None:
|
||
|
|
pass
|
||
|
|
|
||
|
|
|
||
|
|
class MoveCommand(Command):
|
||
|
|
|
||
|
|
def __init__(self, player: Player, maze: Maze, direction: str):
|
||
|
|
self.player = player
|
||
|
|
self.maze = maze
|
||
|
|
self.direction = direction
|
||
|
|
self.previous_cell: Optional[Cell] = None
|
||
|
|
self.new_cell: Optional[Cell] = None
|
||
|
|
|
||
|
|
def _get_target_cell(self) -> Optional[Cell]:
|
||
|
|
x, y = self.player.current_cell.x, self.player.current_cell.y
|
||
|
|
|
||
|
|
if self.direction == 'w':
|
||
|
|
y -= 1
|
||
|
|
elif self.direction == 's':
|
||
|
|
y += 1
|
||
|
|
elif self.direction == 'a':
|
||
|
|
x -= 1
|
||
|
|
elif self.direction == 'd':
|
||
|
|
x += 1
|
||
|
|
else:
|
||
|
|
return None
|
||
|
|
|
||
|
|
return self.maze.get_cell(x, y)
|
||
|
|
|
||
|
|
def execute(self) -> bool:
|
||
|
|
self.previous_cell = self.player.current_cell
|
||
|
|
self.new_cell = self._get_target_cell()
|
||
|
|
|
||
|
|
if self.new_cell and self.new_cell.is_passable():
|
||
|
|
self.player.move_to(self.new_cell)
|
||
|
|
return True
|
||
|
|
return False
|
||
|
|
|
||
|
|
def undo(self) -> None:
|
||
|
|
if self.previous_cell:
|
||
|
|
self.player.move_to(self.previous_cell)
|