├── AUTHORS ├── src ├── syzygy │ ├── tbprobe.h │ └── tbcore.h ├── evaluate.h ├── main.cpp ├── timeman.h ├── movegen.h ├── uci.h ├── thread_win32.h ├── pawns.h ├── material.h ├── misc.h ├── thread.h ├── endgame.h ├── search.h ├── tt.h ├── movepick.h ├── tt.cpp ├── psqt.cpp ├── timeman.cpp ├── thread.cpp ├── ucioption.cpp ├── misc.cpp ├── benchmark.cpp ├── bitbase.cpp ├── material.cpp ├── uci.cpp ├── movepick.cpp ├── bitboard.h ├── pawns.cpp ├── bitboard.cpp ├── types.h ├── position.h ├── Makefile └── movegen.cpp ├── .travis.yml └── Readme.md /AUTHORS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anil-matcha/Stockfish/master/AUTHORS -------------------------------------------------------------------------------- /src/syzygy/tbprobe.h: -------------------------------------------------------------------------------- 1 | #ifndef TBPROBE_H 2 | #define TBPROBE_H 3 | 4 | #include "../search.h" 5 | 6 | namespace Tablebases { 7 | 8 | extern int MaxCardinality; 9 | 10 | void init(const std::string& path); 11 | int probe_wdl(Position& pos, int *success); 12 | int probe_dtz(Position& pos, int *success); 13 | bool root_probe(Position& pos, Search::RootMoveVector& rootMoves, Value& score); 14 | bool root_probe_wdl(Position& pos, Search::RootMoveVector& rootMoves, Value& score); 15 | 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | sudo: required 3 | dist: trusty 4 | 5 | matrix: 6 | include: 7 | - os: linux 8 | compiler: gcc 9 | addons: 10 | apt: 11 | sources: ['ubuntu-toolchain-r-test'] 12 | packages: ['g++-multilib'] 13 | env: 14 | - COMPILER=g++ 15 | - COMP=gcc 16 | 17 | - os: linux 18 | compiler: clang 19 | addons: 20 | apt: 21 | sources: ['ubuntu-toolchain-r-test'] 22 | packages: ['clang', 'g++-multilib'] 23 | env: 24 | - COMPILER=clang++ 25 | - COMP=clang 26 | 27 | - os: osx 28 | compiler: gcc 29 | env: 30 | - COMPILER=g++ 31 | - COMP=gcc 32 | 33 | - os: osx 34 | compiler: clang 35 | env: 36 | - COMPILER=clang++ V='Apple LLVM 6.0' # Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) 37 | - COMP=clang 38 | 39 | branches: 40 | only: 41 | - master 42 | 43 | before_script: 44 | - cd src 45 | 46 | script: 47 | - make clean && make build ARCH=x86-64 && ./stockfish bench 2>&1 >/dev/null | grep 'Nodes searched' | tee bench1 48 | - make clean && make build ARCH=x86-32 && ./stockfish bench 2>&1 >/dev/null | grep 'Nodes searched' | tee bench2 49 | - echo "Checking for same bench numbers..." 50 | - diff bench1 bench2 > result 51 | - test ! -s result 52 | -------------------------------------------------------------------------------- /src/evaluate.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef EVALUATE_H_INCLUDED 22 | #define EVALUATE_H_INCLUDED 23 | 24 | #include 25 | 26 | #include "types.h" 27 | 28 | class Position; 29 | 30 | namespace Eval { 31 | 32 | const Value Tempo = Value(20); // Must be visible to search 33 | 34 | void init(); 35 | std::string trace(const Position& pos); 36 | 37 | template 38 | Value evaluate(const Position& pos); 39 | } 40 | 41 | #endif // #ifndef EVALUATE_H_INCLUDED 42 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include "bitboard.h" 24 | #include "evaluate.h" 25 | #include "position.h" 26 | #include "search.h" 27 | #include "thread.h" 28 | #include "tt.h" 29 | #include "uci.h" 30 | #include "syzygy/tbprobe.h" 31 | 32 | int main(int argc, char* argv[]) { 33 | 34 | std::cout << engine_info() << std::endl; 35 | 36 | UCI::init(Options); 37 | PSQT::init(); 38 | Bitboards::init(); 39 | Position::init(); 40 | Bitbases::init(); 41 | Search::init(); 42 | Eval::init(); 43 | Pawns::init(); 44 | Threads.init(); 45 | Tablebases::init(Options["SyzygyPath"]); 46 | TT.resize(Options["Hash"]); 47 | 48 | UCI::loop(argc, argv); 49 | 50 | Threads.exit(); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /src/timeman.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef TIMEMAN_H_INCLUDED 22 | #define TIMEMAN_H_INCLUDED 23 | 24 | #include "misc.h" 25 | #include "search.h" 26 | #include "thread.h" 27 | 28 | /// The TimeManagement class computes the optimal time to think depending on 29 | /// the maximum available time, the game move number and other parameters. 30 | 31 | class TimeManagement { 32 | public: 33 | void init(Search::LimitsType& limits, Color us, int ply); 34 | int optimum() const { return optimumTime; } 35 | int maximum() const { return maximumTime; } 36 | int elapsed() const { return int(Search::Limits.npmsec ? Threads.nodes_searched() : now() - startTime); } 37 | 38 | int64_t availableNodes; // When in 'nodes as time' mode 39 | 40 | private: 41 | TimePoint startTime; 42 | int optimumTime; 43 | int maximumTime; 44 | }; 45 | 46 | extern TimeManagement Time; 47 | 48 | #endif // #ifndef TIMEMAN_H_INCLUDED 49 | -------------------------------------------------------------------------------- /src/movegen.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef MOVEGEN_H_INCLUDED 22 | #define MOVEGEN_H_INCLUDED 23 | 24 | #include "types.h" 25 | 26 | class Position; 27 | 28 | enum GenType { 29 | CAPTURES, 30 | QUIETS, 31 | QUIET_CHECKS, 32 | EVASIONS, 33 | NON_EVASIONS, 34 | LEGAL 35 | }; 36 | 37 | struct ExtMove { 38 | Move move; 39 | Value value; 40 | 41 | operator Move() const { return move; } 42 | void operator=(Move m) { move = m; } 43 | }; 44 | 45 | inline bool operator<(const ExtMove& f, const ExtMove& s) { 46 | return f.value < s.value; 47 | } 48 | 49 | template 50 | ExtMove* generate(const Position& pos, ExtMove* moveList); 51 | 52 | /// The MoveList struct is a simple wrapper around generate(). It sometimes comes 53 | /// in handy to use this class instead of the low level generate() function. 54 | template 55 | struct MoveList { 56 | 57 | explicit MoveList(const Position& pos) : last(generate(pos, moveList)) {} 58 | const ExtMove* begin() const { return moveList; } 59 | const ExtMove* end() const { return last; } 60 | size_t size() const { return last - moveList; } 61 | bool contains(Move move) const { 62 | for (const auto& m : *this) if (m == move) return true; 63 | return false; 64 | } 65 | 66 | private: 67 | ExtMove moveList[MAX_MOVES], *last; 68 | }; 69 | 70 | #endif // #ifndef MOVEGEN_H_INCLUDED 71 | -------------------------------------------------------------------------------- /src/uci.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef UCI_H_INCLUDED 22 | #define UCI_H_INCLUDED 23 | 24 | #include 25 | #include 26 | 27 | #include "types.h" 28 | 29 | class Position; 30 | 31 | namespace UCI { 32 | 33 | class Option; 34 | 35 | /// Custom comparator because UCI options should be case insensitive 36 | struct CaseInsensitiveLess { 37 | bool operator() (const std::string&, const std::string&) const; 38 | }; 39 | 40 | /// Our options container is actually a std::map 41 | typedef std::map OptionsMap; 42 | 43 | /// Option class implements an option as defined by UCI protocol 44 | class Option { 45 | 46 | typedef void (*OnChange)(const Option&); 47 | 48 | public: 49 | Option(OnChange = nullptr); 50 | Option(bool v, OnChange = nullptr); 51 | Option(const char* v, OnChange = nullptr); 52 | Option(int v, int min, int max, OnChange = nullptr); 53 | 54 | Option& operator=(const std::string&); 55 | void operator<<(const Option&); 56 | operator int() const; 57 | operator std::string() const; 58 | 59 | private: 60 | friend std::ostream& operator<<(std::ostream&, const OptionsMap&); 61 | 62 | std::string defaultValue, currentValue, type; 63 | int min, max; 64 | size_t idx; 65 | OnChange on_change; 66 | }; 67 | 68 | void init(OptionsMap&); 69 | void loop(int argc, char* argv[]); 70 | std::string value(Value v); 71 | std::string square(Square s); 72 | std::string move(Move m, bool chess960); 73 | std::string pv(const Position& pos, Depth depth, Value alpha, Value beta); 74 | Move to_move(const Position& pos, std::string& str); 75 | 76 | } // namespace UCI 77 | 78 | extern UCI::OptionsMap Options; 79 | 80 | #endif // #ifndef UCI_H_INCLUDED 81 | -------------------------------------------------------------------------------- /src/thread_win32.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef THREAD_WIN32_H_INCLUDED 22 | #define THREAD_WIN32_H_INCLUDED 23 | 24 | /// STL thread library used by mingw and gcc when cross compiling for Windows 25 | /// relies on libwinpthread. Currently libwinpthread implements mutexes directly 26 | /// on top of Windows semaphores. Semaphores, being kernel objects, require kernel 27 | /// mode transition in order to lock or unlock, which is very slow compared to 28 | /// interlocked operations (about 30% slower on bench test). To work around this 29 | /// issue, we define our wrappers to the low level Win32 calls. We use critical 30 | /// sections to support Windows XP and older versions. Unfortunately, cond_wait() 31 | /// is racy between unlock() and WaitForSingleObject() but they have the same 32 | /// speed performance as the SRW locks. 33 | 34 | #include 35 | #include 36 | 37 | #if defined(_WIN32) && !defined(_MSC_VER) 38 | 39 | #ifndef NOMINMAX 40 | # define NOMINMAX // Disable macros min() and max() 41 | #endif 42 | 43 | #define WIN32_LEAN_AND_MEAN 44 | #include 45 | #undef WIN32_LEAN_AND_MEAN 46 | #undef NOMINMAX 47 | 48 | /// Mutex and ConditionVariable struct are wrappers of the low level locking 49 | /// machinery and are modeled after the corresponding C++11 classes. 50 | 51 | struct Mutex { 52 | Mutex() { InitializeCriticalSection(&cs); } 53 | ~Mutex() { DeleteCriticalSection(&cs); } 54 | void lock() { EnterCriticalSection(&cs); } 55 | void unlock() { LeaveCriticalSection(&cs); } 56 | 57 | private: 58 | CRITICAL_SECTION cs; 59 | }; 60 | 61 | typedef std::condition_variable_any ConditionVariable; 62 | 63 | #else // Default case: use STL classes 64 | 65 | typedef std::mutex Mutex; 66 | typedef std::condition_variable ConditionVariable; 67 | 68 | #endif 69 | 70 | #endif // #ifndef THREAD_WIN32_H_INCLUDED 71 | -------------------------------------------------------------------------------- /src/pawns.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef PAWNS_H_INCLUDED 22 | #define PAWNS_H_INCLUDED 23 | 24 | #include "misc.h" 25 | #include "position.h" 26 | #include "types.h" 27 | 28 | namespace Pawns { 29 | 30 | /// Pawns::Entry contains various information about a pawn structure. A lookup 31 | /// to the pawn hash table (performed by calling the probe function) returns a 32 | /// pointer to an Entry object. 33 | 34 | struct Entry { 35 | 36 | Score pawns_score() const { return score; } 37 | Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; } 38 | Bitboard passed_pawns(Color c) const { return passedPawns[c]; } 39 | Bitboard pawn_attacks_span(Color c) const { return pawnAttacksSpan[c]; } 40 | int pawn_span(Color c) const { return pawnSpan[c]; } 41 | int pawn_asymmetry() const { return asymmetry; } 42 | 43 | int semiopen_file(Color c, File f) const { 44 | return semiopenFiles[c] & (1 << f); 45 | } 46 | 47 | int semiopen_side(Color c, File f, bool leftSide) const { 48 | return semiopenFiles[c] & (leftSide ? (1 << f) - 1 : ~((1 << (f + 1)) - 1)); 49 | } 50 | 51 | int pawns_on_same_color_squares(Color c, Square s) const { 52 | return pawnsOnSquares[c][!!(DarkSquares & s)]; 53 | } 54 | 55 | template 56 | Score king_safety(const Position& pos, Square ksq) { 57 | return kingSquares[Us] == ksq && castlingRights[Us] == pos.can_castle(Us) 58 | ? kingSafety[Us] : (kingSafety[Us] = do_king_safety(pos, ksq)); 59 | } 60 | 61 | template 62 | Score do_king_safety(const Position& pos, Square ksq); 63 | 64 | template 65 | Value shelter_storm(const Position& pos, Square ksq); 66 | 67 | Key key; 68 | Score score; 69 | Bitboard passedPawns[COLOR_NB]; 70 | Bitboard pawnAttacks[COLOR_NB]; 71 | Bitboard pawnAttacksSpan[COLOR_NB]; 72 | Square kingSquares[COLOR_NB]; 73 | Score kingSafety[COLOR_NB]; 74 | int castlingRights[COLOR_NB]; 75 | int semiopenFiles[COLOR_NB]; 76 | int pawnSpan[COLOR_NB]; 77 | int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares] 78 | int asymmetry; 79 | }; 80 | 81 | typedef HashTable Table; 82 | 83 | void init(); 84 | Entry* probe(const Position& pos); 85 | 86 | } // namespace Pawns 87 | 88 | #endif // #ifndef PAWNS_H_INCLUDED 89 | -------------------------------------------------------------------------------- /src/material.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef MATERIAL_H_INCLUDED 22 | #define MATERIAL_H_INCLUDED 23 | 24 | #include "endgame.h" 25 | #include "misc.h" 26 | #include "position.h" 27 | #include "types.h" 28 | 29 | namespace Material { 30 | 31 | /// Material::Entry contains various information about a material configuration. 32 | /// It contains a material imbalance evaluation, a function pointer to a special 33 | /// endgame evaluation function (which in most cases is NULL, meaning that the 34 | /// standard evaluation function will be used), and scale factors. 35 | /// 36 | /// The scale factors are used to scale the evaluation score up or down. For 37 | /// instance, in KRB vs KR endgames, the score is scaled down by a factor of 4, 38 | /// which will result in scores of absolute value less than one pawn. 39 | 40 | struct Entry { 41 | 42 | Score imbalance() const { return make_score(value, value); } 43 | Phase game_phase() const { return gamePhase; } 44 | bool specialized_eval_exists() const { return evaluationFunction != nullptr; } 45 | Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); } 46 | 47 | // scale_factor takes a position and a color as input and returns a scale factor 48 | // for the given color. We have to provide the position in addition to the color 49 | // because the scale factor may also be a function which should be applied to 50 | // the position. For instance, in KBP vs K endgames, the scaling function looks 51 | // for rook pawns and wrong-colored bishops. 52 | ScaleFactor scale_factor(const Position& pos, Color c) const { 53 | return !scalingFunction[c] 54 | || (*scalingFunction[c])(pos) == SCALE_FACTOR_NONE ? ScaleFactor(factor[c]) 55 | : (*scalingFunction[c])(pos); 56 | } 57 | 58 | Key key; 59 | int16_t value; 60 | uint8_t factor[COLOR_NB]; 61 | EndgameBase* evaluationFunction; 62 | EndgameBase* scalingFunction[COLOR_NB]; // Could be one for each 63 | // side (e.g. KPKP, KBPsKs) 64 | Phase gamePhase; 65 | }; 66 | 67 | typedef HashTable Table; 68 | 69 | Entry* probe(const Position& pos); 70 | 71 | } // namespace Material 72 | 73 | #endif // #ifndef MATERIAL_H_INCLUDED 74 | -------------------------------------------------------------------------------- /src/misc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef MISC_H_INCLUDED 22 | #define MISC_H_INCLUDED 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "types.h" 31 | 32 | const std::string engine_info(bool to_uci = false); 33 | void prefetch(void* addr); 34 | void start_logger(bool b); 35 | 36 | void dbg_hit_on(bool b); 37 | void dbg_hit_on(bool c, bool b); 38 | void dbg_mean_of(int v); 39 | void dbg_print(); 40 | 41 | typedef std::chrono::milliseconds::rep TimePoint; // A value in milliseconds 42 | 43 | inline TimePoint now() { 44 | return std::chrono::duration_cast 45 | (std::chrono::steady_clock::now().time_since_epoch()).count(); 46 | } 47 | 48 | template 49 | struct HashTable { 50 | Entry* operator[](Key key) { return &table[(uint32_t)key & (Size - 1)]; } 51 | 52 | private: 53 | std::vector table = std::vector(Size); 54 | }; 55 | 56 | 57 | enum SyncCout { IO_LOCK, IO_UNLOCK }; 58 | std::ostream& operator<<(std::ostream&, SyncCout); 59 | 60 | #define sync_cout std::cout << IO_LOCK 61 | #define sync_endl std::endl << IO_UNLOCK 62 | 63 | 64 | /// xorshift64star Pseudo-Random Number Generator 65 | /// This class is based on original code written and dedicated 66 | /// to the public domain by Sebastiano Vigna (2014). 67 | /// It has the following characteristics: 68 | /// 69 | /// - Outputs 64-bit numbers 70 | /// - Passes Dieharder and SmallCrush test batteries 71 | /// - Does not require warm-up, no zeroland to escape 72 | /// - Internal state is a single 64-bit integer 73 | /// - Period is 2^64 - 1 74 | /// - Speed: 1.60 ns/call (Core i7 @3.40GHz) 75 | /// 76 | /// For further analysis see 77 | /// 78 | 79 | class PRNG { 80 | 81 | uint64_t s; 82 | 83 | uint64_t rand64() { 84 | 85 | s ^= s >> 12, s ^= s << 25, s ^= s >> 27; 86 | return s * 2685821657736338717LL; 87 | } 88 | 89 | public: 90 | PRNG(uint64_t seed) : s(seed) { assert(seed); } 91 | 92 | template T rand() { return T(rand64()); } 93 | 94 | /// Special generator used to fast init magic numbers. 95 | /// Output values only have 1/8th of their bits set on average. 96 | template T sparse_rand() 97 | { return T(rand64() & rand64() & rand64()); } 98 | }; 99 | 100 | #endif // #ifndef MISC_H_INCLUDED 101 | -------------------------------------------------------------------------------- /src/thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef THREAD_H_INCLUDED 22 | #define THREAD_H_INCLUDED 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "material.h" 32 | #include "movepick.h" 33 | #include "pawns.h" 34 | #include "position.h" 35 | #include "search.h" 36 | #include "thread_win32.h" 37 | 38 | 39 | /// Thread struct keeps together all the thread-related stuff. We also use 40 | /// per-thread pawn and material hash tables so that once we get a pointer to an 41 | /// entry its life time is unlimited and we don't have to care about someone 42 | /// changing the entry under our feet. 43 | 44 | class Thread { 45 | 46 | std::thread nativeThread; 47 | Mutex mutex; 48 | ConditionVariable sleepCondition; 49 | bool exit, searching; 50 | 51 | public: 52 | Thread(); 53 | virtual ~Thread(); 54 | virtual void search(); 55 | void idle_loop(); 56 | void start_searching(bool resume = false); 57 | void wait_for_search_finished(); 58 | void wait(std::atomic_bool& b); 59 | 60 | Pawns::Table pawnsTable; 61 | Material::Table materialTable; 62 | Endgames endgames; 63 | size_t idx, PVIdx; 64 | int maxPly, callsCnt; 65 | 66 | Position rootPos; 67 | Search::RootMoveVector rootMoves; 68 | Depth rootDepth; 69 | HistoryStats history; 70 | MoveStats counterMoves; 71 | Depth completedDepth; 72 | std::atomic_bool resetCalls; 73 | }; 74 | 75 | 76 | /// MainThread is a derived class with a specific overload for the main thread 77 | 78 | struct MainThread : public Thread { 79 | virtual void search(); 80 | 81 | bool easyMovePlayed, failedLow; 82 | double bestMoveChanges; 83 | Value previousScore; 84 | }; 85 | 86 | 87 | /// ThreadPool struct handles all the threads-related stuff like init, starting, 88 | /// parking and, most importantly, launching a thread. All the access to threads 89 | /// data is done through this class. 90 | 91 | struct ThreadPool : public std::vector { 92 | 93 | void init(); // No constructor and destructor, threads rely on globals that should 94 | void exit(); // be initialized and valid during the whole thread lifetime. 95 | 96 | MainThread* main() { return static_cast(at(0)); } 97 | void start_thinking(const Position&, const Search::LimitsType&, Search::StateStackPtr&); 98 | void read_uci_options(); 99 | int64_t nodes_searched(); 100 | }; 101 | 102 | extern ThreadPool Threads; 103 | 104 | #endif // #ifndef THREAD_H_INCLUDED 105 | -------------------------------------------------------------------------------- /src/endgame.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef ENDGAME_H_INCLUDED 22 | #define ENDGAME_H_INCLUDED 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "position.h" 31 | #include "types.h" 32 | 33 | 34 | /// EndgameType lists all supported endgames 35 | 36 | enum EndgameType { 37 | 38 | // Evaluation functions 39 | 40 | KNNK, // KNN vs K 41 | KXK, // Generic "mate lone king" eval 42 | KBNK, // KBN vs K 43 | KPK, // KP vs K 44 | KRKP, // KR vs KP 45 | KRKB, // KR vs KB 46 | KRKN, // KR vs KN 47 | KQKP, // KQ vs KP 48 | KQKR, // KQ vs KR 49 | 50 | 51 | // Scaling functions 52 | SCALING_FUNCTIONS, 53 | 54 | KBPsK, // KB and pawns vs K 55 | KQKRPs, // KQ vs KR and pawns 56 | KRPKR, // KRP vs KR 57 | KRPKB, // KRP vs KB 58 | KRPPKRP, // KRPP vs KRP 59 | KPsK, // K and pawns vs K 60 | KBPKB, // KBP vs KB 61 | KBPPKB, // KBPP vs KB 62 | KBPKN, // KBP vs KN 63 | KNPK, // KNP vs K 64 | KNPKB, // KNP vs KB 65 | KPKP // KP vs KP 66 | }; 67 | 68 | 69 | /// Endgame functions can be of two types depending on whether they return a 70 | /// Value or a ScaleFactor. 71 | template using 72 | eg_type = typename std::conditional<(E < SCALING_FUNCTIONS), Value, ScaleFactor>::type; 73 | 74 | 75 | /// Base and derived templates for endgame evaluation and scaling functions 76 | 77 | template 78 | struct EndgameBase { 79 | 80 | virtual ~EndgameBase() = default; 81 | virtual Color strong_side() const = 0; 82 | virtual T operator()(const Position&) const = 0; 83 | }; 84 | 85 | 86 | template> 87 | struct Endgame : public EndgameBase { 88 | 89 | explicit Endgame(Color c) : strongSide(c), weakSide(~c) {} 90 | Color strong_side() const { return strongSide; } 91 | T operator()(const Position&) const; 92 | 93 | private: 94 | Color strongSide, weakSide; 95 | }; 96 | 97 | 98 | /// The Endgames class stores the pointers to endgame evaluation and scaling 99 | /// base objects in two std::map. We use polymorphism to invoke the actual 100 | /// endgame function by calling its virtual operator(). 101 | 102 | class Endgames { 103 | 104 | template using Map = std::map>>; 105 | 106 | template> 107 | void add(const std::string& code); 108 | 109 | template 110 | Map& map() { 111 | return std::get::value>(maps); 112 | } 113 | 114 | std::pair, Map> maps; 115 | 116 | public: 117 | Endgames(); 118 | 119 | template 120 | EndgameBase* probe(Key key) { 121 | return map().count(key) ? map()[key].get() : nullptr; 122 | } 123 | }; 124 | 125 | #endif // #ifndef ENDGAME_H_INCLUDED 126 | -------------------------------------------------------------------------------- /src/syzygy/tbcore.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011-2013 Ronald de Man 3 | */ 4 | 5 | #ifndef TBCORE_H 6 | #define TBCORE_H 7 | 8 | #ifndef _WIN32 9 | #include 10 | #define SEP_CHAR ':' 11 | #define FD int 12 | #define FD_ERR -1 13 | #else 14 | #include 15 | #define SEP_CHAR ';' 16 | #define FD HANDLE 17 | #define FD_ERR INVALID_HANDLE_VALUE 18 | #endif 19 | 20 | #ifndef _WIN32 21 | #define LOCK_T pthread_mutex_t 22 | #define LOCK_INIT(x) pthread_mutex_init(&(x), NULL) 23 | #define LOCK(x) pthread_mutex_lock(&(x)) 24 | #define UNLOCK(x) pthread_mutex_unlock(&(x)) 25 | #else 26 | #define LOCK_T HANDLE 27 | #define LOCK_INIT(x) do { x = CreateMutex(NULL, FALSE, NULL); } while (0) 28 | #define LOCK(x) WaitForSingleObject(x, INFINITE) 29 | #define UNLOCK(x) ReleaseMutex(x) 30 | #endif 31 | 32 | #ifndef _MSC_VER 33 | #define BSWAP32(v) __builtin_bswap32(v) 34 | #define BSWAP64(v) __builtin_bswap64(v) 35 | #else 36 | #define BSWAP32(v) _byteswap_ulong(v) 37 | #define BSWAP64(v) _byteswap_uint64(v) 38 | #endif 39 | 40 | #define WDLSUFFIX ".rtbw" 41 | #define DTZSUFFIX ".rtbz" 42 | #define WDLDIR "RTBWDIR" 43 | #define DTZDIR "RTBZDIR" 44 | #define TBPIECES 6 45 | 46 | typedef unsigned long long uint64; 47 | typedef unsigned int uint32; 48 | typedef unsigned char ubyte; 49 | typedef unsigned short ushort; 50 | 51 | const ubyte WDL_MAGIC[4] = { 0x71, 0xe8, 0x23, 0x5d }; 52 | const ubyte DTZ_MAGIC[4] = { 0xd7, 0x66, 0x0c, 0xa5 }; 53 | 54 | #define TBHASHBITS 10 55 | 56 | struct TBHashEntry; 57 | 58 | typedef uint64 base_t; 59 | 60 | struct PairsData { 61 | char *indextable; 62 | ushort *sizetable; 63 | ubyte *data; 64 | ushort *offset; 65 | ubyte *symlen; 66 | ubyte *sympat; 67 | int blocksize; 68 | int idxbits; 69 | int min_len; 70 | base_t base[1]; // C++ complains about base[]... 71 | }; 72 | 73 | struct TBEntry { 74 | char *data; 75 | uint64 key; 76 | uint64 mapping; 77 | ubyte ready; 78 | ubyte num; 79 | ubyte symmetric; 80 | ubyte has_pawns; 81 | } 82 | #ifndef _WIN32 83 | __attribute__((__may_alias__)) 84 | #endif 85 | ; 86 | 87 | struct TBEntry_piece { 88 | char *data; 89 | uint64 key; 90 | uint64 mapping; 91 | ubyte ready; 92 | ubyte num; 93 | ubyte symmetric; 94 | ubyte has_pawns; 95 | ubyte enc_type; 96 | struct PairsData *precomp[2]; 97 | int factor[2][TBPIECES]; 98 | ubyte pieces[2][TBPIECES]; 99 | ubyte norm[2][TBPIECES]; 100 | }; 101 | 102 | struct TBEntry_pawn { 103 | char *data; 104 | uint64 key; 105 | uint64 mapping; 106 | ubyte ready; 107 | ubyte num; 108 | ubyte symmetric; 109 | ubyte has_pawns; 110 | ubyte pawns[2]; 111 | struct { 112 | struct PairsData *precomp[2]; 113 | int factor[2][TBPIECES]; 114 | ubyte pieces[2][TBPIECES]; 115 | ubyte norm[2][TBPIECES]; 116 | } file[4]; 117 | }; 118 | 119 | struct DTZEntry_piece { 120 | char *data; 121 | uint64 key; 122 | uint64 mapping; 123 | ubyte ready; 124 | ubyte num; 125 | ubyte symmetric; 126 | ubyte has_pawns; 127 | ubyte enc_type; 128 | struct PairsData *precomp; 129 | int factor[TBPIECES]; 130 | ubyte pieces[TBPIECES]; 131 | ubyte norm[TBPIECES]; 132 | ubyte flags; // accurate, mapped, side 133 | ushort map_idx[4]; 134 | ubyte *map; 135 | }; 136 | 137 | struct DTZEntry_pawn { 138 | char *data; 139 | uint64 key; 140 | uint64 mapping; 141 | ubyte ready; 142 | ubyte num; 143 | ubyte symmetric; 144 | ubyte has_pawns; 145 | ubyte pawns[2]; 146 | struct { 147 | struct PairsData *precomp; 148 | int factor[TBPIECES]; 149 | ubyte pieces[TBPIECES]; 150 | ubyte norm[TBPIECES]; 151 | } file[4]; 152 | ubyte flags[4]; 153 | ushort map_idx[4][4]; 154 | ubyte *map; 155 | }; 156 | 157 | struct TBHashEntry { 158 | uint64 key; 159 | struct TBEntry *ptr; 160 | }; 161 | 162 | struct DTZTableEntry { 163 | uint64 key1; 164 | uint64 key2; 165 | struct TBEntry *entry; 166 | }; 167 | 168 | #endif 169 | 170 | -------------------------------------------------------------------------------- /src/search.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef SEARCH_H_INCLUDED 22 | #define SEARCH_H_INCLUDED 23 | 24 | #include 25 | #include // For std::unique_ptr 26 | #include 27 | #include 28 | 29 | #include "misc.h" 30 | #include "position.h" 31 | #include "types.h" 32 | 33 | namespace Search { 34 | 35 | /// Stack struct keeps track of the information we need to remember from nodes 36 | /// shallower and deeper in the tree during the search. Each search thread has 37 | /// its own array of Stack objects, indexed by the current ply. 38 | 39 | struct Stack { 40 | Move* pv; 41 | int ply; 42 | Move currentMove; 43 | Move excludedMove; 44 | Move killers[2]; 45 | Value staticEval; 46 | bool skipEarlyPruning; 47 | int moveCount; 48 | }; 49 | 50 | /// RootMove struct is used for moves at the root of the tree. For each root move 51 | /// we store a score and a PV (really a refutation in the case of moves which 52 | /// fail low). Score is normally set at -VALUE_INFINITE for all non-pv moves. 53 | 54 | struct RootMove { 55 | 56 | explicit RootMove(Move m) : pv(1, m) {} 57 | 58 | bool operator<(const RootMove& m) const { return m.score < score; } // Descending sort 59 | bool operator==(const Move& m) const { return pv[0] == m; } 60 | void insert_pv_in_tt(Position& pos); 61 | bool extract_ponder_from_tt(Position& pos); 62 | 63 | Value score = -VALUE_INFINITE; 64 | Value previousScore = -VALUE_INFINITE; 65 | std::vector pv; 66 | }; 67 | 68 | typedef std::vector RootMoveVector; 69 | 70 | /// LimitsType struct stores information sent by GUI about available time to 71 | /// search the current move, maximum depth/time, if we are in analysis mode or 72 | /// if we have to ponder while it's our opponent's turn to move. 73 | 74 | struct LimitsType { 75 | 76 | LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC 77 | nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movestogo = 78 | depth = movetime = mate = infinite = ponder = 0; 79 | } 80 | 81 | bool use_time_management() const { 82 | return !(mate | movetime | depth | nodes | infinite); 83 | } 84 | 85 | std::vector searchmoves; 86 | int time[COLOR_NB], inc[COLOR_NB], npmsec, movestogo, depth, movetime, mate, infinite, ponder; 87 | int64_t nodes; 88 | TimePoint startTime; 89 | }; 90 | 91 | /// The SignalsType struct stores atomic flags updated during the search 92 | /// typically in an async fashion e.g. to stop the search by the GUI. 93 | 94 | struct SignalsType { 95 | std::atomic_bool stop, stopOnPonderhit; 96 | }; 97 | 98 | typedef std::unique_ptr> StateStackPtr; 99 | 100 | extern SignalsType Signals; 101 | extern LimitsType Limits; 102 | extern StateStackPtr SetupStates; 103 | 104 | void init(); 105 | void clear(); 106 | template uint64_t perft(Position& pos, Depth depth); 107 | 108 | } // namespace Search 109 | 110 | #endif // #ifndef SEARCH_H_INCLUDED 111 | -------------------------------------------------------------------------------- /src/tt.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef TT_H_INCLUDED 22 | #define TT_H_INCLUDED 23 | 24 | #include "misc.h" 25 | #include "types.h" 26 | 27 | /// TTEntry struct is the 10 bytes transposition table entry, defined as below: 28 | /// 29 | /// key 16 bit 30 | /// move 16 bit 31 | /// value 16 bit 32 | /// eval value 16 bit 33 | /// generation 6 bit 34 | /// bound type 2 bit 35 | /// depth 8 bit 36 | 37 | struct TTEntry { 38 | 39 | Move move() const { return (Move )move16; } 40 | Value value() const { return (Value)value16; } 41 | Value eval() const { return (Value)eval16; } 42 | Depth depth() const { return (Depth)depth8; } 43 | Bound bound() const { return (Bound)(genBound8 & 0x3); } 44 | 45 | void save(Key k, Value v, Bound b, Depth d, Move m, Value ev, uint8_t g) { 46 | 47 | // Preserve any existing move for the same position 48 | if (m || (k >> 48) != key16) 49 | move16 = (uint16_t)m; 50 | 51 | // Don't overwrite more valuable entries 52 | if ( (k >> 48) != key16 53 | || d > depth8 - 4 54 | /* || g != (genBound8 & 0xFC) // Matching non-zero keys are already refreshed by probe() */ 55 | || b == BOUND_EXACT) 56 | { 57 | key16 = (uint16_t)(k >> 48); 58 | value16 = (int16_t)v; 59 | eval16 = (int16_t)ev; 60 | genBound8 = (uint8_t)(g | b); 61 | depth8 = (int8_t)d; 62 | } 63 | } 64 | 65 | private: 66 | friend class TranspositionTable; 67 | 68 | uint16_t key16; 69 | uint16_t move16; 70 | int16_t value16; 71 | int16_t eval16; 72 | uint8_t genBound8; 73 | int8_t depth8; 74 | }; 75 | 76 | 77 | /// A TranspositionTable consists of a power of 2 number of clusters and each 78 | /// cluster consists of ClusterSize number of TTEntry. Each non-empty entry 79 | /// contains information of exactly one position. The size of a cluster should 80 | /// divide the size of a cache line size, to ensure that clusters never cross 81 | /// cache lines. This ensures best cache performance, as the cacheline is 82 | /// prefetched, as soon as possible. 83 | 84 | class TranspositionTable { 85 | 86 | static const int CacheLineSize = 64; 87 | static const int ClusterSize = 3; 88 | 89 | struct Cluster { 90 | TTEntry entry[ClusterSize]; 91 | char padding[2]; // Align to a divisor of the cache line size 92 | }; 93 | 94 | static_assert(CacheLineSize % sizeof(Cluster) == 0, "Cluster size incorrect"); 95 | 96 | public: 97 | ~TranspositionTable() { free(mem); } 98 | void new_search() { generation8 += 4; } // Lower 2 bits are used by Bound 99 | uint8_t generation() const { return generation8; } 100 | TTEntry* probe(const Key key, bool& found) const; 101 | int hashfull() const; 102 | void resize(size_t mbSize); 103 | void clear(); 104 | 105 | // The lowest order bits of the key are used to get the index of the cluster 106 | TTEntry* first_entry(const Key key) const { 107 | return &table[(size_t)key & (clusterCount - 1)].entry[0]; 108 | } 109 | 110 | private: 111 | size_t clusterCount; 112 | Cluster* table; 113 | void* mem; 114 | uint8_t generation8; // Size must be not bigger than TTEntry::genBound8 115 | }; 116 | 117 | extern TranspositionTable TT; 118 | 119 | #endif // #ifndef TT_H_INCLUDED 120 | -------------------------------------------------------------------------------- /src/movepick.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef MOVEPICK_H_INCLUDED 22 | #define MOVEPICK_H_INCLUDED 23 | 24 | #include // For std::max 25 | #include // For std::memset 26 | 27 | #include "movegen.h" 28 | #include "position.h" 29 | #include "search.h" 30 | #include "types.h" 31 | 32 | 33 | /// The Stats struct stores moves statistics. According to the template parameter 34 | /// the class can store History and Countermoves. History records how often 35 | /// different moves have been successful or unsuccessful during the current search 36 | /// and is used for reduction and move ordering decisions. 37 | /// Countermoves store the move that refute a previous one. Entries are stored 38 | /// using only the moving piece and destination square, hence two moves with 39 | /// different origin but same destination and piece will be considered identical. 40 | template 41 | struct Stats { 42 | 43 | static const Value Max = Value(1 << 28); 44 | 45 | const T* operator[](Piece pc) const { return table[pc]; } 46 | T* operator[](Piece pc) { return table[pc]; } 47 | void clear() { std::memset(table, 0, sizeof(table)); } 48 | 49 | void update(Piece pc, Square to, Move m) { table[pc][to] = m; } 50 | 51 | void update(Piece pc, Square to, Value v) { 52 | 53 | if (abs(int(v)) >= 324) 54 | return; 55 | 56 | table[pc][to] -= table[pc][to] * abs(int(v)) / (CM ? 936 : 324); 57 | table[pc][to] += int(v) * 32; 58 | } 59 | 60 | private: 61 | T table[PIECE_NB][SQUARE_NB]; 62 | }; 63 | 64 | typedef Stats MoveStats; 65 | typedef Stats HistoryStats; 66 | typedef Stats CounterMoveStats; 67 | typedef Stats CounterMoveHistoryStats; 68 | 69 | 70 | /// MovePicker class is used to pick one pseudo legal move at a time from the 71 | /// current position. The most important method is next_move(), which returns a 72 | /// new pseudo legal move each time it is called, until there are no moves left, 73 | /// when MOVE_NONE is returned. In order to improve the efficiency of the alpha 74 | /// beta algorithm, MovePicker attempts to return the moves which are most likely 75 | /// to get a cut-off first. 76 | 77 | class MovePicker { 78 | public: 79 | MovePicker(const MovePicker&) = delete; 80 | MovePicker& operator=(const MovePicker&) = delete; 81 | 82 | MovePicker(const Position&, Move, const HistoryStats&, Value); 83 | MovePicker(const Position&, Move, Depth, const HistoryStats&, Square); 84 | MovePicker(const Position&, Move, Depth, const HistoryStats&, 85 | const CounterMoveStats&, const CounterMoveStats&, Move, Search::Stack*); 86 | 87 | Move next_move(); 88 | 89 | private: 90 | template void score(); 91 | void generate_next_stage(); 92 | ExtMove* begin() { return moves; } 93 | ExtMove* end() { return endMoves; } 94 | 95 | const Position& pos; 96 | const HistoryStats& history; 97 | const CounterMoveStats* counterMoveHistory; 98 | const CounterMoveStats* followupMoveHistory; 99 | Search::Stack* ss; 100 | Move countermove; 101 | Depth depth; 102 | Move ttMove; 103 | ExtMove killers[3]; 104 | Square recaptureSquare; 105 | Value threshold; 106 | int stage; 107 | ExtMove *endQuiets, *endBadCaptures = moves + MAX_MOVES - 1; 108 | ExtMove moves[MAX_MOVES], *cur = moves, *endMoves = moves; 109 | }; 110 | 111 | #endif // #ifndef MOVEPICK_H_INCLUDED 112 | -------------------------------------------------------------------------------- /src/tt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include // For std::memset 22 | #include 23 | 24 | #include "bitboard.h" 25 | #include "tt.h" 26 | 27 | TranspositionTable TT; // Our global transposition table 28 | 29 | 30 | /// TranspositionTable::resize() sets the size of the transposition table, 31 | /// measured in megabytes. Transposition table consists of a power of 2 number 32 | /// of clusters and each cluster consists of ClusterSize number of TTEntry. 33 | 34 | void TranspositionTable::resize(size_t mbSize) { 35 | 36 | size_t newClusterCount = size_t(1) << msb((mbSize * 1024 * 1024) / sizeof(Cluster)); 37 | 38 | if (newClusterCount == clusterCount) 39 | return; 40 | 41 | clusterCount = newClusterCount; 42 | 43 | free(mem); 44 | mem = calloc(clusterCount * sizeof(Cluster) + CacheLineSize - 1, 1); 45 | 46 | if (!mem) 47 | { 48 | std::cerr << "Failed to allocate " << mbSize 49 | << "MB for transposition table." << std::endl; 50 | exit(EXIT_FAILURE); 51 | } 52 | 53 | table = (Cluster*)((uintptr_t(mem) + CacheLineSize - 1) & ~(CacheLineSize - 1)); 54 | } 55 | 56 | 57 | /// TranspositionTable::clear() overwrites the entire transposition table 58 | /// with zeros. It is called whenever the table is resized, or when the 59 | /// user asks the program to clear the table (from the UCI interface). 60 | 61 | void TranspositionTable::clear() { 62 | 63 | std::memset(table, 0, clusterCount * sizeof(Cluster)); 64 | } 65 | 66 | 67 | /// TranspositionTable::probe() looks up the current position in the transposition 68 | /// table. It returns true and a pointer to the TTEntry if the position is found. 69 | /// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry 70 | /// to be replaced later. The replace value of an entry is calculated as its depth 71 | /// minus 8 times its relative age. TTEntry t1 is considered more valuable than 72 | /// TTEntry t2 if its replace value is greater than that of t2. 73 | 74 | TTEntry* TranspositionTable::probe(const Key key, bool& found) const { 75 | 76 | TTEntry* const tte = first_entry(key); 77 | const uint16_t key16 = key >> 48; // Use the high 16 bits as key inside the cluster 78 | 79 | for (int i = 0; i < ClusterSize; ++i) 80 | if (!tte[i].key16 || tte[i].key16 == key16) 81 | { 82 | if ((tte[i].genBound8 & 0xFC) != generation8 && tte[i].key16) 83 | tte[i].genBound8 = uint8_t(generation8 | tte[i].bound()); // Refresh 84 | 85 | return found = (bool)tte[i].key16, &tte[i]; 86 | } 87 | 88 | // Find an entry to be replaced according to the replacement strategy 89 | TTEntry* replace = tte; 90 | for (int i = 1; i < ClusterSize; ++i) 91 | // Due to our packed storage format for generation and its cyclic 92 | // nature we add 259 (256 is the modulus plus 3 to keep the lowest 93 | // two bound bits from affecting the result) to calculate the entry 94 | // age correctly even after generation8 overflows into the next cycle. 95 | if ( replace->depth8 - ((259 + generation8 - replace->genBound8) & 0xFC) * 2 * ONE_PLY 96 | > tte[i].depth8 - ((259 + generation8 - tte[i].genBound8) & 0xFC) * 2 * ONE_PLY) 97 | replace = &tte[i]; 98 | 99 | return found = false, replace; 100 | } 101 | 102 | 103 | /// Returns an approximation of the hashtable occupation during a search. The 104 | /// hash is x permill full, as per UCI protocol. 105 | 106 | int TranspositionTable::hashfull() const 107 | { 108 | int cnt = 0; 109 | for (int i = 0; i < 1000 / ClusterSize; i++) 110 | { 111 | const TTEntry* tte = &table[i].entry[0]; 112 | for (int j = 0; j < ClusterSize; j++) 113 | if ((tte[j].genBound8 & 0xFC) == generation8) 114 | cnt++; 115 | } 116 | return cnt; 117 | } 118 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | ### Overview 2 | 3 | [![Build Status](https://travis-ci.org/official-stockfish/Stockfish.svg?branch=master)](https://travis-ci.org/official-stockfish/Stockfish) 4 | 5 | Stockfish is a free UCI chess engine derived from Glaurung 2.1. It is 6 | not a complete chess program and requires some UCI-compatible GUI 7 | (e.g. XBoard with PolyGlot, eboard, Arena, Sigma Chess, Shredder, Chess 8 | Partner or Fritz) in order to be used comfortably. Read the 9 | documentation for your GUI of choice for information about how to use 10 | Stockfish with it. 11 | 12 | This version of Stockfish supports up to 128 cores. The engine defaults 13 | to one search thread, so it is therefore recommended to inspect the value of 14 | the *Threads* UCI parameter, and to make sure it equals the number of CPU 15 | cores on your computer. 16 | 17 | This version of Stockfish has support for Syzygybases. 18 | 19 | 20 | ### Files 21 | 22 | This distribution of Stockfish consists of the following files: 23 | 24 | * Readme.md, the file you are currently reading. 25 | 26 | * Copying.txt, a text file containing the GNU General Public License. 27 | 28 | * src, a subdirectory containing the full source code, including a Makefile 29 | that can be used to compile Stockfish on Unix-like systems. 30 | 31 | 32 | ### Syzygybases 33 | 34 | **Configuration** 35 | 36 | Syzygybases are configured using the UCI options "SyzygyPath", 37 | "SyzygyProbeDepth", "Syzygy50MoveRule" and "SyzygyProbeLimit". 38 | 39 | The option "SyzygyPath" should be set to the directory or directories that 40 | contain the .rtbw and .rtbz files. Multiple directories should be 41 | separated by ";" on Windows and by ":" on Unix-based operating systems. 42 | **Do not use spaces around the ";" or ":".** 43 | 44 | Example: `C:\tablebases\wdl345;C:\tablebases\wdl6;D:\tablebases\dtz345;D:\tablebases\dtz6` 45 | 46 | It is recommended to store .rtbw files on an SSD. There is no loss in 47 | storing the .rtbz files on a regular HD. 48 | 49 | Increasing the "SyzygyProbeDepth" option lets the engine probe less 50 | aggressively. Set this option to a higher value if you experience too much 51 | slowdown (in terms of nps) due to TB probing. 52 | 53 | Set the "Syzygy50MoveRule" option to false if you want tablebase positions 54 | that are drawn by the 50-move rule to count as win or loss. This may be useful 55 | for correspondence games (because of tablebase adjudication). 56 | 57 | The "SyzygyProbeLimit" option should normally be left at its default value. 58 | 59 | **What to expect** 60 | If the engine is searching a position that is not in the tablebases (e.g. 61 | a position with 7 pieces), it will access the tablebases during the search. 62 | If the engine reports a very large score (typically 123.xx), this means 63 | that it has found a winning line into a tablebase position. 64 | 65 | If the engine is given a position to search that is in the tablebases, it 66 | will use the tablebases at the beginning of the search to preselect all 67 | good moves, i.e. all moves that preserve the win or preserve the draw while 68 | taking into account the 50-move rule. 69 | It will then perform a search only on those moves. **The engine will not move 70 | immediately**, unless there is only a single good move. **The engine likely 71 | will not report a mate score even if the position is known to be won.** 72 | 73 | It is therefore clear that behaviour is not identical to what one might 74 | be used to with Nalimov tablebases. There are technical reasons for this 75 | difference, the main technical reason being that Nalimov tablebases use the 76 | DTM metric (distance-to-mate), while Syzygybases use a variation of the 77 | DTZ metric (distance-to-zero, zero meaning any move that resets the 50-move 78 | counter). This special metric is one of the reasons that Syzygybases are 79 | more compact than Nalimov tablebases, while still storing all information 80 | needed for optimal play and in addition being able to take into account 81 | the 50-move rule. 82 | 83 | 84 | ### Compiling it yourself 85 | 86 | On Unix-like systems, it should be possible to compile Stockfish 87 | directly from the source code with the included Makefile. 88 | 89 | Stockfish has support for 32 or 64-bit CPUs, the hardware POPCNT 90 | instruction, big-endian machines such as Power PC, and other platforms. 91 | 92 | In general it is recommended to run `make help` to see a list of make 93 | targets with corresponding descriptions. When not using the Makefile to 94 | compile (for instance with Microsoft MSVC) you need to manually 95 | set/unset some switches in the compiler command line; see file *types.h* 96 | for a quick reference. 97 | 98 | 99 | ### Terms of use 100 | 101 | Stockfish is free, and distributed under the **GNU General Public License** 102 | (GPL). Essentially, this means that you are free to do almost exactly 103 | what you want with the program, including distributing it among your 104 | friends, making it available for download from your web site, selling 105 | it (either by itself or as part of some bigger software package), or 106 | using it as the starting point for a software project of your own. 107 | 108 | The only real limitation is that whenever you distribute Stockfish in 109 | some way, you must always include the full source code, or a pointer 110 | to where the source code can be found. If you make any changes to the 111 | source code, these changes must also be made available under the GPL. 112 | 113 | For full details, read the copy of the GPL found in the file named 114 | *Copying.txt*. 115 | -------------------------------------------------------------------------------- /src/psqt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include "types.h" 24 | 25 | Value PieceValue[PHASE_NB][PIECE_NB] = { 26 | { VALUE_ZERO, PawnValueMg, KnightValueMg, BishopValueMg, RookValueMg, QueenValueMg }, 27 | { VALUE_ZERO, PawnValueEg, KnightValueEg, BishopValueEg, RookValueEg, QueenValueEg } }; 28 | 29 | namespace PSQT { 30 | 31 | #define S(mg, eg) make_score(mg, eg) 32 | 33 | // Bonus[PieceType][Square / 2] contains Piece-Square scores. For each piece 34 | // type on a given square a (middlegame, endgame) score pair is assigned. Table 35 | // is defined for files A..D and white side: it is symmetric for black side and 36 | // second half of the files. 37 | const Score Bonus[][RANK_NB][int(FILE_NB) / 2] = { 38 | { }, 39 | { // Pawn 40 | { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) }, 41 | { S(-19, 5), S( 1,-4), S( 7, 8), S( 3,-2) }, 42 | { S(-26,-6), S( -7,-5), S( 19, 5), S(24, 4) }, 43 | { S(-25, 1), S(-14, 3), S( 20,-8), S(35,-3) }, 44 | { S(-14, 6), S( 0, 9), S( 3, 7), S(21,-6) }, 45 | { S(-14, 6), S(-13,-5), S( -6, 2), S(-2, 4) }, 46 | { S(-12, 1), S( 15,-9), S( -8, 1), S(-4,18) }, 47 | { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) } 48 | }, 49 | { // Knight 50 | { S(-143, -97), S(-96,-82), S(-80,-46), S(-73,-14) }, 51 | { S( -83, -69), S(-43,-55), S(-21,-17), S(-10, 9) }, 52 | { S( -71, -50), S(-22,-39), S( 0, -8), S( 9, 28) }, 53 | { S( -25, -41), S( 18,-25), S( 43, 7), S( 47, 38) }, 54 | { S( -26, -46), S( 16,-25), S( 38, 2), S( 50, 41) }, 55 | { S( -11, -55), S( 37,-38), S( 56, -8), S( 71, 27) }, 56 | { S( -62, -64), S(-17,-50), S( 5,-24), S( 14, 13) }, 57 | { S(-195,-110), S(-66,-90), S(-42,-50), S(-29,-13) } 58 | }, 59 | { // Bishop 60 | { S(-54,-68), S(-23,-40), S(-35,-46), S(-44,-28) }, 61 | { S(-30,-43), S( 10,-17), S( 2,-23), S( -9, -5) }, 62 | { S(-19,-32), S( 17, -9), S( 11,-13), S( 1, 8) }, 63 | { S(-21,-36), S( 18,-13), S( 11,-15), S( 0, 7) }, 64 | { S(-21,-36), S( 14,-14), S( 6,-17), S( -1, 3) }, 65 | { S(-27,-35), S( 6,-13), S( 2,-10), S( -8, 1) }, 66 | { S(-33,-44), S( 7,-21), S( -4,-22), S(-12, -4) }, 67 | { S(-45,-65), S(-21,-42), S(-29,-46), S(-39,-27) } 68 | }, 69 | { // Rook 70 | { S(-25, 0), S(-16, 0), S(-16, 0), S(-9, 0) }, 71 | { S(-21, 0), S( -8, 0), S( -3, 0), S( 0, 0) }, 72 | { S(-21, 0), S( -9, 0), S( -4, 0), S( 2, 0) }, 73 | { S(-22, 0), S( -6, 0), S( -1, 0), S( 2, 0) }, 74 | { S(-22, 0), S( -7, 0), S( 0, 0), S( 1, 0) }, 75 | { S(-21, 0), S( -7, 0), S( 0, 0), S( 2, 0) }, 76 | { S(-12, 0), S( 4, 0), S( 8, 0), S(12, 0) }, 77 | { S(-23, 0), S(-15, 0), S(-11, 0), S(-5, 0) } 78 | }, 79 | { // Queen 80 | { S( 0,-70), S(-3,-57), S(-4,-41), S(-1,-29) }, 81 | { S(-4,-58), S( 6,-30), S( 9,-21), S( 8, -4) }, 82 | { S(-2,-39), S( 6,-17), S( 9, -7), S( 9, 5) }, 83 | { S(-1,-29), S( 8, -5), S(10, 9), S( 7, 17) }, 84 | { S(-3,-27), S( 9, -5), S( 8, 10), S( 7, 23) }, 85 | { S(-2,-40), S( 6,-16), S( 8,-11), S(10, 3) }, 86 | { S(-2,-54), S( 7,-30), S( 7,-21), S( 6, -7) }, 87 | { S(-1,-75), S(-4,-54), S(-1,-44), S( 0,-30) } 88 | }, 89 | { // King 90 | { S(291, 28), S(344, 76), S(294,103), S(219,112) }, 91 | { S(289, 70), S(329,119), S(263,170), S(205,159) }, 92 | { S(226,109), S(271,164), S(202,195), S(136,191) }, 93 | { S(204,131), S(212,194), S(175,194), S(137,204) }, 94 | { S(177,132), S(205,187), S(143,224), S( 94,227) }, 95 | { S(147,118), S(188,178), S(113,199), S( 70,197) }, 96 | { S(116, 72), S(158,121), S( 93,142), S( 48,161) }, 97 | { S( 94, 30), S(120, 76), S( 78,101), S( 31,111) } 98 | } 99 | }; 100 | 101 | #undef S 102 | 103 | Score psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB]; 104 | 105 | // init() initializes piece-square tables: the white halves of the tables are 106 | // copied from Bonus[] adding the piece value, then the black halves of the 107 | // tables are initialized by flipping and changing the sign of the white scores. 108 | void init() { 109 | 110 | for (PieceType pt = PAWN; pt <= KING; ++pt) 111 | { 112 | PieceValue[MG][make_piece(BLACK, pt)] = PieceValue[MG][pt]; 113 | PieceValue[EG][make_piece(BLACK, pt)] = PieceValue[EG][pt]; 114 | 115 | Score v = make_score(PieceValue[MG][pt], PieceValue[EG][pt]); 116 | 117 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 118 | { 119 | File f = std::min(file_of(s), FILE_H - file_of(s)); 120 | psq[WHITE][pt][ s] = v + Bonus[pt][rank_of(s)][f]; 121 | psq[BLACK][pt][~s] = -psq[WHITE][pt][s]; 122 | } 123 | } 124 | } 125 | 126 | } // namespace PSQT 127 | -------------------------------------------------------------------------------- /src/timeman.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "search.h" 26 | #include "timeman.h" 27 | #include "uci.h" 28 | 29 | TimeManagement Time; // Our global time management object 30 | 31 | namespace { 32 | 33 | enum TimeType { OptimumTime, MaxTime }; 34 | 35 | const int MoveHorizon = 50; // Plan time management at most this many moves ahead 36 | const double MaxRatio = 7.09; // When in trouble, we can step over reserved time with this ratio 37 | const double StealRatio = 0.35; // However we must not steal time from remaining moves over this ratio 38 | 39 | 40 | // move_importance() is a skew-logistic function based on naive statistical 41 | // analysis of "how many games are still undecided after n half-moves". Game 42 | // is considered "undecided" as long as neither side has >275cp advantage. 43 | // Data was extracted from the CCRL game database with some simple filtering criteria. 44 | 45 | double move_importance(int ply) { 46 | 47 | const double XScale = 7.64; 48 | const double XShift = 58.4; 49 | const double Skew = 0.183; 50 | 51 | return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero 52 | } 53 | 54 | template 55 | int remaining(int myTime, int movesToGo, int ply, int slowMover) 56 | { 57 | const double TMaxRatio = (T == OptimumTime ? 1 : MaxRatio); 58 | const double TStealRatio = (T == OptimumTime ? 0 : StealRatio); 59 | 60 | double moveImportance = (move_importance(ply) * slowMover) / 100; 61 | double otherMovesImportance = 0; 62 | 63 | for (int i = 1; i < movesToGo; ++i) 64 | otherMovesImportance += move_importance(ply + 2 * i); 65 | 66 | double ratio1 = (TMaxRatio * moveImportance) / (TMaxRatio * moveImportance + otherMovesImportance); 67 | double ratio2 = (moveImportance + TStealRatio * otherMovesImportance) / (moveImportance + otherMovesImportance); 68 | 69 | return int(myTime * std::min(ratio1, ratio2)); // Intel C++ asks for an explicit cast 70 | } 71 | 72 | } // namespace 73 | 74 | 75 | /// init() is called at the beginning of the search and calculates the allowed 76 | /// thinking time out of the time control and current game ply. We support four 77 | /// different kinds of time controls, passed in 'limits': 78 | /// 79 | /// inc == 0 && movestogo == 0 means: x basetime [sudden death!] 80 | /// inc == 0 && movestogo != 0 means: x moves in y minutes 81 | /// inc > 0 && movestogo == 0 means: x basetime + z increment 82 | /// inc > 0 && movestogo != 0 means: x moves in y minutes + z increment 83 | 84 | void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) 85 | { 86 | int minThinkingTime = Options["Minimum Thinking Time"]; 87 | int moveOverhead = Options["Move Overhead"]; 88 | int slowMover = Options["Slow Mover"]; 89 | int npmsec = Options["nodestime"]; 90 | 91 | // If we have to play in 'nodes as time' mode, then convert from time 92 | // to nodes, and use resulting values in time management formulas. 93 | // WARNING: Given npms (nodes per millisecond) must be much lower then 94 | // the real engine speed to avoid time losses. 95 | if (npmsec) 96 | { 97 | if (!availableNodes) // Only once at game start 98 | availableNodes = npmsec * limits.time[us]; // Time is in msec 99 | 100 | // Convert from millisecs to nodes 101 | limits.time[us] = (int)availableNodes; 102 | limits.inc[us] *= npmsec; 103 | limits.npmsec = npmsec; 104 | } 105 | 106 | startTime = limits.startTime; 107 | optimumTime = maximumTime = std::max(limits.time[us], minThinkingTime); 108 | 109 | const int MaxMTG = limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon; 110 | 111 | // We calculate optimum time usage for different hypothetical "moves to go"-values 112 | // and choose the minimum of calculated search time values. Usually the greatest 113 | // hypMTG gives the minimum values. 114 | for (int hypMTG = 1; hypMTG <= MaxMTG; ++hypMTG) 115 | { 116 | // Calculate thinking time for hypothetical "moves to go"-value 117 | int hypMyTime = limits.time[us] 118 | + limits.inc[us] * (hypMTG - 1) 119 | - moveOverhead * (2 + std::min(hypMTG, 40)); 120 | 121 | hypMyTime = std::max(hypMyTime, 0); 122 | 123 | int t1 = minThinkingTime + remaining(hypMyTime, hypMTG, ply, slowMover); 124 | int t2 = minThinkingTime + remaining(hypMyTime, hypMTG, ply, slowMover); 125 | 126 | optimumTime = std::min(t1, optimumTime); 127 | maximumTime = std::min(t2, maximumTime); 128 | } 129 | 130 | if (Options["Ponder"]) 131 | optimumTime += optimumTime / 4; 132 | } 133 | -------------------------------------------------------------------------------- /src/thread.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include // For std::count 22 | #include 23 | 24 | #include "movegen.h" 25 | #include "search.h" 26 | #include "thread.h" 27 | #include "uci.h" 28 | 29 | using namespace Search; 30 | 31 | ThreadPool Threads; // Global object 32 | 33 | /// Thread constructor launches the thread and then waits until it goes to sleep 34 | /// in idle_loop(). 35 | 36 | Thread::Thread() { 37 | 38 | resetCalls = exit = false; 39 | maxPly = callsCnt = 0; 40 | history.clear(); 41 | counterMoves.clear(); 42 | idx = Threads.size(); // Start from 0 43 | 44 | std::unique_lock lk(mutex); 45 | searching = true; 46 | nativeThread = std::thread(&Thread::idle_loop, this); 47 | sleepCondition.wait(lk, [&]{ return !searching; }); 48 | } 49 | 50 | 51 | /// Thread destructor waits for thread termination before returning 52 | 53 | Thread::~Thread() { 54 | 55 | mutex.lock(); 56 | exit = true; 57 | sleepCondition.notify_one(); 58 | mutex.unlock(); 59 | nativeThread.join(); 60 | } 61 | 62 | 63 | /// Thread::wait_for_search_finished() waits on sleep condition 64 | /// until not searching 65 | 66 | void Thread::wait_for_search_finished() { 67 | 68 | std::unique_lock lk(mutex); 69 | sleepCondition.wait(lk, [&]{ return !searching; }); 70 | } 71 | 72 | 73 | /// Thread::wait() waits on sleep condition until condition is true 74 | 75 | void Thread::wait(std::atomic_bool& condition) { 76 | 77 | std::unique_lock lk(mutex); 78 | sleepCondition.wait(lk, [&]{ return bool(condition); }); 79 | } 80 | 81 | 82 | /// Thread::start_searching() wakes up the thread that will start the search 83 | 84 | void Thread::start_searching(bool resume) { 85 | 86 | std::unique_lock lk(mutex); 87 | 88 | if (!resume) 89 | searching = true; 90 | 91 | sleepCondition.notify_one(); 92 | } 93 | 94 | 95 | /// Thread::idle_loop() is where the thread is parked when it has no work to do 96 | 97 | void Thread::idle_loop() { 98 | 99 | while (!exit) 100 | { 101 | std::unique_lock lk(mutex); 102 | 103 | searching = false; 104 | 105 | while (!searching && !exit) 106 | { 107 | sleepCondition.notify_one(); // Wake up any waiting thread 108 | sleepCondition.wait(lk); 109 | } 110 | 111 | lk.unlock(); 112 | 113 | if (!exit) 114 | search(); 115 | } 116 | } 117 | 118 | 119 | /// ThreadPool::init() creates and launches requested threads that will go 120 | /// immediately to sleep. We cannot use a constructor because Threads is a 121 | /// static object and we need a fully initialized engine at this point due to 122 | /// allocation of Endgames in the Thread constructor. 123 | 124 | void ThreadPool::init() { 125 | 126 | push_back(new MainThread); 127 | read_uci_options(); 128 | } 129 | 130 | 131 | /// ThreadPool::exit() terminates threads before the program exits. Cannot be 132 | /// done in destructor because threads must be terminated before deleting any 133 | /// static objects while still in main(). 134 | 135 | void ThreadPool::exit() { 136 | 137 | while (size()) 138 | delete back(), pop_back(); 139 | } 140 | 141 | 142 | /// ThreadPool::read_uci_options() updates internal threads parameters from the 143 | /// corresponding UCI options and creates/destroys threads to match requested 144 | /// number. Thread objects are dynamically allocated. 145 | 146 | void ThreadPool::read_uci_options() { 147 | 148 | size_t requested = Options["Threads"]; 149 | 150 | assert(requested > 0); 151 | 152 | while (size() < requested) 153 | push_back(new Thread); 154 | 155 | while (size() > requested) 156 | delete back(), pop_back(); 157 | } 158 | 159 | 160 | /// ThreadPool::nodes_searched() returns the number of nodes searched 161 | 162 | int64_t ThreadPool::nodes_searched() { 163 | 164 | int64_t nodes = 0; 165 | for (Thread* th : *this) 166 | nodes += th->rootPos.nodes_searched(); 167 | return nodes; 168 | } 169 | 170 | 171 | /// ThreadPool::start_thinking() wakes up the main thread sleeping in idle_loop() 172 | /// and starts a new search, then returns immediately. 173 | 174 | void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, 175 | StateStackPtr& states) { 176 | 177 | main()->wait_for_search_finished(); 178 | 179 | Signals.stopOnPonderhit = Signals.stop = false; 180 | 181 | main()->rootMoves.clear(); 182 | main()->rootPos = pos; 183 | Limits = limits; 184 | if (states.get()) // If we don't set a new position, preserve current state 185 | { 186 | SetupStates = std::move(states); // Ownership transfer here 187 | assert(!states.get()); 188 | } 189 | 190 | for (const auto& m : MoveList(pos)) 191 | if ( limits.searchmoves.empty() 192 | || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m)) 193 | main()->rootMoves.push_back(RootMove(m)); 194 | 195 | main()->start_searching(); 196 | } 197 | -------------------------------------------------------------------------------- /src/ucioption.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "misc.h" 26 | #include "search.h" 27 | #include "thread.h" 28 | #include "tt.h" 29 | #include "uci.h" 30 | #include "syzygy/tbprobe.h" 31 | 32 | using std::string; 33 | 34 | UCI::OptionsMap Options; // Global object 35 | 36 | namespace UCI { 37 | 38 | /// 'On change' actions, triggered by an option's value change 39 | void on_clear_hash(const Option&) { Search::clear(); } 40 | void on_hash_size(const Option& o) { TT.resize(o); } 41 | void on_logger(const Option& o) { start_logger(o); } 42 | void on_threads(const Option&) { Threads.read_uci_options(); } 43 | void on_tb_path(const Option& o) { Tablebases::init(o); } 44 | 45 | 46 | /// Our case insensitive less() function as required by UCI protocol 47 | bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const { 48 | 49 | return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), 50 | [](char c1, char c2) { return tolower(c1) < tolower(c2); }); 51 | } 52 | 53 | 54 | /// init() initializes the UCI options to their hard-coded default values 55 | 56 | void init(OptionsMap& o) { 57 | 58 | const int MaxHashMB = Is64Bit ? 1024 * 1024 : 2048; 59 | 60 | o["Write Debug Log"] << Option(false, on_logger); 61 | o["Contempt"] << Option(0, -100, 100); 62 | o["Threads"] << Option(1, 1, 128, on_threads); 63 | o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size); 64 | o["Clear Hash"] << Option(on_clear_hash); 65 | o["Ponder"] << Option(false); 66 | o["MultiPV"] << Option(1, 1, 500); 67 | o["Skill Level"] << Option(20, 0, 20); 68 | o["Move Overhead"] << Option(30, 0, 5000); 69 | o["Minimum Thinking Time"] << Option(20, 0, 5000); 70 | o["Slow Mover"] << Option(89, 10, 1000); 71 | o["nodestime"] << Option(0, 0, 10000); 72 | o["UCI_Chess960"] << Option(false); 73 | o["SyzygyPath"] << Option("", on_tb_path); 74 | o["SyzygyProbeDepth"] << Option(1, 1, 100); 75 | o["Syzygy50MoveRule"] << Option(true); 76 | o["SyzygyProbeLimit"] << Option(6, 0, 6); 77 | } 78 | 79 | 80 | /// operator<<() is used to print all the options default values in chronological 81 | /// insertion order (the idx field) and in the format defined by the UCI protocol. 82 | 83 | std::ostream& operator<<(std::ostream& os, const OptionsMap& om) { 84 | 85 | for (size_t idx = 0; idx < om.size(); ++idx) 86 | for (const auto& it : om) 87 | if (it.second.idx == idx) 88 | { 89 | const Option& o = it.second; 90 | os << "\noption name " << it.first << " type " << o.type; 91 | 92 | if (o.type != "button") 93 | os << " default " << o.defaultValue; 94 | 95 | if (o.type == "spin") 96 | os << " min " << o.min << " max " << o.max; 97 | 98 | break; 99 | } 100 | 101 | return os; 102 | } 103 | 104 | 105 | /// Option class constructors and conversion operators 106 | 107 | Option::Option(const char* v, OnChange f) : type("string"), min(0), max(0), on_change(f) 108 | { defaultValue = currentValue = v; } 109 | 110 | Option::Option(bool v, OnChange f) : type("check"), min(0), max(0), on_change(f) 111 | { defaultValue = currentValue = (v ? "true" : "false"); } 112 | 113 | Option::Option(OnChange f) : type("button"), min(0), max(0), on_change(f) 114 | {} 115 | 116 | Option::Option(int v, int minv, int maxv, OnChange f) : type("spin"), min(minv), max(maxv), on_change(f) 117 | { defaultValue = currentValue = std::to_string(v); } 118 | 119 | Option::operator int() const { 120 | assert(type == "check" || type == "spin"); 121 | return (type == "spin" ? stoi(currentValue) : currentValue == "true"); 122 | } 123 | 124 | Option::operator std::string() const { 125 | assert(type == "string"); 126 | return currentValue; 127 | } 128 | 129 | 130 | /// operator<<() inits options and assigns idx in the correct printing order 131 | 132 | void Option::operator<<(const Option& o) { 133 | 134 | static size_t insert_order = 0; 135 | 136 | *this = o; 137 | idx = insert_order++; 138 | } 139 | 140 | 141 | /// operator=() updates currentValue and triggers on_change() action. It's up to 142 | /// the GUI to check for option's limits, but we could receive the new value from 143 | /// the user by console window, so let's check the bounds anyway. 144 | 145 | Option& Option::operator=(const string& v) { 146 | 147 | assert(!type.empty()); 148 | 149 | if ( (type != "button" && v.empty()) 150 | || (type == "check" && v != "true" && v != "false") 151 | || (type == "spin" && (stoi(v) < min || stoi(v) > max))) 152 | return *this; 153 | 154 | if (type != "button") 155 | currentValue = v; 156 | 157 | if (on_change) 158 | on_change(*this); 159 | 160 | return *this; 161 | } 162 | 163 | } // namespace UCI 164 | -------------------------------------------------------------------------------- /src/misc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "misc.h" 27 | #include "thread.h" 28 | 29 | using namespace std; 30 | 31 | namespace { 32 | 33 | /// Version number. If Version is left empty, then compile date in the format 34 | /// DD-MM-YY and show in engine_info. 35 | const string Version = ""; 36 | 37 | /// Our fancy logging facility. The trick here is to replace cin.rdbuf() and 38 | /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We 39 | /// can toggle the logging of std::cout and std:cin at runtime whilst preserving 40 | /// usual I/O functionality, all without changing a single line of code! 41 | /// Idea from http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81 42 | 43 | struct Tie: public streambuf { // MSVC requires split streambuf for cin and cout 44 | 45 | Tie(streambuf* b, streambuf* l) : buf(b), logBuf(l) {} 46 | 47 | int sync() { return logBuf->pubsync(), buf->pubsync(); } 48 | int overflow(int c) { return log(buf->sputc((char)c), "<< "); } 49 | int underflow() { return buf->sgetc(); } 50 | int uflow() { return log(buf->sbumpc(), ">> "); } 51 | 52 | streambuf *buf, *logBuf; 53 | 54 | int log(int c, const char* prefix) { 55 | 56 | static int last = '\n'; // Single log file 57 | 58 | if (last == '\n') 59 | logBuf->sputn(prefix, 3); 60 | 61 | return last = logBuf->sputc((char)c); 62 | } 63 | }; 64 | 65 | class Logger { 66 | 67 | Logger() : in(cin.rdbuf(), file.rdbuf()), out(cout.rdbuf(), file.rdbuf()) {} 68 | ~Logger() { start(false); } 69 | 70 | ofstream file; 71 | Tie in, out; 72 | 73 | public: 74 | static void start(bool b) { 75 | 76 | static Logger l; 77 | 78 | if (b && !l.file.is_open()) 79 | { 80 | l.file.open("io_log.txt", ifstream::out); 81 | cin.rdbuf(&l.in); 82 | cout.rdbuf(&l.out); 83 | } 84 | else if (!b && l.file.is_open()) 85 | { 86 | cout.rdbuf(l.out.buf); 87 | cin.rdbuf(l.in.buf); 88 | l.file.close(); 89 | } 90 | } 91 | }; 92 | 93 | } // namespace 94 | 95 | /// engine_info() returns the full name of the current Stockfish version. This 96 | /// will be either "Stockfish DD-MM-YY" (where DD-MM-YY is the date when 97 | /// the program was compiled) or "Stockfish ", depending on whether 98 | /// Version is empty. 99 | 100 | const string engine_info(bool to_uci) { 101 | 102 | const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"); 103 | string month, day, year; 104 | stringstream ss, date(__DATE__); // From compiler, format is "Sep 21 2008" 105 | 106 | ss << "Stockfish " << Version << setfill('0'); 107 | 108 | if (Version.empty()) 109 | { 110 | date >> month >> day >> year; 111 | ss << setw(2) << day << setw(2) << (1 + months.find(month) / 4) << year.substr(2); 112 | } 113 | 114 | ss << (Is64Bit ? " 64" : "") 115 | << (HasPext ? " BMI2" : (HasPopCnt ? " POPCNT" : "")) 116 | << (to_uci ? "\nid author ": " by ") 117 | << "T. Romstad, M. Costalba, J. Kiiski, G. Linscott"; 118 | 119 | return ss.str(); 120 | } 121 | 122 | 123 | /// Debug functions used mainly to collect run-time statistics 124 | static int64_t hits[2], means[2]; 125 | 126 | void dbg_hit_on(bool b) { ++hits[0]; if (b) ++hits[1]; } 127 | void dbg_hit_on(bool c, bool b) { if (c) dbg_hit_on(b); } 128 | void dbg_mean_of(int v) { ++means[0]; means[1] += v; } 129 | 130 | void dbg_print() { 131 | 132 | if (hits[0]) 133 | cerr << "Total " << hits[0] << " Hits " << hits[1] 134 | << " hit rate (%) " << 100 * hits[1] / hits[0] << endl; 135 | 136 | if (means[0]) 137 | cerr << "Total " << means[0] << " Mean " 138 | << (double)means[1] / means[0] << endl; 139 | } 140 | 141 | 142 | /// Used to serialize access to std::cout to avoid multiple threads writing at 143 | /// the same time. 144 | 145 | std::ostream& operator<<(std::ostream& os, SyncCout sc) { 146 | 147 | static Mutex m; 148 | 149 | if (sc == IO_LOCK) 150 | m.lock(); 151 | 152 | if (sc == IO_UNLOCK) 153 | m.unlock(); 154 | 155 | return os; 156 | } 157 | 158 | 159 | /// Trampoline helper to avoid moving Logger to misc.h 160 | void start_logger(bool b) { Logger::start(b); } 161 | 162 | 163 | /// prefetch() preloads the given address in L1/L2 cache. This is a non-blocking 164 | /// function that doesn't stall the CPU waiting for data to be loaded from memory, 165 | /// which can be quite slow. 166 | #ifdef NO_PREFETCH 167 | 168 | void prefetch(void*) {} 169 | 170 | #else 171 | 172 | void prefetch(void* addr) { 173 | 174 | # if defined(__INTEL_COMPILER) 175 | // This hack prevents prefetches from being optimized away by 176 | // Intel compiler. Both MSVC and gcc seem not be affected by this. 177 | __asm__ (""); 178 | # endif 179 | 180 | # if defined(__INTEL_COMPILER) || defined(_MSC_VER) 181 | _mm_prefetch((char*)addr, _MM_HINT_T0); 182 | # else 183 | __builtin_prefetch(addr); 184 | # endif 185 | } 186 | 187 | #endif 188 | -------------------------------------------------------------------------------- /src/benchmark.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "misc.h" 27 | #include "position.h" 28 | #include "search.h" 29 | #include "thread.h" 30 | #include "uci.h" 31 | 32 | using namespace std; 33 | 34 | namespace { 35 | 36 | const vector Defaults = { 37 | "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", 38 | "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 10", 39 | "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 11", 40 | "4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19", 41 | "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14", 42 | "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14", 43 | "r3r1k1/2p2ppp/p1p1bn2/8/1q2P3/2NPQN2/PPP3PP/R4RK1 b - - 2 15", 44 | "r1bbk1nr/pp3p1p/2n5/1N4p1/2Np1B2/8/PPP2PPP/2KR1B1R w kq - 0 13", 45 | "r1bq1rk1/ppp1nppp/4n3/3p3Q/3P4/1BP1B3/PP1N2PP/R4RK1 w - - 1 16", 46 | "4r1k1/r1q2ppp/ppp2n2/4P3/5Rb1/1N1BQ3/PPP3PP/R5K1 w - - 1 17", 47 | "2rqkb1r/ppp2p2/2npb1p1/1N1Nn2p/2P1PP2/8/PP2B1PP/R1BQK2R b KQ - 0 11", 48 | "r1bq1r1k/b1p1npp1/p2p3p/1p6/3PP3/1B2NN2/PP3PPP/R2Q1RK1 w - - 1 16", 49 | "3r1rk1/p5pp/bpp1pp2/8/q1PP1P2/b3P3/P2NQRPP/1R2B1K1 b - - 6 22", 50 | "r1q2rk1/2p1bppp/2Pp4/p6b/Q1PNp3/4B3/PP1R1PPP/2K4R w - - 2 18", 51 | "4k2r/1pb2ppp/1p2p3/1R1p4/3P4/2r1PN2/P4PPP/1R4K1 b - - 3 22", 52 | "3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26", 53 | "6k1/6p1/6Pp/ppp5/3pn2P/1P3K2/1PP2P2/3N4 b - - 0 1", 54 | "3b4/5kp1/1p1p1p1p/pP1PpP1P/P1P1P3/3KN3/8/8 w - - 0 1", 55 | "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1", 56 | "8/6pk/1p6/8/PP3p1p/5P2/4KP1q/3Q4 w - - 0 1", 57 | "7k/3p2pp/4q3/8/4Q3/5Kp1/P6b/8 w - - 0 1", 58 | "8/2p5/8/2kPKp1p/2p4P/2P5/3P4/8 w - - 0 1", 59 | "8/1p3pp1/7p/5P1P/2k3P1/8/2K2P2/8 w - - 0 1", 60 | "8/pp2r1k1/2p1p3/3pP2p/1P1P1P1P/P5KR/8/8 w - - 0 1", 61 | "8/3p4/p1bk3p/Pp6/1Kp1PpPp/2P2P1P/2P5/5B2 b - - 0 1", 62 | "5k2/7R/4P2p/5K2/p1r2P1p/8/8/8 b - - 0 1", 63 | "6k1/6p1/P6p/r1N5/5p2/7P/1b3PP1/4R1K1 w - - 0 1", 64 | "1r3k2/4q3/2Pp3b/3Bp3/2Q2p2/1p1P2P1/1P2KP2/3N4 w - - 0 1", 65 | "6k1/4pp1p/3p2p1/P1pPb3/R7/1r2P1PP/3B1P2/6K1 w - - 0 1", 66 | "8/3p3B/5p2/5P2/p7/PP5b/k7/6K1 w - - 0 1", 67 | 68 | // 5-man positions 69 | "8/8/8/8/5kp1/P7/8/1K1N4 w - - 0 1", // Kc2 - mate 70 | "8/8/8/5N2/8/p7/8/2NK3k w - - 0 1", // Na2 - mate 71 | "8/3k4/8/8/8/4B3/4KB2/2B5 w - - 0 1", // draw 72 | 73 | // 6-man positions 74 | "8/8/1P6/5pr1/8/4R3/7k/2K5 w - - 0 1", // Re5 - mate 75 | "8/2p4P/8/kr6/6R1/8/8/1K6 w - - 0 1", // Ka2 - mate 76 | "8/8/3P3k/8/1p6/8/1P6/1K3n2 b - - 0 1", // Nd2 - draw 77 | 78 | // 7-man positions 79 | "8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124" // Draw 80 | }; 81 | 82 | } // namespace 83 | 84 | /// benchmark() runs a simple benchmark by letting Stockfish analyze a set 85 | /// of positions for a given limit each. There are five parameters: the 86 | /// transposition table size, the number of search threads that should 87 | /// be used, the limit value spent for each position (optional, default is 88 | /// depth 13), an optional file name where to look for positions in FEN 89 | /// format (defaults are the positions defined above) and the type of the 90 | /// limit value: depth (default), time in millisecs or number of nodes. 91 | 92 | void benchmark(const Position& current, istream& is) { 93 | 94 | string token; 95 | vector fens; 96 | Search::LimitsType limits; 97 | 98 | // Assign default values to missing arguments 99 | string ttSize = (is >> token) ? token : "16"; 100 | string threads = (is >> token) ? token : "1"; 101 | string limit = (is >> token) ? token : "13"; 102 | string fenFile = (is >> token) ? token : "default"; 103 | string limitType = (is >> token) ? token : "depth"; 104 | 105 | Options["Hash"] = ttSize; 106 | Options["Threads"] = threads; 107 | Search::clear(); 108 | 109 | if (limitType == "time") 110 | limits.movetime = stoi(limit); // movetime is in millisecs 111 | 112 | else if (limitType == "nodes") 113 | limits.nodes = stoi(limit); 114 | 115 | else if (limitType == "mate") 116 | limits.mate = stoi(limit); 117 | 118 | else 119 | limits.depth = stoi(limit); 120 | 121 | if (fenFile == "default") 122 | fens = Defaults; 123 | 124 | else if (fenFile == "current") 125 | fens.push_back(current.fen()); 126 | 127 | else 128 | { 129 | string fen; 130 | ifstream file(fenFile); 131 | 132 | if (!file.is_open()) 133 | { 134 | cerr << "Unable to open file " << fenFile << endl; 135 | return; 136 | } 137 | 138 | while (getline(file, fen)) 139 | if (!fen.empty()) 140 | fens.push_back(fen); 141 | 142 | file.close(); 143 | } 144 | 145 | uint64_t nodes = 0; 146 | TimePoint elapsed = now(); 147 | 148 | for (size_t i = 0; i < fens.size(); ++i) 149 | { 150 | Position pos(fens[i], Options["UCI_Chess960"], Threads.main()); 151 | 152 | cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl; 153 | 154 | if (limitType == "perft") 155 | nodes += Search::perft(pos, limits.depth * ONE_PLY); 156 | 157 | else 158 | { 159 | Search::StateStackPtr st; 160 | limits.startTime = now(); 161 | Threads.start_thinking(pos, limits, st); 162 | Threads.main()->wait_for_search_finished(); 163 | nodes += Threads.nodes_searched(); 164 | } 165 | } 166 | 167 | elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero' 168 | 169 | dbg_print(); // Just before exiting 170 | 171 | cerr << "\n===========================" 172 | << "\nTotal time (ms) : " << elapsed 173 | << "\nNodes searched : " << nodes 174 | << "\nNodes/second : " << 1000 * nodes / elapsed << endl; 175 | } 176 | -------------------------------------------------------------------------------- /src/bitbase.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "bitboard.h" 27 | #include "types.h" 28 | 29 | namespace { 30 | 31 | // There are 24 possible pawn squares: the first 4 files and ranks from 2 to 7 32 | const unsigned MAX_INDEX = 2*24*64*64; // stm * psq * wksq * bksq = 196608 33 | 34 | // Each uint32_t stores results of 32 positions, one per bit 35 | uint32_t KPKBitbase[MAX_INDEX / 32]; 36 | 37 | // A KPK bitbase index is an integer in [0, IndexMax] range 38 | // 39 | // Information is mapped in a way that minimizes the number of iterations: 40 | // 41 | // bit 0- 5: white king square (from SQ_A1 to SQ_H8) 42 | // bit 6-11: black king square (from SQ_A1 to SQ_H8) 43 | // bit 12: side to move (WHITE or BLACK) 44 | // bit 13-14: white pawn file (from FILE_A to FILE_D) 45 | // bit 15-17: white pawn RANK_7 - rank (from RANK_7 - RANK_7 to RANK_7 - RANK_2) 46 | unsigned index(Color us, Square bksq, Square wksq, Square psq) { 47 | return wksq | (bksq << 6) | (us << 12) | (file_of(psq) << 13) | ((RANK_7 - rank_of(psq)) << 15); 48 | } 49 | 50 | enum Result { 51 | INVALID = 0, 52 | UNKNOWN = 1, 53 | DRAW = 2, 54 | WIN = 4 55 | }; 56 | 57 | Result& operator|=(Result& r, Result v) { return r = Result(r | v); } 58 | 59 | struct KPKPosition { 60 | KPKPosition() = default; 61 | explicit KPKPosition(unsigned idx); 62 | operator Result() const { return result; } 63 | Result classify(const std::vector& db) 64 | { return us == WHITE ? classify(db) : classify(db); } 65 | 66 | template Result classify(const std::vector& db); 67 | 68 | Color us; 69 | Square ksq[COLOR_NB], psq; 70 | Result result; 71 | }; 72 | 73 | } // namespace 74 | 75 | 76 | bool Bitbases::probe(Square wksq, Square wpsq, Square bksq, Color us) { 77 | 78 | assert(file_of(wpsq) <= FILE_D); 79 | 80 | unsigned idx = index(us, bksq, wksq, wpsq); 81 | return KPKBitbase[idx / 32] & (1 << (idx & 0x1F)); 82 | } 83 | 84 | 85 | void Bitbases::init() { 86 | 87 | std::vector db(MAX_INDEX); 88 | unsigned idx, repeat = 1; 89 | 90 | // Initialize db with known win / draw positions 91 | for (idx = 0; idx < MAX_INDEX; ++idx) 92 | db[idx] = KPKPosition(idx); 93 | 94 | // Iterate through the positions until none of the unknown positions can be 95 | // changed to either wins or draws (15 cycles needed). 96 | while (repeat) 97 | for (repeat = idx = 0; idx < MAX_INDEX; ++idx) 98 | repeat |= (db[idx] == UNKNOWN && db[idx].classify(db) != UNKNOWN); 99 | 100 | // Map 32 results into one KPKBitbase[] entry 101 | for (idx = 0; idx < MAX_INDEX; ++idx) 102 | if (db[idx] == WIN) 103 | KPKBitbase[idx / 32] |= 1 << (idx & 0x1F); 104 | } 105 | 106 | 107 | namespace { 108 | 109 | KPKPosition::KPKPosition(unsigned idx) { 110 | 111 | ksq[WHITE] = Square((idx >> 0) & 0x3F); 112 | ksq[BLACK] = Square((idx >> 6) & 0x3F); 113 | us = Color ((idx >> 12) & 0x01); 114 | psq = make_square(File((idx >> 13) & 0x3), RANK_7 - Rank((idx >> 15) & 0x7)); 115 | 116 | // Check if two pieces are on the same square or if a king can be captured 117 | if ( distance(ksq[WHITE], ksq[BLACK]) <= 1 118 | || ksq[WHITE] == psq 119 | || ksq[BLACK] == psq 120 | || (us == WHITE && (StepAttacksBB[PAWN][psq] & ksq[BLACK]))) 121 | result = INVALID; 122 | 123 | // Immediate win if a pawn can be promoted without getting captured 124 | else if ( us == WHITE 125 | && rank_of(psq) == RANK_7 126 | && ksq[us] != psq + DELTA_N 127 | && ( distance(ksq[~us], psq + DELTA_N) > 1 128 | || (StepAttacksBB[KING][ksq[us]] & (psq + DELTA_N)))) 129 | result = WIN; 130 | 131 | // Immediate draw if it is a stalemate or a king captures undefended pawn 132 | else if ( us == BLACK 133 | && ( !(StepAttacksBB[KING][ksq[us]] & ~(StepAttacksBB[KING][ksq[~us]] | StepAttacksBB[PAWN][psq])) 134 | || (StepAttacksBB[KING][ksq[us]] & psq & ~StepAttacksBB[KING][ksq[~us]]))) 135 | result = DRAW; 136 | 137 | // Position will be classified later 138 | else 139 | result = UNKNOWN; 140 | } 141 | 142 | template 143 | Result KPKPosition::classify(const std::vector& db) { 144 | 145 | // White to move: If one move leads to a position classified as WIN, the result 146 | // of the current position is WIN. If all moves lead to positions classified 147 | // as DRAW, the current position is classified as DRAW, otherwise the current 148 | // position is classified as UNKNOWN. 149 | // 150 | // Black to move: If one move leads to a position classified as DRAW, the result 151 | // of the current position is DRAW. If all moves lead to positions classified 152 | // as WIN, the position is classified as WIN, otherwise the current position is 153 | // classified as UNKNOWN. 154 | 155 | const Color Them = (Us == WHITE ? BLACK : WHITE); 156 | const Result Good = (Us == WHITE ? WIN : DRAW); 157 | const Result Bad = (Us == WHITE ? DRAW : WIN); 158 | 159 | Result r = INVALID; 160 | Bitboard b = StepAttacksBB[KING][ksq[Us]]; 161 | 162 | while (b) 163 | r |= Us == WHITE ? db[index(Them, ksq[Them] , pop_lsb(&b), psq)] 164 | : db[index(Them, pop_lsb(&b), ksq[Them] , psq)]; 165 | 166 | if (Us == WHITE) 167 | { 168 | if (rank_of(psq) < RANK_7) // Single push 169 | r |= db[index(Them, ksq[Them], ksq[Us], psq + DELTA_N)]; 170 | 171 | if ( rank_of(psq) == RANK_2 // Double push 172 | && psq + DELTA_N != ksq[Us] 173 | && psq + DELTA_N != ksq[Them]) 174 | r |= db[index(Them, ksq[Them], ksq[Us], psq + DELTA_N + DELTA_N)]; 175 | } 176 | 177 | return result = r & Good ? Good : r & UNKNOWN ? UNKNOWN : Bad; 178 | } 179 | 180 | } // namespace 181 | -------------------------------------------------------------------------------- /src/material.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include // For std::min 22 | #include 23 | #include // For std::memset 24 | 25 | #include "material.h" 26 | #include "thread.h" 27 | 28 | using namespace std; 29 | 30 | namespace { 31 | 32 | // Polynomial material imbalance parameters 33 | 34 | // pair pawn knight bishop rook queen 35 | const int Linear[6] = { 1667, -168, -1027, -166, 238, -138 }; 36 | 37 | const int QuadraticOurs[][PIECE_TYPE_NB] = { 38 | // OUR PIECES 39 | // pair pawn knight bishop rook queen 40 | { 0 }, // Bishop pair 41 | { 40, 2 }, // Pawn 42 | { 32, 255, -3 }, // Knight OUR PIECES 43 | { 0, 104, 4, 0 }, // Bishop 44 | { -26, -2, 47, 105, -149 }, // Rook 45 | {-185, 24, 122, 137, -134, 0 } // Queen 46 | }; 47 | 48 | const int QuadraticTheirs[][PIECE_TYPE_NB] = { 49 | // THEIR PIECES 50 | // pair pawn knight bishop rook queen 51 | { 0 }, // Bishop pair 52 | { 36, 0 }, // Pawn 53 | { 9, 63, 0 }, // Knight OUR PIECES 54 | { 59, 65, 42, 0 }, // Bishop 55 | { 46, 39, 24, -24, 0 }, // Rook 56 | { 101, 100, -37, 141, 268, 0 } // Queen 57 | }; 58 | 59 | // Endgame evaluation and scaling functions are accessed directly and not through 60 | // the function maps because they correspond to more than one material hash key. 61 | Endgame EvaluateKXK[] = { Endgame(WHITE), Endgame(BLACK) }; 62 | 63 | Endgame ScaleKBPsK[] = { Endgame(WHITE), Endgame(BLACK) }; 64 | Endgame ScaleKQKRPs[] = { Endgame(WHITE), Endgame(BLACK) }; 65 | Endgame ScaleKPsK[] = { Endgame(WHITE), Endgame(BLACK) }; 66 | Endgame ScaleKPKP[] = { Endgame(WHITE), Endgame(BLACK) }; 67 | 68 | // Helper used to detect a given material distribution 69 | bool is_KXK(const Position& pos, Color us) { 70 | return !more_than_one(pos.pieces(~us)) 71 | && pos.non_pawn_material(us) >= RookValueMg; 72 | } 73 | 74 | bool is_KBPsKs(const Position& pos, Color us) { 75 | return pos.non_pawn_material(us) == BishopValueMg 76 | && pos.count(us) == 1 77 | && pos.count(us) >= 1; 78 | } 79 | 80 | bool is_KQKRPs(const Position& pos, Color us) { 81 | return !pos.count(us) 82 | && pos.non_pawn_material(us) == QueenValueMg 83 | && pos.count(us) == 1 84 | && pos.count(~us) == 1 85 | && pos.count(~us) >= 1; 86 | } 87 | 88 | /// imbalance() calculates the imbalance by comparing the piece count of each 89 | /// piece type for both colors. 90 | template 91 | int imbalance(const int pieceCount[][PIECE_TYPE_NB]) { 92 | 93 | const Color Them = (Us == WHITE ? BLACK : WHITE); 94 | 95 | int bonus = 0; 96 | 97 | // Second-degree polynomial material imbalance by Tord Romstad 98 | for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1) 99 | { 100 | if (!pieceCount[Us][pt1]) 101 | continue; 102 | 103 | int v = Linear[pt1]; 104 | 105 | for (int pt2 = NO_PIECE_TYPE; pt2 <= pt1; ++pt2) 106 | v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2] 107 | + QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2]; 108 | 109 | bonus += pieceCount[Us][pt1] * v; 110 | } 111 | 112 | return bonus; 113 | } 114 | 115 | } // namespace 116 | 117 | namespace Material { 118 | 119 | /// Material::probe() looks up the current position's material configuration in 120 | /// the material hash table. It returns a pointer to the Entry if the position 121 | /// is found. Otherwise a new Entry is computed and stored there, so we don't 122 | /// have to recompute all when the same material configuration occurs again. 123 | 124 | Entry* probe(const Position& pos) { 125 | 126 | Key key = pos.material_key(); 127 | Entry* e = pos.this_thread()->materialTable[key]; 128 | 129 | if (e->key == key) 130 | return e; 131 | 132 | std::memset(e, 0, sizeof(Entry)); 133 | e->key = key; 134 | e->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL; 135 | e->gamePhase = pos.game_phase(); 136 | 137 | // Let's look if we have a specialized evaluation function for this particular 138 | // material configuration. Firstly we look for a fixed configuration one, then 139 | // for a generic one if the previous search failed. 140 | if ((e->evaluationFunction = pos.this_thread()->endgames.probe(key)) != nullptr) 141 | return e; 142 | 143 | for (Color c = WHITE; c <= BLACK; ++c) 144 | if (is_KXK(pos, c)) 145 | { 146 | e->evaluationFunction = &EvaluateKXK[c]; 147 | return e; 148 | } 149 | 150 | // OK, we didn't find any special evaluation function for the current material 151 | // configuration. Is there a suitable specialized scaling function? 152 | EndgameBase* sf; 153 | 154 | if ((sf = pos.this_thread()->endgames.probe(key)) != nullptr) 155 | { 156 | e->scalingFunction[sf->strong_side()] = sf; // Only strong color assigned 157 | return e; 158 | } 159 | 160 | // We didn't find any specialized scaling function, so fall back on generic 161 | // ones that refer to more than one material distribution. Note that in this 162 | // case we don't return after setting the function. 163 | for (Color c = WHITE; c <= BLACK; ++c) 164 | { 165 | if (is_KBPsKs(pos, c)) 166 | e->scalingFunction[c] = &ScaleKBPsK[c]; 167 | 168 | else if (is_KQKRPs(pos, c)) 169 | e->scalingFunction[c] = &ScaleKQKRPs[c]; 170 | } 171 | 172 | Value npm_w = pos.non_pawn_material(WHITE); 173 | Value npm_b = pos.non_pawn_material(BLACK); 174 | 175 | if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board 176 | { 177 | if (!pos.count(BLACK)) 178 | { 179 | assert(pos.count(WHITE) >= 2); 180 | 181 | e->scalingFunction[WHITE] = &ScaleKPsK[WHITE]; 182 | } 183 | else if (!pos.count(WHITE)) 184 | { 185 | assert(pos.count(BLACK) >= 2); 186 | 187 | e->scalingFunction[BLACK] = &ScaleKPsK[BLACK]; 188 | } 189 | else if (pos.count(WHITE) == 1 && pos.count(BLACK) == 1) 190 | { 191 | // This is a special case because we set scaling functions 192 | // for both colors instead of only one. 193 | e->scalingFunction[WHITE] = &ScaleKPKP[WHITE]; 194 | e->scalingFunction[BLACK] = &ScaleKPKP[BLACK]; 195 | } 196 | } 197 | 198 | // Zero or just one pawn makes it difficult to win, even with a small material 199 | // advantage. This catches some trivial draws like KK, KBK and KNK and gives a 200 | // drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN). 201 | if (!pos.count(WHITE) && npm_w - npm_b <= BishopValueMg) 202 | e->factor[WHITE] = uint8_t(npm_w < RookValueMg ? SCALE_FACTOR_DRAW : 203 | npm_b <= BishopValueMg ? 4 : 14); 204 | 205 | if (!pos.count(BLACK) && npm_b - npm_w <= BishopValueMg) 206 | e->factor[BLACK] = uint8_t(npm_b < RookValueMg ? SCALE_FACTOR_DRAW : 207 | npm_w <= BishopValueMg ? 4 : 14); 208 | 209 | if (pos.count(WHITE) == 1 && npm_w - npm_b <= BishopValueMg) 210 | e->factor[WHITE] = (uint8_t) SCALE_FACTOR_ONEPAWN; 211 | 212 | if (pos.count(BLACK) == 1 && npm_b - npm_w <= BishopValueMg) 213 | e->factor[BLACK] = (uint8_t) SCALE_FACTOR_ONEPAWN; 214 | 215 | // Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder 216 | // for the bishop pair "extended piece", which allows us to be more flexible 217 | // in defining bishop pair bonuses. 218 | const int PieceCount[COLOR_NB][PIECE_TYPE_NB] = { 219 | { pos.count(WHITE) > 1, pos.count(WHITE), pos.count(WHITE), 220 | pos.count(WHITE) , pos.count(WHITE), pos.count(WHITE) }, 221 | { pos.count(BLACK) > 1, pos.count(BLACK), pos.count(BLACK), 222 | pos.count(BLACK) , pos.count(BLACK), pos.count(BLACK) } }; 223 | 224 | e->value = int16_t((imbalance(PieceCount) - imbalance(PieceCount)) / 16); 225 | return e; 226 | } 227 | 228 | } // namespace Material 229 | -------------------------------------------------------------------------------- /src/uci.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "evaluate.h" 26 | #include "movegen.h" 27 | #include "position.h" 28 | #include "search.h" 29 | #include "thread.h" 30 | #include "timeman.h" 31 | #include "uci.h" 32 | 33 | using namespace std; 34 | 35 | extern void benchmark(const Position& pos, istream& is); 36 | 37 | namespace { 38 | 39 | // FEN string of the initial position, normal chess 40 | const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; 41 | 42 | // Stack to keep track of the position states along the setup moves (from the 43 | // start position to the position just before the search starts). Needed by 44 | // 'draw by repetition' detection. 45 | Search::StateStackPtr SetupStates; 46 | 47 | 48 | // position() is called when engine receives the "position" UCI command. 49 | // The function sets up the position described in the given FEN string ("fen") 50 | // or the starting position ("startpos") and then makes the moves given in the 51 | // following move list ("moves"). 52 | 53 | void position(Position& pos, istringstream& is) { 54 | 55 | Move m; 56 | string token, fen; 57 | 58 | is >> token; 59 | 60 | if (token == "startpos") 61 | { 62 | fen = StartFEN; 63 | is >> token; // Consume "moves" token if any 64 | } 65 | else if (token == "fen") 66 | while (is >> token && token != "moves") 67 | fen += token + " "; 68 | else 69 | return; 70 | 71 | pos.set(fen, Options["UCI_Chess960"], Threads.main()); 72 | SetupStates = Search::StateStackPtr(new std::stack); 73 | 74 | // Parse move list (if any) 75 | while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE) 76 | { 77 | SetupStates->push(StateInfo()); 78 | pos.do_move(m, SetupStates->top(), pos.gives_check(m, CheckInfo(pos))); 79 | } 80 | } 81 | 82 | 83 | // setoption() is called when engine receives the "setoption" UCI command. The 84 | // function updates the UCI option ("name") to the given value ("value"). 85 | 86 | void setoption(istringstream& is) { 87 | 88 | string token, name, value; 89 | 90 | is >> token; // Consume "name" token 91 | 92 | // Read option name (can contain spaces) 93 | while (is >> token && token != "value") 94 | name += string(" ", name.empty() ? 0 : 1) + token; 95 | 96 | // Read option value (can contain spaces) 97 | while (is >> token) 98 | value += string(" ", value.empty() ? 0 : 1) + token; 99 | 100 | if (Options.count(name)) 101 | Options[name] = value; 102 | else 103 | sync_cout << "No such option: " << name << sync_endl; 104 | } 105 | 106 | 107 | // go() is called when engine receives the "go" UCI command. The function sets 108 | // the thinking time and other parameters from the input string, then starts 109 | // the search. 110 | 111 | void go(const Position& pos, istringstream& is) { 112 | 113 | Search::LimitsType limits; 114 | string token; 115 | 116 | limits.startTime = now(); // As early as possible! 117 | 118 | while (is >> token) 119 | if (token == "searchmoves") 120 | while (is >> token) 121 | limits.searchmoves.push_back(UCI::to_move(pos, token)); 122 | 123 | else if (token == "wtime") is >> limits.time[WHITE]; 124 | else if (token == "btime") is >> limits.time[BLACK]; 125 | else if (token == "winc") is >> limits.inc[WHITE]; 126 | else if (token == "binc") is >> limits.inc[BLACK]; 127 | else if (token == "movestogo") is >> limits.movestogo; 128 | else if (token == "depth") is >> limits.depth; 129 | else if (token == "nodes") is >> limits.nodes; 130 | else if (token == "movetime") is >> limits.movetime; 131 | else if (token == "mate") is >> limits.mate; 132 | else if (token == "infinite") limits.infinite = 1; 133 | else if (token == "ponder") limits.ponder = 1; 134 | 135 | Threads.start_thinking(pos, limits, SetupStates); 136 | } 137 | 138 | } // namespace 139 | 140 | 141 | /// UCI::loop() waits for a command from stdin, parses it and calls the appropriate 142 | /// function. Also intercepts EOF from stdin to ensure gracefully exiting if the 143 | /// GUI dies unexpectedly. When called with some command line arguments, e.g. to 144 | /// run 'bench', once the command is executed the function returns immediately. 145 | /// In addition to the UCI ones, also some additional debug commands are supported. 146 | 147 | void UCI::loop(int argc, char* argv[]) { 148 | 149 | Position pos(StartFEN, false, Threads.main()); // The root position 150 | string token, cmd; 151 | 152 | for (int i = 1; i < argc; ++i) 153 | cmd += std::string(argv[i]) + " "; 154 | 155 | do { 156 | if (argc == 1 && !getline(cin, cmd)) // Block here waiting for input or EOF 157 | cmd = "quit"; 158 | 159 | istringstream is(cmd); 160 | 161 | token.clear(); // getline() could return empty or blank line 162 | is >> skipws >> token; 163 | 164 | // The GUI sends 'ponderhit' to tell us to ponder on the same move the 165 | // opponent has played. In case Signals.stopOnPonderhit is set we are 166 | // waiting for 'ponderhit' to stop the search (for instance because we 167 | // already ran out of time), otherwise we should continue searching but 168 | // switching from pondering to normal search. 169 | if ( token == "quit" 170 | || token == "stop" 171 | || (token == "ponderhit" && Search::Signals.stopOnPonderhit)) 172 | { 173 | Search::Signals.stop = true; 174 | Threads.main()->start_searching(true); // Could be sleeping 175 | } 176 | else if (token == "ponderhit") 177 | Search::Limits.ponder = 0; // Switch to normal search 178 | 179 | else if (token == "uci") 180 | sync_cout << "id name " << engine_info(true) 181 | << "\n" << Options 182 | << "\nuciok" << sync_endl; 183 | 184 | else if (token == "ucinewgame") 185 | { 186 | Search::clear(); 187 | Time.availableNodes = 0; 188 | } 189 | else if (token == "isready") sync_cout << "readyok" << sync_endl; 190 | else if (token == "go") go(pos, is); 191 | else if (token == "position") position(pos, is); 192 | else if (token == "setoption") setoption(is); 193 | 194 | // Additional custom non-UCI commands, useful for debugging 195 | else if (token == "flip") pos.flip(); 196 | else if (token == "bench") benchmark(pos, is); 197 | else if (token == "d") sync_cout << pos << sync_endl; 198 | else if (token == "eval") sync_cout << Eval::trace(pos) << sync_endl; 199 | else if (token == "perft") 200 | { 201 | int depth; 202 | stringstream ss; 203 | 204 | is >> depth; 205 | ss << Options["Hash"] << " " 206 | << Options["Threads"] << " " << depth << " current perft"; 207 | 208 | benchmark(pos, ss); 209 | } 210 | else 211 | sync_cout << "Unknown command: " << cmd << sync_endl; 212 | 213 | } while (token != "quit" && argc == 1); // Passed args have one-shot behaviour 214 | 215 | Threads.main()->wait_for_search_finished(); 216 | } 217 | 218 | 219 | /// UCI::value() converts a Value to a string suitable for use with the UCI 220 | /// protocol specification: 221 | /// 222 | /// cp The score from the engine's point of view in centipawns. 223 | /// mate Mate in y moves, not plies. If the engine is getting mated 224 | /// use negative values for y. 225 | 226 | string UCI::value(Value v) { 227 | 228 | stringstream ss; 229 | 230 | if (abs(v) < VALUE_MATE - MAX_PLY) 231 | ss << "cp " << v * 100 / PawnValueEg; 232 | else 233 | ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2; 234 | 235 | return ss.str(); 236 | } 237 | 238 | 239 | /// UCI::square() converts a Square to a string in algebraic notation (g1, a7, etc.) 240 | 241 | std::string UCI::square(Square s) { 242 | return std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) }; 243 | } 244 | 245 | 246 | /// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q). 247 | /// The only special case is castling, where we print in the e1g1 notation in 248 | /// normal chess mode, and in e1h1 notation in chess960 mode. Internally all 249 | /// castling moves are always encoded as 'king captures rook'. 250 | 251 | string UCI::move(Move m, bool chess960) { 252 | 253 | Square from = from_sq(m); 254 | Square to = to_sq(m); 255 | 256 | if (m == MOVE_NONE) 257 | return "(none)"; 258 | 259 | if (m == MOVE_NULL) 260 | return "0000"; 261 | 262 | if (type_of(m) == CASTLING && !chess960) 263 | to = make_square(to > from ? FILE_G : FILE_C, rank_of(from)); 264 | 265 | string move = UCI::square(from) + UCI::square(to); 266 | 267 | if (type_of(m) == PROMOTION) 268 | move += " pnbrqk"[promotion_type(m)]; 269 | 270 | return move; 271 | } 272 | 273 | 274 | /// UCI::to_move() converts a string representing a move in coordinate notation 275 | /// (g1f3, a7a8q) to the corresponding legal Move, if any. 276 | 277 | Move UCI::to_move(const Position& pos, string& str) { 278 | 279 | if (str.length() == 5) // Junior could send promotion piece in uppercase 280 | str[4] = char(tolower(str[4])); 281 | 282 | for (const auto& m : MoveList(pos)) 283 | if (str == UCI::move(m, pos.is_chess960())) 284 | return m; 285 | 286 | return MOVE_NONE; 287 | } 288 | -------------------------------------------------------------------------------- /src/movepick.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include "movepick.h" 24 | #include "thread.h" 25 | 26 | namespace { 27 | 28 | enum Stages { 29 | MAIN_SEARCH, GOOD_CAPTURES, KILLERS, GOOD_QUIETS, BAD_QUIETS, BAD_CAPTURES, 30 | EVASION, ALL_EVASIONS, 31 | QSEARCH_WITH_CHECKS, QCAPTURES_1, CHECKS, 32 | QSEARCH_WITHOUT_CHECKS, QCAPTURES_2, 33 | PROBCUT, PROBCUT_CAPTURES, 34 | RECAPTURE, RECAPTURES, 35 | STOP 36 | }; 37 | 38 | // Our insertion sort, which is guaranteed to be stable, as it should be 39 | void insertion_sort(ExtMove* begin, ExtMove* end) 40 | { 41 | ExtMove tmp, *p, *q; 42 | 43 | for (p = begin + 1; p < end; ++p) 44 | { 45 | tmp = *p; 46 | for (q = p; q != begin && *(q-1) < tmp; --q) 47 | *q = *(q-1); 48 | *q = tmp; 49 | } 50 | } 51 | 52 | // pick_best() finds the best move in the range (begin, end) and moves it to 53 | // the front. It's faster than sorting all the moves in advance when there 54 | // are few moves, e.g., the possible captures. 55 | Move pick_best(ExtMove* begin, ExtMove* end) 56 | { 57 | std::swap(*begin, *std::max_element(begin, end)); 58 | return *begin; 59 | } 60 | 61 | } // namespace 62 | 63 | 64 | /// Constructors of the MovePicker class. As arguments we pass information 65 | /// to help it to return the (presumably) good moves first, to decide which 66 | /// moves to return (in the quiescence search, for instance, we only want to 67 | /// search captures, promotions, and some checks) and how important good move 68 | /// ordering is at the current node. 69 | 70 | MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const HistoryStats& h, 71 | const CounterMoveStats& cmh, const CounterMoveStats& fmh, 72 | Move cm, Search::Stack* s) 73 | : pos(p), history(h), counterMoveHistory(&cmh), 74 | followupMoveHistory(&fmh), ss(s), countermove(cm), depth(d) { 75 | 76 | assert(d > DEPTH_ZERO); 77 | 78 | stage = pos.checkers() ? EVASION : MAIN_SEARCH; 79 | ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE; 80 | endMoves += (ttMove != MOVE_NONE); 81 | } 82 | 83 | MovePicker::MovePicker(const Position& p, Move ttm, Depth d, 84 | const HistoryStats& h, Square s) 85 | : pos(p), history(h) { 86 | 87 | assert(d <= DEPTH_ZERO); 88 | 89 | if (pos.checkers()) 90 | stage = EVASION; 91 | 92 | else if (d > DEPTH_QS_NO_CHECKS) 93 | stage = QSEARCH_WITH_CHECKS; 94 | 95 | else if (d > DEPTH_QS_RECAPTURES) 96 | stage = QSEARCH_WITHOUT_CHECKS; 97 | 98 | else 99 | { 100 | stage = RECAPTURE; 101 | recaptureSquare = s; 102 | ttm = MOVE_NONE; 103 | } 104 | 105 | ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE; 106 | endMoves += (ttMove != MOVE_NONE); 107 | } 108 | 109 | MovePicker::MovePicker(const Position& p, Move ttm, const HistoryStats& h, Value th) 110 | : pos(p), history(h), threshold(th) { 111 | 112 | assert(!pos.checkers()); 113 | 114 | stage = PROBCUT; 115 | 116 | // In ProbCut we generate captures with SEE higher than the given threshold 117 | ttMove = ttm 118 | && pos.pseudo_legal(ttm) 119 | && pos.capture(ttm) 120 | && pos.see(ttm) > threshold ? ttm : MOVE_NONE; 121 | 122 | endMoves += (ttMove != MOVE_NONE); 123 | } 124 | 125 | 126 | /// score() assigns a numerical value to each move in a move list. The moves with 127 | /// highest values will be picked first. 128 | template<> 129 | void MovePicker::score() { 130 | // Winning and equal captures in the main search are ordered by MVV, preferring 131 | // captures near our home rank. Surprisingly, this appears to perform slightly 132 | // better than SEE-based move ordering: exchanging big pieces before capturing 133 | // a hanging piece probably helps to reduce the subtree size. 134 | // In the main search we want to push captures with negative SEE values to the 135 | // badCaptures[] array, but instead of doing it now we delay until the move 136 | // has been picked up, saving some SEE calls in case we get a cutoff. 137 | for (auto& m : *this) 138 | m.value = PieceValue[MG][pos.piece_on(to_sq(m))] 139 | - Value(200 * relative_rank(pos.side_to_move(), to_sq(m))); 140 | } 141 | 142 | template<> 143 | void MovePicker::score() { 144 | 145 | for (auto& m : *this) 146 | m.value = history[pos.moved_piece(m)][to_sq(m)] 147 | + (*counterMoveHistory )[pos.moved_piece(m)][to_sq(m)] 148 | + (*followupMoveHistory)[pos.moved_piece(m)][to_sq(m)]; 149 | } 150 | 151 | template<> 152 | void MovePicker::score() { 153 | // Try winning and equal captures ordered by MVV/LVA, then non-captures ordered 154 | // by history value, then bad captures and quiet moves with a negative SEE ordered 155 | // by SEE value. 156 | Value see; 157 | 158 | for (auto& m : *this) 159 | if ((see = pos.see_sign(m)) < VALUE_ZERO) 160 | m.value = see - HistoryStats::Max; // At the bottom 161 | 162 | else if (pos.capture(m)) 163 | m.value = PieceValue[MG][pos.piece_on(to_sq(m))] 164 | - Value(type_of(pos.moved_piece(m))) + HistoryStats::Max; 165 | else 166 | m.value = history[pos.moved_piece(m)][to_sq(m)]; 167 | } 168 | 169 | 170 | /// generate_next_stage() generates, scores, and sorts the next bunch of moves 171 | /// when there are no more moves to try for the current stage. 172 | 173 | void MovePicker::generate_next_stage() { 174 | 175 | assert(stage != STOP); 176 | 177 | cur = moves; 178 | 179 | switch (++stage) { 180 | 181 | case GOOD_CAPTURES: case QCAPTURES_1: case QCAPTURES_2: 182 | case PROBCUT_CAPTURES: case RECAPTURES: 183 | endMoves = generate(pos, moves); 184 | score(); 185 | break; 186 | 187 | case KILLERS: 188 | killers[0] = ss->killers[0]; 189 | killers[1] = ss->killers[1]; 190 | killers[2] = countermove; 191 | cur = killers; 192 | endMoves = cur + 2 + (countermove != killers[0] && countermove != killers[1]); 193 | break; 194 | 195 | case GOOD_QUIETS: 196 | endQuiets = endMoves = generate(pos, moves); 197 | score(); 198 | endMoves = std::partition(cur, endMoves, [](const ExtMove& m) { return m.value > VALUE_ZERO; }); 199 | insertion_sort(cur, endMoves); 200 | break; 201 | 202 | case BAD_QUIETS: 203 | cur = endMoves; 204 | endMoves = endQuiets; 205 | if (depth >= 3 * ONE_PLY) 206 | insertion_sort(cur, endMoves); 207 | break; 208 | 209 | case BAD_CAPTURES: 210 | // Just pick them in reverse order to get correct ordering 211 | cur = moves + MAX_MOVES - 1; 212 | endMoves = endBadCaptures; 213 | break; 214 | 215 | case ALL_EVASIONS: 216 | endMoves = generate(pos, moves); 217 | if (endMoves - moves > 1) 218 | score(); 219 | break; 220 | 221 | case CHECKS: 222 | endMoves = generate(pos, moves); 223 | break; 224 | 225 | case EVASION: case QSEARCH_WITH_CHECKS: case QSEARCH_WITHOUT_CHECKS: 226 | case PROBCUT: case RECAPTURE: case STOP: 227 | stage = STOP; 228 | break; 229 | 230 | default: 231 | assert(false); 232 | } 233 | } 234 | 235 | 236 | /// next_move() is the most important method of the MovePicker class. It returns 237 | /// a new pseudo legal move every time it is called, until there are no more moves 238 | /// left. It picks the move with the biggest value from a list of generated moves 239 | /// taking care not to return the ttMove if it has already been searched. 240 | 241 | Move MovePicker::next_move() { 242 | 243 | Move move; 244 | 245 | while (true) 246 | { 247 | while (cur == endMoves && stage != STOP) 248 | generate_next_stage(); 249 | 250 | switch (stage) { 251 | 252 | case MAIN_SEARCH: case EVASION: case QSEARCH_WITH_CHECKS: 253 | case QSEARCH_WITHOUT_CHECKS: case PROBCUT: 254 | ++cur; 255 | return ttMove; 256 | 257 | case GOOD_CAPTURES: 258 | move = pick_best(cur++, endMoves); 259 | if (move != ttMove) 260 | { 261 | if (pos.see_sign(move) >= VALUE_ZERO) 262 | return move; 263 | 264 | // Losing capture, move it to the tail of the array 265 | *endBadCaptures-- = move; 266 | } 267 | break; 268 | 269 | case KILLERS: 270 | move = *cur++; 271 | if ( move != MOVE_NONE 272 | && move != ttMove 273 | && pos.pseudo_legal(move) 274 | && !pos.capture(move)) 275 | return move; 276 | break; 277 | 278 | case GOOD_QUIETS: case BAD_QUIETS: 279 | move = *cur++; 280 | if ( move != ttMove 281 | && move != killers[0] 282 | && move != killers[1] 283 | && move != killers[2]) 284 | return move; 285 | break; 286 | 287 | case BAD_CAPTURES: 288 | return *cur--; 289 | 290 | case ALL_EVASIONS: case QCAPTURES_1: case QCAPTURES_2: 291 | move = pick_best(cur++, endMoves); 292 | if (move != ttMove) 293 | return move; 294 | break; 295 | 296 | case PROBCUT_CAPTURES: 297 | move = pick_best(cur++, endMoves); 298 | if (move != ttMove && pos.see(move) > threshold) 299 | return move; 300 | break; 301 | 302 | case RECAPTURES: 303 | move = pick_best(cur++, endMoves); 304 | if (to_sq(move) == recaptureSquare) 305 | return move; 306 | break; 307 | 308 | case CHECKS: 309 | move = *cur++; 310 | if (move != ttMove) 311 | return move; 312 | break; 313 | 314 | case STOP: 315 | return MOVE_NONE; 316 | 317 | default: 318 | assert(false); 319 | } 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /src/bitboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef BITBOARD_H_INCLUDED 22 | #define BITBOARD_H_INCLUDED 23 | 24 | #include 25 | 26 | #include "types.h" 27 | 28 | namespace Bitbases { 29 | 30 | void init(); 31 | bool probe(Square wksq, Square wpsq, Square bksq, Color us); 32 | 33 | } 34 | 35 | namespace Bitboards { 36 | 37 | void init(); 38 | const std::string pretty(Bitboard b); 39 | 40 | } 41 | 42 | const Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL; 43 | 44 | const Bitboard FileABB = 0x0101010101010101ULL; 45 | const Bitboard FileBBB = FileABB << 1; 46 | const Bitboard FileCBB = FileABB << 2; 47 | const Bitboard FileDBB = FileABB << 3; 48 | const Bitboard FileEBB = FileABB << 4; 49 | const Bitboard FileFBB = FileABB << 5; 50 | const Bitboard FileGBB = FileABB << 6; 51 | const Bitboard FileHBB = FileABB << 7; 52 | 53 | const Bitboard Rank1BB = 0xFF; 54 | const Bitboard Rank2BB = Rank1BB << (8 * 1); 55 | const Bitboard Rank3BB = Rank1BB << (8 * 2); 56 | const Bitboard Rank4BB = Rank1BB << (8 * 3); 57 | const Bitboard Rank5BB = Rank1BB << (8 * 4); 58 | const Bitboard Rank6BB = Rank1BB << (8 * 5); 59 | const Bitboard Rank7BB = Rank1BB << (8 * 6); 60 | const Bitboard Rank8BB = Rank1BB << (8 * 7); 61 | 62 | extern int SquareDistance[SQUARE_NB][SQUARE_NB]; 63 | 64 | extern Bitboard SquareBB[SQUARE_NB]; 65 | extern Bitboard FileBB[FILE_NB]; 66 | extern Bitboard RankBB[RANK_NB]; 67 | extern Bitboard AdjacentFilesBB[FILE_NB]; 68 | extern Bitboard InFrontBB[COLOR_NB][RANK_NB]; 69 | extern Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB]; 70 | extern Bitboard BetweenBB[SQUARE_NB][SQUARE_NB]; 71 | extern Bitboard LineBB[SQUARE_NB][SQUARE_NB]; 72 | extern Bitboard DistanceRingBB[SQUARE_NB][8]; 73 | extern Bitboard ForwardBB[COLOR_NB][SQUARE_NB]; 74 | extern Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB]; 75 | extern Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB]; 76 | extern Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB]; 77 | 78 | 79 | /// Overloads of bitwise operators between a Bitboard and a Square for testing 80 | /// whether a given bit is set in a bitboard, and for setting and clearing bits. 81 | 82 | inline Bitboard operator&(Bitboard b, Square s) { 83 | return b & SquareBB[s]; 84 | } 85 | 86 | inline Bitboard operator|(Bitboard b, Square s) { 87 | return b | SquareBB[s]; 88 | } 89 | 90 | inline Bitboard operator^(Bitboard b, Square s) { 91 | return b ^ SquareBB[s]; 92 | } 93 | 94 | inline Bitboard& operator|=(Bitboard& b, Square s) { 95 | return b |= SquareBB[s]; 96 | } 97 | 98 | inline Bitboard& operator^=(Bitboard& b, Square s) { 99 | return b ^= SquareBB[s]; 100 | } 101 | 102 | inline bool more_than_one(Bitboard b) { 103 | return b & (b - 1); 104 | } 105 | 106 | 107 | /// rank_bb() and file_bb() return a bitboard representing all the squares on 108 | /// the given file or rank. 109 | 110 | inline Bitboard rank_bb(Rank r) { 111 | return RankBB[r]; 112 | } 113 | 114 | inline Bitboard rank_bb(Square s) { 115 | return RankBB[rank_of(s)]; 116 | } 117 | 118 | inline Bitboard file_bb(File f) { 119 | return FileBB[f]; 120 | } 121 | 122 | inline Bitboard file_bb(Square s) { 123 | return FileBB[file_of(s)]; 124 | } 125 | 126 | 127 | /// shift_bb() moves a bitboard one step along direction Delta. Mainly for pawns 128 | 129 | template 130 | inline Bitboard shift_bb(Bitboard b) { 131 | return Delta == DELTA_N ? b << 8 : Delta == DELTA_S ? b >> 8 132 | : Delta == DELTA_NE ? (b & ~FileHBB) << 9 : Delta == DELTA_SE ? (b & ~FileHBB) >> 7 133 | : Delta == DELTA_NW ? (b & ~FileABB) << 7 : Delta == DELTA_SW ? (b & ~FileABB) >> 9 134 | : 0; 135 | } 136 | 137 | 138 | /// adjacent_files_bb() returns a bitboard representing all the squares on the 139 | /// adjacent files of the given one. 140 | 141 | inline Bitboard adjacent_files_bb(File f) { 142 | return AdjacentFilesBB[f]; 143 | } 144 | 145 | 146 | /// between_bb() returns a bitboard representing all the squares between the two 147 | /// given ones. For instance, between_bb(SQ_C4, SQ_F7) returns a bitboard with 148 | /// the bits for square d5 and e6 set. If s1 and s2 are not on the same rank, file 149 | /// or diagonal, 0 is returned. 150 | 151 | inline Bitboard between_bb(Square s1, Square s2) { 152 | return BetweenBB[s1][s2]; 153 | } 154 | 155 | 156 | /// in_front_bb() returns a bitboard representing all the squares on all the ranks 157 | /// in front of the given one, from the point of view of the given color. For 158 | /// instance, in_front_bb(BLACK, RANK_3) will return the squares on ranks 1 and 2. 159 | 160 | inline Bitboard in_front_bb(Color c, Rank r) { 161 | return InFrontBB[c][r]; 162 | } 163 | 164 | 165 | /// forward_bb() returns a bitboard representing all the squares along the line 166 | /// in front of the given one, from the point of view of the given color: 167 | /// ForwardBB[c][s] = in_front_bb(c, s) & file_bb(s) 168 | 169 | inline Bitboard forward_bb(Color c, Square s) { 170 | return ForwardBB[c][s]; 171 | } 172 | 173 | 174 | /// pawn_attack_span() returns a bitboard representing all the squares that can be 175 | /// attacked by a pawn of the given color when it moves along its file, starting 176 | /// from the given square: 177 | /// PawnAttackSpan[c][s] = in_front_bb(c, s) & adjacent_files_bb(s); 178 | 179 | inline Bitboard pawn_attack_span(Color c, Square s) { 180 | return PawnAttackSpan[c][s]; 181 | } 182 | 183 | 184 | /// passed_pawn_mask() returns a bitboard mask which can be used to test if a 185 | /// pawn of the given color and on the given square is a passed pawn: 186 | /// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_bb(c, s) 187 | 188 | inline Bitboard passed_pawn_mask(Color c, Square s) { 189 | return PassedPawnMask[c][s]; 190 | } 191 | 192 | 193 | /// aligned() returns true if the squares s1, s2 and s3 are aligned either on a 194 | /// straight or on a diagonal line. 195 | 196 | inline bool aligned(Square s1, Square s2, Square s3) { 197 | return LineBB[s1][s2] & s3; 198 | } 199 | 200 | 201 | /// distance() functions return the distance between x and y, defined as the 202 | /// number of steps for a king in x to reach y. Works with squares, ranks, files. 203 | 204 | template inline int distance(T x, T y) { return x < y ? y - x : x - y; } 205 | template<> inline int distance(Square x, Square y) { return SquareDistance[x][y]; } 206 | 207 | template inline int distance(T2 x, T2 y); 208 | template<> inline int distance(Square x, Square y) { return distance(file_of(x), file_of(y)); } 209 | template<> inline int distance(Square x, Square y) { return distance(rank_of(x), rank_of(y)); } 210 | 211 | 212 | /// attacks_bb() returns a bitboard representing all the squares attacked by a 213 | /// piece of type Pt (bishop or rook) placed on 's'. The helper magic_index() 214 | /// looks up the index using the 'magic bitboards' approach. 215 | template 216 | inline unsigned magic_index(Square s, Bitboard occupied) { 217 | 218 | extern Bitboard RookMasks[SQUARE_NB]; 219 | extern Bitboard RookMagics[SQUARE_NB]; 220 | extern unsigned RookShifts[SQUARE_NB]; 221 | extern Bitboard BishopMasks[SQUARE_NB]; 222 | extern Bitboard BishopMagics[SQUARE_NB]; 223 | extern unsigned BishopShifts[SQUARE_NB]; 224 | 225 | Bitboard* const Masks = Pt == ROOK ? RookMasks : BishopMasks; 226 | Bitboard* const Magics = Pt == ROOK ? RookMagics : BishopMagics; 227 | unsigned* const Shifts = Pt == ROOK ? RookShifts : BishopShifts; 228 | 229 | if (HasPext) 230 | return unsigned(pext(occupied, Masks[s])); 231 | 232 | if (Is64Bit) 233 | return unsigned(((occupied & Masks[s]) * Magics[s]) >> Shifts[s]); 234 | 235 | unsigned lo = unsigned(occupied) & unsigned(Masks[s]); 236 | unsigned hi = unsigned(occupied >> 32) & unsigned(Masks[s] >> 32); 237 | return (lo * unsigned(Magics[s]) ^ hi * unsigned(Magics[s] >> 32)) >> Shifts[s]; 238 | } 239 | 240 | template 241 | inline Bitboard attacks_bb(Square s, Bitboard occupied) { 242 | 243 | extern Bitboard* RookAttacks[SQUARE_NB]; 244 | extern Bitboard* BishopAttacks[SQUARE_NB]; 245 | 246 | return (Pt == ROOK ? RookAttacks : BishopAttacks)[s][magic_index(s, occupied)]; 247 | } 248 | 249 | inline Bitboard attacks_bb(Piece pc, Square s, Bitboard occupied) { 250 | 251 | switch (type_of(pc)) 252 | { 253 | case BISHOP: return attacks_bb(s, occupied); 254 | case ROOK : return attacks_bb(s, occupied); 255 | case QUEEN : return attacks_bb(s, occupied) | attacks_bb(s, occupied); 256 | default : return StepAttacksBB[pc][s]; 257 | } 258 | } 259 | 260 | 261 | /// popcount() counts the number of non-zero bits in a bitboard 262 | 263 | inline int popcount(Bitboard b) { 264 | 265 | #ifndef USE_POPCNT 266 | 267 | extern uint8_t PopCnt16[1 << 16]; 268 | union { Bitboard bb; uint16_t u[4]; } v = { b }; 269 | return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]]; 270 | 271 | #elif defined(_MSC_VER) && defined(__INTEL_COMPILER) 272 | 273 | return _mm_popcnt_u64(b); 274 | 275 | #elif defined(_MSC_VER) 276 | 277 | return (int)__popcnt64(b); 278 | 279 | #else // Assumed gcc or compatible compiler 280 | 281 | return __builtin_popcountll(b); 282 | 283 | #endif 284 | } 285 | 286 | 287 | /// lsb() and msb() return the least/most significant bit in a non-zero bitboard 288 | 289 | #if defined(__GNUC__) 290 | 291 | inline Square lsb(Bitboard b) { 292 | assert(b); 293 | return Square(__builtin_ctzll(b)); 294 | } 295 | 296 | inline Square msb(Bitboard b) { 297 | assert(b); 298 | return Square(63 - __builtin_clzll(b)); 299 | } 300 | 301 | #elif defined(_WIN64) && defined(_MSC_VER) 302 | 303 | inline Square lsb(Bitboard b) { 304 | assert(b); 305 | unsigned long idx; 306 | _BitScanForward64(&idx, b); 307 | return (Square) idx; 308 | } 309 | 310 | inline Square msb(Bitboard b) { 311 | assert(b); 312 | unsigned long idx; 313 | _BitScanReverse64(&idx, b); 314 | return (Square) idx; 315 | } 316 | 317 | #else 318 | 319 | #define NO_BSF // Fallback on software implementation for other cases 320 | 321 | Square lsb(Bitboard b); 322 | Square msb(Bitboard b); 323 | 324 | #endif 325 | 326 | 327 | /// pop_lsb() finds and clears the least significant bit in a non-zero bitboard 328 | 329 | inline Square pop_lsb(Bitboard* b) { 330 | const Square s = lsb(*b); 331 | *b &= *b - 1; 332 | return s; 333 | } 334 | 335 | 336 | /// frontmost_sq() and backmost_sq() return the square corresponding to the 337 | /// most/least advanced bit relative to the given color. 338 | 339 | inline Square frontmost_sq(Color c, Bitboard b) { return c == WHITE ? msb(b) : lsb(b); } 340 | inline Square backmost_sq(Color c, Bitboard b) { return c == WHITE ? lsb(b) : msb(b); } 341 | 342 | #endif // #ifndef BITBOARD_H_INCLUDED 343 | -------------------------------------------------------------------------------- /src/pawns.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #include "bitboard.h" 25 | #include "pawns.h" 26 | #include "position.h" 27 | #include "thread.h" 28 | 29 | namespace { 30 | 31 | #define V Value 32 | #define S(mg, eg) make_score(mg, eg) 33 | 34 | // Isolated pawn penalty by opposed flag and file 35 | const Score Isolated[2][FILE_NB] = { 36 | { S(31, 36), S(45, 41), S(50, 41), S(50, 41), 37 | S(50, 41), S(50, 41), S(45, 41), S(31, 36) }, 38 | { S(21, 24), S(30, 28), S(33, 28), S(33, 28), 39 | S(33, 28), S(33, 28), S(30, 28), S(21, 24) } }; 40 | 41 | // Backward pawn penalty by opposed flag 42 | const Score Backward[2] = { S(56, 33), S(41, 19) }; 43 | 44 | // Unsupported pawn penalty for pawns which are neither isolated or backward, 45 | // by number of pawns it supports [less than 2 / exactly 2]. 46 | const Score Unsupported[2] = { S(17, 8), S(21, 12) }; 47 | 48 | // Connected pawn bonus by opposed, phalanx, twice supported and rank 49 | Score Connected[2][2][2][RANK_NB]; 50 | 51 | // Doubled pawn penalty by file 52 | const Score Doubled[FILE_NB] = { 53 | S(11, 34), S(17, 38), S(19, 38), S(19, 38), 54 | S(19, 38), S(19, 38), S(17, 38), S(11, 34) }; 55 | 56 | // Lever bonus by rank 57 | const Score Lever[RANK_NB] = { 58 | S( 0, 0), S( 0, 0), S(0, 0), S(0, 0), 59 | S(17, 16), S(33, 32), S(0, 0), S(0, 0) }; 60 | 61 | // Weakness of our pawn shelter in front of the king by [distance from edge][rank] 62 | const Value ShelterWeakness[][RANK_NB] = { 63 | { V( 97), V(21), V(26), V(51), V(87), V( 89), V( 99) }, 64 | { V(120), V( 0), V(28), V(76), V(88), V(103), V(104) }, 65 | { V(101), V( 7), V(54), V(78), V(77), V( 92), V(101) }, 66 | { V( 80), V(11), V(44), V(68), V(87), V( 90), V(119) } }; 67 | 68 | // Danger of enemy pawns moving toward our king by [type][distance from edge][rank] 69 | const Value StormDanger[][4][RANK_NB] = { 70 | { { V( 0), V( 67), V( 134), V(38), V(32) }, 71 | { V( 0), V( 57), V( 139), V(37), V(22) }, 72 | { V( 0), V( 43), V( 115), V(43), V(27) }, 73 | { V( 0), V( 68), V( 124), V(57), V(32) } }, 74 | { { V(20), V( 43), V( 100), V(56), V(20) }, 75 | { V(23), V( 20), V( 98), V(40), V(15) }, 76 | { V(23), V( 39), V( 103), V(36), V(18) }, 77 | { V(28), V( 19), V( 108), V(42), V(26) } }, 78 | { { V( 0), V( 0), V( 75), V(14), V( 2) }, 79 | { V( 0), V( 0), V( 150), V(30), V( 4) }, 80 | { V( 0), V( 0), V( 160), V(22), V( 5) }, 81 | { V( 0), V( 0), V( 166), V(24), V(13) } }, 82 | { { V( 0), V(-283), V(-281), V(57), V(31) }, 83 | { V( 0), V( 58), V( 141), V(39), V(18) }, 84 | { V( 0), V( 65), V( 142), V(48), V(32) }, 85 | { V( 0), V( 60), V( 126), V(51), V(19) } } }; 86 | 87 | // Max bonus for king safety. Corresponds to start position with all the pawns 88 | // in front of the king and no enemy pawn on the horizon. 89 | const Value MaxSafetyBonus = V(258); 90 | 91 | #undef S 92 | #undef V 93 | 94 | template 95 | Score evaluate(const Position& pos, Pawns::Entry* e) { 96 | 97 | const Color Them = (Us == WHITE ? BLACK : WHITE); 98 | const Square Up = (Us == WHITE ? DELTA_N : DELTA_S); 99 | const Square Right = (Us == WHITE ? DELTA_NE : DELTA_SW); 100 | const Square Left = (Us == WHITE ? DELTA_NW : DELTA_SE); 101 | 102 | Bitboard b, neighbours, stoppers, doubled, supported, phalanx; 103 | Square s; 104 | bool opposed, lever, connected, backward; 105 | Score score = SCORE_ZERO; 106 | const Square* pl = pos.squares(Us); 107 | const Bitboard* pawnAttacksBB = StepAttacksBB[make_piece(Us, PAWN)]; 108 | 109 | Bitboard ourPawns = pos.pieces(Us , PAWN); 110 | Bitboard theirPawns = pos.pieces(Them, PAWN); 111 | 112 | e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0; 113 | e->kingSquares[Us] = SQ_NONE; 114 | e->semiopenFiles[Us] = 0xFF; 115 | e->pawnAttacks[Us] = shift_bb(ourPawns) | shift_bb(ourPawns); 116 | e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares); 117 | e->pawnsOnSquares[Us][WHITE] = pos.count(Us) - e->pawnsOnSquares[Us][BLACK]; 118 | 119 | // Loop through all pawns of the current color and score each pawn 120 | while ((s = *pl++) != SQ_NONE) 121 | { 122 | assert(pos.piece_on(s) == make_piece(Us, PAWN)); 123 | 124 | File f = file_of(s); 125 | 126 | e->semiopenFiles[Us] &= ~(1 << f); 127 | e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s); 128 | 129 | // Flag the pawn 130 | opposed = theirPawns & forward_bb(Us, s); 131 | stoppers = theirPawns & passed_pawn_mask(Us, s); 132 | lever = theirPawns & pawnAttacksBB[s]; 133 | doubled = ourPawns & forward_bb(Us, s); 134 | neighbours = ourPawns & adjacent_files_bb(f); 135 | phalanx = neighbours & rank_bb(s); 136 | supported = neighbours & rank_bb(s - Up); 137 | connected = supported | phalanx; 138 | 139 | // A pawn is backward when it is behind all pawns of the same color on the 140 | // adjacent files and cannot be safely advanced. 141 | if (!neighbours || lever || relative_rank(Us, s) >= RANK_5) 142 | backward = false; 143 | else 144 | { 145 | // Find the backmost rank with neighbours or stoppers 146 | b = rank_bb(backmost_sq(Us, neighbours | stoppers)); 147 | 148 | // The pawn is backward when it cannot safely progress to that rank: 149 | // either there is a stopper in the way on this rank, or there is a 150 | // stopper on adjacent file which controls the way to that rank. 151 | backward = (b | shift_bb(b & adjacent_files_bb(f))) & stoppers; 152 | 153 | assert(!backward || !(pawn_attack_span(Them, s + Up) & neighbours)); 154 | } 155 | 156 | // Passed pawns will be properly scored in evaluation because we need 157 | // full attack info to evaluate them. Only the frontmost passed 158 | // pawn on each file is considered a true passed pawn. 159 | if (!(stoppers | doubled)) 160 | e->passedPawns[Us] |= s; 161 | 162 | // Score this pawn 163 | if (!neighbours) 164 | score -= Isolated[opposed][f]; 165 | 166 | else if (backward) 167 | score -= Backward[opposed]; 168 | 169 | else if (!supported) 170 | score -= Unsupported[more_than_one(neighbours & pawnAttacksBB[s])]; 171 | 172 | if (connected) 173 | score += Connected[opposed][!!phalanx][more_than_one(supported)][relative_rank(Us, s)]; 174 | 175 | if (doubled) 176 | score -= Doubled[f] / distance(s, frontmost_sq(Us, doubled)); 177 | 178 | if (lever) 179 | score += Lever[relative_rank(Us, s)]; 180 | } 181 | 182 | b = e->semiopenFiles[Us] ^ 0xFF; 183 | e->pawnSpan[Us] = b ? int(msb(b) - lsb(b)) : 0; 184 | 185 | return score; 186 | } 187 | 188 | } // namespace 189 | 190 | namespace Pawns { 191 | 192 | /// Pawns::init() initializes some tables needed by evaluation. Instead of using 193 | /// hard-coded tables, when makes sense, we prefer to calculate them with a formula 194 | /// to reduce independent parameters and to allow easier tuning and better insight. 195 | 196 | void init() 197 | { 198 | static const int Seed[RANK_NB] = { 0, 8, 19, 13, 71, 94, 169, 324 }; 199 | 200 | for (int opposed = 0; opposed <= 1; ++opposed) 201 | for (int phalanx = 0; phalanx <= 1; ++phalanx) 202 | for (int apex = 0; apex <= 1; ++apex) 203 | for (Rank r = RANK_2; r < RANK_8; ++r) 204 | { 205 | int v = (Seed[r] + (phalanx ? (Seed[r + 1] - Seed[r]) / 2 : 0)) >> opposed; 206 | v += (apex ? v / 2 : 0); 207 | Connected[opposed][phalanx][apex][r] = make_score(v, v * 5 / 8); 208 | } 209 | } 210 | 211 | 212 | /// Pawns::probe() looks up the current position's pawns configuration in 213 | /// the pawns hash table. It returns a pointer to the Entry if the position 214 | /// is found. Otherwise a new Entry is computed and stored there, so we don't 215 | /// have to recompute all when the same pawns configuration occurs again. 216 | 217 | Entry* probe(const Position& pos) { 218 | 219 | Key key = pos.pawn_key(); 220 | Entry* e = pos.this_thread()->pawnsTable[key]; 221 | 222 | if (e->key == key) 223 | return e; 224 | 225 | e->key = key; 226 | e->score = evaluate(pos, e) - evaluate(pos, e); 227 | e->asymmetry = popcount(e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK]); 228 | return e; 229 | } 230 | 231 | 232 | /// Entry::shelter_storm() calculates shelter and storm penalties for the file 233 | /// the king is on, as well as the two adjacent files. 234 | 235 | template 236 | Value Entry::shelter_storm(const Position& pos, Square ksq) { 237 | 238 | const Color Them = (Us == WHITE ? BLACK : WHITE); 239 | 240 | enum { NoFriendlyPawn, Unblocked, BlockedByPawn, BlockedByKing }; 241 | 242 | Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq)); 243 | Bitboard ourPawns = b & pos.pieces(Us); 244 | Bitboard theirPawns = b & pos.pieces(Them); 245 | Value safety = MaxSafetyBonus; 246 | File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq))); 247 | 248 | for (File f = center - File(1); f <= center + File(1); ++f) 249 | { 250 | b = ourPawns & file_bb(f); 251 | Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1; 252 | 253 | b = theirPawns & file_bb(f); 254 | Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1; 255 | 256 | safety -= ShelterWeakness[std::min(f, FILE_H - f)][rkUs] 257 | + StormDanger 258 | [f == file_of(ksq) && rkThem == relative_rank(Us, ksq) + 1 ? BlockedByKing : 259 | rkUs == RANK_1 ? NoFriendlyPawn : 260 | rkThem == rkUs + 1 ? BlockedByPawn : Unblocked] 261 | [std::min(f, FILE_H - f)][rkThem]; 262 | } 263 | 264 | return safety; 265 | } 266 | 267 | 268 | /// Entry::do_king_safety() calculates a bonus for king safety. It is called only 269 | /// when king square changes, which is about 20% of total king_safety() calls. 270 | 271 | template 272 | Score Entry::do_king_safety(const Position& pos, Square ksq) { 273 | 274 | kingSquares[Us] = ksq; 275 | castlingRights[Us] = pos.can_castle(Us); 276 | int minKingPawnDistance = 0; 277 | 278 | Bitboard pawns = pos.pieces(Us, PAWN); 279 | if (pawns) 280 | while (!(DistanceRingBB[ksq][minKingPawnDistance++] & pawns)) {} 281 | 282 | Value bonus = shelter_storm(pos, ksq); 283 | 284 | // If we can castle use the bonus after the castling if it is bigger 285 | if (pos.can_castle(MakeCastling::right)) 286 | bonus = std::max(bonus, shelter_storm(pos, relative_square(Us, SQ_G1))); 287 | 288 | if (pos.can_castle(MakeCastling::right)) 289 | bonus = std::max(bonus, shelter_storm(pos, relative_square(Us, SQ_C1))); 290 | 291 | return make_score(bonus, -16 * minKingPawnDistance); 292 | } 293 | 294 | // Explicit template instantiation 295 | template Score Entry::do_king_safety(const Position& pos, Square ksq); 296 | template Score Entry::do_king_safety(const Position& pos, Square ksq); 297 | 298 | } // namespace Pawns 299 | -------------------------------------------------------------------------------- /src/bitboard.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include "bitboard.h" 24 | #include "misc.h" 25 | 26 | uint8_t PopCnt16[1 << 16]; 27 | int SquareDistance[SQUARE_NB][SQUARE_NB]; 28 | 29 | Bitboard RookMasks [SQUARE_NB]; 30 | Bitboard RookMagics [SQUARE_NB]; 31 | Bitboard* RookAttacks[SQUARE_NB]; 32 | unsigned RookShifts [SQUARE_NB]; 33 | 34 | Bitboard BishopMasks [SQUARE_NB]; 35 | Bitboard BishopMagics [SQUARE_NB]; 36 | Bitboard* BishopAttacks[SQUARE_NB]; 37 | unsigned BishopShifts [SQUARE_NB]; 38 | 39 | Bitboard SquareBB[SQUARE_NB]; 40 | Bitboard FileBB[FILE_NB]; 41 | Bitboard RankBB[RANK_NB]; 42 | Bitboard AdjacentFilesBB[FILE_NB]; 43 | Bitboard InFrontBB[COLOR_NB][RANK_NB]; 44 | Bitboard StepAttacksBB[PIECE_NB][SQUARE_NB]; 45 | Bitboard BetweenBB[SQUARE_NB][SQUARE_NB]; 46 | Bitboard LineBB[SQUARE_NB][SQUARE_NB]; 47 | Bitboard DistanceRingBB[SQUARE_NB][8]; 48 | Bitboard ForwardBB[COLOR_NB][SQUARE_NB]; 49 | Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB]; 50 | Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB]; 51 | Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB]; 52 | 53 | namespace { 54 | 55 | // De Bruijn sequences. See chessprogramming.wikispaces.com/BitScan 56 | const uint64_t DeBruijn64 = 0x3F79D71B4CB0A89ULL; 57 | const uint32_t DeBruijn32 = 0x783A9B23; 58 | 59 | int MSBTable[256]; // To implement software msb() 60 | Square BSFTable[SQUARE_NB]; // To implement software bitscan 61 | Bitboard RookTable[0x19000]; // To store rook attacks 62 | Bitboard BishopTable[0x1480]; // To store bishop attacks 63 | 64 | typedef unsigned (Fn)(Square, Bitboard); 65 | 66 | void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[], 67 | Bitboard masks[], unsigned shifts[], Square deltas[], Fn index); 68 | 69 | // bsf_index() returns the index into BSFTable[] to look up the bitscan. Uses 70 | // Matt Taylor's folding for 32 bit case, extended to 64 bit by Kim Walisch. 71 | 72 | unsigned bsf_index(Bitboard b) { 73 | b ^= b - 1; 74 | return Is64Bit ? (b * DeBruijn64) >> 58 75 | : ((unsigned(b) ^ unsigned(b >> 32)) * DeBruijn32) >> 26; 76 | } 77 | 78 | 79 | // popcount16() counts the non-zero bits using SWAR-Popcount algorithm 80 | 81 | unsigned popcount16(unsigned u) { 82 | u -= (u >> 1) & 0x5555U; 83 | u = ((u >> 2) & 0x3333U) + (u & 0x3333U); 84 | u = ((u >> 4) + u) & 0x0F0FU; 85 | return (u * 0x0101U) >> 8; 86 | } 87 | } 88 | 89 | #ifdef NO_BSF 90 | 91 | /// Software fall-back of lsb() and msb() for CPU lacking hardware support 92 | 93 | Square lsb(Bitboard b) { 94 | assert(b); 95 | return BSFTable[bsf_index(b)]; 96 | } 97 | 98 | Square msb(Bitboard b) { 99 | 100 | assert(b); 101 | unsigned b32; 102 | int result = 0; 103 | 104 | if (b > 0xFFFFFFFF) 105 | { 106 | b >>= 32; 107 | result = 32; 108 | } 109 | 110 | b32 = unsigned(b); 111 | 112 | if (b32 > 0xFFFF) 113 | { 114 | b32 >>= 16; 115 | result += 16; 116 | } 117 | 118 | if (b32 > 0xFF) 119 | { 120 | b32 >>= 8; 121 | result += 8; 122 | } 123 | 124 | return Square(result + MSBTable[b32]); 125 | } 126 | 127 | #endif // ifdef NO_BSF 128 | 129 | 130 | /// Bitboards::pretty() returns an ASCII representation of a bitboard suitable 131 | /// to be printed to standard output. Useful for debugging. 132 | 133 | const std::string Bitboards::pretty(Bitboard b) { 134 | 135 | std::string s = "+---+---+---+---+---+---+---+---+\n"; 136 | 137 | for (Rank r = RANK_8; r >= RANK_1; --r) 138 | { 139 | for (File f = FILE_A; f <= FILE_H; ++f) 140 | s += b & make_square(f, r) ? "| X " : "| "; 141 | 142 | s += "|\n+---+---+---+---+---+---+---+---+\n"; 143 | } 144 | 145 | return s; 146 | } 147 | 148 | 149 | /// Bitboards::init() initializes various bitboard tables. It is called at 150 | /// startup and relies on global objects to be already zero-initialized. 151 | 152 | void Bitboards::init() { 153 | 154 | for (unsigned i = 0; i < (1 << 16); ++i) 155 | PopCnt16[i] = (uint8_t) popcount16(i); 156 | 157 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 158 | { 159 | SquareBB[s] = 1ULL << s; 160 | BSFTable[bsf_index(SquareBB[s])] = s; 161 | } 162 | 163 | for (Bitboard b = 2; b < 256; ++b) 164 | MSBTable[b] = MSBTable[b - 1] + !more_than_one(b); 165 | 166 | for (File f = FILE_A; f <= FILE_H; ++f) 167 | FileBB[f] = f > FILE_A ? FileBB[f - 1] << 1 : FileABB; 168 | 169 | for (Rank r = RANK_1; r <= RANK_8; ++r) 170 | RankBB[r] = r > RANK_1 ? RankBB[r - 1] << 8 : Rank1BB; 171 | 172 | for (File f = FILE_A; f <= FILE_H; ++f) 173 | AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0); 174 | 175 | for (Rank r = RANK_1; r < RANK_8; ++r) 176 | InFrontBB[WHITE][r] = ~(InFrontBB[BLACK][r + 1] = InFrontBB[BLACK][r] | RankBB[r]); 177 | 178 | for (Color c = WHITE; c <= BLACK; ++c) 179 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 180 | { 181 | ForwardBB[c][s] = InFrontBB[c][rank_of(s)] & FileBB[file_of(s)]; 182 | PawnAttackSpan[c][s] = InFrontBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)]; 183 | PassedPawnMask[c][s] = ForwardBB[c][s] | PawnAttackSpan[c][s]; 184 | } 185 | 186 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) 187 | for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) 188 | if (s1 != s2) 189 | { 190 | SquareDistance[s1][s2] = std::max(distance(s1, s2), distance(s1, s2)); 191 | DistanceRingBB[s1][SquareDistance[s1][s2] - 1] |= s2; 192 | } 193 | 194 | int steps[][9] = { {}, { 7, 9 }, { 17, 15, 10, 6, -6, -10, -15, -17 }, 195 | {}, {}, {}, { 9, 7, -7, -9, 8, 1, -1, -8 } }; 196 | 197 | for (Color c = WHITE; c <= BLACK; ++c) 198 | for (PieceType pt = PAWN; pt <= KING; ++pt) 199 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 200 | for (int i = 0; steps[pt][i]; ++i) 201 | { 202 | Square to = s + Square(c == WHITE ? steps[pt][i] : -steps[pt][i]); 203 | 204 | if (is_ok(to) && distance(s, to) < 3) 205 | StepAttacksBB[make_piece(c, pt)][s] |= to; 206 | } 207 | 208 | Square RookDeltas[] = { DELTA_N, DELTA_E, DELTA_S, DELTA_W }; 209 | Square BishopDeltas[] = { DELTA_NE, DELTA_SE, DELTA_SW, DELTA_NW }; 210 | 211 | init_magics(RookTable, RookAttacks, RookMagics, RookMasks, RookShifts, RookDeltas, magic_index); 212 | init_magics(BishopTable, BishopAttacks, BishopMagics, BishopMasks, BishopShifts, BishopDeltas, magic_index); 213 | 214 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) 215 | { 216 | PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb(s1, 0); 217 | PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0); 218 | 219 | for (Piece pc = W_BISHOP; pc <= W_ROOK; ++pc) 220 | for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) 221 | { 222 | if (!(PseudoAttacks[pc][s1] & s2)) 223 | continue; 224 | 225 | LineBB[s1][s2] = (attacks_bb(pc, s1, 0) & attacks_bb(pc, s2, 0)) | s1 | s2; 226 | BetweenBB[s1][s2] = attacks_bb(pc, s1, SquareBB[s2]) & attacks_bb(pc, s2, SquareBB[s1]); 227 | } 228 | } 229 | } 230 | 231 | 232 | namespace { 233 | 234 | Bitboard sliding_attack(Square deltas[], Square sq, Bitboard occupied) { 235 | 236 | Bitboard attack = 0; 237 | 238 | for (int i = 0; i < 4; ++i) 239 | for (Square s = sq + deltas[i]; 240 | is_ok(s) && distance(s, s - deltas[i]) == 1; 241 | s += deltas[i]) 242 | { 243 | attack |= s; 244 | 245 | if (occupied & s) 246 | break; 247 | } 248 | 249 | return attack; 250 | } 251 | 252 | 253 | // init_magics() computes all rook and bishop attacks at startup. Magic 254 | // bitboards are used to look up attacks of sliding pieces. As a reference see 255 | // chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we 256 | // use the so called "fancy" approach. 257 | 258 | void init_magics(Bitboard table[], Bitboard* attacks[], Bitboard magics[], 259 | Bitboard masks[], unsigned shifts[], Square deltas[], Fn index) { 260 | 261 | int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 }, 262 | { 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } }; 263 | 264 | Bitboard occupancy[4096], reference[4096], edges, b; 265 | int age[4096] = {0}, current = 0, i, size; 266 | 267 | // attacks[s] is a pointer to the beginning of the attacks table for square 's' 268 | attacks[SQ_A1] = table; 269 | 270 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 271 | { 272 | // Board edges are not considered in the relevant occupancies 273 | edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s)); 274 | 275 | // Given a square 's', the mask is the bitboard of sliding attacks from 276 | // 's' computed on an empty board. The index must be big enough to contain 277 | // all the attacks for each possible subset of the mask and so is 2 power 278 | // the number of 1s of the mask. Hence we deduce the size of the shift to 279 | // apply to the 64 or 32 bits word to get the index. 280 | masks[s] = sliding_attack(deltas, s, 0) & ~edges; 281 | shifts[s] = (Is64Bit ? 64 : 32) - popcount(masks[s]); 282 | 283 | // Use Carry-Rippler trick to enumerate all subsets of masks[s] and 284 | // store the corresponding sliding attack bitboard in reference[]. 285 | b = size = 0; 286 | do { 287 | occupancy[size] = b; 288 | reference[size] = sliding_attack(deltas, s, b); 289 | 290 | if (HasPext) 291 | attacks[s][pext(b, masks[s])] = reference[size]; 292 | 293 | size++; 294 | b = (b - masks[s]) & masks[s]; 295 | } while (b); 296 | 297 | // Set the offset for the table of the next square. We have individual 298 | // table sizes for each square with "Fancy Magic Bitboards". 299 | if (s < SQ_H8) 300 | attacks[s + 1] = attacks[s] + size; 301 | 302 | if (HasPext) 303 | continue; 304 | 305 | PRNG rng(seeds[Is64Bit][rank_of(s)]); 306 | 307 | // Find a magic for square 's' picking up an (almost) random number 308 | // until we find the one that passes the verification test. 309 | do { 310 | do 311 | magics[s] = rng.sparse_rand(); 312 | while (popcount((magics[s] * masks[s]) >> 56) < 6); 313 | 314 | // A good magic must map every possible occupancy to an index that 315 | // looks up the correct sliding attack in the attacks[s] database. 316 | // Note that we build up the database for square 's' as a side 317 | // effect of verifying the magic. 318 | for (++current, i = 0; i < size; ++i) 319 | { 320 | unsigned idx = index(s, occupancy[i]); 321 | 322 | if (age[idx] < current) 323 | { 324 | age[idx] = current; 325 | attacks[s][idx] = reference[i]; 326 | } 327 | else if (attacks[s][idx] != reference[i]) 328 | break; 329 | } 330 | } while (i < size); 331 | } 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /src/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef TYPES_H_INCLUDED 22 | #define TYPES_H_INCLUDED 23 | 24 | /// When compiling with provided Makefile (e.g. for Linux and OSX), configuration 25 | /// is done automatically. To get started type 'make help'. 26 | /// 27 | /// When Makefile is not used (e.g. with Microsoft Visual Studio) some switches 28 | /// need to be set manually: 29 | /// 30 | /// -DNDEBUG | Disable debugging mode. Always use this for release. 31 | /// 32 | /// -DNO_PREFETCH | Disable use of prefetch asm-instruction. You may need this to 33 | /// | run on some very old machines. 34 | /// 35 | /// -DUSE_POPCNT | Add runtime support for use of popcnt asm-instruction. Works 36 | /// | only in 64-bit mode and requires hardware with popcnt support. 37 | /// 38 | /// -DUSE_PEXT | Add runtime support for use of pext asm-instruction. Works 39 | /// | only in 64-bit mode and requires hardware with pext support. 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #if defined(_MSC_VER) 48 | // Disable some silly and noisy warning from MSVC compiler 49 | #pragma warning(disable: 4127) // Conditional expression is constant 50 | #pragma warning(disable: 4146) // Unary minus operator applied to unsigned type 51 | #pragma warning(disable: 4800) // Forcing value to bool 'true' or 'false' 52 | #endif 53 | 54 | /// Predefined macros hell: 55 | /// 56 | /// __GNUC__ Compiler is gcc, Clang or Intel on Linux 57 | /// __INTEL_COMPILER Compiler is Intel 58 | /// _MSC_VER Compiler is MSVC or Intel on Windows 59 | /// _WIN32 Building on Windows (any) 60 | /// _WIN64 Building on Windows 64 bit 61 | 62 | #if defined(_WIN64) && defined(_MSC_VER) // No Makefile used 63 | # include // MSVC popcnt and bsfq instrinsics 64 | # define IS_64BIT 65 | #endif 66 | 67 | #if defined(USE_POPCNT) && defined(__INTEL_COMPILER) && defined(_MSC_VER) 68 | # include // Intel header for _mm_popcnt_u64() intrinsic 69 | #endif 70 | 71 | #if !defined(NO_PREFETCH) && (defined(__INTEL_COMPILER) || defined(_MSC_VER)) 72 | # include // Intel and Microsoft header for _mm_prefetch() 73 | #endif 74 | 75 | #if defined(USE_PEXT) 76 | # include // Header for _pext_u64() intrinsic 77 | # define pext(b, m) _pext_u64(b, m) 78 | #else 79 | # define pext(b, m) (0) 80 | #endif 81 | 82 | #ifdef USE_POPCNT 83 | const bool HasPopCnt = true; 84 | #else 85 | const bool HasPopCnt = false; 86 | #endif 87 | 88 | #ifdef USE_PEXT 89 | const bool HasPext = true; 90 | #else 91 | const bool HasPext = false; 92 | #endif 93 | 94 | #ifdef IS_64BIT 95 | const bool Is64Bit = true; 96 | #else 97 | const bool Is64Bit = false; 98 | #endif 99 | 100 | typedef uint64_t Key; 101 | typedef uint64_t Bitboard; 102 | 103 | const int MAX_MOVES = 256; 104 | const int MAX_PLY = 128; 105 | 106 | /// A move needs 16 bits to be stored 107 | /// 108 | /// bit 0- 5: destination square (from 0 to 63) 109 | /// bit 6-11: origin square (from 0 to 63) 110 | /// bit 12-13: promotion piece type - 2 (from KNIGHT-2 to QUEEN-2) 111 | /// bit 14-15: special move flag: promotion (1), en passant (2), castling (3) 112 | /// NOTE: EN-PASSANT bit is set only when a pawn can be captured 113 | /// 114 | /// Special cases are MOVE_NONE and MOVE_NULL. We can sneak these in because in 115 | /// any normal move destination square is always different from origin square 116 | /// while MOVE_NONE and MOVE_NULL have the same origin and destination square. 117 | 118 | enum Move { 119 | MOVE_NONE, 120 | MOVE_NULL = 65 121 | }; 122 | 123 | enum MoveType { 124 | NORMAL, 125 | PROMOTION = 1 << 14, 126 | ENPASSANT = 2 << 14, 127 | CASTLING = 3 << 14 128 | }; 129 | 130 | enum Color { 131 | WHITE, BLACK, NO_COLOR, COLOR_NB = 2 132 | }; 133 | 134 | enum CastlingSide { 135 | KING_SIDE, QUEEN_SIDE, CASTLING_SIDE_NB = 2 136 | }; 137 | 138 | enum CastlingRight { 139 | NO_CASTLING, 140 | WHITE_OO, 141 | WHITE_OOO = WHITE_OO << 1, 142 | BLACK_OO = WHITE_OO << 2, 143 | BLACK_OOO = WHITE_OO << 3, 144 | ANY_CASTLING = WHITE_OO | WHITE_OOO | BLACK_OO | BLACK_OOO, 145 | CASTLING_RIGHT_NB = 16 146 | }; 147 | 148 | template struct MakeCastling { 149 | static const CastlingRight 150 | right = C == WHITE ? S == QUEEN_SIDE ? WHITE_OOO : WHITE_OO 151 | : S == QUEEN_SIDE ? BLACK_OOO : BLACK_OO; 152 | }; 153 | 154 | enum Phase { 155 | PHASE_ENDGAME, 156 | PHASE_MIDGAME = 128, 157 | MG = 0, EG = 1, PHASE_NB = 2 158 | }; 159 | 160 | enum ScaleFactor { 161 | SCALE_FACTOR_DRAW = 0, 162 | SCALE_FACTOR_ONEPAWN = 48, 163 | SCALE_FACTOR_NORMAL = 64, 164 | SCALE_FACTOR_MAX = 128, 165 | SCALE_FACTOR_NONE = 255 166 | }; 167 | 168 | enum Bound { 169 | BOUND_NONE, 170 | BOUND_UPPER, 171 | BOUND_LOWER, 172 | BOUND_EXACT = BOUND_UPPER | BOUND_LOWER 173 | }; 174 | 175 | enum Value : int { 176 | VALUE_ZERO = 0, 177 | VALUE_DRAW = 0, 178 | VALUE_KNOWN_WIN = 10000, 179 | VALUE_MATE = 32000, 180 | VALUE_INFINITE = 32001, 181 | VALUE_NONE = 32002, 182 | 183 | VALUE_MATE_IN_MAX_PLY = VALUE_MATE - 2 * MAX_PLY, 184 | VALUE_MATED_IN_MAX_PLY = -VALUE_MATE + 2 * MAX_PLY, 185 | 186 | PawnValueMg = 198, PawnValueEg = 258, 187 | KnightValueMg = 817, KnightValueEg = 896, 188 | BishopValueMg = 836, BishopValueEg = 907, 189 | RookValueMg = 1270, RookValueEg = 1356, 190 | QueenValueMg = 2521, QueenValueEg = 2658, 191 | 192 | MidgameLimit = 15581, EndgameLimit = 3998 193 | }; 194 | 195 | enum PieceType { 196 | NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING, 197 | ALL_PIECES = 0, 198 | PIECE_TYPE_NB = 8 199 | }; 200 | 201 | enum Piece { 202 | NO_PIECE, 203 | W_PAWN = 1, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING, 204 | B_PAWN = 9, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING, 205 | PIECE_NB = 16 206 | }; 207 | 208 | enum Depth { 209 | 210 | ONE_PLY = 1, 211 | 212 | DEPTH_ZERO = 0, 213 | DEPTH_QS_CHECKS = 0, 214 | DEPTH_QS_NO_CHECKS = -1, 215 | DEPTH_QS_RECAPTURES = -5, 216 | 217 | DEPTH_NONE = -6, 218 | DEPTH_MAX = MAX_PLY 219 | }; 220 | 221 | enum Square { 222 | SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1, 223 | SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2, 224 | SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3, 225 | SQ_A4, SQ_B4, SQ_C4, SQ_D4, SQ_E4, SQ_F4, SQ_G4, SQ_H4, 226 | SQ_A5, SQ_B5, SQ_C5, SQ_D5, SQ_E5, SQ_F5, SQ_G5, SQ_H5, 227 | SQ_A6, SQ_B6, SQ_C6, SQ_D6, SQ_E6, SQ_F6, SQ_G6, SQ_H6, 228 | SQ_A7, SQ_B7, SQ_C7, SQ_D7, SQ_E7, SQ_F7, SQ_G7, SQ_H7, 229 | SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8, 230 | SQ_NONE, 231 | 232 | SQUARE_NB = 64, 233 | 234 | DELTA_N = 8, 235 | DELTA_E = 1, 236 | DELTA_S = -8, 237 | DELTA_W = -1, 238 | 239 | DELTA_NN = DELTA_N + DELTA_N, 240 | DELTA_NE = DELTA_N + DELTA_E, 241 | DELTA_SE = DELTA_S + DELTA_E, 242 | DELTA_SS = DELTA_S + DELTA_S, 243 | DELTA_SW = DELTA_S + DELTA_W, 244 | DELTA_NW = DELTA_N + DELTA_W 245 | }; 246 | 247 | enum File { 248 | FILE_A, FILE_B, FILE_C, FILE_D, FILE_E, FILE_F, FILE_G, FILE_H, FILE_NB 249 | }; 250 | 251 | enum Rank { 252 | RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8, RANK_NB 253 | }; 254 | 255 | 256 | /// Score enum stores a middlegame and an endgame value in a single integer 257 | /// (enum). The least significant 16 bits are used to store the endgame value 258 | /// and the upper 16 bits are used to store the middlegame value. 259 | enum Score : int { SCORE_ZERO }; 260 | 261 | inline Score make_score(int mg, int eg) { 262 | return Score((mg << 16) + eg); 263 | } 264 | 265 | /// Extracting the signed lower and upper 16 bits is not so trivial because 266 | /// according to the standard a simple cast to short is implementation defined 267 | /// and so is a right shift of a signed integer. 268 | inline Value mg_value(Score s) { 269 | 270 | union { uint16_t u; int16_t s; } mg = { uint16_t(unsigned(s + 0x8000) >> 16) }; 271 | return Value(mg.s); 272 | } 273 | 274 | inline Value eg_value(Score s) { 275 | 276 | union { uint16_t u; int16_t s; } eg = { uint16_t(unsigned(s)) }; 277 | return Value(eg.s); 278 | } 279 | 280 | #define ENABLE_BASE_OPERATORS_ON(T) \ 281 | inline T operator+(T d1, T d2) { return T(int(d1) + int(d2)); } \ 282 | inline T operator-(T d1, T d2) { return T(int(d1) - int(d2)); } \ 283 | inline T operator*(int i, T d) { return T(i * int(d)); } \ 284 | inline T operator*(T d, int i) { return T(int(d) * i); } \ 285 | inline T operator-(T d) { return T(-int(d)); } \ 286 | inline T& operator+=(T& d1, T d2) { return d1 = d1 + d2; } \ 287 | inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; } \ 288 | inline T& operator*=(T& d, int i) { return d = T(int(d) * i); } 289 | 290 | #define ENABLE_FULL_OPERATORS_ON(T) \ 291 | ENABLE_BASE_OPERATORS_ON(T) \ 292 | inline T& operator++(T& d) { return d = T(int(d) + 1); } \ 293 | inline T& operator--(T& d) { return d = T(int(d) - 1); } \ 294 | inline T operator/(T d, int i) { return T(int(d) / i); } \ 295 | inline int operator/(T d1, T d2) { return int(d1) / int(d2); } \ 296 | inline T& operator/=(T& d, int i) { return d = T(int(d) / i); } 297 | 298 | ENABLE_FULL_OPERATORS_ON(Value) 299 | ENABLE_FULL_OPERATORS_ON(PieceType) 300 | ENABLE_FULL_OPERATORS_ON(Piece) 301 | ENABLE_FULL_OPERATORS_ON(Color) 302 | ENABLE_FULL_OPERATORS_ON(Depth) 303 | ENABLE_FULL_OPERATORS_ON(Square) 304 | ENABLE_FULL_OPERATORS_ON(File) 305 | ENABLE_FULL_OPERATORS_ON(Rank) 306 | 307 | ENABLE_BASE_OPERATORS_ON(Score) 308 | 309 | #undef ENABLE_FULL_OPERATORS_ON 310 | #undef ENABLE_BASE_OPERATORS_ON 311 | 312 | /// Additional operators to add integers to a Value 313 | inline Value operator+(Value v, int i) { return Value(int(v) + i); } 314 | inline Value operator-(Value v, int i) { return Value(int(v) - i); } 315 | inline Value& operator+=(Value& v, int i) { return v = v + i; } 316 | inline Value& operator-=(Value& v, int i) { return v = v - i; } 317 | 318 | /// Only declared but not defined. We don't want to multiply two scores due to 319 | /// a very high risk of overflow. So user should explicitly convert to integer. 320 | inline Score operator*(Score s1, Score s2); 321 | 322 | /// Division of a Score must be handled separately for each term 323 | inline Score operator/(Score s, int i) { 324 | return make_score(mg_value(s) / i, eg_value(s) / i); 325 | } 326 | 327 | extern Value PieceValue[PHASE_NB][PIECE_NB]; 328 | 329 | inline Color operator~(Color c) { 330 | return Color(c ^ BLACK); 331 | } 332 | 333 | inline Square operator~(Square s) { 334 | return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8 335 | } 336 | 337 | inline CastlingRight operator|(Color c, CastlingSide s) { 338 | return CastlingRight(WHITE_OO << ((s == QUEEN_SIDE) + 2 * c)); 339 | } 340 | 341 | inline Value mate_in(int ply) { 342 | return VALUE_MATE - ply; 343 | } 344 | 345 | inline Value mated_in(int ply) { 346 | return -VALUE_MATE + ply; 347 | } 348 | 349 | inline Square make_square(File f, Rank r) { 350 | return Square((r << 3) | f); 351 | } 352 | 353 | inline Piece make_piece(Color c, PieceType pt) { 354 | return Piece((c << 3) | pt); 355 | } 356 | 357 | inline PieceType type_of(Piece pc) { 358 | return PieceType(pc & 7); 359 | } 360 | 361 | inline Color color_of(Piece pc) { 362 | assert(pc != NO_PIECE); 363 | return Color(pc >> 3); 364 | } 365 | 366 | inline bool is_ok(Square s) { 367 | return s >= SQ_A1 && s <= SQ_H8; 368 | } 369 | 370 | inline File file_of(Square s) { 371 | return File(s & 7); 372 | } 373 | 374 | inline Rank rank_of(Square s) { 375 | return Rank(s >> 3); 376 | } 377 | 378 | inline Square relative_square(Color c, Square s) { 379 | return Square(s ^ (c * 56)); 380 | } 381 | 382 | inline Rank relative_rank(Color c, Rank r) { 383 | return Rank(r ^ (c * 7)); 384 | } 385 | 386 | inline Rank relative_rank(Color c, Square s) { 387 | return relative_rank(c, rank_of(s)); 388 | } 389 | 390 | inline bool opposite_colors(Square s1, Square s2) { 391 | int s = int(s1) ^ int(s2); 392 | return ((s >> 3) ^ s) & 1; 393 | } 394 | 395 | inline Square pawn_push(Color c) { 396 | return c == WHITE ? DELTA_N : DELTA_S; 397 | } 398 | 399 | inline Square from_sq(Move m) { 400 | return Square((m >> 6) & 0x3F); 401 | } 402 | 403 | inline Square to_sq(Move m) { 404 | return Square(m & 0x3F); 405 | } 406 | 407 | inline MoveType type_of(Move m) { 408 | return MoveType(m & (3 << 14)); 409 | } 410 | 411 | inline PieceType promotion_type(Move m) { 412 | return PieceType(((m >> 12) & 3) + KNIGHT); 413 | } 414 | 415 | inline Move make_move(Square from, Square to) { 416 | return Move(to | (from << 6)); 417 | } 418 | 419 | template 420 | inline Move make(Square from, Square to, PieceType pt = KNIGHT) { 421 | return Move(to | (from << 6) | T | ((pt - KNIGHT) << 12)); 422 | } 423 | 424 | inline bool is_ok(Move m) { 425 | return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE 426 | } 427 | 428 | #endif // #ifndef TYPES_H_INCLUDED 429 | -------------------------------------------------------------------------------- /src/position.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #ifndef POSITION_H_INCLUDED 22 | #define POSITION_H_INCLUDED 23 | 24 | #include 25 | #include // For offsetof() 26 | #include 27 | 28 | #include "bitboard.h" 29 | #include "types.h" 30 | 31 | class Position; 32 | class Thread; 33 | 34 | namespace PSQT { 35 | 36 | extern Score psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB]; 37 | 38 | void init(); 39 | } 40 | 41 | /// CheckInfo struct is initialized at constructor time and keeps info used to 42 | /// detect if a move gives check. 43 | 44 | struct CheckInfo { 45 | 46 | explicit CheckInfo(const Position&); 47 | 48 | Bitboard dcCandidates; 49 | Bitboard pinned; 50 | Bitboard checkSquares[PIECE_TYPE_NB]; 51 | Square ksq; 52 | }; 53 | 54 | 55 | /// StateInfo struct stores information needed to restore a Position object to 56 | /// its previous state when we retract a move. Whenever a move is made on the 57 | /// board (by calling Position::do_move), a StateInfo object must be passed. 58 | 59 | struct StateInfo { 60 | 61 | // Copied when making a move 62 | Key pawnKey; 63 | Key materialKey; 64 | Value nonPawnMaterial[COLOR_NB]; 65 | int castlingRights; 66 | int rule50; 67 | int pliesFromNull; 68 | Score psq; 69 | Square epSquare; 70 | 71 | // Not copied when making a move 72 | Key key; 73 | Bitboard checkersBB; 74 | PieceType capturedType; 75 | StateInfo* previous; 76 | }; 77 | 78 | 79 | /// Position class stores information regarding the board representation as 80 | /// pieces, side to move, hash keys, castling info, etc. Important methods are 81 | /// do_move() and undo_move(), used by the search to update node info when 82 | /// traversing the search tree. 83 | 84 | class Position { 85 | 86 | public: 87 | static void init(); 88 | 89 | Position() = default; // To define the global object RootPos 90 | Position(const Position&) = delete; 91 | Position(const Position& pos, Thread* th) { *this = pos; thisThread = th; } 92 | Position(const std::string& f, bool c960, Thread* th) { set(f, c960, th); } 93 | Position& operator=(const Position&); // To assign RootPos from UCI 94 | 95 | // FEN string input/output 96 | void set(const std::string& fenStr, bool isChess960, Thread* th); 97 | const std::string fen() const; 98 | 99 | // Position representation 100 | Bitboard pieces() const; 101 | Bitboard pieces(PieceType pt) const; 102 | Bitboard pieces(PieceType pt1, PieceType pt2) const; 103 | Bitboard pieces(Color c) const; 104 | Bitboard pieces(Color c, PieceType pt) const; 105 | Bitboard pieces(Color c, PieceType pt1, PieceType pt2) const; 106 | Piece piece_on(Square s) const; 107 | Square ep_square() const; 108 | bool empty(Square s) const; 109 | template int count(Color c) const; 110 | template const Square* squares(Color c) const; 111 | template Square square(Color c) const; 112 | 113 | // Castling 114 | int can_castle(Color c) const; 115 | int can_castle(CastlingRight cr) const; 116 | bool castling_impeded(CastlingRight cr) const; 117 | Square castling_rook_square(CastlingRight cr) const; 118 | 119 | // Checking 120 | Bitboard checkers() const; 121 | Bitboard discovered_check_candidates() const; 122 | Bitboard pinned_pieces(Color c) const; 123 | 124 | // Attacks to/from a given square 125 | Bitboard attackers_to(Square s) const; 126 | Bitboard attackers_to(Square s, Bitboard occupied) const; 127 | Bitboard attacks_from(Piece pc, Square s) const; 128 | template Bitboard attacks_from(Square s) const; 129 | template Bitboard attacks_from(Square s, Color c) const; 130 | 131 | // Properties of moves 132 | bool legal(Move m, Bitboard pinned) const; 133 | bool pseudo_legal(const Move m) const; 134 | bool capture(Move m) const; 135 | bool capture_or_promotion(Move m) const; 136 | bool gives_check(Move m, const CheckInfo& ci) const; 137 | bool advanced_pawn_push(Move m) const; 138 | Piece moved_piece(Move m) const; 139 | PieceType captured_piece_type() const; 140 | 141 | // Piece specific 142 | bool pawn_passed(Color c, Square s) const; 143 | bool opposite_bishops() const; 144 | 145 | // Doing and undoing moves 146 | void do_move(Move m, StateInfo& st, bool givesCheck); 147 | void undo_move(Move m); 148 | void do_null_move(StateInfo& st); 149 | void undo_null_move(); 150 | 151 | // Static exchange evaluation 152 | Value see(Move m) const; 153 | Value see_sign(Move m) const; 154 | 155 | // Accessing hash keys 156 | Key key() const; 157 | Key key_after(Move m) const; 158 | Key exclusion_key() const; 159 | Key material_key() const; 160 | Key pawn_key() const; 161 | 162 | // Other properties of the position 163 | Color side_to_move() const; 164 | Phase game_phase() const; 165 | int game_ply() const; 166 | bool is_chess960() const; 167 | Thread* this_thread() const; 168 | uint64_t nodes_searched() const; 169 | void set_nodes_searched(uint64_t n); 170 | bool is_draw() const; 171 | int rule50_count() const; 172 | Score psq_score() const; 173 | Value non_pawn_material(Color c) const; 174 | 175 | // Position consistency check, for debugging 176 | bool pos_is_ok(int* failedStep = nullptr) const; 177 | void flip(); 178 | 179 | private: 180 | // Initialization helpers (used while setting up a position) 181 | void clear(); 182 | void set_castling_right(Color c, Square rfrom); 183 | void set_state(StateInfo* si) const; 184 | 185 | // Other helpers 186 | Bitboard check_blockers(Color c, Color kingColor) const; 187 | void put_piece(Color c, PieceType pt, Square s); 188 | void remove_piece(Color c, PieceType pt, Square s); 189 | void move_piece(Color c, PieceType pt, Square from, Square to); 190 | template 191 | void do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto); 192 | 193 | // Data members 194 | Piece board[SQUARE_NB]; 195 | Bitboard byTypeBB[PIECE_TYPE_NB]; 196 | Bitboard byColorBB[COLOR_NB]; 197 | int pieceCount[COLOR_NB][PIECE_TYPE_NB]; 198 | Square pieceList[COLOR_NB][PIECE_TYPE_NB][16]; 199 | int index[SQUARE_NB]; 200 | int castlingRightsMask[SQUARE_NB]; 201 | Square castlingRookSquare[CASTLING_RIGHT_NB]; 202 | Bitboard castlingPath[CASTLING_RIGHT_NB]; 203 | StateInfo startState; 204 | uint64_t nodes; 205 | int gamePly; 206 | Color sideToMove; 207 | Thread* thisThread; 208 | StateInfo* st; 209 | bool chess960; 210 | }; 211 | 212 | extern std::ostream& operator<<(std::ostream& os, const Position& pos); 213 | 214 | inline Color Position::side_to_move() const { 215 | return sideToMove; 216 | } 217 | 218 | inline bool Position::empty(Square s) const { 219 | return board[s] == NO_PIECE; 220 | } 221 | 222 | inline Piece Position::piece_on(Square s) const { 223 | return board[s]; 224 | } 225 | 226 | inline Piece Position::moved_piece(Move m) const { 227 | return board[from_sq(m)]; 228 | } 229 | 230 | inline Bitboard Position::pieces() const { 231 | return byTypeBB[ALL_PIECES]; 232 | } 233 | 234 | inline Bitboard Position::pieces(PieceType pt) const { 235 | return byTypeBB[pt]; 236 | } 237 | 238 | inline Bitboard Position::pieces(PieceType pt1, PieceType pt2) const { 239 | return byTypeBB[pt1] | byTypeBB[pt2]; 240 | } 241 | 242 | inline Bitboard Position::pieces(Color c) const { 243 | return byColorBB[c]; 244 | } 245 | 246 | inline Bitboard Position::pieces(Color c, PieceType pt) const { 247 | return byColorBB[c] & byTypeBB[pt]; 248 | } 249 | 250 | inline Bitboard Position::pieces(Color c, PieceType pt1, PieceType pt2) const { 251 | return byColorBB[c] & (byTypeBB[pt1] | byTypeBB[pt2]); 252 | } 253 | 254 | template inline int Position::count(Color c) const { 255 | return pieceCount[c][Pt]; 256 | } 257 | 258 | template inline const Square* Position::squares(Color c) const { 259 | return pieceList[c][Pt]; 260 | } 261 | 262 | template inline Square Position::square(Color c) const { 263 | assert(pieceCount[c][Pt] == 1); 264 | return pieceList[c][Pt][0]; 265 | } 266 | 267 | inline Square Position::ep_square() const { 268 | return st->epSquare; 269 | } 270 | 271 | inline int Position::can_castle(CastlingRight cr) const { 272 | return st->castlingRights & cr; 273 | } 274 | 275 | inline int Position::can_castle(Color c) const { 276 | return st->castlingRights & ((WHITE_OO | WHITE_OOO) << (2 * c)); 277 | } 278 | 279 | inline bool Position::castling_impeded(CastlingRight cr) const { 280 | return byTypeBB[ALL_PIECES] & castlingPath[cr]; 281 | } 282 | 283 | inline Square Position::castling_rook_square(CastlingRight cr) const { 284 | return castlingRookSquare[cr]; 285 | } 286 | 287 | template 288 | inline Bitboard Position::attacks_from(Square s) const { 289 | return Pt == BISHOP || Pt == ROOK ? attacks_bb(s, byTypeBB[ALL_PIECES]) 290 | : Pt == QUEEN ? attacks_from(s) | attacks_from(s) 291 | : StepAttacksBB[Pt][s]; 292 | } 293 | 294 | template<> 295 | inline Bitboard Position::attacks_from(Square s, Color c) const { 296 | return StepAttacksBB[make_piece(c, PAWN)][s]; 297 | } 298 | 299 | inline Bitboard Position::attacks_from(Piece pc, Square s) const { 300 | return attacks_bb(pc, s, byTypeBB[ALL_PIECES]); 301 | } 302 | 303 | inline Bitboard Position::attackers_to(Square s) const { 304 | return attackers_to(s, byTypeBB[ALL_PIECES]); 305 | } 306 | 307 | inline Bitboard Position::checkers() const { 308 | return st->checkersBB; 309 | } 310 | 311 | inline Bitboard Position::discovered_check_candidates() const { 312 | return check_blockers(sideToMove, ~sideToMove); 313 | } 314 | 315 | inline Bitboard Position::pinned_pieces(Color c) const { 316 | return check_blockers(c, c); 317 | } 318 | 319 | inline bool Position::pawn_passed(Color c, Square s) const { 320 | return !(pieces(~c, PAWN) & passed_pawn_mask(c, s)); 321 | } 322 | 323 | inline bool Position::advanced_pawn_push(Move m) const { 324 | return type_of(moved_piece(m)) == PAWN 325 | && relative_rank(sideToMove, from_sq(m)) > RANK_4; 326 | } 327 | 328 | inline Key Position::key() const { 329 | return st->key; 330 | } 331 | 332 | inline Key Position::pawn_key() const { 333 | return st->pawnKey; 334 | } 335 | 336 | inline Key Position::material_key() const { 337 | return st->materialKey; 338 | } 339 | 340 | inline Score Position::psq_score() const { 341 | return st->psq; 342 | } 343 | 344 | inline Value Position::non_pawn_material(Color c) const { 345 | return st->nonPawnMaterial[c]; 346 | } 347 | 348 | inline int Position::game_ply() const { 349 | return gamePly; 350 | } 351 | 352 | inline int Position::rule50_count() const { 353 | return st->rule50; 354 | } 355 | 356 | inline uint64_t Position::nodes_searched() const { 357 | return nodes; 358 | } 359 | 360 | inline void Position::set_nodes_searched(uint64_t n) { 361 | nodes = n; 362 | } 363 | 364 | inline bool Position::opposite_bishops() const { 365 | return pieceCount[WHITE][BISHOP] == 1 366 | && pieceCount[BLACK][BISHOP] == 1 367 | && opposite_colors(square(WHITE), square(BLACK)); 368 | } 369 | 370 | inline bool Position::is_chess960() const { 371 | return chess960; 372 | } 373 | 374 | inline bool Position::capture_or_promotion(Move m) const { 375 | 376 | assert(is_ok(m)); 377 | return type_of(m) != NORMAL ? type_of(m) != CASTLING : !empty(to_sq(m)); 378 | } 379 | 380 | inline bool Position::capture(Move m) const { 381 | 382 | // Castling is encoded as "king captures the rook" 383 | assert(is_ok(m)); 384 | return (!empty(to_sq(m)) && type_of(m) != CASTLING) || type_of(m) == ENPASSANT; 385 | } 386 | 387 | inline PieceType Position::captured_piece_type() const { 388 | return st->capturedType; 389 | } 390 | 391 | inline Thread* Position::this_thread() const { 392 | return thisThread; 393 | } 394 | 395 | inline void Position::put_piece(Color c, PieceType pt, Square s) { 396 | 397 | board[s] = make_piece(c, pt); 398 | byTypeBB[ALL_PIECES] |= s; 399 | byTypeBB[pt] |= s; 400 | byColorBB[c] |= s; 401 | index[s] = pieceCount[c][pt]++; 402 | pieceList[c][pt][index[s]] = s; 403 | pieceCount[c][ALL_PIECES]++; 404 | } 405 | 406 | inline void Position::remove_piece(Color c, PieceType pt, Square s) { 407 | 408 | // WARNING: This is not a reversible operation. If we remove a piece in 409 | // do_move() and then replace it in undo_move() we will put it at the end of 410 | // the list and not in its original place, it means index[] and pieceList[] 411 | // are not guaranteed to be invariant to a do_move() + undo_move() sequence. 412 | byTypeBB[ALL_PIECES] ^= s; 413 | byTypeBB[pt] ^= s; 414 | byColorBB[c] ^= s; 415 | /* board[s] = NO_PIECE; Not needed, overwritten by the capturing one */ 416 | Square lastSquare = pieceList[c][pt][--pieceCount[c][pt]]; 417 | index[lastSquare] = index[s]; 418 | pieceList[c][pt][index[lastSquare]] = lastSquare; 419 | pieceList[c][pt][pieceCount[c][pt]] = SQ_NONE; 420 | pieceCount[c][ALL_PIECES]--; 421 | } 422 | 423 | inline void Position::move_piece(Color c, PieceType pt, Square from, Square to) { 424 | 425 | // index[from] is not updated and becomes stale. This works as long as index[] 426 | // is accessed just by known occupied squares. 427 | Bitboard from_to_bb = SquareBB[from] ^ SquareBB[to]; 428 | byTypeBB[ALL_PIECES] ^= from_to_bb; 429 | byTypeBB[pt] ^= from_to_bb; 430 | byColorBB[c] ^= from_to_bb; 431 | board[from] = NO_PIECE; 432 | board[to] = make_piece(c, pt); 433 | index[to] = index[from]; 434 | pieceList[c][pt][index[to]] = to; 435 | } 436 | 437 | #endif // #ifndef POSITION_H_INCLUDED 438 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # Stockfish, a UCI chess playing engine derived from Glaurung 2.1 2 | # Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 3 | # Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 4 | # Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 5 | # 6 | # Stockfish is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Stockfish is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | ### ========================================================================== 21 | ### Section 1. General Configuration 22 | ### ========================================================================== 23 | 24 | ### Establish the operating system name 25 | UNAME = $(shell uname) 26 | 27 | ### Executable name 28 | EXE = stockfish 29 | 30 | ### Installation dir definitions 31 | PREFIX = /usr/local 32 | BINDIR = $(PREFIX)/bin 33 | 34 | ### Built-in benchmark for pgo-builds 35 | PGOBENCH = ./$(EXE) bench 16 1 1000 default time 36 | 37 | ### Object files 38 | OBJS = benchmark.o bitbase.o bitboard.o endgame.o evaluate.o main.o \ 39 | material.o misc.o movegen.o movepick.o pawns.o position.o psqt.o \ 40 | search.o thread.o timeman.o tt.o uci.o ucioption.o syzygy/tbprobe.o 41 | 42 | ### ========================================================================== 43 | ### Section 2. High-level Configuration 44 | ### ========================================================================== 45 | # 46 | # flag --- Comp switch --- Description 47 | # ---------------------------------------------------------------------------- 48 | # 49 | # debug = yes/no --- -DNDEBUG --- Enable/Disable debug mode 50 | # optimize = yes/no --- (-O3/-fast etc.) --- Enable/Disable optimizations 51 | # arch = (name) --- (-arch) --- Target architecture 52 | # bits = 64/32 --- -DIS_64BIT --- 64-/32-bit operating system 53 | # prefetch = yes/no --- -DUSE_PREFETCH --- Use prefetch asm-instruction 54 | # popcnt = yes/no --- -DUSE_POPCNT --- Use popcnt asm-instruction 55 | # sse = yes/no --- -msse --- Use Intel Streaming SIMD Extensions 56 | # pext = yes/no --- -DUSE_PEXT --- Use pext x86_64 asm-instruction 57 | # 58 | # Note that Makefile is space sensitive, so when adding new architectures 59 | # or modifying existing flags, you have to make sure there are no extra spaces 60 | # at the end of the line for flag values. 61 | 62 | ### 2.1. General and architecture defaults 63 | optimize = yes 64 | debug = no 65 | bits = 32 66 | prefetch = no 67 | popcnt = no 68 | sse = no 69 | pext = no 70 | 71 | ### 2.2 Architecture specific 72 | 73 | ifeq ($(ARCH),general-32) 74 | arch = any 75 | endif 76 | 77 | ifeq ($(ARCH),x86-32-old) 78 | arch = i386 79 | endif 80 | 81 | ifeq ($(ARCH),x86-32) 82 | arch = i386 83 | prefetch = yes 84 | sse = yes 85 | endif 86 | 87 | ifeq ($(ARCH),general-64) 88 | arch = any 89 | bits = 64 90 | endif 91 | 92 | ifeq ($(ARCH),x86-64) 93 | arch = x86_64 94 | bits = 64 95 | prefetch = yes 96 | sse = yes 97 | endif 98 | 99 | ifeq ($(ARCH),x86-64-modern) 100 | arch = x86_64 101 | bits = 64 102 | prefetch = yes 103 | popcnt = yes 104 | sse = yes 105 | endif 106 | 107 | ifeq ($(ARCH),x86-64-bmi2) 108 | arch = x86_64 109 | bits = 64 110 | prefetch = yes 111 | popcnt = yes 112 | sse = yes 113 | pext = yes 114 | endif 115 | 116 | ifeq ($(ARCH),armv7) 117 | arch = armv7 118 | prefetch = yes 119 | endif 120 | 121 | ifeq ($(ARCH),ppc-32) 122 | arch = ppc 123 | endif 124 | 125 | ifeq ($(ARCH),ppc-64) 126 | arch = ppc64 127 | bits = 64 128 | endif 129 | 130 | 131 | ### ========================================================================== 132 | ### Section 3. Low-level configuration 133 | ### ========================================================================== 134 | 135 | ### 3.1 Selecting compiler (default = gcc) 136 | 137 | CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -fno-rtti -std=c++11 $(EXTRACXXFLAGS) 138 | DEPENDFLAGS += -std=c++11 139 | LDFLAGS += $(EXTRALDFLAGS) 140 | 141 | ifeq ($(COMP),) 142 | COMP=gcc 143 | endif 144 | 145 | ifeq ($(COMP),gcc) 146 | comp=gcc 147 | CXX=g++ 148 | CXXFLAGS += -pedantic -Wextra -Wshadow -m$(bits) 149 | ifneq ($(UNAME),Darwin) 150 | LDFLAGS += -Wl,--no-as-needed 151 | endif 152 | endif 153 | 154 | ifeq ($(COMP),mingw) 155 | comp=mingw 156 | 157 | ifeq ($(UNAME),Linux) 158 | ifeq ($(bits),64) 159 | ifeq ($(shell which x86_64-w64-mingw32-c++-posix),) 160 | CXX=x86_64-w64-mingw32-c++ 161 | else 162 | CXX=x86_64-w64-mingw32-c++-posix 163 | endif 164 | else 165 | ifeq ($(shell which i686-w64-mingw32-c++-posix),) 166 | CXX=i686-w64-mingw32-c++ 167 | else 168 | CXX=i686-w64-mingw32-c++-posix 169 | endif 170 | endif 171 | else 172 | CXX=g++ 173 | endif 174 | 175 | CXXFLAGS += -Wextra -Wshadow 176 | LDFLAGS += -static 177 | endif 178 | 179 | ifeq ($(COMP),icc) 180 | comp=icc 181 | CXX=icpc 182 | CXXFLAGS += -diag-disable 1476,10120 -Wcheck -Wabi -Wdeprecated -strict-ansi 183 | endif 184 | 185 | ifeq ($(COMP),clang) 186 | comp=clang 187 | CXX=clang++ 188 | CXXFLAGS += -pedantic -Wextra -Wshadow -m$(bits) 189 | LDFLAGS += -m$(bits) 190 | ifeq ($(UNAME),Darwin) 191 | CXXFLAGS += -stdlib=libc++ 192 | DEPENDFLAGS += -stdlib=libc++ 193 | endif 194 | endif 195 | 196 | ifeq ($(comp),icc) 197 | profile_prepare = icc-profile-prepare 198 | profile_make = icc-profile-make 199 | profile_use = icc-profile-use 200 | profile_clean = icc-profile-clean 201 | else 202 | profile_prepare = gcc-profile-prepare 203 | profile_make = gcc-profile-make 204 | profile_use = gcc-profile-use 205 | profile_clean = gcc-profile-clean 206 | endif 207 | 208 | ifeq ($(UNAME),Darwin) 209 | CXXFLAGS += -arch $(arch) -mmacosx-version-min=10.9 210 | LDFLAGS += -arch $(arch) -mmacosx-version-min=10.9 211 | endif 212 | 213 | ### Travis CI script uses COMPILER to overwrite CXX 214 | ifdef COMPILER 215 | COMPCXX=$(COMPILER) 216 | endif 217 | 218 | ### Allow overwriting CXX from command line 219 | ifdef COMPCXX 220 | CXX=$(COMPCXX) 221 | endif 222 | 223 | ### On mingw use Windows threads, otherwise POSIX 224 | ifneq ($(comp),mingw) 225 | # On Android Bionic's C library comes with its own pthread implementation bundled in 226 | ifneq ($(arch),armv7) 227 | # Haiku has pthreads in its libroot, so only link it in on other platforms 228 | ifneq ($(UNAME),Haiku) 229 | LDFLAGS += -lpthread 230 | endif 231 | endif 232 | endif 233 | 234 | ### 3.4 Debugging 235 | ifeq ($(debug),no) 236 | CXXFLAGS += -DNDEBUG 237 | else 238 | CXXFLAGS += -g 239 | endif 240 | 241 | ### 3.5 Optimization 242 | ifeq ($(optimize),yes) 243 | 244 | ifeq ($(comp),gcc) 245 | CXXFLAGS += -O3 246 | 247 | ifeq ($(UNAME),Darwin) 248 | ifeq ($(arch),i386) 249 | CXXFLAGS += -mdynamic-no-pic 250 | endif 251 | ifeq ($(arch),x86_64) 252 | CXXFLAGS += -mdynamic-no-pic 253 | endif 254 | endif 255 | 256 | ifeq ($(arch),armv7) 257 | CXXFLAGS += -fno-gcse -mthumb -march=armv7-a -mfloat-abi=softfp 258 | endif 259 | endif 260 | 261 | ifeq ($(comp),mingw) 262 | CXXFLAGS += -O3 263 | endif 264 | 265 | ifeq ($(comp),icc) 266 | ifeq ($(UNAME),Darwin) 267 | CXXFLAGS += -fast -mdynamic-no-pic 268 | else 269 | CXXFLAGS += -fast 270 | endif 271 | endif 272 | 273 | ifeq ($(comp),clang) 274 | CXXFLAGS += -O3 275 | 276 | ifeq ($(UNAME),Darwin) 277 | ifeq ($(pext),no) 278 | CXXFLAGS += -flto 279 | LDFLAGS += $(CXXFLAGS) 280 | endif 281 | ifeq ($(arch),i386) 282 | CXXFLAGS += -mdynamic-no-pic 283 | endif 284 | ifeq ($(arch),x86_64) 285 | CXXFLAGS += -mdynamic-no-pic 286 | endif 287 | endif 288 | endif 289 | endif 290 | 291 | ### 3.6. Bits 292 | ifeq ($(bits),64) 293 | CXXFLAGS += -DIS_64BIT 294 | endif 295 | 296 | ### 3.7 prefetch 297 | ifeq ($(prefetch),yes) 298 | ifeq ($(sse),yes) 299 | CXXFLAGS += -msse 300 | DEPENDFLAGS += -msse 301 | endif 302 | else 303 | CXXFLAGS += -DNO_PREFETCH 304 | endif 305 | 306 | ### 3.9 popcnt 307 | ifeq ($(popcnt),yes) 308 | ifeq ($(comp),icc) 309 | CXXFLAGS += -msse3 -DUSE_POPCNT 310 | else 311 | CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT 312 | endif 313 | endif 314 | 315 | ### 3.10 pext 316 | ifeq ($(pext),yes) 317 | CXXFLAGS += -DUSE_PEXT 318 | ifeq ($(comp),$(filter $(comp),gcc clang mingw)) 319 | CXXFLAGS += -mbmi -mbmi2 320 | endif 321 | endif 322 | 323 | ### 3.11 Link Time Optimization, it works since gcc 4.5 but not on mingw under Windows. 324 | ### This is a mix of compile and link time options because the lto link phase 325 | ### needs access to the optimization flags. 326 | ifeq ($(comp),gcc) 327 | ifeq ($(optimize),yes) 328 | ifeq ($(debug),no) 329 | CXXFLAGS += -flto 330 | LDFLAGS += $(CXXFLAGS) 331 | endif 332 | endif 333 | endif 334 | 335 | ifeq ($(comp),mingw) 336 | ifeq ($(UNAME),Linux) 337 | ifeq ($(optimize),yes) 338 | ifeq ($(debug),no) 339 | CXXFLAGS += -flto 340 | LDFLAGS += $(CXXFLAGS) 341 | endif 342 | endif 343 | endif 344 | endif 345 | 346 | ### 3.12 Android 5 can only run position independent executables. Note that this 347 | ### breaks Android 4.0 and earlier. 348 | ifeq ($(arch),armv7) 349 | CXXFLAGS += -fPIE 350 | LDFLAGS += -fPIE -pie 351 | endif 352 | 353 | 354 | ### ========================================================================== 355 | ### Section 4. Public targets 356 | ### ========================================================================== 357 | 358 | help: 359 | @echo "" 360 | @echo "To compile stockfish, type: " 361 | @echo "" 362 | @echo "make target ARCH=arch [COMP=compiler] [COMPCXX=cxx]" 363 | @echo "" 364 | @echo "Supported targets:" 365 | @echo "" 366 | @echo "build > Standard build" 367 | @echo "profile-build > PGO build" 368 | @echo "strip > Strip executable" 369 | @echo "install > Install executable" 370 | @echo "clean > Clean up" 371 | @echo "" 372 | @echo "Supported archs:" 373 | @echo "" 374 | @echo "x86-64 > x86 64-bit" 375 | @echo "x86-64-modern > x86 64-bit with popcnt support" 376 | @echo "x86-64-bmi2 > x86 64-bit with pext support" 377 | @echo "x86-32 > x86 32-bit with SSE support" 378 | @echo "x86-32-old > x86 32-bit fall back for old hardware" 379 | @echo "ppc-64 > PPC 64-bit" 380 | @echo "ppc-32 > PPC 32-bit" 381 | @echo "armv7 > ARMv7 32-bit" 382 | @echo "general-64 > unspecified 64-bit" 383 | @echo "general-32 > unspecified 32-bit" 384 | @echo "" 385 | @echo "Supported compilers:" 386 | @echo "" 387 | @echo "gcc > Gnu compiler (default)" 388 | @echo "mingw > Gnu compiler with MinGW under Windows" 389 | @echo "clang > LLVM Clang compiler" 390 | @echo "icc > Intel compiler" 391 | @echo "" 392 | @echo "Simple examples. If you don't know what to do, you likely want to run: " 393 | @echo "" 394 | @echo "make build ARCH=x86-64 (This is for 64-bit systems)" 395 | @echo "make build ARCH=x86-32 (This is for 32-bit systems)" 396 | @echo "" 397 | @echo "Advanced examples, for experienced users: " 398 | @echo "" 399 | @echo "make build ARCH=x86-64 COMP=clang" 400 | @echo "make profile-build ARCH=x86-64-modern COMP=gcc COMPCXX=g++-4.8" 401 | @echo "" 402 | 403 | 404 | .PHONY: build profile-build 405 | build: 406 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity 407 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) all 408 | 409 | profile-build: 410 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity 411 | @echo "" 412 | @echo "Step 0/4. Preparing for profile build." 413 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_prepare) 414 | @echo "" 415 | @echo "Step 1/4. Building executable for benchmark ..." 416 | @touch *.cpp *.h syzygy/*.cpp syzygy/*.h 417 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_make) 418 | @echo "" 419 | @echo "Step 2/4. Running benchmark for pgo-build ..." 420 | $(PGOBENCH) > /dev/null 421 | @echo "" 422 | @echo "Step 3/4. Building final executable ..." 423 | @touch *.cpp *.h syzygy/*.cpp syzygy/*.h 424 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_use) 425 | @echo "" 426 | @echo "Step 4/4. Deleting profile data ..." 427 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) $(profile_clean) 428 | 429 | strip: 430 | strip $(EXE) 431 | 432 | install: 433 | -mkdir -p -m 755 $(BINDIR) 434 | -cp $(EXE) $(BINDIR) 435 | -strip $(BINDIR)/$(EXE) 436 | 437 | clean: 438 | $(RM) $(EXE) $(EXE).exe *.o .depend *~ core bench.txt *.gcda ./syzygy/*.o ./syzygy/*.gcda 439 | 440 | default: 441 | help 442 | 443 | ### ========================================================================== 444 | ### Section 5. Private targets 445 | ### ========================================================================== 446 | 447 | all: $(EXE) .depend 448 | 449 | config-sanity: 450 | @echo "" 451 | @echo "Config:" 452 | @echo "debug: '$(debug)'" 453 | @echo "optimize: '$(optimize)'" 454 | @echo "arch: '$(arch)'" 455 | @echo "bits: '$(bits)'" 456 | @echo "prefetch: '$(prefetch)'" 457 | @echo "popcnt: '$(popcnt)'" 458 | @echo "sse: '$(sse)'" 459 | @echo "pext: '$(pext)'" 460 | @echo "" 461 | @echo "Flags:" 462 | @echo "CXX: $(CXX)" 463 | @echo "CXXFLAGS: $(CXXFLAGS)" 464 | @echo "LDFLAGS: $(LDFLAGS)" 465 | @echo "" 466 | @echo "Testing config sanity. If this fails, try 'make help' ..." 467 | @echo "" 468 | @test "$(debug)" = "yes" || test "$(debug)" = "no" 469 | @test "$(optimize)" = "yes" || test "$(optimize)" = "no" 470 | @test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \ 471 | test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "armv7" 472 | @test "$(bits)" = "32" || test "$(bits)" = "64" 473 | @test "$(prefetch)" = "yes" || test "$(prefetch)" = "no" 474 | @test "$(popcnt)" = "yes" || test "$(popcnt)" = "no" 475 | @test "$(sse)" = "yes" || test "$(sse)" = "no" 476 | @test "$(pext)" = "yes" || test "$(pext)" = "no" 477 | @test "$(comp)" = "gcc" || test "$(comp)" = "icc" || test "$(comp)" = "mingw" || test "$(comp)" = "clang" 478 | 479 | $(EXE): $(OBJS) 480 | $(CXX) -o $@ $(OBJS) $(LDFLAGS) 481 | 482 | gcc-profile-prepare: 483 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) gcc-profile-clean 484 | 485 | gcc-profile-make: 486 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ 487 | EXTRACXXFLAGS='-fprofile-generate' \ 488 | EXTRALDFLAGS='-lgcov' \ 489 | all 490 | 491 | gcc-profile-use: 492 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ 493 | EXTRACXXFLAGS='-fprofile-use -fno-peel-loops -fno-tracer' \ 494 | EXTRALDFLAGS='-lgcov' \ 495 | all 496 | 497 | gcc-profile-clean: 498 | @rm -rf *.gcda *.gcno syzygy/*.gcda syzygy/*.gcno bench.txt 499 | 500 | icc-profile-prepare: 501 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) icc-profile-clean 502 | @mkdir profdir 503 | 504 | icc-profile-make: 505 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ 506 | EXTRACXXFLAGS='-prof-gen=srcpos -prof_dir ./profdir' \ 507 | all 508 | 509 | icc-profile-use: 510 | $(MAKE) ARCH=$(ARCH) COMP=$(COMP) \ 511 | EXTRACXXFLAGS='-prof_use -prof_dir ./profdir' \ 512 | all 513 | 514 | icc-profile-clean: 515 | @rm -rf profdir bench.txt 516 | 517 | .depend: 518 | -@$(CXX) $(DEPENDFLAGS) -MM $(OBJS:.o=.cpp) > $@ 2> /dev/null 519 | 520 | -include .depend 521 | 522 | -------------------------------------------------------------------------------- /src/movegen.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (C) 2004-2008 Tord Romstad (Glaurung author) 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad 5 | Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad 6 | 7 | Stockfish is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Stockfish is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include "movegen.h" 24 | #include "position.h" 25 | 26 | namespace { 27 | 28 | template 29 | ExtMove* generate_castling(const Position& pos, ExtMove* moveList, Color us, const CheckInfo* ci) { 30 | 31 | static const bool KingSide = (Cr == WHITE_OO || Cr == BLACK_OO); 32 | 33 | if (pos.castling_impeded(Cr) || !pos.can_castle(Cr)) 34 | return moveList; 35 | 36 | // After castling, the rook and king final positions are the same in Chess960 37 | // as they would be in standard chess. 38 | Square kfrom = pos.square(us); 39 | Square rfrom = pos.castling_rook_square(Cr); 40 | Square kto = relative_square(us, KingSide ? SQ_G1 : SQ_C1); 41 | Bitboard enemies = pos.pieces(~us); 42 | 43 | assert(!pos.checkers()); 44 | 45 | const Square K = Chess960 ? kto > kfrom ? DELTA_W : DELTA_E 46 | : KingSide ? DELTA_W : DELTA_E; 47 | 48 | for (Square s = kto; s != kfrom; s += K) 49 | if (pos.attackers_to(s) & enemies) 50 | return moveList; 51 | 52 | // Because we generate only legal castling moves we need to verify that 53 | // when moving the castling rook we do not discover some hidden checker. 54 | // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. 55 | if (Chess960 && (attacks_bb(kto, pos.pieces() ^ rfrom) & pos.pieces(~us, ROOK, QUEEN))) 56 | return moveList; 57 | 58 | Move m = make(kfrom, rfrom); 59 | 60 | if (Checks && !pos.gives_check(m, *ci)) 61 | return moveList; 62 | else 63 | (void)ci; // Silence a warning under MSVC 64 | 65 | *moveList++ = m; 66 | return moveList; 67 | } 68 | 69 | 70 | template 71 | ExtMove* make_promotions(ExtMove* moveList, Square to, const CheckInfo* ci) { 72 | 73 | if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) 74 | *moveList++ = make(to - Delta, to, QUEEN); 75 | 76 | if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS) 77 | { 78 | *moveList++ = make(to - Delta, to, ROOK); 79 | *moveList++ = make(to - Delta, to, BISHOP); 80 | *moveList++ = make(to - Delta, to, KNIGHT); 81 | } 82 | 83 | // Knight promotion is the only promotion that can give a direct check 84 | // that's not already included in the queen promotion. 85 | if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ci->ksq)) 86 | *moveList++ = make(to - Delta, to, KNIGHT); 87 | else 88 | (void)ci; // Silence a warning under MSVC 89 | 90 | return moveList; 91 | } 92 | 93 | 94 | template 95 | ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, 96 | Bitboard target, const CheckInfo* ci) { 97 | 98 | // Compute our parametrized parameters at compile time, named according to 99 | // the point of view of white side. 100 | const Color Them = (Us == WHITE ? BLACK : WHITE); 101 | const Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB); 102 | const Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB); 103 | const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); 104 | const Square Up = (Us == WHITE ? DELTA_N : DELTA_S); 105 | const Square Right = (Us == WHITE ? DELTA_NE : DELTA_SW); 106 | const Square Left = (Us == WHITE ? DELTA_NW : DELTA_SE); 107 | 108 | Bitboard emptySquares; 109 | 110 | Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB; 111 | Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB; 112 | 113 | Bitboard enemies = (Type == EVASIONS ? pos.pieces(Them) & target: 114 | Type == CAPTURES ? target : pos.pieces(Them)); 115 | 116 | // Single and double pawn pushes, no promotions 117 | if (Type != CAPTURES) 118 | { 119 | emptySquares = (Type == QUIETS || Type == QUIET_CHECKS ? target : ~pos.pieces()); 120 | 121 | Bitboard b1 = shift_bb(pawnsNotOn7) & emptySquares; 122 | Bitboard b2 = shift_bb(b1 & TRank3BB) & emptySquares; 123 | 124 | if (Type == EVASIONS) // Consider only blocking squares 125 | { 126 | b1 &= target; 127 | b2 &= target; 128 | } 129 | 130 | if (Type == QUIET_CHECKS) 131 | { 132 | b1 &= pos.attacks_from(ci->ksq, Them); 133 | b2 &= pos.attacks_from(ci->ksq, Them); 134 | 135 | // Add pawn pushes which give discovered check. This is possible only 136 | // if the pawn is not on the same file as the enemy king, because we 137 | // don't generate captures. Note that a possible discovery check 138 | // promotion has been already generated amongst the captures. 139 | if (pawnsNotOn7 & ci->dcCandidates) 140 | { 141 | Bitboard dc1 = shift_bb(pawnsNotOn7 & ci->dcCandidates) & emptySquares & ~file_bb(ci->ksq); 142 | Bitboard dc2 = shift_bb(dc1 & TRank3BB) & emptySquares; 143 | 144 | b1 |= dc1; 145 | b2 |= dc2; 146 | } 147 | } 148 | 149 | while (b1) 150 | { 151 | Square to = pop_lsb(&b1); 152 | *moveList++ = make_move(to - Up, to); 153 | } 154 | 155 | while (b2) 156 | { 157 | Square to = pop_lsb(&b2); 158 | *moveList++ = make_move(to - Up - Up, to); 159 | } 160 | } 161 | 162 | // Promotions and underpromotions 163 | if (pawnsOn7 && (Type != EVASIONS || (target & TRank8BB))) 164 | { 165 | if (Type == CAPTURES) 166 | emptySquares = ~pos.pieces(); 167 | 168 | if (Type == EVASIONS) 169 | emptySquares &= target; 170 | 171 | Bitboard b1 = shift_bb(pawnsOn7) & enemies; 172 | Bitboard b2 = shift_bb(pawnsOn7) & enemies; 173 | Bitboard b3 = shift_bb(pawnsOn7) & emptySquares; 174 | 175 | while (b1) 176 | moveList = make_promotions(moveList, pop_lsb(&b1), ci); 177 | 178 | while (b2) 179 | moveList = make_promotions(moveList, pop_lsb(&b2), ci); 180 | 181 | while (b3) 182 | moveList = make_promotions(moveList, pop_lsb(&b3), ci); 183 | } 184 | 185 | // Standard and en-passant captures 186 | if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) 187 | { 188 | Bitboard b1 = shift_bb(pawnsNotOn7) & enemies; 189 | Bitboard b2 = shift_bb(pawnsNotOn7) & enemies; 190 | 191 | while (b1) 192 | { 193 | Square to = pop_lsb(&b1); 194 | *moveList++ = make_move(to - Right, to); 195 | } 196 | 197 | while (b2) 198 | { 199 | Square to = pop_lsb(&b2); 200 | *moveList++ = make_move(to - Left, to); 201 | } 202 | 203 | if (pos.ep_square() != SQ_NONE) 204 | { 205 | assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6)); 206 | 207 | // An en passant capture can be an evasion only if the checking piece 208 | // is the double pushed pawn and so is in the target. Otherwise this 209 | // is a discovery check and we are forced to do otherwise. 210 | if (Type == EVASIONS && !(target & (pos.ep_square() - Up))) 211 | return moveList; 212 | 213 | b1 = pawnsNotOn7 & pos.attacks_from(pos.ep_square(), Them); 214 | 215 | assert(b1); 216 | 217 | while (b1) 218 | *moveList++ = make(pop_lsb(&b1), pos.ep_square()); 219 | } 220 | } 221 | 222 | return moveList; 223 | } 224 | 225 | 226 | template 227 | ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Color us, 228 | Bitboard target, const CheckInfo* ci) { 229 | 230 | assert(Pt != KING && Pt != PAWN); 231 | 232 | const Square* pl = pos.squares(us); 233 | 234 | for (Square from = *pl; from != SQ_NONE; from = *++pl) 235 | { 236 | if (Checks) 237 | { 238 | if ( (Pt == BISHOP || Pt == ROOK || Pt == QUEEN) 239 | && !(PseudoAttacks[Pt][from] & target & ci->checkSquares[Pt])) 240 | continue; 241 | 242 | if (ci->dcCandidates && (ci->dcCandidates & from)) 243 | continue; 244 | } 245 | 246 | Bitboard b = pos.attacks_from(from) & target; 247 | 248 | if (Checks) 249 | b &= ci->checkSquares[Pt]; 250 | 251 | while (b) 252 | *moveList++ = make_move(from, pop_lsb(&b)); 253 | } 254 | 255 | return moveList; 256 | } 257 | 258 | 259 | template 260 | ExtMove* generate_all(const Position& pos, ExtMove* moveList, Bitboard target, 261 | const CheckInfo* ci = nullptr) { 262 | 263 | const bool Checks = Type == QUIET_CHECKS; 264 | 265 | moveList = generate_pawn_moves(pos, moveList, target, ci); 266 | moveList = generate_moves(pos, moveList, Us, target, ci); 267 | moveList = generate_moves(pos, moveList, Us, target, ci); 268 | moveList = generate_moves< ROOK, Checks>(pos, moveList, Us, target, ci); 269 | moveList = generate_moves< QUEEN, Checks>(pos, moveList, Us, target, ci); 270 | 271 | if (Type != QUIET_CHECKS && Type != EVASIONS) 272 | { 273 | Square ksq = pos.square(Us); 274 | Bitboard b = pos.attacks_from(ksq) & target; 275 | while (b) 276 | *moveList++ = make_move(ksq, pop_lsb(&b)); 277 | } 278 | 279 | if (Type != CAPTURES && Type != EVASIONS && pos.can_castle(Us)) 280 | { 281 | if (pos.is_chess960()) 282 | { 283 | moveList = generate_castling::right, Checks, true>(pos, moveList, Us, ci); 284 | moveList = generate_castling::right, Checks, true>(pos, moveList, Us, ci); 285 | } 286 | else 287 | { 288 | moveList = generate_castling::right, Checks, false>(pos, moveList, Us, ci); 289 | moveList = generate_castling::right, Checks, false>(pos, moveList, Us, ci); 290 | } 291 | } 292 | 293 | return moveList; 294 | } 295 | 296 | } // namespace 297 | 298 | 299 | /// generate generates all pseudo-legal captures and queen 300 | /// promotions. Returns a pointer to the end of the move list. 301 | /// 302 | /// generate generates all pseudo-legal non-captures and 303 | /// underpromotions. Returns a pointer to the end of the move list. 304 | /// 305 | /// generate generates all pseudo-legal captures and 306 | /// non-captures. Returns a pointer to the end of the move list. 307 | 308 | template 309 | ExtMove* generate(const Position& pos, ExtMove* moveList) { 310 | 311 | assert(Type == CAPTURES || Type == QUIETS || Type == NON_EVASIONS); 312 | assert(!pos.checkers()); 313 | 314 | Color us = pos.side_to_move(); 315 | 316 | Bitboard target = Type == CAPTURES ? pos.pieces(~us) 317 | : Type == QUIETS ? ~pos.pieces() 318 | : Type == NON_EVASIONS ? ~pos.pieces(us) : 0; 319 | 320 | return us == WHITE ? generate_all(pos, moveList, target) 321 | : generate_all(pos, moveList, target); 322 | } 323 | 324 | // Explicit template instantiations 325 | template ExtMove* generate(const Position&, ExtMove*); 326 | template ExtMove* generate(const Position&, ExtMove*); 327 | template ExtMove* generate(const Position&, ExtMove*); 328 | 329 | 330 | /// generate generates all pseudo-legal non-captures and knight 331 | /// underpromotions that give check. Returns a pointer to the end of the move list. 332 | template<> 333 | ExtMove* generate(const Position& pos, ExtMove* moveList) { 334 | 335 | assert(!pos.checkers()); 336 | 337 | Color us = pos.side_to_move(); 338 | CheckInfo ci(pos); 339 | Bitboard dc = ci.dcCandidates; 340 | 341 | while (dc) 342 | { 343 | Square from = pop_lsb(&dc); 344 | PieceType pt = type_of(pos.piece_on(from)); 345 | 346 | if (pt == PAWN) 347 | continue; // Will be generated together with direct checks 348 | 349 | Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces(); 350 | 351 | if (pt == KING) 352 | b &= ~PseudoAttacks[QUEEN][ci.ksq]; 353 | 354 | while (b) 355 | *moveList++ = make_move(from, pop_lsb(&b)); 356 | } 357 | 358 | return us == WHITE ? generate_all(pos, moveList, ~pos.pieces(), &ci) 359 | : generate_all(pos, moveList, ~pos.pieces(), &ci); 360 | } 361 | 362 | 363 | /// generate generates all pseudo-legal check evasions when the side 364 | /// to move is in check. Returns a pointer to the end of the move list. 365 | template<> 366 | ExtMove* generate(const Position& pos, ExtMove* moveList) { 367 | 368 | assert(pos.checkers()); 369 | 370 | Color us = pos.side_to_move(); 371 | Square ksq = pos.square(us); 372 | Bitboard sliderAttacks = 0; 373 | Bitboard sliders = pos.checkers() & ~pos.pieces(KNIGHT, PAWN); 374 | 375 | // Find all the squares attacked by slider checkers. We will remove them from 376 | // the king evasions in order to skip known illegal moves, which avoids any 377 | // useless legality checks later on. 378 | while (sliders) 379 | { 380 | Square checksq = pop_lsb(&sliders); 381 | sliderAttacks |= LineBB[checksq][ksq] ^ checksq; 382 | } 383 | 384 | // Generate evasions for king, capture and non capture moves 385 | Bitboard b = pos.attacks_from(ksq) & ~pos.pieces(us) & ~sliderAttacks; 386 | while (b) 387 | *moveList++ = make_move(ksq, pop_lsb(&b)); 388 | 389 | if (more_than_one(pos.checkers())) 390 | return moveList; // Double check, only a king move can save the day 391 | 392 | // Generate blocking evasions or captures of the checking piece 393 | Square checksq = lsb(pos.checkers()); 394 | Bitboard target = between_bb(checksq, ksq) | checksq; 395 | 396 | return us == WHITE ? generate_all(pos, moveList, target) 397 | : generate_all(pos, moveList, target); 398 | } 399 | 400 | 401 | /// generate generates all the legal moves in the given position 402 | 403 | template<> 404 | ExtMove* generate(const Position& pos, ExtMove* moveList) { 405 | 406 | Bitboard pinned = pos.pinned_pieces(pos.side_to_move()); 407 | Square ksq = pos.square(pos.side_to_move()); 408 | ExtMove* cur = moveList; 409 | 410 | moveList = pos.checkers() ? generate(pos, moveList) 411 | : generate(pos, moveList); 412 | while (cur != moveList) 413 | if ( (pinned || from_sq(*cur) == ksq || type_of(*cur) == ENPASSANT) 414 | && !pos.legal(*cur, pinned)) 415 | *cur = (--moveList)->move; 416 | else 417 | ++cur; 418 | 419 | return moveList; 420 | } 421 | --------------------------------------------------------------------------------