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 this.isAttackedBySlideNJump(sq
, color
, V
.AMAZON
, V
.steps
[V
.BISHOP
]) ||
88 this.isAttackedBySlideNJump(sq
, color
, V
.AMAZON
, V
.steps
[V
.ROOK
]) ||
89 this.isAttackedBySlideNJump(
99 isAttackedByEmpress(sq
, color
) {
101 this.isAttackedBySlideNJump(sq
, color
, V
.EMPRESS
, V
.steps
[V
.ROOK
]) ||
102 this.isAttackedBySlideNJump(
112 isAttackedByPrincess(sq
, color
) {
114 this.isAttackedBySlideNJump(sq
, color
, V
.PRINCESS
, V
.steps
[V
.BISHOP
]) ||
115 this.isAttackedBySlideNJump(
125 static get VALUES() {
126 return Object
.assign(
127 { a: 12, e: 7, s: 5 }, //experimental
132 static get SEARCH_DEPTH() {
136 static GenRandInitFen(randomness
) {
138 return "esqakbnr/pppppppp/8/8/8/8/PPPPPPPP/ESQAKBNR w 0 ahah -";
140 let pieces
= { w: new Array(8), b: new Array(8) };
142 let whiteBishopPos
= -1;
143 for (let c
of ["w", "b"]) {
144 if (c
== 'b' && randomness
== 1) {
145 pieces
['b'] = pieces
['w'];
150 let positions
= ArrayFun
.range(8);
152 // Get random squares for bishop: if black, pick a different color
153 // than where the white one stands.
157 : 2 * randInt(4) + (1 - whiteBishopPos
% 2);
158 if (c
== 'w') whiteBishopPos
= randIndex
;
159 const bishopPos
= positions
[randIndex
];
160 positions
.splice(randIndex
, 1);
162 randIndex
= randInt(7);
163 const knightPos
= positions
[randIndex
];
164 positions
.splice(randIndex
, 1);
166 randIndex
= randInt(6);
167 const queenPos
= positions
[randIndex
];
168 positions
.splice(randIndex
, 1);
170 randIndex
= randInt(5);
171 const amazonPos
= positions
[randIndex
];
172 positions
.splice(randIndex
, 1);
174 randIndex
= randInt(4);
175 const princessPos
= positions
[randIndex
];
176 positions
.splice(randIndex
, 1);
178 // Rook, empress and king positions are now almost fixed,
179 // only the ordering rook->empress or empress->rook must be decided.
180 let rookPos
= positions
[0];
181 let empressPos
= positions
[2];
182 const kingPos
= positions
[1];
183 flags
+= V
.CoordToColumn(rookPos
) + V
.CoordToColumn(empressPos
);
184 if (Math
.random() < 0.5) [rookPos
, empressPos
] = [empressPos
, rookPos
];
186 pieces
[c
][rookPos
] = "r";
187 pieces
[c
][knightPos
] = "n";
188 pieces
[c
][bishopPos
] = "b";
189 pieces
[c
][queenPos
] = "q";
190 pieces
[c
][kingPos
] = "k";
191 pieces
[c
][amazonPos
] = "a";
192 pieces
[c
][princessPos
] = "s";
193 pieces
[c
][empressPos
] = "e";
195 // Add turn + flags + enpassant
197 pieces
["b"].join("") +
198 "/pppppppp/8/8/8/8/PPPPPPPP/" +
199 pieces
["w"].join("").toUpperCase() +
200 " w 0 " + flags
+ " -"