1 import { ChessRules
} from "@/base_rules";
2 import { ArrayFun
} from "@/utils/array";
3 import { randInt
} from "@/utils/alea";
5 export class PerfectRules
extends ChessRules
{
7 static get PawnSpecs() {
13 ChessRules
.PawnSpecs
.promotions
14 .concat([V
.AMAZON
, V
.EMPRESS
, V
.PRINCESS
])
21 [V
.AMAZON
, V
.EMPRESS
, V
.PRINCESS
].includes(b
[1])
33 static get EMPRESS() {
38 static get PRINCESS() {
43 return ChessRules
.PIECES
.concat([V
.AMAZON
, V
.EMPRESS
, V
.PRINCESS
]);
46 getPotentialMovesFrom([x
, y
]) {
47 switch (this.getPiece(x
, y
)) {
49 return this.getPotentialAmazonMoves([x
, y
]);
51 return this.getPotentialEmpressMoves([x
, y
]);
53 return this.getPotentialPrincessMoves([x
, y
]);
55 return super.getPotentialMovesFrom([x
, y
]);
59 getPotentialAmazonMoves(sq
) {
60 return super.getPotentialQueenMoves(sq
).concat(
61 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
65 getPotentialEmpressMoves(sq
) {
66 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.ROOK
]).concat(
67 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
71 getPotentialPrincessMoves(sq
) {
72 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
]).concat(
73 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
77 isAttacked(sq
, color
) {
79 super.isAttacked(sq
, color
) ||
80 this.isAttackedByAmazon(sq
, color
) ||
81 this.isAttackedByEmpress(sq
, color
) ||
82 this.isAttackedByPrincess(sq
, color
)
86 isAttackedByAmazon(sq
, color
) {
88 this.isAttackedBySlideNJump(sq
, color
, V
.AMAZON
, V
.steps
[V
.BISHOP
]) ||
89 this.isAttackedBySlideNJump(sq
, color
, V
.AMAZON
, V
.steps
[V
.ROOK
]) ||
90 this.isAttackedBySlideNJump(
100 isAttackedByEmpress(sq
, color
) {
102 this.isAttackedBySlideNJump(sq
, color
, V
.EMPRESS
, V
.steps
[V
.ROOK
]) ||
103 this.isAttackedBySlideNJump(
113 isAttackedByPrincess(sq
, color
) {
115 this.isAttackedBySlideNJump(sq
, color
, V
.PRINCESS
, V
.steps
[V
.BISHOP
]) ||
116 this.isAttackedBySlideNJump(
126 static get VALUES() {
127 return Object
.assign(
128 { a: 12, e: 7, s: 5 }, //experimental
133 static get SEARCH_DEPTH() {
137 static GenRandInitFen(randomness
) {
139 return "esqakbnr/pppppppp/8/8/8/8/PPPPPPPP/ESQAKBNR w 0 ahah -";
141 const baseFen
= ChessRules
.GenRandInitFen(randomness
);
142 const fenParts
= baseFen
.split(' ');
143 const posParts
= fenParts
[0].split('/');
145 // Replace a random rook per side by an empress,
146 // a random knight by a princess, and a bishop by an amazon
147 // (Constraint: the two remaining bishops on different colors).
149 let newPos
= { 0: "", 7: "" };
150 let amazonOddity
= -1;
151 for (let rank
of [0, 7]) {
152 let replaced
= { 'b': -2, 'n': -2, 'r': -2 };
153 for (let i
= 0; i
< 8; i
++) {
154 const curChar
= posParts
[rank
].charAt(i
).toLowerCase();
155 if (['b', 'n', 'r'].includes(curChar
)) {
157 replaced
[curChar
] == -1 ||
158 (curChar
== 'b' && rank
== 7 && i
% 2 == amazonOddity
) ||
160 (curChar
!= 'b' || rank
== 0) &&
161 replaced
[curChar
] == -2 &&
165 replaced
[curChar
] = i
;
166 if (curChar
== 'b') {
167 if (amazonOddity
< 0) amazonOddity
= i
% 2;
170 else if (curChar
== 'r') newPos
[rank
] += 'e';
171 else newPos
[rank
] += 's';
174 if (replaced
[curChar
] == -2) replaced
[curChar
]++;
175 newPos
[rank
] += curChar
;
178 else newPos
[rank
] += curChar
;
183 newPos
[0] + "/" + posParts
.slice(1, 7).join('/') + "/" +
184 newPos
[7].toUpperCase() + " " + fenParts
.slice(1, 5).join(' ') + " -"