From: Gary Linscott Date: Tue, 19 Feb 2013 15:31:52 +0000 (-0500) Subject: Merge branch 'master' into bishop_pin_clop X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=ea4e22be1da1ccbf316d27f2eb3b14d0e13388e4;hp=dc8c6ea2d149cfe9ce17fc9652b9ff90585c7fd8 Merge branch 'master' into bishop_pin_clop --- diff --git a/src/bitbase.cpp b/src/bitbase.cpp index 700eea98..ef067c65 100644 --- a/src/bitbase.cpp +++ b/src/bitbase.cpp @@ -26,22 +26,22 @@ namespace { // The possible pawns squares are 24, the first 4 files and ranks from 2 to 7 - const unsigned IndexMax = 24*64*64*2; // wp_sq * wk_sq * bk_sq * stm = 196608 + const unsigned IndexMax = 2*24*64*64; // stm * psq * wksq * bksq = 196608 // Each uint32_t stores results of 32 positions, one per bit uint32_t KPKBitbase[IndexMax / 32]; // A KPK bitbase index is an integer in [0, IndexMax] range // - // Information is mapped in this way + // Information is mapped in a way that minimizes number of iterations: // - // bit 0: side to move (WHITE or BLACK) - // bit 1- 6: black king square (from SQ_A1 to SQ_H8) - // bit 7-12: white king square (from SQ_A1 to SQ_H8) + // bit 0- 5: white king square (from SQ_A1 to SQ_H8) + // bit 6-11: black king square (from SQ_A1 to SQ_H8) + // bit 12: side to move (WHITE or BLACK) // bit 13-14: white pawn file (from FILE_A to FILE_D) // bit 15-17: white pawn 6 - rank (from 6 - RANK_7 to 6 - RANK_2) - unsigned index(Color stm, Square bksq, Square wksq, Square psq) { - return stm + (bksq << 1) + (wksq << 7) + (file_of(psq) << 13) + ((6 - rank_of(psq)) << 15); + unsigned index(Color us, Square bksq, Square wksq, Square psq) { + return wksq + (bksq << 6) + (us << 12) + (file_of(psq) << 13) + ((6 - rank_of(psq)) << 15); } enum Result { @@ -55,20 +55,15 @@ namespace { struct KPKPosition { - void classify_leaf(unsigned idx); - - Result classify(const std::vector& db) - { return stm == WHITE ? classify(db) : classify(db); } - operator Result() const { return res; } + Result classify_leaf(unsigned idx); + Result classify(const std::vector& db) + { return us == WHITE ? classify(db) : classify(db); } private: - template Bitboard k_attacks() const - { return StepAttacksBB[KING][Us == WHITE ? wksq : bksq]; } - template Result classify(const std::vector& db); - Color stm; + Color us; Square bksq, wksq, psq; Result res; }; @@ -76,12 +71,12 @@ namespace { } // namespace -bool Bitbases::probe_kpk(Square wksq, Square wpsq, Square bksq, Color stm) { +bool Bitbases::probe_kpk(Square wksq, Square wpsq, Square bksq, Color us) { assert(file_of(wpsq) <= FILE_D); - unsigned idx = index(stm, bksq, wksq, wpsq); - return KPKBitbase[idx / 32] & (1 << (idx & 31)); + unsigned idx = index(us, bksq, wksq, wpsq); + return KPKBitbase[idx / 32] & (1 << (idx & 0x1F)); } @@ -94,7 +89,7 @@ void Bitbases::init_kpk() { for (idx = 0; idx < IndexMax; idx++) db[idx].classify_leaf(idx); - // Iterate until all positions are classified (26 cycles needed) + // Iterate until all positions are classified (15 cycles needed) while (repeat) for (repeat = idx = 0; idx < IndexMax; idx++) if (db[idx] == UNKNOWN && db[idx].classify(db) != UNKNOWN) @@ -103,101 +98,61 @@ void Bitbases::init_kpk() { // Map 32 results into one KPKBitbase[] entry for (idx = 0; idx < IndexMax; idx++) if (db[idx] == WIN) - KPKBitbase[idx / 32] |= 1 << (idx & 31); + KPKBitbase[idx / 32] |= 1 << (idx & 0x1F); } namespace { - void KPKPosition::classify_leaf(unsigned idx) { + Result KPKPosition::classify_leaf(unsigned idx) { - stm = Color(idx & 1); - bksq = Square((idx >> 1) & 0x3F); - wksq = Square((idx >> 7) & 0x3F); + wksq = Square((idx >> 0) & 0x3F); + bksq = Square((idx >> 6) & 0x3F); + us = Color((idx >> 12) & 0x01); psq = File((idx >> 13) & 3) | Rank(6 - (idx >> 15)); // Check if two pieces are on the same square or if a king can be captured if ( wksq == psq || wksq == bksq || bksq == psq - || (k_attacks() & bksq) - || (stm == WHITE && (StepAttacksBB[PAWN][psq] & bksq))) - res = INVALID; - - // The position is an immediate win if it is white to move and the white - // pawn can be promoted without getting captured. - else if ( rank_of(psq) == RANK_7 - && stm == WHITE - && wksq != psq + DELTA_N - && ( square_distance(bksq, psq + DELTA_N) > 1 - ||(k_attacks() & (psq + DELTA_N)))) - res = WIN; - - // Check for known draw positions - // - // Case 1: Stalemate - else if ( stm == BLACK - && !(k_attacks() & ~(k_attacks() | StepAttacksBB[PAWN][psq]))) - res = DRAW; - - // Case 2: King can capture undefended pawn - else if ( stm == BLACK - && (k_attacks() & psq & ~k_attacks())) - res = DRAW; - - // Case 3: Black king in front of white pawn - else if ( bksq == psq + DELTA_N - && rank_of(psq) < RANK_7) - res = DRAW; - - // Case 4: White king in front of pawn and black has opposition - else if ( stm == WHITE - && wksq == psq + DELTA_N - && bksq == wksq + DELTA_N + DELTA_N - && rank_of(psq) < RANK_5) - res = DRAW; - - // Case 5: Stalemate with rook pawn - else if ( bksq == SQ_A8 - && file_of(psq) == FILE_A) - res = DRAW; - - // Case 6: White king trapped on the rook file - else if ( file_of(wksq) == FILE_A - && file_of(psq) == FILE_A - && rank_of(wksq) > rank_of(psq) - && bksq == wksq + 2) - res = DRAW; + || (StepAttacksBB[KING][wksq] & bksq) + || (us == WHITE && (StepAttacksBB[PAWN][psq] & bksq))) + return res = INVALID; - else - res = UNKNOWN; + if (us == WHITE) + { + // Immediate win if pawn can be promoted without getting captured + if ( rank_of(psq) == RANK_7 + && wksq != psq + DELTA_N + && ( square_distance(bksq, psq + DELTA_N) > 1 + ||(StepAttacksBB[KING][wksq] & (psq + DELTA_N)))) + return res = WIN; + } + // Immediate draw if is stalemate or king captures undefended pawn + else if ( !(StepAttacksBB[KING][bksq] & ~(StepAttacksBB[KING][wksq] | StepAttacksBB[PAWN][psq])) + || (StepAttacksBB[KING][bksq] & psq & ~StepAttacksBB[KING][wksq])) + return res = DRAW; + + return res = UNKNOWN; } template Result KPKPosition::classify(const std::vector& db) { - // White to Move: If one move leads to a position classified as RESULT_WIN, - // the result of the current position is RESULT_WIN. If all moves lead to - // positions classified as RESULT_DRAW, the current position is classified - // RESULT_DRAW otherwise the current position is classified as RESULT_UNKNOWN. + // White to Move: If one move leads to a position classified as WIN, the result + // of the current position is WIN. If all moves lead to positions classified + // as DRAW, the current position is classified DRAW otherwise the current + // position is classified as UNKNOWN. // - // Black to Move: If one move leads to a position classified as RESULT_DRAW, - // the result of the current position is RESULT_DRAW. If all moves lead to - // positions classified as RESULT_WIN, the position is classified RESULT_WIN. - // Otherwise, the current position is classified as RESULT_UNKNOWN. + // Black to Move: If one move leads to a position classified as DRAW, the result + // of the current position is DRAW. If all moves lead to positions classified + // as WIN, the position is classified WIN otherwise the current position is + // classified UNKNOWN. Result r = INVALID; - Bitboard b = k_attacks(); + Bitboard b = StepAttacksBB[KING][Us == WHITE ? wksq : bksq]; while (b) - { - r |= Us == WHITE ? db[index(BLACK, bksq, pop_lsb(&b), psq)] - : db[index(WHITE, pop_lsb(&b), wksq, psq)]; - - if (Us == WHITE && (r & WIN)) - return res = WIN; - - if (Us == BLACK && (r & DRAW)) - return res = DRAW; - } + r |= Us == WHITE ? db[index(~Us, bksq, pop_lsb(&b), psq)] + : db[index(~Us, pop_lsb(&b), wksq, psq)]; if (Us == WHITE && rank_of(psq) < RANK_7) { @@ -206,12 +161,12 @@ namespace { if (rank_of(s) == RANK_3 && s != wksq && s != bksq) r |= db[index(BLACK, bksq, wksq, s + DELTA_N)]; // Double push - - if (r & WIN) - return res = WIN; } - return res = r & UNKNOWN ? UNKNOWN : Us == WHITE ? DRAW : WIN; + if (Us == WHITE) + return res = r & WIN ? WIN : r & UNKNOWN ? UNKNOWN : DRAW; + else + return res = r & DRAW ? DRAW : r & UNKNOWN ? UNKNOWN : WIN; } -} +} // namespace diff --git a/src/bitboard.h b/src/bitboard.h index e3331bd4..90dec816 100644 --- a/src/bitboard.h +++ b/src/bitboard.h @@ -33,7 +33,7 @@ void print(Bitboard b); namespace Bitbases { void init_kpk(); -bool probe_kpk(Square wksq, Square wpsq, Square bksq, Color stm); +bool probe_kpk(Square wksq, Square wpsq, Square bksq, Color us); } diff --git a/src/endgame.cpp b/src/endgame.cpp index ae29a71a..85916763 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -199,21 +199,21 @@ Value Endgame::operator()(const Position& pos) const { assert(pos.piece_count(weakerSide, PAWN) == 0); Square wksq, bksq, wpsq; - Color stm; + Color us; if (strongerSide == WHITE) { wksq = pos.king_square(WHITE); bksq = pos.king_square(BLACK); wpsq = pos.piece_list(WHITE, PAWN)[0]; - stm = pos.side_to_move(); + us = pos.side_to_move(); } else { wksq = ~pos.king_square(BLACK); bksq = ~pos.king_square(WHITE); wpsq = ~pos.piece_list(BLACK, PAWN)[0]; - stm = ~pos.side_to_move(); + us = ~pos.side_to_move(); } if (file_of(wpsq) >= FILE_E) @@ -223,7 +223,7 @@ Value Endgame::operator()(const Position& pos) const { wpsq = mirror(wpsq); } - if (!Bitbases::probe_kpk(wksq, wpsq, bksq, stm)) + if (!Bitbases::probe_kpk(wksq, wpsq, bksq, us)) return VALUE_DRAW; Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(wpsq)); @@ -920,14 +920,14 @@ ScaleFactor Endgame::operator()(const Position& pos) const { Square wksq = pos.king_square(strongerSide); Square bksq = pos.king_square(weakerSide); Square wpsq = pos.piece_list(strongerSide, PAWN)[0]; - Color stm = pos.side_to_move(); + Color us = pos.side_to_move(); if (strongerSide == BLACK) { wksq = ~wksq; bksq = ~bksq; wpsq = ~wpsq; - stm = ~stm; + us = ~us; } if (file_of(wpsq) >= FILE_E) @@ -945,5 +945,5 @@ ScaleFactor Endgame::operator()(const Position& pos) const { // Probe the KPK bitbase with the weakest side's pawn removed. If it's a draw, // it's probably at least a draw even with the pawn. - return Bitbases::probe_kpk(wksq, wpsq, bksq, stm) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW; + return Bitbases::probe_kpk(wksq, wpsq, bksq, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW; } diff --git a/src/evaluate.cpp b/src/evaluate.cpp index e17a3e34..02810b78 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -498,7 +498,7 @@ Value do_evaluate(const Position& pos, Value& margin) { // Init king safety tables only if we are going to use them if ( pos.piece_count(Us, QUEEN) - && pos.non_pawn_material(Us) >= QueenValueMg + RookValueMg) + && pos.non_pawn_material(Us) > QueenValueMg + PawnValueMg) { ei.kingRing[Them] = (b | (Us == WHITE ? b >> 8 : b << 8)); b &= ei.attackedBy[Us][PAWN]; diff --git a/src/position.cpp b/src/position.cpp index ad0a621d..a51383f0 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -278,11 +278,11 @@ void Position::set(const string& fenStr, bool isChess960, Thread* th) { } // 5-6. Halfmove clock and fullmove number - ss >> std::skipws >> st->rule50 >> startPosPly; + ss >> std::skipws >> st->rule50 >> gamePly; // Convert from fullmove starting from 1 to ply starting from 0, // handle also common incorrect FEN with fullmove = 0. - startPosPly = std::max(2 * (startPosPly - 1), 0) + int(sideToMove == BLACK); + gamePly = std::max(2 * (gamePly - 1), 0) + int(sideToMove == BLACK); st->key = compute_key(); st->pawnKey = compute_pawn_key(); @@ -373,7 +373,7 @@ const string Position::fen() const { ss << '-'; ss << (ep_square() == SQ_NONE ? " - " : " " + square_to_string(ep_square()) + " ") - << st->rule50 << " " << 1 + (startPosPly - int(sideToMove == BLACK)) / 2; + << st->rule50 << " " << 1 + (gamePly - int(sideToMove == BLACK)) / 2; return ss.str(); } @@ -735,8 +735,9 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI // Update side to move k ^= Zobrist::side; - // Increment the 50 moves rule draw counter. Resetting it to zero in the - // case of a capture or a pawn move is taken care of later. + // Increment ply counters.In particular rule50 will be later reset it to zero + // in case of a capture or a pawn move. + gamePly++; st->rule50++; st->pliesFromNull++; @@ -1054,6 +1055,7 @@ void Position::undo_move(Move m) { // Finally point our state pointer back to the previous state st = st->previous; + gamePly--; assert(pos_is_ok()); } @@ -1417,7 +1419,7 @@ void Position::flip() { thisThread = pos.this_thread(); nodes = pos.nodes_searched(); chess960 = pos.is_chess960(); - startPosPly = pos.startpos_ply_counter(); + gamePly = pos.game_ply(); for (Square s = SQ_A1; s <= SQ_H8; s++) if (!pos.is_empty(s)) diff --git a/src/position.h b/src/position.h index 579b5308..fb7eb4b9 100644 --- a/src/position.h +++ b/src/position.h @@ -174,7 +174,7 @@ public: // Other properties of the position Color side_to_move() const; - int startpos_ply_counter() const; + int game_ply() const; bool is_chess960() const; Thread* this_thread() const; int64_t nodes_searched() const; @@ -218,7 +218,7 @@ private: Bitboard castlePath[COLOR_NB][CASTLING_SIDE_NB]; StateInfo startState; int64_t nodes; - int startPosPly; + int gamePly; Color sideToMove; Thread* thisThread; StateInfo* st; @@ -376,8 +376,8 @@ inline bool Position::is_passed_pawn_push(Move m) const { && pawn_is_passed(sideToMove, to_sq(m)); } -inline int Position::startpos_ply_counter() const { - return startPosPly + st->pliesFromNull; // HACK +inline int Position::game_ply() const { + return gamePly; } inline bool Position::opposite_bishops() const { diff --git a/src/search.cpp b/src/search.cpp index 74dc9e29..b9cbb956 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -182,7 +182,7 @@ void Search::think() { static PolyglotBook book; // Defined static to initialize the PRNG only once RootColor = RootPos.side_to_move(); - TimeMgr.init(Limits, RootPos.startpos_ply_counter(), RootColor); + TimeMgr.init(Limits, RootPos.game_ply(), RootColor); if (RootMoves.empty()) {