Draft of Ultima chess rules; almost OK HalfChess
authorBenjamin Auder <benjamin.auder@somewhere>
Tue, 11 Dec 2018 18:09:26 +0000 (19:09 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Tue, 11 Dec 2018 18:09:26 +0000 (19:09 +0100)
TODO [new file with mode: 0644]
public/javascripts/base_rules.js
public/javascripts/components/game.js
public/javascripts/variants/Half.js [new file with mode: 0644]
public/javascripts/variants/Loser.js
public/javascripts/variants/Ultima.js [new file with mode: 0644]
public/stylesheets/variant.sass
variants.js
views/rules/Half.pug [new file with mode: 0644]
views/rules/Ultima.pug [new file with mode: 0644]
views/rules/Zen.pug

diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..f8465c6
--- /dev/null
+++ b/TODO
@@ -0,0 +1,3 @@
+Full detection of repeated positions (including turn)
+Debug HalfChess
+Implement UltimaChess
index a8f2489..750cd2d 100644 (file)
@@ -752,6 +752,7 @@ class ChessRules
        // END OF GAME
 
        // Basic check for 3 repetitions (in the last moves only)
+       // TODO: extend to usual 3-repetition recognition (storing FEN with move?)
        checkRepetition()
        {
                if (this.moves.length >= 8)
@@ -988,9 +989,9 @@ class ChessRules
        // Setup the initial random (assymetric) position
        static GenRandInitFen()
        {
-               let pieces = [new Array(8), new Array(8)];
+               let pieces = { "w": new Array(8), "b": new Array(8) };
                // Shuffle pieces on first and last rank
-               for (let c = 0; c <= 1; c++)
+               for (let c of ["w","b"])
                {
                        let positions = _.range(8);
 
@@ -1032,9 +1033,9 @@ class ChessRules
                        pieces[c][knight2Pos] = 'n';
                        pieces[c][rook2Pos] = 'r';
                }
-               let fen = pieces[0].join("") +
+               let fen = pieces["b"].join("") +
                        "/pppppppp/8/8/8/8/PPPPPPPP/" +
-                       pieces[1].join("").toUpperCase() +
+                       pieces["w"].join("").toUpperCase() +
                        " 1111"; //add flags
                return fen;
        }
index 208e048..d76ab01 100644 (file)
@@ -25,6 +25,7 @@ Vue.component('my-game', {
        },
        render(h) {
                const [sizeX,sizeY] = VariantRules.size;
+               console.log(sizeX + " " + sizeY);
                const smallScreen = (screen.width <= 420);
                // Precompute hints squares to facilitate rendering
                let hintSquares = doubleArray(sizeX, sizeY, false);
diff --git a/public/javascripts/variants/Half.js b/public/javascripts/variants/Half.js
new file mode 100644 (file)
index 0000000..2f1174e
--- /dev/null
@@ -0,0 +1,88 @@
+class HalfRules extends ChessRules
+{
+       // Standard rules on a 4x8 board with no pawns
+
+       initVariables(fen) { } //nothing to do
+
+       setFlags(fen)
+       {
+               // No castling, hence no flags; but flags defined for compatibility
+               this.castleFlags = { "w":[false,false], "b":[false,false] };
+       }
+
+       static get size() { return [8,4]; }
+
+       getPotentialKingMoves(sq)
+       {
+               const V = VariantRules;
+               // No castling
+               return this.getSlideNJumpMoves(sq,
+                       V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
+       }
+
+       isAttacked(sq, colors)
+       {
+               return (this.isAttackedByRook(sq, colors)
+                       || this.isAttackedByKnight(sq, colors)
+                       || this.isAttackedByBishop(sq, colors)
+                       || this.isAttackedByQueen(sq, colors)
+                       || this.isAttackedByKing(sq, colors));
+       }
+
+       // Unused:
+       updateVariables(move) { }
+       unupdateVariables(move) { }
+
+       static get SEARCH_DEPTH() { return 4; }
+
+       static GenRandInitFen()
+       {
+               let minorPieces = { "w": new Array(4), "b": new Array(4) };
+               let majorPieces = { "w": new Array(4), "b": new Array(4) };
+               for (let c of ["w","b"])
+               {
+                       // Minor pieces first (on 2nd rank)
+                       let positions = _.range(4);
+
+                       // Get random squares for bishops
+                       let randIndex = 2 * _.random(1);
+                       let bishop1Pos = positions[randIndex];
+                       let randIndex_tmp = 2 * _.random(1) + 1;
+                       let bishop2Pos = positions[randIndex_tmp];
+                       positions.splice(Math.max(randIndex,randIndex_tmp), 1);
+                       positions.splice(Math.min(randIndex,randIndex_tmp), 1);
+
+                       // Get random squares for knights
+                       randIndex = _.random(1);
+                       let knight1Pos = positions[randIndex];
+                       positions.splice(randIndex, 1);
+                       let knight2Pos = positions[0];
+
+                       minorPieces[c][bishop1Pos] = 'b';
+                       minorPieces[c][bishop2Pos] = 'b';
+                       minorPieces[c][knight1Pos] = 'n';
+                       minorPieces[c][knight2Pos] = 'n';
+
+                       // Major pieces then (on 1st rank)
+                       positions = _.range(4);
+
+                       // Get random square for queen
+                       randIndex = _.random(3);
+                       let queenPos = positions[randIndex];
+                       positions.splice(randIndex, 1);
+
+                       // Rooks and king positions:
+                       let rook1Pos = positions[0];
+                       let kingPos = positions[1];
+                       let rook2Pos = positions[2];
+
+                       majorPieces[c][rook1Pos] = 'r';
+                       majorPieces[c][rook2Pos] = 'r';
+                       majorPieces[c][kingPos] = 'k';
+                       majorPieces[c][queenPos] = 'q';
+               }
+               return majorPieces["b"].join("") + "/" + minorPieces["b"].join("") + "/4/4/4/4/" +
+                       minorPieces["w"].join("").toUpperCase() + "/" +
+                       majorPieces["w"].join("").toUpperCase() + " 0000"; //TODO: flags?!
+       }
+}
index 9ae2e7f..da4999f 100644 (file)
@@ -113,7 +113,6 @@ class LoserRules extends ChessRules
        // Unused:
        updateVariables(move) { }
        unupdateVariables(move) { }
-       parseFlags(flags) { }
 
        getFlagsFen()
        {
diff --git a/public/javascripts/variants/Ultima.js b/public/javascripts/variants/Ultima.js
new file mode 100644 (file)
index 0000000..812d440
--- /dev/null
@@ -0,0 +1,8 @@
+class UltimaRules extends ChessRules
+{
+       // TODO: think about move UI for "removing an immobilized  piece from the board"
+       // (extend game.js and feedback Rules.js with "there was a click, is it a move?")
+
+       // TODO: Keep usual pieces names here (but comment with Ultima pieces names)
+       // Just change moving + capturing modes.
+}
index 3eec290..8839c34 100644 (file)
@@ -81,6 +81,10 @@ div.board
   display: inline-block
   position: relative
 
+div.board4
+  width: 25%
+  padding-bottom: 25%
+
 div.board8
   width: 12.5%
   padding-bottom: 12.5%
index 8a00fe0..5623334 100644 (file)
@@ -12,4 +12,6 @@ module.exports = [
        { "name": "Crazyhouse", "description": "Captures reborn" },
        { "name": "Switching", "description": "Exchange pieces positions" },
        { "name": "Extinction", "description": "Capture all of a kind" },
+       { "name": "Ultima", "description": "Non-standard captures" },
+       { "name": "Half", "description": "Small board" },
 ];
diff --git a/views/rules/Half.pug b/views/rules/Half.pug
new file mode 100644 (file)
index 0000000..605eda4
--- /dev/null
@@ -0,0 +1,24 @@
+p.boxed
+       | 8x4 board with no pawns. Orthodox rules.
+
+figure.diagram-container
+       .diagram
+               | fen:rkqr/nbbn/4/4/4/4/NBBN/RKQR:
+       figcaption Initial position (non-random)
+
+h3 Specifications
+
+ul
+       li Chessboard: 8x4 (see diagram).
+       li Material: no pawns.
+       li Non-capturing moves: standard.
+       li Special moves: none.
+       li Captures: standard.
+       li End of game: standard.
+
+h3 Credits
+
+p
+       | This variant is shortly described on 
+       a(href="https://www.chessvariants.com/small.dir/halfchess.html") chessvariants.com
+       | .
diff --git a/views/rules/Ultima.pug b/views/rules/Ultima.pug
new file mode 100644 (file)
index 0000000..77bfd09
--- /dev/null
@@ -0,0 +1,34 @@
+p.boxed
+       | Pieces look the same but behave very differently.
+       | They generally move like an orthodox queen,
+       | but capturing rules are complex: you need to read on :)
+
+h3 Specifications
+
+ul
+       li Chessboard: standard.
+       li Material: "standard".
+       li Non-capturing moves: often like queen.
+       li Special moves: none.
+       li Captures: very special.
+       li End of game: standard; see below.
+
+h3 Non-capturing moves
+
+// TODO: short paragraph, only the king moves like an orthodox king
+
+h3 Capturing moves
+
+// TODO...
+
+h3 End of the game
+
+// TODO: show the situation from Wikipedia page
+
+h3 Credits
+
+p.
+       A good starting point is the 
+       #[a(href="https://en.wikipedia.org/wiki/Baroque_chess") Wikipedia page], 
+       which also gives pointers to other interesting pages (including chessvariants.com,
+       as usual).
index bc5f9f5..afa6502 100644 (file)
@@ -43,4 +43,3 @@ p.
        Very few resources about this variation:
        #[a(href="http://play.chessvariants.org/erf/ZenChess.html") this webpage] 
        and #[a(href="http://www.pathguy.com/chess/ZenChess.htm") this one].
-       Ed Friedlander developed the Zen Chess applet from the link above.