UNPKG

backgammon

Version:

a clean api for building a backgammon game

165 lines (130 loc) 4.12 kB
import { MovePath } from "./modules/Board"; import { Player, PlayerColor, Players } from "./modules/Player"; import { Dices, SingleDice } from "./modules/Dice"; import { Point } from "./modules/Point"; import { initialPointsState } from "./initialState"; import { unshiftFrom } from "./util"; interface Turn { dices: Dices; player: Player; possibleMoves: MovePath[]; } // interface CompletedTurn extends Turn { // submittedMove: MovePath[]; // } export class Board { // todo make private whatever is possible points = initialPointsState; players: Players; currentTurn: Turn; // private turnsHistory: CompletedTurn[] = []; constructor() { const white = new Player(PlayerColor.white); const black = new Player(PlayerColor.black); const dices = Dices.getStarterDices(); const starter = dices.numbers[0] > dices.numbers[1] ? white : black; this.players = new Players(white, black, starter); this.currentTurn = { player: starter, dices, possibleMoves: this.getAllMovePaths(dices, starter) }; } submitMove(submittedMove: MovePath[]) { // todo validate move. // this.turnsHistory.push({ ...this.currentTurn, submittedMove }); if (submittedMove) { } this.generateNextMove(); } private generateNextMove() { const dices = Dices.roll2Dices(); const player = this.players.toggle(); const possibleMoves = this.getAllMovePaths(dices, player); this.currentTurn = { dices, player, possibleMoves }; // todo test the logic // if (possibleMoves.length === 0) { // this.submitMove([]); // } } PlayerInPrison(player: Player = this.players.current): boolean { return player.prison.checkers.length > 0; } currentPlayerCanBearOff(): boolean { if (this.PlayerInPrison()) { return false; } const points = this.getPlayersPoints(); return points.every( point => point.relativePositionFromHome(this.players.current) <= 6 ); } getPlayersPoints(player: Player = this.players.current) { return this.points.filter(point => point.includesCheckerOf(player)); } score(player: Player) { const playersPoints = this.getPlayersPoints(player); if (this.PlayerInPrison(player)) { playersPoints.push(player.prison); } let totalScore = 0; for (let point of playersPoints) { totalScore += point.relativePositionFromHome(player) * point.checkers.length; } return totalScore; } getTargetPoint( point: Point, dice: SingleDice, player: Player ): Point | undefined { const position = player.color === PlayerColor.white ? Math.max(point.position - dice, player.home.position) : Math.min(point.position + dice, player.home.position); return Point.getPointRefByPosition( position as Point["position"], this.points ); } getMovePathsForPoint(point: Point, dices: Dices, player: Player): MovePath[] { const pointPaths: MovePath[] = []; const LoopDices = (dices: SingleDice[]): void => { const movePath: MovePath = []; let distance = 0; let lastPoint = point; for (let dice of dices) { const target = this.getTargetPoint(point, distance + dice, player); if (!target || !target.isAvailableFor(player)) { break; } movePath.push({ from: lastPoint, to: target, uses: dice }); distance += dice; lastPoint = target; } if (movePath.length > 0) { pointPaths.push(movePath); } }; dices.numbers.forEach(dice => { LoopDices(unshiftFrom(dices.numbers, dice)); }); return pointPaths; } getAllMovePaths( dices: Dices, player: Player = this.players.current ): MovePath[] { // todo check if in prison const allMovePaths: MovePath[] = []; const points = this.getPlayersPoints(player); for (let point of points) { const moves = this.getMovePathsForPoint(point, dices, player); if (moves.length > 0) { allMovePaths.push(...moves); } } return allMovePaths; } }