82 lines
1.9 KiB
Python
82 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Optional, Union
|
|
|
|
|
|
@dataclass
|
|
class HelloServer:
|
|
description: str
|
|
|
|
|
|
@dataclass
|
|
class NewGame:
|
|
player1: str
|
|
player2: str
|
|
|
|
|
|
@dataclass
|
|
class MoveBroadcast:
|
|
square: Optional[int]
|
|
value: int # piece index or 16/17
|
|
|
|
|
|
@dataclass
|
|
class GameOver:
|
|
reason: str # "VICTORY" | "DRAW" | "DISCONNECT"
|
|
winner: Optional[str]
|
|
|
|
|
|
@dataclass
|
|
class UnknownCommand:
|
|
raw: str
|
|
|
|
|
|
ServerMessage = Union[HelloServer, NewGame, MoveBroadcast, GameOver, UnknownCommand]
|
|
|
|
|
|
def parse_server_line(line: str) -> ServerMessage:
|
|
parts = line.strip().split("~")
|
|
if not parts:
|
|
return UnknownCommand(raw=line)
|
|
cmd = parts[0]
|
|
if cmd == "HELLO" and len(parts) == 2:
|
|
return HelloServer(description=parts[1])
|
|
if cmd == "NEWGAME" and len(parts) == 3:
|
|
return NewGame(player1=parts[1], player2=parts[2])
|
|
if cmd == "MOVE":
|
|
if len(parts) == 2:
|
|
try:
|
|
value = int(parts[1])
|
|
except ValueError:
|
|
return UnknownCommand(raw=line)
|
|
return MoveBroadcast(square=None, value=value)
|
|
if len(parts) == 3:
|
|
try:
|
|
square = int(parts[1])
|
|
value = int(parts[2])
|
|
except ValueError:
|
|
return UnknownCommand(raw=line)
|
|
return MoveBroadcast(square=square, value=value)
|
|
if cmd == "GAMEOVER":
|
|
if len(parts) == 2:
|
|
return GameOver(reason=parts[1], winner=None)
|
|
if len(parts) == 3:
|
|
return GameOver(reason=parts[1], winner=parts[2])
|
|
return UnknownCommand(raw=line)
|
|
|
|
|
|
def format_hello(description: str) -> str:
|
|
return f"HELLO~{description}"
|
|
|
|
|
|
def format_queue() -> str:
|
|
return "QUEUE"
|
|
|
|
|
|
def format_move_initial(piece: int) -> str:
|
|
return f"MOVE~{piece}"
|
|
|
|
|
|
def format_move_normal(square: int, m_value: int) -> str:
|
|
return f"MOVE~{square}~{m_value}"
|