From: Benjamin Auder Date: Fri, 17 Mar 2023 13:18:34 +0000 (+0100) Subject: Almost finished Clorange draft X-Git-Url: https://git.auder.net/doc/html/assets/current/git-favicon.png?a=commitdiff_plain;h=6bf2ab3498d5d469ea456b528c178dc481789b76;p=xogo.git Almost finished Clorange draft --- diff --git a/base_rules.js b/base_rules.js index 47f70c2..20ffbee 100644 --- a/base_rules.js +++ b/base_rules.js @@ -408,14 +408,14 @@ export default class ChessRules { } // Some additional variables from FEN (variant dependant) - setOtherVariables(fenParsed) { + setOtherVariables(fenParsed, pieceArray) { // Set flags and enpassant: if (this.hasFlags) this.setFlags(fenParsed.flags); if (this.hasEnpassant) this.epSquare = this.getEpSquare(fenParsed.enpassant); if (this.hasReserve && !this.isDiagram) - this.initReserves(fenParsed.reserve); + this.initReserves(fenParsed.reserve, pieceArray); if (this.options["crazyhouse"]) this.initIspawn(fenParsed.ispawn); if (this.options["teleport"]) { diff --git a/variants/Clorange/class.js b/variants/Clorange/class.js index f245526..38cb958 100644 --- a/variants/Clorange/class.js +++ b/variants/Clorange/class.js @@ -1,232 +1,62 @@ -import { ChessRules, PiPo, Move } from "@/base_rules"; -import { ArrayFun } from "@/utils/array"; +import ChessRules from "/base_rules.js"; export default class ClorangeRules extends ChessRules { + // TODO: options : disable teleport/recycle at least ? + get hasReserve() { return true; } -// TODO - - static GenRandInitFen(options) { - // Capturing and non-capturing reserves: - return ChessRules.GenRandInitFen(options) + " 00000000000000000000"; - } - - getFen() { - return super.getFen() + " " + this.getReserveFen(); - } - - getFenForRepeat() { - return super.getFenForRepeat() + "_" + this.getReserveFen(); - } - - getReserveFen() { + getReserveFen(o) { + if (o.init) + return "00000000000000000000"; return ( - Object.keys(this.reserve).map( - c => Object.values(this.reserve[c]).join("")).join("") + ["w","b"].map(c => Object.values(this.reserve[c]).join("")).join("") ); } - getEpSquare(moveOrSquare) { - if (!moveOrSquare) return undefined; - if (typeof moveOrSquare === "string") { - const square = moveOrSquare; - if (square == "-") return undefined; - return V.SquareToCoords(square); - } - const move = moveOrSquare; - const s = move.start, - e = move.end; - if ( - s.y == e.y && - Math.abs(s.x - e.x) == 2 && - move.vanish.length > 0 && ['p', 's'].includes(move.vanish[0].p) - ) { - return { - x: (s.x + e.x) / 2, - y: s.y - }; - } - return undefined; + pieces(color, x, y) { + let res = super.pieces(color, x, y); + res['s'] = {"class": "nv-pawn", moveas: "p"}; + res['u'] = {"class": "nv-rook", moveas: "r"}; + res['o'] = {"class": "nv-knight", moveas: "n"}; + res['c'] = {"class": "nv-bishop", moveas: "b"}; + res['t'] = {"class": "nv-queen", moveas: "q"}; } setOtherVariables(fen) { - super.setOtherVariables(fen); - // Also init reserves (used by the interface to show landable pieces) - const reserve = - V.ParseFen(fen).reserve.split("").map(x => parseInt(x, 10)); - this.reserve = { - w: { - 'p': reserve[0], - 'r': reserve[1], - 'n': reserve[2], - 'b': reserve[3], - 'q': reserve[4], - 's': reserve[5], - 'u': reserve[6], - 'o': reserve[7], - 'c': reserve[8], - 't': reserve[9] - }, - b: { - 'p': reserve[10], - 'r': reserve[11], - 'n': reserve[12], - 'b': reserve[13], - 'q': reserve[14], - 's': reserve[15], - 'u': reserve[16], - 'o': reserve[17], - 'c': reserve[18], - 't': reserve[19] - } - }; + super.setOtherVariables(fen, + ['p', 'r', 'n', 'b', 'q', 's', 'u', 'o', 'c', 't']); } - getColor(i, j) { - if (i >= V.size.x) return i == V.size.x ? "w" : "b"; - return this.board[i][j].charAt(0); - } - - getPiece(i, j) { - if (i >= V.size.x) return V.RESERVE_PIECES[j]; - return this.board[i][j].charAt(1); - } - - getPpath(b) { - return (V.NON_VIOLENT.includes(b[1]) ? "Clorange/" : "") + b; - } - - getReservePpath(index, color) { - const prefix = - (V.NON_VIOLENT.includes(V.RESERVE_PIECES[index]) ? "Clorange/" : ""); - return prefix + color + V.RESERVE_PIECES[index]; - } - - static get NON_VIOLENT() { - return ['s', 'u', 'o', 'c', 't']; - } - - static get PIECES() { - return ChessRules.PIECES.concat(V.NON_VIOLENT); - } - - // Ordering on reserve pieces - static get RESERVE_PIECES() { - return V.PIECES.filter(p => p != 'k'); - } - - getReserveMoves([x, y]) { - const color = this.turn; - const p = V.RESERVE_PIECES[y]; - if (this.reserve[color][p] == 0) return []; - let moves = []; - let rank1 = 0; - let rank2 = V.size.x - 1; - if (['p', 's'].includes(p)) { - if (color == 'w') rank1++; - else rank2--; - } - for (let i = rank1; i <= rank2; i++) { - for (let j = 0; j < V.size.y; j++) { - if (this.board[i][j] == V.EMPTY) { - let mv = new Move({ - appear: [ - new PiPo({ - x: i, - y: j, - c: color, - p: p - }) - ], - vanish: [], - start: { x: x, y: y }, //a bit artificial... - end: { x: i, y: j } - }); - moves.push(mv); - } - } - } - return moves; - } - - getPotentialMovesFrom([x, y]) { - if (x >= V.size.x) - // Reserves, outside of board: x == sizeX(+1) - return this.getReserveMoves([x, y]); - // Standard moves - switch (this.getPiece(x, y)) { - case 's': return this.getPotentialPawnMoves([x, y]); - case 'u': return super.getPotentialRookMoves([x, y]); - case 'o': return super.getPotentialKnightMoves([x, y]); - case 'c': return super.getPotentialBishopMoves([x, y]); - case 't': return super.getPotentialQueenMoves([x, y]); - default: return super.getPotentialMovesFrom([x, y]); - } - return []; //never reached - } - - getPotentialPawnMoves(sq) { - let moves = super.getPotentialPawnMoves(sq); - if (moves.length > 0 && moves[0].vanish[0].p == 's') { - // Remove captures for non-violent pawns: - moves = moves.filter(m => m.vanish.length == 1); - moves.forEach(m => { - if (m.appear[0].p != 's') { - // Promotion pieces should be non-violent as well: - const pIdx = ChessRules.PIECES.findIndex(p => p == m.appear[0].p) - m.appear[0].p = V.NON_VIOLENT[pIdx]; - } - }); - } - return moves; + postProcessPotentialMoves(moves) { + // Remove captures for non-violent pieces: + return super.postProcessPotentialMoves(moves).filter(m => { + return ( + m.vanish.length != 2 || + m.appear.length != 1 || + ['p', 'r', 'n', 'b', 'q'].includes(m.vanish[0].p) + ); + }); } canTake([x1, y1], [x2, y2]) { return ( this.getColor(x1, y1) !== this.getColor(x2, y2) && - ChessRules.PIECES.includes(this.getPiece(x1, y1)) + ['p', 'r', 'n', 'b', 'q', 'k'].includes(this.getPiece(x1, y1)) ); } - getAllValidMoves() { - let moves = super.getAllPotentialMoves(); - const color = this.turn; - for (let i = 0; i < V.RESERVE_PIECES.length; i++) { - moves = moves.concat( - this.getReserveMoves([V.size.x + (color == "w" ? 0 : 1), i]) - ); - } - return this.filterValid(moves); - } - - atLeastOneMove() { - if (!super.atLeastOneMove()) { - // Search one reserve move - for (let i = 0; i < V.RESERVE_PIECES.length; i++) { - let moves = this.filterValid( - this.getReserveMoves([V.size.x + (this.turn == "w" ? 0 : 1), i]) - ); - if (moves.length > 0) return true; - } - return false; - } - return true; - } - prePlay(move) { super.prePlay(move); - // Skip castle: - if (move.vanish.length == 2 && move.appear.length == 2) return; - const color = this.turn; - if (move.vanish.length == 0) this.reserve[color][move.appear[0].p]--; - else if (move.vanish.length == 2) { - // Capture - const normal = ChessRules.PIECES.includes(move.vanish[1].p); - const pIdx = - normal + // No crazyhouse or recycle, so the last call didn't update reserve: + if (move.vanish.length == 2 && move.appear.length == 1) { + // Capture: update reserves + this.Reserve[move.vanish + const pIdx = ['p', 'r', 'n', 'b', 'q'].indexOf(move.vanish[1].p); + // TODO + if normal ? ChessRules.PIECES.findIndex(p => p == move.vanish[1].p) : V.NON_VIOLENT.findIndex(p => p == move.vanish[1].p); const rPiece = (normal ? V.NON_VIOLENT : ChessRules.PIECES)[pIdx];