+ const condensate = (mArr) => {
+ const illegal = (mArr.length == 1 && mArr[0].illegal) ||
+ (!mArr[0] && mArr[1].illegal);
+ if (mArr.length == 1)
+ return Object.assign({illegal: illegal}, mArr[0]);
+ if (!mArr[0])
+ return Object.assign({illegal: illegal}, mArr[1]);
+ // Pawn relocation
+ return {
+ start: mArr[0].start,
+ end: mArr[1].end,
+ vanish: mArr[0].vanish,
+ appear: mArr[1].appear,
+ segments: [
+ [[mArr[0].start.x, mArr[0].start.y], [mArr[0].end.x, mArr[0].end.y]],
+ [[mArr[1].start.x, mArr[1].start.y], [mArr[1].end.x, mArr[1].end.y]]
+ ]
+ };
+ };
+ const compatible = (m1, m2) => {
+ if (m2.illegal)
+ return false;
+ // Knight promotion?
+ if (m1.appear[0].p != m1.vanish[0].p)
+ return m2.vanish.length == 2 && m2.vanish[1].p == 'n';
+ if (
+ // Self-capture attempt?
+ (m1.vanish.length == 2 && m1.vanish[1].c == m1.vanish[0].c) ||
+ // Pawn captures something by anticipation?
+ (
+ m1.vanish[0].p == 'p' &&
+ m1.vanish.length == 1 &&
+ m1.start.y != m1.end.y
+ )
+ ) {
+ return m2.end.x == m1.end.x && m2.end.y == m1.end.y;
+ }
+ // Pawn push toward an enemy piece?
+ if (
+ m1.vanish[0].p == 'p' &&
+ m1.vanish.length == 2 &&
+ m1.start.y == m1.end.y
+ ) {
+ return m2.start.x == m1.end.x && m2.start.y == m1.end.y;
+ }
+ return true;
+ };
+ const adjust = (res) => {
+ if (!res.wm || !res.bm)
+ return;
+ for (let c of ['w', 'b']) {
+ const myMove = res[c + 'm'], oppMove = res[C.GetOppCol(c) + 'm'];
+ if (
+ myMove.end.x == oppMove.start.x &&
+ myMove.end.y == oppMove.start.y
+ ) {
+ // Whatever was supposed to vanish, finally doesn't vanish
+ myMove.vanish.pop();
+ }
+ }
+ if (res.wm.end.y == res.bm.end.y && res.wm.end.x == res.bm.end.x) {
+ // Collision (necessarily on empty square)
+ if (!res.wm.illegal && !res.bm.illegal) {
+ if (res.wm.vanish[0].p != res.bm.vanish[0].p) {
+ const c = (res.wm.vanish[0].p == 'n' ? 'w' : 'b');
+ res[c + 'm'].vanish.push(res[C.GetOppCol(c) + 'm'].appear.shift());
+ }
+ else {
+ // Collision of two pieces of same nature: both disappear
+ res.wm.appear.shift();
+ res.bm.appear.shift();
+ }
+ }
+ else {
+ const c = (!res.wm.illegal ? 'w' : 'b');
+ // Illegal move wins:
+ res[c + 'm'].appear.shift();
+ }
+ }
+ };
+ // Clone moves to avoid altering them:
+ let whiteMove = JSON.parse(JSON.stringify(this.whiteMove)),
+ blackMove = JSON.parse(JSON.stringify([this.firstMove, move]));
+ [whiteMove, blackMove] = [condensate(whiteMove), condensate(blackMove)];
+ let res = {
+ wm: (
+ (!whiteMove.illegal || compatible(whiteMove, blackMove))
+ ? whiteMove
+ : null
+ ),
+ bm: (
+ (!blackMove.illegal || compatible(blackMove, whiteMove))
+ ? blackMove
+ : null
+ )
+ };
+ adjust(res);
+ return res;