UNPKG

@real_one_chess_king/game-logic

Version:
137 lines 5.02 kB
import { Cell } from "../cell"; import { handleKillAffect, handleMoveAffect, handleSpawnAffect, handleTransformAffect, reverseAffects, } from "../affect/affect"; import { buildPieceByMeta } from "../piece/piece-builder"; import { RulesEngine } from "../rules-engine"; /** * Board keeps data about current game position and pieces on the array of cells * It provides methods for manipulation by affects, but not dirrect access to pieces * Always should be filled in by metadata */ export class Board { size = 8; squares; rulesEngine = new RulesEngine(); /** * Metastorage is needed for saving initial data about pieces * It can be used for transformation of pieces */ meta; constructor() { this.squares = this.buildCells(); } buildCells() { return Array.from({ length: this.size }, () => Array.from({ length: this.size }, () => new Cell())); } isIndexValid = (index) => index >= 0 && index < this.size; getMeta() { if (!this.meta) { throw new Error("Board meta is not defined yet"); } return this.meta; } fillBoardByMeta(meta) { this.meta = meta; const { cellsMeta: cells, postMovementRules, movementRules } = meta; this.rulesEngine.addMovementRules(movementRules); this.rulesEngine.addPostMovementRules(postMovementRules); for (let row = 0; row < this.size; row++) { for (let col = 0; col < this.size; col++) { const pieceMetaId = cells[row][col]; if (pieceMetaId) { const cell = this.getCell(col, row); const pieceMeta = meta.pieceMeta.find(({ id }) => id === pieceMetaId); if (!pieceMeta) { throw new Error("Piece meta not found"); } cell.putPiece(buildPieceByMeta(pieceMeta)); } } } } getPiece = (x, y) => { return this.squares[y][x].getPiece(); }; getPieceByCoordinate = (xy) => { return this.squares[xy[1]][xy[0]].getPiece(); }; getCell(x, y) { return this.squares[y][x]; } forEachPiece(color, callback) { this.squares.forEach((row, y) => { row.forEach((cell, x) => { const piece = cell.getPiece(); if (piece && piece.color === color) { callback(piece, x, y); } }); }); } // now [x, y, affects] // to action: affects[]. Affects with user choice marked with field and will be used for tree building // getPieceAvailableMoves(x, y, turns) { const availableMoves = []; const piece = this.getPiece(x, y); if (!piece) { throw new Error("Can not get moves for invalid piece coordinates"); } const { movementRules, postMovementRules } = piece; movementRules.forEach((ruleId) => { const ruleMoves = this.rulesEngine.getAvailableMoves(ruleId, x, y, this.getPiece, turns, this.size); availableMoves.push(...ruleMoves); }); let updatedMoves = availableMoves; postMovementRules?.forEach((ruleId) => { updatedMoves = this.rulesEngine.addPostMovementCorrections(ruleId, updatedMoves, piece.type); }); return updatedMoves; } /** * We keep all killed and removed from the board pieces here. * Transformations are not included. */ killed = []; updateCellsOnMove(affects) { if (!this.meta) { throw new Error("Board meta is not defined yet"); } affects.forEach((affect) => { handleKillAffect(affect, this.squares, this.killed); handleMoveAffect(affect, this.squares); handleTransformAffect(affect, this.squares, this.meta); handleSpawnAffect(affect, this.squares, this.killed); }); } revertMove(affects) { const reversedAffects = reverseAffects(affects); this.updateCellsOnMove(reversedAffects); } duplicatePosition(cells) { this.squares.forEach((row, y) => { row.forEach((cell, x) => { const piece = cell.getPiece(); if (piece) { cells[y][x].putPiece(piece); } else { cells[y][x].popPiece(); } }); }); return cells; } findUniqPiece(color, pieceType) { for (let i = 0; i < this.squares.length; i++) { for (let j = 0; j < this.squares[i].length; j++) { const cell = this.squares[i][j]; const piece = cell.getPiece(); if (piece && piece.color === color && piece.type === pieceType) { return [j, i]; } } } throw new Error(`${pieceType} not found`); } } //# sourceMappingURL=board.js.map