UNPKG

black-horse

Version:

Chess engine built in Javascript using the alpha-beta algorithm

198 lines (171 loc) 6.13 kB
const BaseBoardModel = require('./base-board-model.js'); const MapModel = require('./map-model.js'); const times = require('lodash/times'); const cloneDeep = require('lodash/cloneDeep'); const isUndefined = require('lodash/isUndefined'); const configs = require('../configurations'); const LoggerService = require('../services/logger-service.js'); module.exports = class BoardModel extends BaseBoardModel { constructor() { super(); this.resetBoard(); } resetBoard() { let indexW; let indexH; let piece; let piecesKeys; let arrayLength; /* 64 board ...┌────────────────────────┐ 8 │ r n b q k b n r │ 7 │ p p p p p p p p │ 6 │ . . . . . . . . │ 5 │ . . . . . . . . │ 4 │ . . . . . . . . │ 3 │ . . . . . . . . │ 2 │ P P P P P P P P │ 1 │ R N B Q K B N R │ ...└────────────────────────┘ .....a b c d e f g h */ this.board = times(8, () => new Array(8)); //put all board squares as empty for (indexW = 0; indexW < 8; indexW++) { for (indexH = 0; indexH < 8; indexH++) { this.board[indexH][indexW] = configs.pieces.empty; } } //enPassant flag this.enPassant = false; this.fiftyMoveCounter = 0; this.fullmoveCounter = 0; //castle flags this.castle = []; this.castle[configs.colors.white] = { kingSide: false, queenSide: false, }; this.castle[configs.colors.black] = { kingSide: false, queenSide: false, }; this.color = configs.colors.white; this.kingPosition = []; //initiate the pieces counter with 0 for all the pieces this.piecesCounter = []; piecesKeys = Object.keys(configs.pieces); for (indexW = 0, arrayLength = piecesKeys.length; indexW < arrayLength; indexW++) { piece = configs.pieces[piecesKeys[indexW]]; if (piece !== configs.pieces.empty && piece !== configs.pieces.offBoard) { this.piecesCounter[configs.pieces[piecesKeys[indexW]]] = 0; } } this.pieceMaterial = []; this.pieceMaterial[configs.colors.black] = 0; this.pieceMaterial[configs.colors.white] = 0; this.pawnMaterial = []; this.pawnMaterial[configs.colors.black] = 0; this.pawnMaterial[configs.colors.white] = 0; this.pawnList = []; this.pawnList[configs.colors.black] = new MapModel(); this.pawnList[configs.colors.white] = new MapModel(); this.pieceList = []; this.pieceList[configs.colors.black] = new MapModel(); this.pieceList[configs.colors.white] = new MapModel(); this.capturedPieces = []; this.capturedPieces[configs.colors.white] = []; this.capturedPieces[configs.colors.black] = []; } clone() { return { board: cloneDeep(this.board), castle: cloneDeep(this.castle), pieceMaterial: cloneDeep(this.pieceMaterial), pawnMaterial: cloneDeep(this.pawnMaterial), capturedPieces: cloneDeep(this.capturedPieces), kingPosition: cloneDeep(this.kingPosition), piecesCounter: cloneDeep(this.piecesCounter), hash: this.hash, color: this.color, enPassant: this.enPassant, fiftyMoveCounter: this.fiftyMoveCounter, fullmoveCounter: this.fullmoveCounter, pawnList: cloneDeep(this.pawnList), pieceList: cloneDeep(this.pieceList), }; } rebuild(obj) { this.board = obj.board; this.castle = obj.castle; this.pieceMaterial = obj.pieceMaterial; this.pawnMaterial = obj.pawnMaterial; this.capturedPieces = obj.capturedPieces; this.kingPosition = obj.kingPosition; this.piecesCounter = obj.piecesCounter; this.hash = obj.hash; this.color = obj.color; this.enPassant = obj.enPassant; this.fiftyMoveCounter = obj.fiftyMoveCounter; this.fullmoveCounter = obj.fullmoveCounter; this.pawnList = []; this.pieceList = []; if ( typeof obj.pawnList[configs.colors.black] === 'object' && typeof obj.pawnList[configs.colors.white] === 'object' && typeof obj.pieceList[configs.colors.black] === 'object' && typeof obj.pieceList[configs.colors.white] === 'object' ) { this.pawnList[configs.colors.black] = obj.pawnList[configs.colors.black].clone(); this.pawnList[configs.colors.white] = obj.pawnList[configs.colors.white].clone(); this.pieceList[configs.colors.black] = obj.pieceList[configs.colors.black].clone(); this.pieceList[configs.colors.white] = obj.pieceList[configs.colors.white].clone(); } else { this.pawnList[configs.colors.black] = new MapModel(); this.pawnList[configs.colors.white] = new MapModel(); this.pieceList[configs.colors.black] = new MapModel(); this.pieceList[configs.colors.white] = new MapModel(); this.pawnList[configs.colors.black].rebuild(obj.pawnList[configs.colors.black]); this.pawnList[configs.colors.white].rebuild(obj.pawnList[configs.colors.white]); this.pieceList[configs.colors.black].rebuild(obj.pieceList[configs.colors.black]); this.pieceList[configs.colors.white].rebuild(obj.pieceList[configs.colors.white]); } } traverse(callback) { let indexW; let indexH; if (isUndefined(callback)) { callback = function (row, columm, piece) { LoggerService.log('(' + row + ', ' + columm + ') = ' + piece); }; } for (indexW = 0; indexW < 8; indexW++) { for (indexH = 0; indexH < 8; indexH++) { callback(8 - indexH, indexW + 1, this.board[indexH][indexW]); } } } traversePieces(callback) { if (isUndefined(callback)) { callback = (key, value) => { const { row, column, piece } = value; LoggerService.log('(' + row + ', ' + column + ') = ' + piece); }; } this.pieceList[configs.colors.black].traverse(callback); this.pieceList[configs.colors.white].traverse(callback); } setPiece(row, column, piece) { if (row > 8 || column > 8 || row < 1 || column < 1) { return false; } this.board[8 - row][column - 1] = piece; } getPiece(row, column) { if (row > 8 || column > 8 || row < 1 || column < 1) { return configs.pieces.offBoard; } return this.board[8 - row][column - 1]; } };