1 class CrazyhouseRules
extends ChessRules
5 if (!ChessRules
.IsGoodFen(fen
))
7 const fenParsed
= V
.ParseFen(fen
);
9 if (!fenParsed
.reserve
|| !fenParsed
.reserve
.match(/^[0-9]{10,10}$/))
11 // 6) Check promoted array
12 if (!fenParsed
.promoted
)
14 fenpromoted
= fenParsed
.promoted
;
15 if (fenpromoted
== "-")
16 return true; //no promoted piece on board
17 const squares
= fenpromoted
.split(",");
18 for (let square
of squares
)
20 const c
= V
.SquareToCoords(square
);
21 if (c
.y
< 0 || c
.y
> V
.size
.y
|| isNaN(c
.x
) || c
.x
< 0 || c
.x
> V
.size
.x
)
27 static GenRandInitFen()
29 const fen
= ChessRules
.GenRandInitFen();
30 return fen
.replace(" w 1111", " w 1111 0000000000 -");
35 return super.getFen() + " " + this.getReserveFen() + " " + this.getPromotedFen();
40 let counts
= _
.map(_
.range(10), 0);
41 for (let i
=0; i
<V
.PIECES
.length
; i
++)
43 counts
[i
] = this.reserve
["w"][V
.PIECES
[i
]];
44 counts
[5+i
] = this.reserve
["b"][V
.PIECES
[i
]];
46 return counts
.join("");
52 for (let i
=0; i
<V
.size
.x
; i
++)
54 for (let j
=0; j
<V
.size
.y
; j
++)
56 if (this.promoted
[i
][j
])
57 res
+= V
.CoordsToSquare({x:i
,y:j
});
61 res
= res
.slice(0,-1); //remove last comma
65 setOtherVariables(fen
)
67 super.setOtherVariables(fen
);
68 const fenParsed
= V
.ParseFen(fen
);
69 // Also init reserves (used by the interface to show landable pieces)
74 [V
.PAWN
]: parseInt(fenParsed
.reserve
[0]),
75 [V
.ROOK
]: parseInt(fenParsed
.reserve
[1]),
76 [V
.KNIGHT
]: parseInt(fenParsed
.reserve
[2]),
77 [V
.BISHOP
]: parseInt(fenParsed
.reserve
[3]),
78 [V
.QUEEN
]: parseInt(fenParsed
.reserve
[4]),
82 [V
.PAWN
]: parseInt(fenParsed
.reserve
[5]),
83 [V
.ROOK
]: parseInt(fenParsed
.reserve
[6]),
84 [V
.KNIGHT
]: parseInt(fenParsed
.reserve
[7]),
85 [V
.BISHOP
]: parseInt(fenParsed
.reserve
[8]),
86 [V
.QUEEN
]: parseInt(fenParsed
.reserve
[9]),
89 this.promoted
= doubleArray(V
.size
.x
, V
.size
.y
, false);
90 for (let square
of fenParsd
.promoted
.split(","))
92 const [x
,y
] = V
.SquareToCoords(square
);
93 promoted
[x
][y
] = true;
100 return (i
==V
.size
.x
? "w" : "b");
101 return this.board
[i
][j
].charAt(0);
107 return V
.RESERVE_PIECES
[j
];
108 return this.board
[i
][j
].charAt(1);
111 // Used by the interface:
112 getReservePpath(color
, index
)
114 return color
+ V
.RESERVE_PIECES
[index
];
117 // Ordering on reserve pieces
118 static get RESERVE_PIECES()
120 return [V
.PAWN
,V
.ROOK
,V
.KNIGHT
,V
.BISHOP
,V
.QUEEN
];
123 getReserveMoves([x
,y
])
125 const color
= this.turn
;
126 const p
= V
.RESERVE_PIECES
[y
];
127 if (this.reserve
[color
][p
] == 0)
130 const pawnShift
= (p
==V
.PAWN
? 1 : 0);
131 for (let i
=pawnShift
; i
<V
.size
.x
-pawnShift
; i
++)
133 for (let j
=0; j
<V
.size
.y
; j
++)
135 if (this.board
[i
][j
] == V
.EMPTY
)
147 start: {x:x
, y:y
}, //a bit artificial...
157 getPotentialMovesFrom([x
,y
])
161 // Reserves, outside of board: x == sizeX(+1)
162 return this.getReserveMoves([x
,y
]);
165 return super.getPotentialMovesFrom([x
,y
]);
170 let moves
= super.getAllValidMoves();
171 const color
= this.turn
;
172 for (let i
=0; i
<V
.RESERVE_PIECES
.length
; i
++)
173 moves
= moves
.concat(this.getReserveMoves([V
.size
.x
+(color
=="w"?0:1),i
]));
174 return this.filterValid(moves
);
179 if (!super.atLeastOneMove())
181 const color
= this.turn
;
182 // Search one reserve move
183 for (let i
=0; i
<V
.RESERVE_PIECES
.length
; i
++)
185 let moves
= this.filterValid(
186 this.getReserveMoves([V
.size
.x
+(this.turn
=="w"?0:1), i
]) );
187 if (moves
.length
> 0)
195 updateVariables(move)
197 super.updateVariables(move);
198 if (move.vanish
.length
== 2 && move.appear
.length
== 2)
199 return; //skip castle
200 const color
= this.turn
;
201 if (move.vanish
.length
== 0)
203 this.reserve
[color
][move.appear
[0].p
]--;
206 move.movePromoted
= this.promoted
[move.start
.x
][move.start
.y
];
207 move.capturePromoted
= this.promoted
[move.end
.x
][move.end
.y
]
208 this.promoted
[move.start
.x
][move.start
.y
] = false;
209 this.promoted
[move.end
.x
][move.end
.y
] = move.movePromoted
210 || (move.vanish
[0].p
== V
.PAWN
&& move.appear
[0].p
!= V
.PAWN
);
211 if (move.capturePromoted
)
212 this.reserve
[color
][V
.PAWN
]++;
213 else if (move.vanish
.length
== 2)
214 this.reserve
[color
][move.vanish
[1].p
]++;
217 unupdateVariables(move)
219 super.unupdateVariables(move);
220 if (move.vanish
.length
== 2 && move.appear
.length
== 2)
222 const color
= this.turn
;
223 if (move.vanish
.length
== 0)
225 this.reserve
[color
][move.appear
[0].p
]++;
228 if (move.movePromoted
)
229 this.promoted
[move.start
.x
][move.start
.y
] = true;
230 this.promoted
[move.end
.x
][move.end
.y
] = move.capturePromoted
;
231 if (move.capturePromoted
)
232 this.reserve
[color
][V
.PAWN
]--;
233 else if (move.vanish
.length
== 2)
234 this.reserve
[color
][move.vanish
[1].p
]--;
237 static get SEARCH_DEPTH() { return 2; } //high branching factor
241 let evaluation
= super.evalPosition();
243 for (let i
=0; i
<V
.RESERVE_PIECES
.length
; i
++)
245 const p
= V
.RESERVE_PIECES
[i
];
246 evaluation
+= this.reserve
["w"][p
] * V
.VALUES
[p
];
247 evaluation
-= this.reserve
["b"][p
] * V
.VALUES
[p
];
254 if (move.vanish
.length
> 0)
255 return super.getNotation(move);
258 (move.appear
[0].p
!= V
.PAWN
? move.appear
[0].p
.toUpperCase() : "");
259 return piece
+ "@" + V
.CoordsToSquare(move.end
);
262 getLongNotation(move)
264 if (move.vanish
.length
> 0)
265 return super.getLongNotation(move);
266 return "@" + V
.CoordsToSquare(move.end
);