import random from copy import copy from dataclasses import dataclass, field from typing import Optional from hopper.enums import ObjectType from hopper.models.player import Player, Position BOARD_DUMP_CHARS: dict[ObjectType, str] = { ObjectType.NONE: "·", ObjectType.OBSTACLE: "✘", ObjectType.PLAYER: "⯧", ObjectType.DESTINATION: "⬤", } @dataclass class LayerObject: type_: ObjectType position: Position @dataclass class Layer: name: Optional[str] = None objects: list[LayerObject] = field(default_factory=list) def get_object_at_position(self, position: Position) -> Optional[LayerObject]: for obj in self.objects: if obj.position == position: return obj return None @dataclass class Destination: position: Position @dataclass class GameBoard: width: int height: int destination: Destination layers: list[Layer] = field(default_factory=list) def dump(self) -> list[list[str]]: board = [ [BOARD_DUMP_CHARS[ObjectType.NONE] for _ in range(self.width)] for _ in range(self.height) ] for layer in self.layers: for obj in layer.objects: board[obj.position.y][obj.position.x] = BOARD_DUMP_CHARS[ ObjectType.OBSTACLE ] board[self.destination.position.y][ self.destination.position.x ] = BOARD_DUMP_CHARS[ObjectType.DESTINATION] return board def get_object_at_position(self, position: Position) -> Optional[LayerObject]: for layer in self.layers: obj = layer.get_object_at_position(position) if obj is not None: return obj return None class BoardLayout: def __init__(self, board: GameBoard, players: list[Player]) -> None: self.board = board self.players = players self.layers = self.__create_layers() def __create_layers(self) -> list[Layer]: layers = copy(self.board.layers) layers.append( Layer( name="destination", objects=[ LayerObject( type_=ObjectType.DESTINATION, position=self.board.destination.position, ), ], ) ) layers.append( Layer( name="players", objects=[ LayerObject( type_=ObjectType.PLAYER, position=player.position, ) for player in self.players ], ) ) return layers def create_random_position(board_width: int, board_height: int) -> Position: return Position( x=random.randint(0, board_width - 1), y=random.randint(0, board_height - 1), )