Move MoveGen::next() { Move res; loop: switch( *phPtr ) { case mpHash: res = killer->hashMove; phPtr++; if ( !res || !(board.inCheck() ? board.isLegal<1,0>( res, pins() ) : board.isLegal<0,0>( res, pins() ) ) ) goto loop; genMoves[ genMoveCount++ ] = res; break; case mpKiller1: res = killer->killers[0]; phPtr++; if ( !res || alreadyGenerated(res) || !(board.inCheck() ? board.isLegal<1,1>( res, pins() ) : board.isLegal<0,1>( res, pins() ) ) ) goto loop; genMoves[ genMoveCount++ ] = res; break; case mpKiller2: res = killer->killers[1]; phPtr++; if ( !res || alreadyGenerated(res) || !(board.inCheck() ? board.isLegal<1,1>( res, pins() ) : board.isLegal<0,1>( res, pins() ) ) ) goto loop; genMoves[ genMoveCount++ ] = res; break; case mpCapNoSort: count = generateCaptures( board, moveBuf ); index = 0; phPtr++; goto loop; break; case mpCap: count = generateCaptures( board, moveBuf ); index = badCapCount = 0; scoreCaptures(); phPtr++; goto loop; break; case mpBadCap: index = 0; phPtr++; goto loop; break; case mpQCap: count = generateCaptures( board, moveBuf, 0 ); index = 0; scoreCaptures(); phPtr++; goto loop; break; case mpQChecks: count = board.turn() == ctWhite ? generateChecks< ctWhite >( moveBuf ) : generateChecks< ctBlack >( moveBuf ); scoreChecks(); index = 0; phPtr++; goto loop; break; case mpCastling: assert( board.canCastle() ); index = 0; count = board.turn() == ctWhite ? generateCastling< ctWhite >( board, moveBuf ) : generateCastling< ctBlack >( board, moveBuf ); phPtr++; goto loop; break; case mpQuietNoSort: count = generateQuiet( board, moveBuf ); index = 0; phPtr++; goto loop; break; case mpQuiet: count = generateQuiet( board, moveBuf ); scoreQuiet(); index = 0; phPtr++; goto loop; break; case mpEvasNoSort: count = generateEvasions( board, moveBuf ); index = 0; phPtr++; goto loop; break; case mpEvas: count = generateEvasions( board, moveBuf ); scoreEvasions(); index = 0; phPtr++; goto loop; break; case mpCapBuffer: // here we'll ocassionally move to badcaps so it's different do { loopcap: if ( index >= count ) { phPtr++; goto loop; } res = moveBuf[ index++ ]; if ( alreadyGenerated(res) ) goto loopcap; // do fast(sign) see if ( board.see<1>(res) < 0 ) { // bad capture detected assert( badCapCount < maxCaptures ); badCaps[ badCapCount++ ] = res; goto loopcap; } } while( !board.pseudoIsLegal<0>( res, pin ) ); break; case mpQCapBuffer: // here we'll ocassionally move to badcaps so it's different do { qloopcap: if ( index >= count ) { phPtr++; goto loop; } res = moveBuf[ index++ ]; if ( alreadyGenerated(res) ) goto qloopcap; // do fast(sign) see if ( board.see<1>( res ) < 0 ) // bad capture detected goto qloopcap; } while( !board.pseudoIsLegal<0>( res, pin ) ); break; case mpCastlingBuffer: if ( index >= count ) { phPtr++; goto loop; } res = moveBuf[ index++ ]; if ( alreadyGenerated(res) ) goto loop; break; case mpCastlingBufferLegal: if ( index >= count ) { phPtr++; goto loop; } res = moveBuf[ index++ ]; break; case mpEvasBuffer: do { if ( index >= count ) { phPtr++; goto loop; } res = moveBuf[ index++ ]; } while ( alreadyGenerated(res) || !board.pseudoIsLegal<1>( res, pin ) ); break; case mpEvasBufferLegal: do { if ( index >= count ) { phPtr++; goto loop; } res = moveBuf[ index++ ]; } while ( !board.pseudoIsLegal<1>( res, pin ) ); break; case mpBufferLegal: do { if ( index >= count ) { phPtr++; goto loop; } res = moveBuf[ index++ ]; } while ( !board.pseudoIsLegal<0>( res, pin ) ); break; case mpQuietBuffer: do { if ( index >= count ) { phPtr++; goto loop; } res = moveBuf[ index++ ]; } while ( alreadyGenerated(res) || !board.pseudoIsLegal<0>( res, pin ) ); break; case mpQChecksBuffer: do { checksloop: if ( index >= count ) { phPtr++; goto loop; } res = moveBuf[ index++ ]; if ( alreadyGenerated(res) ) goto checksloop; if ( MovePack::isCastling(res) ) break; if ( board.see<1>( res ) < 0 ) continue; // skip bad see checks } while ( !board.pseudoIsLegal<0>( res, pin ) ); assert( board.isCheck( res, dcMask ) ); break; case mpBadCapBuffer: do { if ( index >= badCapCount ) { phPtr++; goto loop; } res = badCaps[ index++ ]; } while( alreadyGenerated(res) || !board.pseudoIsLegal<0>( res, pin ) ); break; default: //case mpDone: res = mcNone; break; } return res & mmNoScore; // remove score }
void MovePicker::goNextPhase() { currMove_ = firstMove(); // legalMoves_[0] は番兵 ++phase_; switch (phase()) { case PH_TacticalMoves0: case PH_TacticalMoves1: lastMove_ = generateMoves<CapturePlusPro>(currMove(), pos()); scoreCaptures(); return; case PH_Killers: currMove_ = killerMoves_; lastMove_ = currMove() + 2; return; case PH_NonTacticalMoves0: lastMove_ = generateMoves<NonCaptureMinusPro>(currMove(), pos()); scoreNonCapturesMinusPro<false>(); currMove_ = lastMove(); lastNonCapture_ = lastMove_ = generateMoves<Drop>(currMove(), pos()); scoreNonCapturesMinusPro<true>(); currMove_ = firstMove(); lastMove_ = std::partition(currMove(), lastNonCapture(), HasPositiveScore()); // 要素数は10個くらいまでであることが多い。要素数が少ないので、insertionSort() を使用する。 insertionSort<MoveStack*, true>(currMove(), lastMove()); return; case PH_NonTacticalMoves1: currMove_ = lastMove(); lastMove_ = lastNonCapture(); if (static_cast<Depth>(3 * OnePly) <= depth_) { std::sort(currMove(), lastMove(), std::greater<MoveStack>()); } return; case PH_BadCaptures: currMove_ = legalMoves_ + MaxLegalMoves - 1; lastMove_ = endBadCaptures_; return; case PH_Evasions: case PH_QEvasions: lastMove_ = generateMoves<Evasion>(currMove(), pos()); if (currMove() + 1 < lastMove()) { scoreEvasions(); } return; case PH_QCaptures0: lastMove_ = generateMoves<CapturePlusPro>(firstMove(), pos()); scoreCaptures(); return; case PH_QCaptures1: lastMove_ = generateMoves<Recapture>(firstMove(), pos(), recaptureSquare_); scoreCaptures(); return; case EvasionSearch: case QSearch: case QEvasionSearch: case QRecapture: case ProbCut: // これが無いと、MainSearch の後に EvasionSearch が始まったりしてしまう。 phase_ = PH_Stop; case PH_Stop: lastMove_ = currMove() + 1; return; default: UNREACHABLE; } }