9cb076850f4f8d4b12dccd801bda1a1ef661a8fd
[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 }
35
36 // Used by the interface:
37 getReservePpath(color, index)
38 {
39 return color + VariantRules.RESERVE_PIECES[index];
40 }
41
42 // Put an ordering on reserve pieces
43 static get RESERVE_PIECES() {
44 const V = VariantRules;
45 return [V.PAWN,V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN];
46 }
47
48 getReserveMoves([x,y])
49 {
50 const color = this.turn;
51 const p = VariantRules.RESERVE_PIECES[y];
52 if (this.reserve[color][p] == 0)
53 return [];
54 let moves = [];
55 for (let i=0; i<sizeX; i++)
56 {
57 for (let j=0; j<sizeY; j++)
58 {
59 if (this.board[i][j] != VariantRules.EMPTY)
60 {
61 let mv = new Move({
62 appear: [
63 new PiPo({
64 x: i,
65 y: j,
66 c: color,
67 p: p
68 })
69 ]
70 });
71 moves.push(mv);
72 }
73 }
74 }
75 return moves;
76 }
77
78 getPotentialMovesFrom([x,y])
79 {
80 const sizeX = VariantRules.size[0];
81 if (x < sizeX)
82 return super.getPotentialMovesFrom([x,y]);
83 // Reserves, outside of board: x == sizeX
84 return this.getReserveMoves([x,y]);
85 }
86
87 getAllValidMoves()
88 {
89 let moves = super.getAllValidMoves();
90 const color = this.turn;
91 const sizeX = VariantRules.size[0];
92 for (let i=0; i<VariantRules.RESERVE_PIECES.length; i++)
93 moves = moves.concat(this.getReserveMoves([sizeX,i]));
94 return this.filterValid(moves);
95 }
96
97 atLeastOneMove()
98 {
99 if (!super.atLeastOneMove())
100 {
101 const sizeX = VariantRules.size[0];
102 // Scan for reserve moves
103 for (let i=0; i<VariantRules.RESERVE_PIECES.length; i++)
104 {
105 let moves = this.filterValid(this.getReserveMoves([sizeX,i]));
106 if (moves.length > 0)
107 return true;
108 }
109 return false;
110 }
111 return true;
112 }
113
114 updateVariables(move)
115 {
116 super.updateVariables(move);
117 const color = this.turn;
118 if (move.vanish.length==2)
119 this.reserve[color][move.appear[0].p]++;
120 if (move.vanish.length==0)
121 this.reserve[color][move.appear[0].p]--;
122 }
123
124 unupdateVariables(move)
125 {
126 super.unupdateVariables(move);
127 const color = this.turn;
128 if (move.vanish.length==2)
129 this.reserve[color][move.appear[0].p]--;
130 if (move.vanish.length==0)
131 this.reserve[color][move.appear[0].p]++;
132 }
133
134 static get SEARCH_DEPTH() { return 2; } //high branching factor
135
136 getNotation(move)
137 {
138 if (move.vanish.length > 0)
139 return super.getNotation(move);
140 // Rebirth:
141 const piece =
142 (move.appear[0].p != VariantRules.PAWN ? move.appear.p.toUpperCase() : "");
143 const finalSquare =
144 String.fromCharCode(97 + move.end.y) + (VariantRules.size[0]-move.end.x);
145 return piece + "@" + finalSquare;
146 }
147 }