240f13097bb5db1872163d75bb2d67497b51bd9e
[xogo.git] / variants / Baroque / class.js
1 import GiveawayRules from "/variants/Giveaway/class.js";
2 import AbstractSpecialCaptureRules from "/variants/_SpecialCaptures.js";
3 import {Random} from "/utils/alea.js";
4
5 export default class BaroqueRules extends AbstractSpecialCaptureRules {
6
7 static get Options() {
8 return {
9 select: C.Options.Select,
10 input: [
11 {
12 label: "Capture king",
13 variable: "taking",
14 type: "checkbox",
15 defaut: false
16 }
17 ],
18 styles: [
19 "balance",
20 "capture",
21 "crazyhouse",
22 "cylinder",
23 "doublemove",
24 "progressive",
25 "recycle",
26 "teleport"
27 ]
28 };
29 }
30
31 get hasFlags() {
32 return false;
33 }
34
35 genRandInitBaseFen() {
36 if (this.options["randomness"] == 0)
37 return "rnbkqbnm/pppppppp/8/8/8/8/PPPPPPPP/MNBQKBNR";
38 const options = Object.assign({mode: "suicide"}, this.options);
39 const gr = new GiveawayRules({options: options, genFenOnly: true});
40 let res = gr.genRandInitBaseFen();
41 let immPos = {};
42 for (let c of ['w', 'b']) {
43 const rookChar = (c == 'w' ? 'R' : 'r');
44 switch (Random.randInt(2)) {
45 case 0:
46 immPos[c] = res.fen.indexOf(rookChar);
47 break;
48 case 1:
49 immPos[c] = res.fen.lastIndexOf(rookChar);
50 break;
51 }
52 }
53 res.fen = res.fen.substring(0, immPos['b']) + 'i' +
54 res.fen.substring(immPos['b'] + 1, immPos['w']) + 'I' +
55 res.fen.substring(immPos['w'] + 1);
56 return res;
57 }
58
59 pieces() {
60 return Object.assign({},
61 super.pieces(),
62 {
63 'p': {
64 "class": "pawn", //pincer
65 moves: [
66 {steps: [[0, 1], [0, -1], [1, 0], [-1, 0]]}
67 ]
68 },
69 'r': {
70 "class": "rook", //coordinator
71 moves: [
72 {
73 steps: [
74 [1, 0], [0, 1], [-1, 0], [0, -1],
75 [1, 1], [1, -1], [-1, 1], [-1, -1]
76 ]
77 }
78 ]
79 },
80 'n': {
81 "class": "knight", //long-leaper
82 moveas: 'r'
83 },
84 'b': {
85 "class": "bishop", //chameleon
86 moveas: 'r'
87 },
88 'q': {
89 "class": "queen", //withdrawer
90 moveas: 'r'
91 },
92 'i': {
93 "class": "immobilizer",
94 moveas: 'r'
95 }
96 }
97 );
98 }
99
100 // Is piece on square (x,y) immobilized?
101 isImmobilized([x, y]) {
102 const piece = this.getPiece(x, y);
103 const color = this.getColor(x, y);
104 const oppCol = C.GetOppCol(color);
105 const adjacentSteps = this.pieces()['k'].moves[0].steps;
106 for (let step of adjacentSteps) {
107 const [i, j] = [x + step[0], this.getY(y + step[1])];
108 if (
109 this.onBoard(i, j) &&
110 this.board[i][j] != "" &&
111 this.getColor(i, j) == oppCol
112 ) {
113 const oppPiece = this.getPiece(i, j);
114 if (oppPiece == 'i') {
115 // Moving is possible only if this immobilizer is neutralized
116 for (let step2 of adjacentSteps) {
117 const [i2, j2] = [i + step2[0], this.getY(j + step2[1])];
118 if (i2 == x && j2 == y)
119 continue; //skip initial piece!
120 if (
121 this.onBoard(i2, j2) &&
122 this.board[i2][j2] != "" &&
123 this.getColor(i2, j2) == color
124 ) {
125 if (['b', 'i'].includes(this.getPiece(i2, j2)))
126 return false;
127 }
128 }
129 return true; //immobilizer isn't neutralized
130 }
131 // Chameleons can't be immobilized twice,
132 // because there is only one immobilizer
133 if (oppPiece == 'b' && piece == 'i')
134 return true;
135 }
136 }
137 return false;
138 }
139
140 canTake([x1, y1], [x2, y2]) {
141 // Deactivate standard captures, except for king:
142 return (
143 this.getPiece(x1, y1) == 'k' &&
144 this.getColor(x1, y1) != this.getColor(x2, y2)
145 );
146 }
147
148 postProcessPotentialMoves(moves) {
149 if (moves.length == 0)
150 return [];
151 switch (moves[0].vanish[0].p) {
152 case 'p':
153 this.addPincerCaptures(moves);
154 break;
155 case 'r':
156 this.addCoordinatorCaptures(moves);
157 break;
158 case 'n':
159 const [x, y] = [moves[0].start.x, moves[0].start.y];
160 moves = moves.concat(this.getLeaperCaptures([x, y]));
161 break;
162 case 'b':
163 moves = this.getChameleonCaptures(moves, "pull");
164 break;
165 case 'q':
166 this.addPushmePullyouCaptures(moves, false, "pull");
167 break;
168 }
169 return moves;
170 }
171
172 };