From e64a4effa6b357addc3253504870cf1a6fc29977 Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Sat, 17 Nov 2018 18:11:18 +0100 Subject: [PATCH] Highlight king in red if undercheck + some improvements --- TODO | 4 ++- public/javascripts/base_rules.js | 52 ++++++++++++++++++++------- public/javascripts/components/game.js | 26 ++++++++++++-- public/stylesheets/variant.sass | 9 +++-- 4 files changed, 73 insertions(+), 18 deletions(-) diff --git a/TODO b/TODO index 92929ac7..dafd7c0b 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,4 @@ -End of game a bit too verbose: should just say "Black win" ... + show PGN Styles must be improved (full width for smartphones, selectable text for PGN...) +Tooltip text should fade (even when mouse stay on it, especially for small screens) +Checkered stage 2: switch button at reserve position. +If a played disconnect right after opponent sent a move, it might be never received: secure this diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js index de1a0d0f..9a4ef912 100644 --- a/public/javascripts/base_rules.js +++ b/public/javascripts/base_rules.js @@ -517,6 +517,32 @@ class ChessRules // No: if happen on last 1/2 move, could lead to forbidden moves, wrong evals return this.filterValid(potentialMoves); } + + // Stop at the first move found + atLeastOneMove(color) + { + const oppCol = this.getOppCol(color); + let [sizeX,sizeY] = VariantRules.size; + for (var i=0; i 0) + { + for (let i=0; i 0) + return true; + } + } + } + } + } + return false; + } // Check if pieces of color 'color' are attacking square x,y isAttacked(sq, color) @@ -676,12 +702,15 @@ class ChessRules this.movesCount++; } - undo(move) + undo(move, ingame) { VariantRules.UndoOnBoard(this.board, move); this.epSquares.pop(); this.movesCount--; + if (!!ingame) + this.moves.pop(); + // Update king position, and reset stored/computed flags const c = this.getColor(move.start.x,move.start.y); if (this.getPiece(move.start.x,move.start.y) == VariantRules.KING) @@ -709,8 +738,7 @@ class ChessRules } } - // TODO: not required to generate ALL: just need one (callback ? hook ? ...) - if (this.getAllValidMoves(color).length > 0) + if (this.atLeastOneMove(color)) { // game not over return "*"; @@ -779,14 +807,14 @@ class ChessRules moves1.sort( (a,b) => { return (color=="w" ? 1 : -1) * (b.eval - a.eval); }); // TODO: show current analyzed move for depth 3, allow stopping eval (return moves1[0]) -// for (let i=0; i { return (color=="w" ? 1 : -1) * (b.eval - a.eval); }); + for (let i=0; i { return (color=="w" ? 1 : -1) * (b.eval - a.eval); }); let candidates = [0]; //indices of candidates moves for (let j=1; j { + if (this.mode == "human") + return; //no newgame while playing if (this.seek) delete localStorage["newgame"]; //cancel game seek else @@ -55,7 +58,13 @@ Vue.component('my-game', { [h('i', { 'class': { "material-icons": true } }, "accessibility")]), h('button', { - on: { click: () => this.newGame("computer") }, + on: { + click: () => { + if (this.mode == "human") + return; //no newgame while playing + this.newGame("computer"); + } + }, attrs: { "aria-label": 'New game VS computer' }, 'class': { "tooltip":true, @@ -162,7 +171,9 @@ Vue.component('my-game', { ); } const lm = this.vr.lastMove; - const highlight = !!lm && _.isMatch(lm.end, {x:ci,y:cj}); //&& _.isMatch(lm.start, {x:ci,y:cj}) + const highlight = !!lm && _.isMatch(lm.end, {x:ci,y:cj}); + const incheck = this.incheck + && _.isEqual(this.vr.kingPos[this.vr.turn], [ci,cj]); return h( 'div', { @@ -171,6 +182,7 @@ Vue.component('my-game', { 'light-square': !highlight && (i+j)%2==0, 'dark-square': !highlight && (i+j)%2==1, 'highlight': highlight, + 'incheck': incheck, }, attrs: { id: this.getSquareId({x:ci,y:cj}), @@ -483,6 +495,14 @@ Vue.component('my-game', { this.oppConnected = true; this.mycolor = color; this.seek = false; + if (!!moves && moves.length > 0) //imply continuation + { + const oppCol = this.vr.turn; + const lastMove = moves[moves.length-1]; + this.vr.undo(lastMove); + this.incheck = this.vr.underCheck(lastMove, oppCol); + this.vr.play(lastMove, "ingame"); + } delete localStorage["newgame"]; this.setStorage(); //in case of interruptions } @@ -610,6 +630,8 @@ Vue.component('my-game', { this.animateMove(move); return; } + const oppCol = this.vr.getOppCol(this.vr.turn); + this.incheck = this.vr.underCheck(move, oppCol); //is opponent in check? // Not programmatic, or animation is over if (this.mode == "human" && this.vr.turn == this.mycolor) { diff --git a/public/stylesheets/variant.sass b/public/stylesheets/variant.sass index 786d54e3..6a8da838 100644 --- a/public/stylesheets/variant.sass +++ b/public/stylesheets/variant.sass @@ -7,10 +7,10 @@ background-color: lightgrey font-weight: bold -.playing +.playing, button.playing:hover background-color: #ffcc99 -.seek +.seek, button.seek:hover background-color: #cc99ff // https://stackoverflow.com/questions/5445491/height-equal-to-dynamic-width-css-fluid-layout @@ -103,7 +103,10 @@ figure.diagram-container > figcaption background-color: #b58863 .highlight - background-color: #00cc00 + background-color: #00cc66 + +.incheck + background-color: #cc3300 .light-square-diag background-color: #e5e5ca -- 2.44.0