Code viewer for Mind: Simple AI

// Cloned by Enhanced on 7 Aug 2018 from Mind "Simple AI - Depth 2" by Mathias Bazin 
// Please leave this clone trail here.
 


// Cloned by Mathias Bazin on 1 Aug 2018 from Mind "Cloned Simple AI - Depth 1" by Mathias Bazin 
// Please leave this clone trail here.
 


// Cloned by Mathias Bazin on 1 Aug 2018 from Mind "Cloned Simple AI - Depth 1" by Mathias Bazin 
// Please leave this clone trail here.
 


// Cloned by Mathias Bazin on 1 Aug 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 depth = 2;  //This sets how many moves the opponent's AI will look ahead
                    //when computing its move. Therefore, it influences greatly the 
                    //strength of the opponent.
                    //Its value should be within 1 and 3. If going farther than 3,
                    //the game will take a lot of time to compute, at least on a standard
                    //browser allowing only 1 CPU core per tab.
	
	
    /*The "AI" part starts here */
    
    let positionCount;
    
    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 move = minimaxRoot(depth, game, true);
        
        
	    return move;
	};

	
}