From bc2bc396ec4df092f218b58a0fbf08ba7eb8ca6e Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Fri, 17 Jun 2022 21:34:03 +0200 Subject: [PATCH] Chakart ready soon --- base_rules.js | 12 ++-- common.css | 9 +++ utils/alea.js | 4 +- variants.js | 2 +- variants/Chakart/class.js | 120 ++++++++++++++++++++++++++---------- variants/Chakart/rules.html | 4 +- variants/Giveaway/class.js | 3 + 7 files changed, 112 insertions(+), 42 deletions(-) diff --git a/base_rules.js b/base_rules.js index dac7bb4..864bb33 100644 --- a/base_rules.js +++ b/base_rules.js @@ -371,14 +371,14 @@ export default class ChessRules { ////////////////// // INITIALIZATION - constructor(o, genFenOnly) { + constructor(o) { this.options = o.options; // Fill missing options (always the case if random challenge) (V.Options.select || []).concat(V.Options.input || []).forEach(opt => { if (this.options[opt.variable] === undefined) this.options[opt.variable] = opt.defaut; }); - if (genFenOnly) + if (o.genFenOnly) // This object will be used only for initial FEN generation return; this.playerColor = o.color; @@ -1046,7 +1046,11 @@ export default class ChessRules { } static GetColorClass(c) { - return (c == 'w' ? "white" : "black"); + if (c == 'w') + return "white"; + if (c == 'b') + return "black"; + return ""; //unidentified color } // Assume square i,j isn't empty @@ -2161,7 +2165,7 @@ export default class ChessRules { move.appear.forEach(a => { this.g_pieces[a.x][a.y] = document.createElement("piece"); this.g_pieces[a.x][a.y].classList.add(this.pieces()[a.p]["class"]); - this.g_pieces[a.x][a.y].classList.add(a.c == "w" ? "white" : "black"); + this.g_pieces[a.x][a.y].classList.add(C.GetColorClass(a.c)); this.g_pieces[a.x][a.y].style.width = pieceWidth + "px"; this.g_pieces[a.x][a.y].style.height = pieceWidth + "px"; const [ip, jp] = this.getPixelPosition(a.x, a.y, r); diff --git a/common.css b/common.css index ece4aba..a69f4fb 100644 --- a/common.css +++ b/common.css @@ -117,6 +117,15 @@ h4 { margin: 10px 0; } +#gameInfos > .rules > ul { + list-style-type: square; + padding-left: 30px; +} +#gameInfos > .rules > ol { + list-style-type: numeric; + padding-left: 30px; +} + #gameInfos > .rules > a { padding-bottom: 1px; border-bottom: 1px dotted black; diff --git a/utils/alea.js b/utils/alea.js index 8b5a4ea..aa3aa57 100644 --- a/utils/alea.js +++ b/utils/alea.js @@ -31,14 +31,14 @@ export const Random = { n = n || 1; let cpArr = arr.map(e => e); for (let index = 0; index < n; index++) { - const rand = randInt(index, arr.length); + const rand = Random.randInt(index, arr.length); [ cpArr[index], cpArr[rand] ] = [ cpArr[rand], cpArr[index] ]; } return cpArr.slice(0, n); }, shuffle: function(arr) { - return sample(arr, arr.length); + return Random.sample(arr, arr.length); } }; diff --git a/variants.js b/variants.js index 13dac98..dc7540e 100644 --- a/variants.js +++ b/variants.js @@ -27,7 +27,7 @@ const variants = [ // {name: 'Capablanca', desc: 'Capablanca Chess', disp: 'Capablanca Chess'}, {name: 'Capture', desc: 'Mandatory captures'}, // {name: 'Castle', desc: 'Win by castling long'}, -// {name: 'Chakart', desc: 'Capture the princess'}, + {name: 'Chakart', desc: 'Capture the princess'}, // {name: 'Checkered', desc: 'Shared pieces'}, // {name: 'Checkless', desc: 'No-check mode'}, {name: 'Chess960', disp: "Chess 960", desc: "Standard rules"}, diff --git a/variants/Chakart/class.js b/variants/Chakart/class.js index 5bb1bde..768f50e 100644 --- a/variants/Chakart/class.js +++ b/variants/Chakart/class.js @@ -1,11 +1,11 @@ -import ChessRules from "/base_rules"; -import GiveawayRules from "/variants/Giveaway"; +import ChessRules from "/base_rules.js"; +import GiveawayRules from "/variants/Giveaway/class.js"; import { ArrayFun } from "/utils/array.js"; import { Random } from "/utils/alea.js"; import PiPo from "/utils/PiPo.js"; import Move from "/utils/Move.js"; -export class ChakartRules extends ChessRules { +export default class ChakartRules extends ChessRules { static get Options() { return { @@ -76,9 +76,10 @@ export class ChakartRules extends ChessRules { } genRandInitFen(seed) { - const gr = new GiveawayRules({mode: "suicide"}, true); + const gr = new GiveawayRules( + {mode: "suicide", options: {}, genFenOnly: true}); return ( - gr.genRandInitFen(seed).slice(0, -1) + + gr.genRandInitFen(seed).slice(0, -17) + // Add Peach + Mario flags + capture counts '{"flags":"1111","ccount":"000000000000"}' ); @@ -125,23 +126,22 @@ export class ChakartRules extends ChessRules { } getCapturedFen() { - const res = ['w', 'b'].map(c => { - Object.values(this.captured[c]) - }); + const res = ['w', 'b'].map(c => Object.values(this.captured[c])); return res[0].concat(res[1]).join(""); } setOtherVariables(fenParsed) { super.setOtherVariables(fenParsed); // Initialize captured pieces' counts from FEN - const allCapts = fenParsed.captured.split("").map(x => parseInt(x, 10)); + const allCapts = fenParsed.ccount.split("").map(x => parseInt(x, 10)); const pieces = ['p', 'r', 'n', 'b', 'q', 'k']; this.captured = { - w: Array.toObject(pieces, allCapts.slice(0, 6)), - b: Array.toObject(pieces, allCapts.slice(6, 12)) + w: ArrayFun.toObject(pieces, allCapts.slice(0, 6)), + b: ArrayFun.toObject(pieces, allCapts.slice(6, 12)) }; this.reserve = { w: {}, b: {} }; //to be replaced by this.captured this.moveStack = []; + this.egg = null; } // For Toadette bonus @@ -176,18 +176,39 @@ export class ChakartRules extends ChessRules { } // Moving something. Potential effects resolved after playing - getPotentialMovesFrom([x, y], bonus) { + getPotentialMovesFrom([x, y]) { let moves = []; - if (bonus == "toadette") + if (this.egg == "toadette") return this.getDropMovesFrom([x, y]); - if (bonus == "kingboo") { + if (this.egg == "kingboo") { const initPiece = this.getPiece(x, y); const color = this.getColor(x, y); const oppCol = C.GetOppCol(color); - // Only allow to swap pieces (TODO: restrict for pawns) + // Only allow to swap pieces for (let i=0; i= 0 && - y + shiftY < sizeY && + y + shiftY < this.size.y && this.board[x + shiftX][y + shiftY] != "" && // Pawns cannot capture invisible queen this way! this.getPiece(x + shiftX, y + shiftY) != V.INVISIBLE_QUEEN && @@ -416,18 +437,27 @@ export class ChakartRules extends ChessRules { this.movesCount++; this.subTurn = 1; } + + + if (move.egg) + this.displayBonus(move.egg); + else if (this.egg) + this.egg = null; //the egg is consumed + } + + displayBonus(egg) { + alert(egg); //TODO: nicer display } filterValid(moves) { return moves; } - // idée : on joue le coup, puis son effet est déterminé, puis la suite (si suite) - // est jouée automatiquement ou demande action utilisateur, etc jusqu'à coup terminal. tryMoveFollowup(move, cb) { - if (this.getColor(move.end.x, move.end.y) == 'a') { + // Warning: at this stage, the move is played + if (move.vanish.length == 2 && move.vanish[1].c == 'a') { // effect, or bonus/malus - const endType = this.getPiece(m.end.x, m.end.y); + const endType = move.vanish[1].p; switch (endType) { case V.EGG: this.applyRandomBonus(move, cb); @@ -439,26 +469,48 @@ export class ChakartRules extends ChessRules { endType == V.BANANA ? [[1, 1], [1, -1], [-1, 1], [-1, -1]] : [[1, 0], [-1, 0], [0, 1], [0, -1]]); - const nextMove = this.getBasicMove([move.end.x, move.end.y], dest); - cb(nextMove); + cb(this.getBasicMove([move.end.x, move.end.y], dest)); break; } - case V.MUSHROOM: - // aller dans direction, saut par dessus pièce adverse - // ou amie (tjours), new step si roi caval pion + case V.MUSHROOM: { + let step = [move.end.x - move.start.x, move.end.y - move.start.y]; + if ([0, 1].some(i => step[i] >= 2 && step[1-i] != 1)) { + // Slider, multi-squares: normalize step + for (let j of [0, 1]) + step[j] = step[j] / Math.abs(step[j]) || 0; + } + const nextSquare = [move.end.x + step[0], move.end.y + step[1]]; + if (this.onBoard(nextSquare[0], nextSquare[1])) { + if ( + this.board[nextSquare[0]][nextSquare[1]] != "" && + this.getColor(nextSquare[0], nextSquare[1]) != 'a' + ) { + // (try to) jump + const afterSquare = + [nextSquare[0] + step[0], nextSquare[1] + step[1]]; + if ( + this.onBoard(afterSquare[0], afterSquare[1]) && + this.getColor(afterSquare[0], afterSquare[1]) != this.turn + ) { + cb(this.getBasicMove([move.end.x, move.end.y], afterSquare)); + } + } + else if (!['b', 'r', 'q'].includes(move.vanish[0].p)) + // Take another step forward if not slider move + cb(this.getBasicMove([move.end.x, move.end.y], nextSquare)); + } break; + } } } } - playVisual(move, r) { - super.playVisual(move, r); - if (move.bonus) - alert(move.bonus); //TODO: nicer display - } - applyRandomBonus(move, cb) { - // TODO: determine bonus/malus, and then + // TODO: determine bonus/malus, and then ... + // if toadette, daisy or kingboo : do not call cb + this.egg = "daisy"; //not calling cb in this case + this.displayBonus(this.egg); + move.egg = this.egg; //for play() by opponent } // Helper to apply banana/bomb effect diff --git a/variants/Chakart/rules.html b/variants/Chakart/rules.html index c87be5c..f2e5068 100644 --- a/variants/Chakart/rules.html +++ b/variants/Chakart/rules.html @@ -4,7 +4,9 @@
  • Mushrooms speed-up your pieces.
  • Bananas redirect by one square orthogonally.
  • Bombs redirect by one square diagonally.
  • -
  • Eggs hide either a bonus or malus, as indicated...
  • +
  • Eggs hide either a bonus or malus: see full description.
  • +Full rules description. +

    Charlotte Blard & Benjamin Auder (2020).

    diff --git a/variants/Giveaway/class.js b/variants/Giveaway/class.js index 77f5c74..71f70be 100644 --- a/variants/Giveaway/class.js +++ b/variants/Giveaway/class.js @@ -37,6 +37,9 @@ export default class GiveawayRules extends ChessRules { } genRandInitFen(seed) { + if (this.options["mode"] == "losers") + return super.genRandInitFen(seed); + if (this.options["randomness"] == 0) { return ( 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w 0 {"enpassant":"-"}' -- 2.44.0