9558fe4bf1b5048b251964eaea34c3aa07c03ed5
[vchess.git] / public / javascripts / variants / Crazyhouse.js
1 class CrazyhouseRules extends ChessRules
2 {
3 initVariables(fen)
4 {
5 super.initVariables(fen);
6 // Also init reserves (used by the interface to show landing pieces)
7 const V = VariantRules;
8 this.reserve =
9 {
10 "w":
11 {
12 [V.PAWN]: 0,
13 [V.ROOK]: 0,
14 [V.KNIGHT]: 0,
15 [V.BISHOP]: 0,
16 [V.QUEEN]: 0,
17 },
18 "b":
19 {
20 [V.PAWN]: 0,
21 [V.ROOK]: 0,
22 [V.KNIGHT]: 0,
23 [V.BISHOP]: 0,
24 [V.QUEEN]: 0,
25 }
26 };
27 // May be a continuation: adjust numbers of pieces according to captures + rebirths
28 this.moves.forEach(m => {
29 if (m.vanish.length == 2)
30 this.reserve[m.appear[0].c][m.vanish[1].p]++;
31 else if (m.vanish.length == 0)
32 this.reserve[m.appear[0].c][m.appear[0].p]--;
33 });
34 // TODO: keep track of promoted pawns ==> give a pawn if captured.
35 }
36
37 getColor(i,j)
38 {
39 const sizeX = VariantRules.size[0];
40 if (i >= sizeX)
41 return (i==sizeX ? "w" : "b");
42 return this.board[i][j].charAt(0);
43 }
44 getPiece(i,j)
45 {
46 const sizeX = VariantRules.size[0];
47 if (i >= sizeX)
48 return VariantRules.RESERVE_PIECES[j];
49 return this.board[i][j].charAt(1);
50 }
51
52 // Used by the interface:
53 getReservePpath(color, index)
54 {
55 return color + VariantRules.RESERVE_PIECES[index];
56 }
57
58 // Put an ordering on reserve pieces
59 static get RESERVE_PIECES() {
60 const V = VariantRules;
61 return [V.PAWN,V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN];
62 }
63
64 getReserveMoves([x,y])
65 {
66 const color = this.turn;
67 const p = VariantRules.RESERVE_PIECES[y];
68 if (this.reserve[color][p] == 0)
69 return [];
70 let moves = [];
71 const [sizeX,sizeY] = VariantRules.size;
72 const pawnShift = (p==VariantRules.PAWN ? 1 : 0);
73 for (let i=pawnShift; i<sizeX-pawnShift; i++)
74 {
75 for (let j=0; j<sizeY; j++)
76 {
77 if (this.board[i][j] == VariantRules.EMPTY)
78 {
79 let mv = new Move({
80 appear: [
81 new PiPo({
82 x: i,
83 y: j,
84 c: color,
85 p: p
86 })
87 ],
88 vanish: [],
89 start: {x:sizeX, y:y}, //a bit artificial...
90 end: {x:i, y:j}
91 });
92 moves.push(mv);
93 }
94 }
95 }
96 return moves;
97 }
98
99 getPotentialMovesFrom([x,y])
100 {
101 const sizeX = VariantRules.size[0];
102 if (x < sizeX)
103 return super.getPotentialMovesFrom([x,y]);
104 // Reserves, outside of board: x == sizeX
105 return this.getReserveMoves([x,y]);
106 }
107
108 getAllValidMoves()
109 {
110 let moves = super.getAllValidMoves();
111 const color = this.turn;
112 const sizeX = VariantRules.size[0];
113 for (let i=0; i<VariantRules.RESERVE_PIECES.length; i++)
114 moves = moves.concat(this.getReserveMoves([sizeX,i]));
115 return this.filterValid(moves);
116 }
117
118 atLeastOneMove()
119 {
120 if (!super.atLeastOneMove())
121 {
122 const sizeX = VariantRules.size[0];
123 // Scan for reserve moves
124 for (let i=0; i<VariantRules.RESERVE_PIECES.length; i++)
125 {
126 let moves = this.filterValid(this.getReserveMoves([sizeX,i]));
127 if (moves.length > 0)
128 return true;
129 }
130 return false;
131 }
132 return true;
133 }
134
135 updateVariables(move)
136 {
137 super.updateVariables(move);
138 const color = this.turn;
139 if (move.vanish.length==2)
140 this.reserve[color][move.vanish[1].p]++;
141 if (move.vanish.length==0)
142 this.reserve[color][move.appear[0].p]--;
143 }
144
145 unupdateVariables(move)
146 {
147 super.unupdateVariables(move);
148 const color = this.turn;
149 if (move.vanish.length==2)
150 this.reserve[color][move.vanish[1].p]--;
151 if (move.vanish.length==0)
152 this.reserve[color][move.appear[0].p]++;
153 }
154
155 static get SEARCH_DEPTH() { return 2; } //high branching factor
156
157 getNotation(move)
158 {
159 if (move.vanish.length > 0)
160 return super.getNotation(move);
161 // Rebirth:
162 const piece =
163 (move.appear[0].p != VariantRules.PAWN ? move.appear[0].p.toUpperCase() : "");
164 const finalSquare =
165 String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x);
166 return piece + "@" + finalSquare;
167 }
168 }