393e407b91888538f9c98c95293e523dbe80c1a3
[xogo.git] / variants / Cwda / class.js
1 import ChessRules from "/base_rules.js";
2
3 export default class CwdaRules extends ChessRules {
4
5 static get Options() {
6 return {
7 select: ChessRules.Options.select.concat([
8 {
9 label: "Army 1",
10 variable: "army1",
11 defaut: 'C',
12 options: [
13 { label: "Colorbound Clobberers", value: 'C' },
14 { label: "Nutty Knights", value: 'N' },
15 { label: "Remarkable Rookies", value: 'R' },
16 { label: "Fide", value: 'F' }
17 ]
18 },
19 {
20 label: "Army 2",
21 variable: "army2",
22 defaut: 'C',
23 options: [
24 { label: "Colorbound Clobberers", value: 'C' },
25 { label: "Nutty Knights", value: 'N' },
26 { label: "Remarkable Rookies", value: 'R' },
27 { label: "Fide", value: 'F' }
28 ]
29 }
30 ]),
31 input: ChessRules.Options.input,
32 styles: ChessRules.Options.styles
33 };
34 }
35
36 static get PiecesMap() {
37 return {
38 // Colorbound Clobberers
39 'C': {
40 'r': 'd',
41 'n': 'w',
42 'b': 'f',
43 'q': 'c',
44 'k': 'm',
45 'p': 'z'
46 },
47 // Nutty Knights
48 'N': {
49 'r': 'g',
50 'n': 'i',
51 'b': 't',
52 'q': 'l',
53 'k': 'e',
54 'p': 'v'
55 },
56 // Remarkable Rookies
57 'R': {
58 'r': 's',
59 'n': 'y',
60 'b': 'h',
61 'q': 'o',
62 'k': 'a',
63 'p': 'u'
64 }
65 };
66 }
67
68 genRandInitBaseFen() {
69 let s = FenUtil.setupPieces(
70 ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'],
71 {
72 randomness: this.options["randomness"],
73 between: [{p1: 'k', p2: 'r'}],
74 diffCol: ['b'],
75 flags: ['r', 'k']
76 }
77 );
78 let pawnLines = {
79 w: "pppppppp",
80 b: "pppppppp"
81 };
82 for (const c of ['w', 'b']) {
83 const army = "army" + (c == 'w' ? "1" : "2");
84 if (this.options[army] != 'F') {
85 for (let obj of [s, pawnLines]) {
86 obj[c] = obj[c].split("")
87 .map(p => V.PiecesMap[this.options[army]][p]).join("");
88 }
89 }
90 }
91 return {
92 fen: s.b.join("") + "/" +
93 pawnLines['b'] + "/8/8/8/8/" + pawnLines['w'].toUpperCase() +
94 "/" + s.w.join("").toUpperCase(),
95 o: {flags: s.flags}
96 };
97 }
98
99 getPartFen(o) {
100 return Object.assign(
101 { "armies": this.options["army1"] + this.options["army2"] },
102 super.getPartFen(o)
103 );
104 }
105
106 setOtherVariables(fenParsed) {
107 super.setOtherVariables(fenParsed);
108 this.army1 = fenParsed.armies.charAt(0);
109 this.army2 = fenParsed.armies.charAt(1);
110 }
111
112 isKing(x, y, p) {
113 if (!p)
114 p = this.getPiece(x, y);
115 return (super.isKing(x, y, p) || ['a', 'e', 'm'].includes(p));
116 }
117
118 // Helper to describe pieces movements
119 static get steps() {
120 return {
121 // Dabbabah
122 'd': [
123 [-2, 0],
124 [0, -2],
125 [2, 0],
126 [0, 2]
127 ],
128 // Alfil
129 'a': [
130 [2, 2],
131 [2, -2],
132 [-2, 2],
133 [-2, -2]
134 ],
135 // Ferz
136 'f': [
137 [1, 1],
138 [1, -1],
139 [-1, 1],
140 [-1, -1]
141 ],
142 // Wazir
143 'w': [
144 [-1, 0],
145 [0, -1],
146 [1, 0],
147 [0, 1]
148 ],
149 // Threeleaper
150 '$3': [
151 [-3, 0],
152 [0, -3],
153 [3, 0],
154 [0, 3]
155 ],
156 // Narrow knight
157 '$n': [
158 [-2, -1],
159 [-2, 1],
160 [2, -1],
161 [2, 1]
162 ]
163 };
164 }
165
166 pieces(color, x, y) {
167 const res = super.pieces(color, x, y);
168 return Object.assign(
169 {
170 'd': {
171 "class": "c_rook",
172 both: [
173 {steps: V.steps.b},
174 {steps: V.steps.d, range: 1}
175 ]
176 },
177 'w': {
178 "class": "c_knight",
179 both: [
180 {steps: V.steps.a, range: 1},
181 {steps: V.steps.r, range: 1}
182 ]
183 },
184 'f': {
185 "class": "c_bishop",
186 both: [
187 {steps: V.steps.d, range: 1},
188 {steps: V.steps.a, range: 1},
189 {steps: V.steps.b, range: 1}
190 ]
191 },
192 'c': {
193 "class": "c_queen",
194 both: [
195 {steps: V.steps.b},
196 {steps: V.steps.n, range: 1}
197 ]
198 },
199 'm': { moveas: 'k' },
200 'z': { moveas: 'p' },
201 'g': {
202
203 },
204 'i': {
205
206 },
207 't': {
208
209 },
210 'l': {
211
212 },
213 'e': { moveas: 'k' },
214 'v': { moveas: 'p' },
215 's': {
216
217 },
218 'y': {
219
220 },
221 'h': {
222
223 },
224 'o': {
225
226 },
227 'a': { moveas: 'k' },
228 'u': { moveas: 'p' }
229 },
230 res
231 );
232
233
234
235
236
237 getPotentialN_rookMoves(sq) {
238 const c = this.turn;
239 const rookSteps = [ [0, -1], [0, 1], [c == 'w' ? -1 : 1, 0] ];
240 const backward = (c == 'w' ? 1 : -1);
241 const kingSteps = [ [backward, -1], [backward, 0], [backward, 1] ];
242 return (
243 this.getSlideNJumpMoves(sq, rookSteps).concat(
244 this.getSlideNJumpMoves(sq, kingSteps, 1))
245 );
246 }
247
248 getPotentialN_knightMoves(sq) {
249 return (
250 this.getSlideNJumpMoves(sq, V.steps.$n, 1).concat(
251 this.getSlideNJumpMoves(sq, V.steps.f, 1))
252 );
253 }
254
255 getPotentialN_bishopMoves(sq) {
256 const backward = (this.turn == 'w' ? 1 : -1);
257 const kingSteps = [
258 [0, -1], [0, 1], [backward, -1], [backward, 0], [backward, 1]
259 ];
260 const forward = -backward;
261 const knightSteps = [
262 [2*forward, -1], [2*forward, 1], [forward, -2], [forward, 2]
263 ];
264 return (
265 this.getSlideNJumpMoves(sq, knightSteps, 1).concat(
266 this.getSlideNJumpMoves(sq, kingSteps, 1))
267 );
268 }
269
270 getPotentialN_queenMoves(sq) {
271 const backward = (this.turn == 'w' ? 1 : -1);
272 const forward = -backward;
273 const kingSteps = [
274 [forward, -1], [forward, 1],
275 [backward, -1], [backward, 0], [backward, 1]
276 ];
277 const knightSteps = [
278 [2*forward, -1], [2*forward, 1], [forward, -2], [forward, 2]
279 ];
280 const rookSteps = [ [0, -1], [0, 1], [forward, 0] ];
281 return (
282 this.getSlideNJumpMoves(sq, rookSteps).concat(
283 this.getSlideNJumpMoves(sq, kingSteps, 1)).concat(
284 this.getSlideNJumpMoves(sq, knightSteps, 1))
285 );
286 }
287
288 getPotentialR_rookMoves(sq) {
289 return this.getSlideNJumpMoves(sq, V.steps.r, 4);
290 }
291
292 getPotentialR_knightMoves(sq) {
293 return (
294 this.getSlideNJumpMoves(sq, V.steps.d, 1).concat(
295 this.getSlideNJumpMoves(sq, V.steps.w, 1))
296 );
297 }
298
299 getPotentialR_bishopMoves(sq) {
300 return (
301 this.getSlideNJumpMoves(sq, V.steps.d, 1).concat(
302 this.getSlideNJumpMoves(sq, V.steps.f, 1)).concat(
303 this.getSlideNJumpMoves(sq, V.steps.$3, 1))
304 );
305 }
306
307 getPotentialR_queenMoves(sq) {
308 return (
309 this.getSlideNJumpMoves(sq, V.steps.r).concat(
310 this.getSlideNJumpMoves(sq, V.steps.n, 1))
311 );
312 }
313
314 case V.PAWN: {
315 // Can promote in anything from the two current armies
316 let promotions = [];
317 for (let army of ["army1", "army2"]) {
318 if (army == "army2" && this.army2 == this.army1) break;
319 switch (this[army]) {
320 case 'C': {
321 Array.prototype.push.apply(promotions,
322 [V.C_ROOK, V.C_KNIGHT, V.C_BISHOP, V.C_QUEEN]);
323 break;
324 }
325 case 'N': {
326 Array.prototype.push.apply(promotions,
327 [V.N_ROOK, V.N_KNIGHT, V.N_BISHOP, V.N_QUEEN]);
328 break;
329 }
330 case 'R': {
331 Array.prototype.push.apply(promotions,
332 [V.R_ROOK, V.R_KNIGHT, V.R_BISHOP, V.R_QUEEN]);
333 break;
334 }
335 case 'F': {
336 Array.prototype.push.apply(promotions,
337 [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN]);
338 break;
339 }
340 }
341 }
342 return super.getPotentialPawnMoves(sq, promotions);
343 }
344 default: return super.getPotentialMovesFrom(sq);
345 }
346
347 getCastleMoves([x, y]) {
348 const color = this.getColor(x, y);
349 let finalSquares = [ [2, 3], [V.size.y - 2, V.size.y - 3] ];
350 if (
351 (color == 'w' && this.army1 == 'C') ||
352 (color == 'b' && this.army2 == 'C')
353 ) {
354 // Colorbound castle long in an unusual way:
355 finalSquares[0] = [1, 2];
356 }
357 return super.getCastleMoves([x, y], finalSquares);
358 }
359
360 };