View file game/chekers/js/game.js

File size: 5.55Kb
define('game', ['move', 'piece', 'clone'], function(Move, Piece, clone) {
  function Game() {
    this.player = 1;
    this.selected = null;
    this.moves = [];
  }

  Game.prototype = {
    board: null,
    player: null,
    selected: null,
    moves: null,
    _playerToPieces: null,

    init: function() {
      var board = [];
      var playerToPieces = { '1': [], '-1': [] };
      for (var i = 0; i < 8; i++) {
        var row = [];
        for (var j = 0; j < 8; j++) {
          var piece = null;
          if ((i < 3 || i > 4) && (i % 2 === j % 2)) {
            var player = i > 4 ? 1 : -1;
            piece = new Piece({
              col: j,
              king: false,
              player: player,
              row: i,
              dead: false
            });
            playerToPieces[player].push(piece);
          }

          row.push(piece);
        }

        board.push(row);
      }

      this.board = board;
      this._playerToPieces = playerToPieces;
    },

    move: function(move) {
      var board = this.board;
      var selected = this.selected;

      // Update the board.
      board[selected.row][selected.col] = null;
      board[move.row][move.col] = selected;

      // Update the piece.
      selected.row = move.row;
      selected.col = move.col;
      if (move.row === 0 || move.row === 7) {
        selected.king = true;
      }

      // Remove the captured pieces.
      for (var i = 0; i < move.captures.length; i++) {
        var capture = move.captures[i];
        board[capture.row][capture.col].dead = true;
        board[capture.row][capture.col] = null;
      }

      // Switch player.
      this.alternateTurn();
    },

    alternateTurn: function() {
      // Remove any selections.
      this.select(null);

      this.player = this.player === 1 ? -1 : 1;
    },

    select: function(row, col, dontExpand) {
      var piece = (typeof row === 'number' && typeof col === 'number') ?
        this.board[row][col] : null;
      this.selected = piece;
      this.moves = [];
      if (piece && !dontExpand) {
        this.moves = this.expandMoves(piece);
      }
    },

    expandMoves: function(piece) {
      var moves = [];

      var move = new Move({
        captures: [],
        col: piece.col,
        jump: false,
        row: piece.row,
        start: piece
      });

      var stack = [move];
      while (stack.length > 0) {
        var next = stack.pop();
        var expand = this.expand(next, this.board, piece.player, piece.king);
        expand.forEach(function(found) {
          moves.push(found);
          if (found.jump) {
            stack.push(found);
          }
        });
      }

      return moves;
    },

    expand: function(move, board, player, king) {
      var row = move.row,
          col = move.col;

      var directions = ['ul', 'ur'];
      if (king) {
        directions = directions.concat(['dl', 'dr']);
      }

      var moves = [];
      directions.forEach(function(direction) {
        var slideMove = new Move({ captures: [], jump: false });
        var jumpMove = new Move({ captures: clone(move.captures), jump: true });

        switch (direction) {
          case 'ul':
            slideMove.row = row - player;
            slideMove.col = col - player;
            jumpMove.row = slideMove.row - player;
            jumpMove.col = slideMove.col - player;
            break;
          case 'ur':
            slideMove.row = row - player;
            slideMove.col = col + player;
            jumpMove.row = slideMove.row - player;
            jumpMove.col = slideMove.col + player;
            break;
          case 'dl':
            slideMove.row = row + player;
            slideMove.col = col - player;
            jumpMove.row = slideMove.row + player;
            jumpMove.col = slideMove.col - player;
            break;
          case 'dr':
            slideMove.row = row + player;
            slideMove.col = col + player;
            jumpMove.row = slideMove.row + player;
            jumpMove.col = slideMove.col + player;
            break;
        }

        if (!move.jump &&
            slideMove.inbounds() &&
            !board[slideMove.row][slideMove.col]) {
          // We can still slide.
          return moves.push(slideMove);
        }

        if (jumpMove.inbounds()) {
          var capture = board[slideMove.row][slideMove.col];
          if (capture && capture.player !== player &&
              !board[jumpMove.row][jumpMove.col]) {
            if (move.previous &&
                move.previous.row === jumpMove.row &&
                move.previous.col === jumpMove.col) {
              return;
            }

            jumpMove.captures.push({ row: capture.row, col: capture.col });
            jumpMove.previous = { row: move.row, col: move.col };
            return moves.push(jumpMove);
          }
        }
      });

      return moves;
    },

    // playerToPieces: function(player) {
    //   var pieces = this._playerToPieces[player];
    //   return pieces.filter(function(piece) {
    //     return !!piece && !piece.dead;
    //   });
    // },

    playerToPieces: function(player) {
      var result = { '-1': [], '1': [] };
      this.board.forEach(function(row, i) {
        row.forEach(function(piece, j) {
          if (piece) {
            result[piece.player].push(piece);
          }
        }.bind(this));
      }.bind(this));

      return result[player];
    },

    toString: function() {
      return '\n' + this.board.map(function(row) {
        return row.map(function(piece) {
          return piece ? Math.max(0, piece.player) : 'x';
        }).join(' ');
      }).join('\n');
    }
  };

  return Game;
});