Project rename and restructure

This commit is contained in:
Eden Kirin
2023-03-25 13:21:07 +01:00
commit 0041b7d43e
21 changed files with 1328 additions and 0 deletions

View File

111
hopper/models/board.py Normal file
View File

@ -0,0 +1,111 @@
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),
)

29
hopper/models/config.py Normal file
View File

@ -0,0 +1,29 @@
from dataclasses import dataclass
from typing import Optional
@dataclass
class BoardSettings:
WIDTH: int = 21
HEIGHT: int = 21
OBSTACLE_COUNT: int = 10
@dataclass
class InactivityWatchdogSettings:
INACIVITY_TIMEOUT: int = 10 # seconds
KICK_TIMEOUT: int = 60 * 10 # seconds
TICK_INTERVAL: int = 1 # seconds
@dataclass
class DebugSettings:
PRINT_BOARD: bool = False
CREATE_TEST_PLAYER: bool = False
@dataclass
class Settings:
board: BoardSettings
inacivity_watchdog: InactivityWatchdogSettings
debug: Optional[DebugSettings] = None

34
hopper/models/player.py Normal file
View File

@ -0,0 +1,34 @@
import datetime
import uuid
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class Position:
x: int
y: int
@dataclass
class Player:
name: str
uuid: str = field(default_factory=lambda: str(uuid.uuid4()))
position: Position = field(default_factory=lambda: Position(0, 0))
move_count: int = 0
move_attempt_count: int = 0
last_seen: datetime.datetime = field(
default_factory=lambda: datetime.datetime.now()
)
active: bool = True
def reset_timeout(self) -> None:
self.last_seen = datetime.datetime.now()
class PlayerList(list[Player]):
def find(self, uuid: str) -> Optional[Player]:
for player in self:
if player.uuid == uuid:
return player
return None