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
], 1)
65 getPotentialEmpressMoves(sq
) {
66 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.ROOK
]).concat(
67 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], 1)
71 getPotentialPrincessMoves(sq
) {
72 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
]).concat(
73 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], 1)
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(sq
, color
, V
.AMAZON
, V
.steps
[V
.KNIGHT
], 1)
94 isAttackedByEmpress(sq
, color
) {
96 this.isAttackedBySlideNJump(sq
, color
, V
.EMPRESS
, V
.steps
[V
.ROOK
]) ||
97 this.isAttackedBySlideNJump(sq
, color
, V
.EMPRESS
, V
.steps
[V
.KNIGHT
], 1)
101 isAttackedByPrincess(sq
, color
) {
103 this.isAttackedBySlideNJump(sq
, color
, V
.PRINCESS
, V
.steps
[V
.BISHOP
]) ||
104 this.isAttackedBySlideNJump(sq
, color
, V
.PRINCESS
, V
.steps
[V
.KNIGHT
], 1)
108 static get VALUES() {
109 return Object
.assign(
110 { a: 12, e: 7, s: 5 }, //experimental
115 static get SEARCH_DEPTH() {
119 static GenRandInitFen(options
) {
120 if (options
.randomness
== 0)
121 return "esqakbnr/pppppppp/8/8/8/8/PPPPPPPP/ESQAKBNR w 0 ahah -";
123 const baseFen
= ChessRules
.GenRandInitFen(options
);
124 const fenParts
= baseFen
.split(' ');
125 const posParts
= fenParts
[0].split('/');
127 // Replace a random rook per side by an empress,
128 // a random knight by a princess, and a bishop by an amazon
129 // (Constraint: the two remaining bishops on different colors).
131 let newPos
= { 0: "", 7: "" };
132 let amazonOddity
= -1;
133 for (let rank
of [0, 7]) {
134 let replaced
= { 'b': -2, 'n': -2, 'r': -2 };
135 for (let i
= 0; i
< 8; i
++) {
136 const curChar
= posParts
[rank
].charAt(i
).toLowerCase();
137 if (['b', 'n', 'r'].includes(curChar
)) {
139 replaced
[curChar
] == -1 ||
140 (curChar
== 'b' && rank
== 7 && i
% 2 == amazonOddity
) ||
142 (curChar
!= 'b' || rank
== 0) &&
143 replaced
[curChar
] == -2 &&
147 replaced
[curChar
] = i
;
148 if (curChar
== 'b') {
149 if (amazonOddity
< 0) amazonOddity
= i
% 2;
152 else if (curChar
== 'r') newPos
[rank
] += 'e';
153 else newPos
[rank
] += 's';
156 if (replaced
[curChar
] == -2) replaced
[curChar
]++;
157 newPos
[rank
] += curChar
;
160 else newPos
[rank
] += curChar
;
165 newPos
[0] + "/" + posParts
.slice(1, 7).join('/') + "/" +
166 newPos
[7].toUpperCase() + " " + fenParts
.slice(1, 5).join(' ') + " -"