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