See raw JS.
// Cloned by Mathias Bazin on 31 Jul 2018 from Mind "Bad AI" by Mathias Bazin // Please leave this clone trail here. // Cloned by Mathias Bazin on 31 Jul 2018 from Mind "Simple AI - Depth 1" by Mathias Bazin // Please leave this clone trail here. // Cloned by Mathias Bazin on 31 Jul 2018 from Mind "Simple AI - Depth 2" by Mathias Bazin // Please leave this clone trail here. // Cloned by Mathias Bazin on 31 Jul 2018 from Mind "Simple AI - Depth 1" by Mathias Bazin // Please leave this clone trail here. // Cloned by Mathias Bazin on 30 Jul 2018 from Mind "First move always" by Mathias Bazin // Please leave this clone trail here. function Mind() { let positionCount; /*The "AI" part starts here */ let minimaxRoot =function(depth, game, isMaximisingPlayer) { let newGameMoves = game.moves(); let bestMove = -9999; let bestMoveFound; for(let i = 0; i < newGameMoves.length; i++) { let newGameMove = newGameMoves[i] game.move(newGameMove); let value = minimax(depth - 1, game, -10000, 10000, !isMaximisingPlayer); game.undo(); if(value >= bestMove) { bestMove = value; bestMoveFound = newGameMove; } } return bestMoveFound; }; let minimax = function (depth, game, alpha, beta, isMaximisingPlayer) { positionCount++; if (depth === 0) { return -evaluateBoard(board(game)); } let newGameMoves = game.moves(); if (isMaximisingPlayer) { let bestMove = -9999; for (let i = 0; i < newGameMoves.length; i++) { game.move(newGameMoves[i]); bestMove = Math.max(bestMove, minimax(depth - 1, game, alpha, beta, !isMaximisingPlayer)); game.undo(); alpha = Math.max(alpha, bestMove); if (beta <= alpha) { return bestMove; } } return bestMove; } else { let bestMove = 9999; for (let i = 0; i < newGameMoves.length; i++) { game.move(newGameMoves[i]); bestMove = Math.min(bestMove, minimax(depth - 1, game, alpha, beta, !isMaximisingPlayer)); game.undo(); beta = Math.min(beta, bestMove); if (beta <= alpha) { return bestMove; } } return bestMove; } }; let evaluateBoard = function (board) { let totalEvaluation = 0; for (let i = 0; i < 8; i++) { for (let j = 0; j < 8; j++) { totalEvaluation = totalEvaluation + getPieceValue(board[i][j], i ,j); } } return totalEvaluation; }; let reverseArray = function(array) { return array.slice().reverse(); }; let pawnEvalWhite = [ [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0], [1.0, 1.0, 2.0, 3.0, 3.0, 2.0, 1.0, 1.0], [0.5, 0.5, 1.0, 2.5, 2.5, 1.0, 0.5, 0.5], [0.0, 0.0, 0.0, 2.0, 2.0, 0.0, 0.0, 0.0], [0.5, -0.5, -1.0, 0.0, 0.0, -1.0, -0.5, 0.5], [0.5, 1.0, 1.0, -2.0, -2.0, 1.0, 1.0, 0.5], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] ]; let pawnEvalBlack = reverseArray(pawnEvalWhite); let knightEval = [ [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0], [-4.0, -2.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0], [-3.0, 0.0, 1.0, 1.5, 1.5, 1.0, 0.0, -3.0], [-3.0, 0.5, 1.5, 2.0, 2.0, 1.5, 0.5, -3.0], [-3.0, 0.0, 1.5, 2.0, 2.0, 1.5, 0.0, -3.0], [-3.0, 0.5, 1.0, 1.5, 1.5, 1.0, 0.5, -3.0], [-4.0, -2.0, 0.0, 0.5, 0.5, 0.0, -2.0, -4.0], [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0] ]; let bishopEvalWhite = [ [ -2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0], [ -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0], [ -1.0, 0.0, 0.5, 1.0, 1.0, 0.5, 0.0, -1.0], [ -1.0, 0.5, 0.5, 1.0, 1.0, 0.5, 0.5, -1.0], [ -1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -1.0], [ -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0], [ -1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, -1.0], [ -2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0] ]; let bishopEvalBlack = reverseArray(bishopEvalWhite); let rookEvalWhite = [ [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [ 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5], [ -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], [ -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], [ -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], [ -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], [ -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], [ 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0] ]; let rookEvalBlack = reverseArray(rookEvalWhite); let evalQueen = [ [ -2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0], [ -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0], [ -1.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, -1.0], [ -0.5, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, -0.5], [ 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, -0.5], [ -1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.0, -1.0], [ -1.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, -1.0], [ -2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0] ]; let kingEvalWhite = [ [ -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0], [ -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0], [ -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0], [ -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0], [ -2.0, -3.0, -3.0, -4.0, -4.0, -3.0, -3.0, -2.0], [ -1.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -1.0], [ 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0 ], [ 2.0, 3.0, 1.0, 0.0, 0.0, 1.0, 3.0, 2.0 ] ]; let kingEvalBlack = reverseArray(kingEvalWhite); let getPieceValue = function (piece, x, y) { if (piece === null) { return 0; } let getAbsoluteValue = function (piece, isWhite, x ,y) { if (piece.type === 'p') { return 10 + ( isWhite ? pawnEvalWhite[y][x] : pawnEvalBlack[y][x] ); } else if (piece.type === 'r') { return 50 + ( isWhite ? rookEvalWhite[y][x] : rookEvalBlack[y][x] ); } else if (piece.type === 'n') { return 30 + knightEval[y][x]; } else if (piece.type === 'b') { return 30 + ( isWhite ? bishopEvalWhite[y][x] : bishopEvalBlack[y][x] ); } else if (piece.type === 'q') { return 90 + evalQueen[y][x]; } else if (piece.type === 'k') { return 900 + ( isWhite ? kingEvalWhite[y][x] : kingEvalBlack[y][x] ); } throw "Unknown piece type: " + piece.type; }; let absoluteValue = getAbsoluteValue(piece, piece.color === 'w', x ,y); return piece.color === 'w' ? absoluteValue : -absoluteValue; }; function board(game) { let letters = ['a','b','c','d','e','f','g','h']; let nbs = ['8','7','6','5','4','3','2','1']; let b = new Array(8); for (let i =0; i<8; i++) { b[i] = new Array(8); for (let j = 0; j <8; j++) { let square = letters[j] + nbs[i]; b[i][j] = game.get(square); } } return b; } function boardToString(b) { let s = ""; for (let i = 0; i<8; i++) { for (let j = 0; j<8; j++) { if (b[i][j] === null) s += " "; else { if (b[i][j].color == 'b') s += b[i][j].type; else s += b[i][j].type.toUpperCase(); } } s += "\n"; } return s; } this.getAction = function ( state ) { let game = new Chess(state); let b = board(game); let move = minimaxRoot(2, game, true); return move; }; }