1 import { ChessRules
} from "@/base_rules";
2 import { ArrayFun
} from "@/utils/array";
3 import { shuffle
} from "@/utils/alea";
5 export class TencubedRules
extends ChessRules
{
6 static get PawnSpecs() {
11 initShift: { w: 2, b: 2 },
12 promotions: [V
.QUEEN
, V
.MARSHALL
, V
.ARCHBISHOP
]
17 static get HasFlags() {
23 [V
.MARSHALL
, V
.ARCHBISHOP
, V
.CHAMPION
, V
.WIZARD
].includes(b
[1])
30 return { x: 10, y: 10 };
34 static get MARSHALL() {
39 static get ARCHBISHOP() {
43 // Dabbabah + alfil + wazir
44 static get CHAMPION() {
56 .concat([V
.MARSHALL
, V
.ARCHBISHOP
, V
.CHAMPION
, V
.WIZARD
])
97 static GenRandInitFen(randomness
) {
98 if (randomness
== 0) {
100 "2cwamwc2/1rnbqkbnr1/pppppppppp/91/91/" +
101 "91/91/PPPPPPPPPP/1RNBQKBNR1/2CWAMWC2/ " +
106 const baseFen
= V
.ParseFen(ChessRules
.GenRandInitFen(randomness
));
107 const positionParts
= baseFen
.position
.split("/");
109 "1" + positionParts
[0] +
110 "1/pppppppppp/91/91/91/91/PPPPPPPPPP/1" +
111 positionParts
[7] + "1"
113 // Now just obtain randomized new pieces placements:
114 let pieces
= { w: new Array(6), b: new Array(6) };
115 for (let c
of ["w", "b"]) {
116 if (c
== 'b' && randomness
== 1) {
117 pieces
['b'] = pieces
['w'];
121 let positions
= shuffle(ArrayFun
.range(6));
122 const composition
= ['w', 'w', 'c', 'c', 'a', 'm'];
123 let rem2
= positions
[0] % 2;
124 if (rem2
== positions
[1] % 2) {
125 // Fix wizards (on different colors)
126 for (let i
=4; i
<6; i
++) {
127 if (positions
[i
] % 2 != rem2
)
128 [positions
[1], positions
[i
]] = [positions
[i
], positions
[1]];
131 rem2
= positions
[2] % 2;
132 if (rem2
== positions
[3] % 2) {
133 // Fix champions too: [NOTE: positions[4] & [5] should do]
134 for (let i
=4; i
<6; i
++) {
135 if (positions
[i
] % 2 != rem2
)
136 [positions
[3], positions
[i
]] = [positions
[i
], positions
[3]];
139 for (let i
= 0; i
< 9; i
++) pieces
[c
][positions
[i
]] = composition
[i
];
142 "2" + pieces
["b"].join("") + "2/" +
144 "/2" + pieces
["w"].join("").toUpperCase() + "2" +
149 getPotentialMovesFrom([x
, y
]) {
150 switch (this.getPiece(x
, y
)) {
152 return this.getPotentialMarshallMoves([x
, y
]);
154 return this.getPotentialArchbishopMoves([x
, y
]);
156 return this.getPotentialChampionMoves([x
, y
]);
158 return this.getPotentialWizardMoves([x
, y
]);
160 return super.getPotentialMovesFrom([x
, y
]);
164 getPotentialMarshallMoves(sq
) {
165 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.ROOK
]).concat(
166 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
170 getPotentialArchbishopMoves(sq
) {
171 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
]).concat(
172 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
176 getPotentialChampionMoves(sq
) {
177 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.CHAMPION
], "oneStep");
180 getPotentialWizardMoves(sq
) {
181 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.WIZARD
], "oneStep");
184 isAttacked(sq
, color
) {
186 super.isAttacked(sq
, color
) ||
187 this.isAttackedByMarshall(sq
, color
) ||
188 this.isAttackedByArchbishop(sq
, color
) ||
189 this.isAttackedByChampion(sq
, color
) ||
190 this.isAttackedByWizard(sq
, color
)
194 isAttackedByMarshall(sq
, color
) {
196 this.isAttackedBySlideNJump(sq
, color
, V
.MARSHALL
, V
.steps
[V
.ROOK
]) ||
197 this.isAttackedBySlideNJump(
207 isAttackedByArchbishop(sq
, color
) {
209 this.isAttackedBySlideNJump(sq
, color
, V
.CARDINAL
, V
.steps
[V
.BISHOP
]) ||
210 this.isAttackedBySlideNJump(
220 isAttackedByWizard(sq
, color
) {
222 this.isAttackedBySlideNJump(
223 sq
, color
, V
.WIZARD
, V
.steps
[V
.WIZARD
], "oneStep")
227 isAttackedByChampion(sq
, color
) {
229 this.isAttackedBySlideNJump(
230 sq
, color
, V
.CHAMPION
, V
.steps
[V
.CHAMPION
], "oneStep")
234 static get SEARCH_DEPTH() {
238 static get VALUES() {
239 return Object
.assign(
242 { c: 4, w: 3, a: 6, m: 8 }