73 lines
1.8 KiB
Python
73 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Optional, Union
|
|
|
|
|
|
@dataclass
|
|
class ClientHello:
|
|
description: str
|
|
|
|
|
|
class ClientQueue:
|
|
pass
|
|
|
|
|
|
@dataclass
|
|
class ClientMove:
|
|
square: Optional[int] # None for initial move MOVE~M
|
|
m_value: int # 0-17
|
|
|
|
|
|
@dataclass
|
|
class UnknownCommand:
|
|
raw: str
|
|
|
|
|
|
ClientCommand = Union[ClientHello, ClientQueue, ClientMove, UnknownCommand]
|
|
|
|
|
|
def parse_client_line(line: str) -> ClientCommand:
|
|
parts = line.strip().split("~")
|
|
if not parts:
|
|
return UnknownCommand(raw=line)
|
|
cmd = parts[0]
|
|
if cmd == "HELLO" and len(parts) == 2:
|
|
return ClientHello(description=parts[1])
|
|
if cmd == "QUEUE" and len(parts) == 1:
|
|
return ClientQueue()
|
|
if cmd == "MOVE":
|
|
if len(parts) == 2:
|
|
try:
|
|
m_value = int(parts[1])
|
|
except ValueError:
|
|
return UnknownCommand(raw=line)
|
|
return ClientMove(square=None, m_value=m_value)
|
|
if len(parts) == 3:
|
|
try:
|
|
square = int(parts[1])
|
|
m_value = int(parts[2])
|
|
except ValueError:
|
|
return UnknownCommand(raw=line)
|
|
return ClientMove(square=square, m_value=m_value)
|
|
return UnknownCommand(raw=line)
|
|
|
|
|
|
def format_hello(description: str) -> str:
|
|
return f"HELLO~{description}"
|
|
|
|
|
|
def format_newgame(player1: str, player2: str) -> str:
|
|
return f"NEWGAME~{player1}~{player2}"
|
|
|
|
|
|
def format_move_broadcast(square: Optional[int], m_value: int) -> str:
|
|
if square is None:
|
|
return f"MOVE~{m_value}"
|
|
return f"MOVE~{square}~{m_value}"
|
|
|
|
|
|
def format_gameover(reason: str, winner: Optional[str]) -> str:
|
|
if winner is None:
|
|
return f"GAMEOVER~{reason}"
|
|
return f"GAMEOVER~{reason}~{winner}"
|