From c5fd037c7c787097c5c731a2d8c1bd070be692ed Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Sat, 9 May 2026 12:42:46 +0200 Subject: [PATCH] Some fixes, improvements... --- js/base_rules.js | 21 ++++++++-- js/server.js | 2 +- variants/Alapo/class.js | 13 ++++-- variants/Apocalypse/class.js | 3 ++ variants/Atarigo/class.js | 9 +++- variants/Avalam/class.js | 6 ++- variants/Discoduel/class.js | 3 ++ variants/Giveaway/class.js | 4 ++ variants/Hex/class.js | 3 ++ variants/Sleepy/class.js | 81 ++++++++++++++++++++---------------- variants/Weiqi/class.js | 6 ++- 11 files changed, 102 insertions(+), 49 deletions(-) diff --git a/js/base_rules.js b/js/base_rules.js index 5ff92f8..347d5b2 100644 --- a/js/base_rules.js +++ b/js/base_rules.js @@ -66,7 +66,7 @@ export default class ChessRules { "cannibal", "capture", "crazyhouse", - "cylinder", //ok with all + "cylinder", //ok with ~all "dark", "doublemove", "madrasi", @@ -117,6 +117,11 @@ export default class ChessRules { return this.hasReserve; } + // Some variants don't have kings, not relevant + static get HasKing() { + return true; + } + get noAnimate() { return !!this.options["dark"]; } @@ -1187,6 +1192,8 @@ export default class ChessRules { } isKing(x, y, p) { + if (!V.HasKing) + return false; if (!p) p = this.getPiece(x, y); if (!this.options["cannibal"]) @@ -2244,6 +2251,8 @@ export default class ChessRules { // 'color' arg because some variants (e.g. Refusal) check opponent moves filterValid(moves, color) { + if (!V.HasKing) + return moves; color = color || this.turn; const oppCols = this.getOppCols(color); let kingPos = this.searchKingPos(color); @@ -2401,9 +2410,11 @@ export default class ChessRules { if (move.next) return false; const color = this.turn; - const oppKingPos = this.searchKingPos(C.GetOppTurn(color)); - if (oppKingPos.length == 0 || this.underCheck(oppKingPos, [color])) - return true; + if (V.HasKing) { + const oppKingPos = this.searchKingPos(C.GetOppTurn(color)); + if (oppKingPos.length == 0 || this.underCheck(oppKingPos, [color])) + return true; + } return ( ( !this.options["balance"] || @@ -2453,6 +2464,8 @@ export default class ChessRules { // Shortcut in case the score was computed before: if (move.result) return move.result; + if (!V.HasKing) + return "*"; //can't guess better.. const oppTurn = C.GetOppTurn(this.turn); const kingPos = { w: this.searchKingPos('w'), diff --git a/js/server.js b/js/server.js index 2c0211e..1104b94 100644 --- a/js/server.js +++ b/js/server.js @@ -54,7 +54,7 @@ function getRandomVariant() { if (params.dev) { const chokidar = require("chokidar"); const watcher = chokidar.watch( - ["*.js", "*.css", "utils/", "variants/"], + ["*.js", "*.css", "css/", "js/", "pieces/", "utils/", "variants/"], { persistent: true } ); diff --git a/variants/Alapo/class.js b/variants/Alapo/class.js index 4ad6f88..fa047eb 100644 --- a/variants/Alapo/class.js +++ b/variants/Alapo/class.js @@ -8,7 +8,7 @@ export default class AlapoRules extends ChessRules { static get Options() { return { select: C.Options.select, - styles: C.Options.styles.filter(s => s != "teleport") + styles: C.Options.styles.filter(s => !["recycle","teleport"].includes(s)) }; } @@ -18,6 +18,9 @@ export default class AlapoRules extends ChessRules { get hasEnpassant() { return false; } + static get HasKing() { + return false; + } getSvgChessboard() { let board = super.getSvgChessboard().slice(0, -6); @@ -49,7 +52,7 @@ export default class AlapoRules extends ChessRules { s.w.map(p => piece2pawn[p].toUpperCase()).join("") + "/" + s.w.join("").toUpperCase() ); - return { fen: fen, o: {} }; + return { fen, o: {} }; } // Triangles are rotated from opponent viewpoint (=> suffix "_inv") @@ -58,8 +61,10 @@ export default class AlapoRules extends ChessRules { return { 'r': allSpecs['r'], 'q': allSpecs['q'], - 'b': Object.assign({}, allSpecs['b'], - {"class": "bishop" + (this.playerColor != color ? "_inv" : "")}), + 'b': { + "class": "bishop" + (this.playerColor != color ? "_inv" : ""), + ...allSpecs['b'] + }, 's': { //"square" "class": "babyrook", both: [ diff --git a/variants/Apocalypse/class.js b/variants/Apocalypse/class.js index e77bb2c..c380eaa 100644 --- a/variants/Apocalypse/class.js +++ b/variants/Apocalypse/class.js @@ -16,6 +16,9 @@ export default class ApocalypseRules extends ChessRules { get hideMoves() { return true; } + static get HasKing() { + return false; + } pawnPromotions() { return ['n', 'p']; diff --git a/variants/Atarigo/class.js b/variants/Atarigo/class.js index 1b848c9..120afdc 100644 --- a/variants/Atarigo/class.js +++ b/variants/Atarigo/class.js @@ -8,7 +8,14 @@ export default class AtarigoRules extends WeiqiRules { static get Options() { let input = WeiqiRules.Options.input; input[0].defaut = 11; - return {input: input}; + return { + input, + styles: WeiqiRules.Options.styles + }; + } + + static get HasKing() { + return false; } getCurrentScore(move_s) { diff --git a/variants/Avalam/class.js b/variants/Avalam/class.js index 6e9fc3e..13cc55e 100644 --- a/variants/Avalam/class.js +++ b/variants/Avalam/class.js @@ -23,7 +23,8 @@ export default class AvalamRules extends ChessRules { type: "checkbox", defaut: false } - ] + ], + styles: ["doublemove", "progressive"] }; } @@ -33,6 +34,9 @@ export default class AvalamRules extends ChessRules { get hasEnpassant() { return false; } + static get HasKing() { + return false; + } pieces(color, x, y) { const steps = [ diff --git a/variants/Discoduel/class.js b/variants/Discoduel/class.js index 50ebee0..07502aa 100644 --- a/variants/Discoduel/class.js +++ b/variants/Discoduel/class.js @@ -14,6 +14,9 @@ export default class DiscoduelRules extends ChessRules { get hasFlags() { return false; } + static get HasKing() { + return false; + } genRandInitBaseFen() { return { diff --git a/variants/Giveaway/class.js b/variants/Giveaway/class.js index c08f75a..b34be7b 100644 --- a/variants/Giveaway/class.js +++ b/variants/Giveaway/class.js @@ -21,6 +21,7 @@ export default class GiveawayRules extends ChessRules { input: C.Options.input.filter(i => i.variable == "pawnfall"), styles: [ "atomic", "cannibal", "cylinder", "dark", + "doublemove", "progressive", "madrasi", "rifle", "teleport", "zen" ] }; @@ -29,6 +30,9 @@ export default class GiveawayRules extends ChessRules { get hasFlags() { return this.options["mode"] == "losers"; } + static get HasKing() { + return this.options["mode"] == "losers"; + } pawnPromotions() { let res = ['q', 'r', 'n', 'b']; diff --git a/variants/Hex/class.js b/variants/Hex/class.js index 05200be..22dee0d 100644 --- a/variants/Hex/class.js +++ b/variants/Hex/class.js @@ -38,6 +38,9 @@ export default class HexRules extends AbstractClickFillRules { get clickOnly() { return true; } + static get HasKing() { + return false; + } doClick(coords) { if ( diff --git a/variants/Sleepy/class.js b/variants/Sleepy/class.js index b40ebab..b50ca0b 100644 --- a/variants/Sleepy/class.js +++ b/variants/Sleepy/class.js @@ -2,58 +2,65 @@ import ChessRules from "/js/base_rules.js"; export default class SleepyRules extends ChessRules { + static get Options() { + return { + select: C.Options.select, + input: C.Options.input, + styles: ["balance", "capture", "cylinder", "dark", "rifle", "zen"] + }; + } + + setOtherVariables(fenParsed) { + super.setOtherVariables(fenParsed); + this.states = JSON.parse(fenParsed.states); + } + + getPartFen(o) { + return { + "states": (o.init ? '0'.repeat(64) : JSON.stringify(this.states)), + ...super.getPartFen(o) + }; + } + pieces(color, x, y) { - let res = super.pieces(color, x, y); - res['s'] = {"class": "sleepy-pawn", moveas: "p"}; - res['u'] = {"class": "sleepy-rook", moveas: "r"}; - res['o'] = {"class": "sleepy-knight", moveas: "n"}; - res['c'] = {"class": "sleepy-bishop", moveas: "b"}; - res['t'] = {"class": "sleepy-queen", moveas: "q"}; - return res; + return { + 's': {"class": "sleepy-pawn"}, + 'u': {"class": "sleepy-rook"}, + 'o': {"class": "sleepy-knight"}, + 'c': {"class": "sleepy-bishop"}, + 't': {"class": "sleepy-queen"}, + ...super.pieces(color, x, y) + }; } - static get V_PIECES() { + static get M_PIECES() { return ['p', 'r', 'n', 'b', 'q']; } static get S_PIECES() { return ['s', 'u', 'o', 'c', 't']; } - // Forbid sleepy pieces to capture - canTake([x1, y1], [x2, y2]) { - return ( - this.getColor(x1, y1) !== this.getColor(x2, y2) && - (['k'].concat(V.V_PIECES)).includes(this.getPiece(x1, y1)) - ); + getPotentialMovesOf(piece, [x, y]) { + if (V.S_PIECES.includes(piece)) + return []; + return super.getPotentialMovesOf(piece, [x, y]); } - - //TODO: - - - pawnPostProcess(moves, color, oppCols) { - let res = super.pawnPostProcess(moves, color, oppCols); - if (res.length > 0 && res[0].vanish[0].p == 's') { - // Fix promotions of non-violent pawns (if any) - res.forEach(m => { - if (m.appear[0].p != 's') - m.appear[0].p = V.NV_PIECES[V.V_PIECES.indexOf(m.appear[0].p)]; - }); - } - return res; + getStateIndex(coords) { + return this.size.y * coords.x + coords.y; } prePlay(move) { super.prePlay(move); - // NOTE: drop moves already taken into account in base prePlay() - if (move.vanish.length == 2 && move.appear.length == 1) { - const normal = V.V_PIECES.includes(move.vanish[1].p); - const pIdx = - (normal ? V.V_PIECES : V.NV_PIECES).indexOf(move.vanish[1].p); - const resPiece = (normal ? V.NV_PIECES : V.V_PIECES)[pIdx]; - super.updateReserve(C.GetOppTurn(this.turn), resPiece, - this.reserve[C.GetOppTurn(this.turn)][resPiece] + 1); - } + // 1) Wake up observed pieces + // TODO: findDestSquares(attackOnly = true) with changing piece color on board + // Loop on found squares + if index in S_PIECES then change + // 2) Update sleepy status + const indices = [move.start, move.end].map(this.getStateIndex); + this.states[indices[1]] = this.states[indices[0]] + 1; + this.states[indices[0]] = 0; + if (this.states[indices[1]] >= 3) + move.appear[0].p = V.S_PIECES[V.M_PIECES.indexOf(move.appear[0].p)]; } }; diff --git a/variants/Weiqi/class.js b/variants/Weiqi/class.js index 6f6b1d8..f9ca469 100644 --- a/variants/Weiqi/class.js +++ b/variants/Weiqi/class.js @@ -20,7 +20,8 @@ export default class WeiqiRules extends ChessRules { type: "checkbox", defaut: false } - ] + ], + styles: ["doublemove", "progressive"] }; } @@ -33,6 +34,9 @@ export default class WeiqiRules extends ChessRules { get clickOnly() { return true; } + static get HasKing() { + return false; + } getSvgChessboard() { const flipped = (this.playerColor == 'b'); -- 2.53.0