X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=client%2Fsrc%2Fvariants%2FTeleport.js;fp=client%2Fsrc%2Fvariants%2FTeleport.js;h=0000000000000000000000000000000000000000;hb=2c9f08fce443d57a70e886242ec391d89e450a7b;hp=cbf6a786adbc59c3d2e1a01c068dd66547777ec5;hpb=3c9dded7df4334236ab6d83a0210c7f4729e29c1;p=vchess.git diff --git a/client/src/variants/Teleport.js b/client/src/variants/Teleport.js deleted file mode 100644 index cbf6a786..00000000 --- a/client/src/variants/Teleport.js +++ /dev/null @@ -1,329 +0,0 @@ -import { ChessRules, Move, PiPo } from "@/base_rules"; -import { randInt } from "@/utils/alea"; - -export class TeleportRules extends ChessRules { - - hoverHighlight([x, y]) { - // Testing move validity results in an infinite update loop. - // TODO: find a way to test validity anyway. - return (this.subTurn == 2 && this.board[x][y] == V.EMPTY); - } - - setOtherVariables(fen) { - super.setOtherVariables(fen); - this.subTurn = 1; - this.firstMove = []; - } - - canTake([x1, y1], [x2, y2]) { - return this.subTurn == 1; - } - - canIplay(side, [x, y]) { - if (this.subTurn == 2) return (this.board[x][y] == V.EMPTY); - return super.canIplay(side, [x, y]); - } - - getPPpath(m) { - if ( - m.vanish.length == 2 && - m.appear.length == 1 && - m.vanish[0].c == m.vanish[1].c && - m.appear[0].p == V.KING - ) { - // Rook teleportation with the king - return this.getPpath(m.vanish[1].c + m.vanish[1].p); - } - return this.getPpath(m.appear[0].c + m.appear[0].p); - } - - getPotentialMovesFrom([x, y]) { - if (this.subTurn == 1) return super.getPotentialMovesFrom([x, y]); - // subTurn == 2: a move is a click, not handled here - return []; - } - - filterValid(moves) { - if (this.subTurn == 2) return super.filterValid(moves); - const color = this.turn; - return moves.filter(m => { - this.play(m); - let res = false; - if ( - m.vanish.length == 1 || - m.appear.length == 2 || - m.vanish[0].c != m.vanish[1].c - ) { - // Standard check: - res = !this.underCheck(color); - } - else { - // Self-capture: find landing square not resulting in check - outerLoop: for (let i=0; i<8; i++) { - for (let j=0; j<8; j++) { - if ( - this.board[i][j] == V.EMPTY && - ( - m.vanish[1].p != V.PAWN || - i != (color == 'w' ? 0 : 7) - ) - ) { - const tMove = new Move({ - appear: [ - new PiPo({ - x: i, - y: j, - c: color, - // The dropped piece nature has no importance: - p: V.KNIGHT - }) - ], - vanish: [], - start: { x: -1, y: -1 } - }); - this.play(tMove); - const moveOk = !this.underCheck(color); - this.undo(tMove); - if (moveOk) { - res = true; - break outerLoop; - } - } - } - } - } - this.undo(m); - return res; - }); - } - - getAllValidMoves() { - if (this.subTurn == 1) return super.getAllValidMoves(); - // Subturn == 2: only teleportations - let moves = []; - const L = this.firstMove.length; - const color = this.turn; - for (let i=0; i<8; i++) { - for (let j=0; j<8; j++) { - if ( - this.board[i][j] == V.EMPTY && - ( - this.firstMove[L-1].vanish[1].p != V.PAWN || - i != (color == 'w' ? 0 : 7) - ) - ) { - const tMove = new Move({ - appear: [ - new PiPo({ - x: i, - y: j, - c: color, - p: this.firstMove[L-1].vanish[1].p - }) - ], - vanish: [], - start: { x: -1, y: -1 } - }); - this.play(tMove); - const moveOk = !this.underCheck(color); - this.undo(tMove); - if (moveOk) moves.push(tMove); - } - } - } - return moves; - } - - underCheck(color) { - if (this.kingPos[color][0] < 0) - // King is being moved: - return false; - return super.underCheck(color); - } - - doClick(square) { - if (isNaN(square[0])) return null; - // If subTurn == 2 && square is empty && !underCheck, then teleport - if (this.subTurn == 2 && this.board[square[0]][square[1]] == V.EMPTY) { - const L = this.firstMove.length; - const color = this.turn; - if ( - this.firstMove[L-1].vanish[1].p == V.PAWN && - square[0] == (color == 'w' ? 0 : 7) - ) { - // Pawns cannot be teleported on last rank - return null; - } - const tMove = new Move({ - appear: [ - new PiPo({ - x: square[0], - y: square[1], - c: color, - p: this.firstMove[L-1].vanish[1].p - }) - ], - vanish: [], - start: { x: -1, y: -1 } - }); - this.play(tMove); - const moveOk = !this.underCheck(color); - this.undo(tMove); - if (moveOk) return tMove; - } - return null; - } - - play(move) { - move.flags = JSON.stringify(this.aggregateFlags()); - if (move.vanish.length > 0) { - this.epSquares.push(this.getEpSquare(move)); - this.firstMove.push(move); - } - V.PlayOnBoard(this.board, move); - if ( - this.subTurn == 2 || - move.vanish.length == 1 || - move.appear.length == 2 || - move.vanish[0].c != move.vanish[1].c - ) { - this.turn = V.GetOppCol(this.turn); - this.subTurn = 1; - this.movesCount++; - } - else this.subTurn = 2; - this.postPlay(move); - } - - postPlay(move) { - if (move.vanish.length == 2 && move.vanish[1].p == V.KING) - // A king is moved: temporarily off board - this.kingPos[move.vanish[1].c] = [-1, -1]; - else if (move.appear[0].p == V.KING) - this.kingPos[move.appear[0].c] = [move.appear[0].x, move.appear[0].y]; - this.updateCastleFlags(move); - } - - // NOTE: no need to update if castleFlags already off - updateCastleFlags(move) { - if (move.vanish.length == 0) return; - const c = move.vanish[0].c; - if ( - move.vanish.length == 2 && - move.appear.length == 1 && - move.vanish[0].c == move.vanish[1].c - ) { - // Self-capture: of the king or a rook? - if (move.vanish[1].p == V.KING) - this.castleFlags[c] = [V.size.y, V.size.y]; - else if (move.vanish[1].p == V.ROOK) { - const firstRank = (c == "w" ? V.size.x - 1 : 0); - if ( - move.end.x == firstRank && - this.castleFlags[c].includes(move.end.y) - ) { - const flagIdx = (move.end.y == this.castleFlags[c][0] ? 0 : 1); - this.castleFlags[c][flagIdx] = V.size.y; - } - } - } - // Normal check: - super.updateCastleFlags(move, move.vanish[0].p, c); - } - - undo(move) { - this.disaggregateFlags(JSON.parse(move.flags)); - if (move.vanish.length > 0) { - this.epSquares.pop(); - this.firstMove.pop(); - } - V.UndoOnBoard(this.board, move); - if (this.subTurn == 2) this.subTurn = 1; - else { - this.turn = V.GetOppCol(this.turn); - this.movesCount--; - this.subTurn = (move.vanish.length > 0 ? 1 : 2); - } - this.postUndo(move); - } - - postUndo(move) { - if (move.vanish.length == 0) { - if (move.appear[0].p == V.KING) - // A king was teleported - this.kingPos[move.appear[0].c] = [-1, -1]; - } - else if (move.vanish.length == 2 && move.vanish[1].p == V.KING) - // A king was (self-)taken - this.kingPos[move.vanish[1].c] = [move.end.x, move.end.y]; - else super.postUndo(move); - } - - getComputerMove() { - let moves = this.getAllValidMoves(); - if (moves.length == 0) return null; - // Custom "search" at depth 1 (for now. TODO?) - const maxeval = V.INFINITY; - const color = this.turn; - const initEval = this.evalPosition(); - moves.forEach(m => { - this.play(m); - m.eval = (color == "w" ? -1 : 1) * maxeval; - if ( - m.vanish.length == 2 && - m.appear.length == 1 && - m.vanish[0].c == m.vanish[1].c - ) { - const moves2 = this.getAllValidMoves(); - m.next = moves2[0]; - moves2.forEach(m2 => { - this.play(m2); - const score = this.getCurrentScore(); - let mvEval = 0; - if (["1-0", "0-1"].includes(score)) - mvEval = (score == "1-0" ? 1 : -1) * maxeval; - else if (score == "*") - // Add small fluctuations to avoid dropping pieces always on the - // first square available. - mvEval = initEval + 0.05 - Math.random() / 10; - if ( - (color == 'w' && mvEval > m.eval) || - (color == 'b' && mvEval < m.eval) - ) { - m.eval = mvEval; - m.next = m2; - } - this.undo(m2); - }); - } - else { - const score = this.getCurrentScore(); - if (score != "1/2") { - if (score != "*") m.eval = (score == "1-0" ? 1 : -1) * maxeval; - else m.eval = this.evalPosition(); - } - } - this.undo(m); - }); - moves.sort((a, b) => { - return (color == "w" ? 1 : -1) * (b.eval - a.eval); - }); - let candidates = [0]; - for (let i = 1; i < moves.length && moves[i].eval == moves[0].eval; i++) - candidates.push(i); - const mIdx = candidates[randInt(candidates.length)]; - if (!moves[mIdx].next) return moves[mIdx]; - const move2 = moves[mIdx].next; - delete moves[mIdx]["next"]; - return [moves[mIdx], move2]; - } - - getNotation(move) { - if (move.vanish.length > 0) return super.getNotation(move); - // Teleportation: - const piece = - move.appear[0].p != V.PAWN ? move.appear[0].p.toUpperCase() : ""; - return piece + "@" + V.CoordsToSquare(move.end); - } - -};