import { Agent, type Connection, type WSMessage } from "agents";
import type { GeneratedEnv } from "@ayjnt/env";
type Piece = { color: "w" | "b"; type: "K" | "Q" | "R" | "B" | "N" | "P" };
type State = {
board: (Piece | null)[];
toMove: "w" | "b";
white: string | null; black: string | null;
whiteName: string | null; blackName: string | null;
history: { from: number; to: number; san: string }[];
result: "white" | "black" | "draw" | null;
};
export default class MatchAgent extends Agent<GeneratedEnv, State> {
override initialState: State = freshState();
override async onConnect(conn: Connection) { conn.setState({ name: null }); }
override async onMessage(conn: Connection, message: WSMessage) {
if (typeof message !== "string") return;
const frame = JSON.parse(message);
if (frame.kind === "join") { /* bind seat by connection id */ }
if (frame.kind === "move" && !this.state.result) {
const side = sideOf(conn.id, this.state);
if (!side || side !== this.state.toMove) return; // wrong turn
const check = validateMove(this.state.board, frame.from, frame.to, side);
if (!check.ok) return; // illegal
const piece = this.state.board[frame.from]!;
const capture = this.state.board[frame.to];
const board = [...this.state.board];
board[frame.to] = piece; board[frame.from] = null;
this.setState({ ...this.state, board,
toMove: side === "w" ? "b" : "w",
history: [...this.state.history, { from: frame.from, to: frame.to, san: square(frame.to) }],
result: capture?.type === "K" ? (side === "w" ? "white" : "black") : null });
}
}
override async onClose(conn: Connection) { /* open the seat if this was a player */ }
override async onRequest() { return Response.json({ instance: this.name, ...this.state }); }
}
function freshState(): State { /* 32 pieces in starting position */ return {} as State; }
function sideOf(id: string, s: State) { return id === s.white ? "w" : id === s.black ? "b" : null; }
function validateMove(board: any, from: number, to: number, side: "w"|"b") { return { ok: true }; }
function square(i: number) { return "abcdefgh"[i % 8] + String(8 - Math.floor(i / 8)); }