feat(engine): board/player constant maps and shared types
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { BOARD_IDS, PLAYERS, PLAYER_BOARDS, PLAYER_COLOR, BOARD_PLAYERS, BOARD_ROTATION } from './boards';
|
||||||
|
|
||||||
|
describe('boards constants', () => {
|
||||||
|
it('lists four boards and four players in turn order', () => {
|
||||||
|
expect(BOARD_IDS).toEqual(['NW', 'NE', 'SW', 'SE']);
|
||||||
|
expect(PLAYERS).toEqual(['N', 'S', 'E', 'W']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('each player controls exactly two boards', () => {
|
||||||
|
for (const p of PLAYERS) expect(PLAYER_BOARDS[p]).toHaveLength(2);
|
||||||
|
expect(PLAYER_BOARDS.N).toEqual(['NW', 'NE']);
|
||||||
|
expect(PLAYER_BOARDS.W).toEqual(['NW', 'SW']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('board players are consistent with player boards', () => {
|
||||||
|
for (const b of BOARD_IDS) {
|
||||||
|
const { w, b: black } = BOARD_PLAYERS[b];
|
||||||
|
expect(PLAYER_BOARDS[w]).toContain(b);
|
||||||
|
expect(PLAYER_BOARDS[black]).toContain(b);
|
||||||
|
expect(PLAYER_COLOR[w]).toBe('w');
|
||||||
|
expect(PLAYER_COLOR[black]).toBe('b');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has a rotation for every board', () => {
|
||||||
|
expect(BOARD_ROTATION).toEqual({ NW: 225, NE: 135, SW: 315, SE: 45 });
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import type { BoardId, Player, Color } from './types';
|
||||||
|
|
||||||
|
export const BOARD_IDS: BoardId[] = ['NW', 'NE', 'SW', 'SE'];
|
||||||
|
|
||||||
|
/** Turn order. */
|
||||||
|
export const PLAYERS: Player[] = ['N', 'S', 'E', 'W'];
|
||||||
|
|
||||||
|
/** The two boards each player controls (order is stable: [boardA, boardB]). */
|
||||||
|
export const PLAYER_BOARDS: Record<Player, [BoardId, BoardId]> = {
|
||||||
|
N: ['NW', 'NE'],
|
||||||
|
S: ['SW', 'SE'],
|
||||||
|
E: ['NE', 'SE'],
|
||||||
|
W: ['NW', 'SW'],
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The colour each player plays on both their boards. */
|
||||||
|
export const PLAYER_COLOR: Record<Player, Color> = {
|
||||||
|
N: 'w', S: 'w', E: 'b', W: 'b',
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The white and black player of each board. */
|
||||||
|
export const BOARD_PLAYERS: Record<BoardId, { w: Player; b: Player }> = {
|
||||||
|
NW: { w: 'N', b: 'W' },
|
||||||
|
NE: { w: 'N', b: 'E' },
|
||||||
|
SW: { w: 'S', b: 'W' },
|
||||||
|
SE: { w: 'S', b: 'E' },
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Compass rotation in degrees for rendering each board (see spec §5.1). */
|
||||||
|
export const BOARD_ROTATION: Record<BoardId, number> = {
|
||||||
|
NW: 225, NE: 135, SW: 315, SE: 45,
|
||||||
|
};
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
export type BoardId = 'NW' | 'NE' | 'SW' | 'SE';
|
||||||
|
export type Player = 'N' | 'S' | 'E' | 'W';
|
||||||
|
export type Color = 'w' | 'b';
|
||||||
|
export type Square = string;
|
||||||
|
export type PromotionPiece = 'q' | 'r' | 'b' | 'n';
|
||||||
|
|
||||||
|
export interface SyncMove {
|
||||||
|
from: Square;
|
||||||
|
to: Square;
|
||||||
|
promotion?: PromotionPiece;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HistoryEntry extends SyncMove {
|
||||||
|
player: Player;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GhostMarker {
|
||||||
|
board: BoardId;
|
||||||
|
square: Square;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PlayerResult = 'win' | 'draw' | 'loss';
|
||||||
|
export type GameResult = Record<Player, PlayerResult>;
|
||||||
|
export type GameState = 'playing' | 'checkmate' | 'stalemate' | 'draw';
|
||||||
|
export type DrawReason = 'stalemate' | 'threefold' | 'fifty-move' | 'manual';
|
||||||
|
|
||||||
|
export interface GameStatus {
|
||||||
|
state: GameState;
|
||||||
|
/** Present when state !== 'playing'. */
|
||||||
|
result?: GameResult;
|
||||||
|
/** Present for a draw/stalemate. */
|
||||||
|
reason?: DrawReason;
|
||||||
|
/** Boards on which the player to move is currently in check. */
|
||||||
|
checks: BoardId[];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user