From 32cfcea44bf00b0c6c4d172cca715823076ff490 Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Tue, 11 Dec 2018 19:09:26 +0100 Subject: [PATCH] Draft of Ultima chess rules; almost OK HalfChess --- TODO | 3 + public/javascripts/base_rules.js | 9 +-- public/javascripts/components/game.js | 1 + public/javascripts/variants/Half.js | 88 +++++++++++++++++++++++++++ public/javascripts/variants/Loser.js | 1 - public/javascripts/variants/Ultima.js | 8 +++ public/stylesheets/variant.sass | 4 ++ variants.js | 2 + views/rules/Half.pug | 24 ++++++++ views/rules/Ultima.pug | 34 +++++++++++ views/rules/Zen.pug | 1 - 11 files changed, 169 insertions(+), 6 deletions(-) create mode 100644 TODO create mode 100644 public/javascripts/variants/Half.js create mode 100644 public/javascripts/variants/Ultima.js create mode 100644 views/rules/Half.pug create mode 100644 views/rules/Ultima.pug diff --git a/TODO b/TODO new file mode 100644 index 00000000..f8465c6c --- /dev/null +++ b/TODO @@ -0,0 +1,3 @@ +Full detection of repeated positions (including turn) +Debug HalfChess +Implement UltimaChess diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js index a8f24893..750cd2d4 100644 --- a/public/javascripts/base_rules.js +++ b/public/javascripts/base_rules.js @@ -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; } diff --git a/public/javascripts/components/game.js b/public/javascripts/components/game.js index 208e0482..d76ab011 100644 --- a/public/javascripts/components/game.js +++ b/public/javascripts/components/game.js @@ -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 index 00000000..2f1174ed --- /dev/null +++ b/public/javascripts/variants/Half.js @@ -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?! + } +} diff --git a/public/javascripts/variants/Loser.js b/public/javascripts/variants/Loser.js index 9ae2e7fc..da4999fe 100644 --- a/public/javascripts/variants/Loser.js +++ b/public/javascripts/variants/Loser.js @@ -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 index 00000000..812d440b --- /dev/null +++ b/public/javascripts/variants/Ultima.js @@ -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. +} diff --git a/public/stylesheets/variant.sass b/public/stylesheets/variant.sass index 3eec2900..8839c342 100644 --- a/public/stylesheets/variant.sass +++ b/public/stylesheets/variant.sass @@ -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% diff --git a/variants.js b/variants.js index 8a00fe00..5623334e 100644 --- a/variants.js +++ b/variants.js @@ -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 index 00000000..605eda4b --- /dev/null +++ b/views/rules/Half.pug @@ -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 index 00000000..77bfd093 --- /dev/null +++ b/views/rules/Ultima.pug @@ -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). diff --git a/views/rules/Zen.pug b/views/rules/Zen.pug index bc5f9f58..afa6502f 100644 --- a/views/rules/Zen.pug +++ b/views/rules/Zen.pug @@ -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. -- 2.44.0