+
+ getEggEffect(move) {
+ const getRandomPiece = (c) => {
+ let bagOfPieces = [];
+ for (let i=0; i<this.size.x; i++) {
+ for (let j=0; j<this.size.y; j++) {
+ const pieceIJ = this.getPiece(i, j);
+ if (
+ this.getColor(i, j) == c && pieceIJ != 'k' &&
+ (
+ // The color will change, so pawns on first rank are ineligible
+ pieceIJ != 'p' ||
+ (c == 'w' && i < this.size.x - 1) || (c == 'b' && i > 0)
+ )
+ ) {
+ bagOfPieces.push([i, j]);
+ }
+ }
+ }
+ if (bagOfPieces.length >= 1)
+ return Random.sample(bagOfPieces);
+ return null;
+ };
+ const color = this.turn;
+ let em = null;
+ switch (move.egg) {
+ case "luigi":
+ case "waluigi":
+ // Change color of friendly or enemy piece, king excepted
+ const oldColor = (move.egg == "waluigi" ? color : C.GetOppCol(color));
+ const newColor = C.GetOppCol(oldColor);
+ const coords = getRandomPiece(oldColor);
+ if (coords) {
+ const piece = this.getPiece(coords[0], coords[1]);
+ em = new Move({
+ appear: [
+ new PiPo({x: coords[0], y: coords[1], c: newColor, p: piece})
+ ],
+ vanish: [
+ new PiPo({x: coords[0], y: coords[1], c: oldColor, p: piece})
+ ]
+ });
+ em.luigiEffect = true; //avoid dropping bomb/banana by mistake
+ }
+ break;
+ case "bowser":
+ em = new Move({
+ appear: [
+ new PiPo({
+ x: move.end.x,
+ y: move.end.y,
+ c: color,
+ p: V.IMMOBILIZE_CODE[move.appear[0].p]
+ })
+ ],
+ vanish: [
+ new PiPo({
+ x: move.end.x,
+ y: move.end.y,
+ c: color,
+ p: move.appear[0].p
+ })
+ ]
+ });
+ break;
+ case "koopa":
+ // Reverse move
+ em = new Move({
+ appear: [
+ new PiPo({
+ x: move.start.x, y: move.start.y, c: color, p: move.appear[0].p
+ })
+ ],
+ vanish: [
+ new PiPo({
+ x: move.end.x, y: move.end.y, c: color, p: move.appear[0].p
+ })
+ ]
+ });
+ if (this.board[move.start.x][move.start.y] != "") {
+ // Pawn or knight let something on init square
+ em.vanish.push(new PiPo({
+ x: move.start.x,
+ y: move.start.y,
+ c: 'a',
+ p: this.getPiece(move.start.x, move.start.y)
+ }));
+ }
+ break;
+ case "chomp":
+ // Eat piece
+ em = new Move({
+ appear: [],
+ vanish: [
+ new PiPo({
+ x: move.end.x, y: move.end.y, c: color, p: move.appear[0].p
+ })
+ ],
+ end: {x: move.end.x, y: move.end.y}
+ });
+ break;
+ }
+ if (em && move.egg != "koopa")
+ em.noAnimate = true; //static move
+ return em;
+ }
+
+ getMushroomEffect(move) {
+ if (
+ typeof move.start.x == "string" || //drop move (toadette)
+ ['b', 'r', 'q'].includes(move.vanish[0].p) //slider
+ ) {
+ return null;
+ }
+ let step = [move.end.x - move.start.x, move.end.y - move.start.y];
+ if (Math.abs(step[0]) == 2 && Math.abs(step[1]) == 0)
+ // Pawn initial 2-squares move: normalize step
+ step[0] /= 2;
+ const nextSquare = [move.end.x + step[0], move.end.y + step[1]];
+ let nextMove = null;
+ if (
+ this.onBoard(nextSquare[0], nextSquare[1]) &&
+ (
+ this.board[nextSquare[0]][nextSquare[1]] == "" ||
+ this.getColor(nextSquare[0], nextSquare[1]) == 'a'
+ )
+ ) {
+ this.playOnBoard(move); //HACK for getBasicMove()
+ nextMove = this.getBasicMove([move.end.x, move.end.y], nextSquare);
+ this.undoOnBoard(move);
+ }
+ return nextMove;
+ }
+
+ getBombBananaEffect(move, item) {
+ const steps = item == V.BANANA
+ ? [[1, 0], [-1, 0], [0, 1], [0, -1]]
+ : [[1, 1], [1, -1], [-1, 1], [-1, -1]];
+ const nextSquare = this.getRandomSquare([move.end.x, move.end.y], steps);
+ this.playOnBoard(move); //HACK for getBasicMove()
+ const res = this.getBasicMove([move.end.x, move.end.y], nextSquare);
+ this.undoOnBoard(move);
+ return res;
+ }
+
+ displayBonus(move) {
+ let divBonus = document.createElement("div");
+ divBonus.classList.add("bonus-text");
+ divBonus.innerHTML = move.egg;
+ let container = document.getElementById(this.containerId);
+ container.appendChild(divBonus);
+ setTimeout(() => container.removeChild(divBonus), 2000);
+ }
+
+ atLeastOneMove() {
+ return true;
+ }
+
+ filterValid(moves) {
+ return moves;
+ }
+
+ // Kingboo bonus can be animated better:
+ customAnimate(move, segments, cb) {
+ if (!move.kingboo)
+ return 0;
+ super.animateMoving(move.end, move.start, null,
+ segments.reverse().map(s => s.reverse()), cb);
+ return 1;