Attempt to fix promotions on mobile browsers
[vchess.git] / client / src / variants / Extinction.js
CommitLineData
0c3fe8a6
BA
1import { ChessRules } from "@/base_rules";
2
6808d7a1 3export const VariantRules = class ExtinctionRules extends ChessRules {
d7c00f6a
BA
4 static IsGoodPosition(position) {
5 if (!ChessRules.IsGoodPosition(position))
6 return false;
7 // Also check that each piece type is present
8 const rows = position.split("/");
9 let pieces = {};
10 for (let row of rows) {
11 for (let i = 0; i < row.length; i++) {
12 if (isNaN(parseInt(row[i])) && !pieces[row[i]])
13 pieces[row[i]] = true;
14 }
15 }
16 if (Object.keys(pieces).length != 12)
17 return false;
18 return true;
19 }
20
6808d7a1 21 setOtherVariables(fen) {
dac39588
BA
22 super.setOtherVariables(fen);
23 const pos = V.ParseFen(fen).position;
24 // NOTE: no need for safety "|| []", because each piece type must be present
25 // (otherwise game is already over!)
6808d7a1
BA
26 this.material = {
27 w: {
dac39588
BA
28 [V.KING]: pos.match(/K/g).length,
29 [V.QUEEN]: pos.match(/Q/g).length,
30 [V.ROOK]: pos.match(/R/g).length,
31 [V.KNIGHT]: pos.match(/N/g).length,
32 [V.BISHOP]: pos.match(/B/g).length,
33 [V.PAWN]: pos.match(/P/g).length
34 },
6808d7a1 35 b: {
dac39588
BA
36 [V.KING]: pos.match(/k/g).length,
37 [V.QUEEN]: pos.match(/q/g).length,
38 [V.ROOK]: pos.match(/r/g).length,
39 [V.KNIGHT]: pos.match(/n/g).length,
40 [V.BISHOP]: pos.match(/b/g).length,
41 [V.PAWN]: pos.match(/p/g).length
42 }
43 };
44 }
a6abf094 45
6808d7a1
BA
46 getPotentialPawnMoves([x, y]) {
47 let moves = super.getPotentialPawnMoves([x, y]);
dac39588
BA
48 // Add potential promotions into king
49 const color = this.turn;
6808d7a1
BA
50 const shift = color == "w" ? -1 : 1;
51 const lastRank = color == "w" ? 0 : V.size.x - 1;
1221ac47 52
6808d7a1 53 if (x + shift == lastRank) {
dac39588 54 // Normal move
6808d7a1
BA
55 if (this.board[x + shift][y] == V.EMPTY)
56 moves.push(
57 this.getBasicMove([x, y], [x + shift, y], { c: color, p: V.KING })
58 );
dac39588 59 // Captures
6808d7a1
BA
60 if (
61 y > 0 &&
62 this.board[x + shift][y - 1] != V.EMPTY &&
63 this.canTake([x, y], [x + shift, y - 1])
64 ) {
65 moves.push(
66 this.getBasicMove([x, y], [x + shift, y - 1], { c: color, p: V.KING })
67 );
dac39588 68 }
6808d7a1
BA
69 if (
70 y < V.size.y - 1 &&
71 this.board[x + shift][y + 1] != V.EMPTY &&
72 this.canTake([x, y], [x + shift, y + 1])
73 ) {
74 moves.push(
75 this.getBasicMove([x, y], [x + shift, y + 1], { c: color, p: V.KING })
76 );
dac39588
BA
77 }
78 }
1221ac47 79
dac39588
BA
80 return moves;
81 }
1221ac47 82
dac39588 83 // TODO: verify this assertion
6808d7a1 84 atLeastOneMove() {
dac39588
BA
85 return true; //always at least one possible move
86 }
a6abf094 87
6b7b2cf7
BA
88 filterValid(moves) {
89 return moves; //there is no check
dac39588 90 }
a6abf094 91
6808d7a1 92 getCheckSquares() {
dac39588
BA
93 return [];
94 }
a6abf094 95
6808d7a1 96 updateVariables(move) {
dac39588
BA
97 super.updateVariables(move);
98 // Treat the promotion case: (not the capture part)
6808d7a1 99 if (move.appear[0].p != move.vanish[0].p) {
dac39588
BA
100 this.material[move.appear[0].c][move.appear[0].p]++;
101 this.material[move.appear[0].c][V.PAWN]--;
102 }
6808d7a1
BA
103 if (move.vanish.length == 2 && move.appear.length == 1)
104 //capture
dac39588
BA
105 this.material[move.vanish[1].c][move.vanish[1].p]--;
106 }
a6abf094 107
6808d7a1 108 unupdateVariables(move) {
dac39588 109 super.unupdateVariables(move);
6808d7a1 110 if (move.appear[0].p != move.vanish[0].p) {
dac39588
BA
111 this.material[move.appear[0].c][move.appear[0].p]--;
112 this.material[move.appear[0].c][V.PAWN]++;
113 }
6808d7a1 114 if (move.vanish.length == 2 && move.appear.length == 1)
dac39588
BA
115 this.material[move.vanish[1].c][move.vanish[1].p]++;
116 }
a6abf094 117
6808d7a1
BA
118 getCurrentScore() {
119 if (this.atLeastOneMove()) {
6b7b2cf7 120 // Game not over?
dac39588 121 const color = this.turn;
6808d7a1
BA
122 if (
123 Object.keys(this.material[color]).some(p => {
124 return this.material[color][p] == 0;
125 })
126 ) {
127 return this.turn == "w" ? "0-1" : "1-0";
dac39588
BA
128 }
129 return "*";
130 }
a6abf094 131
6808d7a1 132 return this.turn == "w" ? "0-1" : "1-0"; //NOTE: currently unreachable...
dac39588 133 }
a6abf094 134
6808d7a1 135 evalPosition() {
dac39588 136 const color = this.turn;
6808d7a1
BA
137 if (
138 Object.keys(this.material[color]).some(p => {
139 return this.material[color][p] == 0;
140 })
141 ) {
dac39588 142 // Very negative (resp. positive) if white (reps. black) pieces set is incomplete
6808d7a1 143 return (color == "w" ? -1 : 1) * V.INFINITY;
dac39588
BA
144 }
145 return super.evalPosition();
146 }
6808d7a1 147};