//Returns pawn evaluation score int Get_Pawn_Eval_Score(BOARD_STRUCT *board) { int sq64; int score = 0; int hash_score = 0; const U64 white_pawns = board->piece_bitboards[wP]; const U64 black_pawns = board->piece_bitboards[bP]; const U64 all_pawns = white_pawns | black_pawns; //White pawns U64 temp = white_pawns; while(temp) //loop through all white pawns { sq64 = pop_1st_bit(&temp); //pawn location in 64 square array //if no black pawns in passed mask area if ((black_pawns & white_passed_masks[sq64]) == 0) { score += passed_pawn_rank_bonus[GET_RANK(sq64)]; //If protected by king if (king_attack_masks[sq64] & board->piece_bitboards[wK]) score += PROTECTED_PASSER_SCORE; } //if no white pawns in isolated mask area if ((white_pawns & isolated_masks[sq64]) == 0) score += ISOLATED_PAWN_PENALTY; //If a white pawn is found in the same file if ((white_pawns & doubled_masks[sq64]) != 0) score += DOUBLED_PAWN_PENALTY; } //Black pawns temp = black_pawns; while (temp) //loop through all black pawns { sq64 = pop_1st_bit(&temp); //pawn location in 64 square array //if no white pawns in passed mask area if ((white_pawns & black_passed_masks[sq64]) == 0) { score -= passed_pawn_rank_bonus[RANK_8 - GET_RANK(sq64)]; //If protected by king if (king_attack_masks[sq64] & board->piece_bitboards[bK]) score -= PROTECTED_PASSER_SCORE; } //if no black pawns in isolated mask area if ((black_pawns & isolated_masks[sq64]) == 0) score -= ISOLATED_PAWN_PENALTY; //If a black pawn is found in the same file if ((black_pawns & doubled_masks[sq64]) != 0) score -= DOUBLED_PAWN_PENALTY; } return score; }
MoveStack* generate_non_capture_checks(const Position& pos, MoveStack* mlist) { assert(pos.is_ok()); assert(!pos.is_check()); Bitboard b, dc; Square from; Color us = pos.side_to_move(); Square ksq = pos.king_square(opposite_color(us)); assert(pos.piece_on(ksq) == piece_of_color_and_type(opposite_color(us), KING)); // Discovered non-capture checks b = dc = pos.discovered_check_candidates(us); while (b) { from = pop_1st_bit(&b); switch (pos.type_of_piece_on(from)) { case PAWN: /* Will be generated togheter with pawns direct checks */ break; case KNIGHT: mlist = generate_discovered_checks<KNIGHT>(pos, mlist, from); break; case BISHOP: mlist = generate_discovered_checks<BISHOP>(pos, mlist, from); break; case ROOK: mlist = generate_discovered_checks<ROOK>(pos, mlist, from); break; case KING: mlist = generate_discovered_checks<KING>(pos, mlist, from); break; default: assert(false); break; } } // Direct non-capture checks mlist = generate_direct_checks<PAWN>(pos, mlist, us, dc, ksq); mlist = generate_direct_checks<KNIGHT>(pos, mlist, us, dc, ksq); mlist = generate_direct_checks<BISHOP>(pos, mlist, us, dc, ksq); mlist = generate_direct_checks<ROOK>(pos, mlist, us, dc, ksq); return generate_direct_checks<QUEEN>(pos, mlist, us, dc, ksq); }
MoveStack* generate<MV_QUIET_CHECK>(const Position& pos, MoveStack* mlist) { assert(!pos.in_check()); Color us = pos.side_to_move(); CheckInfo ci(pos); Bitboard dc = ci.dcCandidates; while (dc) { Square from = pop_1st_bit(&dc); PieceType pt = type_of(pos.piece_on(from)); if (pt == PAWN) continue; // Will be generated togheter with direct checks Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces(); if (pt == KING) b &= ~PseudoAttacks[QUEEN][ci.ksq]; SERIALIZE(b); } mlist = (us == WHITE ? generate_pawn_moves<WHITE, MV_QUIET_CHECK>(pos, mlist, ci.dcCandidates, ci.ksq) : generate_pawn_moves<BLACK, MV_QUIET_CHECK>(pos, mlist, ci.dcCandidates, ci.ksq)); mlist = generate_direct_checks<KNIGHT>(pos, mlist, us, ci); mlist = generate_direct_checks<BISHOP>(pos, mlist, us, ci); mlist = generate_direct_checks<ROOK>(pos, mlist, us, ci); mlist = generate_direct_checks<QUEEN>(pos, mlist, us, ci); if (pos.can_castle(us)) { mlist = generate_castle<KING_SIDE, true>(pos, mlist, us); mlist = generate_castle<QUEEN_SIDE, true>(pos, mlist, us); } return mlist; }
MoveStack* generate<MV_EVASION>(const Position& pos, MoveStack* mlist) { assert(pos.in_check()); Bitboard b, target; Square from, checksq; int checkersCnt = 0; Color us = pos.side_to_move(); Square ksq = pos.king_square(us); Bitboard sliderAttacks = 0; Bitboard checkers = pos.checkers(); assert(checkers); // Find squares attacked by slider checkers, we will remove them from the king // evasions so to skip known illegal moves avoiding useless legality check later. b = checkers; do { checkersCnt++; checksq = pop_1st_bit(&b); assert(color_of(pos.piece_on(checksq)) == ~us); switch (type_of(pos.piece_on(checksq))) { case BISHOP: sliderAttacks |= PseudoAttacks[BISHOP][checksq]; break; case ROOK: sliderAttacks |= PseudoAttacks[ROOK][checksq]; break; case QUEEN: // If queen and king are far or not on a diagonal line we can safely // remove all the squares attacked in the other direction becuase are // not reachable by the king anyway. if (between_bb(ksq, checksq) || !(PseudoAttacks[BISHOP][checksq] & ksq)) sliderAttacks |= PseudoAttacks[QUEEN][checksq]; // Otherwise we need to use real rook attacks to check if king is safe // to move in the other direction. For example: king in B2, queen in A1 // a knight in B1, and we can safely move to C1. else sliderAttacks |= PseudoAttacks[BISHOP][checksq] | pos.attacks_from<ROOK>(checksq); default: break; } } while (b); // Generate evasions for king, capture and non capture moves b = pos.attacks_from<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks; from = ksq; SERIALIZE(b); // Generate evasions for other pieces only if not under a double check if (checkersCnt > 1) return mlist; // Blocking evasions or captures of the checking piece target = between_bb(checksq, ksq) | checkers; mlist = (us == WHITE ? generate_pawn_moves<WHITE, MV_EVASION>(pos, mlist, target) : generate_pawn_moves<BLACK, MV_EVASION>(pos, mlist, target)); mlist = generate_moves<KNIGHT>(pos, mlist, us, target); mlist = generate_moves<BISHOP>(pos, mlist, us, target); mlist = generate_moves<ROOK>(pos, mlist, us, target); return generate_moves<QUEEN>(pos, mlist, us, target); }
MoveStack* generate_evasions(const Position& pos, MoveStack* mlist) { assert(pos.is_ok()); assert(pos.is_check()); Bitboard b, target; Square from, checksq; int checkersCnt = 0; Color us = pos.side_to_move(); Square ksq = pos.king_square(us); Bitboard checkers = pos.checkers(); Bitboard sliderAttacks = EmptyBoardBB; assert(pos.piece_on(ksq) == piece_of_color_and_type(us, KING)); assert(checkers); // Find squares attacked by slider checkers, we will remove // them from the king evasions set so to early skip known // illegal moves and avoid an useless legality check later. b = checkers; do { checkersCnt++; checksq = pop_1st_bit(&b); assert(pos.color_of_piece_on(checksq) == opposite_color(us)); switch (pos.type_of_piece_on(checksq)) { case BISHOP: sliderAttacks |= BishopPseudoAttacks[checksq]; break; case ROOK: sliderAttacks |= RookPseudoAttacks[checksq]; break; case QUEEN: // In case of a queen remove also squares attacked in the other direction to // avoid possible illegal moves when queen and king are on adjacent squares. if (direction_is_straight(checksq, ksq)) sliderAttacks |= RookPseudoAttacks[checksq] | pos.attacks_from<BISHOP>(checksq); else sliderAttacks |= BishopPseudoAttacks[checksq] | pos.attacks_from<ROOK>(checksq); default: break; } } while (b); // Generate evasions for king, capture and non capture moves b = pos.attacks_from<KING>(ksq) & ~pos.pieces_of_color(us) & ~sliderAttacks; from = ksq; SERIALIZE_MOVES(b); // Generate evasions for other pieces only if not double check if (checkersCnt > 1) return mlist; // Find squares where a blocking evasion or a capture of the // checker piece is possible. target = squares_between(checksq, ksq) | checkers; mlist = generate_piece_moves<PAWN, EVASION>(pos, mlist, us, target); mlist = generate_piece_moves<KNIGHT>(pos, mlist, us, target); mlist = generate_piece_moves<BISHOP>(pos, mlist, us, target); mlist = generate_piece_moves<ROOK>(pos, mlist, us, target); return generate_piece_moves<QUEEN>(pos, mlist, us, target); }
// probe_egtb() does the actual probing. On failure it returns VALUE_NONE. Value probe_egtb(Position &pos, const int ply, const bool hard, const bool exact) { // Conversion variables Bitboard occ; int count; // stockfish -> egtb int stm, epsquare, castling; unsigned int ws[17], bs[17]; unsigned char wp[17], bp[17]; // egtb -> stockfish int tb_available; unsigned info = tb_UNKNOWN; unsigned pliestomate; // Prepare info for white (stockfish -> egtb) occ = pos.pieces_of_color(WHITE); count = 0; while (occ) { Square s = pop_1st_bit(&occ); ws[count] = s; wp[count] = (unsigned char) pos.type_of_piece_on(s); count++; } ws[count] = tb_NOSQUARE; wp[count] = tb_NOPIECE; // Prepare info for black (stockfish -> egtb) occ = pos.pieces_of_color(BLACK); count = 0; while (occ) { Square s = pop_1st_bit(&occ); bs[count] = s; bp[count] = (unsigned char) pos.type_of_piece_on(s); count++; } bs[count] = tb_NOSQUARE; bp[count] = tb_NOPIECE; // Prepare general info stm = pos.side_to_move(); epsquare = pos.ep_square(); castling = tb_NOCASTLE; if (pos.can_castle(WHITE) || pos.can_castle(BLACK)) { if (Chess960) return VALUE_NONE; if (pos.can_castle_kingside(WHITE)) castling |= tb_WOO; if (pos.can_castle_queenside(WHITE)) castling |= tb_WOOO; if (pos.can_castle_kingside(BLACK)) castling |= tb_BOO; if (pos.can_castle_queenside(BLACK)) castling |= tb_BOOO; } // Do the actual probing if (hard) { if (exact) tb_available = tb_probe_hard (stm, epsquare, castling, ws, bs, wp, bp, &info, &pliestomate); else tb_available = tb_probe_WDL_hard (stm, epsquare, castling, ws, bs, wp, bp, &info); } else { if (exact) tb_available = tb_probe_soft (stm, epsquare, castling, ws, bs, wp, bp, &info, &pliestomate); else tb_available = tb_probe_WDL_soft (stm, epsquare, castling, ws, bs, wp, bp, &info); } // Return probing info (if available) if (tb_available) { pos.set_tb_hits(pos.tb_hits() + 1); if (info == tb_DRAW) return VALUE_DRAW; else if (info == tb_WMATE && stm == tb_WHITE_TO_MOVE) return (exact ? value_mate_in(pliestomate+ply) : VALUE_KNOWN_WIN); else if (info == tb_BMATE && stm == tb_BLACK_TO_MOVE) return (exact ? value_mate_in(pliestomate+ply) : VALUE_KNOWN_WIN); else if (info == tb_WMATE && stm == tb_BLACK_TO_MOVE) return (exact ? value_mated_in(pliestomate+ply) : -VALUE_KNOWN_WIN); else if (info == tb_BMATE && stm == tb_WHITE_TO_MOVE) return (exact ? value_mated_in(pliestomate+ply) : -VALUE_KNOWN_WIN); else return VALUE_NONE; } else return VALUE_NONE; }
//Looks at pawn shielding around each king and returns white - black score int Get_King_Safety_Score(BOARD_STRUCT *board) { int white_score = 0; int black_score = 0; U64 temp = board->piece_bitboards[wK]; int white_king_square = pop_1st_bit(&temp); temp = board->piece_bitboards[bK]; int black_king_square = pop_1st_bit(&temp); //White king on kingside if (GET_FILE(white_king_square) > FILE_E && GET_RANK(white_king_square) == RANK_1) { if (board->board_array[F2] == wP) white_score += PAWN_SHIELD_SCORE; else if (board->board_array[F3] == wP) white_score += PAWN_SHIELD_SCORE / 2; if (board->board_array[G2] == wP) white_score += PAWN_SHIELD_SCORE; else if (board->board_array[G3] == wP) white_score += PAWN_SHIELD_SCORE / 2; if (board->board_array[H2] == wP) white_score += PAWN_SHIELD_SCORE; else if (board->board_array[H3] == wP) white_score += PAWN_SHIELD_SCORE / 2; } else if (GET_FILE(white_king_square) < FILE_D && GET_RANK(white_king_square) == RANK_1) { if (board->board_array[A2] == wP) white_score += PAWN_SHIELD_SCORE; else if (board->board_array[A3] == wP) white_score += PAWN_SHIELD_SCORE / 2; if (board->board_array[B2] == wP) white_score += PAWN_SHIELD_SCORE; else if (board->board_array[B3] == wP) white_score += PAWN_SHIELD_SCORE / 2; if (board->board_array[C2] == wP) white_score += PAWN_SHIELD_SCORE; else if (board->board_array[C3] == wP) white_score += PAWN_SHIELD_SCORE / 2; } //Black king on kingside if (GET_FILE(black_king_square) > FILE_E && GET_RANK(black_king_square) == RANK_8) { if (board->board_array[F7] == bP) black_score += PAWN_SHIELD_SCORE; else if (board->board_array[F6] == bP) black_score += PAWN_SHIELD_SCORE / 2; if (board->board_array[G7] == bP) black_score += PAWN_SHIELD_SCORE; else if (board->board_array[G6] == bP) black_score += PAWN_SHIELD_SCORE / 2; if (board->board_array[H7] == bP) black_score += PAWN_SHIELD_SCORE; else if (board->board_array[H6] == bP) black_score += PAWN_SHIELD_SCORE / 2; } else if (GET_FILE(black_king_square) < FILE_D && GET_RANK(black_king_square) == RANK_8) { if (board->board_array[A7] == bP) black_score += PAWN_SHIELD_SCORE; else if (board->board_array[A6] == bP) black_score += PAWN_SHIELD_SCORE / 2; if (board->board_array[B7] == bP) black_score += PAWN_SHIELD_SCORE; else if (board->board_array[B6] == bP) black_score += PAWN_SHIELD_SCORE / 2; if (board->board_array[C7] == bP) black_score += PAWN_SHIELD_SCORE; else if (board->board_array[C6] == bP) black_score += PAWN_SHIELD_SCORE / 2; } return white_score - black_score; }