1 import { ChessRules
} from "@/base_rules";
2 import { ArrayFun
} from "@/utils/array";
3 import { shuffle
} from "@/utils/alea";
5 export class TencubedRules
extends ChessRules
{
7 static get PawnSpecs() {
12 initShift: { w: 2, b: 2 },
13 promotions: [V
.QUEEN
, V
.MARSHALL
, V
.ARCHBISHOP
]
18 static get HasFlags() {
24 [V
.MARSHALL
, V
.ARCHBISHOP
, V
.CHAMPION
, V
.WIZARD
].includes(b
[1])
31 return { x: 10, y: 10 };
35 static get MARSHALL() {
40 static get ARCHBISHOP() {
44 // Dabbabah + alfil + wazir
45 static get CHAMPION() {
57 .concat([V
.MARSHALL
, V
.ARCHBISHOP
, V
.CHAMPION
, V
.WIZARD
])
98 static GenRandInitFen(randomness
) {
99 if (randomness
== 0) {
101 "2cwamwc2/1rnbqkbnr1/pppppppppp/91/91/" +
102 "91/91/PPPPPPPPPP/1RNBQKBNR1/2CWAMWC2/ " +
107 const baseFen
= V
.ParseFen(ChessRules
.GenRandInitFen(randomness
));
108 const positionParts
= baseFen
.position
.split("/");
110 "1" + positionParts
[0] +
111 "1/pppppppppp/91/91/91/91/PPPPPPPPPP/1" +
112 positionParts
[7] + "1"
114 // Now just obtain randomized new pieces placements:
115 let pieces
= { w: new Array(6), b: new Array(6) };
116 for (let c
of ["w", "b"]) {
117 if (c
== 'b' && randomness
== 1) {
118 pieces
['b'] = pieces
['w'];
122 let positions
= shuffle(ArrayFun
.range(6));
123 const composition
= ['w', 'w', 'c', 'c', 'a', 'm'];
124 let rem2
= positions
[0] % 2;
125 if (rem2
== positions
[1] % 2) {
126 // Fix wizards (on different colors)
127 for (let i
=4; i
<6; i
++) {
128 if (positions
[i
] % 2 != rem2
)
129 [positions
[1], positions
[i
]] = [positions
[i
], positions
[1]];
132 rem2
= positions
[2] % 2;
133 if (rem2
== positions
[3] % 2) {
134 // Fix champions too: [NOTE: positions[4] & [5] should do]
135 for (let i
=4; i
<6; i
++) {
136 if (positions
[i
] % 2 != rem2
)
137 [positions
[3], positions
[i
]] = [positions
[i
], positions
[3]];
140 for (let i
= 0; i
< 9; i
++) pieces
[c
][positions
[i
]] = composition
[i
];
143 "2" + pieces
["b"].join("") + "2/" +
145 "/2" + pieces
["w"].join("").toUpperCase() + "2" +
150 getPotentialMovesFrom([x
, y
]) {
151 switch (this.getPiece(x
, y
)) {
153 return this.getPotentialMarshallMoves([x
, y
]);
155 return this.getPotentialArchbishopMoves([x
, y
]);
157 return this.getPotentialChampionMoves([x
, y
]);
159 return this.getPotentialWizardMoves([x
, y
]);
161 return super.getPotentialMovesFrom([x
, y
]);
165 getPotentialMarshallMoves(sq
) {
166 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.ROOK
]).concat(
167 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
171 getPotentialArchbishopMoves(sq
) {
172 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
]).concat(
173 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], "oneStep")
177 getPotentialChampionMoves(sq
) {
178 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.CHAMPION
], "oneStep");
181 getPotentialWizardMoves(sq
) {
182 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.WIZARD
], "oneStep");
185 isAttacked(sq
, color
) {
187 super.isAttacked(sq
, color
) ||
188 this.isAttackedByMarshall(sq
, color
) ||
189 this.isAttackedByArchbishop(sq
, color
) ||
190 this.isAttackedByChampion(sq
, color
) ||
191 this.isAttackedByWizard(sq
, color
)
195 isAttackedByMarshall(sq
, color
) {
197 this.isAttackedBySlideNJump(sq
, color
, V
.MARSHALL
, V
.steps
[V
.ROOK
]) ||
198 this.isAttackedBySlideNJump(
208 isAttackedByArchbishop(sq
, color
) {
210 this.isAttackedBySlideNJump(sq
, color
, V
.ARCHBISHOP
, V
.steps
[V
.BISHOP
]) ||
211 this.isAttackedBySlideNJump(
221 isAttackedByWizard(sq
, color
) {
223 this.isAttackedBySlideNJump(
224 sq
, color
, V
.WIZARD
, V
.steps
[V
.WIZARD
], "oneStep")
228 isAttackedByChampion(sq
, color
) {
230 this.isAttackedBySlideNJump(
231 sq
, color
, V
.CHAMPION
, V
.steps
[V
.CHAMPION
], "oneStep")
235 static get SEARCH_DEPTH() {
239 static get VALUES() {
240 return Object
.assign(
243 { c: 4, w: 3, a: 6, m: 8 }