From: Benjamin Auder Date: Sat, 11 Mar 2023 08:32:05 +0000 (+0100) Subject: Draft Circular chess. Move animation not per segments for now X-Git-Url: https://git.auder.net/doc/html/index.html?a=commitdiff_plain;h=65203419968be4b63acf55172fe4b28658b96f38;p=xogo.git Draft Circular chess. Move animation not per segments for now --- diff --git a/base_rules.js b/base_rules.js index e8cf4f4..98c6bd4 100644 --- a/base_rules.js +++ b/base_rules.js @@ -122,6 +122,11 @@ export default class ChessRules { return false; } + // Some variants do not flip board as black + get flippedBoard() { + return (this.playerColor == 'b'); + } + // Some variants use click infos: doClick(coords) { if (typeof coords.x != "number") @@ -566,7 +571,7 @@ export default class ChessRules { // Get SVG board (background, no pieces) getSvgChessboard() { - const flipped = (this.playerColor == 'b'); + const flipped = this.flippedBoard; let board = ` = 6) || (color == 'b' && x <= 1); + } pieces(color, x, y) { const pawnShift = this.getPawnShift(color); - // NOTE: jump 2 squares from first rank (pawns can be here sometimes) - const initRank = ((color == 'w' && x >= 6) || (color == 'b' && x <= 1)); return { 'p': { "class": "pawn", moves: [ { steps: [[pawnShift, 0]], - range: (initRank ? 2 : 1) + range: (this.isPawnInitRank(x, color) ? 2 : 1) } ], attack: [ @@ -1290,6 +1296,17 @@ export default class ChessRules { res += this.size.y; return res; } + // Circular? + getX(x) { + return x; //generally, no + } + + increment([x, y], step) { + return [ + this.getX(x + step[0]), + this.getY(y + step[1]) + ]; + } getSegments(curSeg, segStart, segEnd) { if (curSeg.length == 0) @@ -1355,13 +1372,12 @@ export default class ChessRules { const attacks = stepSpec.both.concat(stepSpec.attack); for (let a of attacks) { outerLoop: for (let step of a.steps) { - let [i, j] = [x + step[0], y + step[1]]; - let stepCounter = 1; + let [i, j] = this.increment([x, y], step); + let stepCounter = 0; while (this.onBoard(i, j) && this.board[i][j] == "") { if (a.range <= stepCounter++) continue outerLoop; - i += step[0]; - j = this.getY(j + step[1]); + [i, j] = this.increment([i, j], step); } if ( this.onBoard(i, j) && @@ -1570,8 +1586,7 @@ export default class ChessRules { vanish: [] }); for (let step of steps) { - let x = m.end.x + step[0]; - let y = this.getY(m.end.y + step[1]); + let [x, y] = this.increment([m.end.x, m.end.y], step); if ( this.onBoard(x, y) && this.board[x][y] != "" && @@ -1659,7 +1674,7 @@ export default class ChessRules { m.appear[0].p = this.pawnPromotions[0]; for (let i=1; i 1) { // Boundary between segments (cylinder mode) segments.push([[segStart[0], segStart[1]], oldIJ]); @@ -1990,7 +2004,7 @@ export default class ChessRules { const oppCols = this.getOppCols(color); if ( this.epSquare && - this.epSquare.x == x + shiftX && + this.epSquare.x == x + shiftX && //NOTE: epSquare.x not on edge Math.abs(this.getY(this.epSquare.y - y)) == 1 && // Doublemove (and Progressive?) guards: this.board[this.epSquare.x][this.epSquare.y] == "" && diff --git a/variants.js b/variants.js index 8353853..c20f800 100644 --- a/variants.js +++ b/variants.js @@ -29,7 +29,7 @@ const variants = [ {name: 'Checkered', desc: 'Shared pieces'}, {name: 'Checkless', desc: 'No-check mode'}, {name: 'Chess960', disp: "Chess 960", desc: "Standard rules"}, -// {name: 'Circular', desc: 'Run forward'}, + {name: 'Circular', desc: 'Run forward'}, // {name: 'Clorange', desc: 'A Clockwork Orange', disp: 'Clockwork Orange'}, // {name: 'Convert', desc: 'Convert enemy pieces'}, // {name: 'Copycat', desc: 'Borrow powers'}, diff --git a/variants/Circular/class.js b/variants/Circular/class.js new file mode 100644 index 0000000..24aa98e --- /dev/null +++ b/variants/Circular/class.js @@ -0,0 +1,99 @@ +import ChessRules from "/base_rules.js"; +import {FenUtil} from "/utils/setupPieces.js"; + +export default class CircularRules extends ChessRules { + + get hasCastle() { + return false; + } + get hasEnpassant() { + return false; + } + + // Everypawn is going up! + getPawnShift(color) { + return -1; + } + isPawnInitRank(x, color) { + return (color == 'w' && x == 6) || (color == 'b' && x == 2); + } + + get flippedBoard() { + return false; + } + + // Circular board: + // TODO: graph with segments, as for cylindrical... + getX(x) { + let res = x % this.size.x; + if (res < 0) + res += this.size.x; + return res; + } + + // TODO: rewrite in more elegant way + getFlagsFen() { + let flags = ""; + for (let c of ["w", "b"]) { + for (let i = 0; i < 8; i++) + flags += this.pawnFlags[c][i] ? "1" : "0"; + } + return flags; + } + + setFlags(fenflags) { + this.pawnFlags = { + w: [...Array(8)], //pawns can move 2 squares? + b: [...Array(8)] + }; + for (let c of ["w", "b"]) { + for (let i = 0; i < 8; i++) + this.pawnFlags[c][i] = fenflags.charAt((c == "w" ? 0 : 8) + i) == "1"; + } + } + + genRandInitBaseFen() { + let setupOpts = { + randomness: this.options["randomness"], + diffCol: ['b'] + }; + const s = FenUtil.setupPieces( + ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'], setupOpts); + return { + fen: "8/8/pppppppp/" + s.b.join("") + "/8/8/PPPPPPPP/" + + s.w.join("").toUpperCase(), + o: {flags: "11111111"} + }; + } + + filterValid(moves) { + const filteredMoves = super.filterValid(moves); + // If at least one full move made, everything is allowed: + if (this.movesCount >= 2) + return filteredMoves; + // Else, forbid checks: + const oppCol = C.GetOppTurn(this.turn); + const oppKingPos = this.searchKingPos(oppCol); + return filteredMoves.filter(m => { + this.playOnBoard(m); + const res = !this.underCheck(oppKingPos, [this.turn]); + this.undoOnBoard(m); + return res; + }); + } + + prePlay(move) { + if (move.appear.length > 0 && move.vanish.length > 0) { + super.prePlay(move); + if ( + [2, 6].includes(move.start.x) && + move.vanish[0].p == 'p' && + Math.abs(move.end.x - move.start.x) == 2 + ) { + // This move turns off a 2-squares pawn flag + this.pawnFlags[move.start.x == 6 ? "w" : "b"][move.start.y] = false; + } + } + } + +}; diff --git a/variants/Circular/rules.html b/variants/Circular/rules.html new file mode 100644 index 0000000..6db9dd8 --- /dev/null +++ b/variants/Circular/rules.html @@ -0,0 +1,4 @@ +

+Lower and upper sides of the board communicate.
+ All pawns move forward (up). +

diff --git a/variants/Circular/style.css b/variants/Circular/style.css new file mode 100644 index 0000000..290a6f4 --- /dev/null +++ b/variants/Circular/style.css @@ -0,0 +1 @@ +@import url("/base_pieces.css")