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
])
97 static GenRandInitFen(options
) {
98 if (options
.randomness
== 0) {
100 "2cwamwc2/1rnbqkbnr1/pppppppppp/91/91/" +
101 "91/91/PPPPPPPPPP/1RNBQKBNR1/2CWAMWC2/ " +
106 const baseFen
= V
.ParseFen(ChessRules
.GenRandInitFen(options
));
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
], 1)
170 getPotentialArchbishopMoves(sq
) {
171 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.BISHOP
]).concat(
172 this.getSlideNJumpMoves(sq
, V
.steps
[V
.KNIGHT
], 1)
176 getPotentialChampionMoves(sq
) {
177 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.CHAMPION
], 1);
180 getPotentialWizardMoves(sq
) {
181 return this.getSlideNJumpMoves(sq
, V
.steps
[V
.WIZARD
], 1);
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(sq
, color
, V
.MARSHALL
, V
.steps
[V
.KNIGHT
], 1)
201 isAttackedByArchbishop(sq
, color
) {
203 this.isAttackedBySlideNJump(
204 sq
, color
, V
.ARCHBISHOP
, V
.steps
[V
.BISHOP
])
206 this.isAttackedBySlideNJump(
207 sq
, color
, V
.ARCHBISHOP
, V
.steps
[V
.KNIGHT
], 1)
211 isAttackedByWizard(sq
, color
) {
212 return this.isAttackedBySlideNJump(
213 sq
, color
, V
.WIZARD
, V
.steps
[V
.WIZARD
], 1);
216 isAttackedByChampion(sq
, color
) {
217 return this.isAttackedBySlideNJump(
218 sq
, color
, V
.CHAMPION
, V
.steps
[V
.CHAMPION
], 1);
221 static get SEARCH_DEPTH() {
225 static get VALUES() {
226 return Object
.assign(