// "Parse" FEN: just return untransformed string data
parseFen(fen) {
- const fenParts = fen.split(" ");
- let res = {
- position: fenParts[0],
- turn: fenParts[1],
- movesCount: fenParts[2]
+ const [position, turn, movesCount, extraData] = fen.split(" ");
+ return {
+ position,
+ turn,
+ movesCount,
+ ...(extraData ? JSON.parse(extraData) : {})
};
- if (fenParts.length > 3)
- res = Object.assign(res, JSON.parse(fenParts[3]));
- return res;
}
// Return current fen (game state)
r = chessboard.getBoundingClientRect();
pieceWidth = this.getPieceWidth(r.width);
const cd = this.idToCoords(e.target.id);
- if (cd) {
+ const [x, y] = Object.values(cd || {x: -1, y: -1});
+ if (cd && this.canIplay(x, y)) {
const move_s = this.doClick(cd);
if (move_s) {
if (Array.isArray(move_s)) //8-pieces (at least.. only?)
this.buildMoveStack(move_s, r);
}
else if (!this.clickOnly) {
- const [x, y] = Object.values(cd);
if (typeof x != "number")
startPiece = this.r_pieces[x][y];
else
startPiece = this.g_pieces[x][y];
- if (startPiece && this.canIplay(x, y)) {
+ if (startPiece) {
e.preventDefault();
start = cd;
curPiece = startPiece.cloneNode();
genRandInitBaseFen() {
let fen = "";
- if (this.freefill)
+ if (this.options.freefill)
fen = "9/".repeat(8) + "9";
else if (this.options["randomness"] == 0) {
fen = "2Bb5/1BbBb4/1bBbBbB2/1BbBbBbBb/BbBb1bBbB/" +
}
doClick(coords) {
- if (!this.freefill || this.board[coords.x][coords.y] != "")
+ if (!this.options.freefill || this.board[coords.x][coords.y] != "")
return null;
return new Move({
start: {x: coords.x, y: coords.y},
getPotentialMovesFrom([x, y]) {
const height = this.board[x][y].charCodeAt(1) - 97;
- if (height == 5)
+ if (
+ height == 5
+ ||
+ (
+ this.options.freefill &&
+ this.board.some(row => row.some(sq => sq == ""))
+ )
+ ) {
return [];
+ }
let moves = [];
for (let s of this.pieces(this.turn, x, y)['b'].both[0].steps) {
const [i, j] = [x + s[0], y + s[1]];
let towersCount = {w: 0, b: 0};
for (let i = 0; i < this.size.x; i++) {
for (let j = 0; j < this.size.y; j++) {
+ if (this.board[i][j] == "")
+ return "*"; //freefill
if (this.board[i][j] != "") {
if (this.getPotentialMovesFrom([i, j]).length > 0)
return '*';
);
}
- get onlyClick() {
+ get clickOnly() {
return this.movesCount <= 1;
}
);
}
+ static get ReserveArray() {
+ return ['r', 'n', 'b', 'q'];
+ }
+
initReserves(reserveStr) {
- super.initReserves(reserveStr, ['r', 'n', 'b', 'q']);
+ super.initReserves(reserveStr, V.ReserveArray);
}
setOtherVariables(fenParsed) {
case 0:
return i == this.captureUndef.x && j == this.captureUndef.y;
case 1:
- return this.getPiece(i, j) == 'u' && c == this.getColor(i, j);
+ return (
+ this.board[i][j] != "" &&
+ this.getPiece(i, j) == 'u' &&
+ c == this.getColor(i, j)
+ );
}
return false; //never reached
}
return false;
}
+ resetReserve(move, computeNext) {
+ const variety = (c) => {
+ return (
+ [...new Set(
+ Array.prototype.concat.apply([],
+ this.board.map(row =>
+ row.filter(cell =>
+ cell.charAt(0) == c && !['p', 'k'].includes(cell.charAt(1))
+ ).map(cell => cell.charAt(1))
+ )
+ )
+ )].length >= 2
+ );
+ };
+ let next;
+ if (computeNext) {
+ next = {start: move.end, end: move.end, vanish: [], appear: []};
+ this.playOnBoard(move);
+ }
+ const twoOrMorePieces = {w: variety('w'), b: variety('b')};
+ const resetCols =
+ Object.keys(twoOrMorePieces).filter(k => twoOrMorePieces[k]);
+ if (resetCols.length >= 1) {
+ for (let i=0; i<this.size.x; i++) {
+ for (let j=0; j<this.size.y; j++) {
+ if (this.board[i][j] == "")
+ continue;
+ const colIJ = this.getColor(i, j);
+ const pieceIJ = this.getPiece(i, j);
+ if (resetCols.includes(colIJ) && !['p', 'k', 'u'].includes(pieceIJ))
+ {
+ if (computeNext) {
+ // NOTE: could also use a "flip" strategy similar to Benedict
+ next.vanish.push(new PiPo({c: colIJ, p: pieceIJ, x: i, y: j}));
+ next.appear.push(new PiPo({c: colIJ, p: 'u', x: i, y: j}));
+ }
+ this.reserve[colIJ][pieceIJ]++;
+ }
+ }
+ }
+ super.re_drawReserve(resetCols);
+ }
+ if (computeNext) {
+ this.undoOnBoard(move);
+ if (next.vanish.length >= 1) {
+ next.reset = true;
+ move.next = next;
+ }
+ }
+ }
+
+ prePlay(move) {
+ super.prePlay(move);
+ if (move.reset && move.vanish[0].c != this.playerColor)
+ this.resetReserve(move);
+ }
+
postPlay(move) {
const color = this.turn;
if (this.movesCount <= 1 || move.reset || move.next) {
computeNextMove(move) {
if (
- !this.definition || this.playerColor != this.turn ||
- this.board.some(row => row.some(cell =>
- cell.charAt(0) == this.turn && cell.charAt(1) == 'u'))
+ this.definition && this.playerColor == this.turn &&
+ this.board.every(row => row.every(cell => {
+ return (
+ cell == "" || cell.charAt(0) != this.turn || cell.charAt(1) != 'u');
+ }))
) {
- return;
- }
- const variety = (c) => {
- return (
- [...new Set(
- Array.prototype.concat.apply([],
- this.board.map(row =>
- row.filter(cell =>
- cell.charAt(0) == c && !['p', 'k'].includes(cell.charAt(1))
- ).map(cell => cell.charAt(1))
- )
- )
- )].length >= 2
- );
- };
- let next = {start: move.end, end: move.end, vanish: [], appear: []};
- this.playOnBoard(move);
- const twoOrMorePieces = {w: variety('w'), b: variety('b')};
- const resetCols =
- Object.keys(twoOrMorePieces).filter(k => twoOrMorePieces[k]);
- if (resetCols.length >= 1) {
- for (let i=0; i<this.size.x; i++) {
- for (let j=0; j<this.size.y; j++) {
- const colIJ = this.getColor(i, j);
- const pieceIJ = this.getPiece(i, j);
- if (
- resetCols.includes(colIJ) &&
- this.board[i][j] != "" &&
- !['p', 'k', 'u'].includes(pieceIJ)
- ) {
- // NOTE: could also use a "flip" strategy similar to Benedict
- next.vanish.push(new PiPo({c: colIJ, p: pieceIJ, x: i, y: j}));
- next.appear.push(new PiPo({c: colIJ, p: 'u', x: i, y: j}));
- this.reserve[colIJ][pieceIJ]++;
- }
- }
- }
- super.re_drawReserve(resetCols);
- }
- this.undoOnBoard(move);
- if (next.vanish.length >= 1) {
- next.reset = true;
- move.next = next;
+ this.resetReserve(move, true);
}
}