if (V.HasEnpassant) {
const epSq =
parsedFen.enpassant != "-"
- ? V.SquareToCoords(parsedFen.enpassant)
+ ? this.getEpSquare(parsedFen.enpassant)
: undefined;
this.epSquares = [epSq];
}
const oppCol = V.GetOppCol(c);
let moves = [];
let i = 0;
+ // King, then rook:
const finalSquares = [
[2, 3],
[V.size.y - 2, V.size.y - 3]
- ]; //king, then rook
+ ];
castlingCheck: for (
let castleSide = 0;
castleSide < 2;
play(move) {
// DEBUG:
- // if (!this.states) this.states = [];
- // const stateFen = this.getBaseFen() + this.getTurnFen() + this.getFlagsFen();
- // this.states.push(stateFen);
+// if (!this.states) this.states = [];
+// const stateFen = this.getBaseFen() + this.getTurnFen() + this.getFlagsFen();
+// this.states.push(stateFen);
if (V.HasFlags) move.flags = JSON.stringify(this.aggregateFlags()); //save flags (for undo)
if (V.HasEnpassant) this.epSquares.push(this.getEpSquare(move));
this.unupdateVariables(move);
// DEBUG:
- // const stateFen = this.getBaseFen() + this.getTurnFen() + this.getFlagsFen();
- // if (stateFen != this.states[this.states.length-1]) debugger;
- // this.states.pop();
+// const stateFen = this.getBaseFen() + this.getTurnFen() + this.getFlagsFen();
+// if (stateFen != this.states[this.states.length-1]) debugger;
+// this.states.pop();
}
///////////////
"Both sides of the mirror": "Both sides of the mirror",
"Capture all of a kind": "Capture all of a kind",
"Captures reborn": "Captures reborn",
+ "Change colors": "Change colors",
"Exchange pieces positions": "Exchange pieces positions",
"Exotic captures": "Exotic captures",
"Explosive captures": "Explosive captures",
"Both sides of the mirror": "Ambos lados del espejo",
"Capture all of a kind": "Capturar todo del mismo tipo",
"Captures reborn": "Las capturas renacen",
+ "Change colors": "Cambiar colores",
"Exchange pieces positions": "Intercambiar las posiciones de las piezas",
"Exotic captures": "Capturas exóticas",
"Explosive captures": "Capturas explosivas",
"Both sides of the mirror": "Les deux côté du miroir",
"Capture all of a kind": "Capturez tout d'un même type",
"Captures reborn": "Les captures renaissent",
+ "Change colors": "Changer les couleurs",
"Exchange pieces positions": "Échangez les positions des pièces",
"Exotic captures": "Captures exotiques",
"Explosive captures": "Captures explosives",
--- /dev/null
+p.boxed
+ | Attacked pieces change color after each turn. Goal is to change king's color.
+
+p.
+ More precisely, only pieces attacked by the moving unit are flipped.
+ They change side, until the opponent in turn can attack them.
+ There are no captures: only color changes.
+
+figure.diagram-container
+ .diagram
+ | fen:r1bqkbnr/ppPpPppp/2n5/3N4/8/8/PPPPPPPP/R1BQKBNR:
+ figcaption After 1.Nc3 Nc6 2.Nd5: pawns on c7 and e7 change color.
+
+h3 End of the game
+
+p.
+ The game ends when a king changes color.
+ There can be no stalemate since all pieces remain on the board.
+
+p.
+ In the diagram position, 2...g6?? for example would allow 3.Nf6 which
+ attacks the king and therefore ends the game.
+ However black can defend with 2...Nb4 or 2...Nf6 which flips the d5 knight,
+ or even 2...f6.
+
+h3 Source
+
+p
+ a(href="https://www.chessvariants.com/difftaking.dir/benedict.html") Benedict chess
+ | on chessvariants.com.
--- /dev/null
+p.boxed
+ | Las piezas atacadas cambian de color después de cada turno.
+ | El objetivo es cambiar el color del rey.
+
+figure.diagram-container
+ .diagram
+ | fen:r1bqkbnr/ppPpPppp/2n5/3N4/8/8/PPPPPPPP/R1BQKBNR:
+ figcaption Después de 1.Nc3 Nc6 2.Nd5: los peones en c7 y e7 cambian de color.
+
+h3 Fin de la partida
+
+p.
+ El juego termina cuando un rey cambia de color.
+ No puede hay empate ya que todas las piezas permanecen en el tablero.
+
+p.
+ En la posición del diagrama, 2...g6?? por ejemplo permitiría 3.Nf6 que
+ atacar al rey y ganar (1-0).
+ Sin embargo, las negras pueden defender con 2...Nb4 o 2...Nf6 que hacen
+ cambiar de lado el caballo d5, o incluso 2...f6.
+
+h3 Fuente
+
+p
+ | La
+ a(href="https://www.chessvariants.com/difftaking.dir/benedict.html") variante Benedict
+ | en chessvariants.com.
--- /dev/null
+p.boxed
+ | Les pièces attaquées changent de couleur après chaque tour.
+ | Le but est de changer la couleur du roi.
+
+figure.diagram-container
+ .diagram
+ | fen:r1bqkbnr/ppPpPppp/2n5/3N4/8/8/PPPPPPPP/R1BQKBNR:
+ figcaption Après 1.Nc3 Nc6 2.Nd5 : les pions en c7 et e7 changent de couleur.
+
+h3 Fin de la partie
+
+p.
+ La partie s'achève quand un roi change de couleur.
+ Il ne peut pas y avoir de pat puisque toutes les pièces restent sur l'échiquier.
+
+p.
+ Dans la position du diagrame, 2...g6?? par exemple permettrait 3.Nf6 qui
+ attaque le roi et gagne (1-0).
+ Cependant les noirs peuvent défendre avec 2...Nb4 ou 2...Nf6 qui font
+ changer de camp le cavalier d5, ou même 2...f6.
+
+h3 Source
+
+p
+ | La
+ a(href="https://www.chessvariants.com/difftaking.dir/benedict.html") variante Benedict
+ | sur chessvariants.com.
h3 Source
p
- a(href="https://www.chessvariants.com/winning.dir/extinction.html") Extinction chess
- | on chessvariants.com.
+ a(href="https://www.chessvariants.com/winning.dir/extinction.html") Extinction chess
+ | on chessvariants.com.
--- /dev/null
+import { ChessRules, PiPo, Move } from "@/base_rules";
+
+export const VariantRules = class BenedictRules extends ChessRules {
+ static get HasEnpassant() {
+ return false;
+ }
+
+ // TODO(?): some duplicated code in 2 next functions
+ getSlideNJumpMoves([x, y], steps, oneStep) {
+ let moves = [];
+ outerLoop: for (let loop = 0; loop < steps.length; loop++) {
+ const step = steps[loop];
+ 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];
+ }
+ // No capture check: handled elsewhere (next method)
+ }
+ return moves;
+ }
+
+ // Find possible captures from a square
+ // follow steps from x,y until something is met.
+ findCaptures([x, y]) {
+ const color = this.getColor(x, y);
+ const piece = this.getPiece(x, y);
+ let squares = [];
+ const steps =
+ piece != V.PAWN
+ ? [V.QUEEN,V.KING].includes(piece)
+ ? V.steps[V.ROOK].concat(V.steps[V.BISHOP])
+ : V.steps[piece]
+ : color == "w"
+ ? [
+ [-1, -1],
+ [-1, 1]
+ ]
+ : [
+ [1, -1],
+ [1, 1]
+ ];
+ const oneStep = [V.KNIGHT,V.PAWN,V.KING].includes(piece);
+ outerLoop: for (let loop = 0; loop < steps.length; loop++) {
+ const step = steps[loop];
+ let i = x + step[0];
+ let j = y + step[1];
+ while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
+ if (oneStep) continue outerLoop;
+ i += step[0];
+ j += step[1];
+ }
+ if (
+ V.OnBoard(i, j) &&
+ this.getColor(i, j) == V.GetOppCol(color)
+ ) {
+ // eat!
+ squares.push([i, j]);
+ }
+ }
+ return squares;
+ }
+
+ getPotentialPawnMoves([x, y]) {
+ const color = this.getColor(x, y);
+ let moves = [];
+ const sizeY = V.size.y;
+ const shift = color == "w" ? -1 : 1;
+ const startRank = color == "w" ? sizeY - 2 : 1;
+ const firstRank = color == "w" ? sizeY - 1 : 0;
+ const lastRank = color == "w" ? 0 : sizeY - 1;
+
+ if (x + shift != lastRank) {
+ // Normal moves
+ if (this.board[x + shift][y] == V.EMPTY) {
+ moves.push(this.getBasicMove([x, y], [x + shift, y]));
+ if (
+ [startRank, firstRank].includes(x) &&
+ this.board[x + 2 * shift][y] == V.EMPTY
+ ) {
+ // Two squares jump
+ moves.push(this.getBasicMove([x, y], [x + 2 * shift, y]));
+ }
+ }
+ }
+ else {
+ // Promotion
+ let promotionPieces = [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN];
+ promotionPieces.forEach(p => {
+ // Normal move
+ if (this.board[x + shift][y] == V.EMPTY)
+ moves.push(
+ this.getBasicMove([x, y], [x + shift, y], { c: color, p: p })
+ );
+ });
+ }
+
+ // No en passant here
+
+ return moves;
+ }
+
+ getPotentialRookMoves(sq) {
+ return this.getSlideNJumpMoves(sq, V.steps[V.ROOK]);
+ }
+
+ getPotentialKnightMoves(sq) {
+ return this.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep");
+ }
+
+ getPotentialBishopMoves(sq) {
+ return this.getSlideNJumpMoves(sq, V.steps[V.BISHOP]);
+ }
+
+ getPotentialQueenMoves(sq) {
+ return this.getSlideNJumpMoves(
+ sq,
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP])
+ );
+ }
+
+ getPotentialKingMoves(sq) {
+ // Initialize with normal (non-capturing) moves
+ let noCaptures = this.getSlideNJumpMoves(
+ sq,
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
+ "oneStep"
+ );
+ return noCaptures.concat(this.getCastleMoves(sq));
+ }
+
+ // TODO: appear/vanish description of a move is too verbose for Benedict.
+ // => Would need a new "flipped" array, to be passed in Game.vue...
+ getPotentialMovesFrom([x, y]) {
+ const color = this.turn;
+ const oppCol = V.GetOppCol(color);
+ // Get all moves from x,y without captures:
+ let moves = super.getPotentialMovesFrom([x, y]);
+ // Add flips:
+ moves.forEach(m => {
+ V.PlayOnBoard(this.board, m);
+ const flipped = this.findCaptures([m.end.x, m.end.y]);
+ V.UndoOnBoard(this.board, m);
+ flipped.forEach(sq => {
+ const piece = this.getPiece(sq[0],sq[1]);
+ const pipoA = new PiPo({
+ x:sq[0],
+ y:sq[1],
+ c:color,
+ p:piece
+ });
+ const pipoV = new PiPo({
+ x:sq[0],
+ y:sq[1],
+ c:oppCol,
+ p:piece
+ });
+ m.appear.push(pipoA);
+ m.vanish.push(pipoV);
+ });
+ });
+ return moves;
+ }
+
+ // Moves cannot flip our king's color, so all are valid
+ filterValid(moves) {
+ return moves;
+ }
+
+ // No notion of check here:
+ getCheckSquares() {
+ return [];
+ }
+
+ getCurrentScore() {
+ const color = this.turn;
+ // Did a king change color?
+ const kp = this.kingPos[color];
+ if (this.getColor(kp[0], kp[1]) != color)
+ return color == "w" ? "0-1" : "1-0";
+ return "*";
+ }
+};
// if met piece is opponent and same movement (asA): eat it!
findCaptures_aux([x, y], asA) {
const color = this.getColor(x, y);
- var moves = [];
+ let moves = [];
const steps =
asA != V.PAWN
? asA == V.QUEEN
[1, -1],
[1, 1]
];
- const oneStep = asA == V.KNIGHT || asA == V.PAWN; //we don't capture king
+ const oneStep = [V.KNIGHT,V.PAWN].includes(asA); //we don't capture king
const lastRank = color == "w" ? 0 : V.size.x - 1;
const promotionPieces = [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN];
outerLoop: for (let loop = 0; loop < steps.length; loop++) {
[startRank, firstRank].includes(x) &&
this.board[x + 2 * shift][y] == V.EMPTY
) {
- //two squares jump
+ // Two squares jump
moves.push(this.getBasicMove([x, y], [x + 2 * shift, y]));
}
}
- } //promotion
+ }
else {
+ // Promotion
let promotionPieces = [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN];
promotionPieces.forEach(p => {
// Normal move
@click="gotoAnalyze()"
)
| {{ st.tr["Analyse"] }}
+ .row
+ .col-sm-12.col-md-8.col-md-offset-2.col-lg-6.col-lg-offset-3
div(
v-show="display=='rules'"
v-html="content"
},
computed: {
showAnalyzeBtn: function() {
- return (this.display=='rules' && (!window.V || V.CanAnalyse));
+ return (this.display=='rules' && (!window.V || V.CanAnalyze));
},
content: function() {
if (!this.gameInfo.vname) return ""; //variant not set yet
('Antiking', 'Keep antiking in check'),
('Atomic', 'Explosive captures'),
('Baroque', 'Exotic captures'),
+ ('Benedict', 'Change colors'),
('Berolina', 'Pawns move diagonally'),
('Checkered', 'Shared pieces'),
('Chess960', 'Standard rules'),