+ return piece + "@" + finalSquare;
+ }
+ else if (move.appear.length == 0) {
+ const piece = this.getPiece(move.start.x, move.start.y);
+ if (piece == V.KING && !move.end.effect)
+ // King remote capture
+ return "Kx" + finalSquare;
+ // Koopa or Chomp, or loopback after bananas, bombs & mushrooms:
+ return (
+ piece.toUpperCase() + "x" + finalSquare +
+ (
+ !!move.end.effect
+ ? "*" + (move.end.effect == "koopa" ? "K" : "C")
+ : ""
+ )
+ );
+ }
+ if (move.appear.length == 1 && move.vanish.length == 1) {
+ const moveStart = move.appear[0].p.toUpperCase() + "@";
+ if (move.appear[0].c == 'a' && move.vanish[0].c == 'a')
+ // Bonus replacement:
+ return moveStart + finalSquare;
+ if (
+ move.vanish[0].p == V.INVISIBLE_QUEEN &&
+ move.appear[0].x == move.vanish[0].x &&
+ move.appear[0].y == move.vanish[0].y
+ ) {
+ // Toadette takes invisible queen
+ return moveStart + "Q" + finalSquare;
+ }
+ }
+ if (
+ move.appear.length == 2 &&
+ move.vanish.length == 2 &&
+ move.appear.every(a => a.c != 'a') &&
+ move.vanish.every(v => v.c != 'a')
+ ) {
+ // King Boo exchange
+ return V.CoordsToSquare(move.start) + finalSquare;
+ }
+ const piece = move.vanish[0].p;
+ let notation = undefined;
+ if (piece == V.PAWN) {
+ // Pawn move
+ if (this.board[move.end.x][move.end.y] != V.EMPTY) {
+ // Capture
+ const startColumn = V.CoordToColumn(move.start.y);
+ notation = startColumn + "x" + finalSquare;
+ }
+ else notation = finalSquare;
+ if (move.appear[0].p != V.PAWN)
+ // Promotion
+ notation += "=" + move.appear[0].p.toUpperCase();
+ }
+ else {
+ notation =
+ piece.toUpperCase() +
+ (this.board[move.end.x][move.end.y] != V.EMPTY ? "x" : "") +
+ finalSquare;