return (Object.keys(V.ALICE_PIECES).includes(b[1]) ? "Alice/" : "") + b;
}
+ getEpSquare(moveOrSquare) {
+ if (!moveOrSquare) return undefined;
+ if (typeof moveOrSquare === "string") {
+ const square = moveOrSquare;
+ if (square == "-") return undefined;
+ return V.SquareToCoords(square);
+ }
+ // Argument is a move:
+ const move = moveOrSquare;
+ const s = move.start,
+ e = move.end;
+ if (
+ s.y == e.y &&
+ Math.abs(s.x - e.x) == 2 &&
+ // Special conditions: a pawn can be on the other side
+ ['p','s'].includes(move.appear[0].p) &&
+ ['p','s'].includes(move.vanish[0].p)
+ ) {
+ return {
+ x: (s.x + e.x) / 2,
+ y: s.y
+ };
+ }
+ return undefined; //default
+ }
+
setOtherVariables(fen) {
super.setOtherVariables(fen);
const rows = V.ParseFen(fen).position.split("/");
//atLeastOneMove() should be OK
+ doClick(square) {
+ // A click to promote a piece on subTurn 2 would trigger this.
+ // For now it would then return [NaN, NaN] because surrounding squares
+ // have no IDs in the promotion modal. TODO: improve this?
+ if (!square[0]) return null;
+ // If subTurn == 2:
+ // if square is empty && firstMove is compatible,
+ // complete the move (banana or bomb).
+ // if square not empty, just complete with empty move
+ const Lf = this.firstMove.length;
+ if (this.subTurn == 2) {
+ if (
+ this.board[square[0]][square[1]] == V.EMPTY &&
+ !this.underCheck(this.turn) &&
+ (La == 0 || !this.oppositeMoves(this.amoves[La-1], this.firstMove[Lf-1]))
+ ) {
+ return {
+ start: { x: -1, y: -1 },
+ end: { x: -1, y: -1 },
+ appear: [],
+ vanish: []
+ };
+ }
+ }
+ return null;
+ }
+
+ postPlay(move) {
+ // TODO: king may also be "chomped"
+ super.updateCastleFlags(move, piece);
+ }
+
getCurrentScore() {
+ if (this.kingPos[this.turn][0] < 0)
+ // King captured (or "chomped")
+ return this.turn == "w" ? "0-1" : "1-0";
+ const color = V.GetOppCol(this.turn);
+ const lastRank = (color == 'w' ? 0 : 7);
+ if (this.kingPos[color][0] == lastRank)
+ // The opposing edge is reached!
+ return color == "w" ? "1-0" : "0-1";
+ if (this.atLeastOneMove()) return "*";
+ // Game over
+ const oppCol = this.turn;
+ if (!this.underCheck(oppCol)) return "1/2";
+ return (oppCol == "w" ? "0-1" : "1-0");
//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 '*';
}
+ getComputerMove() {
+ // TODO: random mover
+ }
+
//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 :)
return Object.assign(
{},
ChessRules.PawnSpecs,
- {
- twoSquares: false,
- promotions: ChessRules.PawnSpecs.promotions.concat([V.GRASSHOPPER])
- }
+ { promotions: ChessRules.PawnSpecs.promotions.concat([V.GRASSHOPPER]) }
);
}
return Object.assign(
{},
ChessRules.PawnSpecs,
- {
- twoSquares: false,
- promotions: [V.QUEEN]
- }
+ { promotions: [V.QUEEN] }
);
}
{},
ChessRules.PawnSpecs,
{
- twoSquares: false,
// Promotions are handled differently here
promotions: [V.QUEEN]
}
)
.card
label.modal-close(for="modalRules")
- h4#variantNameInAnalyze(@click="gotoRules()") {{ game.vname }}
+ a#variantNameInAnalyze(:href="'/#/variants/'+game.vname")
+ | {{ game.vname }}
div(v-html="rulesContent")
.row
.col-sm-12
.replace(/"$/, "")
.replace(/(fen:)([^:]*):/g, replaceByDiag);
},
- gotoRules: function() {
- this.$router.push("/variants/" + this.gameRef.vname);
- },
loadGame: function(orientation) {
this.game.vname = this.gameRef.vname;
this.game.fenStart = this.gameRef.fen;
</style>
<style lang="sass" scoped>
-h4#variantNameInAnalyze
- cursor: pointer
+a#variantNameInAnalyze
+ color: var(--card-fore-color)
text-align: center
- text-decoration: underline
font-weight: bold
+ font-size: calc(1rem * var(--heading-ratio))
+ line-height: 1.2
+ margin: calc(1.5 * var(--universal-margin))
#rulesDiv > .card
padding: 5px 0
)
.card
label.modal-close(for="modalRules")
- h4#variantNameInGame(@click="gotoRules") {{ game.vname }}
+ a#variantNameInGame(:href="'/#/variants/'+game.vname") {{ game.vname }}
div(v-html="rulesContent")
input#modalScore.modal(type="checkbox")
div#scoreDiv(
},
// NOTE: some redundant code with Hall.vue (mostly related to people array)
created: function() {
+ if (this.$route.query["focus"] === "false")
+ // Focus explicitely set to false from Hall (live game)
+ this.focus = false;
this.atCreation();
},
mounted: function() {
)
);
},
- gotoRules: function() {
- this.$router.push("/variants/" + this.game.vname);
- },
participateInChat: function(p) {
return Object.keys(p.tmpIds).some(x => p.tmpIds[x].focus) && !!p.name;
},
button.refuseBtn
background-color: red
-h4#variantNameInGame
- cursor: pointer
+a#variantNameInGame
+ color: var(--card-fore-color)
text-align: center
- text-decoration: underline
font-weight: bold
+ font-size: calc(1rem * var(--heading-ratio))
+ line-height: 1.2
+ margin: calc(1.5 * var(--universal-margin))
</style>
<style lang="sass">
}
});
const gid = gids[Math.floor(Math.random() * gids.length)];
- const game = this.games.find(g => g.id == gid);
- if (!!game) this.showGame(game);
- else this.$router.push("/game/" + gid); //game vs. me
+ window.open("/#/game/" + gid, "_blank");
},
showGame: function(g) {
// NOTE: we are an observer, since only games I don't play are shown here
// ==> Moves sent by connected remote player(s) if live game
- this.$router.push("/game/" + g.id);
+ window.open("/#/game/" + g.id, "_blank");
},
toggleSocialColor: function(action) {
if (!action && document.getElementById("modalPeople").checked)
{ body: "vs " + game.players[1-myIdx].name || "@nonymous" }
);
}
- this.$router.push("/game/" + gameInfo.id);
+ this.$router.push(
+ "/game/" + gameInfo.id + "/?focus=" + this.focus);
});
},
this.focus ? 500 + 1000 * Math.random() : 0