e12a7482fac1f37bb46d35a54adc70646d3c4343
1 import { ChessRules
, Move
, PiPo
} from "@/base_rules";
2 import { ArrayFun
} from "@/utils/array";
3 import { randInt
, sample
} from "@/utils/alea";
5 export class CoregalRules
extends ChessRules
{
7 // TODO: special symbol (l) for royal queen...
11 m
.vanish
.length
== 2 &&
12 m
.appear
.length
== 2 &&
13 m
.vanish
[0].p
== V
.QUEEN
15 // Large castle: show castle symbol
16 return "Coregal/castle";
18 return super.getPPpath(m
);
21 genRandInitBaseFen() {
22 const s
= FenUtil
.setupPieces(
23 ['r', 'n', 'b', 'l', 'k', 'b', 'n', 'r'],
25 randomness: this.options
["randomness"],
26 between: [{p1: 'k', p2: 'r'}, {p1: 'l', p2: 'r'}],
28 flags: ['r', 'k', 'l']
32 fen: s
.b
.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
33 s
.w
.join("").toUpperCase(),
39 let res
= super.pieces();
45 // white pieces positions, then black pieces positions
46 this.castleFlags
= { w: [...Array(4)], b: [...Array(4)] };
47 for (let i
= 0; i
< 8; i
++) {
48 this.castleFlags
[i
< 4 ? "w" : "b"][i
% 4] =
49 parseInt(fenflags
.charAt(i
), 10);
53 getPotentialQueenMoves([x
, y
]) {
54 let moves
= super.getPotentialQueenMoves([x
, y
]);
55 const c
= this.getColor(x
, y
);
56 if (this.castleFlags
[c
].slice(1, 3).includes(y
))
57 moves
= moves
.concat(this.getCastleMoves([x
, y
]));
61 getPotentialKingMoves([x
, y
]) {
62 let moves
= this.getSlideNJumpMoves(
63 [x
, y
], V
.steps
[V
.ROOK
].concat(V
.steps
[V
.BISHOP
]), 1);
64 const c
= this.getColor(x
, y
);
65 if (this.castleFlags
[c
].slice(1, 3).includes(y
))
66 moves
= moves
.concat(this.getCastleMoves([x
, y
]));
70 getCastleMoves([x
, y
]) {
71 // Relative position of the selected piece: left or right ?
72 // If left: small castle left, large castle right.
73 // If right: usual situation.
74 const c
= this.getColor(x
, y
);
75 const relPos
= (this.castleFlags
[c
][1] == y
? "left" : "right");
77 const finalSquares
= [
78 relPos
== "left" ? [1, 2] : [2, 3],
79 relPos
== "right" ? [6, 5] : [5, 4]
81 const saveFlags
= JSON
.stringify(this.castleFlags
[c
]);
82 // Alter flags to follow base_rules semantic
83 this.castleFlags
[c
] = [0, 3].map(i
=> this.castleFlags
[c
][i
]);
84 const moves
= super.getCastleMoves([x
, y
], finalSquares
);
85 this.castleFlags
[c
] = JSON
.parse(saveFlags
);
89 // "twoKings" arg for the similar Twokings variant.
90 updateCastleFlags(move, piece
, twoKings
) {
91 const c
= V
.GetOppCol(this.turn
);
92 const firstRank
= (c
== "w" ? V
.size
.x
- 1 : 0);
93 // Update castling flags if castling pieces moved or were captured
94 const oppCol
= V
.GetOppCol(c
);
95 const oppFirstRank
= V
.size
.x
- 1 - firstRank
;
96 if (move.start
.x
== firstRank
) {
97 if (piece
== V
.KING
|| (!twoKings
&& piece
== V
.QUEEN
)) {
98 if (this.castleFlags
[c
][1] == move.start
.y
)
99 this.castleFlags
[c
][1] = 8;
100 else if (this.castleFlags
[c
][2] == move.start
.y
)
101 this.castleFlags
[c
][2] = 8;
102 // Else: the flag is already turned off
106 move.start
.x
== firstRank
&& //our rook moves?
107 [this.castleFlags
[c
][0], this.castleFlags
[c
][3]].includes(move.start
.y
)
109 const flagIdx
= (move.start
.y
== this.castleFlags
[c
][0] ? 0 : 3);
110 this.castleFlags
[c
][flagIdx
] = 8;
112 move.end
.x
== oppFirstRank
&& //we took opponent rook?
113 [this.castleFlags
[oppCol
][0], this.castleFlags
[oppCol
][3]]
114 .includes(move.end
.y
)
116 const flagIdx
= (move.end
.y
== this.castleFlags
[oppCol
][0] ? 0 : 3);
117 this.castleFlags
[oppCol
][flagIdx
] = 8;