1 import ChessRules
from "/base_rules.js";
2 import PiPo
from "/utils/PiPo.js";
3 import Move
from "/utils/Move.js";
5 export default class ConvertRules
extends ChessRules
{
9 select: C
.Options
.select
,
10 styles: ["cylinder", "dark", "recycle", "teleport"]
18 setOtherVariables(fenParsed
) {
19 super.setOtherVariables(fenParsed
);
20 // Stack of "last move" only for intermediate chaining
21 this.lastMoveEnd
= [];
24 genRandInitBaseFen() {
25 const baseFen
= super.genRandInitBaseFen();
27 fen: baseFen
.fen
.replace("pppppppp/8", "8/pppppppp")
28 .replace("8/PPPPPPPP", "PPPPPPPP/8"),
33 getBasicMove([sx
, sy
], [ex
, ey
], tr
) {
34 const L
= this.lastMoveEnd
.length
;
35 const piece
= (L
>= 1 ? this.lastMoveEnd
[L
-1].p : null);
36 if (this.board
[ex
][ey
] == "") {
38 tr
= {c: this.turn
, p: piece
};
39 let mv
= super.getBasicMove([sx
, sy
], [ex
, ey
], tr
);
41 mv
.vanish
.pop(); //end of a chain: initial piece remains
44 // Capture: initial, or inside a chain
45 const initPiece
= (piece
|| this.getPiece(sx
, sy
)),
46 destPiece
= this.getPiece(ex
, ey
);
48 start: {x: sx
, y: sy
},
55 p: (!!tr
? tr
.p : initPiece
)
62 c: C
.GetOppTurn(this.turn
),
78 mv
.converted
= destPiece
; //easier (no need to detect it)
79 // mv.drag = {c: this.turn, p: initPiece}; //TODO: doesn't work
84 const L
= this.lastMoveEnd
.length
;
85 if (L
>= 1 && this.lastMoveEnd
[L
-1].x
== x
&& this.lastMoveEnd
[L
-1].y
== y
)
86 return this.lastMoveEnd
[L
-1].p
;
87 return super.getPiece(x
, y
);
90 getPotentialMovesFrom([x
, y
], color
) {
91 const L
= this.lastMoveEnd
.length
;
94 (x
!= this.lastMoveEnd
[L
-1].x
|| y
!= this.lastMoveEnd
[L
-1].y
)
96 // A capture was played: wrong square
99 return super.getPotentialMovesFrom([x
, y
], color
);
102 underAttack_aux([x
, y
], color
, explored
) {
103 if (explored
.some(sq
=> sq
[0] == x
&& sq
[1] == y
))
104 // Start of an infinite loop: exit
106 explored
.push([x
, y
]);
107 if (super.underAttack([x
, y
], [color
]))
109 // Maybe indirect "chaining" attack:
110 const myColor
= this.turn
;
112 let toCheck
= []; //check all but king (no need)
114 const shiftToPawn
= (myColor
== 'w' ? -1 : 1);
115 for (let yShift
of [-1, 1]) {
116 const [i
, j
] = [x
+ shiftToPawn
, y
+ yShift
];
118 this.onBoard(i
, j
) &&
119 this.board
[i
][j
] != "" &&
120 // NOTE: no need to check color (no enemy pawn can take directly)
121 this.getPiece(i
, j
) == 'p'
123 toCheck
.push([i
, j
]);
127 this.pieces()['n'].both
[0].steps
.forEach(s
=> {
128 const [i
, j
] = [x
+ s
[0], y
+ s
[1]];
130 this.onBoard(i
, j
) &&
131 this.board
[i
][j
] != "" &&
132 this.getPiece(i
, j
) == 'n'
134 toCheck
.push([i
, j
]);
138 this.pieces()['q'].both
[0].steps
.forEach(s
=> {
139 let [i
, j
] = [x
+ s
[0], y
+ s
[1]];
140 while (this.onBoard(i
, j
) && this.board
[i
][j
] == "") {
144 if (!this.onBoard(i
, j
))
146 const piece
= this.getPiece(i
, j
);
149 (piece
== 'r' && (s
[0] == 0 || s
[1] == 0)) ||
150 (piece
== 'b' && (s
[0] != 0 && s
[1] != 0))
152 toCheck
.push([i
, j
]);
155 for (let ij
of toCheck
) {
156 if (this.underAttack_aux(ij
, color
, explored
))
162 underAttack([x
, y
], [color
]) {
164 return this.underAttack_aux([x
, y
], color
, explored
);
168 // No "checks" (except to forbid castle)
173 return !move.converted
;
177 super.postPlay(move);
178 if (!!move.converted
) {
179 this.lastMoveEnd
.push({
186 this.lastMoveEnd
= [];