| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include <cassert> |
| #include <vector> |
| #include <bitset> |
|
|
| #include "bitboard.h" |
| #include "types.h" |
|
|
| namespace Stockfish { |
|
|
| namespace { |
|
|
| |
| |
| constexpr unsigned MAX_INDEX = 2*24*64*64; |
|
|
| std::bitset<MAX_INDEX> KPKBitbase; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| unsigned index(Color stm, Square bksq, Square wksq, Square psq) { |
| return int(wksq) | (bksq << 6) | (stm << 12) | (file_of(psq) << 13) | ((RANK_7 - rank_of(psq)) << 15); |
| } |
|
|
| enum Result { |
| INVALID = 0, |
| UNKNOWN = 1, |
| DRAW = 2, |
| WIN = 4 |
| }; |
|
|
| Result& operator|=(Result& r, Result v) { return r = Result(r | v); } |
|
|
| struct KPKPosition { |
| KPKPosition() = default; |
| explicit KPKPosition(unsigned idx); |
| operator Result() const { return result; } |
| Result classify(const std::vector<KPKPosition>& db); |
|
|
| Color stm; |
| Square ksq[COLOR_NB], psq; |
| Result result; |
| }; |
|
|
| } |
|
|
| bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color stm) { |
|
|
| assert(file_of(wpsq) <= FILE_D); |
|
|
| return KPKBitbase[index(stm, bksq, wksq, wpsq)]; |
| } |
|
|
|
|
| void Bitbases::init() { |
|
|
| std::vector<KPKPosition> db(MAX_INDEX); |
| unsigned idx, repeat = 1; |
|
|
| |
| for (idx = 0; idx < MAX_INDEX; ++idx) |
| db[idx] = KPKPosition(idx); |
|
|
| |
| |
| while (repeat) |
| for (repeat = idx = 0; idx < MAX_INDEX; ++idx) |
| repeat |= (db[idx] == UNKNOWN && db[idx].classify(db) != UNKNOWN); |
|
|
| |
| for (idx = 0; idx < MAX_INDEX; ++idx) |
| if (db[idx] == WIN) |
| KPKBitbase.set(idx); |
| } |
|
|
| namespace { |
|
|
| KPKPosition::KPKPosition(unsigned idx) { |
|
|
| ksq[WHITE] = Square((idx >> 0) & 0x3F); |
| ksq[BLACK] = Square((idx >> 6) & 0x3F); |
| stm = Color ((idx >> 12) & 0x01); |
| psq = make_square(File((idx >> 13) & 0x3), Rank(RANK_7 - ((idx >> 15) & 0x7))); |
|
|
| |
| if ( distance(ksq[WHITE], ksq[BLACK]) <= 1 |
| || ksq[WHITE] == psq |
| || ksq[BLACK] == psq |
| || (stm == WHITE && (pawn_attacks_bb(WHITE, psq) & ksq[BLACK]))) |
| result = INVALID; |
|
|
| |
| else if ( stm == WHITE |
| && rank_of(psq) == RANK_7 |
| && ksq[WHITE] != psq + NORTH |
| && ( distance(ksq[BLACK], psq + NORTH) > 1 |
| || (distance(ksq[WHITE], psq + NORTH) == 1))) |
| result = WIN; |
|
|
| |
| else if ( stm == BLACK |
| && ( !(attacks_bb<KING>(ksq[BLACK]) & ~(attacks_bb<KING>(ksq[WHITE]) | pawn_attacks_bb(WHITE, psq))) |
| || (attacks_bb<KING>(ksq[BLACK]) & ~attacks_bb<KING>(ksq[WHITE]) & psq))) |
| result = DRAW; |
|
|
| |
| else |
| result = UNKNOWN; |
| } |
|
|
| Result KPKPosition::classify(const std::vector<KPKPosition>& db) { |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| const Result Good = (stm == WHITE ? WIN : DRAW); |
| const Result Bad = (stm == WHITE ? DRAW : WIN); |
|
|
| Result r = INVALID; |
| Bitboard b = attacks_bb<KING>(ksq[stm]); |
|
|
| while (b) |
| r |= stm == WHITE ? db[index(BLACK, ksq[BLACK], pop_lsb(b), psq)] |
| : db[index(WHITE, pop_lsb(b), ksq[WHITE], psq)]; |
|
|
| if (stm == WHITE) |
| { |
| if (rank_of(psq) < RANK_7) |
| r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH)]; |
|
|
| if ( rank_of(psq) == RANK_2 |
| && psq + NORTH != ksq[WHITE] |
| && psq + NORTH != ksq[BLACK]) |
| r |= db[index(BLACK, ksq[BLACK], ksq[WHITE], psq + NORTH + NORTH)]; |
| } |
|
|
| return result = r & Good ? Good : r & UNKNOWN ? UNKNOWN : Bad; |
| } |
|
|
| } |
|
|
| } |
|
|