On smartphone for Teleport, Chakart, Weiqi and some others: option "confirm moves on touch screen"
(=> comme pour corr) + option "confirm moves in corr games"?
-Clorange:
-Clockwork Orange Chess (Fergus Duniho,
-1999). https://www.chessvariants.com/other.dir/clockworkorange.html
-implem : pieces code, yellow/red, easy
-
https://www.chessvariants.com/difftaking.dir/replacement.html
https://www.chessvariants.com/other.dir/pocket.html
--- /dev/null
+../Alice/bc.svg
\ No newline at end of file
--- /dev/null
+../Alice/bo.svg
\ No newline at end of file
--- /dev/null
+../Alice/bs.svg
\ No newline at end of file
--- /dev/null
+../Alice/bt.svg
\ No newline at end of file
--- /dev/null
+../Alice/bu.svg
\ No newline at end of file
--- /dev/null
+../Alice/wc.svg
\ No newline at end of file
--- /dev/null
+../Alice/wo.svg
\ No newline at end of file
--- /dev/null
+../Alice/ws.svg
\ No newline at end of file
--- /dev/null
+../Alice/wt.svg
\ No newline at end of file
--- /dev/null
+../Alice/wu.svg
\ No newline at end of file
// 2) Check turn
if (!fenParsed.turn || !V.IsGoodTurn(fenParsed.turn)) return false;
// 3) Check moves count
- if (!fenParsed.movesCount || !(parseInt(fenParsed.movesCount) >= 0))
+ if (!fenParsed.movesCount || !(parseInt(fenParsed.movesCount, 10) >= 0))
return false;
// 4) Check flags
if (V.HasFlags && (!fenParsed.flags || !V.IsGoodFlags(fenParsed.flags)))
if (['K','k'].includes(row[i])) kings[row[i]]++;
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
return {
// NOTE: column is always one char => max 26 columns
// row is counted from black side => subtraction
- x: V.size.x - parseInt(sq.substr(1)),
+ x: V.size.x - parseInt(sq.substr(1), 10),
y: sq[0].charCodeAt() - 97
};
}
let j = 0;
for (let indexInRow = 0; indexInRow < rows[i].length; indexInRow++) {
const character = rows[i][indexInRow];
- const num = parseInt(character);
+ const num = parseInt(character, 10);
// If num is a number, just shift j:
if (!isNaN(num)) j += num;
// Else: something at position i,j
const fenParsed = V.ParseFen(fen);
this.board = V.GetBoard(fenParsed.position);
this.turn = fenParsed.turn;
- this.movesCount = parseInt(fenParsed.movesCount);
+ this.movesCount = parseInt(fenParsed.movesCount, 10);
this.setOtherVariables(fen);
}
this.INIT_COL_KING["w"] = k;
break;
default: {
- const num = parseInt(fenRows[i].charAt(j));
+ const num = parseInt(fenRows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
endgameMessage: "",
orientation: "w",
mode: "",
+ gameMode: "",
score: "*", //'*' means 'unfinished'
moves: [],
cursor: -1, //index of the move just played
}
else {
// Exit analyze mode:
- this.mode = this.gameMode ;
+ this.mode = this.gameMode;
this.cursor = this.gameCursor;
this.moves = this.gameMoves;
let fen = this.game.fenStart;
this.stackToPlay.unshift(move);
return;
}
- this.inPlay = true;
if (this.mode == "analyze") this.toggleAnalyze();
if (this.cursor < this.moves.length - 1)
// To play a received move, cursor must be at the end of the game:
this.gotoEnd();
+ this.inPlay = true;
}
// The board may show some possible moves: (TODO: bad solution)
this.$refs["board"].resetCurrentAttempt();
document.getElementById("adjuster")
.addEventListener("click", processModalClick);
// Take full width on small screens:
- let boardSize = parseInt(localStorage.getItem("boardSize"));
+ let boardSize = parseInt(localStorage.getItem("boardSize"), 10);
if (!boardSize) {
boardSize =
window.innerWidth >= 768
import { extractTime } from "@/utils/timeControl";
export function checkChallenge(c) {
- const vid = parseInt(c.vid);
+ const vid = parseInt(c.vid, 10);
if (isNaN(vid) || vid <= 0) return "Please select a variant";
const tc = extractTime(c.cadence);
export function checkProblem(p) {
- const vid = parseInt(p.vid);
+ const vid = parseInt(p.vid, 10);
if (isNaN(vid) || vid <= 0) return "Please select a variant";
if (!V.IsGoodFen(p.fen)) return "Errors in FEN";
hints: getItemDefaultTrue("hints"),
highlight: getItemDefaultTrue("highlight"),
gotonext: getItemDefaultTrue("gotonext"),
- randomness: parseInt(localStorage.getItem("randomness"))
+ randomness: parseInt(localStorage.getItem("randomness"), 10)
};
if (isNaN(this.state.settings.randomness))
// Default: random asymmetric
p.boxed
- | TODO
+ | Captured pieces can be dropped later in the game,
+ | with or without capturing abilities.
+
+p Orthodox rules apply, with the following exceptions:
+ul
+ li.
+ When a regular (resp. non-capturing) Chess piece is captured, it is
+ replaced with a non-capturing (resp. regular) counterpart of the same
+ color and given back to the player of that color,
+ who holds it in hand until he drops it on the board.
+ li.
+ A player who has a piece in hand may use his turn to place it on any
+ empty square on the board. Pawns cannot be dropped on the last rank.
+
+p Non-capturing units appear in yellow for white, and red for black.
+
+figure.diagram-container
+ .diagram
+ | fen:3nkr2/1pNSpp1b/1p1sq3/7p/rT1N1cPp/8/PPPPPP2/R1BB1KR1:
+ figcaption The black king must capture the non-capturing white pawn.
+
+h3 Source
+
+p
+ | Slightly simplified from
+ a(href="https://www.chessvariants.com/other.dir/clockworkorange.html")
+ | Clockwork Orange Chess
+ | on chessvariants.com.
+
+p Inventor: Fergus Duniho (1999)
p.boxed
- | TODO
+ | Las piezas capturadas se pueden soltar más adelante en el juego,
+ | con o sin capacidad de captura.
+
+p Se aplican reglas ortodoxas, con las siguientes excepciones:
+ul
+ li.
+ Cuando se captura una pieza estándar (resp. sin-captura), es
+ reemplazado por una pieza sin-captura (resp. estándar) del mismo color
+ y regresó al jugador de ese color, que lo tiene en la mano hasta que él
+ decide ponerlo en el tablero.
+ li.
+ Un jugador con una pieza en reserva puede soltarlo en cualquier casilla
+ del tablero en lugar de hacer un movimiento. Los peones no pueden alcanzar
+ la última fila así.
+
+p.
+ Las unidades que no capturan aparecen en amarillo para las blancas,
+ y en rojo para las negras.
+
+figure.diagram-container
+ .diagram
+ | fen:3nkr2/1pNSpp1b/1p1sq3/7p/rT1N1cPp/8/PPPPPP2/R1BB1KR1:
+ figcaption El rey negro debe capturar el peón blanco sin-captura.
+
+h3 Fuente
+
+p
+ | Ligeramente simplificado desde
+ a(href="https://www.chessvariants.com/other.dir/clockworkorange.html")
+ | Clockwork Orange Chess
+ | en chessvariants.com.
+
+p Inventor: Fergus Duniho (1999)
p.boxed
- | TODO
+ | Les pièces capturées peuvent être parachutées plus tard dans la partie,
+ | avec ou sans capacité de capture.
+
+p Les règles orthodoxes s'appliquent, avec les exceptions suivantes :
+ul
+ li.
+ Quand une pièce standard (resp. non-capturante) est capturée, elle est
+ remplacée par une pièce non-capturante (resp. standard) de la même couleur
+ et rendue au joueur de cette couleur, qui la garde en main jusqu'à ce qu'il
+ décide de la poser sur l'échiquier.
+ li.
+ Un joueur ayant une pièce en réserve peut la parachuter n'importe où sur
+ l'échiquier au lieu d'effectuer un coup. Les pions ne peuvent atteindre
+ la dernière rangée ainsi.
+
+p.
+ Les unités non-capturantes apparaissent en jaune pour les blancs,
+ et en rouge pour les noirs.
+
+figure.diagram-container
+ .diagram
+ | fen:3nkr2/1pNSpp1b/1p1sq3/7p/rT1N1cPp/8/PPPPPP2/R1BB1KR1:
+ figcaption le roi noir doit capturer le pion blanc non-capturant.
+
+h3 Source
+
+p
+ | Légèrement simplifié depuis
+ a(href="https://www.chessvariants.com/other.dir/clockworkorange.html")
+ | Clockwork Orange Chess
+ | sur chessvariants.com.
+
+p Inventeur : Fergus Duniho (1999)
let shadowArray = ArrayFun.init(V.size.x, V.size.y, false);
const squares = shadow.split(",");
for (let i = 0; i < squares.length; i++) {
- const rownum = V.size.x - parseInt(squares[i]);
+ const rownum = V.size.x - parseInt(squares[i], 10);
if (!isNaN(rownum)) {
// Shadow a full row
for (let i = 0; i < V.size.y; i++) shadowArray[rownum][i] = true;
// Inverse function
export function getSquareFromId(id) {
const idParts = id.split("-");
- return [parseInt(idParts[1]), parseInt(idParts[2])];
+ return [parseInt(idParts[1], 10), parseInt(idParts[2], 10)];
}
tcParts[0] += "m";
const mainTimeArray = tcParts[0].match(/^([0-9]+)([smhd]+)$/);
if (!mainTimeArray) return null;
- const mainTimeValue = parseInt(mainTimeArray[1]);
+ const mainTimeValue = parseInt(mainTimeArray[1], 10);
const mainTimeUnit = mainTimeArray[2][0];
const mainTime = timeUnitToSeconds(mainTimeValue, mainTimeUnit);
let increment = 0;
tcParts[1] += "s";
const incrementArray = tcParts[1].match(/^([0-9]+)([smhd]+)$/);
if (!incrementArray) return null;
- const incrementValue = parseInt(incrementArray[1]);
+ const incrementValue = parseInt(incrementArray[1], 10);
const incrementUnit = incrementArray[2][0];
// Increment unit cannot be larger than main unit:
if (isLargerUnit(incrementUnit, mainTimeUnit)) return null;
if (['K','k','L','l'].includes(row[i])) kings[row[i]]++;
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
this.kingPos["w"] = [i, k];
break;
default: {
- const num = parseInt(rows[i].charAt(j));
+ const num = parseInt(rows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
this.antikingPos["w"] = [i, k];
break;
default: {
- const num = parseInt(rows[i].charAt(j));
+ const num = parseInt(rows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
this.antikingPos["w"] = [i, k];
break;
default: {
- const num = parseInt(rows[i].charAt(j));
+ const num = parseInt(rows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
if (['P','p'].includes(row[i])) pawns[row[i]]++;
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
setFlags(fenflags) {
this.penaltyFlags = {
- 'w': parseInt(fenflags[0]),
- 'b': parseInt(fenflags[1])
+ 'w': parseInt(fenflags[0], 10),
+ 'b': parseInt(fenflags[1], 10)
};
}
if (['K','k','Q','q'].includes(row[i])) royals[row[i]]++;
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
if (withBall.includes(lowerRi)) ballCount++;
sumElts++;
} else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
this.kingPos["w"] = [i, k];
break;
default: {
- const num = parseInt(position[i].charAt(j));
+ const num = parseInt(position[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
else if (kingWhiteCodes.includes(row[i])) kings['w']++;
if (allPiecesCodes.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
const color = (piece.charCodeAt(0) <= 90 ? 'w' : 'b');
this.kingPos[color] = [i, k];
} else {
- const num = parseInt(rows[i].charAt(j));
+ const num = parseInt(rows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
k++;
if (['K', 'k', 'L', 'l'].includes(row[i])) kings[row[i]]++;
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const fenParsed = V.ParseFen(fen);
// Initialize captured pieces' counts from FEN
+ const captured =
+ V.ParseFen(fen).captured.split("").map(x => parseInt(x, 10));
this.captured = {
w: {
- [V.PAWN]: parseInt(fenParsed.captured[0]),
- [V.ROOK]: parseInt(fenParsed.captured[1]),
- [V.KNIGHT]: parseInt(fenParsed.captured[2]),
- [V.BISHOP]: parseInt(fenParsed.captured[3]),
- [V.QUEEN]: parseInt(fenParsed.captured[4]),
- [V.KING]: parseInt(fenParsed.captured[5])
+ [V.PAWN]: captured[0],
+ [V.ROOK]: captured[1],
+ [V.KNIGHT]: captured[2],
+ [V.BISHOP]: captured[3],
+ [V.QUEEN]: captured[4],
+ [V.KING]: captured[5]
},
b: {
- [V.PAWN]: parseInt(fenParsed.captured[6]),
- [V.ROOK]: parseInt(fenParsed.captured[7]),
- [V.KNIGHT]: parseInt(fenParsed.captured[8]),
- [V.BISHOP]: parseInt(fenParsed.captured[9]),
- [V.QUEEN]: parseInt(fenParsed.captured[10]),
- [V.KING]: parseInt(fenParsed.captured[11])
+ [V.PAWN]: captured[6],
+ [V.ROOK]: captured[7],
+ [V.KNIGHT]: captured[8],
+ [V.BISHOP]: captured[9],
+ [V.QUEEN]: captured[10],
+ [V.KING]: captured[11]
}
};
this.firstMove = [];
}
// Stage 1: as Checkered2. Stage 2: checkered pieces are autonomous
const stageInfo = V.ParseFen(fen).stage;
- this.stage = parseInt(stageInfo[0]);
+ this.stage = parseInt(stageInfo[0], 10);
this.sideCheckered = (this.stage == 2 ? stageInfo[1] : undefined);
}
import { ArrayFun } from "@/utils/array";
export class ClorangeRules extends ChessRules {
- static get PawnSpecs() {
- return Object.assign(
- {},
- ChessRules.PawnSpecs,
- // TODO: pawns reaching last rank promote normally? Seems better
- { promotions: [V.PAWN] }
- );
- }
-
static IsGoodFen(fen) {
if (!ChessRules.IsGoodFen(fen)) return false;
const fenParsed = V.ParseFen(fen);
}
getReserveFen() {
- let counts = new Array(10);
- for (
- let i = 0;
- i < V.PIECES.length - 1;
- i++ //-1: no king reserve
+ return (
+ Object.keys(this.reserve).map(
+ c => Object.values(this.reserve[c]).join("")).join("")
+ );
+ }
+
+ getEpSquare(moveOrSquare) {
+ if (!moveOrSquare) return undefined;
+ if (typeof moveOrSquare === "string") {
+ const square = moveOrSquare;
+ if (square == "-") return undefined;
+ return V.SquareToCoords(square);
+ }
+ const move = moveOrSquare;
+ const s = move.start,
+ e = move.end;
+ if (
+ s.y == e.y &&
+ Math.abs(s.x - e.x) == 2 &&
+ move.vanish.length > 0 && ['p', 's'].includes(move.vanish[0].p)
) {
- // TODO: adapt
- counts[i] = this.reserve["w"][V.PIECES[i]];
- counts[5 + i] = this.reserve["b"][V.PIECES[i]];
+ return {
+ x: (s.x + e.x) / 2,
+ y: s.y
+ };
}
- return counts.join("");
+ return undefined;
}
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const fenParsed = V.ParseFen(fen);
// Also init reserves (used by the interface to show landable pieces)
- // TODO: adapt
+ const reserve =
+ V.ParseFen(fen).reserve.split("").map(x => parseInt(x, 10));
this.reserve = {
w: {
- [V.PAWN]: parseInt(fenParsed.reserve[0]),
- [V.ROOK]: parseInt(fenParsed.reserve[1]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[2]),
- [V.BISHOP]: parseInt(fenParsed.reserve[3]),
- [V.QUEEN]: parseInt(fenParsed.reserve[4])
+ 'p': reserve[0],
+ 'r': reserve[1],
+ 'n': reserve[2],
+ 'b': reserve[3],
+ 'q': reserve[4],
+ 's': reserve[5],
+ 'u': reserve[6],
+ 'o': reserve[7],
+ 'c': reserve[8],
+ 't': reserve[9]
},
b: {
- [V.PAWN]: parseInt(fenParsed.reserve[5]),
- [V.ROOK]: parseInt(fenParsed.reserve[6]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[7]),
- [V.BISHOP]: parseInt(fenParsed.reserve[8]),
- [V.QUEEN]: parseInt(fenParsed.reserve[9])
+ 'p': reserve[10],
+ 'r': reserve[11],
+ 'n': reserve[12],
+ 'b': reserve[13],
+ 'q': reserve[14],
+ 's': reserve[15],
+ 'u': reserve[16],
+ 'o': reserve[17],
+ 'c': reserve[18],
+ 't': reserve[19]
}
};
}
return this.board[i][j].charAt(1);
}
+ getPpath(b) {
+ return (V.NON_VIOLENT.includes(b[1]) ? "Clorange/" : "") + b;
+ }
+
getReservePpath(index, color) {
- return color + V.RESERVE_PIECES[index];
+ const prefix =
+ (V.NON_VIOLENT.includes(V.RESERVE_PIECES[index]) ? "Clorange/" : "");
+ return prefix + color + V.RESERVE_PIECES[index];
}
static get NON_VIOLENT() {
- return ['s', 'u', 'o', 'c', 't', 'l'];
+ return ['s', 'u', 'o', 'c', 't'];
+ }
+
+ static get PIECES() {
+ return ChessRules.PIECES.concat(V.NON_VIOLENT);
}
// Ordering on reserve pieces
static get RESERVE_PIECES() {
- return ChessRules.PIECES.concat(V.NON_VIOLENT);
+ return V.PIECES.filter(p => p != 'k');
}
getReserveMoves([x, y]) {
const p = V.RESERVE_PIECES[y];
if (this.reserve[color][p] == 0) return [];
let moves = [];
- const pawnShift = p == V.PAWN ? 1 : 0;
- for (let i = pawnShift; i < V.size.x - pawnShift; i++) {
+ let rank1 = 0;
+ let rank2 = V.size.x - 1;
+ if (['p', 's'].includes(p)) {
+ if (color == 'w') rank1++;
+ else rank2--;
+ }
+ for (let i = rank1; i <= rank2; i++) {
for (let j = 0; j < V.size.y; j++) {
if (this.board[i][j] == V.EMPTY) {
let mv = new Move({
return moves;
}
- // TODO: adapt all below:
getPotentialMovesFrom([x, y]) {
- if (x >= V.size.x) {
+ if (x >= V.size.x)
// Reserves, outside of board: x == sizeX(+1)
return this.getReserveMoves([x, y]);
- }
// Standard moves
- return super.getPotentialMovesFrom([x, y]);
+ switch (this.getPiece(x, y)) {
+ case 's': return super.getPotentialPawnMoves([x, y]);
+ case 'u': return super.getPotentialRookMoves([x, y]);
+ case 'o': return super.getPotentialKnightMoves([x, y]);
+ case 'c': return super.getPotentialBishopMoves([x, y]);
+ case 't': return super.getPotentialQueenMoves([x, y]);
+ default: return super.getPotentialMovesFrom([x, y]);
+ }
+ return []; //never reached
}
- getPotentialPawnMoves([x, y]) {
-
- let moves = super.getPotentialPawnMoves([x, y]);
- // Remove pawns on 8th rank ("fallen"):
- const color = this.turn;
- const lastRank = (color == "w" ? 0 : V.size.x - 1);
+ getPotentialPawnMoves(sq) {
+ let moves = super.getPotentialPawnMoves(sq);
moves.forEach(m => {
- if (m.appear[0].x == lastRank) m.appear.pop();
+ if (m.vanish[0].p == 's' && m.appear[0].p != 's') {
+ // Promotion pieces should be non-violent as well:
+ const pIdx = ChessRules.PIECES.findIndex(p => p == m.appear[0].p)
+ m.appear[0].p = V.NON_VIOLENT[pIdx];
+ }
});
return moves;
}
+ getSlideNJumpMoves([x, y], steps, oneStep) {
+ let moves = [];
+ const canTake = ChessRules.PIECES.includes(this.getPiece(x, y));
+ outerLoop: for (let step of steps) {
+ let i = x + step[0];
+ let j = y + step[1];
+ while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
+ moves.push(this.getBasicMove([x, y], [i, j]));
+ if (oneStep) continue outerLoop;
+ i += step[0];
+ j += step[1];
+ }
+ if (V.OnBoard(i, j) && canTake && this.canTake([x, y], [i, j]))
+ moves.push(this.getBasicMove([x, y], [i, j]));
+ }
+ return moves;
+ }
+
getAllValidMoves() {
let moves = super.getAllPotentialMoves();
const color = this.turn;
return true;
}
- canTake([x1, y1], [x2, y2]) {
- // Self-captures allowed, except for the king:
- return this.getPiece(x2, y2) != V.KING;
- }
-
prePlay(move) {
super.prePlay(move);
// Skip castle:
if (move.vanish.length == 2 && move.appear.length == 2) return;
const color = this.turn;
if (move.vanish.length == 0) this.reserve[color][move.appear[0].p]--;
- else if (move.vanish.length == 2 && move.vanish[1].c == color)
- // Self-capture
- this.reserve[color][move.vanish[1].p]++;
+ else if (move.vanish.length == 2) {
+ // Capture
+ const normal = ChessRules.PIECES.includes(move.vanish[1].p);
+ const pIdx =
+ normal
+ ? ChessRules.PIECES.findIndex(p => p == move.vanish[1].p)
+ : V.NON_VIOLENT.findIndex(p => p == move.vanish[1].p);
+ const rPiece = (normal ? V.NON_VIOLENT : ChessRules.PIECES)[pIdx];
+ this.reserve[move.vanish[1].c][rPiece]++;
+ }
}
postUndo(move) {
if (move.vanish.length == 2 && move.appear.length == 2) return;
const color = this.turn;
if (move.vanish.length == 0) this.reserve[color][move.appear[0].p]++;
- else if (move.vanish.length == 2 && move.vanish[1].c == color)
- this.reserve[color][move.vanish[1].p]--;
+ else if (move.vanish.length == 2) {
+ const normal = ChessRules.PIECES.includes(move.vanish[1].p);
+ const pIdx =
+ normal
+ ? ChessRules.PIECES.findIndex(p => p == move.vanish[1].p)
+ : V.NON_VIOLENT.findIndex(p => p == move.vanish[1].p);
+ const rPiece = (normal ? V.NON_VIOLENT : ChessRules.PIECES)[pIdx];
+ this.reserve[move.vanish[1].c][rPiece]--;
+ }
}
static get SEARCH_DEPTH() {
return 2;
}
+ static get VALUES() {
+ return Object.assign(
+ {
+ s: 0.75,
+ u: 4,
+ o: 2,
+ c: 2,
+ t: 7
+ },
+ ChessRules.VALUES
+ );
+ }
+
evalPosition() {
let evaluation = super.evalPosition();
// Add reserves:
getNotation(move) {
const finalSquare = V.CoordsToSquare(move.end);
if (move.vanish.length > 0) {
- if (move.appear.length > 0) {
- // Standard move
- return super.getNotation(move);
- } else {
- // Pawn fallen: capturing or not
- let res = "";
- if (move.vanish.length == 2)
- res += V.CoordToColumn(move.start.y) + "x";
- return res + finalSquare;
- }
+ // Standard move (maybe with non-violent piece)
+ let notation = super.getNotation(move);
+ if (move.vanish[0].p == 's' && move.appear[0].p != 's')
+ // Fix non-violent promotions:
+ notation += "=" + move.appear[0].p.toUpperCase();
+ return notation;
}
// Rebirth:
const piece =
this.kingPos["w"] = [i, k];
break;
default: {
- const num = parseInt(fenRows[i].charAt(j));
+ const num = parseInt(fenRows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
if (!!bishop1Options[pos]) delete bishop1Options[pos];
else if (!!bishop2Options[pos]) delete bishop2Options[pos];
});
- const bishop1Pos = parseInt(sample(Object.keys(bishop1Options), 1)[0]);
- const bishop2Pos = parseInt(sample(Object.keys(bishop2Options), 1)[0]);
+ const bishop1Pos =
+ parseInt(sample(Object.keys(bishop1Options), 1)[0], 10);
+ const bishop2Pos =
+ parseInt(sample(Object.keys(bishop2Options), 1)[0], 10);
// Knights' positions are now determined
const forbidden = [
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const fenParsed = V.ParseFen(fen);
// Also init reserves (used by the interface to show landable pieces)
+ const reserve =
+ V.ParseFen(fen).reserve.split("").map(x => parseInt(x, 10));
this.reserve = {
w: {
- [V.PAWN]: parseInt(fenParsed.reserve[0]),
- [V.ROOK]: parseInt(fenParsed.reserve[1]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[2]),
- [V.BISHOP]: parseInt(fenParsed.reserve[3]),
- [V.QUEEN]: parseInt(fenParsed.reserve[4])
+ [V.PAWN]: reserve[0],
+ [V.ROOK]: reserve[1],
+ [V.KNIGHT]: reserve[2],
+ [V.BISHOP]: reserve[3],
+ [V.QUEEN]: reserve[4]
},
b: {
- [V.PAWN]: parseInt(fenParsed.reserve[5]),
- [V.ROOK]: parseInt(fenParsed.reserve[6]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[7]),
- [V.BISHOP]: parseInt(fenParsed.reserve[8]),
- [V.QUEEN]: parseInt(fenParsed.reserve[9])
+ [V.PAWN]: reserve[5],
+ [V.ROOK]: reserve[6],
+ [V.KNIGHT]: reserve[7],
+ [V.BISHOP]: reserve[8],
+ [V.QUEEN]: reserve[9]
}
};
this.promoted = ArrayFun.init(V.size.x, V.size.y, false);
let pieces = {};
for (let row of rows) {
for (let i = 0; i < row.length; i++) {
- if (isNaN(parseInt(row[i])) && !pieces[row[i]])
+ if (isNaN(parseInt(row[i], 10)) && !pieces[row[i]])
pieces[row[i]] = true;
}
}
pieces[row[i] == lowerRi ? "b" : "w"]++;
sumElts++;
} else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
this.INIT_COL_KING["w"] = k;
break;
default: {
- const num = parseInt(fenRows[i].charAt(j));
+ const num = parseInt(fenRows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const captured = V.ParseFen(fen).captured.split("").map(parseInt);
+ const captured =
+ V.ParseFen(fen).captured.split("").map(x => parseInt(x, 10));
// Initialize captured pieces' counts from FEN
this.captured = {
w: {
for (let i = 0; i < row.length; i++) {
if (['x'].concat(V.PIECES).includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
this.kingPos["w"] = [i, k];
break;
default: {
- const num = parseInt(fenRows[i].charAt(j));
+ const num = parseInt(fenRows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
}
sumElts++;
} else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
if (['K','k'].includes(row[i])) kings[row[i]]++;
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const fenParsed = V.ParseFen(fen);
+ const captured =
+ V.ParseFen(fen).captured.split("").map(x => parseInt(x, 10));
// Initialize captured pieces' counts from FEN
this.captured = {
w: {
- [V.ROOK]: parseInt(fenParsed.captured[0]),
- [V.KNIGHT]: parseInt(fenParsed.captured[1]),
- [V.BISHOP]: parseInt(fenParsed.captured[2]),
+ [V.ROOK]: captured[0],
+ [V.KNIGHT]: captured[1],
+ [V.BISHOP]: captured[2]
},
b: {
- [V.ROOK]: parseInt(fenParsed.captured[3]),
- [V.KNIGHT]: parseInt(fenParsed.captured[4]),
- [V.BISHOP]: parseInt(fenParsed.captured[5]),
+ [V.ROOK]: captured[3],
+ [V.KNIGHT]: captured[4],
+ [V.BISHOP]: captured[5]
}
};
// Stack of "last move" only for intermediate captures
if (lowerRi == 'p') pawns[row[i] == lowerRi ? "b" : "w"]++;
sumElts++;
} else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
}
getStunnedFen() {
- return (
- Object.keys(this.stunned)
- .map(square => square + this.stunned[square])
- .join(",")
- );
+ const squares = Object.keys(this.stunned);
+ if (squares.length == 0) return "-";
+ return squares.map(square => square + this.stunned[square]).join(",");
}
// Base GenRandInitFen() is fine because en-passant indicator will
this.INIT_COL_KING["w"] = k;
break;
default: {
- const num = parseInt(fenRows[i].charAt(j));
+ const num = parseInt(fenRows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
.map(s => {
return {
square: s.substr(0, 2),
- state: parseInt(s[2])
+ state: parseInt(s[2], 10)
};
});
}
if (['K','k'].includes(row[i])) kings[row[i]]++;
if (['x'].concat(V.PIECES).includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
this.kingPos["w"] = [i, k];
break;
default: {
- const num = parseInt(position[i].charAt(j));
+ const num = parseInt(position[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const fenParsed = V.ParseFen(fen);
// Also init reserves (used by the interface to show landable pieces)
+ const reserve =
+ V.ParseFen(fen).reserve.split("").map(x => parseInt(x, 10));
this.reserve = {
w: {
- [V.PAWN]: parseInt(fenParsed.reserve[0]),
- [V.ROOK]: parseInt(fenParsed.reserve[1]),
- [V.BISHOP]: parseInt(fenParsed.reserve[2]),
- [V.GOLD_G]: parseInt(fenParsed.reserve[3]),
- [V.SILVER_G]: parseInt(fenParsed.reserve[4])
+ [V.PAWN]: reserve[0],
+ [V.ROOK]: reserve[1],
+ [V.BISHOP]: reserve[2],
+ [V.GOLD_G]: reserve[3],
+ [V.SILVER_G]: reserve[4]
},
b: {
- [V.PAWN]: parseInt(fenParsed.reserve[5]),
- [V.ROOK]: parseInt(fenParsed.reserve[6]),
- [V.BISHOP]: parseInt(fenParsed.reserve[7]),
- [V.GOLD_G]: parseInt(fenParsed.reserve[8]),
- [V.SILVER_G]: parseInt(fenParsed.reserve[9])
+ [V.PAWN]: reserve[5],
+ [V.ROOK]: reserve[6],
+ [V.BISHOP]: reserve[7],
+ [V.GOLD_G]: reserve[8],
+ [V.SILVER_G]: reserve[9]
}
};
}
for (let i = 0; i < row.length; i++) {
if (V.PIECES.includes(row[i])) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
if (['K','k'].includes(row[i])) kings[row[i]]++;
if (['x'].concat(V.PIECES).includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
if (['K','k'].includes(row[i])) kingsCount++;
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
this.INIT_COL_KING["w"] = k;
break;
default: {
- const num = parseInt(fenRows[i].charAt(j));
+ const num = parseInt(fenRows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
for (let i = 0; i < row.length; i++) {
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const fenParsed = V.ParseFen(fen);
// Also init reserves (used by the interface to show landable pieces)
+ const reserve =
+ V.ParseFen(fen).reserve.split("").map(x => parseInt(x, 10));
this.reserve = {
w: {
- [V.PAWN]: parseInt(fenParsed.reserve[0]),
- [V.ROOK]: parseInt(fenParsed.reserve[1]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[2]),
- [V.BISHOP]: parseInt(fenParsed.reserve[3]),
- [V.QUEEN]: parseInt(fenParsed.reserve[4]),
- [V.KING]: parseInt(fenParsed.reserve[5])
+ [V.PAWN]: reserve[0],
+ [V.ROOK]: reserve[1],
+ [V.KNIGHT]: reserve[2],
+ [V.BISHOP]: reserve[3],
+ [V.QUEEN]: reserve[4],
+ [V.KING]: reserve[5]
},
b: {
- [V.PAWN]: parseInt(fenParsed.reserve[6]),
- [V.ROOK]: parseInt(fenParsed.reserve[7]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[8]),
- [V.BISHOP]: parseInt(fenParsed.reserve[9]),
- [V.QUEEN]: parseInt(fenParsed.reserve[10]),
- [V.KING]: parseInt(fenParsed.reserve[11])
+ [V.PAWN]: reserve[6],
+ [V.ROOK]: reserve[7],
+ [V.KNIGHT]: reserve[8],
+ [V.BISHOP]: reserve[9],
+ [V.QUEEN]: reserve[10],
+ [V.KING]: reserve[11]
}
};
}
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const fenParsed = V.ParseFen(fen);
// Also init reserves (used by the interface to show landable pieces)
+ const reserve =
+ V.ParseFen(fen).reserve.split("").map(x => parseInt(x, 10));
this.reserve = {
w: {
- [V.PAWN]: parseInt(fenParsed.reserve[0]),
- [V.ROOK]: parseInt(fenParsed.reserve[1]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[2]),
- [V.BISHOP]: parseInt(fenParsed.reserve[3]),
- [V.QUEEN]: parseInt(fenParsed.reserve[4])
+ [V.PAWN]: reserve[0],
+ [V.ROOK]: reserve[1],
+ [V.KNIGHT]: reserve[2],
+ [V.BISHOP]: reserve[3],
+ [V.QUEEN]: reserve[4]
},
b: {
- [V.PAWN]: parseInt(fenParsed.reserve[5]),
- [V.ROOK]: parseInt(fenParsed.reserve[6]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[7]),
- [V.BISHOP]: parseInt(fenParsed.reserve[8]),
- [V.QUEEN]: parseInt(fenParsed.reserve[9])
+ [V.PAWN]: reserve[5],
+ [V.ROOK]: reserve[6],
+ [V.KNIGHT]: reserve[7],
+ [V.BISHOP]: reserve[8],
+ [V.QUEEN]: reserve[9]
}
};
}
}
getPotentialMovesFrom([x, y]) {
- if (x >= V.size.x) {
+ if (x >= V.size.x)
// Reserves, outside of board: x == sizeX(+1)
return this.getReserveMoves([x, y]);
- }
// Standard moves
return super.getPotentialMovesFrom([x, y]);
}
this.kingPos["w"] = [i, k];
break;
default: {
- const num = parseInt(position[i].charAt(j));
+ const num = parseInt(position[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
const fenParsed = V.ParseFen(fen);
this.pocket = {
"w": {
- h: parseInt(fenParsed.pocket[0]),
- e: parseInt(fenParsed.pocket[1])
+ h: parseInt(fenParsed.pocket[0], 10),
+ e: parseInt(fenParsed.pocket[1], 10)
},
"b": {
- h: parseInt(fenParsed.pocket[2]),
- e: parseInt(fenParsed.pocket[3])
+ h: parseInt(fenParsed.pocket[2], 10),
+ e: parseInt(fenParsed.pocket[3], 10)
}
};
}
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const fenParsed = V.ParseFen(fen);
// Also init reserves (used by the interface to show landable pieces)
+ const reserve =
+ V.ParseFen(fen).reserve.split("").map(x => parseInt(x, 10));
this.reserve = {
w: {
- [V.PAWN]: parseInt(fenParsed.reserve[0]),
- [V.ROOK]: parseInt(fenParsed.reserve[1]),
- [V.BISHOP]: parseInt(fenParsed.reserve[2]),
- [V.GOLD_G]: parseInt(fenParsed.reserve[3]),
- [V.SILVER_G]: parseInt(fenParsed.reserve[4]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[5]),
- [V.LANCE]: parseInt(fenParsed.reserve[6])
+ [V.PAWN]: reserve[0],
+ [V.ROOK]: reserve[1],
+ [V.BISHOP]: reserve[2],
+ [V.GOLD_G]: reserve[3],
+ [V.SILVER_G]: reserve[4],
+ [V.KNIGHT]: reserve[5],
+ [V.LANCE]: reserve[6]
},
b: {
- [V.PAWN]: parseInt(fenParsed.reserve[7]),
- [V.ROOK]: parseInt(fenParsed.reserve[8]),
- [V.BISHOP]: parseInt(fenParsed.reserve[9]),
- [V.GOLD_G]: parseInt(fenParsed.reserve[10]),
- [V.SILVER_G]: parseInt(fenParsed.reserve[11]),
- [V.KNIGHT]: parseInt(fenParsed.reserve[12]),
- [V.LANCE]: parseInt(fenParsed.reserve[13])
+ [V.PAWN]: reserve[7],
+ [V.ROOK]: reserve[8],
+ [V.BISHOP]: reserve[9],
+ [V.GOLD_G]: reserve[10],
+ [V.SILVER_G]: reserve[11],
+ [V.KNIGHT]: reserve[12],
+ [V.LANCE]: reserve[13]
}
};
}
pieces[row[i] == lowerRi ? "b" : "w"]++;
sumElts++;
} else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
this.checkFlags = { w: 0, b: 0 };
const flags = fenflags.substr(4); //skip first 4 digits, for castle
for (let c of ["w", "b"]) {
- this.checkFlags[c] = parseInt(flags.charAt(c == "w" ? 0 : 1));
+ this.checkFlags[c] = parseInt(flags.charAt(c == "w" ? 0 : 1), 10);
}
}
if (['K','k'].includes(row[i])) kings[row[i]]++;
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
if (['K','k'].includes(row[i])) kings[row[i]]++;
if (['x'].concat(V.PIECES).includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
// - from server (one correspondance game I play[ed] or not)
// - from remote peer (one live game I don't play, finished or not)
fetchGame: function(callback) {
- if (Number.isInteger(this.gameRef) || !isNaN(parseInt(this.gameRef))) {
+ if (
+ Number.isInteger(this.gameRef) ||
+ !isNaN(parseInt(this.gameRef, 10))
+ ) {
// corr games identifiers are integers
ajax(
"/games",
infoMessage: "",
newchallenge: {
fen: "",
- vid: parseInt(localStorage.getItem("vid")) || 0,
+ vid: parseInt(localStorage.getItem("vid"), 10) || 0,
to: "", //name of challenged player (if any)
cadence: localStorage.getItem("cadence") || "",
randomness:
// Warning: randomness can be 0, then !!randomness is false
- (parseInt(localStorage.getItem("challRandomness"))+1 || 3) - 1,
+ (parseInt(localStorage.getItem("challRandomness"),10)+1 || 3) - 1,
// VariantRules object, stored to not interfere with
// diagrams of targetted challenges:
V: null,
case "notifyturn":
case "notifyscore": {
const info = data.data;
- const type = (!!parseInt(info.gid) ? "corr" : "live");
+ const type = (!!parseInt(info.gid, 10) ? "corr" : "live");
let game = gamesArrays[type].find(g => g.id == info.gid);
// "notifything" --> "thing":
const thing = data.code.substr(6);
('Doublearmy', '64 pieces on the board'),
('Doublemove1', 'Double moves (v1)'),
('Doublemove2', 'Double moves (v2)'),
- ('Doubleorda', 'Mongolian Horde (v2)'),
('Dynamo', 'Push and pull'),
('Eightpieces', 'Each piece is unique'),
('Enpassant', 'Capture en passant'),
('Monster', 'White move twice'),
('Omega', 'A wizard in the corner'),
('Orda', 'Mongolian Horde (v1)'),
+ ('Ordamirror', 'Mongolian Horde (v2)'),
('Pacifist1', 'Convert & support (v1)'),
('Pacifist2', 'Convert & support (v2)'),
('Parachute', 'Landing on the board'),