1 class CrazyhouseRules
extends ChessRules
5 super.initVariables(fen
);
6 // Also init reserves (used by the interface to show landing pieces)
7 const V
= VariantRules
;
27 const [sizeX
,sizeY
] = VariantRules
.size
;
28 this.promoted
= doubleArray(sizeX
, sizeY
, false);
29 // May be a continuation: adjust numbers of pieces in reserve + promoted pieces
30 this.moves
.forEach(m
=> { this.updateVariables(m
); });
35 const sizeX
= VariantRules
.size
[0];
37 return (i
==sizeX
? "w" : "b");
38 return this.board
[i
][j
].charAt(0);
42 const sizeX
= VariantRules
.size
[0];
44 return VariantRules
.RESERVE_PIECES
[j
];
45 return this.board
[i
][j
].charAt(1);
48 // Used by the interface:
49 getReservePpath(color
, index
)
51 return color
+ VariantRules
.RESERVE_PIECES
[index
];
54 // Put an ordering on reserve pieces
55 static get RESERVE_PIECES() {
56 const V
= VariantRules
;
57 return [V
.PAWN
,V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
];
60 getReserveMoves([x
,y
])
62 const color
= this.turn
;
63 const p
= VariantRules
.RESERVE_PIECES
[y
];
64 if (this.reserve
[color
][p
] == 0)
67 const [sizeX
,sizeY
] = VariantRules
.size
;
68 const pawnShift
= (p
==VariantRules
.PAWN
? 1 : 0);
69 for (let i
=pawnShift
; i
<sizeX
-pawnShift
; i
++)
71 for (let j
=0; j
<sizeY
; j
++)
73 if (this.board
[i
][j
] == VariantRules
.EMPTY
)
85 start: {x:x
, y:y
}, //a bit artificial...
95 getPotentialMovesFrom([x
,y
])
97 const sizeX
= VariantRules
.size
[0];
100 // Reserves, outside of board: x == sizeX
101 return this.getReserveMoves([x
,y
]);
104 return super.getPotentialMovesFrom([x
,y
]);
109 let moves
= super.getAllValidMoves();
110 const color
= this.turn
;
111 const sizeX
= VariantRules
.size
[0];
112 for (let i
=0; i
<VariantRules
.RESERVE_PIECES
.length
; i
++)
113 moves
= moves
.concat(this.getReserveMoves([sizeX
+(color
=="w"?0:1),i
]));
114 return this.filterValid(moves
);
119 if (!super.atLeastOneMove())
121 const sizeX
= VariantRules
.size
[0];
122 // Scan for reserve moves
123 for (let i
=0; i
<VariantRules
.RESERVE_PIECES
.length
; i
++)
125 let moves
= this.filterValid(this.getReserveMoves([sizeX
,i
]));
126 if (moves
.length
> 0)
134 updateVariables(move)
136 super.updateVariables(move);
137 if (move.vanish
.length
== 2 && move.appear
.length
== 2)
138 return; //skip castle
139 const color
= this.turn
;
140 const V
= VariantRules
;
141 // Three types of move:
142 // 1. Rebirth: just update material
144 // a. check if a promoted piece is moving
145 // b. check if it's a promotion (mutually exclusive)
147 // a. check if a promoted piece is captured (and mark move)
148 // b. check if a promoted piece is moving
149 // c. check if it's a promotion (mutually exclusive with b)
150 if (move.vanish
.length
== 0)
151 this.reserve
[color
][move.appear
[0].p
]--;
152 else if (move.vanish
.length
== 1)
154 if (this.promoted
[move.start
.x
][move.start
.y
])
156 this.promoted
[move.start
.x
][move.start
.y
] = false;
157 this.promoted
[move.end
.x
][move.end
.y
] = true;
159 else if (move.vanish
[0].p
== V
.PAWN
&& move.appear
[0].p
!= V
.PAWN
)
160 this.promoted
[move.end
.x
][move.end
.y
] = true;
164 if (this.promoted
[move.end
.x
][move.end
.y
])
166 move.capturePromoted
= true; //required for undo
167 this.reserve
[color
][VariantRules
.PAWN
]++;
168 this.promoted
[move.end
.x
][move.end
.y
] = false;
171 this.reserve
[color
][move.vanish
[1].p
]++;
172 if (this.promoted
[move.start
.x
][move.start
.y
])
174 this.promoted
[move.start
.x
][move.start
.y
] = false;
175 this.promoted
[move.end
.x
][move.end
.y
] = true;
177 else if (move.vanish
[0].p
== V
.PAWN
&& move.appear
[0].p
!= V
.PAWN
)
178 this.promoted
[move.end
.x
][move.end
.y
] = true;
182 unupdateVariables(move)
184 super.unupdateVariables(move);
185 const color
= this.turn
;
186 const V
= VariantRules
;
187 if (move.vanish
.length
== 0)
188 this.reserve
[color
][move.appear
[0].p
]++;
189 else if (move.vanish
.length
== 1)
191 if (this.promoted
[move.end
.x
][move.end
.y
])
193 this.promoted
[move.end
.x
][move.end
.y
] = false;
194 if (move.vanish
[0].p
!= V
.PAWN
|| move.appear
[0].p
== V
.PAWN
)
196 // Not a promotion (= promoted piece creation)
197 this.promoted
[move.start
.x
][move.start
.y
] = true;
203 if (this.promoted
[move.end
.x
][move.end
.y
])
205 this.promoted
[move.end
.x
][move.end
.y
] = !!move.capturePromoted
;
206 if (move.vanish
[0].p
!= V
.PAWN
|| move.appear
[0].p
== V
.PAWN
)
207 this.promoted
[move.start
.x
][move.start
.y
] = true;
209 // Un-update material:
210 if (move.capturePromoted
)
211 this.reserve
[color
][VariantRules
.PAWN
]--;
213 this.reserve
[color
][move.vanish
[1].p
]--;
217 static get SEARCH_DEPTH() { return 2; } //high branching factor
221 let evaluation
= super.evalPosition();
223 for (let i
=0; i
<VariantRules
.RESERVE_PIECES
.length
; i
++)
225 const p
= VariantRules
.RESERVE_PIECES
[i
];
226 evaluation
+= this.reserve
["w"][p
] * VariantRules
.VALUES
[p
];
227 evaluation
-= this.reserve
["b"][p
] * VariantRules
.VALUES
[p
];
234 if (move.vanish
.length
> 0)
235 return super.getNotation(move);
238 (move.appear
[0].p
!= VariantRules
.PAWN
? move.appear
[0].p
.toUpperCase() : "");
240 String
.fromCharCode(97 + move.end
.y
) + (VariantRules
.size
[0]-move.end
.x
);
241 return piece
+ "@" + finalSquare
;
244 getLongNotation(move)
246 if (move.vanish
.length
> 0)
247 return super.getLongNotation(move);
249 String
.fromCharCode(97 + move.end
.y
) + (VariantRules
.size
[0]-move.end
.x
);
250 return "@" + finalSquare
;