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