b22cbd75a62d60f2b5f7e9794a1ffd534e3e127b
[vchess.git] / public / javascripts / variants / Antiking.js
1 class AntikingRules extends ChessRules
2 {
3 // Path to pieces
4 static getPpath(b)
5 {
6 return b[1]=='a' ? "Antiking/"+b : b;
7 }
8
9 static get ANTIKING() { return 'a'; }
10
11 initVariables(fen)
12 {
13 super.initVariables(fen);
14 this.antikingPos = {'w':[-1,-1], 'b':[-1,-1]};
15 const position = fen.split(" ")[0].split("/");
16 for (let i=0; i<position.length; i++)
17 {
18 let k = 0;
19 for (let j=0; j<position[i].length; j++)
20 {
21 switch (position[i].charAt(j))
22 {
23 case 'a':
24 this.antikingPos['b'] = [i,k];
25 break;
26 case 'A':
27 this.antikingPos['w'] = [i,k];
28 break;
29 default:
30 let num = parseInt(position[i].charAt(j));
31 if (!isNaN(num))
32 k += (num-1);
33 }
34 k++;
35 }
36 }
37 }
38
39 canTake([x1,y1], [x2,y2])
40 {
41 const piece1 = this.getPiece(x1,y1);
42 const piece2 = this.getPiece(x2,y2);
43 const color1 = this.getColor(x1,y1);
44 const color2 = this.getColor(x2,y2);
45 return piece2 != "a" &&
46 ((piece1 != "a" && color1 != color2) || (piece1 == "a" && color1 == color2));
47 }
48
49 getPotentialMovesFrom([x,y])
50 {
51 switch (this.getPiece(x,y))
52 {
53 case VariantRules.ANTIKING:
54 return this.getPotentialAntikingMoves([x,y]);
55 default:
56 return super.getPotentialMovesFrom([x,y]);
57 }
58 }
59
60 getPotentialAntikingMoves(sq)
61 {
62 const V = VariantRules;
63 return this.getSlideNJumpMoves(sq,
64 V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
65 }
66
67 isAttacked(sq, colors)
68 {
69 return (super.isAttacked(sq, colors) || this.isAttackedByAntiking(sq, colors));
70 }
71
72 isAttackedByKing([x,y], colors)
73 {
74 const V = VariantRules;
75 if (this.getPiece(x,y) == V.ANTIKING)
76 return false; //antiking is not attacked by king
77 return this.isAttackedBySlideNJump([x,y], colors, V.KING,
78 V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
79 }
80
81 isAttackedByAntiking([x,y], colors)
82 {
83 const V = VariantRules;
84 if ([V.KING,V.ANTIKING].includes(this.getPiece(x,y)))
85 return false; //(anti)king is not attacked by antiking
86 return this.isAttackedBySlideNJump([x,y], colors, V.ANTIKING,
87 V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
88 }
89
90 underCheck(move)
91 {
92 const c = this.turn;
93 const oppCol = this.getOppCol(c);
94 this.play(move)
95 let res = this.isAttacked(this.kingPos[c], [oppCol])
96 || !this.isAttacked(this.antikingPos[c], [oppCol]);
97 this.undo(move);
98 return res;
99 }
100
101 getCheckSquares(move)
102 {
103 let res = super.getCheckSquares(move);
104 this.play(move);
105 const c = this.turn;
106 if (!this.isAttacked(this.antikingPos[c], [this.getOppCol(c)]))
107 res.push(JSON.parse(JSON.stringify(this.antikingPos[c])));
108 this.undo(move);
109 return res;
110 }
111
112 updateVariables(move)
113 {
114 super.updateVariables(move);
115 const piece = this.getPiece(move.start.x,move.start.y);
116 const c = this.getColor(move.start.x,move.start.y);
117 // Update antiking position
118 if (piece == VariantRules.ANTIKING)
119 {
120 this.antikingPos[c][0] = move.appear[0].x;
121 this.antikingPos[c][1] = move.appear[0].y;
122 }
123 }
124
125 unupdateVariables(move)
126 {
127 super.unupdateVariables(move);
128 const c = this.getColor(move.start.x,move.start.y);
129 if (this.getPiece(move.start.x,move.start.y) == VariantRules.ANTIKING)
130 this.antikingPos[c] = [move.start.x, move.start.y];
131 }
132
133 checkGameEnd()
134 {
135 const color = this.turn;
136 const oppCol = this.getOppCol(color);
137 if (!this.isAttacked(this.kingPos[color], [oppCol])
138 && this.isAttacked(this.antikingPos[color], [oppCol]))
139 {
140 return "1/2";
141 }
142 return color == "w" ? "0-1" : "1-0";
143 }
144
145 // Pieces values (TODO: use Object.assign() + ChessRules.VALUES ?)
146 static get VALUES() {
147 return {
148 'p': 1,
149 'r': 5,
150 'n': 3,
151 'b': 3,
152 'q': 9,
153 'k': 1000,
154 'a': 1000
155 };
156 }
157
158 static GenRandInitFen()
159 {
160 let pieces = { "w": new Array(8), "b": new Array(8) };
161 let antikingPos = { "w": -1, "b": -1 };
162 for (let c of ["w","b"])
163 {
164 let positions = _.range(8);
165
166 // Get random squares for bishops, but avoid corners; because,
167 // if an antiking blocks a cornered bishop, it can never be checkmated
168 let randIndex = 2 * _.random(1,3);
169 const bishop1Pos = positions[randIndex];
170 let randIndex_tmp = 2 * _.random(2) + 1;
171 const bishop2Pos = positions[randIndex_tmp];
172 positions.splice(Math.max(randIndex,randIndex_tmp), 1);
173 positions.splice(Math.min(randIndex,randIndex_tmp), 1);
174
175 randIndex = _.random(5);
176 const knight1Pos = positions[randIndex];
177 positions.splice(randIndex, 1);
178 randIndex = _.random(4);
179 const knight2Pos = positions[randIndex];
180 positions.splice(randIndex, 1);
181
182 randIndex = _.random(3);
183 const queenPos = positions[randIndex];
184 positions.splice(randIndex, 1);
185
186 const rook1Pos = positions[0];
187 const kingPos = positions[1];
188 const rook2Pos = positions[2];
189
190 // Random squares for antikings
191 antikingPos[c] = _.random(7);
192
193 pieces[c][rook1Pos] = 'r';
194 pieces[c][knight1Pos] = 'n';
195 pieces[c][bishop1Pos] = 'b';
196 pieces[c][queenPos] = 'q';
197 pieces[c][kingPos] = 'k';
198 pieces[c][bishop2Pos] = 'b';
199 pieces[c][knight2Pos] = 'n';
200 pieces[c][rook2Pos] = 'r';
201 }
202 const ranks23_black = "pppppppp/" + (antikingPos["w"]>0?antikingPos["w"]:"")
203 + "A" + (antikingPos["w"]<7?7-antikingPos["w"]:"");
204 const ranks23_white = (antikingPos["b"]>0?antikingPos["b"]:"") + "a"
205 + (antikingPos["b"]<7?7-antikingPos["b"]:"") + "/PPPPPPPP";
206 let fen = pieces["b"].join("") + "/" + ranks23_black +
207 "/8/8/" +
208 ranks23_white + "/" + pieces["w"].join("").toUpperCase() +
209 " 1111"; //add flags
210 return fen;
211 }
212 }