X-Git-Url: https://git.auder.net/?p=vchess.git;a=blobdiff_plain;f=client%2Fsrc%2Fcomponents%2FBaseGame.vue;h=65e96cf6aa42ec5a1711b85556cc83b1a41ccd20;hp=0b6fa05545b00ca92cc653c7b26a470732d27f49;hb=a68362420a3a92099dfaacea10f6cbd579161183;hpb=5aa14a21484cf36838b5541afe2ee76b6d5c274b diff --git a/client/src/components/BaseGame.vue b/client/src/components/BaseGame.vue index 0b6fa055..65e96cf6 100644 --- a/client/src/components/BaseGame.vue +++ b/client/src/components/BaseGame.vue @@ -11,6 +11,7 @@ div#baseGame #gameContainer #boardContainer Board( + ref="board" :vr="vr" :last-move="lastMove" :analyze="game.mode=='analyze'" @@ -22,7 +23,7 @@ div#baseGame @play-move="play" ) #turnIndicator(v-if="showTurn") {{ turn }} - #controls + #controls.button-group button(@click="gotoBegin()") img.inline(src="/images/icons/fast-forward_rev.svg") button(@click="undo()") @@ -86,13 +87,6 @@ export default { stackToPlay: [] }; }, - watch: { - // game initial FEN changes when a new game starts. - // NOTE: when game ID change on Game page, fenStart may be temporarily undefined - "game.fenStart": function(fenStart) { - if (!!fenStart) this.re_setVariables(); - }, - }, computed: { showMoves: function() { return this.game.score != "*" @@ -127,7 +121,7 @@ export default { } }, created: function() { - if (this.game.fenStart) this.re_setVariables(); + if (!!this.game.fenStart) this.re_setVariables(); }, mounted: function() { if (!("ontouchstart" in window)) { @@ -138,9 +132,8 @@ export default { baseGameDiv.addEventListener("keydown", this.handleKeys); baseGameDiv.addEventListener("wheel", this.handleScroll); } - document.getElementById("eogDiv").addEventListener( - "click", - processModalClick); + document.getElementById("eogDiv") + .addEventListener("click", processModalClick); }, methods: { focusBg: function() { @@ -175,22 +168,26 @@ export default { //this.$router.push("/variants/" + this.game.vname); window.open("#/variants/" + this.game.vname, "_blank"); //better }, - re_setVariables: function() { + re_setVariables: function(game) { + if (!game) game = this.game; //in case of... this.endgameMessage = ""; // "w": default orientation for observed games - this.orientation = this.game.mycolor || "w"; - this.moves = JSON.parse(JSON.stringify(this.game.moves || [])); + this.orientation = game.mycolor || "w"; + this.moves = JSON.parse(JSON.stringify(game.moves || [])); // Post-processing: decorate each move with notation and FEN - this.vr = new V(this.game.fenStart); - const parsedFen = V.ParseFen(this.game.fenStart); + this.vr = new V(game.fenStart); + const parsedFen = V.ParseFen(game.fenStart); const firstMoveColor = parsedFen.turn; this.firstMoveNumber = Math.floor(parsedFen.movesCount / 2); + let L = this.moves.length; this.moves.forEach(move => { // Strategy working also for multi-moves: if (!Array.isArray(move)) move = [move]; - move.forEach(m => { + move.forEach((m,idx) => { m.notation = this.vr.getNotation(m); this.vr.play(m); + if (idx < L - 1 && this.vr.getCheckSquares(this.vr.turn).length > 0) + m.notation += "+"; }); }); if (firstMoveColor == "b") { @@ -198,11 +195,18 @@ export default { this.moves.unshift({ notation: "...", start: { x: -1, y: -1 }, - end: { x: -1, y: -1 } + end: { x: -1, y: -1 }, + fen: game.fenStart }); + L++; } this.positionCursorTo(this.moves.length - 1); this.incheck = this.vr.getCheckSquares(this.vr.turn); + const score = this.vr.getCurrentScore(); + if (["1-0","0-1"].includes(score)) + this.moves[L - 1].notation += "#"; + else if (this.vr.getCheckSquares(this.vr.turn).length > 0) + this.moves[L - 1].notation += "+"; }, positionCursorTo: function(index) { this.cursor = index; @@ -214,9 +218,7 @@ export default { } else { this.lastMove = this.moves[index]; } - } - else - this.lastMove = null; + } else this.lastMove = null; }, analyzePosition: function() { let newUrl = @@ -299,12 +301,14 @@ export default { if (this.game.mode == "analyze") { this.$emit( "fenchange", - this.lastMove ? this.lastMove.fen : this.game.fenStart + !!this.lastMove ? this.lastMove.fen : this.game.fenStart ); } }, // "light": if gotoMove() or gotoEnd() play: function(move, received, light, noemit) { + // Freeze while choices are shown: + if (this.$refs["board"].choices.length > 0) return; if (!!noemit) { if (this.inPlay) { // Received moves in observed games can arrive too fast: @@ -315,30 +319,26 @@ export default { } const navigate = !move; const playSubmove = (smove) => { - if (!navigate) smove.notation = this.vr.getNotation(smove); + smove.notation = this.vr.getNotation(smove); this.vr.play(smove); this.lastMove = smove; - // Is opponent in check? - this.incheck = this.vr.getCheckSquares(this.vr.turn); - if (!navigate) { - if (!this.inMultimove) { - if (this.cursor < this.moves.length - 1) - this.moves = this.moves.slice(0, this.cursor + 1); - this.moves.push(smove); - this.inMultimove = true; //potentially - this.cursor++; - } else { - // Already in the middle of a multi-move - const L = this.moves.length; - if (!Array.isArray(this.moves[L-1])) - this.$set(this.moves, L-1, [this.moves[L-1], smove]); - else - this.$set(this.moves, L-1, this.moves.concat([smove])); - } + if (!this.inMultimove) { + if (this.cursor < this.moves.length - 1) + this.moves = this.moves.slice(0, this.cursor + 1); + this.moves.push(smove); + this.inMultimove = true; //potentially + this.cursor++; + } else { + // Already in the middle of a multi-move + const L = this.moves.length; + if (!Array.isArray(this.moves[L-1])) + this.$set(this.moves, L-1, [this.moves[L-1], smove]); + else + this.$set(this.moves, L-1, this.moves.concat([smove])); } }; const playMove = () => { - const animate = V.ShowMoves == "all" && (received || navigate); + const animate = (V.ShowMoves == "all" && !!received); if (!Array.isArray(move)) move = [move]; let moveIdx = 0; let self = this; @@ -359,31 +359,40 @@ export default { } })(); }; + const computeScore = () => { + const score = this.vr.getCurrentScore(); + if (!navigate) { + if (["1-0","0-1"].includes(score)) + this.lastMove.notation += "#"; + else if (this.vr.getCheckSquares(this.vr.turn).length > 0) + this.lastMove.notation += "+"; + } + if (score != "*" && this.game.mode == "analyze") { + const message = getScoreMessage(score); + // Just show score on screen (allow undo) + this.showEndgameMsg(score + " . " + this.st.tr[message]); + } + return score; + }; const afterMove = (smove, initurn) => { if (this.vr.turn != initurn) { // Turn has changed: move is complete - if (!smove.fen) { + if (!smove.fen) // NOTE: only FEN of last sub-move is required (thus setting it here) smove.fen = this.vr.getFen(); - this.emitFenIfAnalyze(); - } + // Is opponent in check? + this.incheck = this.vr.getCheckSquares(this.vr.turn); + this.emitFenIfAnalyze(); this.inMultimove = false; - if (!noemit) { - var score = this.vr.getCurrentScore(); - if (score != "*" && this.game.mode == "analyze") { - const message = getScoreMessage(score); - // Just show score on screen (allow undo) - this.showEndgameMsg(score + " . " + this.st.tr[message]); - } - } - if (!navigate && this.game.mode != "analyze") { - const L = this.moves.length; - if (!noemit) + this.score = computeScore(); + if (this.game.mode != "analyze") { + if (!noemit) { // Post-processing (e.g. computer play). + const L = this.moves.length; // NOTE: always emit the score, even in unfinished, // to tell Game::processMove() that it's not a received move. - this.$emit("newmove", this.moves[L-1], { score: score }); - else { + this.$emit("newmove", this.moves[L-1], { score: this.score }); + } else { this.inPlay = false; if (this.stackToPlay.length > 0) // Move(s) arrived in-between @@ -397,13 +406,13 @@ export default { // The move to navigate to is necessarily full: if (this.cursor == this.moves.length - 1) return; //no more moves move = this.moves[this.cursor + 1]; - if (light) { - // Just play the move, nothing else: - if (!Array.isArray(move)) move = [move]; - for (let i=0; i < move.length; i++) this.vr.play(move[i]); - } - else { - playMove(); + // Just play the move: + if (!Array.isArray(move)) move = [move]; + for (let i=0; i < move.length; i++) this.vr.play(move[i]); + if (!light) { + this.lastMove = move[move.length-1]; + this.incheck = this.vr.getCheckSquares(this.vr.turn); + this.score = computeScore(); this.emitFenIfAnalyze(); } this.cursor++; @@ -439,15 +448,20 @@ export default { }, // "light": if gotoMove() or gotoBegin() undo: function(move, light) { + // Freeze while choices are shown: + if (this.$refs["board"].choices.length > 0) return; if (this.inMultimove) { this.cancelCurrentMultimove(); this.incheck = this.vr.getCheckSquares(this.vr.turn); } else { if (!move) { - if (this.cursor < 0) return; //no more moves + const minCursor = + this.moves.length > 0 && this.moves[0].notation == "..." + ? 1 + : 0; + if (this.cursor < minCursor) return; //no more moves move = this.moves[this.cursor]; } - // Caution; if multi-move, undo all submoves from last to first undoMove(move, this.vr); if (light) this.cursor--; else { @@ -458,6 +472,7 @@ export default { } }, gotoMove: function(index) { + if (this.$refs["board"].choices.length > 0) return; if (this.inMultimove) this.cancelCurrentMultimove(); if (index == this.cursor) return; if (index < this.cursor) { @@ -475,24 +490,25 @@ export default { this.emitFenIfAnalyze(); }, gotoBegin: function() { + if (this.$refs["board"].choices.length > 0) return; if (this.inMultimove) this.cancelCurrentMultimove(); - while (this.cursor >= 0) - this.undo(null, null, "light"); - if (this.moves.length > 0 && this.moves[0].notation == "...") { - this.cursor = 0; - this.lastMove = this.moves[0]; - } else { - this.lastMove = null; - } - this.incheck = []; + const minCursor = + this.moves.length > 0 && this.moves[0].notation == "..." + ? 1 + : 0; + while (this.cursor >= minCursor) this.undo(null, null, "light"); + this.lastMove = (minCursor == 1 ? this.moves[0] : null); + this.incheck = this.vr.getCheckSquares(this.vr.turn); this.emitFenIfAnalyze(); }, gotoEnd: function() { + if (this.$refs["board"].choices.length > 0) return; 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; this.orientation = V.GetOppCol(this.orientation); } } @@ -516,12 +532,9 @@ export default { display: inline-block #controls - margin: 0 auto - text-align: center - display: flex + user-select: none button - display: inline-block - width: 20% + border: none margin: 0 padding-top: 5px padding-bottom: 5px