- // Next phase
- phasePtr++;
- switch (*phasePtr) {
-
- case PH_NULL_MOVE:
- return MOVE_NULL;
-
- case PH_TT_MOVES:
- movesPicked = 0; // This is used as index to ttMoves[]
- break;
-
- case PH_GOOD_CAPTURES:
- numOfMoves = generate_captures(pos, moves);
- score_captures();
- std::sort(moves, moves + numOfMoves);
- movesPicked = 0;
- break;
-
- case PH_KILLERS:
- movesPicked = 0; // This is used as index to killers[]
- break;
-
- case PH_NONCAPTURES:
- numOfMoves = generate_noncaptures(pos, moves);
- score_noncaptures();
- std::sort(moves, moves + numOfMoves);
- movesPicked = 0;
- break;
-
- case PH_BAD_CAPTURES:
- // Bad captures SEE value is already calculated so just sort them
- // to get SEE move ordering.
- std::sort(badCaptures, badCaptures + numOfBadCaptures);
- movesPicked = 0;
- break;
-
- case PH_EVASIONS:
- assert(pos.is_check());
- numOfMoves = generate_evasions(pos, moves, pinned);
- score_evasions();
- std::sort(moves, moves + numOfMoves);
- movesPicked = 0;
- break;
-
- case PH_QCAPTURES:
- numOfMoves = generate_captures(pos, moves);
- score_captures();
- std::sort(moves, moves + numOfMoves);
- movesPicked = 0;
- break;
-
- case PH_QCHECKS:
- // Perhaps we should order moves move here? FIXME
- numOfMoves = generate_non_capture_checks(pos, moves, dc);
- movesPicked = 0;
- break;
-
- case PH_STOP:
- return MOVE_NONE;
-
- default:
- assert(false);
- return MOVE_NONE;
- }
+ // Skip TT move if is not a capture or a promotion, this avoids qsearch
+ // tree explosion due to a possible perpetual check or similar rare cases
+ // when TT table is full.
+ if (ttm && !pos.is_capture_or_promotion(ttm))
+ ttm = MOVE_NONE;