Fist draft of Antiking variant (still being debugged)
authorBenjamin Auder <benjamin.auder@somewhere>
Tue, 20 Nov 2018 13:59:19 +0000 (14:59 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Tue, 20 Nov 2018 13:59:19 +0000 (14:59 +0100)
public/javascripts/base_rules.js
public/javascripts/components/game.js
public/javascripts/variants/Antiking.js
variants.js
views/rules/Antiking.pug [new file with mode: 0644]

index a400122..8626b88 100644 (file)
@@ -621,7 +621,7 @@ class ChessRules
        getCheckSquares(move)
        {
                this.play(move);
-               const color = this.turn;
+               const color = this.turn; //opponent
                let res = this.isAttacked(this.kingPos[color], this.getOppCol(color))
                        ? [ JSON.parse(JSON.stringify(this.kingPos[color])) ] //need to duplicate!
                        : [ ];
index 9364c8d..1863285 100644 (file)
@@ -217,18 +217,21 @@ Vue.component('my-game', {
                                        );
                                }), choices]
                        );
-                       actionArray.push(
-                               h('button',
-                                       {
-                                               on: { click: this.resign },
-                                               attrs: { "aria-label": 'Resign' },
-                                               'class': {
-                                                       "tooltip":true,
-                                                       "bottom": true,
+                       if (this.mode != "idle")
+                       {
+                               actionArray.push(
+                                       h('button',
+                                               {
+                                                       on: { click: this.resign },
+                                                       attrs: { "aria-label": 'Resign' },
+                                                       'class': {
+                                                               "tooltip":true,
+                                                               "bottom": true,
+                                                       },
                                                },
-                                       },
-                                       [h('i', { 'class': { "material-icons": true } }, "flag")])
-                       );
+                                               [h('i', { 'class': { "material-icons": true } }, "flag")])
+                               );
+                       }
                        elementArray.push(gameDiv);
        //                      if (!!vr.reserve)
        //                      {
@@ -494,6 +497,7 @@ Vue.component('my-game', {
                        this.score = score;
                        let modalBox = document.getElementById("modal-eog");
                        modalBox.checked = true;
+                       // Variants may have special PGN structure (so next function isn't defined here)
                        this.pgnTxt = this.vr.getPGN(this.mycolor, this.score, this.fenStart, this.mode);
                        setTimeout(() => { modalBox.checked = false; }, 2000);
                        if (this.mode == "human")
index 360deaf..2770261 100644 (file)
@@ -1,4 +1,4 @@
-class AntikingRules
+class AntikingRules extends ChessRules
 {
        // Path to pieces
        static getPpath(b)
@@ -11,30 +11,55 @@ class AntikingRules
        initVariables(fen)
        {
                super.initVariables(fen);
-               // TODO: initialize this.antikingPos[...]
+               this.antikingPos = {'w':[-1,-1], 'b':[-1,-1]};
+               const position = fen.split(" ")[0].split("/");
+               for (let i=0; i<position.length; i++)
+               {
+                       let j = 0;
+                       while (j < position[i].length)
+                       {
+                               switch (position[i].charAt(j))
+                               {
+                                       case 'a':
+                                               this.antikingPos['b'] = [i,j];
+                                               break;
+                                       case 'A':
+                                               this.antikingPos['w'] = [i,j];
+                                               break;
+                                       default:
+                                               let num = parseInt(position[i].charAt(j));
+                                               if (!isNaN(num))
+                                                       j += (num-1);
+                               }
+                               j++;
+                       }
+               }
        }
 
-       canTake(color1, color2, [x,y])
+       canTake([x1,y1], [x2,y2])
        {
-               const piece = this.getPiece(x,y);
-               return (piece != "a" && color1 != color2) || (piece == "a" && color1 == color2);
+               const piece1 = this.getPiece(x1,y1);
+               const piece2 = this.getPiece(x2,y2);
+               const color1 = this.getColor(x1,y1);
+               const color2 = this.getColor(x2,y2);
+               return !["a","A"].includes(piece2) &&
+                       ((piece1 != "a" && color1 != color2) || (piece1 == "a" && color1 == color2));
        }
 
        getPotentialMovesFrom([x,y])
        {
-               let c = this.getColor(x,y);
                switch (this.getPiece(x,y))
                {
                        case VariantRules.ANTIKING:
-                               return this.getPotentialAntikingMoves(x,y,c);
+                               return this.getPotentialAntikingMoves([x,y]);
                        default:
-                               return super.getPotentielMovesFrom([x,y]);
+                               return super.getPotentialMovesFrom([x,y]);
                }
        }
 
-       getPotentialAntikingMoves([x,y])
+       getPotentialAntikingMoves(sq)
        {
-               // TODO
+               return this.getSlideNJumpMoves(sq, VariantRules.steps[VariantRules.QUEEN], "oneStep");
        }
 
        isAttacked(sq, colors)
@@ -42,49 +67,67 @@ class AntikingRules
                return (super.isAttacked(sq, colors) || this.isAttackedByAntiking(sq, colors));
        }
 
-       isAttackedByAntiking(sq, color)
+       isAttackedByAntiking([x,y], colors)
        {
-               // TODO
+               console.log(x + " " + y); //TODO: debug -1, -1 (wrong undo ?!)
+               if (this.getPiece(x,y) == VariantRules.KING)
+                       return false; //king is not attacked by antiking
+               return super.isAttackedBySlideNJump([x,y], colors,
+                       VariantRules.ANTIKING, VariantRules.steps[VariantRules.QUEEN], "oneStep");
        }
 
        underCheck(move)
        {
                const c = this.turn;
-               this.play(move);
-               let res = this.isAttacked(this.kingPos[c], this.getOppCol(c));
-               // TODO: also check that antiking is still in check
+               const oppCol = this.getOppCol(c);
+               this.play(move)
+               let res = this.isAttacked(this.kingPos[c], oppCol)
+                       || !this.isAttacked(this.antikingPos[c], oppCol);
                this.undo(move);
                return res;
        }
 
        getCheckSquares(move)
        {
+               let res = super.getCheckSquares(move);
                this.play(move);
                const c = this.turn;
-               // TODO
-               let res = this.isAttacked(this.kingPos[c], this.getOppCol(c))
-                       ? [ JSON.parse(JSON.stringify(this.kingPos[c])) ]
-                       : [ ];
+               if (!this.isAttacked(this.antikingPos[c], this.getOppCol(c)))
+                       res.push(JSON.parse(JSON.stringify(this.antikingPos[c])));
                this.undo(move);
                return res;
        }
 
-       // TODO: need antikingPos as well
        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);
+               // Update antiking position
+               if (piece == VariantRules.ANTIKING)
+               {
+                       this.antikingPos[c][0] = move.appear[0].x;
+                       this.antikingPos[c][1] = move.appear[0].y;
+               }
        }
 
        unupdateVariables(move)
        {
-               // TODO
+               super.unupdateVariables(move);
+               const c = this.getColor(move.start.x,move.start.y);
+               if (this.getPiece(move.start.x,move.start.y) == VariantRules.ANTIKING)
+                       this.antikingPos[c] = [move.start.x, move.start.y];
        }
 
-       checkGameEnd(color)
+       checkGameEnd()
        {
-               // TODO
-               if (!this.isAttacked(this.kingPos[color], this.getOppCol(color)))
+               const color = this.turn;
+               const oppCol = this.getOppCol(color);
+               if (!this.isAttacked(this.kingPos[color], oppCol)
+                       && this.isAttacked(this.antikingPos[color], oppCol))
+               {
                        return "1/2";
+               }
                return color == "w" ? "0-1" : "1-0";
        }
 
@@ -104,7 +147,14 @@ class AntikingRules
        static GenRandInitFen()
        {
                let randFen = ChessRules.GenRandInitFen();
-               // TODO: just add an antiking at random on 3rd ranks
+               // Black side
+               let antikingPos = _.random(7);
+               let ranks23 = "pppppppp/" + (antikingPos>0?antikingPos:"") + "A" + (antikingPos<7?7-antikingPos:"");
+               randFen = randFen.replace("pppppppp/8", ranks23);
+               // White side
+               antikingPos = _.random(7);
+               ranks23 = (antikingPos>0?antikingPos:"") + "a" + (antikingPos<7?7-antikingPos:"") + "/PPPPPPPP";
+               randFen = randFen.replace("8/PPPPPPPP", ranks23);
                return randFen;
        }
 }
index ed2b6ba..6c2f62c 100644 (file)
@@ -3,7 +3,7 @@ module.exports = [
        { "name" : "Zen", "description" : "Reverse captures" },
        { "name" : "Atomic", "description" : "Explosive captures" },
        { "name" : "Chess960", "description" : "Standard rules" },
-//  { "name" : "AntiKing", "description" : "Keep anti-king in check" },
+  { "name" : "Antiking", "description" : "Keep antiking in check" },
 //  { "name" : "Magnetic", "description" : "Laws of attraction" },
 //  { "name" : "Alice", "description" : "Both sides of the mirror" },
 //  { "name" : "Grand", "description" : "Big board" },
diff --git a/views/rules/Antiking.pug b/views/rules/Antiking.pug
new file mode 100644 (file)
index 0000000..eda7db4
--- /dev/null
@@ -0,0 +1,43 @@
+p.boxed
+       | You have a king and an antiking. King must stay away from checks, but antiking must always stay in check.
+       | Antiking captures his own kind.
+
+h3 Specifications
+
+ul
+       li Chessboard: standard.
+       li Material: additional antiking.
+       li Non-capturing moves: standard.
+       li Special moves: standard.
+       li Captures: special case of antiking (see below).
+       li End of game: Checkmate or anti-checkmate.
+
+h3 Basics
+
+p
+       | The additional piece is a royal figure, thus cannot be captured.
+       | It captures the pieces of his color (to help checkmate opponent antiking, but by doing so it also make standard checkmate more difficult...).
+       | It should always remains under check (if it cannot, game is over).
+
+figure.diagram-container
+       .diagram
+               | fen:rnbqkbnr/pppppppp/3A4/8/8/3a4/PPPPPPPP/RNBQKBNR:
+       figcaption Initial position (non-random). 1.Ae5 is forbidden.
+
+h3 End of the game
+
+p There are two ways to win:
+ol
+       li Checkmate opponent king
+       li Anti-checkmate opponent antiking
+p ...Or maybe do both at the same time?
+
+p Note 1: athough antiking captures his color, it doesn't check his king.
+
+p Note 2: since it would allow a basic tactic (keep antiking touching opponent's king), kings do not attack antikings.
+
+h3 Credits
+
+p
+       a(href="https://www.chessvariants.com/diffobjective.dir/anti-king-chess.html") Antiking chess 
+       | on chessvariants.com.