0

I have a Javascript class that I need to clone to create the minimax algorithm with Alpha beta pruning in javascript. But when I pass the board object to the minimax function, its supposed to deep copy the board object then make changes, but it makes changes to the original board. Why is it doing this?

var Buddha = function() {

  this.movehistory = 0;
  this.color = "b";
  this.opp = "w";

  this.clone = function(board) {
    return $.extend(true, {}, board)
  }

  this.minimax = function(board, depth, alpha, beta) {
    if(depth === 0 || board.game_over() === true) {
      return [this.eval_board(board), null]
    } else {
      if(board.turn() === "w") {
        var bestmove = null

        var possible_moves = board.moves()
        for (index = 0; index < possible_moves.length; ++index) {
          var new_board = this.clone(board)
          new_board.move(possible_moves[index])

          var mini = this.minimax(new_board, --depth, alpha, beta)
          var score = mini[0];
          var move = mini[1];

          if(score > alpha) {
            alpha = score;
            bestmove = possible_moves[index];
            if(alpha >= beta) {
              break;
            }
          }
        }
        return [alpha, bestmove]
      } else if(board.turn() === "b") {
        var bestmove = null

        var possible_moves = board.moves()
        for (index = 0; index < possible_moves.length; ++index) {
          var new_board = this.clone(board)
          new_board.move(possible_moves[index])

          var mini = this.minimax(new_board, --depth, alpha, beta)
          var score = mini[0];
          var move = mini[1];

          if(score < beta) {
            beta = score;
            bestmove = possible_moves[index];
            if(alpha >= beta) {
              break;
            }
          }
        }
        return [beta, bestmove]
      }
    }
  }

  this.eval_board = function(board) {
    if(board.in_check()) {
      if(board.turn() == this.opp) {
        return Number.POSITIVE_INFINITY;
      } else {
        return Number.NEGATIVE_INFINITY;
      }
    } else if(board.in_checkmate()) {
      if(board.turn() == this.opp) {
        return Number.POSITIVE_INFINITY;
      } else {
        return Number.NEGATIVE_INFINITY;
      }
    } else if(board.in_stalemate()) {
      if(board.turn() == this.opp) {
        return Number.POSITIVE_INFINITY;
      } else {
        return Number.NEGATIVE_INFINITY;
      }
    }
  }

  this.move = function(board) {
    console.log(board.fen());
    var bestmove = this.minimax(this.clone(board), 8, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY) 

    console.log(board.fen());
  }

}

The output of the console log is:

rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
R2r1b2/2q1k1p1/2n4n/2P2Q2/8/8/4K2P/1NBQ1BNR b - - 30 55

My module uses the chess.js api from: https://github.com/jhlywa/chess.js.


Edit: I've narrowed it down to the cloning function not cloning the Chess function correctly. Is it because the Chess function doesn't declare the variables with the this decorator?

TimCPogue
  • 57
  • 2
  • 8
  • It isn't supposed to make a deep copy. It's supposed to behave like all objects, and pass a reference. – cookie monster Mar 07 '14 at 01:31
  • How could I make a deep copy? I don't want to modify the original object. – TimCPogue Mar 07 '14 at 01:33
  • 1
    Take a look at some of the links to the right, under the **Related** heading. – cookie monster Mar 07 '14 at 01:39
  • I have looked at the other answers, and I implemented the best answer in the clone function that uses the jQuery extend function, but its obviously not working. – TimCPogue Mar 07 '14 at 01:45
  • because $.extend doesnt clone anything.If your objects are pure data you can serialize/deserialize them with JSON functions in order to close them. – mpm Mar 07 '14 at 03:27

1 Answers1

0

The chess.js library creates its variables statically. Making it difficult to clone the object. Luckily the Chess object allows a FEN variable to be passed. Allowing me to clone the board like so:

var clonedBoard = new Chess(oldBoard.fen());

This prevents modification to the original board.

TimCPogue
  • 57
  • 2
  • 8