X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=www%2Fjs%2Fchess.js;h=4598758205ed2173b1bf75fe59129ed2b572fed1;hb=HEAD;hp=a0e3813c8e4ceea1e5c9d4c7cd0c78dacacdeb08;hpb=af810b27bbc126ec160cede505313a3a530cdcb4;p=remoteglot
diff --git a/www/js/chess.js b/www/js/chess.js
index a0e3813..4598758 100644
--- a/www/js/chess.js
+++ b/www/js/chess.js
@@ -68,44 +68,6 @@ var Chess = function(fen) {
k: [-17, -16, -15, 1, 17, 16, 15, -1]
};
- var ATTACKS = [
- 20, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0,20, 0,
- 0,20, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0,20, 0, 0,
- 0, 0,20, 0, 0, 0, 0, 24, 0, 0, 0, 0,20, 0, 0, 0,
- 0, 0, 0,20, 0, 0, 0, 24, 0, 0, 0,20, 0, 0, 0, 0,
- 0, 0, 0, 0,20, 0, 0, 24, 0, 0,20, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,20, 2, 24, 2,20, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 2,53, 56, 53, 2, 0, 0, 0, 0, 0, 0,
- 24,24,24,24,24,24,56, 0, 56,24,24,24,24,24,24, 0,
- 0, 0, 0, 0, 0, 2,53, 56, 53, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,20, 2, 24, 2,20, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,20, 0, 0, 24, 0, 0,20, 0, 0, 0, 0, 0,
- 0, 0, 0,20, 0, 0, 0, 24, 0, 0, 0,20, 0, 0, 0, 0,
- 0, 0,20, 0, 0, 0, 0, 24, 0, 0, 0, 0,20, 0, 0, 0,
- 0,20, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0,20, 0, 0,
- 20, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0,20
- ];
-
- var RAYS = [
- 17, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 15, 0,
- 0, 17, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 15, 0, 0,
- 0, 0, 17, 0, 0, 0, 0, 16, 0, 0, 0, 0, 15, 0, 0, 0,
- 0, 0, 0, 17, 0, 0, 0, 16, 0, 0, 0, 15, 0, 0, 0, 0,
- 0, 0, 0, 0, 17, 0, 0, 16, 0, 0, 15, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 17, 0, 16, 0, 15, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 17, 16, 15, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1,-1, -1, -1, -1, 0,
- 0, 0, 0, 0, 0, 0,-15,-16,-17, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,-15, 0,-16, 0,-17, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,-15, 0, 0,-16, 0, 0,-17, 0, 0, 0, 0, 0,
- 0, 0, 0,-15, 0, 0, 0,-16, 0, 0, 0,-17, 0, 0, 0, 0,
- 0, 0,-15, 0, 0, 0, 0,-16, 0, 0, 0, 0,-17, 0, 0, 0,
- 0,-15, 0, 0, 0, 0, 0,-16, 0, 0, 0, 0, 0,-17, 0, 0,
- -15, 0, 0, 0, 0, 0, 0,-16, 0, 0, 0, 0, 0, 0,-17
- ];
-
- var SHIFTS = { p: 0, n: 1, b: 2, r: 3, q: 4, k: 5 };
-
var FLAGS = {
NORMAL: 'n',
CAPTURE: 'c',
@@ -166,11 +128,7 @@ var Chess = function(fen) {
load(fen);
}
- function clear(keep_headers) {
- if (typeof keep_headers === 'undefined') {
- keep_headers = false;
- }
-
+ function clear() {
board = new Array(128);
kings = {w: EMPTY, b: EMPTY};
turn = WHITE;
@@ -179,7 +137,7 @@ var Chess = function(fen) {
half_moves = 0;
move_number = 1;
history = [];
- if (!keep_headers) header = {};
+ header = {};
update_setup(generate_fen());
}
@@ -187,11 +145,7 @@ var Chess = function(fen) {
load(DEFAULT_POSITION);
}
- function load(fen, keep_headers) {
- if (typeof keep_headers === 'undefined') {
- keep_headers = false;
- }
-
+ function load(fen) {
var tokens = fen.split(/\s+/);
var position = tokens[0];
var square = 0;
@@ -200,7 +154,7 @@ var Chess = function(fen) {
return false;
}
- clear(keep_headers);
+ clear();
for (var i = 0; i < position.length; i++) {
var piece = position.charAt(i);
@@ -242,7 +196,7 @@ var Chess = function(fen) {
var i, flag;
if (white_frc_columns !== null) {
for (i = 0; i < white_frc_columns.length; ++i) {
- var sq = SQUARES.a1 + (white_frc_columns[0].charCodeAt(0) - "A".charCodeAt(0));
+ var sq = SQUARES.a1 + (white_frc_columns[i].charCodeAt(0) - "A".charCodeAt(0));
flag = sq < kings[WHITE] ? BITS.QSIDE_CASTLE : BITS.KSIDE_CASTLE;
castling.w |= flag;
rooks[WHITE].push({square: sq, flag: flag});
@@ -270,7 +224,7 @@ var Chess = function(fen) {
var black_frc_columns = tokens[2].match(/[a-h]/g);
if (black_frc_columns !== null) {
for (i = 0; i < black_frc_columns.length; ++i) {
- var sq = SQUARES.a1 + (black_frc_columns[0].charCodeAt(0) - "A".charCodeAt(0));
+ var sq = SQUARES.a8 + (black_frc_columns[i].charCodeAt(0) - "a".charCodeAt(0));
flag = sq < kings[BLACK] ? BITS.QSIDE_CASTLE : BITS.KSIDE_CASTLE;
castling.b |= flag;
rooks[BLACK].push({square: sq, flag: flag});
@@ -708,6 +662,10 @@ var Chess = function(fen) {
}
}
+ return possibly_filter_moves(moves, us, legal);
+ }
+
+ function possibly_filter_moves(moves, us, legal) {
/* return all pseudo-legal moves (this includes moves that allow the king
* to be captured)
*/
@@ -820,40 +778,71 @@ var Chess = function(fen) {
}
function attacked(color, square) {
- for (var i = SQUARES.a8; i <= SQUARES.h1; i++) {
- /* did we run off the end of the board */
- if (i & 0x88) { i += 7; continue; }
+ // Check for attacks by the king.
+ if (Math.abs(rank(kings[color]) - rank(square)) <= 1 &&
+ Math.abs(file(kings[color]) - file(square)) <= 1) {
+ return true;
+ }
- /* if empty square or wrong color */
- if (board[i] == null || board[i].color !== color) continue;
+ // Check for attacks by knights.
+ for (const offset of PIECE_OFFSETS[KNIGHT]) {
+ let knight_sq = square + offset;
+ if (knight_sq & 0x88) continue;
- var piece = board[i];
- var difference = i - square;
- var index = difference + 119;
+ if (board[knight_sq] != null &&
+ board[knight_sq].type === KNIGHT &&
+ board[knight_sq].color === color) {
+ return true;
+ }
+ }
- if (ATTACKS[index] & (1 << SHIFTS[piece.type])) {
- if (piece.type === PAWN) {
- if (difference > 0) {
- if (piece.color === WHITE) return true;
- } else {
- if (piece.color === BLACK) return true;
+ // Check for attacks by pawns.
+ const p1sq = square - PAWN_OFFSETS[color][2];
+ const p2sq = square - PAWN_OFFSETS[color][3];
+ if (!(p1sq & 0x88) &&
+ board[p1sq] != null &&
+ board[p1sq].type === PAWN &&
+ board[p1sq].color === color) {
+ return true;
+ }
+ if (!(p2sq & 0x88) &&
+ board[p2sq] != null &&
+ board[p2sq].type === PAWN &&
+ board[p2sq].color === color) {
+ return true;
+ }
+
+ // Check for attacks by rooks (where queens count as rooks).
+ for (const offset of PIECE_OFFSETS[ROOK]) {
+ let rook_sq = square;
+ while (true) {
+ rook_sq += offset;
+ if (rook_sq & 0x88) break;
+
+ if (board[rook_sq] != null) {
+ if ((board[rook_sq].type === ROOK || board[rook_sq].type === QUEEN) &&
+ board[rook_sq].color === color) {
+ return true;
}
- continue;
+ break;
}
+ }
+ }
- /* if the piece is a knight or a king */
- if (piece.type === 'n' || piece.type === 'k') return true;
-
- var offset = RAYS[index];
- var j = i + offset;
+ // And similarly for attacks by bishops (where queens count as bishops).
+ for (const offset of PIECE_OFFSETS[BISHOP]) {
+ let bishop_sq = square;
+ while (true) {
+ bishop_sq += offset;
+ if (bishop_sq & 0x88) break;
- var blocked = false;
- while (j !== square) {
- if (board[j] != null) { blocked = true; break; }
- j += offset;
+ if (board[bishop_sq] != null) {
+ if ((board[bishop_sq].type === BISHOP || board[bishop_sq].type === QUEEN) &&
+ board[bishop_sq].color === color) {
+ return true;
+ }
+ break;
}
-
- if (!blocked) return true;
}
}
@@ -1114,12 +1103,24 @@ var Chess = function(fen) {
/* this function is used to uniquely identify ambiguous moves */
function get_disambiguator(move, sloppy) {
- var moves = generate_moves({legal: !sloppy});
-
var from = move.from;
var to = move.to;
var piece = move.piece;
+ if (piece === 'p' || piece === 'k') {
+ // Pawn or king moves are never ambiguous.
+ return '';
+ }
+
+ let moves = find_attacking_moves(move.to, piece, move.color);
+ if (moves.length <= 1) {
+ // There can be no ambiguity, so don't bother checking legality
+ // (we assume the move has already been found legal).
+ return '';
+ }
+
+ moves = possibly_filter_moves(moves, move.color, !sloppy);
+
var ambiguities = 0;
var same_rank = 0;
var same_file = 0;
@@ -1167,6 +1168,42 @@ var Chess = function(fen) {
return '';
}
+ // Find all pseudolegal moves featuring the given piece moving to
+ // the given square (using symmetry of all non-pawn-or-castle moves,
+ // we simply generate moves backwards). Does not support pawns.
+ // Assumes there's not already a piece of our own color
+ // on the destination square.
+ function find_attacking_moves(to, piece, us) {
+ let moves = [];
+
+ function add_move(board, moves, from, to, flags, rook_sq) {
+ moves.push(build_move(board, from, to, flags, undefined, rook_sq));
+ }
+ for (let offset of PIECE_OFFSETS[piece]) {
+ var square = to;
+
+ while (true) {
+ square += offset;
+ if (square & 0x88) break;
+
+ if (board[square] != null) {
+ if (board[square].color !== us || board[square].type !== piece) break;
+ if (board[to] == null) {
+ add_move(board, moves, square, to, BITS.NORMAL);
+ } else {
+ add_move(board, moves, square, to, BITS.CAPTURE);
+ }
+ break;
+ }
+
+ /* break if knight or king */
+ if (piece === 'n' || piece === 'k') break;
+ }
+ }
+
+ return moves;
+ }
+
function ascii() {
var s = ' +------------------------+\n';
for (var i = SQUARES.a8; i <= SQUARES.h1; i++) {
@@ -1214,7 +1251,23 @@ var Chess = function(fen) {
}
}
- var moves = generate_moves();
+ let moves;
+ let piece_matches = clean_move.match(/^([NBRQK])x?([a-h][1-8])$/);
+ if (piece_matches) {
+ // Only look for moves by the given piece to the given square.
+ let to = SQUARES[piece_matches[2]];
+ if (board[to] != null && board[to].color === turn) {
+ // Cannot capture our own piece.
+ return null;
+ }
+ moves = find_attacking_moves(to, piece_matches[1].toLowerCase(), turn);
+ // Legal moves only.
+ moves = possibly_filter_moves(moves, turn, true);
+ } else {
+ // Fallback (also used for pawns): Any (legal) moves.
+ moves = generate_moves();
+ }
+
for (var i = 0, len = moves.length; i < len; i++) {
// try the strict parser first, then the sloppy parser if requested
// by the user
@@ -1356,9 +1409,9 @@ var Chess = function(fen) {
return load(fen);
},
- reset: function() {
- return reset();
- },
+ // reset: function() {
+ // return reset();
+ // },
moves: function(options) {
/* The internal representation of a chess move is in 0x88 format, and
@@ -1386,32 +1439,32 @@ var Chess = function(fen) {
return moves;
},
- in_check: function() {
- return in_check();
- },
+ // in_check: function() {
+ // return in_check();
+ // },
- in_checkmate: function() {
- return in_checkmate();
- },
+ // in_checkmate: function() {
+ // return in_checkmate();
+ // },
- in_stalemate: function() {
- return in_stalemate();
- },
+ // in_stalemate: function() {
+ // return in_stalemate();
+ // },
- in_draw: function() {
- return half_moves >= 100 ||
- in_stalemate() ||
- insufficient_material() ||
- in_threefold_repetition();
- },
+ // in_draw: function() {
+ // return half_moves >= 100 ||
+ // in_stalemate() ||
+ // insufficient_material() ||
+ // in_threefold_repetition();
+ // },
- insufficient_material: function() {
- return insufficient_material();
- },
+ // insufficient_material: function() {
+ // return insufficient_material();
+ // },
- in_threefold_repetition: function() {
- return in_threefold_repetition();
- },
+ // in_threefold_repetition: function() {
+ // return in_threefold_repetition();
+ // },
game_over: function() {
return half_moves >= 100 ||
@@ -1421,263 +1474,263 @@ var Chess = function(fen) {
in_threefold_repetition();
},
- validate_fen: function(fen) {
- return validate_fen(fen);
- },
+ // validate_fen: function(fen) {
+ // return validate_fen(fen);
+ // },
fen: function() {
return generate_fen();
},
- board: function() {
- var output = [],
- row = [];
-
- for (var i = SQUARES.a8; i <= SQUARES.h1; i++) {
- if (board[i] == null) {
- row.push(null)
- } else {
- row.push({type: board[i].type, color: board[i].color})
- }
- if ((i + 1) & 0x88) {
- output.push(row);
- row = []
- i += 8;
- }
- }
-
- return output;
- },
-
- pgn: function(options) {
- /* using the specification from http://www.chessclub.com/help/PGN-spec
- * example for html usage: .pgn({ max_width: 72, newline_char: "
" })
- */
- var newline = (typeof options === 'object' &&
- typeof options.newline_char === 'string') ?
- options.newline_char : '\n';
- var max_width = (typeof options === 'object' &&
- typeof options.max_width === 'number') ?
- options.max_width : 0;
- var result = [];
- var header_exists = false;
-
- /* add the PGN header headerrmation */
- for (var i in header) {
- /* TODO: order of enumerated properties in header object is not
- * guaranteed, see ECMA-262 spec (section 12.6.4)
- */
- result.push('[' + i + ' \"' + header[i] + '\"]' + newline);
- header_exists = true;
- }
-
- if (header_exists && history.length) {
- result.push(newline);
- }
-
- /* pop all of history onto reversed_history */
- var reversed_history = [];
- while (history.length > 0) {
- reversed_history.push(undo_move());
- }
-
- var moves = [];
- var move_string = '';
-
- /* build the list of moves. a move_string looks like: "3. e3 e6" */
- while (reversed_history.length > 0) {
- var move = reversed_history.pop();
-
- /* if the position started with black to move, start PGN with 1. ... */
- if (!history.length && move.color === 'b') {
- move_string = move_number + '. ...';
- } else if (move.color === 'w') {
- /* store the previous generated move_string if we have one */
- if (move_string.length) {
- moves.push(move_string);
- }
- move_string = move_number + '.';
- }
-
- move_string = move_string + ' ' + move_to_san(move, false);
- make_move(move);
- }
-
- /* are there any other leftover moves? */
- if (move_string.length) {
- moves.push(move_string);
- }
-
- /* is there a result? */
- if (typeof header.Result !== 'undefined') {
- moves.push(header.Result);
- }
-
- /* history should be back to what is was before we started generating PGN,
- * so join together moves
- */
- if (max_width === 0) {
- return result.join('') + moves.join(' ');
- }
-
- /* wrap the PGN output at max_width */
- var current_width = 0;
- for (var i = 0; i < moves.length; i++) {
- /* if the current move will push past max_width */
- if (current_width + moves[i].length > max_width && i !== 0) {
-
- /* don't end the line with whitespace */
- if (result[result.length - 1] === ' ') {
- result.pop();
- }
-
- result.push(newline);
- current_width = 0;
- } else if (i !== 0) {
- result.push(' ');
- current_width++;
- }
- result.push(moves[i]);
- current_width += moves[i].length;
- }
-
- return result.join('');
- },
-
- load_pgn: function(pgn, options) {
- // allow the user to specify the sloppy move parser to work around over
- // disambiguation bugs in Fritz and Chessbase
- var sloppy = (typeof options !== 'undefined' && 'sloppy' in options) ?
- options.sloppy : false;
-
- function mask(str) {
- return str.replace(/\\/g, '\\');
- }
-
- function has_keys(object) {
- for (var key in object) {
- return true;
- }
- return false;
- }
-
- function parse_pgn_header(header, options) {
- var newline_char = (typeof options === 'object' &&
- typeof options.newline_char === 'string') ?
- options.newline_char : '\r?\n';
- var header_obj = {};
- var headers = header.split(new RegExp(mask(newline_char)));
- var key = '';
- var value = '';
-
- for (var i = 0; i < headers.length; i++) {
- key = headers[i].replace(/^\[([A-Z][A-Za-z]*)\s.*\]$/, '$1');
- value = headers[i].replace(/^\[[A-Za-z]+\s"(.*)"\]$/, '$1');
- if (trim(key).length > 0) {
- header_obj[key] = value;
- }
- }
-
- return header_obj;
- }
-
- var newline_char = (typeof options === 'object' &&
- typeof options.newline_char === 'string') ?
- options.newline_char : '\r?\n';
- var regex = new RegExp('^(\\[(.|' + mask(newline_char) + ')*\\])' +
- '(' + mask(newline_char) + ')*' +
- '1.(' + mask(newline_char) + '|.)*$', 'g');
-
- /* get header part of the PGN file */
- var header_string = pgn.replace(regex, '$1');
-
- /* no info part given, begins with moves */
- if (header_string[0] !== '[') {
- header_string = '';
- }
-
- reset();
-
- /* parse PGN header */
- var headers = parse_pgn_header(header_string, options);
- for (var key in headers) {
- set_header([key, headers[key]]);
- }
-
- /* load the starting position indicated by [Setup '1'] and
- * [FEN position] */
- if (headers['SetUp'] === '1') {
- if (!(('FEN' in headers) && load(headers['FEN'], true ))) { // second argument to load: don't clear the headers
- return false;
- }
- }
-
- /* delete header to get the moves */
- var ms = pgn.replace(header_string, '').replace(new RegExp(mask(newline_char), 'g'), ' ');
-
- /* delete comments */
- ms = ms.replace(/(\{[^}]+\})+?/g, '');
-
- /* delete recursive annotation variations */
- var rav_regex = /(\([^\(\)]+\))+?/g
- while (rav_regex.test(ms)) {
- ms = ms.replace(rav_regex, '');
- }
-
- /* delete move numbers */
- ms = ms.replace(/\d+\.(\.\.)?/g, '');
-
- /* delete ... indicating black to move */
- ms = ms.replace(/\.\.\./g, '');
-
- /* delete numeric annotation glyphs */
- ms = ms.replace(/\$\d+/g, '');
-
- /* trim and get array of moves */
- var moves = trim(ms).split(new RegExp(/\s+/));
-
- /* delete empty entries */
- moves = moves.join(',').replace(/,,+/g, ',').split(',');
- var move = '';
-
- for (var half_move = 0; half_move < moves.length - 1; half_move++) {
- move = move_from_san(moves[half_move], sloppy);
-
- /* move not possible! (don't clear the board to examine to show the
- * latest valid position)
- */
- if (move == null) {
- return false;
- } else {
- make_move(move);
- }
- }
-
- /* examine last move */
- move = moves[moves.length - 1];
- if (POSSIBLE_RESULTS.indexOf(move) > -1) {
- if (has_keys(header) && typeof header.Result === 'undefined') {
- set_header(['Result', move]);
- }
- }
- else {
- move = move_from_san(move, sloppy);
- if (move == null) {
- return false;
- } else {
- make_move(move);
- }
- }
- return true;
- },
-
- header: function() {
- return set_header(arguments);
- },
-
- ascii: function() {
- return ascii();
- },
+ // board: function() {
+ // var output = [],
+ // row = [];
+
+ // for (var i = SQUARES.a8; i <= SQUARES.h1; i++) {
+ // if (board[i] == null) {
+ // row.push(null)
+ // } else {
+ // row.push({type: board[i].type, color: board[i].color})
+ // }
+ // if ((i + 1) & 0x88) {
+ // output.push(row);
+ // row = []
+ // i += 8;
+ // }
+ // }
+
+ // return output;
+ // },
+
+ // pgn: function(options) {
+ // /* using the specification from http://www.chessclub.com/help/PGN-spec
+ // * example for html usage: .pgn({ max_width: 72, newline_char: "
" })
+ // */
+ // var newline = (typeof options === 'object' &&
+ // typeof options.newline_char === 'string') ?
+ // options.newline_char : '\n';
+ // var max_width = (typeof options === 'object' &&
+ // typeof options.max_width === 'number') ?
+ // options.max_width : 0;
+ // var result = [];
+ // var header_exists = false;
+
+ // /* add the PGN header headerrmation */
+ // for (var i in header) {
+ // /* TODO: order of enumerated properties in header object is not
+ // * guaranteed, see ECMA-262 spec (section 12.6.4)
+ // */
+ // result.push('[' + i + ' \"' + header[i] + '\"]' + newline);
+ // header_exists = true;
+ // }
+
+ // if (header_exists && history.length) {
+ // result.push(newline);
+ // }
+
+ // /* pop all of history onto reversed_history */
+ // var reversed_history = [];
+ // while (history.length > 0) {
+ // reversed_history.push(undo_move());
+ // }
+
+ // var moves = [];
+ // var move_string = '';
+
+ // /* build the list of moves. a move_string looks like: "3. e3 e6" */
+ // while (reversed_history.length > 0) {
+ // var move = reversed_history.pop();
+
+ // /* if the position started with black to move, start PGN with 1. ... */
+ // if (!history.length && move.color === 'b') {
+ // move_string = move_number + '. ...';
+ // } else if (move.color === 'w') {
+ // /* store the previous generated move_string if we have one */
+ // if (move_string.length) {
+ // moves.push(move_string);
+ // }
+ // move_string = move_number + '.';
+ // }
+
+ // move_string = move_string + ' ' + move_to_san(move, false);
+ // make_move(move);
+ // }
+
+ // /* are there any other leftover moves? */
+ // if (move_string.length) {
+ // moves.push(move_string);
+ // }
+
+ // /* is there a result? */
+ // if (typeof header.Result !== 'undefined') {
+ // moves.push(header.Result);
+ // }
+
+ // /* history should be back to what is was before we started generating PGN,
+ // * so join together moves
+ // */
+ // if (max_width === 0) {
+ // return result.join('') + moves.join(' ');
+ // }
+
+ // /* wrap the PGN output at max_width */
+ // var current_width = 0;
+ // for (var i = 0; i < moves.length; i++) {
+ // /* if the current move will push past max_width */
+ // if (current_width + moves[i].length > max_width && i !== 0) {
+
+ // /* don't end the line with whitespace */
+ // if (result[result.length - 1] === ' ') {
+ // result.pop();
+ // }
+
+ // result.push(newline);
+ // current_width = 0;
+ // } else if (i !== 0) {
+ // result.push(' ');
+ // current_width++;
+ // }
+ // result.push(moves[i]);
+ // current_width += moves[i].length;
+ // }
+
+ // return result.join('');
+ // },
+
+ // load_pgn: function(pgn, options) {
+ // // allow the user to specify the sloppy move parser to work around over
+ // // disambiguation bugs in Fritz and Chessbase
+ // var sloppy = (typeof options !== 'undefined' && 'sloppy' in options) ?
+ // options.sloppy : false;
+
+ // function mask(str) {
+ // return str.replace(/\\/g, '\\');
+ // }
+
+ // function has_keys(object) {
+ // for (var key in object) {
+ // return true;
+ // }
+ // return false;
+ // }
+
+ // function parse_pgn_header(header, options) {
+ // var newline_char = (typeof options === 'object' &&
+ // typeof options.newline_char === 'string') ?
+ // options.newline_char : '\r?\n';
+ // var header_obj = {};
+ // var headers = header.split(new RegExp(mask(newline_char)));
+ // var key = '';
+ // var value = '';
+
+ // for (var i = 0; i < headers.length; i++) {
+ // key = headers[i].replace(/^\[([A-Z][A-Za-z]*)\s.*\]$/, '$1');
+ // value = headers[i].replace(/^\[[A-Za-z]+\s"(.*)"\]$/, '$1');
+ // if (trim(key).length > 0) {
+ // header_obj[key] = value;
+ // }
+ // }
+
+ // return header_obj;
+ // }
+
+ // var newline_char = (typeof options === 'object' &&
+ // typeof options.newline_char === 'string') ?
+ // options.newline_char : '\r?\n';
+ // var regex = new RegExp('^(\\[(.|' + mask(newline_char) + ')*\\])' +
+ // '(' + mask(newline_char) + ')*' +
+ // '1.(' + mask(newline_char) + '|.)*$', 'g');
+
+ // /* get header part of the PGN file */
+ // var header_string = pgn.replace(regex, '$1');
+
+ // /* no info part given, begins with moves */
+ // if (header_string[0] !== '[') {
+ // header_string = '';
+ // }
+
+ // reset();
+
+ // /* parse PGN header */
+ // var headers = parse_pgn_header(header_string, options);
+ // for (var key in headers) {
+ // set_header([key, headers[key]]);
+ // }
+
+ // /* load the starting position indicated by [Setup '1'] and
+ // * [FEN position] */
+ // if (headers['SetUp'] === '1') {
+ // if (!(('FEN' in headers) && load(headers['FEN'], true ))) { // second argument to load: don't clear the headers
+ // return false;
+ // }
+ // }
+
+ // /* delete header to get the moves */
+ // var ms = pgn.replace(header_string, '').replace(new RegExp(mask(newline_char), 'g'), ' ');
+
+ // /* delete comments */
+ // ms = ms.replace(/(\{[^}]+\})+?/g, '');
+
+ // /* delete recursive annotation variations */
+ // var rav_regex = /(\([^\(\)]+\))+?/g
+ // while (rav_regex.test(ms)) {
+ // ms = ms.replace(rav_regex, '');
+ // }
+
+ // /* delete move numbers */
+ // ms = ms.replace(/\d+\.(\.\.)?/g, '');
+
+ // /* delete ... indicating black to move */
+ // ms = ms.replace(/\.\.\./g, '');
+
+ // /* delete numeric annotation glyphs */
+ // ms = ms.replace(/\$\d+/g, '');
+
+ // /* trim and get array of moves */
+ // var moves = trim(ms).split(new RegExp(/\s+/));
+
+ // /* delete empty entries */
+ // moves = moves.join(',').replace(/,,+/g, ',').split(',');
+ // var move = '';
+
+ // for (var half_move = 0; half_move < moves.length - 1; half_move++) {
+ // move = move_from_san(moves[half_move], sloppy);
+
+ // /* move not possible! (don't clear the board to examine to show the
+ // * latest valid position)
+ // */
+ // if (move == null) {
+ // return false;
+ // } else {
+ // make_move(move);
+ // }
+ // }
+
+ // /* examine last move */
+ // move = moves[moves.length - 1];
+ // if (POSSIBLE_RESULTS.indexOf(move) > -1) {
+ // if (has_keys(header) && typeof header.Result === 'undefined') {
+ // set_header(['Result', move]);
+ // }
+ // }
+ // else {
+ // move = move_from_san(move, sloppy);
+ // if (move == null) {
+ // return false;
+ // } else {
+ // make_move(move);
+ // }
+ // }
+ // return true;
+ // },
+
+ // header: function() {
+ // return set_header(arguments);
+ // },
+
+ // ascii: function() {
+ // return ascii();
+ // },
turn: function() {
return turn;
@@ -1742,30 +1795,30 @@ var Chess = function(fen) {
return clear();
},
- put: function(piece, square) {
- return put(piece, square);
- },
+ // put: function(piece, square) {
+ // return put(piece, square);
+ // },
- get: function(square) {
- return get(square);
- },
+ // get: function(square) {
+ // return get(square);
+ // },
- remove: function(square) {
- return remove(square);
- },
+ // remove: function(square) {
+ // return remove(square);
+ // },
- perft: function(depth) {
- return perft(depth);
- },
+ // perft: function(depth) {
+ // return perft(depth);
+ // },
- square_color: function(square) {
- if (square in SQUARES) {
- var sq_0x88 = SQUARES[square];
- return ((rank(sq_0x88) + file(sq_0x88)) % 2 === 0) ? 'light' : 'dark';
- }
+ // square_color: function(square) {
+ // if (square in SQUARES) {
+ // var sq_0x88 = SQUARES[square];
+ // return ((rank(sq_0x88) + file(sq_0x88)) % 2 === 0) ? 'light' : 'dark';
+ // }
- return null;
- },
+ // return null;
+ // },
history: function(options) {
var reversed_history = [];