void MovePicker::score_evasions() { // Try good captures ordered by MVV/LVA, then non-captures if // destination square is not under attack, ordered by history // value, and at the end bad-captures and non-captures with a // negative SEE. This last group is ordered by the SEE score. Move m; int seeScore; // Skip if we don't have at least two moves to order if (lastMove < moves + 2) return; for (MoveStack* cur = moves; cur != lastMove; cur++) { m = cur->move; if ((seeScore = pos.see_sign(m)) < 0) cur->score = seeScore - History::MaxValue; // Be sure we are at the bottom else if (pos.is_capture(m)) #if defined(NANOHA) cur->score = piece_value_midgame(pos.piece_on(move_to(m))) - type_of(move_piece(m)) + History::MaxValue; #else cur->score = piece_value_midgame(pos.piece_on(move_to(m))) - type_of(pos.piece_on(move_from(m))) + History::MaxValue; #endif else #if defined(NANOHA) { Piece piece = is_promotion(m) ? Piece(move_piece(m) | PROMOTED) : move_piece(m); cur->score = H.value(piece, move_to(m)); } #else cur->score = H.value(pos.piece_on(move_from(m)), move_to(m)); #endif }
void MovePicker::score_captures() { // Winning and equal captures in the main search are ordered by MVV/LVA. // Suprisingly, this appears to perform slightly better than SEE based // move ordering. The reason is probably that in a position with a winning // capture, capturing a more valuable (but sufficiently defended) piece // first usually doesn't hurt. The opponent will have to recapture, and // the hanging piece will still be hanging (except in the unusual cases // where it is possible to recapture with the hanging piece). Exchanging // big pieces before capturing a hanging piece probably helps to reduce // the subtree size. // In main search we want to push captures with negative SEE values to // badCaptures[] array, but instead of doing it now we delay till when // the move has been picked up in pick_move_from_list(), this way we save // some SEE calls in case we get a cutoff (idea from Pablo Vazquez). Move m; // Use MVV/LVA ordering for (MoveStack* cur = moves; cur != lastMove; cur++) { m = cur->move; cur->score = piece_value_midgame(pos.piece_on(move_to(m))) - type_of(pos.piece_on(move_from(m))); if (is_promotion(m)) #if defined(NANOHA) cur->score += piece_value_midgame(Piece(move_piece(m) | PROMOTED)); #else cur->score += piece_value_midgame(Piece(promotion_piece_type(m))); #endif } }
static int handle_beta_extension(struct node *node, move m, int value) { if (!node->common->sd.settings.use_beta_extensions) return value; if (value >= node->beta && !node[-1].is_in_null_move_search && is_in_check(node[1].pos) && value < mate_value && node->depth > PLY && node->depth < 10 * PLY && node->mo->picked_count > 1 && !is_capture(m) && !is_promotion(m) && mtype(m) != mt_castle_kingside && mtype(m) != mt_castle_queenside) { node[1].alpha = -node->beta; node[1].beta = -node->alpha; node[1].depth = node->depth; return negamax_child(node); } else { return value; } }
static char* print_san_promotion(move m, char *str) { if (is_promotion(m)) { *str++ = '='; *str++ = toupper((unsigned char)piece_to_char(mresultp(m))); } return str; }
static bool pmove_match(uint16_t polyglot_move, move m, bool flip) { if (flip) m = flip_m(m); if (pmfrom(polyglot_move) != mfrom(m) || pmto(polyglot_move) != mto(m)) return false; if (is_promotion(m)) return pmpromotion(polyglot_move) == mresultp(m); else return pmpromotion(polyglot_move) == 0; }
void MovePicker::score_noncaptures() { Move m; for (MoveStack* cur = moves; cur != lastMove; cur++) { m = cur->move; #if defined(NANOHA) assert(m != MOVE_NULL); Piece piece = is_promotion(m) ? Piece(move_piece(m) | PROMOTED) : move_piece(m); cur->score = H.value(piece, move_to(m)); #else Square from = move_from(m); cur->score = H.value(pos.piece_on(from), move_to(m)); #endif } }