+Animate castle by both movements (and generalize? match vanishes with appears?)
+
add variants :
Dark Racing Kings ? Checkered-Teleport ?
return (f.charCodeAt(0) <= 90 ? "w" + f.toLowerCase() : "b" + f);
}
- // Setup the initial random-or-not (asymmetric-or-not) position
genRandInitFen(seed) {
+ Random.setSeed(seed); //may be unused
+ let baseFen = this.genRandInitBaseFen();
+ baseFen.o = Object.assign({init: true}, baseFen.o);
+ const parts = this.getPartFen(baseFen.o);
+ return (
+ baseFen.fen +
+ (Object.keys(parts).length > 0 ? (" " + JSON.stringify(parts)) : "")
+ );
+ }
+
+ // Setup the initial random-or-not (asymmetric-or-not) position
+ genRandInitBaseFen() {
let fen, flags = "0707";
if (!this.options.randomness)
// Deterministic:
else {
// Randomize
- Random.setSeed(seed);
let pieces = {w: new Array(8), b: new Array(8)};
flags = "";
// Shuffle pieces on first (and last rank if randomness == 2)
flags += flags;
break;
}
-
let positions = ArrayFun.range(8);
-
// Get random squares for bishops
let randIndex = 2 * Random.randInt(4);
const bishop1Pos = positions[randIndex];
// Remove chosen squares
positions.splice(Math.max(randIndex, randIndex_tmp), 1);
positions.splice(Math.min(randIndex, randIndex_tmp), 1);
-
// Get random squares for knights
randIndex = Random.randInt(6);
const knight1Pos = positions[randIndex];
randIndex = Random.randInt(5);
const knight2Pos = positions[randIndex];
positions.splice(randIndex, 1);
-
// Get random square for queen
randIndex = Random.randInt(4);
const queenPos = positions[randIndex];
positions.splice(randIndex, 1);
-
// Rooks and king positions are now fixed,
// because of the ordering rook-king-rook
const rook1Pos = positions[0];
const kingPos = positions[1];
const rook2Pos = positions[2];
-
// Finally put the shuffled pieces in the board array
pieces[c][rook1Pos] = "r";
pieces[c][knight1Pos] = "n";
" w 0"
);
}
- // Add turn + flags + enpassant (+ reserve)
- let parts = [];
- if (this.hasFlags)
- parts.push(`"flags":"${flags}"`);
- if (this.hasEnpassant)
- parts.push('"enpassant":"-"');
- if (this.hasReserveFen)
- parts.push('"reserve":"000000000000"');
- if (this.options["crazyhouse"])
- parts.push('"ispawn":"-"');
- if (parts.length >= 1)
- fen += " {" + parts.join(",") + "}";
- return fen;
+ return { fen: fen, o: {flags: flags} };
}
// "Parse" FEN: just return untransformed string data
// Return current fen (game state)
getFen() {
- let fen = (
- this.getPosition() + " " +
- this.getTurnFen() + " " +
- this.movesCount
+ const parts = this.getPartFen({});
+ return (
+ this.getBaseFen() +
+ (Object.keys(parts).length > 0 ? (" " + JSON.stringify(parts)) : "")
);
- let parts = [];
+ }
+
+ getBaseFen() {
+ return this.getPosition() + " " + this.turn + " " + this.movesCount;
+ }
+
+ getPartFen(o) {
+ let parts = {};
if (this.hasFlags)
- parts.push(`"flags":"${this.getFlagsFen()}"`);
+ parts["flags"] = o.init ? o.flags : this.getFlagsFen();
if (this.hasEnpassant)
- parts.push(`"enpassant":"${this.getEnpassantFen()}"`);
+ parts["enpassant"] = o.init ? "-" : this.getEnpassantFen();
if (this.hasReserveFen)
- parts.push(`"reserve":"${this.getReserveFen()}"`);
+ parts["reserve"] = this.getReserveFen(o);
if (this.options["crazyhouse"])
- parts.push(`"ispawn":"${this.getIspawnFen()}"`);
- if (parts.length >= 1)
- fen += " {" + parts.join(",") + "}";
- return fen;
+ parts["ispawn"] = this.getIspawnFen(o);
+ return parts;
}
static FenEmptySquares(count) {
return position;
}
- getTurnFen() {
- return this.turn;
- }
-
// Flags part of the FEN string
getFlagsFen() {
return ["w", "b"].map(c => {
// Enpassant part of the FEN string
getEnpassantFen() {
if (!this.epSquare)
- return "-"; //no en-passant
+ return "-";
return C.CoordsToSquare(this.epSquare);
}
- getReserveFen() {
+ getReserveFen(o) {
+ if (o.init)
+ return "000000000000";
return (
["w","b"].map(c => Object.values(this.reserve[c]).join("")).join("")
);
}
- getIspawnFen() {
+ getIspawnFen(o) {
+ if (o.init)
+ // NOTE: cannot merge because this.ispawn doesn't exist yet
+ return "-";
const squares = Object.keys(this.ispawn);
if (squares.length == 0)
return "-";
if (o.genFenOnly)
// This object will be used only for initial FEN generation
return;
+
+ // Some variables
this.playerColor = o.color;
this.afterPlay = o.afterPlay; //trigger some actions after playing a move
+ this.containerId = o.element;
+ this.isDiagram = o.diagram;
+ this.marks = o.marks;
- // Fen string fully describes the game state
+ // Initializations
if (!o.fen)
o.fen = this.genRandInitFen(o.seed);
this.re_initFromFen(o.fen);
-
- // Graphical (can use variables defined above)
- this.containerId = o.element;
- this.isDiagram = o.diagram;
- this.marks = o.marks;
this.graphicalInit();
}
return board;
}
- genRandInitFen(seed) {
+ genRandInitBaseFen() {
+ let fen = "";
if (this.options["randomness"] == 0)
- return "rbqqbr/tcssct/6/6/TCSSCT/RBQQBR w 0";
-
- Random.setSeed(seed);
-
- const piece2pawn = {
- r: 't',
- q: 's',
- b: 'c'
- };
-
- let pieces = { w: new Array(6), b: new Array(6) };
- // Shuffle pieces on first (and last rank if randomness == 2)
- for (let c of ["w", "b"]) {
- if (c == 'b' && this.options["randomness"] == 1) {
- pieces['b'] = pieces['w'];
- break;
+ fen = "rbqqbr/tcssct/6/6/TCSSCT/RBQQBR w 0";
+ else {
+ const piece2pawn = {
+ r: 't',
+ q: 's',
+ b: 'c'
+ };
+ let pieces = { w: new Array(6), b: new Array(6) };
+ // Shuffle pieces on first (and last rank if randomness == 2)
+ for (let c of ["w", "b"]) {
+ if (c == 'b' && this.options["randomness"] == 1) {
+ pieces['b'] = pieces['w'];
+ break;
+ }
+ let positions = ArrayFun.range(6);
+ // Get random squares for bishops
+ let randIndex = 2 * Random.randInt(3);
+ const bishop1Pos = positions[randIndex];
+ let randIndex_tmp = 2 * Random.randInt(3) + 1;
+ const bishop2Pos = positions[randIndex_tmp];
+ positions.splice(Math.max(randIndex, randIndex_tmp), 1);
+ positions.splice(Math.min(randIndex, randIndex_tmp), 1);
+ // Get random square for queens
+ randIndex = Random.randInt(4);
+ const queen1Pos = positions[randIndex];
+ positions.splice(randIndex, 1);
+ randIndex = Random.randInt(3);
+ const queen2Pos = positions[randIndex];
+ positions.splice(randIndex, 1);
+ // Rooks positions are now fixed,
+ const rook1Pos = positions[0];
+ const rook2Pos = positions[1];
+ pieces[c][rook1Pos] = "r";
+ pieces[c][bishop1Pos] = "b";
+ pieces[c][queen1Pos] = "q";
+ pieces[c][queen2Pos] = "q";
+ pieces[c][bishop2Pos] = "b";
+ pieces[c][rook2Pos] = "r";
}
-
- let positions = ArrayFun.range(6);
-
- // Get random squares for bishops
- let randIndex = 2 * Random.randInt(3);
- const bishop1Pos = positions[randIndex];
- let randIndex_tmp = 2 * Random.randInt(3) + 1;
- const bishop2Pos = positions[randIndex_tmp];
- positions.splice(Math.max(randIndex, randIndex_tmp), 1);
- positions.splice(Math.min(randIndex, randIndex_tmp), 1);
-
- // Get random square for queens
- randIndex = Random.randInt(4);
- const queen1Pos = positions[randIndex];
- positions.splice(randIndex, 1);
- randIndex = Random.randInt(3);
- const queen2Pos = positions[randIndex];
- positions.splice(randIndex, 1);
-
- // Rooks positions are now fixed,
- const rook1Pos = positions[0];
- const rook2Pos = positions[1];
-
- pieces[c][rook1Pos] = "r";
- pieces[c][bishop1Pos] = "b";
- pieces[c][queen1Pos] = "q";
- pieces[c][queen2Pos] = "q";
- pieces[c][bishop2Pos] = "b";
- pieces[c][rook2Pos] = "r";
+ fen = (
+ pieces["b"].join("") + "/" +
+ pieces["b"].map(p => piece2pawn[p]).join("") +
+ "/6/6/" +
+ pieces["w"].map(p => piece2pawn[p].toUpperCase()).join("") + "/" +
+ pieces["w"].join("").toUpperCase() +
+ " w 0"
+ );
}
-
- return (
- pieces["b"].join("") + "/" +
- pieces["b"].map(p => piece2pawn[p]).join("") +
- "/6/6/" +
- pieces["w"].map(p => piece2pawn[p].toUpperCase()).join("") + "/" +
- pieces["w"].join("").toUpperCase() +
- " w 0"
- );
+ return { fen: fen, o: {} };
}
// Triangles are rotated from opponent viewpoint (=> suffix "_inv")
return false;
}
- genRandInitFen(seed) {
- const baseFen = super.genRandInitFen(seed);
- const fen = baseFen.replace("rnbqkbnr/pppppppp", "4k3/8");
- const fenParts = fen.split(" ");
- let others = JSON.parse(fenParts[3]);
- others["flags"] = others["flags"].substr(0, 2) + "88";
- return fenParts.slice(0, 3).join(" ") + " " + JSON.stringify(others);
+ genRandInitBaseFen() {
+ let baseFen = super.genRandInitBaseFen();
+ return { fen: baseFen.fen.replace("rnbqkbnr/pppppppp", "4k3/8"), o: {} };
+ }
+
+ getPartFen(o) {
+ let parts = super.getPartFen(o);
+ parts["flags"] = parts["flags"].substr(0, 2) + "88";
+ return parts;
}
initReserves() {
this.subTurn = 1;
}
- genRandInitFen(seed) {
+ genRandInitBaseFen() {
const options = Object.assign({mode: "suicide"}, this.options);
const gr = new GiveawayRules({options: options, genFenOnly: true});
- return gr.genRandInitFen(seed);
+ return gr.genRandInitBaseFen();
}
canStepOver(x, y) {
.map(m => {
if (m.vanish.length == 1)
m.appear[0].p = V.GOAL;
- else
+ else {
m.appear[0].p = V.TARGET_CODE[m.vanish[1].p];
+ m.appear[0].c = m.vanish[1].c;
+ }
m.vanish.shift();
return m;
})
);
}
// At subTurn == 1, play a targeted move for the opponent.
- // Search for target (we could also have it in a stack...)
+ // Search for target:
let target = {x: -1, y: -1};
outerLoop: for (let i = 0; i < this.size.x; i++) {
for (let j = 0; j < this.size.y; j++) {
return moves;
}
- isKing(symbol) {
- return ['k', 'l'].includes(symbol);
+ isKing(x, y, p) {
+ if (!p)
+ p = this.getPiece(x, y);
+ return ['k', 'l'].includes(p);
}
getCurrentScore() {
return res;
}
- genRandInitFen() {
+ genRandInitBaseFen() {
// Always deterministic setup
- return (
- '2prbkqA/2p1nnbr/2pppppp/8/8/PPPPPP2/RBNN1P2/aQKBRP2 w 0 ' +
- '{"flags":"KAka"}'
- );
+ return {
+ fen: "2prbkqA/2p1nnbr/2pppppp/8/8/PPPPPP2/RBNN1P2/aQKBRP2 w 0",
+ o: {"flags": "KAka"}
+ };
}
// (Anti)King flags at 1 (true) if they can knight-jump
- setFlags(fenFlags) {
+ setFlags(fenflags) {
this.kingFlags = { w: {}, b: {} };
- for (let i=0; i<fenFlags.length; i++) {
- const white = fenFlags.charCodeAt(i) <= 90;
- const curChar = fenFlags.charAt(i).toLowerCase();
+ for (let i=0; i<fenflags.length; i++) {
+ const white = fenflags.charCodeAt(i) <= 90;
+ const curChar = fenflags.charAt(i).toLowerCase();
this.kingFlags[white ? 'w' : 'b'][curChar] = true;
}
}
getFlagsFen() {
return (
Array.prototype.concat.apply(
- ['w', 'b'].map(c => Object.keys(this.kingFlags[c]))
+ ['w', 'b'].map(c => {
+ const res = Object.keys(this.kingFlags[c]).join("");
+ return (c == 'w' ? res.toUpperCase() : res);
+ })
).join("")
);
}
};
}
- genRandInitFen(seed) {
- const baseFen = super.genRandInitFen(seed);
+ genRandInitBaseFen() {
+ const baseFen = super.genRandInitBaseFen();
// Just add an antiking on 3rd ranks
let akPos = [3, 3];
if (this.options.randomness >= 1) {
: "")
);
};
- return (
- baseFen.replace("p/8", "p/" + antikingLine('b'))
- .replace("8/P", antikingLine('w') + "/P")
- );
+ return {
+ fen: baseFen.fen.replace("p/8", "p/" + antikingLine('b'))
+ .replace("8/P", antikingLine('w') + "/P"),
+ o: baseFen.o
+ };
+ }
+
+ getCastleMoves([x, y]) {
+ if (this.getPiece(x, y) == 'a')
+ return [];
+ return super.getCastleMoves([x, y]);
+ }
+
+ updateCastleFlags(move) {
+ if (move.vanish.length > 0 && move.vanish[0].p == 'a')
+ return;
+ super.updateCastleFlags(move);
}
};
--- /dev/null
+import ChessRules from "/base_rules.js";
+
+export class ApocalypseRules extends ChessRules {
+
+ static get Options() {
+ return {};
+ }
+
+ get pawnPromotions() {
+ return ['n', 'p'];
+ }
+
+ get size() {
+ return {x: 5, y: 5};
+ }
+
+ genRandInitBaseFen() {
+ return {
+ fen: "npppn/p3p/5/P3P/NPPPN w 0",
+ o: {"flags":"00"}
+ };
+ }
+
+ getPartFen(o) {
+ let parts = super.getPartFen(o);
+ parts["whiteMove"] = this.whiteMove || "-";
+ return parts;
+ }
+
+ getFlagsFen() {
+ return (
+ this.penaltyFlags['w'].toString() + this.penaltyFlags['b'].toString()
+ );
+ }
+
+ setOtherVariables(fen) {
+ const parsedFen = V.ParseFen(fen);
+ this.setFlags(parsedFen.flags);
+ // Also init whiteMove
+ this.whiteMove =
+ parsedFen.whiteMove != "-"
+ ? JSON.parse(parsedFen.whiteMove)
+ : null;
+ }
+
+ setFlags(fenflags) {
+ this.penaltyFlags = {
+ 'w': parseInt(fenflags[0], 10),
+ 'b': parseInt(fenflags[1], 10)
+ };
+ }
+
+ // TODO: could be a stack of 2 (pawn promote + relocation)
+ getWhitemoveFen() {
+ if (!this.whiteMove) return "-";
+ return JSON.stringify({
+ start: this.whiteMove.start,
+ end: this.whiteMove.end,
+ appear: this.whiteMove.appear,
+ vanish: this.whiteMove.vanish
+ });
+ }
+
+ // allow pawns to move diagonally and capture vertically --> only purpose illegal
+ // allow capture self --> same purpose
+ // ---> MARK such moves : move.illegal = true
+
+ // simpler: allow all moves, including "capturing nothing"
+ // flag every pawn capture as "illegal" (potentially)
+
+ pieces(color, x, y) {
+ const pawnShift = (color == "w" ? -1 : 1);
+ return {
+ 'p': {
+ "class": "pawn",
+ moves: [
+ {
+ steps: [[pawnShift, 0], [pawnShift, -1], [pawnShift, 1]],
+ range: 1
+ }
+ ],
+ },
+ 'n': super.pieces(color, x, y)['n']
+ };
+ }
+
+ canTake() {
+ return true;
+ }
+
+ getPotentialMovesFrom([x, y]) {
+ let moves = [];
+ if (this.subTurn == 2) {
+ const start = this.moveStack[0].end;
+ if (x == start.x && y == start.y) {
+ // Move the pawn to any empty square not on last rank (== x)
+ for (let i=0; i<this.size.x; i++) {
+ if (i == x)
+ continue;
+ for (let j=0; j<this.size.y; j++) {
+ if (this.board[i][j] == "")
+ moves.push(this.getBasicMove([x, y], [i, j]));
+ }
+ }
+ }
+ }
+ else {
+ moves = super.getPotentialMovesFrom([x, y])
+ // Flag a priori illegal moves
+ moves.forEach(m => {
+ if (
+ // Self-capture test:
+ (m.vanish.length == 2 && m.vanish[1].c == m.vanish[0].c) ||
+ // Pawn going diagonaly to empty square, or vertically to occupied
+ (
+ m.vanish[0].p == 'p' &&
+ (
+ (m.end.y == m.start.y && m.vanish.length == 2) ||
+ (m.end.y != m.start.y && m.vanish.length == 1)
+ )
+ )
+ ) {
+ m.illegal = true;
+ }
+ });
+ }
+ return moves;
+ }
+
+ filterValid(moves) {
+ // No checks:
+ return moves;
+ }
+
+ // White and black (partial) moves were played: merge
+ // + animate both at the same time !
+ resolveSynchroneMove(move) {
+ // TODO
+ }
+
+ play(move) {
+ // Do not play on board (would reveal the move...)
+ this.turn = V.GetOppCol(this.turn);
+ this.movesCount++;
+ this.postPlay(move);
+ }
+
+ postPlay(move) {
+ if (pawn promotion into pawn) {
+ this.curMove move; //TODO: animate both move at same time + effects AFTER !
+ this.subTurn = 2
+ }
+ else if (this.turn == 'b')
+ // NOTE: whiteMove is used read-only, so no need to copy
+ this.whiteMove = move;
+ }
+ else {
+ // A full turn just ended:
+ const smove = this.resolveSynchroneMove(move);
+ V.PlayOnBoard(this.board, smove); //----> ici : animate both !
+ this.whiteMove = null;
+ }
+ }
+
+ atLeastOneLegalMove(...) {
+ // TODO
+ }
+
+ getCurrentScore() {
+ if (this.turn == 'b')
+ // Turn (white + black) not over yet. Could be stalemate if black cannot move (legally)
+ // TODO: check. If so, return "1/2".
+ return "*";
+ // Count footmen: if a side has none, it loses
+ let fmCount = { 'w': 0, 'b': 0 };
+ for (let i=0; i<5; i++) {
+ for (let j=0; j<5; j++) {
+ if (this.board[i][j] != V.EMPTY && this.getPiece(i, j) == V.PAWN)
+ fmCount[this.getColor(i, j)]++;
+ }
+ }
+ if (Object.values(fmCount).some(v => v == 0)) {
+ if (fmCount['w'] == 0 && fmCount['b'] == 0)
+ // Everyone died
+ return "1/2";
+ if (fmCount['w'] == 0) return "0-1";
+ return "1-0"; //fmCount['b'] == 0
+ }
+ // Check penaltyFlags: if a side has 2 or more, it loses
+ if (Object.values(this.penaltyFlags).every(v => v == 2)) return "1/2";
+ if (this.penaltyFlags['w'] == 2) return "0-1";
+ if (this.penaltyFlags['b'] == 2) return "1-0";
+ if (!this.atLeastOneLegalMove('w') || !this.atLeastOneLegalMove('b'))
+ // Stalemate (should be very rare)
+ return "1/2";
+ return "*";
+ }
+
+};
);
}
- genRandInitFen(seed) {
+ genRandInitBaseFen() {
const options = Object.assign({mode: "suicide"}, this.options);
const gr = new GiveawayRules({options: options, genFenOnly: true});
- const baseFen = gr.genRandInitFen(seed);
- const fenParts = baseFen.split(" ");
- let others = JSON.parse(fenParts[3]);
- delete others["enpassant"];
- others["flags"] = "1111"; //Peach + Mario flags
- return fenParts.slice(0, 3).join(" ") + " " + JSON.stringify(others);
+ let res = gr.genRandInitBaseFen();
+ res.o["flags"] = "1111"; //Peach + Mario flags
+ return res;
}
fen2board(f) {
return res;
}
- genRandInitFen(seed) {
+ genRandInitBaseFen() {
if (this.options["mode"] == "losers")
- return super.genRandInitFen(seed);
+ return super.genRandInitBaseFen();
- if (this.options["randomness"] == 0) {
- return (
- 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w 0 {"enpassant":"-"}'
- );
- }
-
- Random.setSeed(seed);
- let pieces = { w: new Array(8), b: new Array(8) };
- for (let c of ["w", "b"]) {
- if (c == 'b' && this.options["randomness"] == 1) {
- pieces['b'] = pieces['w'];
- break;
- }
-
- // Get random squares for every piece, totally freely
- let positions = Random.shuffle(ArrayFun.range(8));
- const composition = ['b', 'b', 'r', 'r', 'n', 'n', 'k', 'q'];
- const rem2 = positions[0] % 2;
- if (rem2 == positions[1] % 2) {
- // Fix bishops (on different colors)
- for (let i=2; i<8; i++) {
- if (positions[i] % 2 != rem2) {
- [positions[1], positions[i]] = [positions[i], positions[1]];
- break;
+ let fen = "";
+ if (this.options["randomness"] == 0)
+ fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w 0";
+ else {
+ let pieces = { w: new Array(8), b: new Array(8) };
+ for (let c of ["w", "b"]) {
+ if (c == 'b' && this.options["randomness"] == 1) {
+ pieces['b'] = pieces['w'];
+ break;
+ }
+ // Get random squares for every piece, totally freely
+ let positions = Random.shuffle(ArrayFun.range(8));
+ const composition = ['b', 'b', 'r', 'r', 'n', 'n', 'k', 'q'];
+ const rem2 = positions[0] % 2;
+ if (rem2 == positions[1] % 2) {
+ // Fix bishops (on different colors)
+ for (let i=2; i<8; i++) {
+ if (positions[i] % 2 != rem2) {
+ [positions[1], positions[i]] = [positions[i], positions[1]];
+ break;
+ }
}
}
+ for (let i = 0; i < 8; i++)
+ pieces[c][positions[i]] = composition[i];
}
- for (let i = 0; i < 8; i++)
- pieces[c][positions[i]] = composition[i];
+ fen = (
+ pieces["b"].join("") +
+ "/pppppppp/8/8/8/8/PPPPPPPP/" +
+ pieces["w"].join("").toUpperCase() +
+ " w 0"
+ );
}
- return (
- pieces["b"].join("") +
- "/pppppppp/8/8/8/8/PPPPPPPP/" +
- pieces["w"].join("").toUpperCase() +
- // En-passant allowed, but no flags
- ' w 0 {"enpassant":"-"}'
- );
+ return { fen: fen, o: {} };
}
constructor(o) {
}
getCurrentScore() {
- if (this.atLeastOneMove()) return "*";
+ if (this.atLeastOneMove(this.turn))
+ return "*";
// No valid move: the side who cannot move wins
return (this.turn == "w" ? "1-0" : "0-1");
}
return res;
}
- genRandInitFen() {
+ genRandInitBaseFen() {
// NOTE: size.x == size.y (square boards)
const emptyCount = C.FenEmptySquares(this.size.x);
- return (emptyCount + "/").repeat(this.size.x).slice(0, -1) + " w 0";
+ return {
+ fen: (emptyCount + "/").repeat(this.size.x).slice(0, -1) + " w 0",
+ o: {}
+ };
}
getSvgChessboard() {
get size() {
const baseRatio = 1.6191907514450865; //2801.2 / 1730, "widescreen"
const rc =
- document.getElementById(this.containerid).getBoundingClientRect();
+ document.getElementById(this.containerId).getBoundingClientRect();
const rotate = rc.width < rc.height; //"vertical screen"
return {
x: this.options["bsize"],
return false;
}
- genRandInitFen(seed) {
- return super.genRandInitFen(seed).slice(0, -1) + ',"lastmove":"null"}';
- }
-
- getFen() {
- return (
- super.getFen().slice(0, -1) + ',"lastmove":"' +
- JSON.stringify(this.lastMove) + '"}');
+ getPartFen(o) {
+ let parts = super.getPartFen(o);
+ parts["lastmove"] = o.init ? null : this.lastMove;
+ return parts;
}
setOtherVariables(fenParsed) {
super.postPlay(move);
}
- atLeastOneMove() {
+ atLeastOneMove(color) {
if (!this.lastMove.noRef)
return true;
- return super.atLeastOneMove();
+ return super.atLeastOneMove(color);
}
};
}
}
- genRandInitFen(seed) {
+ genRandInitBaseFen() {
const options = Object.assign({mode: "suicide"}, this.options);
const gr = new GiveawayRules({options: options, genFenOnly: true});
- const baseFen = gr.genRandInitFen(seed);
- // Add empty cmove:
- const fenParts = baseFen.split(" ");
- let others = JSON.parse(fenParts[3]);
- others["cmove"] = "-";
- return fenParts.slice(0, 3).join(" ") + " " + JSON.stringify(others);
+ return gr.genRandInitBaseFen();
}
- getFen() {
- const cmoveFen = !this.cmove
+ getPartFen(o) {
+ let parts = super.getPartFen(o);
+ const cmoveFen = o.init || !this.cmove
? "-"
: C.CoordsToSquare(this.cmove.start) + C.CoordsToSquare(this.cmove.end);
- return super.getFen().slice(0, -1) + ',"cmove":"' + cmoveFen + '"}';
+ parts["cmove"] = cmoveFen;
+ return parts;
}
getBasicMove([sx, sy], [ex, ey]) {
m.vanish.length == 1 || m.vanish[1].p != 'a');
}
- underCheck(squares, color) {
+ underCheck(square_s, color) {
let res = false;
- squares.forEach(sq => {
+ if (!Array.isArray(square_s[0]))
+ square_s = [square_s];
+ square_s.forEach(sq => {
switch (this.getPiece(sq[0], sq[1])) {
case 'k':
res ||= super.underAttack(sq, color);