| 1 | import { ChessRules } from "@/base_rules"; |
| 2 | |
| 3 | export class ChakartRules extends ChessRules { |
| 4 | // NOTE: getBasicMove, ajouter les bonus à vanish array |
| 5 | // + déterminer leur effet (si cavalier) ou case (si banane ou bombe) |
| 6 | // (L'effet doit être caché au joueur : devrait être OK) |
| 7 | // |
| 8 | // Saut possible par dessus bonus ou champis mais pas bananes ou bombes |
| 9 | //==> redefinir isAttackedBySlide et getPotentialSlide... |
| 10 | |
| 11 | // keep track of captured pieces: comme Grand; pieces can get back to board with toadette bonus. |
| 12 | // --> pour ce bonus, passer "capture" temporairement en "reserve" pour permettre de jouer le coup. |
| 13 | |
| 14 | // FEN : castle flags + flags peach (power used?) + Mario (invisibility used? --> move notation Q??) |
| 15 | // "pièces" supplémentaires : bananes, bombes, champis, bonus --> + couleur ? |
| 16 | // (Semble mieux sans couleur => couleur spéciale indiquant que c'est pas jouable) |
| 17 | // (Attention: pas jouables cf. getPotentialMoves...) |
| 18 | |
| 19 | hoverHighlight(x, y) { |
| 20 | // TODO: exact squares |
| 21 | return this.subTurn == 2; //&& this.firstMove.donkey or wario or bonus roi boo |
| 22 | } |
| 23 | |
| 24 | // king can be l or L (immobilized) --> copy-paste from Alice variant |
| 25 | static IsGoodPosition(position) { |
| 26 | if (position.length == 0) return false; |
| 27 | const rows = position.split("/"); |
| 28 | if (rows.length != V.size.x) return false; |
| 29 | let kings = { "k": 0, "K": 0 }; |
| 30 | for (let row of rows) { |
| 31 | let sumElts = 0; |
| 32 | for (let i = 0; i < row.length; i++) { |
| 33 | if (['K','k'].includes(row[i])) kings[row[i]]++; |
| 34 | if (V.PIECES.includes(row[i].toLowerCase())) sumElts++; |
| 35 | else { |
| 36 | const num = parseInt(row[i]); |
| 37 | if (isNaN(num)) return false; |
| 38 | sumElts += num; |
| 39 | } |
| 40 | } |
| 41 | if (sumElts != V.size.y) return false; |
| 42 | } |
| 43 | if (Object.values(kings).some(v => v != 1)) return false; |
| 44 | return true; |
| 45 | } |
| 46 | |
| 47 | setOtherVariables(fen) { |
| 48 | super.setOtherVariables(fen); |
| 49 | this.subTurn = 1; |
| 50 | } |
| 51 | |
| 52 | getPotentialMovesFrom([x, y]) { |
| 53 | // TODO: bananes et bombes limitent les déplacements (agissent comme un mur "capturable") |
| 54 | // bananes jaunes et rouges ?! (agissant sur une seule couleur ?) --> mauvaise idée. |
| 55 | if (this.subTurn == 2) { |
| 56 | // TODO: coup compatible avec firstMove |
| 57 | } |
| 58 | //Détails : |
| 59 | //Si une pièce pose quelque chose sur une case ça remplace ce qui y était déjà. |
| 60 | } |
| 61 | |
| 62 | getPotentialPawnMoves(sq) { |
| 63 | //Toad: pion |
| 64 | // laisse sur sa case de départ un champi turbo permettant à Peach et cavalier et autres pions d'aller |
| 65 | // un dep plus loin (evt 2 cases si pion saut initial), et aux pièces arrivant sur cette case de sauter par |
| 66 | // dessus une pièce immédiatement adjacente dans leur trajectoire (en atterissant juste derrière). |
| 67 | } |
| 68 | |
| 69 | // Coups en 2 temps (si pose possible) |
| 70 | getPotentialRookMoves(sq) { |
| 71 | //Donkey : tour |
| 72 | // pose une banane (optionnel) sur une case adjacente (diagonale) à celle d'arrivée |
| 73 | // Si une pièce arrive sur la peau de banane, alors elle effectue un déplacement |
| 74 | // aléatoire d'une (2?) case (vertical ou horizontal) depuis sa position finale. |
| 75 | } |
| 76 | |
| 77 | // Coups en 2 temps (si pose) |
| 78 | getPotentialBishopMoves([x, y]) { |
| 79 | //Wario: fou |
| 80 | // pose une bombe (optionnel) sur une case orthogonalement adjacente à la case d'arrivée |
| 81 | // Si une pièce arrive sur une bombe, alors elle effectue un déplacement diagonal |
| 82 | // aléatoire d'une (2?) case depuis sa position finale (juste une case si impossible). |
| 83 | } |
| 84 | |
| 85 | getPotentialKnightMoves([x, y]) { |
| 86 | //Yoshi: cavalier |
| 87 | // laisse sur sa case de départ un bonus aléatoire |
| 88 | // (NOTE: certains bonus pourraient ne pas être applicables ==> pion bloqué par exemple) |
| 89 | // - i) roi boo(*E*) : échange avec n'importe quelle pièce (choix du joueur, type et/ou couleur différents) |
| 90 | // - i*) koopa(*B*) : ramène sur la case initiale |
| 91 | // - ii) toadette(*R*) : permet de poser une pièce capturée sur le plateau |
| 92 | // (n'importe où sauf 8eme rangée pour les pions) |
| 93 | // - ii*) chomp(*W*) : mange la pièce ; si c'est Peach, c'est perdu |
| 94 | // - iii) daisy(*T*) : permet de rejouer un coup avec la même pièce --> cumulable si ensuite coup sur bonus Daisy. |
| 95 | // - iii*) bowser(*M*) : immobilise la pièce (marquée jaune/rouge), qui ne pourra pas jouer au tour suivant |
| 96 | // - iv) luigi(*L*) : fait changer de camp une pièce adverse (aléatoire) (sauf le roi) |
| 97 | // - iv*) waluigi(*D*) : fait changer de camp une de nos pièces (aléatoire, sauf le roi) |
| 98 | // --> i, ii, iii en deux temps (subTurn 1 & 2) |
| 99 | } |
| 100 | |
| 101 | getPotentialQueenMoves(sq) { |
| 102 | //Mario: dame |
| 103 | // pouvoir "fantôme" : peut effectuer une fois dans la partie un coup non-capturant invisible (=> choix à chaque coup, getPPpath(m) teste m.nvisible...) |
| 104 | //wg bg ghost once in the game the queen can make an invisible move --> printed as "?" |
| 105 | } |
| 106 | |
| 107 | getPotentialKingMoves(sq) { |
| 108 | //Peach: roi |
| 109 | // Carapace rouge (disons ^^) jouable une seule fois dans la partie, |
| 110 | // au lieu de se déplacer. Capture un ennemi au choix parmi les plus proches, |
| 111 | // à condition qu'ils soient visibles (suivant les directions de déplacement d'une dame). |
| 112 | // Profite des accélérateurs posés par les pions (+ 1 case : obligatoire). |
| 113 | } |
| 114 | |
| 115 | atLeastOneMove() { |
| 116 | // TODO: check that |
| 117 | return true; |
| 118 | } |
| 119 | |
| 120 | play(move) { |
| 121 | // TODO: subTurn passe à 2 si arrivée sur bonus cavalier |
| 122 | // potentiellement pose (tour, fou) ou si choix (reconnaître i (ok), ii (ok) et iii (si coup normal + pas immobilisé) ?) |
| 123 | // voire +2 si plusieurs daisy... |
| 124 | // si pièce immobilisée de ma couleur : elle redevient utilisable (changer status fin de play) |
| 125 | } |
| 126 | |
| 127 | undo(move) { |
| 128 | // TODO: reconnaissance inverse si subTurn == 1 --> juste impossible ==> marquer pendant play (comme DoubleMove1 : move.turn = ...) |
| 129 | } |
| 130 | |
| 131 | doClick(square) { |
| 132 | // A click to promote a piece on subTurn 2 would trigger this. |
| 133 | // For now it would then return [NaN, NaN] because surrounding squares |
| 134 | // have no IDs in the promotion modal. TODO: improve this? |
| 135 | if (isNaN(square[0])) return null; |
| 136 | // If subTurn == 2: |
| 137 | // if square is empty && firstMove is compatible, |
| 138 | // complete the move (banana or bomb). |
| 139 | // if square not empty, just complete with empty move |
| 140 | const Lf = this.firstMove.length; |
| 141 | if (this.subTurn == 2) { |
| 142 | if ( |
| 143 | this.board[square[0]][square[1]] == V.EMPTY && |
| 144 | !this.underCheck(this.turn) && |
| 145 | (La == 0 || !this.oppositeMoves(this.amoves[La-1], this.firstMove[Lf-1])) |
| 146 | ) { |
| 147 | return { |
| 148 | start: { x: -1, y: -1 }, |
| 149 | end: { x: -1, y: -1 }, |
| 150 | appear: [], |
| 151 | vanish: [] |
| 152 | }; |
| 153 | } |
| 154 | } |
| 155 | return null; |
| 156 | } |
| 157 | |
| 158 | postPlay(move) { |
| 159 | // TODO: king may also be "chomped" |
| 160 | super.updateCastleFlags(move, piece); |
| 161 | } |
| 162 | |
| 163 | getCurrentScore() { |
| 164 | if (this.kingPos[this.turn][0] < 0) |
| 165 | // King captured (or "chomped") |
| 166 | return this.turn == "w" ? "0-1" : "1-0"; |
| 167 | //TODO: But = capturer la princesse adverse (téléportation possible donc pas but = arriver de l'autre côté) |
| 168 | return '*'; |
| 169 | } |
| 170 | |
| 171 | getComputerMove() { |
| 172 | // TODO: random mover |
| 173 | } |
| 174 | }; |