// Post-processing: decorate each move with notation and FEN
this.vr = new V(game.fenStart);
this.inMultimove = false; //in case of
- this.$refs["board"].resetCurrentAttempt(); //also in case of
+ if (!!this.$refs["board"])
+ // Also in case of:
+ this.$refs["board"].resetCurrentAttempt();
let analyseBtn = document.getElementById("analyzeBtn");
if (!!analyseBtn) analyseBtn.classList.remove("active");
const parsedFen = V.ParseFen(game.fenStart);
this.firstMoveNumber = Math.floor(parsedFen.movesCount / 2) + 1;
let L = this.moves.length;
if (L == 0) {
- this.incheck = [];
- this.score = "*";
+ // Could be started on a random position in analysis mode:
+ this.incheck = this.vr.getCheckSquares();
+ this.score = this.vr.getCurrentScore();
+ if (this.score != '*') {
+ // Show score on screen
+ const message = getScoreMessage(this.score);
+ this.showEndgameMsg(this.score + " . " + this.st.tr[message]);
+ }
}
- this.moves.forEach((move,idx) => {
- // Strategy working also for multi-moves:
- if (!Array.isArray(move)) move = [move];
- const Lm = move.length;
- move.forEach((m,idxM) => {
- m.notation = this.vr.getNotation(m);
- m.unambiguous = V.GetUnambiguousNotation(m);
- this.vr.play(m);
- const checkSquares = this.vr.getCheckSquares();
- if (checkSquares.length > 0) m.notation += "+";
- if (idxM == Lm - 1) m.fen = this.vr.getFen();
- if (idx == L - 1 && idxM == Lm - 1) {
- this.incheck = checkSquares;
- this.score = this.vr.getCurrentScore();
- if (["1-0", "0-1"].includes(this.score)) m.notation += "#";
- }
+ else {
+ this.moves.forEach((move,idx) => {
+ // Strategy working also for multi-moves:
+ if (!Array.isArray(move)) move = [move];
+ const Lm = move.length;
+ move.forEach((m,idxM) => {
+ m.notation = this.vr.getNotation(m);
+ m.unambiguous = V.GetUnambiguousNotation(m);
+ this.vr.play(m);
+ const checkSquares = this.vr.getCheckSquares();
+ if (checkSquares.length > 0) m.notation += "+";
+ if (idxM == Lm - 1) m.fen = this.vr.getFen();
+ if (idx == L - 1 && idxM == Lm - 1) {
+ this.incheck = checkSquares;
+ this.score = this.vr.getCurrentScore();
+ if (["1-0", "0-1"].includes(this.score)) m.notation += "#";
+ }
+ });
});
- });
+ }
if (firstMoveColor == "b") {
// 'start' & 'end' is required for Board component
this.moves.unshift({
// "light": if gotoMove() or gotoEnd()
play: function(move, received, light, autoplay) {
// Freeze while choices are shown:
- if (this.$refs["board"].choices.length > 0) return;
+ if (
+ !!this.$refs["board"].selectedPiece ||
+ this.$refs["board"].choices.length > 0
+ ) {
+ return;
+ }
const navigate = !move;
// Forbid navigation during autoplay:
if (navigate && this.autoplay && !autoplay) return;
},
// "light": if gotoMove() or gotoBegin()
undo: function(move, light) {
- // Freeze while choices are shown:
- if (this.$refs["board"].choices.length > 0 || this.autoplay) return;
+ if (
+ this.autoplay ||
+ !!this.$refs["board"].selectedPiece ||
+ this.$refs["board"].choices.length > 0
+ ) {
+ return;
+ }
this.$refs["board"].resetCurrentAttempt();
if (this.inMultimove) {
this.cancelCurrentMultimove();
}
},
gotoMove: function(index) {
- if (this.$refs["board"].choices.length > 0 || this.autoplay) return;
+ if (
+ this.autoplay ||
+ !!this.$refs["board"].selectedPiece ||
+ this.$refs["board"].choices.length > 0
+ ) {
+ return;
+ }
this.$refs["board"].resetCurrentAttempt();
if (this.inMultimove) this.cancelCurrentMultimove();
if (index == this.cursor) return;
this.emitFenIfAnalyze();
},
gotoBegin: function() {
- if (this.$refs["board"].choices.length > 0 || this.autoplay) return;
+ if (
+ this.autoplay ||
+ !!this.$refs["board"].selectedPiece ||
+ this.$refs["board"].choices.length > 0
+ ) {
+ return;
+ }
this.$refs["board"].resetCurrentAttempt();
if (this.inMultimove) this.cancelCurrentMultimove();
const minCursor =
this.emitFenIfAnalyze();
},
gotoEnd: function() {
- if (this.$refs["board"].choices.length > 0 || this.autoplay) return;
- this.$refs["board"].resetCurrentAttempt();
if (this.cursor == this.moves.length - 1) return;
this.gotoMove(this.moves.length - 1);
- this.emitFenIfAnalyze();
},
flip: function() {
if (this.$refs["board"].choices.length > 0) return;
--- /dev/null
+import { ChessRules } from "@/base_rules";
+
+export class ChakartRules extends ChessRules {
+ // NOTE: getBasicMove, ajouter les bonus à vanish array
+ // + déterminer leur effet (si cavalier) ou case (si banane ou bombe)
+ // (L'effet doit être caché au joueur : devrait être OK)
+ //
+ // Saut possible par dessus bonus ou champis mais pas bananes ou bombes
+
+ // FEN : immobilized (pas flag), castle flags + flags peach (power used?)
+ // "pièces" supplémentaires : bananes, bombes, champis, bonus --> + couleur ?
+ // (Semble mieux sans couleur => couleur spéciale indiquant que c'est pas jouable)
+ // (Attention: pas jouables cf. getPotentialMoves...)
+
+ setOtherVariables(fen) {
+ super.setOtherVariables(fen);
+ this.subTurn = 1;
+ }
+
+ getPotentialMovesFrom([x, y]) {
+ // TODO: bananes et bombes limitent les déplacements (agissent comme un mur "capturable")
+ // bananes jaunes et rouges ?! (agissant sur une seule couleur ?) --> mauvaise idée.
+ if (this.subTurn == 2) {
+ // TODO: coup compatible avec firstMove
+ }
+ }
+
+ getPotentialPawnMoves(sq) {
+ //Toad: pion
+ // laisse sur sa case de départ un champi turbo permettant à Peach d'aller
+ // une case plus loin, et aux pièces arrivant sur cette case de sauter par
+ // dessus une pièce immédiatement adjacente (en atterissant juste derrière).
+ }
+
+ // Coups en 2 temps (si pose)
+ getPotentialRookMoves(sq) {
+ //Donkey : tour
+ // pose une banane (optionnel) sur une case adjacente (diagonale) à celle d'arrivée
+ // Si une pièce arrive sur la peau de banane, alors elle effectue un déplacement
+ // aléatoire d'une (2?) case (vertical ou horizontal) depuis sa position finale.
+ }
+
+ // Coups en 2 temps (si pose)
+ getPotentialBishopMoves([x, y]) {
+ //Wario: fou
+ // pose une bombe (optionnel) sur une case orthogonalement adjacente à la case d'arrivée
+ // Si une pièce arrive sur une bombe, alors elle effectue un déplacement diagonal
+ // aléatoire d'une (2?) case depuis sa position finale (juste une case si impossible).
+ }
+
+ getPotentialKnightMoves([x, y]) {
+ //Yoshi: cavalier
+ // laisse sur sa case de départ un bonus aléatoire
+ // (NOTE: certains bonus pourraient ne pas être applicables ==> pion bloqué par exemple)
+ // - i) roi boo(*E*) : échange avec n'importe quelle pièce (choix du joueur, type et/ou couleur différents)
+ // à condition que la position résultante ne soit pas un auto-échec
+ // - i*) koopa(*B*) : ramène sur la case initiale
+ // - ii) toadette(*R*) : permet de poser une pièce capturée sur le plateau
+ // (n'importe où sauf 8eme rangée pour les pions)
+ // - ii*) chomp(*W*) : mange la pièce ; si c'est Peach, c'est perdu
+ // - iii) daisy(*T*) : permet de rejouer un coup avec la même pièce --> cumulable si ensuite coup sur bonus Daisy.
+ // - iii*) bowser(*M*) : immobilise la pièce (marquée jaune/rouge), qui ne pourra pas jouer au tour suivant
+ // - iv) luigi(*L*) : fait changer de camp une pièce adverse (aléatoire ?) (sauf le roi)
+ // - iv*) waluigi(*D*) : fait changer de camp une de nos pièces (aléatoire ?) (sauf le roi)
+ // --> i, ii, iii en deux temps (subTurn 1 & 2)
+ // iii* : indication dans FEN (immobilized)
+ }
+
+ getPotentialQueenMoves(sq) {
+ //Mario: dame
+ // pouvoir "casquette ailée" (à chaque coup?) : peut sauter par dessus n'importe quelle pièce (une seule), sans la capturer.
+ }
+
+ getPotentialKingMoves(sq) {
+ //Peach: roi
+ // Carapace rouge (disons ^^) jouable une seule fois dans la partie,
+ // au lieu de se déplacer. Capture un ennemi au choix parmi les plus proches,
+ // à condition qu'ils soient visible (suivant les directions de déplacement d'une dame).
+ // Profite des accélérateurs posés par les pions (+ 1 case : obligatoire).
+ }
+
+ play(move) {
+ // TODO: subTurn passe à 2 si potentiellement pose (tour, fou) ou si choix (reconnaître i (ok), ii (ok) et iii (si coup normal + pas immobilisé) ?)
+ // voire +2 si plusieurs daisy...
+ }
+
+ undo(move) {
+ // TODO: reconnaissance inverse si subTurn == 1 --> juste impossible ==> marquer pendant play (comme DoubleMove1 : move.turn = ...)
+ }
+
+ //atLeastOneMove() should be OK
+
+ getCurrentScore() {
+ //TODO: But = capturer la princesse adverse. Variante : but = la princesse arrive de l'autre côté de l'échiquier.
+ //==> On peut mixer ces deux conditions : arriver au bout du plateau ou capturer la princesse adverse.
+ return '*';
+ }
+
+ //Détails :
+ //Si une pièce pose quelque chose sur une case ça remplace ce qui y était déjà.
+ //Pas de condition de pat, puisque l'objectif est la capture de la reine :)
+};
this.isAttackedByKheshig(sq, color)
);
}
- // Horde: only pawn and queen (if promotions) in common:
+ // Horde: only pawn, king and queen (if promotions) in common:
return (
super.isAttackedByPawn(sq, color) ||
this.isAttackedByLancer(sq, color) ||
this.isAttackedByKheshig(sq, color) ||
this.isAttackedByArcher(sq, color) ||
this.isAttackedByYurt(sq, color) ||
+ super.isAttackedByKing(sq, color) ||
super.isAttackedByQueen(sq, color)
);
}
);
}
+ getPotentialLanceMoves(sq) {
+ const forward = (this.turn == 'w' ? -1 : 1);
+ return this.getSlideNJumpMoves(
+ sq,
+ [[forward, 0]],
+ {
+ promote: V.P_LANCE,
+ force: true
+ }
+ );
+ }
+
getPotentialRookMoves(sq) {
return this.getSlideNJumpMoves(
sq, V.steps[V.ROOK], { promote: V.P_ROOK });
sq, V.steps[V.BISHOP], { promote: V.P_BISHOP });
}
- getPotentialLanceMoves(sq) {
- const forward = (this.turn == 'w' ? -1 : 1);
- return this.getSlideNJumpMoves(
- sq, [[forward, 0]], { promote: V.P_LANCE });
- }
-
getPotentialDragonMoves(sq) {
return (
this.getSlideNJumpMoves(sq, V.steps[V.ROOK]).concat(
// Ignore games where I play (will go in MyGames page),
// and also games that I already received.
if (
+ this.games.findIndex(g => g.id == game.id) == -1 &&
game.players.every(p => {
return (
p.sid != this.st.user.sid &&
(p.id == 0 || p.id != this.st.user.id)
);
- }) && this.games.findIndex(g => g.id == game.id) == -1
+ })
) {
let newGame = game;
newGame.type = this.classifyObject(game);
newGame.score = "*";
this.games.push(newGame);
if (
+ newGame.score == '*' &&
(newGame.type == "live" && this.gdisplay == "corr") ||
(newGame.type == "corr" && this.gdisplay == "live")
) {
if (
this.cursor == Number.MAX_SAFE_INTEGER &&
this.games.length == 0 &&
- this.gdisplay == "live"
+ this.gdisplay == "live" &&
+ res.games.some(g => g.score == '*')
) {
// First loading: show indicators
document
db.serialize(function() {
let query =
"SELECT id, vid, cadence, created, score, white, black " +
- "FROM Games ";
- if (uid > 0) query +=
- "WHERE " +
- " created < " + cursor + " AND " +
- " white <> " + uid + " AND " +
- " black <> " + uid + " ";
+ "FROM Games " +
+ "WHERE created < " + cursor + " ";
+ if (uid > 0) {
+ query +=
+ " AND white <> " + uid + " " +
+ " AND black <> " + uid + " ";
+ }
query +=
"ORDER BY created DESC " +
"LIMIT 20"; //TODO: 20 hard-coded...