Add Fugue variant
[vchess.git] / client / src / variants / Capablanca.js
1 import { ChessRules } from "@/base_rules";
2 import { ArrayFun } from "@/utils/array";
3 import { randInt } from "@/utils/alea";
4
5 export class CapablancaRules extends ChessRules {
6
7 static get PawnSpecs() {
8 return Object.assign(
9 {},
10 ChessRules.PawnSpecs,
11 {
12 promotions:
13 ChessRules.PawnSpecs.promotions
14 .concat([V.EMPRESS, V.PRINCESS])
15 }
16 );
17 }
18
19 getPpath(b) {
20 return ([V.EMPRESS, V.PRINCESS].includes(b[1]) ? "Capablanca/" : "") + b;
21 }
22
23 static get size() {
24 return { x: 8, y: 10 };
25 }
26
27 // Rook + knight:
28 static get EMPRESS() {
29 return "e";
30 }
31
32 // Bishop + knight
33 static get PRINCESS() {
34 return "s";
35 }
36
37 static get PIECES() {
38 return ChessRules.PIECES.concat([V.EMPRESS, V.PRINCESS]);
39 }
40
41 getPotentialMovesFrom([x, y]) {
42 switch (this.getPiece(x, y)) {
43 case V.EMPRESS:
44 return this.getPotentialEmpressMoves([x, y]);
45 case V.PRINCESS:
46 return this.getPotentialPrincessMoves([x, y]);
47 default:
48 return super.getPotentialMovesFrom([x, y]);
49 }
50 }
51
52 getPotentialEmpressMoves(sq) {
53 return this.getSlideNJumpMoves(sq, V.steps[V.ROOK]).concat(
54 this.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep")
55 );
56 }
57
58 getPotentialPrincessMoves(sq) {
59 return this.getSlideNJumpMoves(sq, V.steps[V.BISHOP]).concat(
60 this.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep")
61 );
62 }
63
64 isAttacked(sq, color) {
65 return (
66 super.isAttacked(sq, color) ||
67 this.isAttackedByEmpress(sq, color) ||
68 this.isAttackedByPrincess(sq, color)
69 );
70 }
71
72 isAttackedByEmpress(sq, color) {
73 return (
74 this.isAttackedBySlideNJump(sq, color, V.EMPRESS, V.steps[V.ROOK]) ||
75 this.isAttackedBySlideNJump(
76 sq,
77 color,
78 V.EMPRESS,
79 V.steps[V.KNIGHT],
80 "oneStep"
81 )
82 );
83 }
84
85 isAttackedByPrincess(sq, color) {
86 return (
87 this.isAttackedBySlideNJump(sq, color, V.PRINCESS, V.steps[V.BISHOP]) ||
88 this.isAttackedBySlideNJump(
89 sq,
90 color,
91 V.PRINCESS,
92 V.steps[V.KNIGHT],
93 "oneStep"
94 )
95 );
96 }
97
98 static get VALUES() {
99 return Object.assign(
100 { s: 5, e: 7 },
101 ChessRules.VALUES
102 );
103 }
104
105 static get SEARCH_DEPTH() {
106 return 2;
107 }
108
109 static GenRandInitFen(randomness) {
110 if (randomness == 0) {
111 return (
112 "rnsbqkbenr/pppppppppp/91/91/91/91/PPPPPPPPPP/RNSBQKBENR w 0 ajaj -"
113 );
114 }
115
116 let pieces = { w: new Array(10), b: new Array(10) };
117 let flags = "";
118 for (let c of ["w", "b"]) {
119 if (c == 'b' && randomness == 1) {
120 pieces['b'] = pieces['w'];
121 flags += flags;
122 break;
123 }
124
125 let positions = ArrayFun.range(10);
126
127 // Get random squares for bishops
128 let randIndex = 2 * randInt(5);
129 const bishop1Pos = positions[randIndex];
130 // The second bishop must be on a square of different color
131 let randIndex_tmp = 2 * randInt(5) + 1;
132 const bishop2Pos = positions[randIndex_tmp];
133 // Remove chosen squares
134 positions.splice(Math.max(randIndex, randIndex_tmp), 1);
135 positions.splice(Math.min(randIndex, randIndex_tmp), 1);
136
137 // Get random square for empress
138 randIndex = randInt(8);
139 const empressPos = positions[randIndex];
140 positions.splice(randIndex, 1);
141
142 // Get random square for princess
143 randIndex = randInt(7);
144 const princessPos = positions[randIndex];
145 positions.splice(randIndex, 1);
146
147 // Get random squares for knights
148 randIndex = randInt(6);
149 const knight1Pos = positions[randIndex];
150 positions.splice(randIndex, 1);
151 randIndex = randInt(5);
152 const knight2Pos = positions[randIndex];
153 positions.splice(randIndex, 1);
154
155 // Get random square for queen
156 randIndex = randInt(4);
157 const queenPos = positions[randIndex];
158 positions.splice(randIndex, 1);
159
160 // Now rooks + king positions are fixed:
161 const rook1Pos = positions[0];
162 const kingPos = positions[1];
163 const rook2Pos = positions[2];
164
165 // Finally put the shuffled pieces in the board array
166 pieces[c][rook1Pos] = "r";
167 pieces[c][knight1Pos] = "n";
168 pieces[c][bishop1Pos] = "b";
169 pieces[c][queenPos] = "q";
170 pieces[c][empressPos] = "e";
171 pieces[c][princessPos] = "s";
172 pieces[c][kingPos] = "k";
173 pieces[c][bishop2Pos] = "b";
174 pieces[c][knight2Pos] = "n";
175 pieces[c][rook2Pos] = "r";
176 flags += V.CoordToColumn(rook1Pos) + V.CoordToColumn(rook2Pos);
177 }
178 return (
179 pieces["b"].join("") + "/pppppppppp/91/91/91/91/PPPPPPPPPP/" +
180 pieces["w"].join("").toUpperCase() + " w 0 " + flags + " - -"
181 );
182 }
183
184 };