From: Benjamin Auder Date: Mon, 14 Jan 2019 15:52:55 +0000 (+0100) Subject: Fix moveList + progress on game navigation system X-Git-Url: https://git.auder.net/%7B%7B%20asset%28%27mixstore/images/doc/html/assets/%7B%7B?a=commitdiff_plain;h=7d9e99bc177972c5af8b1b45f4bfb043d8306f30;p=vchess.git Fix moveList + progress on game navigation system --- diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js index 4b0b4705..7db4cfde 100644 --- a/public/javascripts/base_rules.js +++ b/public/javascripts/base_rules.js @@ -1053,6 +1053,8 @@ class ChessRules move.flags = JSON.stringify(this.aggregateFlags()); //save flags (for undo) if (V.HasEnpassant) this.epSquares.push( this.getEpSquare(move) ); + if (!move.color) + move.color = this.turn; //for interface V.PlayOnBoard(this.board, move); this.turn = V.GetOppCol(this.turn); this.movesCount++; diff --git a/public/javascripts/components/game.js b/public/javascripts/components/game.js index 594c8c22..4048a3d4 100644 --- a/public/javascripts/components/game.js +++ b/public/javascripts/components/game.js @@ -24,8 +24,10 @@ Vue.component('my-game', { vr: null, //VariantRules object, describing the game state + rules endgameMessage: "", orientation: "w", + fenStart: "", moves: [], //TODO: initialize if gameId is defined... + cursor: 0, // orientation :: button flip // userColor: given by gameId, or fen (if no game Id) // gameOver: known if gameId; otherwise assue false @@ -47,6 +49,7 @@ Vue.component('my-game', { return this.allowChat && this.mode=='human' && this.score != '*'; }, showMoves: function() { + return true; return this.allowMovelist && window.innerWidth >= 768; }, showFen: function() { @@ -81,6 +84,13 @@ Vue.component('my-game', { +
+ + + + + +

{{ vr.getFen() }} @@ -93,18 +103,18 @@ Vue.component('my-game', { {{ translate("Download PGN") }}

- + `, created: function() { - -// console.log(this.fen); -// console.log(this.gameId); if (!!this.gameId) this.loadGame(); else if (!!this.fen) + { this.vr = new VariantRules(this.fen); + this.fenStart = this.fen; + } // TODO: after game, archive in indexedDB // TODO: this events listener is central. Refactor ? How ? const socketMessageListener = msg => { @@ -316,12 +326,25 @@ Vue.component('my-game', { }, 250); }, play: function(move, programmatic) { + // Forbid playing outside analyze mode when cursor isn't at moves.length-1 + if (this.mode != "analyze" && this.cursor < this.moves.length-1) + return; + let navigate = !move; + if (navigate) + { + if (this.cursor == this.moves.length) + return; //no more moves + move = this.moves[this.cursor]; + } if (!!programmatic) //computer or human opponent return this.animateMove(move); // Not programmatic, or animation is over if (!move.notation) move.notation = this.vr.getNotation(move); + if (!move.color) + move.color = this.vr.turn; this.vr.play(move); + this.cursor++; if (!move.fen) move.fen = this.vr.getFen(); if (this.sound == 2) @@ -337,10 +360,13 @@ Vue.component('my-game', { // Send the move to web worker (including his own moves) this.compWorker.postMessage(["newmove",move]); } - if (this.score == "*" || this.mode == "analyze") + if (!navigate && (this.score == "*" || this.mode == "analyze")) { - // Stack move on movesList - this.moves.push(move); + // Stack move on movesList at current cursor + if (this.cursor == this.moves.length) + this.moves.push(move); + else + this.moves = this.moves.slice(0,this.cursor-1).concat([move]); } // Is opponent in check? this.incheck = this.vr.getCheckSquares(this.vr.turn); @@ -355,18 +381,45 @@ Vue.component('my-game', { } else if (this.mode == "computer" && this.vr.turn != this.userColor) this.playComputerMove(); + if (navigate) + this.$children[0].$forceUpdate(); //TODO!? }, undo: function(move) { + let navigate = !move; + if (navigate) + { + if (this.cursor == 0) + return; //no more moves + move = this.moves[this.cursor-1]; + } this.vr.undo(move); + this.cursor--; + if (navigate) + this.$children[0].$forceUpdate(); //TODO!? if (this.sound == 2) new Audio("/sounds/undo.mp3").play().catch(err => {}); this.incheck = this.vr.getCheckSquares(this.vr.turn); - if (this.mode == "analyze") + if (!navigate && this.mode == "analyze") this.moves.pop(); + if (navigate) + this.$forceUpdate(); //TODO!? + }, + gotoMove: function(index) { + this.vr = new VariantRules(this.moves[index].fen); + this.cursor = index+1; + }, + gotoBegin: function() { + this.vr = new VariantRules(this.fenStart); + this.cursor = 0; + }, + gotoEnd: function() { + this.gotoMove(this.moves.length-1); + }, + flip: function() { + this.orientation = V.GetNextCol(this.orientation); }, }, }) -// cursor + ........ //TODO: confirm dialog with "opponent offers draw", avec possible bouton "prevent future offers" + bouton "proposer nulle" //+ bouton "abort" avec score == "?" + demander confirmation pour toutes ces actions, //comme sur lichess diff --git a/public/javascripts/components/moveList.js b/public/javascripts/components/moveList.js index 3687864c..b3c4255f 100644 --- a/public/javascripts/components/moveList.js +++ b/public/javascripts/components/moveList.js @@ -1,12 +1,12 @@ //TODO: component for moves list on the right // TODO: generic "getPGN" in the same way (following move.color) Vue.component('my-move-list', { - props: ["moves"], //TODO: other props for e.g. players names + connected indicator + props: ["moves","cursor"], //TODO: other props for e.g. players names + connected indicator // --> we could also add turn indicator here + // + missing "cursor" prop data: function() { return { - // if oppid == "computer" then mode = "computer" (otherwise human) - myid: "", //TODO + something: "", //TODO }; }, // TODO: extend rendering for more than 2 colors: would be a parameter @@ -14,8 +14,9 @@ Vue.component('my-move-list', { if (this.moves.length == 0) return; const nbColors = 2; - if (this.moves[0].color == "black") - this.moves.unshift({color: "white", notation: "..."}); + // TODO: name colors "white", "black", "red", "yellow" ? + if (this.moves[0].color == "b") + this.moves.unshift({color: "w", notation: "..."}); let tableContent = []; let moveCounter = 0; let tableRow = undefined; @@ -23,45 +24,62 @@ Vue.component('my-move-list', { let curCellContent = ""; for (let i=0; i0 && this.moves[i-1].color=="black") + if (i == 0 || i>0 && this.moves[i-1].color=="b") { if (!!tableRow) + { + tableRow.children = moveCells; tableContent.push(tableRow); + } moveCells = [ h( "td", - { attrs: { innerHTML: (++moveCounter) + "." } } + { domProps: { innerHTML: (++moveCounter) + "." } } ) ]; tableRow = h( "tr", - { }, - moveCells + { } ); curCellContent = ""; } - curCellContent += this.moves[i].notation + ","; + } + curCellContent += this.moves[i].notation; + if (i < this.moves.length-1 && this.moves[i+1].color == this.moves[i].color) + curCellContent += ","; + else //color change + { moveCells.push( h( "td", - { attrs: .............. + { + domProps: { innerHTML: curCellContent }, + on: { click: () => this.gotoMove(i) }, + "class": { "highlight-lm": this.cursor-1 == i }, + } + ) + ); + curCellContent = ""; } } // Complete last row, which might not be full: - if (tableRow.length-1 < nbColors) + if (moveCells.length-1 < nbColors) { const delta = nbColors - (moveCells.length-1); for (let i=0; i