Files
codexPySnake/server/model.py
Vladyslav Doloman 7a5f2d8794 Server: implement JOIN/JOIN_ACK/JOIN_DENY handling, input parsing/relay, spawn logic, apples maintenance; fix InMemoryTransport to address specific peer; add state_full encoder
- Protocol: join parser, join_ack/deny builders, input parser, state_full builder
- Server: on_datagram dispatch, spawn per rules (prefer length 3 else 1), join deny if no cell, immediate input_broadcast relay
- Model: occupancy map and helpers
- Transport: deliver to specified peer in in-memory mode
2025-10-07 20:22:22 +03:00

56 lines
1.4 KiB
Python

from __future__ import annotations
from dataclasses import dataclass, field
from typing import Deque, Dict, List, Optional, Tuple
from collections import deque
from .protocol import Direction
Coord = Tuple[int, int]
@dataclass
class Snake:
snake_id: int
head: Coord
direction: Direction
body: Deque[Coord] = field(default_factory=deque) # includes head at index 0
@property
def length(self) -> int:
return len(self.body)
@dataclass
class PlayerSession:
player_id: int
name: str
color_id: int
peer: object # transport-specific handle
input_seq: int = 0
@dataclass
class GameState:
width: int
height: int
snakes: Dict[int, Snake] = field(default_factory=dict)
apples: List[Coord] = field(default_factory=list)
tick: int = 0
occupancy: Dict[Coord, Tuple[int, int]] = field(default_factory=dict) # cell -> (snake_id, index)
def in_bounds(self, x: int, y: int) -> bool:
return 0 <= x < self.width and 0 <= y < self.height
def cell_free(self, x: int, y: int) -> bool:
return (x, y) not in self.occupancy
def occupy_snake(self, snake: Snake) -> None:
for idx, (cx, cy) in enumerate(snake.body):
self.occupancy[(cx, cy)] = (snake.snake_id, idx)
def clear_snake(self, snake: Snake) -> None:
for (cx, cy) in list(snake.body):
self.occupancy.pop((cx, cy), None)