return this.getColor(x1, y1) !== this.getColor(x2, y2);
}
- // TODO: currently unused, but makes sense?
+ // Teleport & Recycle. Assumption: color(x1,y1) == color(x2,y2)
canSelfTake([x1, y1], [x2, y2]) {
- return true;
+ return !this.isKing(x2, y2);
}
canStepOver(i, j, p) {
}
// All possible moves from selected square
+ // TODO: generalize usage if arg "color" (e.g. Checkered)
getPotentialMovesFrom([x, y], color) {
if (this.subTurnTeleport == 2)
return [];
segments: this.options["cylinder"],
stepSpec: stepSpec
},
- ([i1, j1], [i2, j2]) =>
- this.getColor(i2, j2) == color && !this.isKing(i2, j2)
+ ([i1, j1], [i2, j2]) => {
+ return (
+ this.getColor(i2, j2) == color &&
+ this.canSelfTake([i1, j1], [i2, j2])
+ );
+ }
);
Array.prototype.push.apply(squares, selfCaptures);
}
return res;
}
+ // cb: callback returning a boolean (false if king missing)
+ trackKingWrap(move, kingPos, cb) {
+ let newKingPP = null,
+ sqIdx = 0,
+ res = true; //a priori valid
+ const oldKingPP =
+ move.vanish.find(v => this.isKing(0, 0, v.p) && v.c == color);
+ if (oldKingPP) {
+ // Search king in appear array:
+ newKingPP =
+ move.appear.find(a => this.isKing(0, 0, a.p) && a.c == color);
+ if (newKingPP) {
+ sqIdx = kingPos.findIndex(kp =>
+ kp[0] == oldKingPP.x && kp[1] == oldKingPP.y);
+ kingPos[sqIdx] = [newKingPP.x, newKingPP.y];
+ }
+ else
+ res = false; //king vanished
+ }
+ res &&= cb(kingPos);
+ if (oldKingPP && newKingPP)
+ kingPos[sqIdx] = [oldKingPP.x, oldKingPP.y];
+ return res;
+ }
+
// 'color' arg because some variants (e.g. Refusal) check opponent moves
filterValid(moves, color) {
if (!color)
let kingPos = this.searchKingPos(color);
return moves.filter(m => {
this.playOnBoard(m);
- let newKingPP = null,
- sqIdx = 0,
- res = true; //a priori valid
- const oldKingPP =
- m.vanish.find(v => this.isKing(0, 0, v.p) && v.c == color);
- if (oldKingPP) {
- // Search king in appear array:
- newKingPP =
- m.appear.find(a => this.isKing(0, 0, a.p) && a.c == color);
- if (newKingPP) {
- sqIdx = kingPos.findIndex(kp =>
- kp[0] == oldKingPP.x && kp[1] == oldKingPP.y);
- kingPos[sqIdx] = [newKingPP.x, newKingPP.y];
- }
- else
- res = false; //king vanished
- }
- res &&= !this.underCheck(kingPos, oppCols);
- if (oldKingPP && newKingPP)
- kingPos[sqIdx] = [oldKingPP.x, oldKingPP.y];
+ const res = this.trackKingWrap(m, kingPos, (kp) => {
+ return !this.underCheck(kp, oppCols);
+ });
this.undoOnBoard(m);
return res;
});
if (this.board[i][j] != "" && this.getColor(i, j) == color) {
// NOTE: in fact searching for all potential moves from i,j.
// I don't believe this is an issue, for now at least.
- const moves = this.getPotentialMovesFrom([i, j]);
+ const moves = this.getPotentialMovesFrom([i, j], color);
if (moves.some(m => this.filterValid([m]).length >= 1))
return true;
}
}
},
"node_modules/anymatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
- "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
},
"dependencies": {
"anymatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
- "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
{name: 'Capture', desc: 'Mandatory captures'},
{name: 'Chakart', desc: 'Capture the princess'},
{name: 'Checkered', desc: 'Shared pieces'},
-// {name: 'Checkless', desc: 'No-check mode'},
+ {name: 'Checkless', desc: 'No-check mode'},
{name: 'Chess960', disp: "Chess 960", desc: "Standard rules"},
// {name: 'Circular', desc: 'Run forward'},
// {name: 'Clorange', desc: 'A Clockwork Orange', disp: 'Clockwork Orange'},
--- /dev/null
+import ChessRules from "/base_rules.js";
+
+export default class ChecklessRules extends ChessRules {
+
+ // Cannot use super.atLeastOneMove: lead to infinite recursion
+ atLeastOneMove_aux(kingPos, oppKingPos, color, oppCol) {
+ for (let i = 0; i < this.size.x; i++) {
+ for (let j = 0; j < this.size.y; j++) {
+ if (this.getColor(i, j) == color) {
+ const moves = this.getPotentialMovesFrom([i, j]);
+ for (let m of moves) {
+ this.playOnBoard(m);
+ const res = this.trackKingWrap(m, kingPos, (kp) => {
+ return !this.underCheck(kp, [oppCol]);
+ });
+ this.undoOnBoard(m);
+ if (res)
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ filterValid(moves) {
+ fmoves = super.filterValid(moves);
+ // Filter out moves giving check but not checkmate
+ const color = this.turn;
+ const oppCol = C.GetOppTurn(color);
+ let kingPos = this.searchKingPos(color),
+ oppKingPos = this.searchKingPos(oppCol);
+ return fmoves.filter(m => {
+ this.playOnBoard(m);
+ const res = this.trackKingWrap(m, oppKingPos, (oppKp) => {
+ return (
+ !this.underCheck(oppKp, [color]) ||
+ this.atLeastOneMove_aux(oppKp, kingPos, oppCol, color)
+ );
+ });
+ this.undoOnBoard(m);
+ return res;
+ });
+ }
+
+};