X-Git-Url: https://git.auder.net/rpsls.js?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FAlapo.js;fp=client%2Fsrc%2Fvariants%2FAlapo.js;h=6864457ebab8a471ee16f55032f2aa77712edfc5;hb=0f7762c1d87e21d1c13ff0f38bd234b64b0a29d9;hp=0000000000000000000000000000000000000000;hpb=da9e846e41622111a4f877742dc0b35406635b5c;p=vchess.git diff --git a/client/src/variants/Alapo.js b/client/src/variants/Alapo.js new file mode 100644 index 00000000..6864457e --- /dev/null +++ b/client/src/variants/Alapo.js @@ -0,0 +1,224 @@ +import { ChessRules } from "@/base_rules"; + +export class AlapoRules extends ChessRules { + + static get HasFlags() { + return false; + } + + static get HasEnpassant() { + return false; + } + + static get Lines() { + return [ + [[1, 0], [1, 6]], + [[5, 0], [5, 6]] + ]; + } + + static get PIECES() { + return [V.ROOK, V.BISHOP, V.QUEEN, V.ROOK_S, V.BISHOP_S, V.QUEEN_S]; + } + + static get ROOK_S() { + return "t"; + } + static get BISHOP_S() { + return "c"; + } + static get QUEEN_S() { + return "s"; + } + + getPotentialMinirookMoves(sq) { + return super.getSlideNJumpMoves(sq, V.steps[V.ROOK], "oneStep"); + } + getPotentialMinibishopMoves(sq) { + return super.getSlideNJumpMoves(sq, V.steps[V.BISHOP], "oneStep"); + } + getPotentialMiniqueenMoves(sq) { + return ( + super.getSlideNJumpMoves( + sq, V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep") + ); + } + + getPotentialMovesFrom(sq) { + switch (this.getPiece(sq[0], sq[1])) { + case V.ROOK: return super.getPotentialRookMoves(sq); + case V.BISHOP: return super.getPotentialBishopMoves(sq); + case V.QUEEN: return super.getPotentialQueenMoves(sq); + case V.ROOK_S: return this.getPotentialMinirookMoves(sq); + case V.BISHOP_S: return this.getPotentialMinibishopMoves(sq); + case V.QUEEN_S: return this.getPotentialMiniqueenMoves(sq); + } + return []; + } + + static get size() { + return { x: 6, y: 6 }; + } + + getPpath(b, color, score, orientation) { + // 'i' for "inversed": + const suffix = (b[0] == orientation ? "" : "i"); + return "Alapo/" + b + suffix; + } + + static GenRandInitFen(randomness) { + if (randomness == 0) + return "rbqqbr/tcssct/6/6/TCSSCT/RBQQBR w 0"; + + const piece2pawn = { + r: 't', + q: 's', + b: 'c' + }; + + let pieces = { w: new Array(6), b: new Array(6) }; + // Shuffle pieces on first (and last rank if randomness == 2) + for (let c of ["w", "b"]) { + if (c == 'b' && randomness == 1) { + pieces['b'] = pieces['w']; + break; + } + + let positions = ArrayFun.range(6); + + // Get random squares for bishops + let randIndex = 2 * randInt(3); + const bishop1Pos = positions[randIndex]; + let randIndex_tmp = 2 * randInt(3) + 1; + const bishop2Pos = positions[randIndex_tmp]; + positions.splice(Math.max(randIndex, randIndex_tmp), 1); + positions.splice(Math.min(randIndex, randIndex_tmp), 1); + + // Get random square for queens + randIndex = randInt(4); + const queen1Pos = positions[randIndex]; + positions.splice(randIndex, 1); + randIndex = randInt(3); + const queen2Pos = positions[randIndex]; + positions.splice(randIndex, 1); + + // Rooks positions are now fixed, + const rook1Pos = positions[0]; + const rook2Pos = positions[1]; + + pieces[c][rook1Pos] = "r"; + pieces[c][bishop1Pos] = "b"; + pieces[c][queen1Pos] = "q"; + pieces[c][queen2Pos] = "q"; + pieces[c][bishop2Pos] = "b"; + pieces[c][rook2Pos] = "r"; + } + return ( + pieces["b"].join("") + "/" + + pieces["b"].map(p => piece2pawn[p]).join() + + "/8/8/8/8/" + + pieces["w"].map(p => piece2pawn[p].toUpperCase()).join() + "/" + + pieces["w"].join("").toUpperCase() + + " w 0" + ); + } + + static IsGoodPosition(position) { + if (position.length == 0) return false; + const rows = position.split("/"); + if (rows.length != V.size.x) return false; + // Just check that at least one piece of each color is there: + let pieces = { "w": 0, "b": 0 }; + for (let row of rows) { + let sumElts = 0; + for (let i = 0; i < row.length; i++) { + const lowerRi = row[i].toLowerCase(); + if (V.PIECES.includes(lowerRi)) { + pieces[row[i] == lowerRi ? "b" : "w"]++; + sumElts++; + } + else { + const num = parseInt(row[i], 10); + if (isNaN(num)) return false; + sumElts += num; + } + } + if (sumElts != V.size.y) return false; + } + if (Object.values(pieces).some(v => v == 0)) return false; + return true; + } + + // Find possible captures by opponent on [x, y] + findCaptures([x, y]) { + const color = this.getColor(x, y); + let moves = []; + const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]); + const oppCol = V.GetOppCol(color); + for (let loop = 0; loop < steps.length; loop++) { + const step = steps[loop]; + let i = x + step[0]; + let j = y + step[1]; + let stepsAfter = 1; + while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) { + i += step[0]; + j += step[1]; + stepsAfter++; + } + if ( + V.OnBoard(i, j) && + this.board[i][j] != V.EMPTY && + this.getColor(i, j) == oppCol + ) { + const oppPiece = this.getPiece(i, j); + if ( + ( + stepsAfter >= 2 && + [V.ROOK_S, V.BISHOP_S, V.QUEEN_S].includes(oppPiece) + ) + || + ( + [V.BISHOP, V.BISHOP_S].includes(oppPiece) && + step.some(e => e == 0) + ) + || + ( + [V.ROOK, V.ROOK_S].includes(oppPiece) && + step.every(e => e != 0) + ) + ) { + continue; + } + return true; + } + } + return false; + } + + postPlay() {} + postUndo() {} + + getCheckSquares() { + return []; + } + filterValid(moves) { + return moves; + } + + getCurrentScore() { + // Try both colors (to detect potential suicides) + for (let c of ['w', 'b']) { + const oppCol = V.GetOppCol(c); + const goal = (c == 'w' ? 0 : 5); + if ( + this.board[goal].some( + (b,j) => b[0] == c && !this.findCaptures([goal, j]) + ) + ) { + return c == 'w' ? "1-0" : "0-1"; + } + } + return super.getCurrentScore(); + } + +};