From: Benjamin Auder Date: Mon, 24 Dec 2018 17:20:17 +0000 (+0100) Subject: Implemented and tested DarkChess. Berolina, Upsidedown should be OK. Marseille: TODO X-Git-Url: https://git.auder.net/variants/img/pieces/css/doc/pieces/cq.svg?a=commitdiff_plain;h=388e4c401f05b1f6a4c54e33c9da9114969a53c0;p=vchess.git Implemented and tested DarkChess. Berolina, Upsidedown should be OK. Marseille: TODO --- diff --git a/db/create.sql b/db/create.sql index 033df4be..321274d0 100644 --- a/db/create.sql +++ b/db/create.sql @@ -18,6 +18,10 @@ insert into Variants values ('Crazyhouse', 'Captures reborn'), ('Switching', 'Exchange pieces positions'), ('Extinction', 'Capture all of a kind'), + ('Marseille', 'Move twice'), + ('Upsidedown', 'Walking on the hands'), + ('Dark', 'In the shadow'), + ('Berolina', 'Pawns move diagonally'), ('Ultima', 'Exotic captures'); create table Problems ( diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js index d85ff869..6cdae328 100644 --- a/public/javascripts/base_rules.js +++ b/public/javascripts/base_rules.js @@ -994,12 +994,12 @@ class ChessRules if (V.HasFlags) move.flags = JSON.stringify(this.aggregateFlags()); //save flags (for undo) - this.updateVariables(move); - this.moves.push(move); if (V.HasEnpassant) this.epSquares.push( this.getEpSquare(move) ); - this.turn = this.getOppCol(this.turn); V.PlayOnBoard(this.board, move); + this.turn = this.getOppCol(this.turn); + this.moves.push(move); + this.updateVariables(move); if (!!ingame) { @@ -1010,14 +1010,14 @@ class ChessRules undo(move) { - V.UndoOnBoard(this.board, move); - this.turn = this.getOppCol(this.turn); if (V.HasEnpassant) this.epSquares.pop(); - this.moves.pop(); - this.unupdateVariables(move); if (V.HasFlags) this.disaggregateFlags(JSON.parse(move.flags)); + V.UndoOnBoard(this.board, move); + this.turn = this.getOppCol(this.turn); + this.moves.pop(); + this.unupdateVariables(move); // DEBUG: // if (this.getFen() != this.states[this.states.length-1]) diff --git a/public/javascripts/components/game.js b/public/javascripts/components/game.js index b308aa89..3474ea84 100644 --- a/public/javascripts/components/game.js +++ b/public/javascripts/components/game.js @@ -276,7 +276,7 @@ Vue.component('my-game', { ); // Create board element (+ reserves if needed by variant or mode) const lm = this.vr.lastMove; - const showLight = this.hints && + const showLight = this.hints && variant!="Dark" && (!["idle","chat"].includes(this.mode) || this.cursor==this.vr.moves.length); const gameDiv = h('div', { @@ -299,7 +299,7 @@ Vue.component('my-game', { let cj = (this.mycolor=='w' ? j : sizeY-j-1); let elems = []; if (this.vr.board[ci][cj] != VariantRules.EMPTY && (variant!="Dark" - || this.score!="*" || this.vr.isEnlightened(ci,cj,this.mycolor))) + || this.score!="*" || this.vr.enlightened[this.mycolor][ci][cj])) { elems.push( h( @@ -344,7 +344,7 @@ Vue.component('my-game', { 'dark-square': (i+j)%2==1, [this.color]: true, 'in-shadow': variant=="Dark" && this.score=="*" - && !this.vr.isEnlightened(ci,cj,this.mycolor), + && !this.vr.enlightened[this.mycolor][ci][cj], 'highlight': showLight && !!lm && _.isMatch(lm.end, {x:ci,y:cj}), 'incheck': showLight && incheckSq[ci][cj], }, @@ -1022,7 +1022,7 @@ Vue.component('my-game', { this.newGame("human", data.fen, data.color, data.oppid); break; case "newmove": //..he played! - this.play(data.move, "animate"); + this.play(data.move, (variant!="Dark" ? "animate" : null)); break; case "pong": //received if we sent a ping (game still alive on our side) if (this.gameId != data.gameId) diff --git a/public/javascripts/variants/Alice.js b/public/javascripts/variants/Alice.js index f7d2fa13..1cbfccf3 100644 --- a/public/javascripts/variants/Alice.js +++ b/public/javascripts/variants/Alice.js @@ -256,8 +256,8 @@ class AliceRules extends ChessRules updateVariables(move) { super.updateVariables(move); //standard king - const piece = this.getPiece(move.start.x,move.start.y); - const c = this.getColor(move.start.x,move.start.y); + const piece = move.vanish[0].p; + const c = move.vanish[0].c; // "l" = Alice king if (piece == "l") { @@ -270,8 +270,8 @@ class AliceRules extends ChessRules unupdateVariables(move) { super.unupdateVariables(move); - const c = this.getColor(move.start.x,move.start.y); - if (this.getPiece(move.start.x,move.start.y) == "l") + const c = move.vanish[0].c; + if (move.vanish[0].p == "l") this.kingPos[c] = [move.start.x, move.start.y]; } diff --git a/public/javascripts/variants/Antiking.js b/public/javascripts/variants/Antiking.js index e4d402ce..25a9dfcd 100644 --- a/public/javascripts/variants/Antiking.js +++ b/public/javascripts/variants/Antiking.js @@ -113,8 +113,8 @@ class AntikingRules extends ChessRules updateVariables(move) { super.updateVariables(move); - const piece = this.getPiece(move.start.x,move.start.y); - const c = this.getColor(move.start.x,move.start.y); + const piece = move.vanish[0].p; + const c = move.vanish[0].c; // Update antiking position if (piece == V.ANTIKING) { @@ -126,8 +126,8 @@ class AntikingRules extends ChessRules unupdateVariables(move) { super.unupdateVariables(move); - const c = this.getColor(move.start.x,move.start.y); - if (this.getPiece(move.start.x,move.start.y) == V.ANTIKING) + const c = move.vanish[0].c; + if (move.vanish[0].p == V.ANTIKING) this.antikingPos[c] = [move.start.x, move.start.y]; } diff --git a/public/javascripts/variants/Atomic.js b/public/javascripts/variants/Atomic.js index 0275805f..666c50b2 100644 --- a/public/javascripts/variants/Atomic.js +++ b/public/javascripts/variants/Atomic.js @@ -58,7 +58,7 @@ class AtomicRules extends ChessRules updateVariables(move) { super.updateVariables(move); - const color = this.getColor(move.start.x,move.start.y); + const color = move.vanish[0].c; if (move.appear.length == 0) //capture { const firstRank = {"w": 7, "b": 0}; @@ -89,7 +89,7 @@ class AtomicRules extends ChessRules unupdateVariables(move) { super.unupdateVariables(move); - const c = this.getColor(move.start.x,move.start.y); + const c = move.vanish[0].c; const oppCol = this.getOppCol(c); if ([this.kingPos[c][0],this.kingPos[oppCol][0]].some(e => { return e < 0; })) { diff --git a/public/javascripts/variants/Crazyhouse.js b/public/javascripts/variants/Crazyhouse.js index f36bfcc4..c4780b78 100644 --- a/public/javascripts/variants/Crazyhouse.js +++ b/public/javascripts/variants/Crazyhouse.js @@ -212,7 +212,7 @@ class CrazyhouseRules extends ChessRules super.updateVariables(move); if (move.vanish.length == 2 && move.appear.length == 2) return; //skip castle - const color = this.turn; + const color = move.appear[0].c; if (move.vanish.length == 0) { this.reserve[color][move.appear[0].p]--; diff --git a/public/javascripts/variants/Dark.js b/public/javascripts/variants/Dark.js index 9cf50513..4031462c 100644 --- a/public/javascripts/variants/Dark.js +++ b/public/javascripts/variants/Dark.js @@ -1,25 +1,42 @@ -class Chess960Rules extends ChessRules +class DarkRules extends ChessRules { // Standard rules, in the shadow setOtherVariables(fen) { super.setOtherVariables(fen); - const [sizeX,sizeY] = {V.size.x,V.size.y}; + const [sizeX,sizeY] = [V.size.x,V.size.y]; this.enlightened = { - "w": doubleArray(sizeX,sizeY,false), - "b": doubleArray(sizeX,sizeY,false) + "w": doubleArray(sizeX,sizeY), + "b": doubleArray(sizeX,sizeY) }; - setup enlightened: squares reachable by each side (TODO: one side would be enough) + // Setup enlightened: squares reachable by each side + // (TODO: one side would be enough ?) + this.updateEnlightened(); } - isEnlightened(x, y, color) + updateEnlightened() { - //TODO: artificlaly change turn - } - - getAllPotentialMoves() - { - let moves = []; //TODO + // Initialize with pieces positions (which are seen) + for (let i=0; i but isEnlightened() should have its variable updated - // --> in fact an array is enough (no need for a function) - // recomputed after every play/undo (although there are no undo here for now) + updateVariables(move) + { + // Update kings positions + const piece = move.vanish[0].p; + const c = move.vanish[0].c; + if (piece == V.KING && move.appear.length > 0) + { + this.kingPos[c][0] = move.appear[0].x; + this.kingPos[c][1] = move.appear[0].y; + } + if (move.vanish.length >= 2 && move.vanish[1].p == V.KING) + { + // We took opponent king ! + const oppCol = this.getOppCol(c); + this.kingPos[oppCol] = [-1,-1]; + } + + // Update moves for both colors: + this.updateEnlightened(); + } + + unupdateVariables(move) + { + super.unupdateVariables(move); + const c = move.vanish[0].c; + const oppCol = this.getOppCol(c); + if (this.kingPos[oppCol][0] < 0) + { + // Last move took opponent's king + for (let psq of move.vanish) + { + if (psq.p == 'k') + { + this.kingPos[oppCol] = [psq.x, psq.y]; + break; + } + } + } + + // Update moves for both colors: + this.updateEnlightened(); + } checkGameEnd() { diff --git a/public/javascripts/variants/Loser.js b/public/javascripts/variants/Loser.js index 407c6aad..e6eb3207 100644 --- a/public/javascripts/variants/Loser.js +++ b/public/javascripts/variants/Loser.js @@ -97,7 +97,7 @@ class LoserRules extends ChessRules return []; } - // No variables update because no castling + // No variables update because no royal king + no castling updateVariables(move) { } unupdateVariables(move) { } diff --git a/public/javascripts/variants/Magnetic.js b/public/javascripts/variants/Magnetic.js index 8480d799..1ccc192e 100644 --- a/public/javascripts/variants/Magnetic.js +++ b/public/javascripts/variants/Magnetic.js @@ -160,10 +160,8 @@ class MagneticRules extends ChessRules updateVariables(move) { super.updateVariables(move); - const c = this.getColor(move.start.x,move.start.y); - if (this.board[move.end.x][move.end.y] != V.EMPTY - && c != this.getColor(move.end.x,move.end.y) - && this.getPiece(move.end.x,move.end.y) == V.KING) + const c = move.vanish[0].c; + if (move.vanish.length >= 2 && move.vanish[1].p == V.KING) { // We took opponent king ! const oppCol = this.getOppCol(c); @@ -185,7 +183,7 @@ class MagneticRules extends ChessRules unupdateVariables(move) { super.unupdateVariables(move); - const c = this.getColor(move.start.x,move.start.y); + const c = move.vanish[0].c; const oppCol = this.getOppCol(c); if (this.kingPos[oppCol][0] < 0) { diff --git a/public/javascripts/variants/Marseille.js b/public/javascripts/variants/Marseille.js new file mode 100644 index 00000000..ab7a3afe --- /dev/null +++ b/public/javascripts/variants/Marseille.js @@ -0,0 +1,3 @@ +//TODO: turn en fonction de la parité des coups... +//adapter alphabeta (dans baserules ? --> basé sur turn OK) +// le reste == standard diff --git a/public/javascripts/variants/Switching.js b/public/javascripts/variants/Switching.js index e53ab692..53b14d58 100644 --- a/public/javascripts/variants/Switching.js +++ b/public/javascripts/variants/Switching.js @@ -104,7 +104,7 @@ class SwitchingRules extends ChessRules && move.appear[1].p == V.KING) { // Switch with the king; not castle, and not handled by main class - const color = this.getColor(move.start.x, move.start.y); + const color = move.vanish[0].c; this.kingPos[color] = [move.appear[1].x, move.appear[1].y]; } } @@ -115,7 +115,7 @@ class SwitchingRules extends ChessRules if (move.appear.length == 2 && move.vanish.length == 2 && move.appear[1].p == V.KING) { - const color = this.getColor(move.start.x, move.start.y); + const color = move.vanish[0].c; this.kingPos[color] = [move.appear[0].x, move.appear[0].y]; } } diff --git a/public/javascripts/variants/Ultima.js b/public/javascripts/variants/Ultima.js index 04d62b7d..0b00c262 100644 --- a/public/javascripts/variants/Ultima.js +++ b/public/javascripts/variants/Ultima.js @@ -529,8 +529,8 @@ class UltimaRules extends ChessRules updateVariables(move) { // Just update king(s) position(s) - const piece = this.getPiece(move.start.x,move.start.y); - const c = this.getColor(move.start.x,move.start.y); + const piece = move.vanish[0].p; + const c = move.vanish[0].c; if (piece == V.KING && move.appear.length > 0) { this.kingPos[c][0] = move.appear[0].x; diff --git a/public/javascripts/variants/Upsidedown.js b/public/javascripts/variants/Upsidedown.js new file mode 100644 index 00000000..aa9a696d --- /dev/null +++ b/public/javascripts/variants/Upsidedown.js @@ -0,0 +1,57 @@ +class UpsidedownRules extends ChessRUles +{ + static HasFlags() { return false; } + + getPotentialKingMoves(sq) + { + // No castle + return this.getSlideNJumpMoves(sq, + V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep"); + } + + static GenRandInitFen() + { + let pieces = { "w": new Array(8), "b": new Array(8) }; + for (let c of ["w","b"]) + { + let positions = _.range(8); + + let randIndex = 2 * _.random(3); + let bishop1Pos = positions[randIndex]; + let randIndex_tmp = 2 * _.random(3) + 1; + let bishop2Pos = positions[randIndex_tmp]; + positions.splice(Math.max(randIndex,randIndex_tmp), 1); + positions.splice(Math.min(randIndex,randIndex_tmp), 1); + + randIndex = _.random(5); + let knight1Pos = positions[randIndex]; + positions.splice(randIndex, 1); + randIndex = _.random(4); + let knight2Pos = positions[randIndex]; + positions.splice(randIndex, 1); + + randIndex = _.random(3); + let queenPos = positions[randIndex]; + positions.splice(randIndex, 1); + + let rook1Pos = positions[0]; + let kingPos = positions[1]; + let rook2Pos = positions[2]; + + pieces[c][rook1Pos] = 'r'; + pieces[c][knight1Pos] = 'n'; + pieces[c][bishop1Pos] = 'b'; + pieces[c][queenPos] = 'q'; + pieces[c][kingPos] = 'k'; + pieces[c][bishop2Pos] = 'b'; + pieces[c][knight2Pos] = 'n'; + pieces[c][rook2Pos] = 'r'; + } + return pieces["w"].join("") + + "/PPPPPPPP/8/8/8/8/pppppppp/" + + pieces["b"].join("").toUpperCase() + + " w 1111 -"; //add turn + flags + enpassant + } +} + +const VariantRules = UpsidedownRules; diff --git a/public/stylesheets/variant.sass b/public/stylesheets/variant.sass index 0ebad8c3..c3df08c4 100644 --- a/public/stylesheets/variant.sass +++ b/public/stylesheets/variant.sass @@ -222,7 +222,7 @@ img.ghost background-color: #00cc66 !important .in-shadow - opacity: 0.5 + filter: brightness(50%) .incheck background-color: #cc3300 !important