};
}
- static get INVISIBLE_QUEEN() {
- return 'i';
- }
-
// Fictive color 'a', bomb banana mushroom egg
static get BOMB() {
return 'w'; //"Wario"
pieces(color, x, y) {
const specials = {
'i': {"class": "invisible"}, //queen
+ '?': {"class": "mystery"}, //...initial square
'e': {"class": "egg"},
'm': {"class": "mushroom"},
'd': {"class": "banana"},
't': {"class": ["immobilized", "queen"]},
'l': {"class": ["immobilized", "king"]}
};
- return Object.assign({}, specials, bowsered, super.pieces(color, x, y));
+ return Object.assign(
+ {
+ 'y': {
+ // Virtual piece for "king remote shell captures"
+ moves: [],
+ attack: [
+ {
+ steps: [
+ [0, 1], [0, -1], [1, 0], [-1, 0],
+ [1, 1], [1, -1], [-1, 1], [-1, -1]
+ ]
+ }
+ ]
+ }
+ },
+ specials, bowsered, super.pieces(color, x, y));
}
genRandInitFen(seed) {
- const gr = new GiveawayRules(
- {mode: "suicide", options: {}, genFenOnly: true});
+ const options = Object.assign({mode: "suicide"}, this.options);
+ const gr = new GiveawayRules({options: options, genFenOnly: true});
// Add Peach + mario flags
return gr.genRandInitFen(seed).slice(0, -17) + '{"flags":"1111"}';
}
this.moveStack = [];
// Change seed (after FEN generation!!)
// so that further calls differ between players:
- Random.setSeed(Math.floor(10000 * Math.random()));
+ Random.setSeed(Math.floor(19840 * Math.random()));
}
// For Toadette bonus
for (let j = 0; j < this.size.y; j++) {
const pieceIJ = this.getPiece(i, j);
const colIJ = this.getColor(i, j);
- if (
- this.board[i][j] == "" ||
- colIJ == 'a' ||
- pieceIJ == V.INVISIBLE_QUEEN
- ) {
+ if (this.board[i][j] == "" || colIJ == 'a' || pieceIJ == 'i') {
let m = new Move({
start: {x: c, y: p},
appear: [new PiPo({x: i, y: j, c: c, p: p})],
case 'b':
case 'r':
// Explicitely listing types to avoid moving immobilized piece
- moves = super.getPotentialMovesOf(piece, [x, y]);
+ moves = this.getPotentialMovesOf(piece, [x, y]);
break;
}
}
canStepOver(i, j) {
return (
this.board[i][j] == "" ||
- [V.MUSHROOM, V.EGG].includes(this.getPiece(i, j)));
+ ['i', V.EGG, V.MUSHROOM].includes(this.getPiece(i, j))
+ );
}
getPawnMovesFrom([x, y]) {
const shiftX = (color == 'w' ? -1 : 1);
const firstRank = (color == "w" ? this.size.x - 1 : 0);
let moves = [];
+ const frontPiece = this.getPiece(x + shiftX, y);
if (
this.board[x + shiftX][y] == "" ||
this.getColor(x + shiftX, y) == 'a' ||
- this.getPiece(x + shiftX, y) == V.INVISIBLE_QUEEN
+ frontPiece == 'i'
) {
moves.push(this.getBasicMove([x, y], [x + shiftX, y]));
if (
[firstRank, firstRank + shiftX].includes(x) &&
+ ![V.BANANA, V.BOMB].includes(frontPiece) &&
(
this.board[x + 2 * shiftX][y] == "" ||
this.getColor(x + 2 * shiftX, y) == 'a' ||
- this.getPiece(x + 2 * shiftX, y) == V.INVISIBLE_QUEEN
+ this.getPiece(x + 2 * shiftX, y) == 'i'
)
) {
moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
}
}
for (let shiftY of [-1, 1]) {
+ const nextY = this.getY(y + shiftY);
if (
- y + shiftY >= 0 &&
- y + shiftY < this.size.y &&
- this.board[x + shiftX][y + shiftY] != "" &&
+ nextY >= 0 &&
+ nextY < this.size.y &&
+ this.board[x + shiftX][nextY] != "" &&
// Pawns cannot capture invisible queen this way!
- this.getPiece(x + shiftX, y + shiftY) != V.INVISIBLE_QUEEN &&
- ['a', oppCol].includes(this.getColor(x + shiftX, y + shiftY))
+ this.getPiece(x + shiftX, nextY) != 'i' &&
+ ['a', oppCol].includes(this.getColor(x + shiftX, nextY))
) {
- moves.push(this.getBasicMove([x, y], [x + shiftX, y + shiftY]));
+ moves.push(this.getBasicMove([x, y], [x + shiftX, nextY]));
}
}
this.pawnPostProcess(moves, color, oppCol);
- // Add mushroom on before-last square
+ // Add mushroom on before-last square (+ potential segments)
moves.forEach(m => {
- let revStep = [m.start.x - m.end.x, m.start.y - m.end.y];
- for (let i of [0, 1])
- revStep[i] = revStep[i] / Math.abs(revStep[i]) || 0;
- const [blx, bly] = [m.end.x + revStep[0], m.end.y + revStep[1]];
- m.appear.push(new PiPo({x: blx, y: bly, c: 'a', p: 'm'}));
- if (blx != x && this.board[blx][bly] != "") {
+ let [mx, my] = [x, y];
+ if (Math.abs(m.end.x - m.start.x) == 2)
+ mx = (m.start.x + m.end.x) / 2;
+ m.appear.push(new PiPo({x: mx, y: my, c: 'a', p: 'm'}));
+ if (mx != x && this.board[mx][my] != "") {
m.vanish.push(new PiPo({
- x: blx,
- y: bly,
- c: this.getColor(blx, bly),
- p: this.getPiece(blx, bly)
+ x: mx,
+ y: my,
+ c: this.getColor(mx, my),
+ p: this.getPiece(mx, my)
}));
}
+ if (Math.abs(m.end.y - m.start.y) > 1) {
+ m.segments = [
+ [[x, y], [x, y]],
+ [[m.end.x, m.end.y], [m.end.x, m.end.y]]
+ ];
+ }
});
return moves;
}
m.vanish[0].c != 'a'
) {
let im = JSON.parse(JSON.stringify(m));
- im.appear[0].p = V.INVISIBLE_QUEEN;
+ im.appear[0].p = 'i';
im.noAnimate = true;
invisibleMoves.push(im);
}
let moves = this.getPotentialMovesOf('k', [x, y]);
// If flag allows it, add 'remote shell captures'
if (this.powerFlags[this.turn]['k']) {
- super.pieces()['k'].moves[0].steps.forEach(step => {
- let [i, j] = [x + step[0], y + step[1]];
- while (
- this.onBoard(i, j) &&
- (
- this.board[i][j] == "" ||
- this.getPiece(i, j) == V.INVISIBLE_QUEEN ||
- (
- this.getColor(i, j) == 'a' &&
- [V.EGG, V.MUSHROOM].includes(this.getPiece(i, j))
- )
- )
- ) {
- i += step[0];
- j += step[1];
- }
- if (this.onBoard(i, j)) {
- const colIJ = this.getColor(i, j);
- if (colIJ != this.turn) {
- // May just destroy a bomb or banana:
- let shellCapture = new Move({
- start: {x: x, y: y},
- end: {x: i, y: j},
- appear: [],
- vanish: [
- new PiPo({x: i, y: j, c: colIJ, p: this.getPiece(i, j)})
- ]
- });
- shellCapture.shell = true; //easier play()
- shellCapture.choice = 'z'; //to display in showChoices()
- moves.push(shellCapture);
- }
- }
+ let shellCaptures = this.getPotentialMovesOf('y', [x, y]);
+ shellCaptures.forEach(sc => {
+ sc.shell = true; //easier play()
+ sc.choice = 'z'; //to display in showChoices()
+ // Fix move (Rifle style):
+ sc.vanish.shift();
+ sc.appear.shift();
});
+ Array.prototype.push.apply(moves, shellCaptures);
}
return moves;
}
play(move) {
+ const color = this.turn;
+ const oppCol = C.GetOppCol(color);
+ if (
+ move.appear.length > 0 &&
+ move.appear[0].p == 'p' &&
+ (
+ (color == 'w' && move.end.x == 0) ||
+ (color == 'b' && move.end.x == this.size.x - 1)
+ )
+ ) {
+ // "Forgotten" promotion, which occurred after some effect
+ let moves = [move];
+ super.pawnPostProcess(moves, color, oppCol);
+ super.showChoices(moves);
+ return false;
+ }
if (!move.nextComputed) {
// Set potential random effects, so that play() is deterministic
// from opponent viewpoint:
move.nextComputed = true;
}
this.egg = move.egg;
- const color = this.turn;
- const oppCol = C.GetOppCol(color);
if (move.egg == "toadette") {
this.reserve = { w: {}, b: {} };
// Randomly select a piece in pawnPromotions
}
if (move.shell)
this.powerFlags[color]['k'] = false;
- else if (move.appear.length > 0 && move.appear[0].p == V.INVISIBLE_QUEEN) {
+ else if (move.appear.length > 0 && move.appear[0].p == 'i') {
this.powerFlags[move.appear[0].c]['q'] = false;
- if (color != this.playerColor)
- alert("Invisible queen!");
+ if (color == this.playerColor) {
+ move.appear.push(
+ new PiPo({x: move.start.x, y: move.start.y, c: color, p: '?'}));
+ }
}
if (color == this.playerColor) {
// Look for an immobilized piece of my color: it can now move
for (let j=0; j<8; j++) {
if (
this.board[i][j] != "" &&
- this.getColor(i, j) == oppCol &&
- this.getPiece(i, j) == V.INVISIBLE_QUEEN
+ this.getColor(i, j) == oppCol
) {
- move.vanish.push(new PiPo({
- x: i, y: j, c: oppCol, p: V.INVISIBLE_QUEEN
- }));
- move.appear.push(new PiPo({
- x: i, y: j, c: oppCol, p: 'q'
- }));
+ const pieceIJ = this.getPiece(i, j);
+ if (pieceIJ == 'i') {
+ move.vanish.push(new PiPo({x: i, y: j, c: oppCol, p: 'i'}));
+ move.appear.push(new PiPo({x: i, y: j, c: oppCol, p: 'q'}));
+ }
+ else if (pieceIJ == '?')
+ move.vanish.push(new PiPo({x: i, y: j, c: oppCol, p: '?'}));
}
}
}
this.movesCount++;
}
if (move.egg)
- this.displayBonus(move.egg);
+ this.displayBonus(move);
this.playOnBoard(move);
this.nextMove = move.next;
+ return true;
}
// Helper to set and apply banana/bomb effect
}
getMushroomEffect(move) {
+ if (typeof move.start.x == "string") //drop move (toadette)
+ return null;
let step = [move.end.x - move.start.x, move.end.y - move.start.y];
if ([0, 1].some(i => Math.abs(step[i]) >= 2 && Math.abs(step[1-i]) != 1)) {
// Slider, multi-squares: normalize step
const afterSquare =
[nextSquare[0] + step[0], nextSquare[1] + step[1]];
let nextMove = null;
- this.playOnBoard(move); //HACK for getBasicMove() below
- if (
- this.onBoard(nextSquare[0], nextSquare[1]) &&
- ['k', 'p', 'n'].includes(move.vanish[0].p) &&
- !['w', 'b'].includes(this.getColor(nextSquare[0], nextSquare[1]))
- ) {
- // Speed up non-sliders
+ if (this.onBoard(nextSquare[0], nextSquare[1])) {
+ this.playOnBoard(move); //HACK for getBasicMove()
nextMove = this.getBasicMove([move.end.x, move.end.y], nextSquare);
+ this.undoOnBoard(move);
}
- else if (
- this.onBoard(afterSquare[0], afterSquare[1]) &&
- this.board[nextSquare[0]][nextSquare[1]] != "" &&
- this.getColor(nextSquare[0], nextSquare[1]) != 'a' &&
- this.getColor(afterSquare[0], afterSquare[1]) != this.turn
- ) {
- nextMove = this.getBasicMove([move.end.x, move.end.y], afterSquare);
- }
- this.undoOnBoard(move);
return nextMove;
}
return res;
}
- displayBonus(egg) {
- alert(egg); //TODO: nicer display
+ 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() {
}
playPlusVisual(move, r) {
- this.moveStack.push(move);
const nextLines = () => {
- this.play(move);
+ if (!this.play(move))
+ return;
+ this.moveStack.push(move);
this.playVisual(move, r);
if (this.nextMove)
this.playPlusVisual(this.nextMove, r);
this.moveStack = [];
}
};
- if (this.moveStack.length == 1)
+ if (this.moveStack.length == 0)
nextLines();
else
this.animate(move, nextLines);