/* * A compromise between probe_hard and probe_soft. Check the cache, and return * if the position is found. If not, use a thread to load the position into * cache in the background while we return to the main search. The background * load uses a worker thread, and has minimal load implications because the * thread is blocked nearly 100% of the time. * Get DTM information instead of just WDL. */ bool probe_gtb_firm_dtm(const position_t* pos, int* score) { gtb_args_t args_storage; gtb_args_t* gtb_args = &args_storage; gtb_args->stm = stm_to_gtb(pos->side_to_move); gtb_args->ep = ep_to_gtb(pos->ep_square); gtb_args->castle = castle_to_gtb(pos->castle_rights); fill_gtb_arrays(pos, gtb_args->ws, gtb_args->bs, gtb_args->wp, gtb_args->bp); unsigned res, val; int success = tb_probe_soft(gtb_args->stm, gtb_args->ep, gtb_args->castle, gtb_args->ws, gtb_args->bs, gtb_args->wp, gtb_args->bp, &res, &val); if (success) { if (res == tb_DRAW) *score = DRAW_VALUE; else if (res == tb_BMATE) *score = mated_in(val); else if (res == tb_WMATE) *score = mate_in(val); else assert(false); if (pos->side_to_move == BLACK) *score *= -1; return true; } if (worker_task_ready) return false; memcpy(&worker_args, gtb_args, sizeof(gtb_args_t)); worker_task_ready = true; return false; }
int GTB::getDtm(const int xside, const bool doPrint, const _Tchessboard &chessboard, const int depth) const { const int side = xside ^1; const uchar rightCastle = chessboard[RIGHT_CASTLE_IDX]; unsigned int ws[17]; /* list of squares for white */ unsigned int bs[17]; /* list of squares for black */ unsigned char wp[17]; /* what white pieces are on those squares */ unsigned char bp[17]; /* what black pieces are on those squares */ unsigned info = tb_UNKNOWN; /* default, no tbvalue */ unsigned pliestomate = 0; int count = 0; //white for (int piece = 1; piece < 12; piece += 2) { for (u64 b = chessboard[piece]; b; RESET_LSB(b)) { int position = BITScanForward(b); ws[count] = DECODE_POSITION[position]; wp[count] = DECODE_PIECE[piece]; count++; } } ws[count] = tb_NOSQUARE; /* it marks the end of list */ wp[count] = tb_NOPIECE; /* it marks the end of list */ //black count = 0; for (int piece = 0; piece < 12; piece += 2) { for (u64 b = chessboard[piece]; b; RESET_LSB(b)) { int position = BITScanForward(b); bs[count] = DECODE_POSITION[position]; bp[count] = DECODE_PIECE[piece]; count++; } } bs[count] = tb_NOSQUARE; bp[count] = tb_NOPIECE; unsigned int tb_castling = 0; tb_castling = rightCastle & ChessBoard::RIGHT_QUEEN_CASTLE_WHITE_MASK ? tb_WOOO : 0; tb_castling |= rightCastle & ChessBoard::RIGHT_KING_CASTLE_WHITE_MASK ? tb_WOO : 0; tb_castling |= rightCastle & ChessBoard::RIGHT_KING_CASTLE_BLACK_MASK ? tb_BOO : 0; tb_castling |= rightCastle & ChessBoard::RIGHT_QUEEN_CASTLE_BLACK_MASK ? tb_BOOO : 0; int tb_available = 0; if (depth > 8) { tb_available = tb_probe_hard(side, tb_NOSQUARE, tb_castling, ws, bs, wp, bp, &info, &pliestomate); } else if (depth >= probeDepth) { tb_available = tb_probe_soft(side, tb_NOSQUARE, tb_castling, ws, bs, wp, bp, &info, &pliestomate); } return extractDtm(side, doPrint, tb_available, info, pliestomate); }
/* * Probe the tb cache only, without considering what's available on disk. * Get DTM information instead of just WDL. */ bool probe_gtb_soft_dtm(const position_t* pos, int* score) { int stm = stm_to_gtb(pos->side_to_move); int ep = ep_to_gtb(pos->ep_square); int castle = castle_to_gtb(pos->castle_rights); unsigned int ws[17], bs[17]; unsigned char wp[17], bp[17]; fill_gtb_arrays(pos, ws, bs, wp, bp); unsigned res, val; int success = tb_probe_soft(stm, ep, castle, ws, bs, wp, bp, &res, &val); if (success) { if (res == tb_DRAW) *score = DRAW_VALUE; else if (res == tb_BMATE) *score = mated_in(val); else if (res == tb_WMATE) *score = mate_in(val); else assert(false); if (pos->side_to_move == BLACK) *score *= -1; } return success; }
int GaviotaTb::probe_tb(const Board &board, int &score, int ply, bool hard) { unsigned int stm = stm_map[board.sideToMove()]; Square epsq = board.enPassantSq(); // map en-passant square to format used by GTBs unsigned int epsquare = (epsq == InvalidSquare) ? tb_NOSQUARE : MakeSquare(File(epsq),6,board.sideToMove()); unsigned int castling = castle_map[board.castleStatus(Black)] | (castle_map[board.castleStatus(White)] << 2); unsigned info = tb_UNKNOWN; unsigned pliestomate; unsigned int ws[17], bs[17]; unsigned char wp[17], bp[17]; // pack arrays ws, bs, wp, bp with the square/piece info from the // board: Square wsq; Bitboard temp(board.occupied[White]); int w = 0; while (temp.iterate(wsq)) { // our square & piece types map directly to the GTB piece types ws[w] = (unsigned int)wsq; wp[w] = (unsigned char)TypeOfPiece(board[wsq]); w++; } ws[w] = tb_NOSQUARE; wp[w] = tb_NOPIECE; Square bsq; Bitboard temp2(board.occupied[Black]); int b = 0; while (temp2.iterate(bsq)) { // our square & piece types map directly to the GTB piece types bs[b] = (unsigned int)bsq; bp[b] = (unsigned char)TypeOfPiece(board[bsq]); b++; } bs[b] = tb_NOSQUARE; bp[b] = tb_NOPIECE; int avail; if (hard) avail = tb_probe_hard(stm, epsquare, castling, ws, bs, wp, bp, &info, &pliestomate); else avail = tb_probe_soft(stm, epsquare, castling, ws, bs, wp, bp, &info, &pliestomate); if (!avail) return 0; score = 0; if (info == tb_WMATE) score = board.sideToMove() == White ? Constants::MATE-(int)pliestomate : -Constants::MATE+(int)pliestomate; else if (info == tb_BMATE) score = board.sideToMove() == Black ? Constants::MATE-(int)pliestomate : -Constants::MATE+(int)pliestomate; // correct for search depth (a mate found far from the root is less // valuable than one found closer to the root) if (score > 0) score -= ply; else if (score < 0) score += ply; return 1; /* success */ }
// 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; }
bool gtb_probe(int *value) { int sq, w, b, success; unsigned int ws[17], bs[17]; unsigned char wp[17], bp[17]; unsigned pliestomate; unsigned info = tb_UNKNOWN; unsigned int tb_castling = 0; unsigned int ep; bitboard_t t; ws[0] = bitscanf(pos->occ[WK]); wp[0] = tb_KING; bs[0] = bitscanf(pos->occ[BK]); bp[0] = tb_KING; w = b = 1; t = pos->occ[WP]; while(t) { sq = bitscanf(t); bitclear(t, sq); ws[w] = sq; wp[w] = tb_PAWN; w++; } t = pos->occ[WN]; while(t) { sq = bitscanf(t); bitclear(t, sq); ws[w] = sq; wp[w] = tb_KNIGHT; w++; } t = pos->occ[WB]; while(t) { sq = bitscanf(t); bitclear(t, sq); ws[w] = sq; wp[w] = tb_BISHOP; w++; } t = pos->occ[WR]; while(t) { sq = bitscanf(t); bitclear(t, sq); ws[w] = sq; wp[w] = tb_ROOK; w++; } t = pos->occ[WQ]; while(t) { sq = bitscanf(t); bitclear(t, sq); ws[w] = sq; wp[w] = tb_QUEEN; w++; } t = pos->occ[BP]; while(t) { sq = bitscanf(t); bitclear(t, sq); bs[b] = sq; bp[b] = tb_PAWN; b++; } t = pos->occ[BN]; while(t) { sq = bitscanf(t); bitclear(t, sq); bs[b] = sq; bp[b] = tb_KNIGHT; b++; } t = pos->occ[BB]; while(t) { sq = bitscanf(t); bitclear(t, sq); bs[b] = sq; bp[b] = tb_BISHOP; b++; } t = pos->occ[BR]; while(t) { sq = bitscanf(t); bitclear(t, sq); bs[b] = sq; bp[b] = tb_ROOK; b++; } t = pos->occ[BQ]; while(t) { sq = bitscanf(t); bitclear(t, sq); bs[b] = sq; bp[b] = tb_QUEEN; b++; } ws[w] = tb_NOSQUARE; wp[w] = tb_NOPIECE; bs[b] = tb_NOSQUARE; bp[b] = tb_NOPIECE; ep = pos->ep ? (pos->ep) : (tb_NOSQUARE); if(pos->castle) { tb_castling = ((1 && (pos->castle & WHITE_OO)) * tb_WOO); tb_castling |= ((1 && (pos->castle & WHITE_OOO)) * tb_WOOO); tb_castling |= ((1 && (pos->castle & BLACK_OO)) * tb_BOO); tb_castling |= ((1 && (pos->castle & BLACK_OOO)) * tb_BOOO); } if((opt.analyze) || ((get_time() - opt.startup_time) < opt.time_low/2 && opt.time_low > 500)) success = tb_probe_hard(pos->side, ep, tb_castling, ws, bs, wp, bp, &info, &pliestomate); else success = tb_probe_soft(pos->side, ep, tb_castling, ws, bs, wp, bp, &info, &pliestomate); if(success) { tbhits++; if(info == tb_DRAW) *value = 0; else if((info == tb_WMATE && pos->side == W) ||(info == tb_BMATE && pos->side == B)) *value = (MATEVALUE-pliestomate)-1; else if((info == tb_WMATE && pos->side == B) ||(info == tb_BMATE && pos->side == W)) *value = (-MATEVALUE+pliestomate)+1; return true; } return false; }