callback();
}, 250);
},
+ // For Analyse mode:
+ emitFenIfAnalyze: function() {
+ if (this.game.mode == "analyze") {
+ this.$emit(
+ "fenchange",
+ this.lastMove ? this.lastMove.fen : this.game.fenStart
+ );
+ }
+ },
// "light": if gotoMove() or gotoEnd()
// data: some custom data (addTime) to be re-emitted
play: function(move, received, light, data) {
if (!navigate) {
if (!this.inMultimove) {
if (this.cursor < this.moves.length - 1)
- this.moves = this.moves.slice(0, Math.max(this.cursor, 0));
+ this.moves = this.moves.slice(0, this.cursor + 1);
this.moves.push(smove);
this.inMultimove = true; //potentially
this.cursor++;
if (!Array.isArray(move)) move = [move];
for (let i=0; i < move.length; i++) this.vr.play(move[i]);
}
- else playMove();
+ else {
+ playMove();
+ this.emitFenIfAnalyze();
+ }
this.cursor++;
return;
}
if (received && this.cursor < this.moves.length - 1)
this.gotoEnd();
playMove();
+ this.lastMove.fen = this.vr.getFen();
+ this.emitFenIfAnalyze();
},
cancelCurrentMultimove: function() {
// Cancel current multi-move
if (this.st.settings.sound == 2)
new Audio("/sounds/undo.mp3").play().catch(() => {});
this.incheck = this.vr.getCheckSquares(this.vr.turn);
+ this.emitFenIfAnalyze();
}
}
},
// NOTE: next line also re-assign cursor, but it's very light
this.positionCursorTo(index);
this.incheck = this.vr.getCheckSquares(this.vr.turn);
+ this.emitFenIfAnalyze();
},
gotoBegin: function() {
if (this.inMultimove) this.cancelCurrentMultimove();
this.lastMove = null;
}
this.incheck = [];
+ this.emitFenIfAnalyze();
},
gotoEnd: function() {
if (this.cursor == this.moves.length - 1) return;
this.gotoMove(this.moves.length - 1);
+ this.emitFenIfAnalyze();
},
flip: function() {
this.orientation = V.GetOppCol(this.orientation);
"Accept challenge?": "Accept challenge?",
All: "All",
Analyse: "Analyse",
+ "Analysis mode": "Analysis mode",
"Any player": "Any player",
Apply: "Apply",
"Are you sure?": "Are you sure?",
"Accept challenge?": "¿Acceptar el desafío?",
All: "Todos",
Analyse: "Analizar",
+ "Analysis mode": "Modo análisis",
"Any player": "Cualquier jugador",
Apply: "Aplicar",
"Are you sure?": "¿Está usted seguro?",
"Accept challenge?": "Accepter le défi ?",
All: "Tous",
Analyse: "Analyser",
+ "Analysis mode": "Mode analyse",
"Any player": "N'importe qui",
Apply: "Appliquer",
"Authentication successful!": "Authentification réussie !",
p.
In addition to its normal abilities, a piece guarded by a knight can move like him.
On the following diagram, 1.Nf4 would checkmate because it guard the g6 queen.
- If it was black to play, then 1...Rxe2 is possible due to the c8 knight.
+ If it is black to play, then 1...Rxe2 is possible due to the c8 knight.
figure.diagram-container
.diagram
| fen:7k/8/6Q1/1n6/8/2r5/4N3/K7:
+p.
+ A pawn on the sixth rank guarded by a knight could thus make a knight move to reach
+ the last rank and promote.
+
+p These oddities excepted, orthodox rules apply.
+
h3 Source
p
- a(href="TODO") TODO
+ | The original rule is described for example
+ a(href="https://www.chessvariants.com/diffmove.dir/nrelay.html") on this page
+ | . However, I don't really like the invulnerability condition and the restrictions
+ | imposed in these rules, so I implemented this simpler version.
-p TODO
+p.boxed
+ | Cualquier parte protegida por un caballo también puede moverse como un caballo.
+
+p.
+ Además de sus capacidades normales, una pieza defendida por un caballo puede
+ muévete como él.
+ En el siguiente diagrama, 1.Nf4 sería jaque mate porque protege a la dama en g6.
+ Si son las negras para jugar, entonces 1...Rxe2 es posible gracias al caballo c8.
+
+figure.diagram-container
+ .diagram
+ | fen:7k/8/6Q1/1n6/8/2r5/4N3/K7:
+
+p.
+ Un peón en la sexta fila protegido por un caballo podría realizar
+ un salto de caballo para llegar a la última fila y promocionarse.
+
+p Salvo estas rarezas, se aplican las reglas ortodoxas.
+
+h3 Fuente
+
+p
+ | Las reglas de origen se describen por ejemplo
+ a(href="https://www.chessvariants.com/diffmove.dir/nrelay.html") en esta página
+ | . Sin embargo, no me gusta mucho la condición de invulnerabilidad y las
+ | restricciones impuestas por estas reglas, por lo que implementé esta versión simplificada.
-p TODO
+p.boxed
+ | Toute pièce protégée par un cavalier peut aussi se déplacer comme un cavalier.
+
+p.
+ En plus de ses capacités normales, une pièce défendue par un cavalier peut se
+ déplacer comme lui.
+ Sur le diagramme suivant, 1.Nf4 ferait mat car il protège la dame en g6.
+ Si c'est aux noirs de jouer, alors 1...Txe2 est possible grâce au cavalier c8.
+
+figure.diagram-container
+ .diagram
+ | fen:7k/8/6Q1/1n6/8/2r5/4N3/K7:
+
+p.
+ Un pion sur la sixième rangée protégé par un cavalier pourrait ainsi effectuer
+ un coup de cavalier pour atteindre la dernière rangée et se promouvoir.
+
+p Ces bizarreries exceptées, les règles orthodoxes s'appliquent.
+
+h3 Source
+
+p
+ | Les règles d'origine sont décrites par exemple
+ a(href="https://www.chessvariants.com/diffmove.dir/nrelay.html") sur cette page
+ | . Cependant, je n'aime pas vraiment la condition d'invulnérabilité et les
+ | restrictions imposées par ces règles, donc j'ai implémenté cette version simplifiée.
+
-p TODO
+p.boxed
+ | Capturing pieces don't move.
+
+p.
+ Everything is the same as in orthodox chess, except that after capturing
+ a piece, the attacker stay still.
+
+figure.diagram-container
+ .diagram.diag12
+ | fen:r1bqkbnr/p1pppppp/1pn5/7Q/4P3/8/PPPP1PPP/RNB1KBNR:
+ .diagram.diag22
+ | fen:r1bqkbnr/p1ppp2p/1pn5/7Q/4P3/8/PPPP1PPP/RNB1KBNR:
+ figcaption Left: after 1.e4 Nc6 2.Qh5 b6??. Right: after 3.Qxf7+ g6 4.Qxg6#.
+
+p.
+ This "small" difference alters the strategy a lot: guarding pieces is useless,
+ for example, and the king cannot escape a check by capturing.
+
+h3 Source
+
+p
+ a(href="https://www.chessvariants.com/difftaking.dir/rifle.html") Rifle Chess
+ | on chessvariants.com.
-p TODO
+p.boxed
+ | Las piezas que capturan no se mueven.
+
+p.
+ Todo sigue como en el ajedrez ortodoxo, excepto que después de haber capturado
+ una pieza, el atacante se queda en su casilla.
+
+figure.diagram-container
+ .diagram.diag12
+ | fen:r1bqkbnr/p1pppppp/1pn5/7Q/4P3/8/PPPP1PPP/RNB1KBNR:
+ .diagram.diag22
+ | fen:r1bqkbnr/p1ppp2p/1pn5/7Q/4P3/8/PPPP1PPP/RNB1KBNR:
+ figcaption Izquierda: después de 1.e4 Nc6 2.Qh5 b6??. Derecha: después de 3.Qxf7+ g6 4.Qxg6#.
+
+p.
+ Esta "pequeña" diferencia altera enormemente la estrategia: defender las piezas
+ es inútil, por ejemplo, y el rey no puede escapar un jaque capturando.
+
+h3 Fuente
+
+p
+ | La
+ a(href="https://www.chessvariants.com/difftaking.dir/rifle.html") variante Rifle
+ | en chessvariants.com.
-p TODO
+p.boxed
+ | Les pièces capturantes ne bougent pas.
+
+p.
+ Tout se déroule comme aux échecs orthodoxes, excepté qu'après avoir capturé
+ une pièce, l'attaquant reste à sa place.
+
+figure.diagram-container
+ .diagram.diag12
+ | fen:r1bqkbnr/p1pppppp/1pn5/7Q/4P3/8/PPPP1PPP/RNB1KBNR:
+ .diagram.diag22
+ | fen:r1bqkbnr/p1ppp2p/1pn5/7Q/4P3/8/PPPP1PPP/RNB1KBNR:
+ figcaption Gauche: après 1.e4 Nc6 2.Qh5 b6??. Droite: après 3.Qxf7+ g6 4.Qxg6#.
+
+p.
+ Cette "petite" différence altère beaucoup la stratégie : défendre les pièces
+ est inutile, par exemple, et le roi ne pas échapper à un échec en capturant.
+
+h3 Source
+
+p
+ | La
+ a(href="https://www.chessvariants.com/difftaking.dir/rifle.html") variante Rifle
+ | sur chessvariants.com.
-p TODO
+p.boxed
+ | Bishops and queen are less powerful then in standard chess.
+
+ul
+ li Elephants replace the orthodox bishops.
+ li General or vizir replace the orthodox queen.
+ li The only special pawn move is the promotion, always to a vizir.
+ li There is no castling option.
+ li Stalemate or bare king counts as a win, but two bare kings count as a draw.
+p.
+ Note: the general is still represented as a queen, because I didn't find an
+ appropriate image. Please tell me if you have one :)
+
+p
+ | I implemented a slightly different version of Shatranj
+ | as described for example
+ a(href="https://www.chessvariants.com/historic.dir/shatranj.html") on chessvariants.com
+ | , because otherwise elephants could only evolve on a quarter of the board,
+ | and the vizirs would be colorbound as well as the promoted pawns.
+
+p.
+ So, while trying to keep the feeling of this old game,
+ here is what I came up with:
+ul
+ li.
+ Elephants can move by one or two squares diagonally.
+ Only the 2-squares moves (maybe jumping over a piece) can capture.
+ li.
+ Generals can move (without capturing) to any adjacent square
+ horizontally or vertically.
+ They capture on any diagonally adjacent square, so that a general corresponds
+ to a natural pawn promotion.
+p All other pieces move like in orthodoxe chess.
+
+figure.diagram-container
+ .diagram
+ | fen:2bkn3/7R/2qPP3/8/8/3n4/1r3r2/3K4:
+ figcaption White can mate in two moves: see problems section.
-p TODO
+p.boxed
+ | Los alfiles y la dama son menos poderosos que el ajedrez estándar.
+
+ul
+ li Los elefantes reemplazan a los alfiles.
+ li El general o vizir reemplaza a la dama ortodoxa.
+ li El único movimiento de peón especial es la promoción, siempre en vizir.
+ li No hay enroque.
+ li.
+ El empate y un rey desnudo cuentan como una victoria,
+ pero solo dos reyes es equivalente a tablas.
+p.
+ Nota: el general todavía está representado por una dama, porque
+ No encontré una imagen adecuada. Dime si tienes uno :)
+
+p
+ | Implementé una versión ligeramente diferente de Shatranj como
+ | descrito por ejemplo
+ a(href="https://www.chessvariants.com/historic.dir/shatranj.html") en chessvariants.com
+ | , porque de lo contrario los elefantes solo evolucionan en un cuarto de tablero,
+ | y los vizires (así como los peones promocionados) solo viajan un medio tablero
+ | de ajedrez.
+
+p.
+ Entonces, al tratar de permanecer en el espíritu de este antiguo juego,
+ esto es lo que obtuve:
+ul
+ li.
+ Los elefantes pueden mover una o dos cajas en diagonal.
+ Solo los saltos de dos cajas (posiblemente sobre una pieza) pueden capturar.
+ li.
+ Los generales se mueven (sin capturar) en cualquier casilla
+ adyacente, horizontal o verticalmente.
+ Capturan en cualquier casilla diagonalmente adyacente,
+ para que un general corresponda a una promoción de peón natural.
+p Todas las otras piezas se mueven como en el ajedrez ortodoxo.
+
+figure.diagram-container
+ .diagram
+ | fen:2bkn3/7R/2qPP3/8/8/3n4/1r3r2/3K4:
+ figcaption Las blancas pueden mate en dos jugadas: vea la sección de problemas.
-p TODO
+p.boxed
+ | Les fous et la dame sont moins puissants qu'aux échecs standards.
+
+ul
+ li Les éléphants remplacent les fous.
+ li Le général ou vizir remplace la dame orthodoxe
+ li Le seul coup spécial de pion est la promotion, toujours en vizir.
+ li Il n'y a pas de roque.
+ li.
+ Le pat ainsi qu'un roi nu compte comme une victoire,
+ mais deux rois seuls équivaut à un match nul.
+p.
+ Note : le général est encore représenté par une dame, parce que
+ je n'ai pas trouvé d'image appropriée. Dites-moi si vous en avez une :)
+
+p
+ | J'ai implémenté une version légèrement différente du Shatranj telle que
+ | décrite par exemple
+ a(href="https://www.chessvariants.com/historic.dir/shatranj.html") sur chessvariants.com
+ | , car sinon les éléphants n'évoluent que sur un quart d'échiquier,
+ | et les vizirs (ainsi que les pions promus) ne parcourent qu'un demi-échiquier.
+
+p.
+ Donc, tout en essayant de rester dans l'esprit de ce jeu ancien,
+ voici ce à quoi j'ai abouti :
+ul
+ li.
+ Les éléphants peuvent se déplacer d'une ou deux cases en diagonale.
+ Seuls les sauts de deux cases (éventuellement par dessus une pièce)
+ peuvent capturer.
+ li.
+ Les généraux se déplacent (sans capturer) sur n'importe quelle case
+ adjacente, horizontalement ou verticalemnt.
+ Ils capturent sur n'importe quele case diagonalement adjacente,
+ de telle sorte qu'un général correspond à une promotion de pion naturelle.
+p Toutes les autres pièces se déplacent comme aux échecs orthodoxes.
+
+figure.diagram-container
+ .diagram
+ | fen:2bkn3/7R/2qPP3/8/8/3n4/1r3r2/3K4:
+ figcaption Les blancs peuvent mater en deux coups : voir la section problèmes.
li The rook moves one or two squares vertically or horizontally.
li The bishop moves one or two squares diagonally.
li The queen moves either like a rook or like a bishop.
- li.
- The pawn moves like in orthodox chess, but can jumped over pieces at its
- initial potential 2-squares move.
+ li The other pieces move like in orthodox chess.
+p All pieces can jump over others when moving by two squares.
h3 End of the game
li La torre se mueve de una o dos casillas verticalmente u horizontalmente.
li El alfil se mueve de una o dos casillas en diagonal.
li La dama puede moverse como una torre o un alfil.
- li.
- El peón se mueve como en el ajedrez ortodoxo, y también puede saltar
- por encima de una pieza durante su potencial doble movimiento inicial.
+ li Las otras piezas se mueven como en el ajedrez ortodoxo.
+p Todas las piezas pueden saltar sobre otras cuando se mueven dos espacios.
h3 Fin de la partida
li La tour se déplace d'une ou deux cases verticalement ou horizontalement.
li Le fous se déplace d'une ou deux cases en diagonale.
li La dame peut se mouvoir comme une tour ou un fou.
- li.
- Le pion se déplace comme aux échecs orthodoxes, et peut aussi sauter par
- dessus une pièce lors de son potentiel double coup initial.
+ li Les autres pièces se déplacent comme aux échecs orthodoxes.
+p.
+ Toutes les pièces peuvent sauter par dessus d'autres
+ quand elles se déplacent de deux cases.
h3 Fin de la partie
let moves = super.getPotentialMovesFrom([x, y]);
// Expand possible moves if guarded by a knight:
- if (this.getPiece(x,y) != V.KNIGHT) {
+ const piece = this.getPiece(x,y);
+ if (piece != V.KNIGHT) {
const color = this.turn;
let guardedByKnight = false;
for (const step of V.steps[V.KNIGHT]) {
}
}
if (guardedByKnight) {
+ const lastRank = color == "w" ? 0 : V.size.x - 1;
for (const step of V.steps[V.KNIGHT]) {
if (
V.OnBoard(x+step[0],y+step[1]) &&
this.getColor(x+step[0],y+step[1]) != color
) {
- moves.push(this.getBasicMove([x,y], [x+step[0],y+step[1]]));
+ // Potential promotions:
+ const finalPieces = piece == V.PAWN && x + step[0] == lastRank
+ ? [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN]
+ : [V.PAWN];
+ for (let p of finalPieces) {
+ moves.push(
+ this.getBasicMove([x,y], [x+step[0],y+step[1]], {
+ c: color,
+ p: p
+ })
+ );
+ }
}
}
}
}
getPotentialQueenMoves(sq) {
- return this.getSlideNJumpMoves(
+ // Diagonal capturing moves
+ let captures = this.getSlideNJumpMoves(
sq,
V.steps[V.BISHOP],
"oneStep"
+ ).filter(m => m.vanish.length == 2);
+ return captures.concat(
+ // Orthogonal non-capturing moves
+ this.getSlideNJumpMoves(
+ sq,
+ V.steps[V.ROOK],
+ "oneStep"
+ ).filter(m => m.vanish.length == 1)
);
}
);
}
+ getCurrentScore() {
+ const color = this.turn;
+ const getScoreLost = () => {
+ // Result if I lose:
+ return color == "w" ? "0-1" : "1-0";
+ };
+ if (!this.atLeastOneMove())
+ // No valid move: I lose (this includes checkmate)
+ return getScoreLost();
+ // Win if the opponent has no pieces left (except king),
+ // and cannot bare king on the next move.
+ let piecesLeft = {
+ // No need to remember all pieces' squares:
+ // variable only used if just one remaining piece.
+ "w": {count: 0, square: null},
+ "b": {count: 0, square: null}
+ };
+ outerLoop: for (let i=0; i<V.size.x; i++) {
+ for (let j=0; j<V.size.y; j++) {
+ if (this.board[i][j] != V.EMPTY && this.getPiece(i,j) != V.KING) {
+ const sqCol = this.getColor(i,j);
+ piecesLeft[sqCol].count++;
+ piecesLeft[sqCol].square = [i,j];
+ }
+ }
+ }
+ if (Object.values(piecesLeft).every(v => v.count > 0))
+ return "*";
+ // No pieces left for some side: if both kings are bare, it's a draw
+ if (Object.values(piecesLeft).every(v => v.count == 0))
+ return "1/2";
+ if (piecesLeft[color].count > 0)
+ // He could have drawn, but didn't take my last piece...
+ return color == "w" ? "1-0" : "0-1";
+ const oppCol = V.GetOppCol(color);
+ if (piecesLeft[oppCol].count >= 2)
+ // 2 enemy units or more: I lose
+ return getScoreLost();
+ // I don't have any piece, my opponent have one: can I take it?
+ if (this.isAttacked(piecesLeft[oppCol].square, [color]))
+ // Yes! But I still need to take it
+ return "*";
+ // No :(
+ return getScoreLost();
+ }
+
static get VALUES() {
return {
p: 1,
r: 5,
n: 3,
- b: 2.5,
- q: 2,
+ b: 3,
+ q: 3,
k: 1000
};
}
)
BaseGame(
:game="game"
- :vr="vr"
+ @fenchange="setFen"
)
</template>
players: [{ name: "Analyse" }, { name: "Analyse" }],
mode: "analyze"
},
- vr: null, //"variant rules" object initialized from FEN
curFen: ""
};
},
- watch: {
- // NOTE: no watcher for $route change, because if fenStart doesn't change
- // then it doesn't trigger BaseGame.re_init() and the result is weird.
- "vr.movesCount": function() {
- this.curFen = this.vr.getFen();
- this.adjustFenSize();
- }
- },
+ // NOTE: no watcher for $route change, because if fenStart doesn't change
+ // then it doesn't trigger BaseGame.re_init() and the result is weird.
created: function() {
this.gameRef.vname = this.$route.params["vname"];
this.gameRef.fen = this.$route.query["fen"].replace(/_/g, " ");
this.game.fen = this.gameRef.fen;
this.curFen = this.game.fen;
this.adjustFenSize();
- this.vr = new V(this.game.fen);
- this.game.mycolor = this.vr.turn;
+ this.game.mycolor = V.ParseFen(this.gameRef.fen).turn;
this.$set(this.game, "fenStart", this.gameRef.fen);
},
+ // Triggered by "fenchange" emitted in BaseGame:
+ setFen: function(fen) {
+ this.curFen = fen;
+ this.adjustFenSize();
+ },
adjustFenSize: function() {
+ console.log("flababa");
let fenInput = document.getElementById("fen");
fenInput.style.width = this.curFen.length + "ch";
},
v-if="showAnalyzeBtn"
@click="gotoAnalyze()"
)
- | {{ st.tr["Analyse"] }}
+ | {{ st.tr["Analysis mode"] }}
.row
.col-sm-12.col-md-8.col-md-offset-2.col-lg-6.col-lg-offset-3
div(
},
computed: {
showAnalyzeBtn: function() {
- return (this.display=='rules' && (!this.V || this.V.CanAnalyze));
+ return this.V && this.V.CanAnalyze;
},
content: function() {
if (!this.gameInfo.vname) return ""; //variant not set yet