26 #include <boost/foreach.hpp>
33 # define SAFE_MOVE_ONLY
45 if (static_feature_set == 0)
56 &MoveGenerator::generateKingEscape<BLACK>,
57 &MoveGenerator::generateTakeBack<BLACK>,
58 &MoveGenerator::generateBreakThreatmate<BLACK>,
59 &MoveGenerator::generateCapture<BLACK>,
61 &MoveGenerator::generateTesuji<BLACK>,
62 &MoveGenerator::generateAll<BLACK>,
66 &MoveGenerator::generateKingEscape<WHITE>,
67 &MoveGenerator::generateTakeBack<WHITE>,
68 &MoveGenerator::generateBreakThreatmate<WHITE>,
69 &MoveGenerator::generateCapture<WHITE>,
71 &MoveGenerator::generateTesuji<WHITE>,
72 &MoveGenerator::generateAll<WHITE>,
76 "INITIAL",
"KING_ESCAPE",
"TAKEBACK",
"BREAK_THREATMATE",
"TACTICAL",
"SENTINEL",
"TESUJI",
"ALL",
78 #ifdef STAT_WIDTH_VS_LIMIT
81 CArray<stat::Average,10> averages;
87 stat::Average& average(
int limit)
94 std::cerr <<
"WidthVSLimit@MoveGenerator\n";
95 for (
int limit=300; limit<300+(int)averages.size()*100; limit+=100) {
96 std::cerr << std::setw(5) << limit <<
" " << average(limit).getAverage() << std::endl;
102 void MoveGenerator::init<osl::eval::ProgressEval>(
104 const NumEffectState&,
bool in_pv, Move hash_move,
bool quiesce);
106 void MoveGenerator::init<osl::eval::ml::OpenMidEndingEval>(
107 int limit,
const SimpleHashRecord *record,
109 const NumEffectState&,
bool in_pv, Move hash_move,
bool quiesce);
134 value_t& val = marker(toIndex(m), pieceIndex(state, m));
144 return marker(toIndex(m), pieceIndex(state, m)) == cur;
165 template <
class EvalT>
169 const NumEffectState& state,
bool in_pv,
Move hash_move,
178 cur_index = tried = 0;
179 progress = eval.progress32();
180 eval_suggestion = eval.suggestMove(state);
183 env.make(state, state.pin(state.turn()), state.pin(
alt(state.turn())),
186 marker.registerMove(state, hash_move);
188 in_quiesce = quiesce;
196 std::cerr <<
"generator " << cur_state <<
" index " << cur_index
197 <<
" limit " << limit <<
" tried " << tried <<
"\n";
198 std::cerr <<
moves.size() <<
"\n"
205 template <osl::Player P>
211 assert(cur_index >=
moves.size());
212 if (cur_state == KING_ESCAPE && record->inCheck()) {
216 if (++cur_state >= TACTICAL_FINISH)
221 if (cur_index <
moves.size()) {
223 return moves[cur_index++];
229 template <osl::Player P>
235 assert(cur_index >=
moves.size());
236 if (++cur_state >= FINISH)
241 if (cur_index <
moves.size()) {
243 return moves[cur_index++];
249 template <osl::Player P>
253 env.history = sstate.
history();
254 if (! record->inCheck())
257 const NumEffectState& state = sstate.
state();
258 const Piece king = state.kingPiece<P>();
259 assert(state.hasEffectAt(
alt(P), king.
square()));
263 size_t last = src.size();
264 for (
size_t i=0; i<last; ++i)
265 if (src[i].hasIgnoredUnpromote<P>())
268 if (src.size() == 1) {
272 BOOST_FOREACH(
Move move, src) {
277 moves.sortByProbability();
282 template <osl::Player P>
286 const NumEffectState& state = sstate.
state();
287 const Move threatmate_move = record->threatmate().threatmateMove(state.turn());
292 marker.registerMove(state, move.
move());
295 template <osl::Player P>
299 using namespace move_action;
301 if (! last_move.isNormal())
303 const Square last_to = last_move.to();
305 const NumEffectState& state = sstate.
state();
308 return quiesceCapture<P>(state, last_to);
313 assert(
moves.empty());
314 BOOST_FOREACH(
Move move, src) {
315 assert(! ShouldPromoteCut::canIgnoreMove<P>(move));
319 && env.my_pin.test(state.pieceOnBoard(move.
from()).number())) {
324 if (prob <=
std::min(200, limit) && marker.registerIfNew(state, move))
327 moves.sortByProbability();
332 template <Player P, Ptype PTYPE>
337 mask_t pieces = state.piecesOnBoard(
alt(P)).template selectBit<PTYPE>()
348 template <osl::Player P>
354 BOOST_FOREACH(
Move move, src) {
355 assert(!ShouldPromoteCut::canIgnoreMove<P>(move));
356 const int see = PieceEval::computeDiffAfterMoveForRP(state, move);
364 BOOST_FOREACH(
Move move, src) {
365 assert(! ShouldPromoteCut::canIgnoreMove<P>(move));
366 #ifdef SAFE_MOVE_ONLY
368 && env.my_pin.test(state.pieceOnBoard(move.
from()).number())) {
375 if (prob <= 200 && marker.registerIfNew(state, move)) {
382 template <osl::Player P>
386 using namespace move_action;
388 const NumEffectState& state = sstate.
state();
392 makeCapture<P,LANCE>(state, src);
393 makeCapture<P,BISHOP>(state, src);
394 makeCapture<P,ROOK>(state, src);
396 makeCapture<P,KNIGHT>(state, src);
397 makeCapture<P,SILVER>(state, src);
398 makeCapture<P,GOLD>(state, src);
400 makeCaptureOtherThanPawn<P>(state, src);
402 addCapture<P>(state, env, src);
405 template <osl::Player P>
409 const NumEffectState& state = sstate.
state();
410 if (! state.inCheck() && eval_suggestion.isNormal()
411 && marker.registerIfNew(state, eval_suggestion)) {
412 assert(sstate.
state().isValidMove(eval_suggestion));
419 makeCapture<P,PAWN>(state, src);
420 addCapture<P>(state, env, src);
426 template <osl::Player P>
433 BOOST_FOREACH(
Move move, moves) {
434 assert(!ShouldPromoteCut::canIgnoreAndNotDrop<P>(move));
435 int see = PieceEval::computeDiffAfterMoveForRP(state, move);
440 this->moves.sortByProbabilityReverse();
444 template <osl::Player P>
452 const NumEffectState& state = sstate.
state();
453 MoveLogProbVector all;
455 #ifdef STAT_WIDTH_VS_LIMIT
456 const size_t moves_size_before =
moves.size();
459 assert(!ShouldPromoteCut::canIgnoreAndNotDrop<P>(move.
move()));
462 if (this->limit >= 400) {
463 using namespace move_classifier;
465 || (in_pv && MoveAdaptor<Check<P> >::isMember(state, move.
move())))
468 if (limit <= this->limit
469 && marker.registerIfNew(state, move.
move())) {
472 assert(! (env.my_pin.test(state.pieceOnBoard(m.
from()).number())
474 assert(! (m.
ptype() ==
KING && state.hasEffectAt(
alt(P), m.
to())));
480 #ifdef STAT_WIDTH_VS_LIMIT
481 Width_VS_Limit.average(limit).add(
moves.size() - moves_size_before);
490 assert(
moves.size() == 0);
492 for (
int i=0; i<FINISH; ++i) {
497 bool generated =
moves.size();
499 if (i == KING_ESCAPE && generated)
506 template <osl::Player P>
508 #if (defined __GNUC__) && (! defined GPSONE) && (! defined GPSUSIONE)
514 using namespace move_classifier;
516 m.
validMove(); m = nextTacticalMove<P>(state)) {
517 assert(state.
state().isValidMove(m.move()));
518 if (ConditionAdaptor<SafeMove>::isMember(state.
state(), m.move()))
522 m = nextMove<P>(state)) {
523 assert(state.
state().isValidMove(m.move()));
524 if (ConditionAdaptor<SafeMove>::isMember(state.
state(), m.move()))
533 generateAll<BLACK>(state,
out);
535 generateAll<WHITE>(state,
out);