Implemented and tested DarkChess. Berolina, Upsidedown should be OK. Marseille: TODO
authorBenjamin Auder <benjamin.auder@somewhere>
Mon, 24 Dec 2018 17:20:17 +0000 (18:20 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Mon, 24 Dec 2018 17:20:17 +0000 (18:20 +0100)
15 files changed:
db/create.sql
public/javascripts/base_rules.js
public/javascripts/components/game.js
public/javascripts/variants/Alice.js
public/javascripts/variants/Antiking.js
public/javascripts/variants/Atomic.js
public/javascripts/variants/Crazyhouse.js
public/javascripts/variants/Dark.js
public/javascripts/variants/Loser.js
public/javascripts/variants/Magnetic.js
public/javascripts/variants/Marseille.js [new file with mode: 0644]
public/javascripts/variants/Switching.js
public/javascripts/variants/Ultima.js
public/javascripts/variants/Upsidedown.js [new file with mode: 0644]
public/stylesheets/variant.sass

index 033df4b..321274d 100644 (file)
@@ -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 (
index d85ff86..6cdae32 100644 (file)
@@ -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])
index b308aa8..3474ea8 100644 (file)
@@ -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)
index f7d2fa1..1cbfccf 100644 (file)
@@ -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];
        }
 
index e4d402c..25a9dfc 100644 (file)
@@ -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];
        }
 
index 0275805..666c50b 100644 (file)
@@ -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; }))
                {
index f36bfcc..c4780b7 100644 (file)
@@ -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]--;
index 9cf5051..4031462 100644 (file)
@@ -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<V.size.x; i++)
+               {
+                       for (let j=0; j<V.size.y; j++)
+                       {
+                               this.enlightened["w"][i][j] = false;
+                               this.enlightened["b"][i][j] = false;
+                               if (this.board[i][j] != V.EMPTY)
+                                       this.enlightened[this.getColor(i,j)][i][j] = true;
+                       }
+               }
+               const currentTurn = this.turn;
+               this.turn = "w";
+               const movesWhite = this.getAllValidMoves();
+               this.turn = "b";
+               const movesBlack = this.getAllValidMoves();
+               this.turn = currentTurn;
+               for (let move of movesWhite)
+                       this.enlightened["w"][move.end.x][move.end.y] = true;
+               for (let move of movesBlack)
+                       this.enlightened["b"][move.end.x][move.end.y] = true;
        }
 
        atLeastOneMove()
@@ -47,10 +64,48 @@ class Chess960Rules extends ChessRules
                return res;
        }
 
-       // NOTE: no (un)updateVariables() because no computer mode
-       // --> 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()
        {
index 407c6aa..e6eb320 100644 (file)
@@ -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) { }
 
index 8480d79..1ccc192 100644 (file)
@@ -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 (file)
index 0000000..ab7a3af
--- /dev/null
@@ -0,0 +1,3 @@
+//TODO: turn en fonction de la parité des coups...
+//adapter alphabeta (dans baserules ? --> basé sur turn OK)
+// le reste == standard
index e53ab69..53b14d5 100644 (file)
@@ -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];
                }
        }
index 04d62b7..0b00c26 100644 (file)
@@ -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 (file)
index 0000000..aa9a696
--- /dev/null
@@ -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;
index 0ebad8c..c3df08c 100644 (file)
@@ -222,7 +222,7 @@ img.ghost
   background-color: #00cc66 !important
 
 .in-shadow
-  opacity: 0.5
+  filter: brightness(50%)
 
 .incheck
   background-color: #cc3300 !important