import { BitBoard } from 'shared/bot/BitBoard.ts' import { isBoardCoordInBounds } from 'shared/board.ts' import type { Cell, SerializedBitBoard } from 'shared/types.ts' import { debug } from '../debug.ts' export class BoardStore { boardSize: number symbols: [string, string] bitBoard: BitBoard constructor(boardSize = 15, symbols: [string, string] = ['X', 'O']) { this.boardSize = boardSize this.symbols = symbols this.bitBoard = BitBoard.empty(boardSize) } get cells(): Map { return this.bitBoard.toMap(this.symbols) } getCell(x: number, y: number): Cell | undefined { return this.bitBoard.getCell(x, y, this.symbols) } setCell(x: number, y: number, cell: Cell): void { debug('BoardStore', 'setCell', { x, y, playerId: cell.playerId, symbol: cell.symbol }) if (!isBoardCoordInBounds(x, y, this.boardSize)) { debug('BoardStore', 'setCell: out of bounds'); return } const player = Number(cell.playerId) if (player !== 0 && player !== 1) { debug('BoardStore', 'setCell: invalid player', player); return } if (this.bitBoard.has(x, y)) { debug('BoardStore', 'setCell: removing existing'); this.bitBoard.remove(x, y) } this.bitBoard.place(x, y, player) } removeCell(x: number, y: number): void { debug('BoardStore', 'removeCell', { x, y }) this.bitBoard.remove(x, y) } clear(): void { debug('BoardStore', 'clear') this.bitBoard.clear() } getCellsInBounds( minX: number, minY: number, maxX: number, maxY: number, ): [string, Cell][] { const result: [string, Cell][] = [] for (const [key, cell] of this.cells) { const [x, y] = key.split(':').map(Number) if (x >= minX && x <= maxX && y >= minY && y <= maxY) { result.push([key, cell]) } } return result } deserialize(data: SerializedBitBoard | Record, symbols = this.symbols): void { debug('BoardStore', 'deserialize', { type: isSerializedBitBoard(data) ? 'bitboard' : 'record', dataSize: Object.keys(data).length }) this.symbols = [symbols[0], symbols[1]] if (isSerializedBitBoard(data)) { this.boardSize = data.boardSize this.bitBoard = BitBoard.deserialize(data) return } this.bitBoard = BitBoard.fromBoard(data, this.boardSize) } setBoardSize(boardSize: number): void { if (this.boardSize === boardSize) return debug('BoardStore', 'setBoardSize', { from: this.boardSize, to: boardSize }) this.boardSize = boardSize this.bitBoard = BitBoard.empty(boardSize) } } function isSerializedBitBoard(data: SerializedBitBoard | Record): data is SerializedBitBoard { return Array.isArray((data as SerializedBitBoard).words) }