1a006e22553cebc67e8f948ef308789e58e0a7ea
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
{
10 select: C
.Options
.select
,
11 input: C
.Options
.input
,
13 "atomic", "cannibal", "capture", "cylinder",
14 "dark", "madrasi", "rifle", "teleport"
23 setOtherVariables(fenParsed
, pieceArray
) {
24 super.setOtherVariables(fenParsed
, pieceArray
);
25 // Stack of "last move" only for intermediate chaining
26 this.lastMoveEnd
= [null];
29 genRandInitBaseFen() {
30 const baseFen
= super.genRandInitBaseFen();
32 fen: baseFen
.fen
.replace("pppppppp/8", "8/pppppppp")
33 .replace("8/PPPPPPPP", "PPPPPPPP/8"),
38 getBasicMove([sx
, sy
], [ex
, ey
], tr
) {
39 const L
= this.lastMoveEnd
.length
;
40 const lm
= this.lastMoveEnd
[L
-1];
41 const piece
= (!!lm
? lm
.p : null);
43 if (this.board
[ex
][ey
] == "") {
45 tr
= {c: c
, p: piece
};
46 let mv
= super.getBasicMove([sx
, sy
], [ex
, ey
], tr
);
51 // Capture: initial, or inside a chain
52 const initPiece
= (piece
|| this.getPiece(sx
, sy
));
53 const oppCol
= C
.GetOppTurn(c
);
54 const oppPiece
= this.getPiece(ex
, ey
);
56 start: {x: sx
, y: sy
},
63 p: (!!tr
? tr
.p : initPiece
)
91 getPotentialMovesFrom([x
, y
], asA
) {
92 const L
= this.lastMoveEnd
.length
;
93 if (!!this.lastMoveEnd
[L
-1]) {
94 if (x
!= this.lastMoveEnd
[L
-1].x
|| y
!= this.lastMoveEnd
[L
-1].y
)
95 // A capture was played: wrong square
97 asA
= this.lastMoveEnd
[L
-1].p
;
99 switch (asA
|| this.getPiece(x
, y
)) {
100 case V
.PAWN: return super.getPotentialPawnMoves([x
, y
]);
101 case V
.ROOK: return super.getPotentialRookMoves([x
, y
]);
102 case V
.KNIGHT: return super.getPotentialKnightMoves([x
, y
]);
103 case V
.BISHOP: return super.getPotentialBishopMoves([x
, y
]);
104 case V
.QUEEN: return super.getPotentialQueenMoves([x
, y
]);
105 case V
.KING: return super.getPotentialKingMoves([x
, y
]);
110 getPossibleMovesFrom(sq
) {
111 const L
= this.lastMoveEnd
.length
;
113 if (!!this.lastMoveEnd
[L
-1]) {
115 sq
[0] != this.lastMoveEnd
[L
-1].x
||
116 sq
[1] != this.lastMoveEnd
[L
-1].y
120 asA
= this.lastMoveEnd
[L
-1].p
;
122 return this.filterValid(this.getPotentialMovesFrom(sq
, asA
));
125 isAttacked_aux([x
, y
], color
, explored
) {
126 if (explored
.some(sq
=> sq
[0] == x
&& sq
[1] == y
))
127 // Start of an infinite loop: exit
129 explored
.push([x
, y
]);
130 if (super.isAttacked([x
, y
], color
)) return true;
131 // Maybe indirect "chaining" attack:
132 const myColor
= this.turn
134 let toCheck
= []; //check all but king (no need)
136 const shiftToPawn
= (myColor
== 'w' ? -1 : 1);
137 for (let yShift
of [-1, 1]) {
138 const [i
, j
] = [x
+ shiftToPawn
, y
+ yShift
];
141 this.board
[i
][j
] != V
.EMPTY
&&
142 // NOTE: no need to check color (no enemy pawn can take directly)
143 this.getPiece(i
, j
) == V
.PAWN
145 toCheck
.push([i
, j
]);
149 V
.steps
[V
.KNIGHT
].forEach(s
=> {
150 const [i
, j
] = [x
+ s
[0], y
+ s
[1]];
153 this.board
[i
][j
] != V
.EMPTY
&&
154 this.getPiece(i
, j
) == V
.KNIGHT
156 toCheck
.push([i
, j
]);
160 V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]).forEach(s
=> {
161 let [i
, j
] = [x
+ s
[0], y
+ s
[1]];
162 while (V
.OnBoard(i
, j
) && this.board
[i
][j
] == V
.EMPTY
) {
166 if (!V
.OnBoard(i
, j
)) return;
167 const piece
= this.getPiece(i
, j
);
170 (piece
== V
.ROOK
&& (s
[0] == 0 || s
[1] == 0)) ||
171 (piece
== V
.BISHOP
&& (s
[0] != 0 && s
[1] != 0))
173 toCheck
.push([i
, j
]);
176 for (let ij
of toCheck
) {
177 if (this.isAttacked_aux(ij
, color
, explored
)) return true;
182 isAttacked([x
, y
], color
) {
184 return this.isAttacked_aux([x
, y
], color
, explored
);
188 // No "checks" (except to forbid castle)
194 // Extra conditions to avoid tracking converted kings:
196 move.appear
[0].p
== V
.KING
&&
197 move.vanish
.length
>= 1 &&
198 move.vanish
[0].p
== V
.KING
200 this.kingPos
[c
][0] = move.appear
[0].x
;
201 this.kingPos
[c
][1] = move.appear
[0].y
;
208 move.flags
= JSON
.stringify(this.aggregateFlags());
209 V
.PlayOnBoard(this.board
, move);
210 if (!move.end
.converted
) {
211 // Not a capture: change turn
212 this.turn
= V
.GetOppCol(this.turn
);
214 this.lastMoveEnd
.push(null);
217 this.lastMoveEnd
.push(
218 Object
.assign({}, move.end
, { p: move.end
.converted
})
221 super.updateCastleFlags(move, move.appear
[0].p
, c
);