1 import { ChessRules
} from "@/base_rules";
2 import { ArrayFun
} from "@/utils/array";
3 import { randInt
} from "@/utils/alea";
5 export class PerfectRules
extends ChessRules
{
6 static get PawnSpecs() {
12 ChessRules
.PawnSpecs
.promotions
13 .concat([V
.AMAZON
, V
.EMPRESS
, V
.PRINCESS
])
20 [V
.AMAZON
, V
.EMPRESS
, V
.PRINCESS
].includes(b
[1])
32 static get EMPRESS() {
37 static get PRINCESS() {
42 return ChessRules
.PIECES
.concat([V
.AMAZON
, V
.EMPRESS
, V
.PRINCESS
]);
45 getPotentialMovesFrom([x
, y
]) {
46 switch (this.getPiece(x
, y
)) {
48 return this.getPotentialAmazonMoves([x
, y
]);
50 return this.getPotentialEmpressMoves([x
, y
]);
52 return this.getPotentialPrincessMoves([x
, y
]);
54 return super.getPotentialMovesFrom([x
, y
]);
58 getPotentialAmazonMoves(sq
) {
59 return super.getPotentialQueenMoves(sq
).concat(
60 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
64 getPotentialEmpressMoves(sq
) {
65 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.ROOK
]).concat(
66 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
70 getPotentialPrincessMoves(sq
) {
71 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
]).concat(
72 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
76 isAttacked(sq
, color
) {
78 super.isAttacked(sq
, color
) ||
79 this.isAttackedByAmazon(sq
, color
) ||
80 this.isAttackedByEmpress(sq
, color
) ||
81 this.isAttackedByPrincess(sq
, color
)
85 isAttackedByAmazon(sq
, color
) {
87 super.isAttackedByQueen(sq
, color
) ||
88 this.isAttackedBySlideNJump(
98 isAttackedByEmpress(sq
, color
) {
100 this.isAttackedBySlideNJump(sq
, color
, V
.MARSHALL
, V
.steps
[V
.ROOK
]) ||
101 this.isAttackedBySlideNJump(
111 isAttackedByPrincess(sq
, color
) {
113 this.isAttackedBySlideNJump(sq
, color
, V
.CARDINAL
, V
.steps
[V
.BISHOP
]) ||
114 this.isAttackedBySlideNJump(
124 static get VALUES() {
125 return Object
.assign(
126 { a: 12, e: 7, s: 5 }, //experimental
131 static get SEARCH_DEPTH() {
135 static GenRandInitFen(randomness
) {
137 return "esqakbnr/pppppppp/8/8/8/8/PPPPPPPP/ESQAKBNR w 0 ahah -";
139 let pieces
= { w: new Array(8), b: new Array(8) };
141 let whiteBishopPos
= -1;
142 for (let c
of ["w", "b"]) {
143 if (c
== 'b' && randomness
== 1) {
144 pieces
['b'] = pieces
['w'];
149 let positions
= ArrayFun
.range(8);
151 // Get random squares for bishop: if black, pick a different color
152 // than where the white one stands.
156 : 2 * randInt(4) + (1 - whiteBishopPos
% 2);
157 if (c
== 'w') whiteBishopPos
= randIndex
;
158 const bishopPos
= positions
[randIndex
];
159 positions
.splice(randIndex
, 1);
161 randIndex
= randInt(7);
162 const knightPos
= positions
[randIndex
];
163 positions
.splice(randIndex
, 1);
165 randIndex
= randInt(6);
166 const queenPos
= positions
[randIndex
];
167 positions
.splice(randIndex
, 1);
169 randIndex
= randInt(5);
170 const amazonPos
= positions
[randIndex
];
171 positions
.splice(randIndex
, 1);
173 randIndex
= randInt(4);
174 const princessPos
= positions
[randIndex
];
175 positions
.splice(randIndex
, 1);
177 // Rook, empress and king positions are now almost fixed,
178 // only the ordering rook->empress or empress->rook must be decided.
179 let rookPos
= positions
[0];
180 let empressPos
= positions
[2];
181 const kingPos
= positions
[1];
182 flags
+= V
.CoordToColumn(rookPos
) + V
.CoordToColumn(empressPos
);
183 if (Math
.random() < 0.5) [rookPos
, empressPos
] = [empressPos
, rookPos
];
185 pieces
[c
][rookPos
] = "r";
186 pieces
[c
][knightPos
] = "n";
187 pieces
[c
][bishopPos
] = "b";
188 pieces
[c
][queenPos
] = "q";
189 pieces
[c
][kingPos
] = "k";
190 pieces
[c
][amazonPos
] = "a";
191 pieces
[c
][princessPos
] = "s";
192 pieces
[c
][empressPos
] = "e";
194 // Add turn + flags + enpassant
196 pieces
["b"].join("") +
197 "/pppppppp/8/8/8/8/PPPPPPPP/" +
198 pieces
["w"].join("").toUpperCase() +
199 " w 0 " + flags
+ " -"