X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FMinishogi.js;fp=client%2Fsrc%2Fvariants%2FMinishogi.js;h=ae5876fe54b9196beeaab60b4df9a84f95586815;hb=e2f204eda8630746cb951889da01241b1e5f5733;hp=0000000000000000000000000000000000000000;hpb=ad2494bd14f9a2fd068d713df0f8ac1fb3c3743f;p=vchess.git diff --git a/client/src/variants/Minishogi.js b/client/src/variants/Minishogi.js new file mode 100644 index 00000000..ae5876fe --- /dev/null +++ b/client/src/variants/Minishogi.js @@ -0,0 +1,170 @@ +import { ChessRules } from "@/base_rules"; +import { ShogiRules } from "@/variants/Shogi"; + +export class MinishogiRules extends ShogiRules { + static IsGoodFen(fen) { + if (!ChessRules.IsGoodFen(fen)) return false; + const fenParsed = V.ParseFen(fen); + // 3) Check reserves + if (!fenParsed.reserve || !fenParsed.reserve.match(/^[0-9]{10,10}$/)) + return false; + return true; + } + + // No knight or lance + static get PIECES() { + return [ + ChessRules.PAWN, + ChessRules.ROOK, + ChessRules.BISHOP, + ChessRules.KING, + V.GOLD_G, + V.SILVER_G, + V.P_PAWN, + V.P_SILVER, + V.P_ROOK, + V.P_BISHOP + ]; + } + + static GenRandInitFen() { + return "rbsgk/4p/5/P4/KGSBR w 0 0000000000"; + } + + getReserveFen() { + let counts = new Array(10); + for (let i = 0; i < V.RESERVE_PIECES.length; i++) { + counts[i] = this.reserve["w"][V.RESERVE_PIECES[i]]; + counts[5 + i] = this.reserve["b"][V.RESERVE_PIECES[i]]; + } + return counts.join(""); + } + + setOtherVariables(fen) { + super.setOtherVariables(fen); + const fenParsed = V.ParseFen(fen); + // Also init reserves (used by the interface to show landable pieces) + this.reserve = { + w: { + [V.PAWN]: parseInt(fenParsed.reserve[0]), + [V.ROOK]: parseInt(fenParsed.reserve[1]), + [V.BISHOP]: parseInt(fenParsed.reserve[2]), + [V.GOLD_G]: parseInt(fenParsed.reserve[3]), + [V.SILVER_G]: parseInt(fenParsed.reserve[4]) + }, + b: { + [V.PAWN]: parseInt(fenParsed.reserve[5]), + [V.ROOK]: parseInt(fenParsed.reserve[6]), + [V.BISHOP]: parseInt(fenParsed.reserve[7]), + [V.GOLD_G]: parseInt(fenParsed.reserve[8]), + [V.SILVER_G]: parseInt(fenParsed.reserve[9]) + } + }; + } + + static get size() { + return { x: 5, y: 5 }; + } + + static get RESERVE_PIECES() { + return ( + [V.PAWN, V.ROOK, V.BISHOP, V.GOLD_G, V.SILVER_G] + ); + } + + getReserveMoves([x, y]) { + const color = this.turn; + const p = V.RESERVE_PIECES[y]; + if (p == V.PAWN) { + var oppCol = V.GetOppCol(color); + var allowedFiles = + [...Array(5).keys()].filter(j => + [...Array(5).keys()].every(i => { + return ( + this.board[i][j] == V.EMPTY || + this.getColor(i, j) != color || + this.getPiece(i, j) != V.PAWN + ); + }) + ) + } + if (this.reserve[color][p] == 0) return []; + let moves = []; + const forward = color == 'w' ? -1 : 1; + const lastRank = color == 'w' ? 0 : 4; + for (let i = 0; i < V.size.x; i++) { + if (p == V.PAWN && i == lastRank) continue; + for (let j = 0; j < V.size.y; j++) { + if ( + this.board[i][j] == V.EMPTY && + (p != V.PAWN || allowedFiles.includes(j)) + ) { + 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 } + }); + if (p == V.PAWN) { + // Do not drop on checkmate: + this.play(mv); + const res = (this.underCheck(oppCol) && !this.atLeastOneMove()); + this.undo(mv); + if (res) continue; + } + moves.push(mv); + } + } + } + return moves; + } + + getSlideNJumpMoves([x, y], steps, options) { + options = options || {}; + const color = this.turn; + const oneStep = options.oneStep; + const forcePromoteOnLastRank = options.force; + const promoteInto = options.promote; + const lastRank = (color == 'w' ? 0 : 4); + let moves = []; + outerLoop: for (let step of steps) { + let i = x + step[0]; + let j = y + step[1]; + while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) { + if (i != lastRank || !forcePromoteOnLastRank) + moves.push(this.getBasicMove([x, y], [i, j])); + if (i == lastRank && !!promoteInto) { + moves.push( + this.getBasicMove( + [x, y], [i, j], { c: color, p: promoteInto }) + ); + } + if (oneStep) continue outerLoop; + i += step[0]; + j += step[1]; + } + if (V.OnBoard(i, j) && this.canTake([x, y], [i, j])) { + if (i != lastRank || !forcePromoteOnLastRank) + moves.push(this.getBasicMove([x, y], [i, j])); + if (i == lastRank && !!promoteInto) { + moves.push( + this.getBasicMove( + [x, y], [i, j], { c: color, p: promoteInto }) + ); + } + } + } + return moves; + } + + static get SEARCH_DEPTH() { + return 3; + } +};