From 0fd90e2550f32ab24b9ec58a6f7fd0501c62fec7 Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Sun, 23 Sep 2012 08:13:11 +0000 Subject: [PATCH] DroidFish: Updated stockfish to version 2.3.1. --- DroidFish/jni/stockfish/bitboard.cpp | 46 ++++++++++------------------ DroidFish/jni/stockfish/book.cpp | 42 +++++++++++++++---------- DroidFish/jni/stockfish/book.h | 20 +++--------- DroidFish/jni/stockfish/endgame.cpp | 4 +-- DroidFish/jni/stockfish/evaluate.cpp | 30 ++++++++++++------ DroidFish/jni/stockfish/misc.cpp | 2 +- DroidFish/jni/stockfish/movegen.cpp | 24 ++++++++++----- DroidFish/jni/stockfish/search.cpp | 2 +- 8 files changed, 88 insertions(+), 82 deletions(-) diff --git a/DroidFish/jni/stockfish/bitboard.cpp b/DroidFish/jni/stockfish/bitboard.cpp index 639ef3f..dd5b579 100644 --- a/DroidFish/jni/stockfish/bitboard.cpp +++ b/DroidFish/jni/stockfish/bitboard.cpp @@ -62,8 +62,8 @@ namespace { CACHE_LINE_ALIGNMENT - int BSFTable[64]; int MS1BTable[256]; + Square BSFTable[64]; Bitboard RTable[0x19000]; // Storage space for rook attacks Bitboard BTable[0x1480]; // Storage space for bishop attacks uint8_t BitCount8Bit[256]; @@ -72,6 +72,16 @@ namespace { void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[], Bitboard masks[], unsigned shifts[], Square deltas[], Fn index); + + FORCE_INLINE unsigned bsf_index(Bitboard b) { + + if (Is64Bit) + return ((b & -b) * DeBruijn_64) >> 58; + + // Use Matt Taylor's folding trick for 32 bit systems + b ^= (b - 1); + return ((unsigned(b) ^ unsigned(b >> 32)) * DeBruijn_32) >> 26; + } } /// lsb()/msb() finds the least/most significant bit in a nonzero bitboard. @@ -79,27 +89,13 @@ namespace { #if !defined(USE_BSFQ) -Square lsb(Bitboard b) { - - if (Is64Bit) - return Square(BSFTable[((b & -b) * DeBruijn_64) >> 58]); - - b ^= (b - 1); - uint32_t fold = unsigned(b) ^ unsigned(b >> 32); - return Square(BSFTable[(fold * DeBruijn_32) >> 26]); -} +Square lsb(Bitboard b) { return BSFTable[bsf_index(b)]; } Square pop_lsb(Bitboard* b) { Bitboard bb = *b; *b = bb & (bb - 1); - - if (Is64Bit) - return Square(BSFTable[((bb & -bb) * DeBruijn_64) >> 58]); - - bb ^= (bb - 1); - uint32_t fold = unsigned(bb) ^ unsigned(bb >> 32); - return Square(BSFTable[(fold * DeBruijn_32) >> 26]); + return BSFTable[bsf_index(bb)]; } Square msb(Bitboard b) { @@ -127,7 +123,7 @@ Square msb(Bitboard b) { result += 8; } - return Square(result + MS1BTable[b32]); + return (Square)(result + MS1BTable[b32]); } #endif // !defined(USE_BSFQ) @@ -162,6 +158,9 @@ void Bitboards::init() { while (k < (2 << i)) MS1BTable[k++] = i; + for (int i = 0; i < 64; i++) + BSFTable[bsf_index(1ULL << i)] = Square(i); + for (Bitboard b = 0; b < 256; b++) BitCount8Bit[b] = (uint8_t)popcount(b); @@ -204,17 +203,6 @@ void Bitboards::init() { if (SquareDistance[s1][s2] == d) DistanceRingsBB[s1][d - 1] |= s2; - for (int i = 0; i < 64; i++) - if (!Is64Bit) // Matt Taylor's folding trick for 32 bit systems - { - Bitboard b = 1ULL << i; - b ^= b - 1; - b ^= b >> 32; - BSFTable[(uint32_t)(b * DeBruijn_32) >> 26] = i; - } - else - BSFTable[((1ULL << i) * DeBruijn_64) >> 58] = i; - int steps[][9] = { {}, { 7, 9 }, { 17, 15, 10, 6, -6, -10, -15, -17 }, {}, {}, {}, { 9, 7, -7, -9, 8, 1, -1, -8 } }; diff --git a/DroidFish/jni/stockfish/book.cpp b/DroidFish/jni/stockfish/book.cpp index 77bdc74..b723705 100644 --- a/DroidFish/jni/stockfish/book.cpp +++ b/DroidFish/jni/stockfish/book.cpp @@ -35,6 +35,16 @@ using namespace std; namespace { + // A Polyglot book is a series of "entries" of 16 bytes. All integers are + // stored in big-endian format, with highest byte first (regardless of size). + // The entries are ordered according to the key in ascending order. + struct BookEntry { + uint64_t key; + uint16_t move; + uint16_t count; + uint32_t learn; + }; + // Random numbers from PolyGlot, used to compute book hash keys const Key PolyGlotRandoms[781] = { 0x9D39247E33776D41ULL, 0x2AF7398005AAA5C7ULL, 0x44DB015024623547ULL, @@ -338,20 +348,20 @@ namespace { } // namespace -Book::Book() { +PolyglotBook::PolyglotBook() { for (int i = Time::now() % 10000; i > 0; i--) RKiss.rand(); // Make random number generation less deterministic } -Book::~Book() { if (is_open()) close(); } +PolyglotBook::~PolyglotBook() { if (is_open()) close(); } -/// Book::operator>>() reads sizeof(T) chars from the file's binary byte stream -/// and converts them in a number of type T. A Polyglot book stores numbers in +/// operator>>() reads sizeof(T) chars from the file's binary byte stream and +/// converts them in a number of type T. A Polyglot book stores numbers in /// big-endian format. -template Book& Book::operator>>(T& n) { +template PolyglotBook& PolyglotBook::operator>>(T& n) { n = 0; for (size_t i = 0; i < sizeof(T); i++) @@ -360,15 +370,15 @@ template Book& Book::operator>>(T& n) { return *this; } -template<> Book& Book::operator>>(BookEntry& e) { +template<> PolyglotBook& PolyglotBook::operator>>(BookEntry& e) { return *this >> e.key >> e.move >> e.count >> e.learn; } -/// Book::open() tries to open a book file with the given name after closing -/// any exsisting one. +/// open() tries to open a book file with the given name after closing any +/// exsisting one. -bool Book::open(const char* fName) { +bool PolyglotBook::open(const char* fName) { if (is_open()) // Cannot close an already closed file close(); @@ -381,11 +391,11 @@ bool Book::open(const char* fName) { } -/// Book::probe() tries to find a book move for the given position. If no move -/// is found returns MOVE_NONE. If pickBest is true returns always the highest +/// probe() tries to find a book move for the given position. If no move is +/// found returns MOVE_NONE. If pickBest is true returns always the highest /// rated move, otherwise randomly chooses one, based on the move score. -Move Book::probe(const Position& pos, const string& fName, bool pickBest) { +Move PolyglotBook::probe(const Position& pos, const string& fName, bool pickBest) { if (fileName != fName && !open(fName.c_str())) return MOVE_NONE; @@ -437,11 +447,11 @@ Move Book::probe(const Position& pos, const string& fName, bool pickBest) { } -/// Book::find_first() takes a book key as input, and does a binary search -/// through the book file for the given key. Returns the index of the leftmost -/// book entry with the same key as the input. +/// find_first() takes a book key as input, and does a binary search through +/// the book file for the given key. Returns the index of the leftmost book +/// entry with the same key as the input. -size_t Book::find_first(uint64_t key) { +size_t PolyglotBook::find_first(uint64_t key) { seekg(0, ios::end); // Move pointer to end, so tellg() gets file's size diff --git a/DroidFish/jni/stockfish/book.h b/DroidFish/jni/stockfish/book.h index 9497b9b..fcbce65 100644 --- a/DroidFish/jni/stockfish/book.h +++ b/DroidFish/jni/stockfish/book.h @@ -26,26 +26,14 @@ #include "position.h" #include "rkiss.h" - -/// A Polyglot book is a series of "entries" of 16 bytes. All integers are -/// stored highest byte first (regardless of size). The entries are ordered -/// according to key. Lowest key first. -struct BookEntry { - uint64_t key; - uint16_t move; - uint16_t count; - uint32_t learn; -}; - - -class Book : private std::ifstream { +class PolyglotBook : private std::ifstream { public: - Book(); - ~Book(); + PolyglotBook(); + ~PolyglotBook(); Move probe(const Position& pos, const std::string& fName, bool pickBest); private: - template Book& operator>>(T& n); + template PolyglotBook& operator>>(T& n); bool open(const char* fName); size_t find_first(uint64_t key); diff --git a/DroidFish/jni/stockfish/endgame.cpp b/DroidFish/jni/stockfish/endgame.cpp index dbf1058..20d175b 100644 --- a/DroidFish/jni/stockfish/endgame.cpp +++ b/DroidFish/jni/stockfish/endgame.cpp @@ -648,7 +648,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { // Does the defending king block the pawns? if ( square_distance(ksq, relative_square(strongerSide, SQ_A8)) <= 1 || ( file_of(ksq) == FILE_A - && !in_front_bb(strongerSide, ksq) & pawns)) + && !(in_front_bb(strongerSide, ksq) & pawns))) return SCALE_FACTOR_DRAW; } // Are all pawns on the 'h' file? @@ -657,7 +657,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { // Does the defending king block the pawns? if ( square_distance(ksq, relative_square(strongerSide, SQ_H8)) <= 1 || ( file_of(ksq) == FILE_H - && !in_front_bb(strongerSide, ksq) & pawns)) + && !(in_front_bb(strongerSide, ksq) & pawns))) return SCALE_FACTOR_DRAW; } return SCALE_FACTOR_NONE; diff --git a/DroidFish/jni/stockfish/evaluate.cpp b/DroidFish/jni/stockfish/evaluate.cpp index 46d9151..b5b51d2 100644 --- a/DroidFish/jni/stockfish/evaluate.cpp +++ b/DroidFish/jni/stockfish/evaluate.cpp @@ -138,7 +138,7 @@ namespace { {}, {}, { S(0, 0), S( 7, 39), S( 0, 0), S(24, 49), S(41,100), S(41,100) }, // KNIGHT { S(0, 0), S( 7, 39), S(24, 49), S( 0, 0), S(41,100), S(41,100) }, // BISHOP - { S(0, 0), S(-1, 29), S(15, 49), S(15, 49), S( 0, 0), S(24, 49) }, // ROOK + { S(0, 0), S( 0, 22), S(15, 49), S(15, 49), S( 0, 0), S(24, 49) }, // ROOK { S(0, 0), S(15, 39), S(15, 39), S(15, 39), S(15, 39), S( 0, 0) } // QUEEN }; @@ -153,12 +153,16 @@ namespace { // Bonus for having the side to move (modified by Joona Kiiski) const Score Tempo = make_score(24, 11); - // Rooks and queens on the 7th rank (modified by Joona Kiiski) - const Score RookOn7thBonus = make_score(47, 98); - const Score QueenOn7thBonus = make_score(27, 54); + // Rooks and queens on the 7th rank + const Score RookOn7thBonus = make_score(3, 20); + const Score QueenOn7thBonus = make_score(1, 8); + + // Rooks and queens attacking pawns on the same rank + const Score RookOnPawnBonus = make_score(3, 48); + const Score QueenOnPawnBonus = make_score(1, 40); // Rooks on open files (modified by Joona Kiiski) - const Score RookOpenFileBonus = make_score(43, 21); + const Score RookOpenFileBonus = make_score(43, 21); const Score RookHalfOpenFileBonus = make_score(19, 10); // Penalty for rooks trapped inside a friendly king which has lost the @@ -595,12 +599,18 @@ Value do_evaluate(const Position& pos, Value& margin) { && !(pos.pieces(Them, PAWN) & attack_span_mask(Us, s))) score += evaluate_outposts(pos, ei, s); - // Queen or rook on 7th rank - if ( (Piece == ROOK || Piece == QUEEN) - && relative_rank(Us, s) == RANK_7 - && relative_rank(Us, pos.king_square(Them)) == RANK_8) + if ((Piece == ROOK || Piece == QUEEN) && relative_rank(Us, s) >= RANK_5) { - score += (Piece == ROOK ? RookOn7thBonus : QueenOn7thBonus); + // Major piece on 7th rank + if ( relative_rank(Us, s) == RANK_7 + && relative_rank(Us, pos.king_square(Them)) == RANK_8) + score += (Piece == ROOK ? RookOn7thBonus : QueenOn7thBonus); + + // Major piece attacking pawns on the same rank + Bitboard pawns = pos.pieces(Them, PAWN) & rank_bb(s); + if (pawns) + score += (Piece == ROOK ? RookOnPawnBonus + : QueenOnPawnBonus) * popcount(pawns); } // Special extra evaluation for bishops diff --git a/DroidFish/jni/stockfish/misc.cpp b/DroidFish/jni/stockfish/misc.cpp index 33c3f1f..627b5d4 100644 --- a/DroidFish/jni/stockfish/misc.cpp +++ b/DroidFish/jni/stockfish/misc.cpp @@ -33,7 +33,7 @@ using namespace std; /// Version number. If Version is left empty, then Tag plus current /// date (in the format YYMMDD) is used as a version number. -static const string Version = "2.3"; +static const string Version = "2.3.1"; static const string Tag = ""; diff --git a/DroidFish/jni/stockfish/movegen.cpp b/DroidFish/jni/stockfish/movegen.cpp index 4a19034..be848cf 100644 --- a/DroidFish/jni/stockfish/movegen.cpp +++ b/DroidFish/jni/stockfish/movegen.cpp @@ -31,7 +31,7 @@ (*mlist++).move = make_move(to - (d), to); } namespace { - template + template MoveStack* generate_castle(const Position& pos, MoveStack* mlist, Color us) { if (pos.castle_impeded(us, Side) || !pos.can_castle(make_castle_right(us, Side))) @@ -46,16 +46,18 @@ namespace { assert(!pos.in_check()); - for (Square s = kto; s != kfrom; s += (Square)(Side == KING_SIDE ? -1 : 1)) + const int K = Chess960 ? kto > kfrom ? -1 : 1 + : Side == KING_SIDE ? -1 : 1; + + for (Square s = kto; s != kfrom; s += (Square)K) if (pos.attackers_to(s) & enemies) return mlist; // Because we generate only legal castling moves we need to verify that // when moving the castling rook we do not discover some hidden checker. // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. - if ( pos.is_chess960() - && (pos.attackers_to(kto, pos.pieces() ^ rfrom) & enemies)) - return mlist; + if (Chess960 && (pos.attackers_to(kto, pos.pieces() ^ rfrom) & enemies)) + return mlist; (*mlist++).move = make(kfrom, rfrom); @@ -273,8 +275,16 @@ namespace { if (Type != CAPTURES && Type != EVASIONS && pos.can_castle(us)) { - mlist = generate_castle(pos, mlist, us); - mlist = generate_castle(pos, mlist, us); + if (pos.is_chess960()) + { + mlist = generate_castle(pos, mlist, us); + mlist = generate_castle(pos, mlist, us); + } + else + { + mlist = generate_castle(pos, mlist, us); + mlist = generate_castle(pos, mlist, us); + } } return mlist; diff --git a/DroidFish/jni/stockfish/search.cpp b/DroidFish/jni/stockfish/search.cpp index eeca973..6294859 100644 --- a/DroidFish/jni/stockfish/search.cpp +++ b/DroidFish/jni/stockfish/search.cpp @@ -224,7 +224,7 @@ size_t Search::perft(Position& pos, Depth depth) { void Search::think() { - static Book book; // Defined static to initialize the PRNG only once + static PolyglotBook book; // Defined static to initialize the PRNG only once Position& pos = RootPosition; Chess960 = pos.is_chess960();