├── Images ├── Open-cv.png ├── Python3.jpg ├── input-frame.png ├── locate-boxes.png └── warpperspective.png ├── Method_working ├── Images │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── Result_image.jpg │ ├── show_Contours.jpg │ ├── Difference_image.jpg │ ├── Threshold_image.jpg │ └── Difference_GrayScale_image.jpg └── temp.py ├── numpy_saved ├── 1 │ ├── map_position.npz │ ├── fen_line_board.npz │ ├── chess_board_Box.npz │ ├── chess_board_points.npz │ ├── chess_b_color_points.npz │ ├── chess_w_color_points.npz │ └── chess_board_warp_prespective.npz ├── 2 │ └── map_position.npz └── map_position.npz ├── __pycache__ ├── design.cpython-37.pyc ├── black_player.cpython-37.pyc ├── detect_points.cpython-37.pyc ├── read_warp_img.cpython-37.pyc ├── color_calibration.cpython-37.pyc └── find_position_black.cpython-37.pyc ├── stockfish-10-win ├── Windows │ ├── stockfish_10_x32.exe │ ├── stockfish_10_x64.exe │ ├── stockfish_10_x64_bmi2.exe │ └── stockfish_10_x64_popcnt.exe ├── tests │ ├── signature.sh │ ├── perft.sh │ ├── reprosearch.sh │ └── instrumented.sh ├── src │ ├── evaluate.h │ ├── main.cpp │ ├── timeman.h │ ├── movegen.h │ ├── uci.h │ ├── thread_win32.h │ ├── syzygy │ │ └── tbprobe.h │ ├── pawns.h │ ├── material.h │ ├── tt.h │ ├── search.h │ ├── misc.h │ ├── thread.h │ ├── endgame.h │ ├── psqt.cpp │ ├── timeman.cpp │ ├── tt.cpp │ ├── benchmark.cpp │ ├── movepick.h │ ├── ucioption.cpp │ ├── thread.cpp │ ├── bitbase.cpp │ ├── material.cpp │ ├── movepick.cpp │ ├── misc.cpp │ ├── bitboard.cpp │ ├── pawns.cpp │ ├── uci.cpp │ └── bitboard.h ├── appveyor.yml ├── .travis.yml ├── AUTHORS ├── Readme.md └── Top CPU Contributors.txt ├── read_warp_img.py ├── detect_points.py ├── find_position_black.py └── README.md /Images/Open-cv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Images/Open-cv.png -------------------------------------------------------------------------------- /Images/Python3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Images/Python3.jpg -------------------------------------------------------------------------------- /Images/input-frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Images/input-frame.png -------------------------------------------------------------------------------- /Images/locate-boxes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Images/locate-boxes.png -------------------------------------------------------------------------------- /Images/warpperspective.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Images/warpperspective.png -------------------------------------------------------------------------------- /Method_working/Images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Method_working/Images/1.jpg -------------------------------------------------------------------------------- /Method_working/Images/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Method_working/Images/2.jpg -------------------------------------------------------------------------------- /Method_working/Images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Method_working/Images/3.jpg -------------------------------------------------------------------------------- /numpy_saved/1/map_position.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/numpy_saved/1/map_position.npz -------------------------------------------------------------------------------- /numpy_saved/2/map_position.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/numpy_saved/2/map_position.npz -------------------------------------------------------------------------------- /numpy_saved/map_position.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/numpy_saved/map_position.npz -------------------------------------------------------------------------------- /numpy_saved/1/fen_line_board.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/numpy_saved/1/fen_line_board.npz -------------------------------------------------------------------------------- /__pycache__/design.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/__pycache__/design.cpython-37.pyc -------------------------------------------------------------------------------- /numpy_saved/1/chess_board_Box.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/numpy_saved/1/chess_board_Box.npz -------------------------------------------------------------------------------- /numpy_saved/1/chess_board_points.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/numpy_saved/1/chess_board_points.npz -------------------------------------------------------------------------------- /Method_working/Images/Result_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Method_working/Images/Result_image.jpg -------------------------------------------------------------------------------- /Method_working/Images/show_Contours.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Method_working/Images/show_Contours.jpg -------------------------------------------------------------------------------- /__pycache__/black_player.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/__pycache__/black_player.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/detect_points.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/__pycache__/detect_points.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/read_warp_img.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/__pycache__/read_warp_img.cpython-37.pyc -------------------------------------------------------------------------------- /numpy_saved/1/chess_b_color_points.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/numpy_saved/1/chess_b_color_points.npz -------------------------------------------------------------------------------- /numpy_saved/1/chess_w_color_points.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/numpy_saved/1/chess_w_color_points.npz -------------------------------------------------------------------------------- /Method_working/Images/Difference_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Method_working/Images/Difference_image.jpg -------------------------------------------------------------------------------- /Method_working/Images/Threshold_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Method_working/Images/Threshold_image.jpg -------------------------------------------------------------------------------- /__pycache__/color_calibration.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/__pycache__/color_calibration.cpython-37.pyc -------------------------------------------------------------------------------- /stockfish-10-win/Windows/stockfish_10_x32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/stockfish-10-win/Windows/stockfish_10_x32.exe -------------------------------------------------------------------------------- /stockfish-10-win/Windows/stockfish_10_x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/stockfish-10-win/Windows/stockfish_10_x64.exe -------------------------------------------------------------------------------- /__pycache__/find_position_black.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/__pycache__/find_position_black.cpython-37.pyc -------------------------------------------------------------------------------- /numpy_saved/1/chess_board_warp_prespective.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/numpy_saved/1/chess_board_warp_prespective.npz -------------------------------------------------------------------------------- /stockfish-10-win/Windows/stockfish_10_x64_bmi2.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/stockfish-10-win/Windows/stockfish_10_x64_bmi2.exe -------------------------------------------------------------------------------- /Method_working/Images/Difference_GrayScale_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/Method_working/Images/Difference_GrayScale_image.jpg -------------------------------------------------------------------------------- /stockfish-10-win/Windows/stockfish_10_x64_popcnt.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/HEAD/stockfish-10-win/Windows/stockfish_10_x64_popcnt.exe -------------------------------------------------------------------------------- /read_warp_img.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | def get_warp_img(img,dir_path,img_resize): 5 | pts1 = np.load(dir_path+'/chess_board_warp_prespective.npz')['pts1'] 6 | pts2 = np.load(dir_path+'/chess_board_warp_prespective.npz')['pts2'] 7 | H,maks = cv2.findHomography(pts1,pts2) 8 | result = cv2.warpPerspective(img,H,img_resize) 9 | return result -------------------------------------------------------------------------------- /stockfish-10-win/tests/signature.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # obtain and optionally verify Bench / signature 3 | # if no reference is given, the output is deliberately limited to just the signature 4 | 5 | error() 6 | { 7 | echo "running bench for signature failed on line $1" 8 | exit 1 9 | } 10 | trap 'error ${LINENO}' ERR 11 | 12 | # obtain 13 | 14 | signature=`./stockfish bench 2>&1 | grep "Nodes searched : " | awk '{print $4}'` 15 | 16 | if [ $# -gt 0 ]; then 17 | # compare to given reference 18 | if [ "$1" != "$signature" ]; then 19 | if [ -z "$signature" ]; then 20 | echo "No signature obtained from bench. Code crashed or assert triggered ?" 21 | else 22 | echo "signature mismatch: reference $1 obtained: $signature ." 23 | fi 24 | exit 1 25 | else 26 | echo "signature OK: $signature" 27 | fi 28 | else 29 | # just report signature 30 | echo $signature 31 | fi 32 | -------------------------------------------------------------------------------- /detect_points.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import os 4 | ix,iy = -1,-1 5 | img = 0 6 | 7 | ################################################################################### 8 | ## Code For Detect corner points 9 | ################################################################################### 10 | 11 | def draw_circle(event,x,y,flags,param): 12 | global ix,iy 13 | if event == cv2.EVENT_LBUTTONDBLCLK: 14 | cv2.circle(img,(x,y),2,(255,0,0),-1) 15 | ix,iy = x,y 16 | 17 | def get_points(image,numOfPoints): 18 | global img 19 | img = image.copy() 20 | img = cv2.resize(img,(800,800)) 21 | width, height = image.shape[:2] 22 | cv2.namedWindow("image") 23 | cv2.setMouseCallback("image",draw_circle) 24 | points = [] 25 | print("Press a for add point : ") 26 | while len(points) != numOfPoints: 27 | cv2.imshow("image",img) 28 | k = cv2.waitKey(1) 29 | if k == ord('a'): 30 | points.append([int(ix),int(iy)]) 31 | cv2.circle(img,(ix,iy),3,(0,0,255),-1) 32 | cv2.destroyAllWindows() 33 | return list(points) 34 | -------------------------------------------------------------------------------- /stockfish-10-win/tests/perft.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # verify perft numbers (positions from https://chessprogramming.wikispaces.com/Perft+Results) 3 | 4 | error() 5 | { 6 | echo "perft testing failed on line $1" 7 | exit 1 8 | } 9 | trap 'error ${LINENO}' ERR 10 | 11 | echo "perft testing started" 12 | 13 | cat << EOF > perft.exp 14 | set timeout 10 15 | lassign \$argv pos depth result 16 | spawn ./stockfish 17 | send "position \$pos\\ngo perft \$depth\\n" 18 | expect "Nodes searched? \$result" {} timeout {exit 1} 19 | send "quit\\n" 20 | expect eof 21 | EOF 22 | 23 | expect perft.exp startpos 5 4865609 > /dev/null 24 | expect perft.exp "fen r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq -" 5 193690690 > /dev/null 25 | expect perft.exp "fen 8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - -" 6 11030083 > /dev/null 26 | expect perft.exp "fen r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 1" 5 15833292 > /dev/null 27 | expect perft.exp "fen rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 8" 5 89941194 > /dev/null 28 | expect perft.exp "fen r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1 w - - 0 10" 5 164075551 > /dev/null 29 | 30 | rm perft.exp 31 | 32 | echo "perft testing OK" 33 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | constexpr Value Tempo = Value(20); // Must be visible to search 33 | 34 | std::string trace(const Position& pos); 35 | 36 | Value evaluate(const Position& pos); 37 | } 38 | 39 | #endif // #ifndef EVALUATE_H_INCLUDED 40 | -------------------------------------------------------------------------------- /stockfish-10-win/tests/reprosearch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # verify reproducible search 3 | 4 | error() 5 | { 6 | echo "reprosearch testing failed on line $1" 7 | exit 1 8 | } 9 | trap 'error ${LINENO}' ERR 10 | 11 | echo "reprosearch testing started" 12 | 13 | # repeat two short games, separated by ucinewgame. 14 | # with go nodes $nodes they should result in exactly 15 | # the same node count for each iteration. 16 | cat << EOF > repeat.exp 17 | set timeout 10 18 | spawn ./stockfish 19 | lassign \$argv nodes 20 | 21 | send "uci\n" 22 | expect "uciok" 23 | 24 | send "ucinewgame\n" 25 | send "position startpos\n" 26 | send "go nodes \$nodes\n" 27 | expect "bestmove" 28 | 29 | send "position startpos moves e2e4 e7e6\n" 30 | send "go nodes \$nodes\n" 31 | expect "bestmove" 32 | 33 | send "ucinewgame\n" 34 | send "position startpos\n" 35 | send "go nodes \$nodes\n" 36 | expect "bestmove" 37 | 38 | send "position startpos moves e2e4 e7e6\n" 39 | send "go nodes \$nodes\n" 40 | expect "bestmove" 41 | 42 | send "quit\n" 43 | expect eof 44 | EOF 45 | 46 | # to increase the likelyhood of finding a non-reproducible case, 47 | # the allowed number of nodes are varied systematically 48 | for i in `seq 1 20` 49 | do 50 | 51 | nodes=$((100*3**i/2**i)) 52 | echo "reprosearch testing with $nodes nodes" 53 | 54 | # each line should appear exactly an even number of times 55 | expect repeat.exp $nodes 2>&1 | grep -o "nodes [0-9]*" | sort | uniq -c | awk '{if ($1%2!=0) exit(1)}' 56 | 57 | done 58 | 59 | rm repeat.exp 60 | 61 | echo "reprosearch testing OK" 62 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 "position.h" 25 | #include "search.h" 26 | #include "thread.h" 27 | #include "tt.h" 28 | #include "uci.h" 29 | #include "syzygy/tbprobe.h" 30 | 31 | namespace PSQT { 32 | void init(); 33 | } 34 | 35 | int main(int argc, char* argv[]) { 36 | 37 | std::cout << engine_info() << std::endl; 38 | 39 | UCI::init(Options); 40 | PSQT::init(); 41 | Bitboards::init(); 42 | Position::init(); 43 | Bitbases::init(); 44 | Search::init(); 45 | Pawns::init(); 46 | Threads.set(Options["Threads"]); 47 | Search::clear(); // After threads are up 48 | 49 | UCI::loop(argc, argv); 50 | 51 | Threads.set(0); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | TimePoint optimum() const { return optimumTime; } 35 | TimePoint maximum() const { return maximumTime; } 36 | TimePoint elapsed() const { return Search::Limits.npmsec ? 37 | TimePoint(Threads.nodes_searched()) : now() - startTime; } 38 | 39 | int64_t availableNodes; // When in 'nodes as time' mode 40 | 41 | private: 42 | TimePoint startTime; 43 | TimePoint optimumTime; 44 | TimePoint maximumTime; 45 | }; 46 | 47 | extern TimeManagement Time; 48 | 49 | #endif // #ifndef TIMEMAN_H_INCLUDED 50 | -------------------------------------------------------------------------------- /Method_working/temp.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | from matplotlib import pyplot as plt 3 | 4 | def nothing(X): 5 | pass 6 | 7 | def thresold_calibreation(img): 8 | cv2.namedWindow("thresold_calibration") 9 | cv2.createTrackbar("thresold", "thresold_calibration", 0, 255, nothing) 10 | while True: 11 | t = cv2.getTrackbarPos("thresold", "thresold_calibration") 12 | matrix,thresold = cv2.threshold(img,t,255,cv2.THRESH_BINARY) 13 | cv2.imshow("thresold",thresold) 14 | 15 | if cv2.waitKey(1) & 0xFF == ord('q'): 16 | return t 17 | 18 | image1 = cv2.imread('Method_working\Images/2.jpg') 19 | image2 = cv2.imread('Method_working\Images/3.jpg') 20 | 21 | image1_gray = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) 22 | image2_gray = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) 23 | 24 | diff = cv2.absdiff(image1,image2) 25 | 26 | cv2.imshow("diff", diff) 27 | cv2.waitKey(0) 28 | 29 | diff = cv2.resize(diff,(800,800)) 30 | cv2.imshow("diff",diff) 31 | cv2.imwrite("Method_working/Images/Difference_image.jpg",diff) 32 | 33 | diff_gray = cv2.cvtColor(diff,cv2.COLOR_BGR2GRAY) 34 | cv2.imshow("diff_gray", diff_gray) 35 | cv2.imwrite("Method_working/Images/Difference_GrayScale_image.jpg",diff_gray) 36 | cv2.waitKey(0) 37 | 38 | value = thresold_calibreation(diff_gray) 39 | 40 | matrix,thresold = cv2.threshold(diff_gray,value,255,cv2.THRESH_BINARY) 41 | cv2.imshow("thresold",thresold) 42 | 43 | cnts,_ = cv2.findContours(thresold, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 44 | print(len(cnts)) 45 | 46 | for c in cnts: 47 | area = cv2.contourArea(c) 48 | if area> 500: 49 | (x, y, w, h) = cv2.boundingRect(c) 50 | cv2.rectangle(diff, (x, y), (x + w, y + h), (0, 0, 255), 2) 51 | 52 | cv2.imshow("diff", diff) 53 | cv2.imwrite("Method_working/Images/show_Contours.jpg",diff) 54 | cv2.waitKey(0) 55 | 56 | 57 | result1 = cv2.bitwise_and(image1,image1,mask = thresold) 58 | cv2.imshow("result",result1) 59 | cv2.imwrite("Method_working/Images/Result_image.jpg",result1) 60 | 61 | cv2.waitKey(0) 62 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /stockfish-10-win/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | clone_depth: 50 3 | 4 | branches: 5 | only: 6 | - master 7 | - appveyor 8 | 9 | # Operating system (build VM template) 10 | os: Visual Studio 2015 11 | 12 | # Build platform, i.e. x86, x64, AnyCPU. This setting is optional. 13 | platform: 14 | - x86 15 | - x64 16 | 17 | # build Configuration, i.e. Debug, Release, etc. 18 | configuration: 19 | - Debug 20 | - Release 21 | 22 | matrix: 23 | # The build fail immediately once one of the job fails 24 | fast_finish: true 25 | 26 | # Scripts that are called at very beginning, before repo cloning 27 | init: 28 | - cmake --version 29 | - msbuild /version 30 | 31 | before_build: 32 | - ps: | 33 | # Get sources 34 | $src = get-childitem -Path *.cpp -Recurse | select -ExpandProperty FullName 35 | $src = $src -join ' ' 36 | $src = $src.Replace("\", "/") 37 | 38 | # Build CMakeLists.txt 39 | $t = 'cmake_minimum_required(VERSION 3.8)', 40 | 'project(Stockfish)', 41 | 'set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src)', 42 | 'set(source_files', $src, ')', 43 | 'add_executable(stockfish ${source_files})' 44 | 45 | # Write CMakeLists.txt withouth BOM 46 | $MyPath = (Get-Item -Path "." -Verbose).FullName + '\CMakeLists.txt' 47 | $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False 48 | [System.IO.File]::WriteAllLines($MyPath, $t, $Utf8NoBomEncoding) 49 | 50 | # Obtain bench reference from git log 51 | $b = git log HEAD | sls "\b[Bb]ench[ :]+[0-9]{7}" | select -first 1 52 | $bench = $b -match '\D+(\d+)' | % { $matches[1] } 53 | Write-Host "Reference bench:" $bench 54 | $g = "Visual Studio 14 2015" 55 | If (${env:PLATFORM} -eq 'x64') { $g = $g + ' Win64' } 56 | cmake -G "${g}" . 57 | Write-Host "Generated files for: " $g 58 | 59 | build_script: 60 | - cmake --build . --config %CONFIGURATION% -- /verbosity:minimal 61 | 62 | before_test: 63 | - cd src/%CONFIGURATION% 64 | - stockfish bench 2> out.txt >NUL 65 | - ps: | 66 | # Verify bench number 67 | $s = (gc "./out.txt" | out-string) 68 | $r = ($s -match 'Nodes searched \D+(\d+)' | % { $matches[1] }) 69 | Write-Host "Engine bench:" $r 70 | Write-Host "Reference bench:" $bench 71 | If ($r -ne $bench) { exit 1 } 72 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 25 | 26 | #include "types.h" 27 | 28 | class Position; 29 | 30 | enum GenType { 31 | CAPTURES, 32 | QUIETS, 33 | QUIET_CHECKS, 34 | EVASIONS, 35 | NON_EVASIONS, 36 | LEGAL 37 | }; 38 | 39 | struct ExtMove { 40 | Move move; 41 | int value; 42 | 43 | operator Move() const { return move; } 44 | void operator=(Move m) { move = m; } 45 | 46 | // Inhibit unwanted implicit conversions to Move 47 | // with an ambiguity that yields to a compile error. 48 | operator float() const = delete; 49 | }; 50 | 51 | inline bool operator<(const ExtMove& f, const ExtMove& s) { 52 | return f.value < s.value; 53 | } 54 | 55 | template 56 | ExtMove* generate(const Position& pos, ExtMove* moveList); 57 | 58 | /// The MoveList struct is a simple wrapper around generate(). It sometimes comes 59 | /// in handy to use this class instead of the low level generate() function. 60 | template 61 | struct MoveList { 62 | 63 | explicit MoveList(const Position& pos) : last(generate(pos, moveList)) {} 64 | const ExtMove* begin() const { return moveList; } 65 | const ExtMove* end() const { return last; } 66 | size_t size() const { return last - moveList; } 67 | bool contains(Move move) const { 68 | return std::find(begin(), end(), move) != end(); 69 | } 70 | 71 | private: 72 | ExtMove moveList[MAX_MOVES], *last; 73 | }; 74 | 75 | #endif // #ifndef MOVEGEN_H_INCLUDED 76 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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(double v, int minv, int maxv, OnChange = nullptr); 53 | Option(const char* v, const char* cur, OnChange = nullptr); 54 | 55 | Option& operator=(const std::string&); 56 | void operator<<(const Option&); 57 | operator double() const; 58 | operator std::string() const; 59 | bool operator==(const char*) const; 60 | 61 | private: 62 | friend std::ostream& operator<<(std::ostream&, const OptionsMap&); 63 | 64 | std::string defaultValue, currentValue, type; 65 | int min, max; 66 | size_t idx; 67 | OnChange on_change; 68 | }; 69 | 70 | void init(OptionsMap&); 71 | void loop(int argc, char* argv[]); 72 | std::string value(Value v); 73 | std::string square(Square s); 74 | std::string move(Move m, bool chess960); 75 | std::string pv(const Position& pos, Depth depth, Value alpha, Value beta); 76 | Move to_move(const Position& pos, std::string& str); 77 | 78 | } // namespace UCI 79 | 80 | extern UCI::OptionsMap Options; 81 | 82 | #endif // #ifndef UCI_H_INCLUDED 83 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | -------------------------------------------------------------------------------- /stockfish-10-win/src/syzygy/tbprobe.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stockfish, a UCI chess playing engine derived from Glaurung 2.1 3 | Copyright (c) 2013 Ronald de Man 4 | Copyright (C) 2016-2018 Marco Costalba, Lucas Braesch 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 | #ifndef TBPROBE_H 21 | #define TBPROBE_H 22 | 23 | #include 24 | 25 | #include "../search.h" 26 | 27 | namespace Tablebases { 28 | 29 | enum WDLScore { 30 | WDLLoss = -2, // Loss 31 | WDLBlessedLoss = -1, // Loss, but draw under 50-move rule 32 | WDLDraw = 0, // Draw 33 | WDLCursedWin = 1, // Win, but draw under 50-move rule 34 | WDLWin = 2, // Win 35 | 36 | WDLScoreNone = -1000 37 | }; 38 | 39 | // Possible states after a probing operation 40 | enum ProbeState { 41 | FAIL = 0, // Probe failed (missing file table) 42 | OK = 1, // Probe succesful 43 | CHANGE_STM = -1, // DTZ should check the other side 44 | ZEROING_BEST_MOVE = 2 // Best move zeroes DTZ (capture or pawn move) 45 | }; 46 | 47 | extern int MaxCardinality; 48 | 49 | void init(const std::string& paths); 50 | WDLScore probe_wdl(Position& pos, ProbeState* result); 51 | int probe_dtz(Position& pos, ProbeState* result); 52 | bool root_probe(Position& pos, Search::RootMoves& rootMoves); 53 | bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves); 54 | void rank_root_moves(Position& pos, Search::RootMoves& rootMoves); 55 | 56 | inline std::ostream& operator<<(std::ostream& os, const WDLScore v) { 57 | 58 | os << (v == WDLLoss ? "Loss" : 59 | v == WDLBlessedLoss ? "Blessed loss" : 60 | v == WDLDraw ? "Draw" : 61 | v == WDLCursedWin ? "Cursed win" : 62 | v == WDLWin ? "Win" : "None"); 63 | 64 | return os; 65 | } 66 | 67 | inline std::ostream& operator<<(std::ostream& os, const ProbeState v) { 68 | 69 | os << (v == FAIL ? "Failed" : 70 | v == OK ? "Success" : 71 | v == CHANGE_STM ? "Probed opponent side" : 72 | v == ZEROING_BEST_MOVE ? "Best move zeroes DTZ" : "None"); 73 | 74 | return os; 75 | } 76 | 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /stockfish-10-win/.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++-7', 'g++-7-multilib', 'g++-multilib', 'valgrind', 'expect', 'curl'] 13 | env: 14 | - COMPILER=g++-7 15 | - COMP=gcc 16 | 17 | - os: linux 18 | compiler: clang 19 | addons: 20 | apt: 21 | sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0'] 22 | packages: ['clang-5.0', 'llvm-5.0-dev', 'g++-multilib', 'valgrind', 'expect', 'curl'] 23 | env: 24 | - COMPILER=clang++-5.0 25 | - COMP=clang 26 | - LDFLAGS=-fuse-ld=gold 27 | 28 | - os: osx 29 | compiler: gcc 30 | env: 31 | - COMPILER=g++ 32 | - COMP=gcc 33 | 34 | - os: osx 35 | compiler: clang 36 | env: 37 | - COMPILER=clang++ V='Apple LLVM 6.0' # Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) 38 | - COMP=clang 39 | 40 | branches: 41 | only: 42 | - master 43 | 44 | before_script: 45 | - cd src 46 | 47 | script: 48 | # Obtain bench reference from git log 49 | - git log HEAD | grep "\b[Bb]ench[ :]\+[0-9]\{7\}" | head -n 1 | sed "s/[^0-9]*\([0-9]*\).*/\1/g" > git_sig 50 | - export benchref=$(cat git_sig) 51 | - echo "Reference bench:" $benchref 52 | # 53 | # Verify bench number against various builds 54 | - export CXXFLAGS=-Werror 55 | - make clean && make -j2 ARCH=x86-64 optimize=no debug=yes build && ../tests/signature.sh $benchref 56 | - make clean && make -j2 ARCH=x86-32 optimize=no debug=yes build && ../tests/signature.sh $benchref 57 | - make clean && make -j2 ARCH=x86-32 build && ../tests/signature.sh $benchref 58 | - make clean && make -j2 ARCH=x86-64 build && ../tests/signature.sh $benchref 59 | # 60 | # Check perft and reproducible search 61 | - ../tests/perft.sh 62 | - ../tests/reprosearch.sh 63 | # 64 | # Valgrind 65 | # 66 | - export CXXFLAGS=-O1 67 | - if [ -x "$(command -v valgrind )" ]; then make clean && make -j2 ARCH=x86-64 debug=yes optimize=no build > /dev/null && ../tests/instrumented.sh --valgrind; fi 68 | - if [ -x "$(command -v valgrind )" ]; then ../tests/instrumented.sh --valgrind-thread; fi 69 | # 70 | # Sanitizer 71 | # 72 | # Use g++-7 as a proxy for having sanitizers, might need revision as they become available for more recent versions of clang/gcc 73 | - if [[ "$COMPILER" == "g++-7" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=undefined optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-undefined; fi 74 | - if [[ "$COMPILER" == "g++-7" ]]; then make clean && make -j2 ARCH=x86-64 sanitize=thread optimize=no debug=yes build > /dev/null && ../tests/instrumented.sh --sanitizer-thread; fi 75 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 pawn_score(Color c) const { return scores[c]; } 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 weak_unopposed(Color c) const { return weakUnopposed[c]; } 41 | int pawn_asymmetry() const { return asymmetry; } 42 | int open_files() const { return openFiles; } 43 | 44 | int semiopen_file(Color c, File f) const { 45 | return semiopenFiles[c] & (1 << f); 46 | } 47 | 48 | int pawns_on_same_color_squares(Color c, Square s) const { 49 | return pawnsOnSquares[c][bool(DarkSquares & s)]; 50 | } 51 | 52 | template 53 | Score king_safety(const Position& pos) { 54 | return kingSquares[Us] == pos.square(Us) && castlingRights[Us] == pos.can_castle(Us) 55 | ? kingSafety[Us] : (kingSafety[Us] = do_king_safety(pos)); 56 | } 57 | 58 | template 59 | Score do_king_safety(const Position& pos); 60 | 61 | template 62 | Value evaluate_shelter(const Position& pos, Square ksq); 63 | 64 | Key key; 65 | Score scores[COLOR_NB]; 66 | Bitboard passedPawns[COLOR_NB]; 67 | Bitboard pawnAttacks[COLOR_NB]; 68 | Bitboard pawnAttacksSpan[COLOR_NB]; 69 | Square kingSquares[COLOR_NB]; 70 | Score kingSafety[COLOR_NB]; 71 | int weakUnopposed[COLOR_NB]; 72 | int castlingRights[COLOR_NB]; 73 | int semiopenFiles[COLOR_NB]; 74 | int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares] 75 | int asymmetry; 76 | int openFiles; 77 | }; 78 | 79 | typedef HashTable Table; 80 | 81 | void init(); 82 | Entry* probe(const Position& pos); 83 | 84 | } // namespace Pawns 85 | 86 | #endif // #ifndef PAWNS_H_INCLUDED 87 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | ScaleFactor sf = scalingFunction[c] ? (*scalingFunction[c])(pos) 54 | : SCALE_FACTOR_NONE; 55 | return sf != SCALE_FACTOR_NONE ? sf : ScaleFactor(factor[c]); 56 | } 57 | 58 | Key key; 59 | const EndgameBase* evaluationFunction; 60 | const EndgameBase* scalingFunction[COLOR_NB]; // Could be one for each 61 | // side (e.g. KPKP, KBPsKs) 62 | int16_t value; 63 | uint8_t factor[COLOR_NB]; 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 | -------------------------------------------------------------------------------- /stockfish-10-win/AUTHORS: -------------------------------------------------------------------------------- 1 | # List of authors for Stockfish, updated for version 10 2 | 3 | Tord Romstad (romstad) 4 | Marco Costalba (mcostalba) 5 | Joona Kiiski (zamar) 6 | Gary Linscott (glinscott) 7 | 8 | Aditya (absimaldata) 9 | Ajith Chandy Jose (ajithcj) 10 | Alain Savard (Rocky640) 11 | Alexander Kure 12 | Ali AlZhrani (Cooffe) 13 | Andrew Grant (AndyGrant) 14 | Andrey Neporada (nepal) 15 | Andy Duplain 16 | Aram Tumanian (atumanian) 17 | Arjun Temurnikar 18 | Auguste Pop 19 | Balint Pfliegel 20 | Ben Koshy (BKSpurgeon) 21 | Bill Henry (VoyagerOne) 22 | braich 23 | Brian Sheppard (SapphireBrand) 24 | Bryan Cross (crossbr) 25 | Bujun Guo (noobpwnftw) 26 | Chris Cain (ceebo) 27 | Dan Schmidt 28 | Daniel Dugovic (ddugovic) 29 | Dariusz Orzechowski 30 | David Zar 31 | Daylen Yang (daylen) 32 | DiscanX 33 | Eelco de Groot 34 | ElbertoOne 35 | erbsenzaehler 36 | Ernesto Gatti 37 | Fabian Beuke (madnight) 38 | Fabian Fichter (ianfab) 39 | fanon 40 | Fauzi Akram Dabat (FauziAkram) 41 | Felix Wittmann 42 | gamander 43 | gguliash 44 | Gian-Carlo Pascutto (gcp) 45 | Gontran Lemaire (gonlem) 46 | Goodkov Vasiliy Aleksandrovich (goodkov) 47 | Gregor Cramer 48 | GuardianRM 49 | Günther Demetz (pb00067, pb00068) 50 | Guy Vreuls (gvreuls) 51 | Henri Wiechers 52 | Hiraoka Takuya (HiraokaTakuya) 53 | homoSapiensSapiens 54 | Hongzhi Cheng 55 | Ivan Ivec (IIvec) 56 | Jacques B. (Timshel) 57 | Jan Ondruš (hxim) 58 | Jared Kish (Kurtbusch) 59 | Jarrod Torriero (DU-jdto) 60 | Jean-Francois Romang (jromang) 61 | Jerry Donald Watson (jerrydonaldwatson) 62 | Jonathan Calovski (Mysseno) 63 | Jonathan D. (SFisGOD) 64 | Joost VandeVondele (vondele) 65 | Jörg Oster (joergoster) 66 | Joseph Ellis (jhellis3) 67 | Joseph R. Prostko 68 | jundery 69 | Justin Blanchard 70 | Kelly Wilson 71 | Ken Takusagawa 72 | kinderchocolate 73 | Kiran Panditrao (Krgp) 74 | Kojirion 75 | Leonardo Ljubičić (ICCF World Champion) 76 | Leonid Pechenik (lp--) 77 | Linus Arver 78 | loco-loco 79 | Luca Brivio (lucabrivio) 80 | Lucas Braesch (lucasart) 81 | Lyudmil Antonov (lantonov) 82 | Matthew Lai (matthewlai) 83 | Matthew Sullivan 84 | Mark Tenzer (31m059) 85 | Michael Byrne (MichaelB7) 86 | Michael Stembera (mstembera) 87 | Michael Chaly (Vizvezdenec) 88 | Michel Van den Bergh (vdbergh) 89 | Miguel Lahoz (miguel-l) 90 | Mikael Bäckman (mbootsector) 91 | Mike Whiteley (protonspring) 92 | Miroslav Fontán (Hexik) 93 | Moez Jellouli (MJZ1977) 94 | Mohammed Li (tthsqe12) 95 | Nathan Rugg (nmrugg) 96 | Nicklas Persson (NicklasPersson) 97 | Niklas Fiekas (niklasf) 98 | Ondrej Mosnáček (WOnder93) 99 | Oskar Werkelin Ahlin 100 | Pablo Vazquez 101 | Pascal Romaret 102 | Pasquale Pigazzini (ppigazzini) 103 | Patrick Jansen (mibere) 104 | pellanda 105 | Peter Zsifkovits (CoffeeOne) 106 | Ralph Stößer (Ralph Stoesser) 107 | Raminder Singh 108 | renouve 109 | Reuven Peleg 110 | Richard Lloyd 111 | Rodrigo Exterckötter Tjäder 112 | Ron Britvich (Britvich) 113 | Ronald de Man (syzygy1) 114 | Ryan Schmitt 115 | Ryan Takker 116 | Sebastian Buchwald (UniQP) 117 | Sergei Antonov (saproj) 118 | sf-x 119 | shane31 120 | Steinar Gunderson (sesse) 121 | Stefan Geschwentner (locutus2) 122 | Stefano Cardanobile (Stefano80) 123 | Stéphane Nicolet (snicolet) 124 | Thanar2 125 | thaspel 126 | Tom Vijlbrief (tomtor) 127 | Torsten Franz (torfranz) 128 | Uri Blass (uriblass) 129 | Vince Negri 130 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 * int(ONE_PLY)); } 43 | Bound bound() const { return (Bound)(genBound8 & 0x3); } 44 | void save(Key k, Value v, Bound b, Depth d, Move m, Value ev); 45 | 46 | private: 47 | friend class TranspositionTable; 48 | 49 | uint16_t key16; 50 | uint16_t move16; 51 | int16_t value16; 52 | int16_t eval16; 53 | uint8_t genBound8; 54 | int8_t depth8; 55 | }; 56 | 57 | 58 | /// A TranspositionTable consists of a power of 2 number of clusters and each 59 | /// cluster consists of ClusterSize number of TTEntry. Each non-empty entry 60 | /// contains information of exactly one position. The size of a cluster should 61 | /// divide the size of a cache line size, to ensure that clusters never cross 62 | /// cache lines. This ensures best cache performance, as the cacheline is 63 | /// prefetched, as soon as possible. 64 | 65 | class TranspositionTable { 66 | 67 | static constexpr int CacheLineSize = 64; 68 | static constexpr int ClusterSize = 3; 69 | 70 | struct Cluster { 71 | TTEntry entry[ClusterSize]; 72 | char padding[2]; // Align to a divisor of the cache line size 73 | }; 74 | 75 | static_assert(CacheLineSize % sizeof(Cluster) == 0, "Cluster size incorrect"); 76 | 77 | public: 78 | ~TranspositionTable() { free(mem); } 79 | void new_search() { generation8 += 4; } // Lower 2 bits are used by Bound 80 | TTEntry* probe(const Key key, bool& found) const; 81 | int hashfull() const; 82 | void resize(size_t mbSize); 83 | void clear(); 84 | 85 | // The 32 lowest order bits of the key are used to get the index of the cluster 86 | TTEntry* first_entry(const Key key) const { 87 | return &table[(uint32_t(key) * uint64_t(clusterCount)) >> 32].entry[0]; 88 | } 89 | 90 | private: 91 | friend struct TTEntry; 92 | 93 | size_t clusterCount; 94 | Cluster* table; 95 | void* mem; 96 | uint8_t generation8; // Size must be not bigger than TTEntry::genBound8 97 | }; 98 | 99 | extern TranspositionTable TT; 100 | 101 | #endif // #ifndef TT_H_INCLUDED 102 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | 26 | #include "misc.h" 27 | #include "movepick.h" 28 | #include "types.h" 29 | 30 | class Position; 31 | 32 | namespace Search { 33 | 34 | /// Threshold used for countermoves based pruning 35 | constexpr int CounterMovePruneThreshold = 0; 36 | 37 | 38 | /// Stack struct keeps track of the information we need to remember from nodes 39 | /// shallower and deeper in the tree during the search. Each search thread has 40 | /// its own array of Stack objects, indexed by the current ply. 41 | 42 | struct Stack { 43 | Move* pv; 44 | PieceToHistory* continuationHistory; 45 | int ply; 46 | Move currentMove; 47 | Move excludedMove; 48 | Move killers[2]; 49 | Value staticEval; 50 | int statScore; 51 | int moveCount; 52 | }; 53 | 54 | 55 | /// RootMove struct is used for moves at the root of the tree. For each root move 56 | /// we store a score and a PV (really a refutation in the case of moves which 57 | /// fail low). Score is normally set at -VALUE_INFINITE for all non-pv moves. 58 | 59 | struct RootMove { 60 | 61 | explicit RootMove(Move m) : pv(1, m) {} 62 | bool extract_ponder_from_tt(Position& pos); 63 | bool operator==(const Move& m) const { return pv[0] == m; } 64 | bool operator<(const RootMove& m) const { // Sort in descending order 65 | return m.score != score ? m.score < score 66 | : m.previousScore < previousScore; 67 | } 68 | 69 | Value score = -VALUE_INFINITE; 70 | Value previousScore = -VALUE_INFINITE; 71 | int selDepth = 0; 72 | int tbRank; 73 | Value tbScore; 74 | std::vector pv; 75 | }; 76 | 77 | typedef std::vector RootMoves; 78 | 79 | 80 | /// LimitsType struct stores information sent by GUI about available time to 81 | /// search the current move, maximum depth/time, or if we are in analysis mode. 82 | 83 | struct LimitsType { 84 | 85 | LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC 86 | time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movetime = TimePoint(0); 87 | movestogo = depth = mate = perft = infinite = 0; 88 | nodes = 0; 89 | } 90 | 91 | bool use_time_management() const { 92 | return !(mate | movetime | depth | nodes | perft | infinite); 93 | } 94 | 95 | std::vector searchmoves; 96 | TimePoint time[COLOR_NB], inc[COLOR_NB], npmsec, movetime, startTime; 97 | int movestogo, depth, mate, perft, infinite; 98 | int64_t nodes; 99 | }; 100 | 101 | extern LimitsType Limits; 102 | 103 | void init(); 104 | void clear(); 105 | 106 | } // namespace Search 107 | 108 | #endif // #ifndef SEARCH_H_INCLUDED 109 | -------------------------------------------------------------------------------- /find_position_black.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | def fen2board_black(fen_line): 5 | black_player_bool_position = [] 6 | for row in fen_line.split(' ')[0].split('/'): 7 | bool_row = [] 8 | for cell in list(row): 9 | if cell.isnumeric(): 10 | for i in range(int(cell)): 11 | bool_row.append(0) 12 | else: 13 | if cell.islower(): 14 | bool_row.append(1) 15 | else: 16 | bool_row.append(0) 17 | black_player_bool_position.append(bool_row) 18 | black_player_bool_position = np.array(black_player_bool_position) 19 | return black_player_bool_position 20 | 21 | def rectContains(rect,mid_point): 22 | logic = rect[0]= 2: 39 | required_contoures_mid_point = [] 40 | for c in cnts: 41 | area = cv2.contourArea(c) 42 | if area> 500: 43 | (x, y, w, h) = cv2.boundingRect(c) 44 | required_contoures_mid_point.append([x+int(w/2),y+int(h/2)]) 45 | # cv2.rectangle(diff, (x, y), (x + w, y + h), (0, 0, 255), 2) 46 | 47 | flag = np.zeros((8,8),dtype=int) 48 | for i in range(8): 49 | for j in range(8): 50 | for mid_point in required_contoures_mid_point: 51 | if(rectContains(boxes[i][j],mid_point)) and flag[i][j]==0: 52 | diff_position[i][j] = 2 53 | flag[i][j]=1 54 | 55 | 56 | temp_matrix = past_black_bool_position - diff_position 57 | print(temp_matrix) 58 | position_of_past_black = np.where(temp_matrix == -1) 59 | position_of_new_black = np.where(temp_matrix == -2) 60 | 61 | player_moved = chess_board[position_of_past_black[0][0]][position_of_past_black[1][0]] 62 | chess_board[position_of_past_black]=1 63 | chess_board[position_of_new_black]=player_moved 64 | 65 | move_word = number_to_position_map[int(position_of_past_black[0][0])][int(position_of_past_black[1][0])] 66 | move_word+= number_to_position_map[int(position_of_new_black[0][0])][int(position_of_new_black[1][0])] 67 | 68 | position1 = str(move_word)[0:2] 69 | position2 = str(move_word)[2:4] 70 | 71 | box_1_cordinate = map_position[position1] 72 | box_2_cordinate = map_position[position2] 73 | 74 | position1_box = boxes[box_1_cordinate[0]][box_1_cordinate[1]] 75 | position2_box = boxes[box_2_cordinate[0]][box_2_cordinate[1]] 76 | 77 | draw_img = img_2.copy() 78 | cv2.rectangle(draw_img,(position1_box[0],position1_box[1]),(position1_box[2],position1_box[3]),(0,0,255),3) 79 | cv2.rectangle(draw_img,(position2_box[0],position2_box[1]),(position2_box[2],position2_box[3]),(0,255,0),3) 80 | 81 | return move_word,draw_img,1 82 | else: 83 | return " ",img_2,0 84 | 85 | -------------------------------------------------------------------------------- /stockfish-10-win/tests/instrumented.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # check for errors under valgrind or sanitizers. 3 | 4 | error() 5 | { 6 | echo "instrumented testing failed on line $1" 7 | exit 1 8 | } 9 | trap 'error ${LINENO}' ERR 10 | 11 | # define suitable post and prefixes for testing options 12 | case $1 in 13 | --valgrind) 14 | echo "valgrind testing started" 15 | prefix='' 16 | exeprefix='valgrind --error-exitcode=42' 17 | postfix='1>/dev/null' 18 | threads="1" 19 | ;; 20 | --valgrind-thread) 21 | echo "valgrind-thread testing started" 22 | prefix='' 23 | exeprefix='valgrind --error-exitcode=42' 24 | postfix='1>/dev/null' 25 | threads="2" 26 | ;; 27 | --sanitizer-undefined) 28 | echo "sanitizer-undefined testing started" 29 | prefix='!' 30 | exeprefix='' 31 | postfix='2>&1 | grep "runtime error:"' 32 | threads="1" 33 | ;; 34 | --sanitizer-thread) 35 | echo "sanitizer-thread testing started" 36 | prefix='!' 37 | exeprefix='' 38 | postfix='2>&1 | grep "WARNING: ThreadSanitizer:"' 39 | threads="2" 40 | 41 | cat << EOF > tsan.supp 42 | race:TTEntry::move 43 | race:TTEntry::depth 44 | race:TTEntry::bound 45 | race:TTEntry::save 46 | race:TTEntry::value 47 | race:TTEntry::eval 48 | 49 | race:TranspositionTable::probe 50 | race:TranspositionTable::hashfull 51 | 52 | EOF 53 | 54 | export TSAN_OPTIONS="suppressions=./tsan.supp" 55 | 56 | ;; 57 | *) 58 | echo "unknown testing started" 59 | prefix='' 60 | exeprefix='' 61 | postfix='' 62 | threads="1" 63 | ;; 64 | esac 65 | 66 | # simple command line testing 67 | for args in "eval" \ 68 | "go nodes 1000" \ 69 | "go depth 10" \ 70 | "go movetime 1000" \ 71 | "go wtime 8000 btime 8000 winc 500 binc 500" \ 72 | "bench 128 $threads 10 default depth" 73 | do 74 | 75 | echo "$prefix $exeprefix ./stockfish $args $postfix" 76 | eval "$prefix $exeprefix ./stockfish $args $postfix" 77 | 78 | done 79 | 80 | # more general testing, following an uci protocol exchange 81 | cat << EOF > game.exp 82 | set timeout 10 83 | spawn $exeprefix ./stockfish 84 | 85 | send "uci\n" 86 | expect "uciok" 87 | 88 | send "setoption name Threads value $threads\n" 89 | 90 | send "ucinewgame\n" 91 | send "position startpos\n" 92 | send "go nodes 1000\n" 93 | expect "bestmove" 94 | 95 | send "position startpos moves e2e4 e7e6\n" 96 | send "go nodes 1000\n" 97 | expect "bestmove" 98 | 99 | send "position fen 5rk1/1K4p1/8/8/3B4/8/8/8 b - - 0 1\n" 100 | send "go depth 30\n" 101 | expect "bestmove" 102 | 103 | send "quit\n" 104 | expect eof 105 | 106 | # return error code of the spawned program, useful for valgrind 107 | lassign [wait] pid spawnid os_error_flag value 108 | exit \$value 109 | EOF 110 | 111 | #download TB as needed 112 | if [ ! -d ../tests/syzygy ]; then 113 | curl -sL https://api.github.com/repos/niklasf/python-chess/tarball/9b9aa13f9f36d08aadfabff872882f4ab1494e95 | tar -xzf - 114 | mv niklasf-python-chess-9b9aa13 ../tests/syzygy 115 | fi 116 | 117 | cat << EOF > syzygy.exp 118 | set timeout 240 119 | spawn $exeprefix ./stockfish 120 | send "uci\n" 121 | send "setoption name SyzygyPath value ../tests/syzygy/\n" 122 | expect "info string Found 35 tablebases" {} timeout {exit 1} 123 | send "bench 128 1 10 default depth\n" 124 | send "quit\n" 125 | expect eof 126 | 127 | # return error code of the spawned program, useful for valgrind 128 | lassign [wait] pid spawnid os_error_flag value 129 | exit \$value 130 | EOF 131 | 132 | for exp in game.exp syzygy.exp 133 | do 134 | 135 | echo "$prefix expect $exp $postfix" 136 | eval "$prefix expect $exp $postfix" 137 | 138 | rm $exp 139 | 140 | done 141 | 142 | rm -f tsan.supp 143 | 144 | echo "instrumented testing OK" 145 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 prefetch2(void* addr); 35 | void start_logger(const std::string& fname); 36 | 37 | void dbg_hit_on(bool b); 38 | void dbg_hit_on(bool c, bool b); 39 | void dbg_mean_of(int v); 40 | void dbg_print(); 41 | 42 | typedef std::chrono::milliseconds::rep TimePoint; // A value in milliseconds 43 | 44 | static_assert(sizeof(TimePoint) == sizeof(int64_t), "TimePoint should be 64 bits"); 45 | 46 | inline TimePoint now() { 47 | return std::chrono::duration_cast 48 | (std::chrono::steady_clock::now().time_since_epoch()).count(); 49 | } 50 | 51 | template 52 | struct HashTable { 53 | Entry* operator[](Key key) { return &table[(uint32_t)key & (Size - 1)]; } 54 | 55 | private: 56 | std::vector table = std::vector(Size); 57 | }; 58 | 59 | 60 | enum SyncCout { IO_LOCK, IO_UNLOCK }; 61 | std::ostream& operator<<(std::ostream&, SyncCout); 62 | 63 | #define sync_cout std::cout << IO_LOCK 64 | #define sync_endl std::endl << IO_UNLOCK 65 | 66 | 67 | /// xorshift64star Pseudo-Random Number Generator 68 | /// This class is based on original code written and dedicated 69 | /// to the public domain by Sebastiano Vigna (2014). 70 | /// It has the following characteristics: 71 | /// 72 | /// - Outputs 64-bit numbers 73 | /// - Passes Dieharder and SmallCrush test batteries 74 | /// - Does not require warm-up, no zeroland to escape 75 | /// - Internal state is a single 64-bit integer 76 | /// - Period is 2^64 - 1 77 | /// - Speed: 1.60 ns/call (Core i7 @3.40GHz) 78 | /// 79 | /// For further analysis see 80 | /// 81 | 82 | class PRNG { 83 | 84 | uint64_t s; 85 | 86 | uint64_t rand64() { 87 | 88 | s ^= s >> 12, s ^= s << 25, s ^= s >> 27; 89 | return s * 2685821657736338717LL; 90 | } 91 | 92 | public: 93 | PRNG(uint64_t seed) : s(seed) { assert(seed); } 94 | 95 | template T rand() { return T(rand64()); } 96 | 97 | /// Special generator used to fast init magic numbers. 98 | /// Output values only have 1/8th of their bits set on average. 99 | template T sparse_rand() 100 | { return T(rand64() & rand64() & rand64()); } 101 | }; 102 | 103 | 104 | /// Under Windows it is not possible for a process to run on more than one 105 | /// logical processor group. This usually means to be limited to use max 64 106 | /// cores. To overcome this, some special platform specific API should be 107 | /// called to set group affinity for each thread. Original code from Texel by 108 | /// Peter Österlund. 109 | 110 | namespace WinProcGroup { 111 | void bindThisThread(size_t idx); 112 | } 113 | 114 | #endif // #ifndef MISC_H_INCLUDED 115 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | 30 | #include "material.h" 31 | #include "movepick.h" 32 | #include "pawns.h" 33 | #include "position.h" 34 | #include "search.h" 35 | #include "thread_win32.h" 36 | 37 | 38 | /// Thread class keeps together all the thread-related stuff. We use 39 | /// per-thread pawn and material hash tables so that once we get a 40 | /// pointer to an entry its life time is unlimited and we don't have 41 | /// to care about someone changing the entry under our feet. 42 | 43 | class Thread { 44 | 45 | Mutex mutex; 46 | ConditionVariable cv; 47 | size_t idx; 48 | bool exit = false, searching = true; // Set before starting std::thread 49 | std::thread stdThread; 50 | 51 | public: 52 | explicit Thread(size_t); 53 | virtual ~Thread(); 54 | virtual void search(); 55 | void clear(); 56 | void idle_loop(); 57 | void start_searching(); 58 | void wait_for_search_finished(); 59 | 60 | Pawns::Table pawnsTable; 61 | Material::Table materialTable; 62 | Endgames endgames; 63 | size_t pvIdx, pvLast; 64 | int selDepth, nmpMinPly; 65 | Color nmpColor; 66 | std::atomic nodes, tbHits; 67 | 68 | Position rootPos; 69 | Search::RootMoves rootMoves; 70 | Depth rootDepth, completedDepth; 71 | CounterMoveHistory counterMoves; 72 | ButterflyHistory mainHistory; 73 | CapturePieceToHistory captureHistory; 74 | ContinuationHistory continuationHistory; 75 | Score contempt; 76 | }; 77 | 78 | 79 | /// MainThread is a derived class specific for main thread 80 | 81 | struct MainThread : public Thread { 82 | 83 | using Thread::Thread; 84 | 85 | void search() override; 86 | void check_time(); 87 | 88 | double bestMoveChanges, previousTimeReduction; 89 | Value previousScore; 90 | int callsCnt; 91 | }; 92 | 93 | 94 | /// ThreadPool struct handles all the threads-related stuff like init, starting, 95 | /// parking and, most importantly, launching a thread. All the access to threads 96 | /// is done through this class. 97 | 98 | struct ThreadPool : public std::vector { 99 | 100 | void start_thinking(Position&, StateListPtr&, const Search::LimitsType&, bool = false); 101 | void clear(); 102 | void set(size_t); 103 | 104 | MainThread* main() const { return static_cast(front()); } 105 | uint64_t nodes_searched() const { return accumulate(&Thread::nodes); } 106 | uint64_t tb_hits() const { return accumulate(&Thread::tbHits); } 107 | 108 | std::atomic_bool stop, ponder, stopOnPonderhit; 109 | 110 | private: 111 | StateListPtr setupStates; 112 | 113 | uint64_t accumulate(std::atomic Thread::* member) const { 114 | 115 | uint64_t sum = 0; 116 | for (Thread* th : *this) 117 | sum += (th->*member).load(std::memory_order_relaxed); 118 | return sum; 119 | } 120 | }; 121 | 122 | extern ThreadPool Threads; 123 | 124 | #endif // #ifndef THREAD_H_INCLUDED 125 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | /// EndgameCode lists all supported endgame functions by corresponding codes 35 | 36 | enum EndgameCode { 37 | 38 | EVALUATION_FUNCTIONS, 39 | KNNK, // KNN vs K 40 | KXK, // Generic "mate lone king" eval 41 | KBNK, // KBN vs K 42 | KPK, // KP vs K 43 | KRKP, // KR vs KP 44 | KRKB, // KR vs KB 45 | KRKN, // KR vs KN 46 | KQKP, // KQ vs KP 47 | KQKR, // KQ vs KR 48 | 49 | SCALING_FUNCTIONS, 50 | KBPsK, // KB and pawns vs K 51 | KQKRPs, // KQ vs KR and pawns 52 | KRPKR, // KRP vs KR 53 | KRPKB, // KRP vs KB 54 | KRPPKRP, // KRPP vs KRP 55 | KPsK, // K and pawns vs K 56 | KBPKB, // KBP vs KB 57 | KBPPKB, // KBPP vs KB 58 | KBPKN, // KBP vs KN 59 | KNPK, // KNP vs K 60 | KNPKB, // KNP vs KB 61 | KPKP // KP vs KP 62 | }; 63 | 64 | 65 | /// Endgame functions can be of two types depending on whether they return a 66 | /// Value or a ScaleFactor. 67 | 68 | template using 69 | eg_type = typename std::conditional<(E < SCALING_FUNCTIONS), Value, ScaleFactor>::type; 70 | 71 | 72 | /// Base and derived functors for endgame evaluation and scaling functions 73 | 74 | template 75 | struct EndgameBase { 76 | 77 | explicit EndgameBase(Color c) : strongSide(c), weakSide(~c) {} 78 | virtual ~EndgameBase() = default; 79 | virtual T operator()(const Position&) const = 0; 80 | 81 | const Color strongSide, weakSide; 82 | }; 83 | 84 | 85 | template> 86 | struct Endgame : public EndgameBase { 87 | 88 | explicit Endgame(Color c) : EndgameBase(c) {} 89 | T operator()(const Position&) const override; 90 | }; 91 | 92 | 93 | /// The Endgames class stores the pointers to endgame evaluation and scaling 94 | /// base objects in two std::map. We use polymorphism to invoke the actual 95 | /// endgame function by calling its virtual operator(). 96 | 97 | class Endgames { 98 | 99 | template using Ptr = std::unique_ptr>; 100 | template using Map = std::map>; 101 | 102 | template 103 | Map& map() { 104 | return std::get::value>(maps); 105 | } 106 | 107 | template> 108 | void add(const std::string& code) { 109 | 110 | StateInfo st; 111 | map()[Position().set(code, WHITE, &st).material_key()] = Ptr(new Endgame(WHITE)); 112 | map()[Position().set(code, BLACK, &st).material_key()] = Ptr(new Endgame(BLACK)); 113 | } 114 | 115 | std::pair, Map> maps; 116 | 117 | public: 118 | Endgames() { 119 | 120 | add("KPK"); 121 | add("KNNK"); 122 | add("KBNK"); 123 | add("KRKP"); 124 | add("KRKB"); 125 | add("KRKN"); 126 | add("KQKP"); 127 | add("KQKR"); 128 | 129 | add("KNPK"); 130 | add("KNPKB"); 131 | add("KRPKR"); 132 | add("KRPKB"); 133 | add("KBPKB"); 134 | add("KBPKN"); 135 | add("KBPPKB"); 136 | add("KRPPKRP"); 137 | } 138 | 139 | template 140 | const EndgameBase* probe(Key key) { 141 | return map().count(key) ? map()[key].get() : nullptr; 142 | } 143 | }; 144 | 145 | #endif // #ifndef ENDGAME_H_INCLUDED 146 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | 30 | namespace PSQT { 31 | 32 | #define S(mg, eg) make_score(mg, eg) 33 | 34 | // Bonus[PieceType][Square / 2] contains Piece-Square scores. For each piece 35 | // type on a given square a (middlegame, endgame) score pair is assigned. Table 36 | // is defined for files A..D and white side: it is symmetric for black side and 37 | // second half of the files. 38 | constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = { 39 | { }, 40 | { // Pawn 41 | { S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) }, 42 | { S(-11,-3), S( 7, -1), S( 7, 7), S(17, 2) }, 43 | { S(-16,-2), S( -3, 2), S( 23, 6), S(23,-1) }, 44 | { S(-14, 7), S( -7, -4), S( 20,-8), S(24, 2) }, 45 | { S( -5,13), S( -2, 10), S( -1,-1), S(12,-8) }, 46 | { S(-11,16), S(-12, 6), S( -2, 1), S( 4,16) }, 47 | { S( -2, 1), S( 20,-12), S(-10, 6), S(-2,25) } 48 | }, 49 | { // Knight 50 | { S(-169,-105), S(-96,-74), S(-80,-46), S(-79,-18) }, 51 | { S( -79, -70), S(-39,-56), S(-24,-15), S( -9, 6) }, 52 | { S( -64, -38), S(-20,-33), S( 4, -5), S( 19, 27) }, 53 | { S( -28, -36), S( 5, 0), S( 41, 13), S( 47, 34) }, 54 | { S( -29, -41), S( 13,-20), S( 42, 4), S( 52, 35) }, 55 | { S( -11, -51), S( 28,-38), S( 63,-17), S( 55, 19) }, 56 | { S( -67, -64), S(-21,-45), S( 6,-37), S( 37, 16) }, 57 | { S(-200, -98), S(-80,-89), S(-53,-53), S(-32,-16) } 58 | }, 59 | { // Bishop 60 | { S(-49,-58), S(- 7,-31), S(-10,-37), S(-34,-19) }, 61 | { S(-24,-34), S( 9, -9), S( 15,-14), S( 1, 4) }, 62 | { S( -9,-23), S( 22, 0), S( -3, -3), S( 12, 16) }, 63 | { S( 4,-26), S( 9, -3), S( 18, -5), S( 40, 16) }, 64 | { S( -8,-26), S( 27, -4), S( 13, -7), S( 30, 14) }, 65 | { S(-17,-24), S( 14, -2), S( -6, 0), S( 6, 13) }, 66 | { S(-19,-34), S(-13,-10), S( 7,-12), S(-11, 6) }, 67 | { S(-47,-55), S( -7,-32), S(-17,-36), S(-29,-17) } 68 | }, 69 | { // Rook 70 | { S(-24, 0), S(-15, 3), S( -8, 0), S( 0, 3) }, 71 | { S(-18,-7), S( -5,-5), S( -1,-5), S( 1,-1) }, 72 | { S(-19, 6), S(-10,-7), S( 1, 3), S( 0, 3) }, 73 | { S(-21, 0), S( -7, 4), S( -4,-2), S(-4, 1) }, 74 | { S(-21,-7), S(-12, 5), S( -1,-5), S( 4,-7) }, 75 | { S(-23, 3), S(-10, 2), S( 1,-1), S( 6, 3) }, 76 | { S(-11,-1), S( 8, 7), S( 9,11), S(12,-1) }, 77 | { S(-25, 6), S(-18, 4), S(-11, 6), S( 2, 2) } 78 | }, 79 | { // Queen 80 | { S( 3,-69), S(-5,-57), S(-5,-47), S( 4,-26) }, 81 | { S( -3,-55), S( 5,-31), S( 8,-22), S(12, -4) }, 82 | { S( -3,-39), S( 6,-18), S(13, -9), S( 7, 3) }, 83 | { S( 4,-23), S( 5, -3), S( 9, 13), S( 8, 24) }, 84 | { S( 0,-29), S(14, -6), S(12, 9), S( 5, 21) }, 85 | { S( -4,-38), S(10,-18), S( 6,-12), S( 8, 1) }, 86 | { S( -5,-50), S( 6,-27), S(10,-24), S( 8, -8) }, 87 | { S( -2,-75), S(-2,-52), S( 1,-43), S(-2,-36) } 88 | }, 89 | { // King 90 | { S(272, 0), S(325, 41), S(273, 80), S(190, 93) }, 91 | { S(277, 57), S(305, 98), S(241,138), S(183,131) }, 92 | { S(198, 86), S(253,138), S(168,165), S(120,173) }, 93 | { S(169,103), S(191,152), S(136,168), S(108,169) }, 94 | { S(145, 98), S(176,166), S(112,197), S(69, 194) }, 95 | { S(122, 87), S(159,164), S(85, 174), S(36, 189) }, 96 | { S(87, 40), S(120, 99), S(64, 128), S(25, 141) }, 97 | { S(64, 5), S(87, 60), S(49, 75), S(0, 75) } 98 | } 99 | }; 100 | 101 | #undef S 102 | 103 | Score psq[PIECE_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 (Piece pc = W_PAWN; pc <= W_KING; ++pc) 111 | { 112 | PieceValue[MG][~pc] = PieceValue[MG][pc]; 113 | PieceValue[EG][~pc] = PieceValue[EG][pc]; 114 | 115 | Score score = make_score(PieceValue[MG][pc], PieceValue[EG][pc]); 116 | 117 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 118 | { 119 | File f = std::min(file_of(s), ~file_of(s)); 120 | psq[ pc][ s] = score + Bonus[pc][rank_of(s)][f]; 121 | psq[~pc][~s] = -psq[pc][s]; 122 | } 123 | } 124 | } 125 | 126 | } // namespace PSQT 127 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | constexpr int MoveHorizon = 50; // Plan time management at most this many moves ahead 36 | constexpr double MaxRatio = 7.3; // When in trouble, we can step over reserved time with this ratio 37 | constexpr double StealRatio = 0.34; // 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 | constexpr double XScale = 6.85; 48 | constexpr double XShift = 64.5; 49 | constexpr double Skew = 0.171; 50 | 51 | return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero 52 | } 53 | 54 | template 55 | TimePoint remaining(TimePoint myTime, int movesToGo, int ply, TimePoint slowMover) { 56 | 57 | constexpr double TMaxRatio = (T == OptimumTime ? 1.0 : MaxRatio); 58 | constexpr double TStealRatio = (T == OptimumTime ? 0.0 : StealRatio); 59 | 60 | double moveImportance = (move_importance(ply) * slowMover) / 100.0; 61 | double otherMovesImportance = 0.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 TimePoint(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 | TimePoint minThinkingTime = Options["Minimum Thinking Time"]; 87 | TimePoint moveOverhead = Options["Move Overhead"]; 88 | TimePoint slowMover = Options["Slow Mover"]; 89 | TimePoint npmsec = Options["nodestime"]; 90 | TimePoint hypMyTime; 91 | 92 | // If we have to play in 'nodes as time' mode, then convert from time 93 | // to nodes, and use resulting values in time management formulas. 94 | // WARNING: to avoid time losses, the given npmsec (nodes per millisecond) 95 | // must be much lower than the real engine speed. 96 | if (npmsec) 97 | { 98 | if (!availableNodes) // Only once at game start 99 | availableNodes = npmsec * limits.time[us]; // Time is in msec 100 | 101 | // Convert from milliseconds to nodes 102 | limits.time[us] = TimePoint(availableNodes); 103 | limits.inc[us] *= npmsec; 104 | limits.npmsec = npmsec; 105 | } 106 | 107 | startTime = limits.startTime; 108 | optimumTime = maximumTime = std::max(limits.time[us], minThinkingTime); 109 | 110 | const int maxMTG = limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon; 111 | 112 | // We calculate optimum time usage for different hypothetical "moves to go" values 113 | // and choose the minimum of calculated search time values. Usually the greatest 114 | // hypMTG gives the minimum values. 115 | for (int hypMTG = 1; hypMTG <= maxMTG; ++hypMTG) 116 | { 117 | // Calculate thinking time for hypothetical "moves to go"-value 118 | hypMyTime = limits.time[us] 119 | + limits.inc[us] * (hypMTG - 1) 120 | - moveOverhead * (2 + std::min(hypMTG, 40)); 121 | 122 | hypMyTime = std::max(hypMyTime, TimePoint(0)); 123 | 124 | TimePoint t1 = minThinkingTime + remaining(hypMyTime, hypMTG, ply, slowMover); 125 | TimePoint t2 = minThinkingTime + remaining(hypMyTime, hypMTG, ply, slowMover); 126 | 127 | optimumTime = std::min(t1, optimumTime); 128 | maximumTime = std::min(t2, maximumTime); 129 | } 130 | 131 | if (Options["Ponder"]) 132 | optimumTime += optimumTime / 4; 133 | } 134 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | #include 24 | 25 | #include "bitboard.h" 26 | #include "misc.h" 27 | #include "tt.h" 28 | #include "uci.h" 29 | 30 | TranspositionTable TT; // Our global transposition table 31 | 32 | /// TTEntry::save saves a TTEntry 33 | void TTEntry::save(Key k, Value v, Bound b, Depth d, Move m, Value ev) { 34 | 35 | assert(d / ONE_PLY * ONE_PLY == d); 36 | 37 | // Preserve any existing move for the same position 38 | if (m || (k >> 48) != key16) 39 | move16 = (uint16_t)m; 40 | 41 | // Overwrite less valuable entries 42 | if ( (k >> 48) != key16 43 | || d / ONE_PLY > depth8 - 4 44 | || b == BOUND_EXACT) 45 | { 46 | key16 = (uint16_t)(k >> 48); 47 | value16 = (int16_t)v; 48 | eval16 = (int16_t)ev; 49 | genBound8 = (uint8_t)(TT.generation8 | b); 50 | depth8 = (int8_t)(d / ONE_PLY); 51 | } 52 | } 53 | 54 | 55 | /// TranspositionTable::resize() sets the size of the transposition table, 56 | /// measured in megabytes. Transposition table consists of a power of 2 number 57 | /// of clusters and each cluster consists of ClusterSize number of TTEntry. 58 | 59 | void TranspositionTable::resize(size_t mbSize) { 60 | 61 | clusterCount = mbSize * 1024 * 1024 / sizeof(Cluster); 62 | 63 | free(mem); 64 | mem = malloc(clusterCount * sizeof(Cluster) + CacheLineSize - 1); 65 | 66 | if (!mem) 67 | { 68 | std::cerr << "Failed to allocate " << mbSize 69 | << "MB for transposition table." << std::endl; 70 | exit(EXIT_FAILURE); 71 | } 72 | 73 | table = (Cluster*)((uintptr_t(mem) + CacheLineSize - 1) & ~(CacheLineSize - 1)); 74 | clear(); 75 | } 76 | 77 | 78 | /// TranspositionTable::clear() initializes the entire transposition table to zero, 79 | // in a multi-threaded way. 80 | 81 | void TranspositionTable::clear() { 82 | 83 | std::vector threads; 84 | 85 | for (size_t idx = 0; idx < Options["Threads"]; idx++) 86 | { 87 | threads.emplace_back([this, idx]() { 88 | 89 | // Thread binding gives faster search on systems with a first-touch policy 90 | if (Options["Threads"] > 8) 91 | WinProcGroup::bindThisThread(idx); 92 | 93 | // Each thread will zero its part of the hash table 94 | const size_t stride = clusterCount / Options["Threads"], 95 | start = stride * idx, 96 | len = idx != Options["Threads"] - 1 ? 97 | stride : clusterCount - start; 98 | 99 | std::memset(&table[start], 0, len * sizeof(Cluster)); 100 | }); 101 | } 102 | 103 | for (std::thread& th: threads) 104 | th.join(); 105 | } 106 | 107 | /// TranspositionTable::probe() looks up the current position in the transposition 108 | /// table. It returns true and a pointer to the TTEntry if the position is found. 109 | /// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry 110 | /// to be replaced later. The replace value of an entry is calculated as its depth 111 | /// minus 8 times its relative age. TTEntry t1 is considered more valuable than 112 | /// TTEntry t2 if its replace value is greater than that of t2. 113 | 114 | TTEntry* TranspositionTable::probe(const Key key, bool& found) const { 115 | 116 | TTEntry* const tte = first_entry(key); 117 | const uint16_t key16 = key >> 48; // Use the high 16 bits as key inside the cluster 118 | 119 | for (int i = 0; i < ClusterSize; ++i) 120 | if (!tte[i].key16 || tte[i].key16 == key16) 121 | { 122 | tte[i].genBound8 = uint8_t(generation8 | tte[i].bound()); // Refresh 123 | 124 | return found = (bool)tte[i].key16, &tte[i]; 125 | } 126 | 127 | // Find an entry to be replaced according to the replacement strategy 128 | TTEntry* replace = tte; 129 | for (int i = 1; i < ClusterSize; ++i) 130 | // Due to our packed storage format for generation and its cyclic 131 | // nature we add 259 (256 is the modulus plus 3 to keep the lowest 132 | // two bound bits from affecting the result) to calculate the entry 133 | // age correctly even after generation8 overflows into the next cycle. 134 | if ( replace->depth8 - ((259 + generation8 - replace->genBound8) & 0xFC) * 2 135 | > tte[i].depth8 - ((259 + generation8 - tte[i].genBound8) & 0xFC) * 2) 136 | replace = &tte[i]; 137 | 138 | return found = false, replace; 139 | } 140 | 141 | 142 | /// TranspositionTable::hashfull() returns an approximation of the hashtable 143 | /// occupation during a search. The hash is x permill full, as per UCI protocol. 144 | 145 | int TranspositionTable::hashfull() const { 146 | 147 | int cnt = 0; 148 | for (int i = 0; i < 1000 / ClusterSize; i++) 149 | { 150 | const TTEntry* tte = &table[i].entry[0]; 151 | for (int j = 0; j < ClusterSize; j++) 152 | if ((tte[j].genBound8 & 0xFC) == generation8) 153 | cnt++; 154 | } 155 | return cnt; 156 | } 157 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Realtime-OpenCV-Chess 2 | ♔♕♗♘♙♚♛♝♞♟♖♜ 3 | 4 | --- 5 | 6 | Human vs AI (Stockfish engine) 7 | 8 | Camera captures the image of chessboard then the images analyzed using imageprocessing to identify the moves made by opponent and stockfish engine calculates the best possible move. 9 | 10 | ![opencv](https://img.shields.io/badge/CV-Open--CV-green)|![python](https://img.shields.io/badge/Py-Python3-blue) 11 | :-------------------------:|:-------------------------: 12 | 13 | # Youtube Video 14 | [![check out my youtube video](https://img.youtube.com/vi/JnpxzLM8ht0/0.jpg)](https://youtu.be/JnpxzLM8ht0)|[![check out my youtube video](https://img.youtube.com/vi/PQk7sFsqaRQ/0.jpg)](https://youtu.be/PQk7sFsqaRQ) 15 | :-------------------------:|:-------------------------: 16 | 17 | # Image Transformation 18 | | ![Input-Frame](https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/master/Images/input-frame.png) | ![warp-perspective](https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/master/Images/warpperspective.png) | ![locate-boxes](https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/master/Images/locate-boxes.png) | 19 | :-------------------------:|:-------------------------:|:-------------------------: 20 | |Input-Frame|warp-perspective|locate-boxes| 21 | 22 | # Method of Working 23 | ## Step - 1 24 | Image1 : Image of Chess Board befor player move piece|Image2 : Image of Chess Board after player move piece 25 | :-------------------------:|:-------------------------: 26 | ![](https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/master/Method_working/Images/2.jpg)|![](https://raw.githubusercontent.com/Vatsalparsaniya/Realtime-OpenCV-Chess/master/Method_working/Images/3.jpg) 27 | 28 | ## step - 2 29 | Difference of image by using function absdiff in CV2|Change Difference_image to Gray scale image 30 | :-------------------------:|:-------------------------: 31 | diff = cv2.absdiff(image1,image2)|diff_gray = cv2.cvtColor(diff,cv2.COLOR_BGR2GRAY)| 32 | Difference_image|Difference_image 33 | 34 | 35 | ## step - 3 36 | Apply thresholding on Grayscale image| Find Contours on threshold image 37 | :-------------------------:|:-------------------------: 38 | matrix,thresold = cv2.threshold(diff_gray,value,255,cv2.THRESH_BINARY)|cnts,_ = cv2.findContours(thresold, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)| 39 | Difference_image|Difference_image 40 | 41 | 42 | # Main Variables 43 | Variables|Explain 44 | :-------------------------:|:-------------------------: 45 | points = [] | # contains chess board corners points| 46 | boxes = np.zeros((8,8,4),dtype=int) | # contains top-left and bottom-right point of chessboard boxes 47 | fen_line = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR'| # fen line of chess board 48 | board = chess.Board(fen=fen_line)| # object of chess board 49 | dir_path = os.path.dirname(os.path.realpath(__file__))+"/numpy_saved"| # path of current directory 50 | device = cv2.VideoCapture(1) |# set devidce for read image (1: for tacking input from usb-webcam) 51 | img_resize = (800,800)| # set o/p image size 52 | engine = chess.engine.SimpleEngine.popen_uci("stockfish-10-win\Windows\stockfish_10_x64.exe")| # stockfish engine 53 | chess_board = []| # it will store chess board matrix 54 | bool_position = np.zeros((8,8),dtype=int)| # store bool matrix of Board 55 | number_to_position_map = []| # map move values for [0,0]-> (8,a) , [0,1]-> (8,b).... so on 56 | 57 | # Main Functions 58 | Function Name|Explain 59 | :-------------------------:|:-------------------------: 60 | get_points(img,n)|select n points on image by double click and returns list of selected points 61 | get_warp_img(img,dir_path,img_resize)|return warp prespective of image taken by camera and resize it to img_resize value 62 | map_function()|makes a dictonary to map values { "a8":[0,0],"b8":[0,1],.... so on } 63 | fen2board(fen_line)|retuen a 8X8 matrix of chess player piece name and bool position 64 | board2fen(chess_board)|return fen line of chess board 65 | map_function_for_number_2_position()|makes a list for map values [0,0]="8a", [0,1]="8b",[0,2]="8c",... so on 66 | rectContains(rectangle,mid_point)| logic function for checking given mid_point is inside the rectangle or not 67 | show_game(game_img,board,player_move)|This function shows all game in proper format with plane turn, opponent's last move, current chess board, red and green boxes on moved piece, etc. 68 | set_legal_positions(game_image,board,boxes)| if Illegal move found in chess it shows last correct state of chess board 69 | 70 | 71 | # Author 72 | 73 | 74 | 75 | 85 | 86 |
76 | 77 | 78 | Vatsal Parsaniya 79 | 80 |

81 | 82 | 83 |

84 |
87 | -------------------------------------------------------------------------------- /stockfish-10-win/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 | [![Build Status](https://ci.appveyor.com/api/projects/status/github/official-stockfish/Stockfish?svg=true)](https://ci.appveyor.com/project/mcostalba/stockfish) 5 | 6 | Stockfish is a free UCI chess engine derived from Glaurung 2.1. It is 7 | not a complete chess program and requires some UCI-compatible GUI 8 | (e.g. XBoard with PolyGlot, eboard, Arena, Sigma Chess, Shredder, Chess 9 | Partner or Fritz) in order to be used comfortably. Read the 10 | documentation for your GUI of choice for information about how to use 11 | Stockfish with it. 12 | 13 | This version of Stockfish supports up to 512 cores. The engine defaults 14 | to one search thread, so it is therefore recommended to inspect the value of 15 | the *Threads* UCI parameter, and to make sure it equals the number of CPU 16 | cores on your computer. 17 | 18 | This version of Stockfish has support for Syzygybases. 19 | 20 | 21 | ### Files 22 | 23 | This distribution of Stockfish consists of the following files: 24 | 25 | * Readme.md, the file you are currently reading. 26 | 27 | * Copying.txt, a text file containing the GNU General Public License. 28 | 29 | * src, a subdirectory containing the full source code, including a Makefile 30 | that can be used to compile Stockfish on Unix-like systems. 31 | 32 | 33 | ### Syzygybases 34 | 35 | **Configuration** 36 | 37 | Syzygybases are configured using the UCI options "SyzygyPath", 38 | "SyzygyProbeDepth", "Syzygy50MoveRule" and "SyzygyProbeLimit". 39 | 40 | The option "SyzygyPath" should be set to the directory or directories that 41 | contain the .rtbw and .rtbz files. Multiple directories should be 42 | separated by ";" on Windows and by ":" on Unix-based operating systems. 43 | **Do not use spaces around the ";" or ":".** 44 | 45 | Example: `C:\tablebases\wdl345;C:\tablebases\wdl6;D:\tablebases\dtz345;D:\tablebases\dtz6` 46 | 47 | It is recommended to store .rtbw files on an SSD. There is no loss in 48 | storing the .rtbz files on a regular HD. 49 | 50 | Increasing the "SyzygyProbeDepth" option lets the engine probe less 51 | aggressively. Set this option to a higher value if you experience too much 52 | slowdown (in terms of nps) due to TB probing. 53 | 54 | Set the "Syzygy50MoveRule" option to false if you want tablebase positions 55 | that are drawn by the 50-move rule to count as win or loss. This may be useful 56 | for correspondence games (because of tablebase adjudication). 57 | 58 | The "SyzygyProbeLimit" option should normally be left at its default value. 59 | 60 | **What to expect** 61 | If the engine is searching a position that is not in the tablebases (e.g. 62 | a position with 8 pieces), it will access the tablebases during the search. 63 | If the engine reports a very large score (typically 123.xx), this means 64 | that it has found a winning line into a tablebase position. 65 | 66 | If the engine is given a position to search that is in the tablebases, it 67 | will use the tablebases at the beginning of the search to preselect all 68 | good moves, i.e. all moves that preserve the win or preserve the draw while 69 | taking into account the 50-move rule. 70 | It will then perform a search only on those moves. **The engine will not move 71 | immediately**, unless there is only a single good move. **The engine likely 72 | will not report a mate score even if the position is known to be won.** 73 | 74 | It is therefore clear that behaviour is not identical to what one might 75 | be used to with Nalimov tablebases. There are technical reasons for this 76 | difference, the main technical reason being that Nalimov tablebases use the 77 | DTM metric (distance-to-mate), while Syzygybases use a variation of the 78 | DTZ metric (distance-to-zero, zero meaning any move that resets the 50-move 79 | counter). This special metric is one of the reasons that Syzygybases are 80 | more compact than Nalimov tablebases, while still storing all information 81 | needed for optimal play and in addition being able to take into account 82 | the 50-move rule. 83 | 84 | 85 | ### Compiling it yourself 86 | 87 | On Unix-like systems, it should be possible to compile Stockfish 88 | directly from the source code with the included Makefile. 89 | 90 | Stockfish has support for 32 or 64-bit CPUs, the hardware POPCNT 91 | instruction, big-endian machines such as Power PC, and other platforms. 92 | 93 | In general it is recommended to run `make help` to see a list of make 94 | targets with corresponding descriptions. When not using the Makefile to 95 | compile (for instance with Microsoft MSVC) you need to manually 96 | set/unset some switches in the compiler command line; see file *types.h* 97 | for a quick reference. 98 | 99 | ### Resource For Understanding the Code Base 100 | 101 | * [Chess Programming Wiki](https://www.chessprogramming.org/Main_Page) 102 | has good overall chess engines explanations 103 | (techniques used here are well explained like hash maps etc), it was 104 | also recommended by the [support team at stockfish.](http://support.stockfishchess.org/discussions/questions/1132-how-to-understand-stockfish-sources) 105 | 106 | * [Here](https://www.chessprogramming.org/Stockfish) you can find a set 107 | of features and techniques used by Stockfish and each of them is explained 108 | at the wiki, however, it's a generic way rather than focusing on Stockfish's 109 | own implementation, but it will still help you. 110 | 111 | 112 | ### Terms of use 113 | 114 | Stockfish is free, and distributed under the **GNU General Public License** 115 | (GPL). Essentially, this means that you are free to do almost exactly 116 | what you want with the program, including distributing it among your 117 | friends, making it available for download from your web site, selling 118 | it (either by itself or as part of some bigger software package), or 119 | using it as the starting point for a software project of your own. 120 | 121 | The only real limitation is that whenever you distribute Stockfish in 122 | some way, you must always include the full source code, or a pointer 123 | to where the source code can be found. If you make any changes to the 124 | source code, these changes must also be made available under the GPL. 125 | 126 | For full details, read the copy of the GPL found in the file named 127 | *Copying.txt*. 128 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 "position.h" 27 | 28 | using namespace std; 29 | 30 | namespace { 31 | 32 | const vector Defaults = { 33 | "setoption name UCI_Chess960 value false", 34 | "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", 35 | "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 10", 36 | "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 11", 37 | "4rrk1/pp1n3p/3q2pQ/2p1pb2/2PP4/2P3N1/P2B2PP/4RRK1 b - - 7 19", 38 | "rq3rk1/ppp2ppp/1bnpb3/3N2B1/3NP3/7P/PPPQ1PP1/2KR3R w - - 7 14 moves d4e6", 39 | "r1bq1r1k/1pp1n1pp/1p1p4/4p2Q/4Pp2/1BNP4/PPP2PPP/3R1RK1 w - - 2 14 moves g2g4", 40 | "r3r1k1/2p2ppp/p1p1bn2/8/1q2P3/2NPQN2/PPP3PP/R4RK1 b - - 2 15", 41 | "r1bbk1nr/pp3p1p/2n5/1N4p1/2Np1B2/8/PPP2PPP/2KR1B1R w kq - 0 13", 42 | "r1bq1rk1/ppp1nppp/4n3/3p3Q/3P4/1BP1B3/PP1N2PP/R4RK1 w - - 1 16", 43 | "4r1k1/r1q2ppp/ppp2n2/4P3/5Rb1/1N1BQ3/PPP3PP/R5K1 w - - 1 17", 44 | "2rqkb1r/ppp2p2/2npb1p1/1N1Nn2p/2P1PP2/8/PP2B1PP/R1BQK2R b KQ - 0 11", 45 | "r1bq1r1k/b1p1npp1/p2p3p/1p6/3PP3/1B2NN2/PP3PPP/R2Q1RK1 w - - 1 16", 46 | "3r1rk1/p5pp/bpp1pp2/8/q1PP1P2/b3P3/P2NQRPP/1R2B1K1 b - - 6 22", 47 | "r1q2rk1/2p1bppp/2Pp4/p6b/Q1PNp3/4B3/PP1R1PPP/2K4R w - - 2 18", 48 | "4k2r/1pb2ppp/1p2p3/1R1p4/3P4/2r1PN2/P4PPP/1R4K1 b - - 3 22", 49 | "3q2k1/pb3p1p/4pbp1/2r5/PpN2N2/1P2P2P/5PP1/Q2R2K1 b - - 4 26", 50 | "6k1/6p1/6Pp/ppp5/3pn2P/1P3K2/1PP2P2/3N4 b - - 0 1", 51 | "3b4/5kp1/1p1p1p1p/pP1PpP1P/P1P1P3/3KN3/8/8 w - - 0 1", 52 | "2K5/p7/7P/5pR1/8/5k2/r7/8 w - - 0 1 moves g5g6 f3e3 g6g5 e3f3", 53 | "8/6pk/1p6/8/PP3p1p/5P2/4KP1q/3Q4 w - - 0 1", 54 | "7k/3p2pp/4q3/8/4Q3/5Kp1/P6b/8 w - - 0 1", 55 | "8/2p5/8/2kPKp1p/2p4P/2P5/3P4/8 w - - 0 1", 56 | "8/1p3pp1/7p/5P1P/2k3P1/8/2K2P2/8 w - - 0 1", 57 | "8/pp2r1k1/2p1p3/3pP2p/1P1P1P1P/P5KR/8/8 w - - 0 1", 58 | "8/3p4/p1bk3p/Pp6/1Kp1PpPp/2P2P1P/2P5/5B2 b - - 0 1", 59 | "5k2/7R/4P2p/5K2/p1r2P1p/8/8/8 b - - 0 1", 60 | "6k1/6p1/P6p/r1N5/5p2/7P/1b3PP1/4R1K1 w - - 0 1", 61 | "1r3k2/4q3/2Pp3b/3Bp3/2Q2p2/1p1P2P1/1P2KP2/3N4 w - - 0 1", 62 | "6k1/4pp1p/3p2p1/P1pPb3/R7/1r2P1PP/3B1P2/6K1 w - - 0 1", 63 | "8/3p3B/5p2/5P2/p7/PP5b/k7/6K1 w - - 0 1", 64 | 65 | // 5-man positions 66 | "8/8/8/8/5kp1/P7/8/1K1N4 w - - 0 1", // Kc2 - mate 67 | "8/8/8/5N2/8/p7/8/2NK3k w - - 0 1", // Na2 - mate 68 | "8/3k4/8/8/8/4B3/4KB2/2B5 w - - 0 1", // draw 69 | 70 | // 6-man positions 71 | "8/8/1P6/5pr1/8/4R3/7k/2K5 w - - 0 1", // Re5 - mate 72 | "8/2p4P/8/kr6/6R1/8/8/1K6 w - - 0 1", // Ka2 - mate 73 | "8/8/3P3k/8/1p6/8/1P6/1K3n2 b - - 0 1", // Nd2 - draw 74 | 75 | // 7-man positions 76 | "8/R7/2q5/8/6k1/8/1P5p/K6R w - - 0 124", // Draw 77 | 78 | // Mate and stalemate positions 79 | "6k1/3b3r/1p1p4/p1n2p2/1PPNpP1q/P3Q1p1/1R1RB1P1/5K2 b - - 0 1", 80 | "r2r1n2/pp2bk2/2p1p2p/3q4/3PN1QP/2P3R1/P4PP1/5RK1 w - - 0 1", 81 | "8/8/8/8/8/6k1/6p1/6K1 w - -", 82 | "7k/7P/6K1/8/3B4/8/8/8 b - -", 83 | 84 | // Chess 960 85 | "setoption name UCI_Chess960 value true", 86 | "bbqnnrkr/pppppppp/8/8/8/8/PPPPPPPP/BBQNNRKR w KQkq - 0 1 moves g2g3 d7d5 d2d4 c8h3 c1g5 e8d6 g5e7 f7f6", 87 | "setoption name UCI_Chess960 value false" 88 | }; 89 | 90 | } // namespace 91 | 92 | /// setup_bench() builds a list of UCI commands to be run by bench. There 93 | /// are five parameters: TT size in MB, number of search threads that 94 | /// should be used, the limit value spent for each position, a file name 95 | /// where to look for positions in FEN format and the type of the limit: 96 | /// depth, perft, nodes and movetime (in millisecs). 97 | /// 98 | /// bench -> search default positions up to depth 13 99 | /// bench 64 1 15 -> search default positions up to depth 15 (TT = 64MB) 100 | /// bench 64 4 5000 current movetime -> search current position with 4 threads for 5 sec 101 | /// bench 64 1 100000 default nodes -> search default positions for 100K nodes each 102 | /// bench 16 1 5 default perft -> run a perft 5 on default positions 103 | 104 | vector setup_bench(const Position& current, istream& is) { 105 | 106 | vector fens, list; 107 | string go, token; 108 | 109 | // Assign default values to missing arguments 110 | string ttSize = (is >> token) ? token : "16"; 111 | string threads = (is >> token) ? token : "1"; 112 | string limit = (is >> token) ? token : "13"; 113 | string fenFile = (is >> token) ? token : "default"; 114 | string limitType = (is >> token) ? token : "depth"; 115 | 116 | go = "go " + limitType + " " + limit; 117 | 118 | if (fenFile == "default") 119 | fens = Defaults; 120 | 121 | else if (fenFile == "current") 122 | fens.push_back(current.fen()); 123 | 124 | else 125 | { 126 | string fen; 127 | ifstream file(fenFile); 128 | 129 | if (!file.is_open()) 130 | { 131 | cerr << "Unable to open file " << fenFile << endl; 132 | exit(EXIT_FAILURE); 133 | } 134 | 135 | while (getline(file, fen)) 136 | if (!fen.empty()) 137 | fens.push_back(fen); 138 | 139 | file.close(); 140 | } 141 | 142 | list.emplace_back("ucinewgame"); 143 | list.emplace_back("setoption name Threads value " + threads); 144 | list.emplace_back("setoption name Hash value " + ttSize); 145 | 146 | for (const string& fen : fens) 147 | if (fen.find("setoption") != string::npos) 148 | list.emplace_back(fen); 149 | else 150 | { 151 | list.emplace_back("position fen " + fen); 152 | list.emplace_back(go); 153 | } 154 | 155 | return list; 156 | } 157 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 25 | #include 26 | #include 27 | 28 | #include "movegen.h" 29 | #include "position.h" 30 | #include "types.h" 31 | 32 | /// StatsEntry stores the stat table value. It is usually a number but could 33 | /// be a move or even a nested history. We use a class instead of naked value 34 | /// to directly call history update operator<<() on the entry so to use stats 35 | /// tables at caller sites as simple multi-dim arrays. 36 | template 37 | class StatsEntry { 38 | 39 | T entry; 40 | 41 | public: 42 | void operator=(const T& v) { entry = v; } 43 | T* operator&() { return &entry; } 44 | T* operator->() { return &entry; } 45 | operator const T&() const { return entry; } 46 | 47 | void operator<<(int bonus) { 48 | assert(abs(bonus) <= D); // Ensure range is [-D, D] 49 | static_assert(D <= std::numeric_limits::max(), "D overflows T"); 50 | 51 | entry += bonus - entry * abs(bonus) / D; 52 | 53 | assert(abs(entry) <= D); 54 | } 55 | }; 56 | 57 | /// Stats is a generic N-dimensional array used to store various statistics. 58 | /// The first template parameter T is the base type of the array, the second 59 | /// template parameter D limits the range of updates in [-D, D] when we update 60 | /// values with the << operator, while the last parameters (Size and Sizes) 61 | /// encode the dimensions of the array. 62 | template 63 | struct Stats : public std::array, Size> 64 | { 65 | typedef Stats stats; 66 | 67 | void fill(const T& v) { 68 | 69 | // For standard-layout 'this' points to first struct member 70 | assert(std::is_standard_layout::value); 71 | 72 | typedef StatsEntry entry; 73 | entry* p = reinterpret_cast(this); 74 | std::fill(p, p + sizeof(*this) / sizeof(entry), v); 75 | } 76 | }; 77 | 78 | template 79 | struct Stats : public std::array, Size> {}; 80 | 81 | /// In stats table, D=0 means that the template parameter is not used 82 | enum StatsParams { NOT_USED = 0 }; 83 | 84 | 85 | /// ButterflyHistory records how often quiet moves have been successful or 86 | /// unsuccessful during the current search, and is used for reduction and move 87 | /// ordering decisions. It uses 2 tables (one for each color) indexed by 88 | /// the move's from and to squares, see chessprogramming.wikispaces.com/Butterfly+Boards 89 | typedef Stats ButterflyHistory; 90 | 91 | /// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous 92 | /// move, see chessprogramming.wikispaces.com/Countermove+Heuristic 93 | typedef Stats CounterMoveHistory; 94 | 95 | /// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type] 96 | typedef Stats CapturePieceToHistory; 97 | 98 | /// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to] 99 | typedef Stats PieceToHistory; 100 | 101 | /// ContinuationHistory is the combined history of a given pair of moves, usually 102 | /// the current one given a previous one. The nested history table is based on 103 | /// PieceToHistory instead of ButterflyBoards. 104 | typedef Stats ContinuationHistory; 105 | 106 | 107 | /// MovePicker class is used to pick one pseudo legal move at a time from the 108 | /// current position. The most important method is next_move(), which returns a 109 | /// new pseudo legal move each time it is called, until there are no moves left, 110 | /// when MOVE_NONE is returned. In order to improve the efficiency of the alpha 111 | /// beta algorithm, MovePicker attempts to return the moves which are most likely 112 | /// to get a cut-off first. 113 | class MovePicker { 114 | 115 | enum PickType { Next, Best }; 116 | 117 | public: 118 | MovePicker(const MovePicker&) = delete; 119 | MovePicker& operator=(const MovePicker&) = delete; 120 | MovePicker(const Position&, Move, Value, const CapturePieceToHistory*); 121 | MovePicker(const Position&, Move, Depth, const ButterflyHistory*, 122 | const CapturePieceToHistory*, 123 | const PieceToHistory**, 124 | Square); 125 | MovePicker(const Position&, Move, Depth, const ButterflyHistory*, 126 | const CapturePieceToHistory*, 127 | const PieceToHistory**, 128 | Move, 129 | Move*); 130 | Move next_move(bool skipQuiets = false); 131 | 132 | private: 133 | template Move select(Pred); 134 | template void score(); 135 | ExtMove* begin() { return cur; } 136 | ExtMove* end() { return endMoves; } 137 | 138 | const Position& pos; 139 | const ButterflyHistory* mainHistory; 140 | const CapturePieceToHistory* captureHistory; 141 | const PieceToHistory** continuationHistory; 142 | Move ttMove; 143 | ExtMove refutations[3], *cur, *endMoves, *endBadCaptures; 144 | int stage; 145 | Move move; 146 | Square recaptureSquare; 147 | Value threshold; 148 | Depth depth; 149 | ExtMove moves[MAX_MOVES]; 150 | }; 151 | 152 | #endif // #ifndef MOVEPICK_H_INCLUDED 153 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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& o) { Threads.set(o); } 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 | // at most 2^32 clusters. 59 | constexpr int MaxHashMB = Is64Bit ? 131072 : 2048; 60 | 61 | o["Debug Log File"] << Option("", on_logger); 62 | o["Contempt"] << Option(24, -100, 100); 63 | o["Analysis Contempt"] << Option("Both var Off var White var Black var Both", "Both"); 64 | o["Threads"] << Option(1, 1, 512, on_threads); 65 | o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size); 66 | o["Clear Hash"] << Option(on_clear_hash); 67 | o["Ponder"] << Option(false); 68 | o["MultiPV"] << Option(1, 1, 500); 69 | o["Skill Level"] << Option(20, 0, 20); 70 | o["Move Overhead"] << Option(30, 0, 5000); 71 | o["Minimum Thinking Time"] << Option(20, 0, 5000); 72 | o["Slow Mover"] << Option(84, 10, 1000); 73 | o["nodestime"] << Option(0, 0, 10000); 74 | o["UCI_Chess960"] << Option(false); 75 | o["UCI_AnalyseMode"] << Option(false); 76 | o["SyzygyPath"] << Option("", on_tb_path); 77 | o["SyzygyProbeDepth"] << Option(1, 1, 100); 78 | o["Syzygy50MoveRule"] << Option(true); 79 | o["SyzygyProbeLimit"] << Option(7, 0, 7); 80 | } 81 | 82 | 83 | /// operator<<() is used to print all the options default values in chronological 84 | /// insertion order (the idx field) and in the format defined by the UCI protocol. 85 | 86 | std::ostream& operator<<(std::ostream& os, const OptionsMap& om) { 87 | 88 | for (size_t idx = 0; idx < om.size(); ++idx) 89 | for (const auto& it : om) 90 | if (it.second.idx == idx) 91 | { 92 | const Option& o = it.second; 93 | os << "\noption name " << it.first << " type " << o.type; 94 | 95 | if (o.type == "string" || o.type == "check" || o.type == "combo") 96 | os << " default " << o.defaultValue; 97 | 98 | if (o.type == "spin") 99 | os << " default " << int(stof(o.defaultValue)) 100 | << " min " << o.min 101 | << " max " << o.max; 102 | 103 | break; 104 | } 105 | 106 | return os; 107 | } 108 | 109 | 110 | /// Option class constructors and conversion operators 111 | 112 | Option::Option(const char* v, OnChange f) : type("string"), min(0), max(0), on_change(f) 113 | { defaultValue = currentValue = v; } 114 | 115 | Option::Option(bool v, OnChange f) : type("check"), min(0), max(0), on_change(f) 116 | { defaultValue = currentValue = (v ? "true" : "false"); } 117 | 118 | Option::Option(OnChange f) : type("button"), min(0), max(0), on_change(f) 119 | {} 120 | 121 | Option::Option(double v, int minv, int maxv, OnChange f) : type("spin"), min(minv), max(maxv), on_change(f) 122 | { defaultValue = currentValue = std::to_string(v); } 123 | 124 | Option::Option(const char* v, const char* cur, OnChange f) : type("combo"), min(0), max(0), on_change(f) 125 | { defaultValue = v; currentValue = cur; } 126 | 127 | Option::operator double() const { 128 | assert(type == "check" || type == "spin"); 129 | return (type == "spin" ? stof(currentValue) : currentValue == "true"); 130 | } 131 | 132 | Option::operator std::string() const { 133 | assert(type == "string"); 134 | return currentValue; 135 | } 136 | 137 | bool Option::operator==(const char* s) const { 138 | assert(type == "combo"); 139 | return !CaseInsensitiveLess()(currentValue, s) 140 | && !CaseInsensitiveLess()(s, currentValue); 141 | } 142 | 143 | 144 | /// operator<<() inits options and assigns idx in the correct printing order 145 | 146 | void Option::operator<<(const Option& o) { 147 | 148 | static size_t insert_order = 0; 149 | 150 | *this = o; 151 | idx = insert_order++; 152 | } 153 | 154 | 155 | /// operator=() updates currentValue and triggers on_change() action. It's up to 156 | /// the GUI to check for option's limits, but we could receive the new value from 157 | /// the user by console window, so let's check the bounds anyway. 158 | 159 | Option& Option::operator=(const string& v) { 160 | 161 | assert(!type.empty()); 162 | 163 | if ( (type != "button" && v.empty()) 164 | || (type == "check" && v != "true" && v != "false") 165 | || (type == "spin" && (stof(v) < min || stof(v) > max))) 166 | return *this; 167 | 168 | if (type != "button") 169 | currentValue = v; 170 | 171 | if (on_change) 172 | on_change(*this); 173 | 174 | return *this; 175 | } 176 | 177 | } // namespace UCI 178 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | #include "syzygy/tbprobe.h" 29 | #include "tt.h" 30 | 31 | ThreadPool Threads; // Global object 32 | 33 | 34 | /// Thread constructor launches the thread and waits until it goes to sleep 35 | /// in idle_loop(). Note that 'searching' and 'exit' should be alredy set. 36 | 37 | Thread::Thread(size_t n) : idx(n), stdThread(&Thread::idle_loop, this) { 38 | 39 | wait_for_search_finished(); 40 | } 41 | 42 | 43 | /// Thread destructor wakes up the thread in idle_loop() and waits 44 | /// for its termination. Thread should be already waiting. 45 | 46 | Thread::~Thread() { 47 | 48 | assert(!searching); 49 | 50 | exit = true; 51 | start_searching(); 52 | stdThread.join(); 53 | } 54 | 55 | 56 | /// Thread::clear() reset histories, usually before a new game 57 | 58 | void Thread::clear() { 59 | 60 | counterMoves.fill(MOVE_NONE); 61 | mainHistory.fill(0); 62 | captureHistory.fill(0); 63 | 64 | for (auto& to : continuationHistory) 65 | for (auto& h : to) 66 | h->fill(0); 67 | 68 | continuationHistory[NO_PIECE][0]->fill(Search::CounterMovePruneThreshold - 1); 69 | } 70 | 71 | /// Thread::start_searching() wakes up the thread that will start the search 72 | 73 | void Thread::start_searching() { 74 | 75 | std::lock_guard lk(mutex); 76 | searching = true; 77 | cv.notify_one(); // Wake up the thread in idle_loop() 78 | } 79 | 80 | 81 | /// Thread::wait_for_search_finished() blocks on the condition variable 82 | /// until the thread has finished searching. 83 | 84 | void Thread::wait_for_search_finished() { 85 | 86 | std::unique_lock lk(mutex); 87 | cv.wait(lk, [&]{ return !searching; }); 88 | } 89 | 90 | 91 | /// Thread::idle_loop() is where the thread is parked, blocked on the 92 | /// condition variable, when it has no work to do. 93 | 94 | void Thread::idle_loop() { 95 | 96 | // If OS already scheduled us on a different group than 0 then don't overwrite 97 | // the choice, eventually we are one of many one-threaded processes running on 98 | // some Windows NUMA hardware, for instance in fishtest. To make it simple, 99 | // just check if running threads are below a threshold, in this case all this 100 | // NUMA machinery is not needed. 101 | if (Options["Threads"] > 8) 102 | WinProcGroup::bindThisThread(idx); 103 | 104 | while (true) 105 | { 106 | std::unique_lock lk(mutex); 107 | searching = false; 108 | cv.notify_one(); // Wake up anyone waiting for search finished 109 | cv.wait(lk, [&]{ return searching; }); 110 | 111 | if (exit) 112 | return; 113 | 114 | lk.unlock(); 115 | 116 | search(); 117 | } 118 | } 119 | 120 | /// ThreadPool::set() creates/destroys threads to match the requested number. 121 | /// Created and launched threads will go immediately to sleep in idle_loop. 122 | /// Upon resizing, threads are recreated to allow for binding if necessary. 123 | 124 | void ThreadPool::set(size_t requested) { 125 | 126 | if (size() > 0) { // destroy any existing thread(s) 127 | main()->wait_for_search_finished(); 128 | 129 | while (size() > 0) 130 | delete back(), pop_back(); 131 | } 132 | 133 | if (requested > 0) { // create new thread(s) 134 | push_back(new MainThread(0)); 135 | 136 | while (size() < requested) 137 | push_back(new Thread(size())); 138 | clear(); 139 | } 140 | 141 | // Reallocate the hash with the new threadpool size 142 | TT.resize(Options["Hash"]); 143 | } 144 | 145 | /// ThreadPool::clear() sets threadPool data to initial values. 146 | 147 | void ThreadPool::clear() { 148 | 149 | for (Thread* th : *this) 150 | th->clear(); 151 | 152 | main()->callsCnt = 0; 153 | main()->previousScore = VALUE_INFINITE; 154 | main()->previousTimeReduction = 1.0; 155 | } 156 | 157 | /// ThreadPool::start_thinking() wakes up main thread waiting in idle_loop() and 158 | /// returns immediately. Main thread will wake up other threads and start the search. 159 | 160 | void ThreadPool::start_thinking(Position& pos, StateListPtr& states, 161 | const Search::LimitsType& limits, bool ponderMode) { 162 | 163 | main()->wait_for_search_finished(); 164 | 165 | stopOnPonderhit = stop = false; 166 | ponder = ponderMode; 167 | Search::Limits = limits; 168 | Search::RootMoves rootMoves; 169 | 170 | for (const auto& m : MoveList(pos)) 171 | if ( limits.searchmoves.empty() 172 | || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m)) 173 | rootMoves.emplace_back(m); 174 | 175 | if (!rootMoves.empty()) 176 | Tablebases::rank_root_moves(pos, rootMoves); 177 | 178 | // After ownership transfer 'states' becomes empty, so if we stop the search 179 | // and call 'go' again without setting a new position states.get() == NULL. 180 | assert(states.get() || setupStates.get()); 181 | 182 | if (states.get()) 183 | setupStates = std::move(states); // Ownership transfer, states is now empty 184 | 185 | // We use Position::set() to set root position across threads. But there are 186 | // some StateInfo fields (previous, pliesFromNull, capturedPiece) that cannot 187 | // be deduced from a fen string, so set() clears them and to not lose the info 188 | // we need to backup and later restore setupStates->back(). Note that setupStates 189 | // is shared by threads but is accessed in read-only mode. 190 | StateInfo tmp = setupStates->back(); 191 | 192 | for (Thread* th : *this) 193 | { 194 | th->nodes = th->tbHits = th->nmpMinPly = 0; 195 | th->rootDepth = th->completedDepth = DEPTH_ZERO; 196 | th->rootMoves = rootMoves; 197 | th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th); 198 | } 199 | 200 | setupStates->back() = tmp; 201 | 202 | main()->start_searching(); 203 | } 204 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | constexpr 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(RANK_7 - ((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 && (PawnAttacks[WHITE][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 + NORTH 127 | && ( distance(ksq[~us], psq + NORTH) > 1 128 | || (PseudoAttacks[KING][ksq[us]] & (psq + NORTH)))) 129 | result = WIN; 130 | 131 | // Immediate draw if it is a stalemate or a king captures undefended pawn 132 | else if ( us == BLACK 133 | && ( !(PseudoAttacks[KING][ksq[us]] & ~(PseudoAttacks[KING][ksq[~us]] | PawnAttacks[~us][psq])) 134 | || (PseudoAttacks[KING][ksq[us]] & psq & ~PseudoAttacks[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 | constexpr Color Them = (Us == WHITE ? BLACK : WHITE); 156 | constexpr Result Good = (Us == WHITE ? WIN : DRAW); 157 | constexpr Result Bad = (Us == WHITE ? DRAW : WIN); 158 | 159 | Result r = INVALID; 160 | Bitboard b = PseudoAttacks[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 + NORTH)]; 170 | 171 | if ( rank_of(psq) == RANK_2 // Double push 172 | && psq + NORTH != ksq[Us] 173 | && psq + NORTH != ksq[Them]) 174 | r |= db[index(Them, ksq[Them], ksq[Us], psq + NORTH + NORTH)]; 175 | } 176 | 177 | return result = r & Good ? Good : r & UNKNOWN ? UNKNOWN : Bad; 178 | } 179 | 180 | } // namespace 181 | -------------------------------------------------------------------------------- /stockfish-10-win/Top CPU Contributors.txt: -------------------------------------------------------------------------------- 1 | Contributors with >10,000 CPU hours as of November 4, 2018 2 | Thank you! 3 | 4 | Username CPU Hours Games played 5 | noobpwnftw 3730975 292309380 6 | mibere 535242 43333774 7 | crunchy 375564 29121434 8 | cw 371664 28748719 9 | fastgm 318178 22283584 10 | JojoM 295354 20958931 11 | dew 215476 17079219 12 | ctoks 214031 17312035 13 | glinscott 204517 13932027 14 | bking_US 187568 12233168 15 | velislav 168404 13336219 16 | CSU_Dynasty 168069 14417712 17 | Thanar 162373 13842179 18 | spams 149531 10940322 19 | Fisherman 141137 12099359 20 | drabel 134441 11180178 21 | leszek 133658 9812120 22 | marrco 133566 10115202 23 | sqrt2 128420 10022279 24 | vdbergh 123230 9200516 25 | tvijlbrief 123007 9498831 26 | vdv 120381 8555423 27 | malala 117291 8126488 28 | dsmith 114010 7622414 29 | BrunoBanani 104938 7448565 30 | CoffeeOne 100042 4593596 31 | Data 94621 8433010 32 | mgrabiak 92248 7787406 33 | bcross 89440 8506568 34 | brabos 81868 6647613 35 | BRAVONE 80811 5341681 36 | psk 77195 6156031 37 | nordlandia 74833 6231930 38 | robal 72818 5969856 39 | TueRens 72523 6383294 40 | sterni1971 71049 5647590 41 | sunu 65855 5360884 42 | mhoram 65034 5192880 43 | davar 64794 5457564 44 | nssy 64607 5371952 45 | Pking_cda 64499 5704075 46 | biffhero 63557 5480444 47 | teddybaer 62147 5585620 48 | solarlight 61278 5402642 49 | ElbertoOne 60156 5504304 50 | jromang 58854 4704502 51 | dv8silencer 57421 3961325 52 | tinker 56039 4204914 53 | Freja 50331 3808121 54 | renouve 50318 3544864 55 | robnjr 47504 4131742 56 | grandphish2 47377 4110003 57 | eva42 46857 4075716 58 | ttruscott 46802 3811534 59 | finfish 46244 3481661 60 | rap 46201 3219490 61 | ronaldjerum 45641 3964331 62 | xoto 44998 4170431 63 | gvreuls 44359 3902234 64 | bigpen0r 41780 3448224 65 | Bobo1239 40767 3657490 66 | Antihistamine 39218 2792761 67 | mhunt 38991 2697512 68 | racerschmacer 38929 3756111 69 | VoyagerOne 35896 3378887 70 | homyur 35561 3012398 71 | rkl 33217 2978536 72 | pb00067 33034 2803485 73 | speedycpu 32043 2531964 74 | SC 31954 2848432 75 | EthanOConnor 31638 2143255 76 | oryx 30962 2899534 77 | gri 30108 2429137 78 | csnodgrass 29396 2808611 79 | Garf 28887 2873564 80 | Pyafue 28885 1986098 81 | jkiiski 28014 1923255 82 | slakovv 27017 2031279 83 | Prcuvu 26300 2307154 84 | hyperbolic.tom 26248 2200777 85 | jbwiebe 25663 2129063 86 | anst 25525 2279159 87 | Patrick_G 24222 1835674 88 | nabildanial 23524 1586321 89 | achambord 23495 1942546 90 | Sharaf_DG 22975 1790697 91 | chriswk 22876 1947731 92 | ncfish1 22689 1830009 93 | cuistot 22201 1383031 94 | Zirie 21171 1493227 95 | Isidor 20634 1736219 96 | JanErik 20596 1791991 97 | xor12 20535 1819280 98 | team-oh 20364 1653708 99 | nesoneg 20264 1493435 100 | dex 20110 1682756 101 | rstoesser 19802 1335177 102 | Vizvezdenec 19750 1695579 103 | eastorwest 19531 1841839 104 | sg4032 18913 1720157 105 | horst.prack 18425 1708197 106 | cisco2015 18408 1793774 107 | ianh2105 18133 1668562 108 | MazeOfGalious 18022 1644593 109 | ville 17900 1539130 110 | j3corre 17607 975954 111 | eudhan 17502 1424648 112 | jmdana 17351 1287546 113 | iisiraider 17175 1118788 114 | jundery 17172 1115855 115 | wei 16852 1822582 116 | SFTUser 16635 1363975 117 | purplefishies 16621 1106850 118 | DragonLord 16599 1252348 119 | chris 15274 1575333 120 | IgorLeMasson 15201 1364148 121 | dju 15074 914278 122 | Flopzee 14700 1331632 123 | OssumOpossum 14149 1029265 124 | enedene 13762 935618 125 | ako027ako 13442 1250249 126 | AdrianSA 13324 924980 127 | bpfliegel 13318 886523 128 | Nikolay.IT 13260 1155612 129 | jpulman 12776 854815 130 | joster 12438 988413 131 | fatmurphy 12015 901134 132 | Nesa92 11711 1132245 133 | Adrian.Schmidt123 11542 898699 134 | modolief 11228 926456 135 | Dark_wizzie 11214 1017910 136 | mschmidt 10973 818594 137 | Andrew Grant 10780 947859 138 | infinity 10762 746397 139 | SapphireBrand 10692 1024604 140 | Thomas A. Anderson 10553 736094 141 | basepi 10434 935168 142 | lantonov 10325 972610 143 | pgontarz 10294 878746 144 | Spprtr 10189 823246 145 | crocogoat 10115 1017325 146 | stocky 10083 718114 -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | constexpr int QuadraticOurs[][PIECE_TYPE_NB] = { 35 | // OUR PIECES 36 | // pair pawn knight bishop rook queen 37 | {1438 }, // Bishop pair 38 | { 40, 38 }, // Pawn 39 | { 32, 255, -62 }, // Knight OUR PIECES 40 | { 0, 104, 4, 0 }, // Bishop 41 | { -26, -2, 47, 105, -208 }, // Rook 42 | {-189, 24, 117, 133, -134, -6 } // Queen 43 | }; 44 | 45 | constexpr int QuadraticTheirs[][PIECE_TYPE_NB] = { 46 | // THEIR PIECES 47 | // pair pawn knight bishop rook queen 48 | { 0 }, // Bishop pair 49 | { 36, 0 }, // Pawn 50 | { 9, 63, 0 }, // Knight OUR PIECES 51 | { 59, 65, 42, 0 }, // Bishop 52 | { 46, 39, 24, -24, 0 }, // Rook 53 | { 97, 100, -42, 137, 268, 0 } // Queen 54 | }; 55 | 56 | // Endgame evaluation and scaling functions are accessed directly and not through 57 | // the function maps because they correspond to more than one material hash key. 58 | Endgame EvaluateKXK[] = { Endgame(WHITE), Endgame(BLACK) }; 59 | 60 | Endgame ScaleKBPsK[] = { Endgame(WHITE), Endgame(BLACK) }; 61 | Endgame ScaleKQKRPs[] = { Endgame(WHITE), Endgame(BLACK) }; 62 | Endgame ScaleKPsK[] = { Endgame(WHITE), Endgame(BLACK) }; 63 | Endgame ScaleKPKP[] = { Endgame(WHITE), Endgame(BLACK) }; 64 | 65 | // Helper used to detect a given material distribution 66 | bool is_KXK(const Position& pos, Color us) { 67 | return !more_than_one(pos.pieces(~us)) 68 | && pos.non_pawn_material(us) >= RookValueMg; 69 | } 70 | 71 | bool is_KBPsK(const Position& pos, Color us) { 72 | return pos.non_pawn_material(us) == BishopValueMg 73 | && pos.count(us) == 1 74 | && pos.count(us) >= 1; 75 | } 76 | 77 | bool is_KQKRPs(const Position& pos, Color us) { 78 | return !pos.count(us) 79 | && pos.non_pawn_material(us) == QueenValueMg 80 | && pos.count(us) == 1 81 | && pos.count(~us) == 1 82 | && pos.count(~us) >= 1; 83 | } 84 | 85 | /// imbalance() calculates the imbalance by comparing the piece count of each 86 | /// piece type for both colors. 87 | template 88 | int imbalance(const int pieceCount[][PIECE_TYPE_NB]) { 89 | 90 | constexpr Color Them = (Us == WHITE ? BLACK : WHITE); 91 | 92 | int bonus = 0; 93 | 94 | // Second-degree polynomial material imbalance, by Tord Romstad 95 | for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1) 96 | { 97 | if (!pieceCount[Us][pt1]) 98 | continue; 99 | 100 | int v = 0; 101 | 102 | for (int pt2 = NO_PIECE_TYPE; pt2 <= pt1; ++pt2) 103 | v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2] 104 | + QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2]; 105 | 106 | bonus += pieceCount[Us][pt1] * v; 107 | } 108 | 109 | return bonus; 110 | } 111 | 112 | } // namespace 113 | 114 | namespace Material { 115 | 116 | /// Material::probe() looks up the current position's material configuration in 117 | /// the material hash table. It returns a pointer to the Entry if the position 118 | /// is found. Otherwise a new Entry is computed and stored there, so we don't 119 | /// have to recompute all when the same material configuration occurs again. 120 | 121 | Entry* probe(const Position& pos) { 122 | 123 | Key key = pos.material_key(); 124 | Entry* e = pos.this_thread()->materialTable[key]; 125 | 126 | if (e->key == key) 127 | return e; 128 | 129 | std::memset(e, 0, sizeof(Entry)); 130 | e->key = key; 131 | e->factor[WHITE] = e->factor[BLACK] = (uint8_t)SCALE_FACTOR_NORMAL; 132 | 133 | Value npm_w = pos.non_pawn_material(WHITE); 134 | Value npm_b = pos.non_pawn_material(BLACK); 135 | Value npm = std::max(EndgameLimit, std::min(npm_w + npm_b, MidgameLimit)); 136 | 137 | // Map total non-pawn material into [PHASE_ENDGAME, PHASE_MIDGAME] 138 | e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit)); 139 | 140 | // Let's look if we have a specialized evaluation function for this particular 141 | // material configuration. Firstly we look for a fixed configuration one, then 142 | // for a generic one if the previous search failed. 143 | if ((e->evaluationFunction = pos.this_thread()->endgames.probe(key)) != nullptr) 144 | return e; 145 | 146 | for (Color c = WHITE; c <= BLACK; ++c) 147 | if (is_KXK(pos, c)) 148 | { 149 | e->evaluationFunction = &EvaluateKXK[c]; 150 | return e; 151 | } 152 | 153 | // OK, we didn't find any special evaluation function for the current material 154 | // configuration. Is there a suitable specialized scaling function? 155 | const EndgameBase* sf; 156 | 157 | if ((sf = pos.this_thread()->endgames.probe(key)) != nullptr) 158 | { 159 | e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned 160 | return e; 161 | } 162 | 163 | // We didn't find any specialized scaling function, so fall back on generic 164 | // ones that refer to more than one material distribution. Note that in this 165 | // case we don't return after setting the function. 166 | for (Color c = WHITE; c <= BLACK; ++c) 167 | { 168 | if (is_KBPsK(pos, c)) 169 | e->scalingFunction[c] = &ScaleKBPsK[c]; 170 | 171 | else if (is_KQKRPs(pos, c)) 172 | e->scalingFunction[c] = &ScaleKQKRPs[c]; 173 | } 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 | // Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder 210 | // for the bishop pair "extended piece", which allows us to be more flexible 211 | // in defining bishop pair bonuses. 212 | const int pieceCount[COLOR_NB][PIECE_TYPE_NB] = { 213 | { pos.count(WHITE) > 1, pos.count(WHITE), pos.count(WHITE), 214 | pos.count(WHITE) , pos.count(WHITE), pos.count(WHITE) }, 215 | { pos.count(BLACK) > 1, pos.count(BLACK), pos.count(BLACK), 216 | pos.count(BLACK) , pos.count(BLACK), pos.count(BLACK) } }; 217 | 218 | e->value = int16_t((imbalance(pieceCount) - imbalance(pieceCount)) / 16); 219 | return e; 220 | } 221 | 222 | } // namespace Material 223 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | 25 | namespace { 26 | 27 | enum Stages { 28 | MAIN_TT, CAPTURE_INIT, GOOD_CAPTURE, REFUTATION, QUIET_INIT, QUIET, BAD_CAPTURE, 29 | EVASION_TT, EVASION_INIT, EVASION, 30 | PROBCUT_TT, PROBCUT_INIT, PROBCUT, 31 | QSEARCH_TT, QCAPTURE_INIT, QCAPTURE, QCHECK_INIT, QCHECK 32 | }; 33 | 34 | // Helper filter used with select() 35 | const auto Any = [](){ return true; }; 36 | 37 | // partial_insertion_sort() sorts moves in descending order up to and including 38 | // a given limit. The order of moves smaller than the limit is left unspecified. 39 | void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit) { 40 | 41 | for (ExtMove *sortedEnd = begin, *p = begin + 1; p < end; ++p) 42 | if (p->value >= limit) 43 | { 44 | ExtMove tmp = *p, *q; 45 | *p = *++sortedEnd; 46 | for (q = sortedEnd; q != begin && *(q - 1) < tmp; --q) 47 | *q = *(q - 1); 48 | *q = tmp; 49 | } 50 | } 51 | 52 | } // namespace 53 | 54 | 55 | /// Constructors of the MovePicker class. As arguments we pass information 56 | /// to help it to return the (presumably) good moves first, to decide which 57 | /// moves to return (in the quiescence search, for instance, we only want to 58 | /// search captures, promotions, and some checks) and how important good move 59 | /// ordering is at the current node. 60 | 61 | /// MovePicker constructor for the main search 62 | MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, 63 | const CapturePieceToHistory* cph, const PieceToHistory** ch, Move cm, Move* killers) 64 | : pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), 65 | refutations{{killers[0], 0}, {killers[1], 0}, {cm, 0}}, depth(d) { 66 | 67 | assert(d > DEPTH_ZERO); 68 | 69 | stage = pos.checkers() ? EVASION_TT : MAIN_TT; 70 | ttMove = ttm && pos.pseudo_legal(ttm) ? ttm : MOVE_NONE; 71 | stage += (ttMove == MOVE_NONE); 72 | } 73 | 74 | /// MovePicker constructor for quiescence search 75 | MovePicker::MovePicker(const Position& p, Move ttm, Depth d, const ButterflyHistory* mh, 76 | const CapturePieceToHistory* cph, const PieceToHistory** ch, Square rs) 77 | : pos(p), mainHistory(mh), captureHistory(cph), continuationHistory(ch), recaptureSquare(rs), depth(d) { 78 | 79 | assert(d <= DEPTH_ZERO); 80 | 81 | stage = pos.checkers() ? EVASION_TT : QSEARCH_TT; 82 | ttMove = ttm 83 | && pos.pseudo_legal(ttm) 84 | && (depth > DEPTH_QS_RECAPTURES || to_sq(ttm) == recaptureSquare) ? ttm : MOVE_NONE; 85 | stage += (ttMove == MOVE_NONE); 86 | } 87 | 88 | /// MovePicker constructor for ProbCut: we generate captures with SEE greater 89 | /// than or equal to the given threshold. 90 | MovePicker::MovePicker(const Position& p, Move ttm, Value th, const CapturePieceToHistory* cph) 91 | : pos(p), captureHistory(cph), threshold(th) { 92 | 93 | assert(!pos.checkers()); 94 | 95 | stage = PROBCUT_TT; 96 | ttMove = ttm 97 | && pos.pseudo_legal(ttm) 98 | && pos.capture(ttm) 99 | && pos.see_ge(ttm, threshold) ? ttm : MOVE_NONE; 100 | stage += (ttMove == MOVE_NONE); 101 | } 102 | 103 | /// MovePicker::score() assigns a numerical value to each move in a list, used 104 | /// for sorting. Captures are ordered by Most Valuable Victim (MVV), preferring 105 | /// captures with a good history. Quiets moves are ordered using the histories. 106 | template 107 | void MovePicker::score() { 108 | 109 | static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type"); 110 | 111 | for (auto& m : *this) 112 | if (Type == CAPTURES) 113 | m.value = PieceValue[MG][pos.piece_on(to_sq(m))] 114 | + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))] / 8; 115 | 116 | else if (Type == QUIETS) 117 | m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] 118 | + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] 119 | + (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)] 120 | + (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]; 121 | 122 | else // Type == EVASIONS 123 | { 124 | if (pos.capture(m)) 125 | m.value = PieceValue[MG][pos.piece_on(to_sq(m))] 126 | - Value(type_of(pos.moved_piece(m))); 127 | else 128 | m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] 129 | + (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)] 130 | - (1 << 28); 131 | } 132 | } 133 | 134 | /// MovePicker::select() returns the next move satisfying a predicate function. 135 | /// It never returns the TT move. 136 | template 137 | Move MovePicker::select(Pred filter) { 138 | 139 | while (cur < endMoves) 140 | { 141 | if (T == Best) 142 | std::swap(*cur, *std::max_element(cur, endMoves)); 143 | 144 | move = *cur++; 145 | 146 | if (move != ttMove && filter()) 147 | return move; 148 | } 149 | return move = MOVE_NONE; 150 | } 151 | 152 | /// MovePicker::next_move() is the most important method of the MovePicker class. It 153 | /// returns a new pseudo legal move every time it is called until there are no more 154 | /// moves left, picking the move with the highest score from a list of generated moves. 155 | Move MovePicker::next_move(bool skipQuiets) { 156 | 157 | top: 158 | switch (stage) { 159 | 160 | case MAIN_TT: 161 | case EVASION_TT: 162 | case QSEARCH_TT: 163 | case PROBCUT_TT: 164 | ++stage; 165 | return ttMove; 166 | 167 | case CAPTURE_INIT: 168 | case PROBCUT_INIT: 169 | case QCAPTURE_INIT: 170 | cur = endBadCaptures = moves; 171 | endMoves = generate(pos, cur); 172 | 173 | score(); 174 | ++stage; 175 | goto top; 176 | 177 | case GOOD_CAPTURE: 178 | if (select([&](){ 179 | return pos.see_ge(move, Value(-55 * (cur-1)->value / 1024)) ? 180 | // Move losing capture to endBadCaptures to be tried later 181 | true : (*endBadCaptures++ = move, false); })) 182 | return move; 183 | 184 | // Prepare the pointers to loop over the refutations array 185 | cur = std::begin(refutations); 186 | endMoves = std::end(refutations); 187 | 188 | // If the countermove is the same as a killer, skip it 189 | if ( refutations[0].move == refutations[2].move 190 | || refutations[1].move == refutations[2].move) 191 | --endMoves; 192 | 193 | ++stage; 194 | /* fallthrough */ 195 | 196 | case REFUTATION: 197 | if (select([&](){ return move != MOVE_NONE 198 | && !pos.capture(move) 199 | && pos.pseudo_legal(move); })) 200 | return move; 201 | ++stage; 202 | /* fallthrough */ 203 | 204 | case QUIET_INIT: 205 | cur = endBadCaptures; 206 | endMoves = generate(pos, cur); 207 | 208 | score(); 209 | partial_insertion_sort(cur, endMoves, -4000 * depth / ONE_PLY); 210 | ++stage; 211 | /* fallthrough */ 212 | 213 | case QUIET: 214 | if ( !skipQuiets 215 | && select([&](){return move != refutations[0] 216 | && move != refutations[1] 217 | && move != refutations[2];})) 218 | return move; 219 | 220 | // Prepare the pointers to loop over the bad captures 221 | cur = moves; 222 | endMoves = endBadCaptures; 223 | 224 | ++stage; 225 | /* fallthrough */ 226 | 227 | case BAD_CAPTURE: 228 | return select(Any); 229 | 230 | case EVASION_INIT: 231 | cur = moves; 232 | endMoves = generate(pos, cur); 233 | 234 | score(); 235 | ++stage; 236 | /* fallthrough */ 237 | 238 | case EVASION: 239 | return select(Any); 240 | 241 | case PROBCUT: 242 | return select([&](){ return pos.see_ge(move, threshold); }); 243 | 244 | case QCAPTURE: 245 | if (select([&](){ return depth > DEPTH_QS_RECAPTURES 246 | || to_sq(move) == recaptureSquare; })) 247 | return move; 248 | 249 | // If we did not find any move and we do not try checks, we have finished 250 | if (depth != DEPTH_QS_CHECKS) 251 | return MOVE_NONE; 252 | 253 | ++stage; 254 | /* fallthrough */ 255 | 256 | case QCHECK_INIT: 257 | cur = moves; 258 | endMoves = generate(pos, cur); 259 | 260 | ++stage; 261 | /* fallthrough */ 262 | 263 | case QCHECK: 264 | return select(Any); 265 | } 266 | 267 | assert(false); 268 | return MOVE_NONE; // Silence warning 269 | } 270 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | #ifdef _WIN32 22 | #if _WIN32_WINNT < 0x0601 23 | #undef _WIN32_WINNT 24 | #define _WIN32_WINNT 0x0601 // Force to include needed API prototypes 25 | #endif 26 | 27 | #ifndef NOMINMAX 28 | #define NOMINMAX 29 | #endif 30 | 31 | #include 32 | // The needed Windows API for processor groups could be missed from old Windows 33 | // versions, so instead of calling them directly (forcing the linker to resolve 34 | // the calls at compile time), try to load them at runtime. To do this we need 35 | // first to define the corresponding function pointers. 36 | extern "C" { 37 | typedef bool(*fun1_t)(LOGICAL_PROCESSOR_RELATIONSHIP, 38 | PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); 39 | typedef bool(*fun2_t)(USHORT, PGROUP_AFFINITY); 40 | typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY); 41 | } 42 | #endif 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | #include "misc.h" 51 | #include "thread.h" 52 | 53 | using namespace std; 54 | 55 | namespace { 56 | 57 | /// Version number. If Version is left empty, then compile date in the format 58 | /// DD-MM-YY and show in engine_info. 59 | const string Version = "10"; 60 | 61 | /// Our fancy logging facility. The trick here is to replace cin.rdbuf() and 62 | /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We 63 | /// can toggle the logging of std::cout and std:cin at runtime whilst preserving 64 | /// usual I/O functionality, all without changing a single line of code! 65 | /// Idea from http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81 66 | 67 | struct Tie: public streambuf { // MSVC requires split streambuf for cin and cout 68 | 69 | Tie(streambuf* b, streambuf* l) : buf(b), logBuf(l) {} 70 | 71 | int sync() override { return logBuf->pubsync(), buf->pubsync(); } 72 | int overflow(int c) override { return log(buf->sputc((char)c), "<< "); } 73 | int underflow() override { return buf->sgetc(); } 74 | int uflow() override { return log(buf->sbumpc(), ">> "); } 75 | 76 | streambuf *buf, *logBuf; 77 | 78 | int log(int c, const char* prefix) { 79 | 80 | static int last = '\n'; // Single log file 81 | 82 | if (last == '\n') 83 | logBuf->sputn(prefix, 3); 84 | 85 | return last = logBuf->sputc((char)c); 86 | } 87 | }; 88 | 89 | class Logger { 90 | 91 | Logger() : in(cin.rdbuf(), file.rdbuf()), out(cout.rdbuf(), file.rdbuf()) {} 92 | ~Logger() { start(""); } 93 | 94 | ofstream file; 95 | Tie in, out; 96 | 97 | public: 98 | static void start(const std::string& fname) { 99 | 100 | static Logger l; 101 | 102 | if (!fname.empty() && !l.file.is_open()) 103 | { 104 | l.file.open(fname, ifstream::out); 105 | cin.rdbuf(&l.in); 106 | cout.rdbuf(&l.out); 107 | } 108 | else if (fname.empty() && l.file.is_open()) 109 | { 110 | cout.rdbuf(l.out.buf); 111 | cin.rdbuf(l.in.buf); 112 | l.file.close(); 113 | } 114 | } 115 | }; 116 | 117 | } // namespace 118 | 119 | /// engine_info() returns the full name of the current Stockfish version. This 120 | /// will be either "Stockfish DD-MM-YY" (where DD-MM-YY is the date when 121 | /// the program was compiled) or "Stockfish ", depending on whether 122 | /// Version is empty. 123 | 124 | const string engine_info(bool to_uci) { 125 | 126 | const string months("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"); 127 | string month, day, year; 128 | stringstream ss, date(__DATE__); // From compiler, format is "Sep 21 2008" 129 | 130 | ss << "Stockfish " << Version << setfill('0'); 131 | 132 | if (Version.empty()) 133 | { 134 | date >> month >> day >> year; 135 | ss << setw(2) << day << setw(2) << (1 + months.find(month) / 4) << year.substr(2); 136 | } 137 | 138 | ss << (Is64Bit ? " 64" : "") 139 | << (HasPext ? " BMI2" : (HasPopCnt ? " POPCNT" : "")) 140 | << (to_uci ? "\nid author ": " by ") 141 | << "T. Romstad, M. Costalba, J. Kiiski, G. Linscott"; 142 | 143 | return ss.str(); 144 | } 145 | 146 | 147 | /// Debug functions used mainly to collect run-time statistics 148 | static int64_t hits[2], means[2]; 149 | 150 | void dbg_hit_on(bool b) { ++hits[0]; if (b) ++hits[1]; } 151 | void dbg_hit_on(bool c, bool b) { if (c) dbg_hit_on(b); } 152 | void dbg_mean_of(int v) { ++means[0]; means[1] += v; } 153 | 154 | void dbg_print() { 155 | 156 | if (hits[0]) 157 | cerr << "Total " << hits[0] << " Hits " << hits[1] 158 | << " hit rate (%) " << 100 * hits[1] / hits[0] << endl; 159 | 160 | if (means[0]) 161 | cerr << "Total " << means[0] << " Mean " 162 | << (double)means[1] / means[0] << endl; 163 | } 164 | 165 | 166 | /// Used to serialize access to std::cout to avoid multiple threads writing at 167 | /// the same time. 168 | 169 | std::ostream& operator<<(std::ostream& os, SyncCout sc) { 170 | 171 | static Mutex m; 172 | 173 | if (sc == IO_LOCK) 174 | m.lock(); 175 | 176 | if (sc == IO_UNLOCK) 177 | m.unlock(); 178 | 179 | return os; 180 | } 181 | 182 | 183 | /// Trampoline helper to avoid moving Logger to misc.h 184 | void start_logger(const std::string& fname) { Logger::start(fname); } 185 | 186 | 187 | /// prefetch() preloads the given address in L1/L2 cache. This is a non-blocking 188 | /// function that doesn't stall the CPU waiting for data to be loaded from memory, 189 | /// which can be quite slow. 190 | #ifdef NO_PREFETCH 191 | 192 | void prefetch(void*) {} 193 | 194 | #else 195 | 196 | void prefetch(void* addr) { 197 | 198 | # if defined(__INTEL_COMPILER) 199 | // This hack prevents prefetches from being optimized away by 200 | // Intel compiler. Both MSVC and gcc seem not be affected by this. 201 | __asm__ (""); 202 | # endif 203 | 204 | # if defined(__INTEL_COMPILER) || defined(_MSC_VER) 205 | _mm_prefetch((char*)addr, _MM_HINT_T0); 206 | # else 207 | __builtin_prefetch(addr); 208 | # endif 209 | } 210 | 211 | #endif 212 | 213 | void prefetch2(void* addr) { 214 | 215 | prefetch(addr); 216 | prefetch((uint8_t*)addr + 64); 217 | } 218 | 219 | namespace WinProcGroup { 220 | 221 | #ifndef _WIN32 222 | 223 | void bindThisThread(size_t) {} 224 | 225 | #else 226 | 227 | /// best_group() retrieves logical processor information using Windows specific 228 | /// API and returns the best group id for the thread with index idx. Original 229 | /// code from Texel by Peter Österlund. 230 | 231 | int best_group(size_t idx) { 232 | 233 | int threads = 0; 234 | int nodes = 0; 235 | int cores = 0; 236 | DWORD returnLength = 0; 237 | DWORD byteOffset = 0; 238 | 239 | // Early exit if the needed API is not available at runtime 240 | HMODULE k32 = GetModuleHandle("Kernel32.dll"); 241 | auto fun1 = (fun1_t)(void(*)())GetProcAddress(k32, "GetLogicalProcessorInformationEx"); 242 | if (!fun1) 243 | return -1; 244 | 245 | // First call to get returnLength. We expect it to fail due to null buffer 246 | if (fun1(RelationAll, nullptr, &returnLength)) 247 | return -1; 248 | 249 | // Once we know returnLength, allocate the buffer 250 | SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buffer, *ptr; 251 | ptr = buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(returnLength); 252 | 253 | // Second call, now we expect to succeed 254 | if (!fun1(RelationAll, buffer, &returnLength)) 255 | { 256 | free(buffer); 257 | return -1; 258 | } 259 | 260 | while (ptr->Size > 0 && byteOffset + ptr->Size <= returnLength) 261 | { 262 | if (ptr->Relationship == RelationNumaNode) 263 | nodes++; 264 | 265 | else if (ptr->Relationship == RelationProcessorCore) 266 | { 267 | cores++; 268 | threads += (ptr->Processor.Flags == LTP_PC_SMT) ? 2 : 1; 269 | } 270 | 271 | byteOffset += ptr->Size; 272 | ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((char*)ptr) + ptr->Size); 273 | } 274 | 275 | free(buffer); 276 | 277 | std::vector groups; 278 | 279 | // Run as many threads as possible on the same node until core limit is 280 | // reached, then move on filling the next node. 281 | for (int n = 0; n < nodes; n++) 282 | for (int i = 0; i < cores / nodes; i++) 283 | groups.push_back(n); 284 | 285 | // In case a core has more than one logical processor (we assume 2) and we 286 | // have still threads to allocate, then spread them evenly across available 287 | // nodes. 288 | for (int t = 0; t < threads - cores; t++) 289 | groups.push_back(t % nodes); 290 | 291 | // If we still have more threads than the total number of logical processors 292 | // then return -1 and let the OS to decide what to do. 293 | return idx < groups.size() ? groups[idx] : -1; 294 | } 295 | 296 | 297 | /// bindThisThread() set the group affinity of the current thread 298 | 299 | void bindThisThread(size_t idx) { 300 | 301 | // Use only local variables to be thread-safe 302 | int group = best_group(idx); 303 | 304 | if (group == -1) 305 | return; 306 | 307 | // Early exit if the needed API are not available at runtime 308 | HMODULE k32 = GetModuleHandle("Kernel32.dll"); 309 | auto fun2 = (fun2_t)(void(*)())GetProcAddress(k32, "GetNumaNodeProcessorMaskEx"); 310 | auto fun3 = (fun3_t)(void(*)())GetProcAddress(k32, "SetThreadGroupAffinity"); 311 | 312 | if (!fun2 || !fun3) 313 | return; 314 | 315 | GROUP_AFFINITY affinity; 316 | if (fun2(group, &affinity)) 317 | fun3(GetCurrentThread(), &affinity, nullptr); 318 | } 319 | 320 | #endif 321 | 322 | } // namespace WinProcGroup 323 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 SquareBB[SQUARE_NB]; 30 | Bitboard FileBB[FILE_NB]; 31 | Bitboard RankBB[RANK_NB]; 32 | Bitboard AdjacentFilesBB[FILE_NB]; 33 | Bitboard ForwardRanksBB[COLOR_NB][RANK_NB]; 34 | Bitboard BetweenBB[SQUARE_NB][SQUARE_NB]; 35 | Bitboard LineBB[SQUARE_NB][SQUARE_NB]; 36 | Bitboard DistanceRingBB[SQUARE_NB][8]; 37 | Bitboard ForwardFileBB[COLOR_NB][SQUARE_NB]; 38 | Bitboard PassedPawnMask[COLOR_NB][SQUARE_NB]; 39 | Bitboard PawnAttackSpan[COLOR_NB][SQUARE_NB]; 40 | Bitboard PseudoAttacks[PIECE_TYPE_NB][SQUARE_NB]; 41 | Bitboard PawnAttacks[COLOR_NB][SQUARE_NB]; 42 | 43 | Magic RookMagics[SQUARE_NB]; 44 | Magic BishopMagics[SQUARE_NB]; 45 | 46 | namespace { 47 | 48 | Bitboard RookTable[0x19000]; // To store rook attacks 49 | Bitboard BishopTable[0x1480]; // To store bishop attacks 50 | 51 | void init_magics(Bitboard table[], Magic magics[], Direction directions[]); 52 | 53 | // popcount16() counts the non-zero bits using SWAR-Popcount algorithm 54 | 55 | unsigned popcount16(unsigned u) { 56 | u -= (u >> 1) & 0x5555U; 57 | u = ((u >> 2) & 0x3333U) + (u & 0x3333U); 58 | u = ((u >> 4) + u) & 0x0F0FU; 59 | return (u * 0x0101U) >> 8; 60 | } 61 | } 62 | 63 | 64 | /// Bitboards::pretty() returns an ASCII representation of a bitboard suitable 65 | /// to be printed to standard output. Useful for debugging. 66 | 67 | const std::string Bitboards::pretty(Bitboard b) { 68 | 69 | std::string s = "+---+---+---+---+---+---+---+---+\n"; 70 | 71 | for (Rank r = RANK_8; r >= RANK_1; --r) 72 | { 73 | for (File f = FILE_A; f <= FILE_H; ++f) 74 | s += b & make_square(f, r) ? "| X " : "| "; 75 | 76 | s += "|\n+---+---+---+---+---+---+---+---+\n"; 77 | } 78 | 79 | return s; 80 | } 81 | 82 | 83 | /// Bitboards::init() initializes various bitboard tables. It is called at 84 | /// startup and relies on global objects to be already zero-initialized. 85 | 86 | void Bitboards::init() { 87 | 88 | for (unsigned i = 0; i < (1 << 16); ++i) 89 | PopCnt16[i] = (uint8_t) popcount16(i); 90 | 91 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 92 | SquareBB[s] = (1ULL << s); 93 | 94 | for (File f = FILE_A; f <= FILE_H; ++f) 95 | FileBB[f] = f > FILE_A ? FileBB[f - 1] << 1 : FileABB; 96 | 97 | for (Rank r = RANK_1; r <= RANK_8; ++r) 98 | RankBB[r] = r > RANK_1 ? RankBB[r - 1] << 8 : Rank1BB; 99 | 100 | for (File f = FILE_A; f <= FILE_H; ++f) 101 | AdjacentFilesBB[f] = (f > FILE_A ? FileBB[f - 1] : 0) | (f < FILE_H ? FileBB[f + 1] : 0); 102 | 103 | for (Rank r = RANK_1; r < RANK_8; ++r) 104 | ForwardRanksBB[WHITE][r] = ~(ForwardRanksBB[BLACK][r + 1] = ForwardRanksBB[BLACK][r] | RankBB[r]); 105 | 106 | for (Color c = WHITE; c <= BLACK; ++c) 107 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 108 | { 109 | ForwardFileBB [c][s] = ForwardRanksBB[c][rank_of(s)] & FileBB[file_of(s)]; 110 | PawnAttackSpan[c][s] = ForwardRanksBB[c][rank_of(s)] & AdjacentFilesBB[file_of(s)]; 111 | PassedPawnMask[c][s] = ForwardFileBB [c][s] | PawnAttackSpan[c][s]; 112 | } 113 | 114 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) 115 | for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) 116 | if (s1 != s2) 117 | { 118 | SquareDistance[s1][s2] = std::max(distance(s1, s2), distance(s1, s2)); 119 | DistanceRingBB[s1][SquareDistance[s1][s2]] |= s2; 120 | } 121 | 122 | int steps[][5] = { {}, { 7, 9 }, { 6, 10, 15, 17 }, {}, {}, {}, { 1, 7, 8, 9 } }; 123 | 124 | for (Color c = WHITE; c <= BLACK; ++c) 125 | for (PieceType pt : { PAWN, KNIGHT, KING }) 126 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 127 | for (int i = 0; steps[pt][i]; ++i) 128 | { 129 | Square to = s + Direction(c == WHITE ? steps[pt][i] : -steps[pt][i]); 130 | 131 | if (is_ok(to) && distance(s, to) < 3) 132 | { 133 | if (pt == PAWN) 134 | PawnAttacks[c][s] |= to; 135 | else 136 | PseudoAttacks[pt][s] |= to; 137 | } 138 | } 139 | 140 | Direction RookDirections[] = { NORTH, EAST, SOUTH, WEST }; 141 | Direction BishopDirections[] = { NORTH_EAST, SOUTH_EAST, SOUTH_WEST, NORTH_WEST }; 142 | 143 | init_magics(RookTable, RookMagics, RookDirections); 144 | init_magics(BishopTable, BishopMagics, BishopDirections); 145 | 146 | for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1) 147 | { 148 | PseudoAttacks[QUEEN][s1] = PseudoAttacks[BISHOP][s1] = attacks_bb(s1, 0); 149 | PseudoAttacks[QUEEN][s1] |= PseudoAttacks[ ROOK][s1] = attacks_bb< ROOK>(s1, 0); 150 | 151 | for (PieceType pt : { BISHOP, ROOK }) 152 | for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2) 153 | { 154 | if (!(PseudoAttacks[pt][s1] & s2)) 155 | continue; 156 | 157 | LineBB[s1][s2] = (attacks_bb(pt, s1, 0) & attacks_bb(pt, s2, 0)) | s1 | s2; 158 | BetweenBB[s1][s2] = attacks_bb(pt, s1, SquareBB[s2]) & attacks_bb(pt, s2, SquareBB[s1]); 159 | } 160 | } 161 | } 162 | 163 | 164 | namespace { 165 | 166 | Bitboard sliding_attack(Direction directions[], Square sq, Bitboard occupied) { 167 | 168 | Bitboard attack = 0; 169 | 170 | for (int i = 0; i < 4; ++i) 171 | for (Square s = sq + directions[i]; 172 | is_ok(s) && distance(s, s - directions[i]) == 1; 173 | s += directions[i]) 174 | { 175 | attack |= s; 176 | 177 | if (occupied & s) 178 | break; 179 | } 180 | 181 | return attack; 182 | } 183 | 184 | 185 | // init_magics() computes all rook and bishop attacks at startup. Magic 186 | // bitboards are used to look up attacks of sliding pieces. As a reference see 187 | // chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we 188 | // use the so called "fancy" approach. 189 | 190 | void init_magics(Bitboard table[], Magic magics[], Direction directions[]) { 191 | 192 | // Optimal PRNG seeds to pick the correct magics in the shortest time 193 | int seeds[][RANK_NB] = { { 8977, 44560, 54343, 38998, 5731, 95205, 104912, 17020 }, 194 | { 728, 10316, 55013, 32803, 12281, 15100, 16645, 255 } }; 195 | 196 | Bitboard occupancy[4096], reference[4096], edges, b; 197 | int epoch[4096] = {}, cnt = 0, size = 0; 198 | 199 | for (Square s = SQ_A1; s <= SQ_H8; ++s) 200 | { 201 | // Board edges are not considered in the relevant occupancies 202 | edges = ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s)); 203 | 204 | // Given a square 's', the mask is the bitboard of sliding attacks from 205 | // 's' computed on an empty board. The index must be big enough to contain 206 | // all the attacks for each possible subset of the mask and so is 2 power 207 | // the number of 1s of the mask. Hence we deduce the size of the shift to 208 | // apply to the 64 or 32 bits word to get the index. 209 | Magic& m = magics[s]; 210 | m.mask = sliding_attack(directions, s, 0) & ~edges; 211 | m.shift = (Is64Bit ? 64 : 32) - popcount(m.mask); 212 | 213 | // Set the offset for the attacks table of the square. We have individual 214 | // table sizes for each square with "Fancy Magic Bitboards". 215 | m.attacks = s == SQ_A1 ? table : magics[s - 1].attacks + size; 216 | 217 | // Use Carry-Rippler trick to enumerate all subsets of masks[s] and 218 | // store the corresponding sliding attack bitboard in reference[]. 219 | b = size = 0; 220 | do { 221 | occupancy[size] = b; 222 | reference[size] = sliding_attack(directions, s, b); 223 | 224 | if (HasPext) 225 | m.attacks[pext(b, m.mask)] = reference[size]; 226 | 227 | size++; 228 | b = (b - m.mask) & m.mask; 229 | } while (b); 230 | 231 | if (HasPext) 232 | continue; 233 | 234 | PRNG rng(seeds[Is64Bit][rank_of(s)]); 235 | 236 | // Find a magic for square 's' picking up an (almost) random number 237 | // until we find the one that passes the verification test. 238 | for (int i = 0; i < size; ) 239 | { 240 | for (m.magic = 0; popcount((m.magic * m.mask) >> 56) < 6; ) 241 | m.magic = rng.sparse_rand(); 242 | 243 | // A good magic must map every possible occupancy to an index that 244 | // looks up the correct sliding attack in the attacks[s] database. 245 | // Note that we build up the database for square 's' as a side 246 | // effect of verifying the magic. Keep track of the attempt count 247 | // and save it in epoch[], little speed-up trick to avoid resetting 248 | // m.attacks[] after every failed attempt. 249 | for (++cnt, i = 0; i < size; ++i) 250 | { 251 | unsigned idx = m.index(occupancy[i]); 252 | 253 | if (epoch[idx] < cnt) 254 | { 255 | epoch[idx] = cnt; 256 | m.attacks[idx] = reference[i]; 257 | } 258 | else if (m.attacks[idx] != reference[i]) 259 | break; 260 | } 261 | } 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | // Pawn penalties 35 | constexpr Score Backward = S( 9, 24); 36 | constexpr Score Doubled = S(11, 56); 37 | constexpr Score Isolated = S( 5, 15); 38 | 39 | // Connected pawn bonus by opposed, phalanx, #support and rank 40 | Score Connected[2][2][3][RANK_NB]; 41 | 42 | // Strength of pawn shelter for our king by [distance from edge][rank]. 43 | // RANK_1 = 0 is used for files where we have no pawn, or pawn is behind our king. 44 | constexpr Value ShelterStrength[int(FILE_NB) / 2][RANK_NB] = { 45 | { V( -6), V( 81), V( 93), V( 58), V( 39), V( 18), V( 25) }, 46 | { V(-43), V( 61), V( 35), V(-49), V(-29), V(-11), V( -63) }, 47 | { V(-10), V( 75), V( 23), V( -2), V( 32), V( 3), V( -45) }, 48 | { V(-39), V(-13), V(-29), V(-52), V(-48), V(-67), V(-166) } 49 | }; 50 | 51 | // Danger of enemy pawns moving toward our king by [distance from edge][rank]. 52 | // RANK_1 = 0 is used for files where the enemy has no pawn, or their pawn 53 | // is behind our king. 54 | constexpr Value UnblockedStorm[int(FILE_NB) / 2][RANK_NB] = { 55 | { V( 89), V(107), V(123), V(93), V(57), V( 45), V( 51) }, 56 | { V( 44), V(-18), V(123), V(46), V(39), V( -7), V( 23) }, 57 | { V( 4), V( 52), V(162), V(37), V( 7), V(-14), V( -2) }, 58 | { V(-10), V(-14), V( 90), V(15), V( 2), V( -7), V(-16) } 59 | }; 60 | 61 | #undef S 62 | #undef V 63 | 64 | template 65 | Score evaluate(const Position& pos, Pawns::Entry* e) { 66 | 67 | constexpr Color Them = (Us == WHITE ? BLACK : WHITE); 68 | constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH); 69 | 70 | Bitboard b, neighbours, stoppers, doubled, supported, phalanx; 71 | Bitboard lever, leverPush; 72 | Square s; 73 | bool opposed, backward; 74 | Score score = SCORE_ZERO; 75 | const Square* pl = pos.squares(Us); 76 | 77 | Bitboard ourPawns = pos.pieces( Us, PAWN); 78 | Bitboard theirPawns = pos.pieces(Them, PAWN); 79 | 80 | e->passedPawns[Us] = e->pawnAttacksSpan[Us] = e->weakUnopposed[Us] = 0; 81 | e->semiopenFiles[Us] = 0xFF; 82 | e->kingSquares[Us] = SQ_NONE; 83 | e->pawnAttacks[Us] = pawn_attacks_bb(ourPawns); 84 | e->pawnsOnSquares[Us][BLACK] = popcount(ourPawns & DarkSquares); 85 | e->pawnsOnSquares[Us][WHITE] = pos.count(Us) - e->pawnsOnSquares[Us][BLACK]; 86 | 87 | // Loop through all pawns of the current color and score each pawn 88 | while ((s = *pl++) != SQ_NONE) 89 | { 90 | assert(pos.piece_on(s) == make_piece(Us, PAWN)); 91 | 92 | File f = file_of(s); 93 | 94 | e->semiopenFiles[Us] &= ~(1 << f); 95 | e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s); 96 | 97 | // Flag the pawn 98 | opposed = theirPawns & forward_file_bb(Us, s); 99 | stoppers = theirPawns & passed_pawn_mask(Us, s); 100 | lever = theirPawns & PawnAttacks[Us][s]; 101 | leverPush = theirPawns & PawnAttacks[Us][s + Up]; 102 | doubled = ourPawns & (s - Up); 103 | neighbours = ourPawns & adjacent_files_bb(f); 104 | phalanx = neighbours & rank_bb(s); 105 | supported = neighbours & rank_bb(s - Up); 106 | 107 | // A pawn is backward when it is behind all pawns of the same color 108 | // on the adjacent files and cannot be safely advanced. 109 | backward = !(ourPawns & pawn_attack_span(Them, s + Up)) 110 | && (stoppers & (leverPush | (s + Up))); 111 | 112 | // Passed pawns will be properly scored in evaluation because we need 113 | // full attack info to evaluate them. Include also not passed pawns 114 | // which could become passed after one or two pawn pushes when are 115 | // not attacked more times than defended. 116 | if ( !(stoppers ^ lever ^ leverPush) 117 | && popcount(supported) >= popcount(lever) - 1 118 | && popcount(phalanx) >= popcount(leverPush)) 119 | e->passedPawns[Us] |= s; 120 | 121 | else if ( stoppers == SquareBB[s + Up] 122 | && relative_rank(Us, s) >= RANK_5) 123 | { 124 | b = shift(supported) & ~theirPawns; 125 | while (b) 126 | if (!more_than_one(theirPawns & PawnAttacks[Us][pop_lsb(&b)])) 127 | e->passedPawns[Us] |= s; 128 | } 129 | 130 | // Score this pawn 131 | if (supported | phalanx) 132 | score += Connected[opposed][bool(phalanx)][popcount(supported)][relative_rank(Us, s)]; 133 | 134 | else if (!neighbours) 135 | score -= Isolated, e->weakUnopposed[Us] += !opposed; 136 | 137 | else if (backward) 138 | score -= Backward, e->weakUnopposed[Us] += !opposed; 139 | 140 | if (doubled && !supported) 141 | score -= Doubled; 142 | } 143 | 144 | return score; 145 | } 146 | 147 | } // namespace 148 | 149 | namespace Pawns { 150 | 151 | /// Pawns::init() initializes some tables needed by evaluation. Instead of using 152 | /// hard-coded tables, when makes sense, we prefer to calculate them with a formula 153 | /// to reduce independent parameters and to allow easier tuning and better insight. 154 | 155 | void init() { 156 | 157 | static constexpr int Seed[RANK_NB] = { 0, 13, 24, 18, 65, 100, 175, 330 }; 158 | 159 | for (int opposed = 0; opposed <= 1; ++opposed) 160 | for (int phalanx = 0; phalanx <= 1; ++phalanx) 161 | for (int support = 0; support <= 2; ++support) 162 | for (Rank r = RANK_2; r < RANK_8; ++r) 163 | { 164 | int v = 17 * support; 165 | v += (Seed[r] + (phalanx ? (Seed[r + 1] - Seed[r]) / 2 : 0)) >> opposed; 166 | 167 | Connected[opposed][phalanx][support][r] = make_score(v, v * (r - 2) / 4); 168 | } 169 | } 170 | 171 | 172 | /// Pawns::probe() looks up the current position's pawns configuration in 173 | /// the pawns hash table. It returns a pointer to the Entry if the position 174 | /// is found. Otherwise a new Entry is computed and stored there, so we don't 175 | /// have to recompute all when the same pawns configuration occurs again. 176 | 177 | Entry* probe(const Position& pos) { 178 | 179 | Key key = pos.pawn_key(); 180 | Entry* e = pos.this_thread()->pawnsTable[key]; 181 | 182 | if (e->key == key) 183 | return e; 184 | 185 | e->key = key; 186 | e->scores[WHITE] = evaluate(pos, e); 187 | e->scores[BLACK] = evaluate(pos, e); 188 | e->openFiles = popcount(e->semiopenFiles[WHITE] & e->semiopenFiles[BLACK]); 189 | e->asymmetry = popcount( (e->passedPawns[WHITE] | e->passedPawns[BLACK]) 190 | | (e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK])); 191 | 192 | return e; 193 | } 194 | 195 | 196 | /// Entry::evaluate_shelter() calculates the shelter bonus and the storm 197 | /// penalty for a king, looking at the king file and the two closest files. 198 | 199 | template 200 | Value Entry::evaluate_shelter(const Position& pos, Square ksq) { 201 | 202 | constexpr Color Them = (Us == WHITE ? BLACK : WHITE); 203 | constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH); 204 | constexpr Bitboard BlockRanks = (Us == WHITE ? Rank1BB | Rank2BB : Rank8BB | Rank7BB); 205 | 206 | Bitboard b = pos.pieces(PAWN) & ~forward_ranks_bb(Them, ksq); 207 | Bitboard ourPawns = b & pos.pieces(Us); 208 | Bitboard theirPawns = b & pos.pieces(Them); 209 | 210 | Value safety = (shift(theirPawns) & (FileABB | FileHBB) & BlockRanks & ksq) ? 211 | Value(374) : Value(5); 212 | 213 | File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq))); 214 | for (File f = File(center - 1); f <= File(center + 1); ++f) 215 | { 216 | b = ourPawns & file_bb(f); 217 | int ourRank = b ? relative_rank(Us, backmost_sq(Us, b)) : 0; 218 | 219 | b = theirPawns & file_bb(f); 220 | int theirRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : 0; 221 | 222 | int d = std::min(f, ~f); 223 | safety += ShelterStrength[d][ourRank]; 224 | safety -= (ourRank && (ourRank == theirRank - 1)) ? 66 * (theirRank == RANK_3) 225 | : UnblockedStorm[d][theirRank]; 226 | } 227 | 228 | return safety; 229 | } 230 | 231 | 232 | /// Entry::do_king_safety() calculates a bonus for king safety. It is called only 233 | /// when king square changes, which is about 20% of total king_safety() calls. 234 | 235 | template 236 | Score Entry::do_king_safety(const Position& pos) { 237 | 238 | Square ksq = pos.square(Us); 239 | kingSquares[Us] = ksq; 240 | castlingRights[Us] = pos.can_castle(Us); 241 | int minKingPawnDistance = 0; 242 | 243 | Bitboard pawns = pos.pieces(Us, PAWN); 244 | if (pawns) 245 | while (!(DistanceRingBB[ksq][++minKingPawnDistance] & pawns)) {} 246 | 247 | Value bonus = evaluate_shelter(pos, ksq); 248 | 249 | // If we can castle use the bonus after the castling if it is bigger 250 | if (pos.can_castle(Us | KING_SIDE)) 251 | bonus = std::max(bonus, evaluate_shelter(pos, relative_square(Us, SQ_G1))); 252 | 253 | if (pos.can_castle(Us | QUEEN_SIDE)) 254 | bonus = std::max(bonus, evaluate_shelter(pos, relative_square(Us, SQ_C1))); 255 | 256 | return make_score(bonus, -16 * minKingPawnDistance); 257 | } 258 | 259 | // Explicit template instantiation 260 | template Score Entry::do_king_safety(const Position& pos); 261 | template Score Entry::do_king_safety(const Position& pos); 262 | 263 | } // namespace Pawns 264 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 "evaluate.h" 27 | #include "movegen.h" 28 | #include "position.h" 29 | #include "search.h" 30 | #include "thread.h" 31 | #include "timeman.h" 32 | #include "tt.h" 33 | #include "uci.h" 34 | #include "syzygy/tbprobe.h" 35 | 36 | using namespace std; 37 | 38 | extern vector setup_bench(const Position&, istream&); 39 | 40 | namespace { 41 | 42 | // FEN string of the initial position, normal chess 43 | const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; 44 | 45 | 46 | // position() is called when engine receives the "position" UCI command. 47 | // The function sets up the position described in the given FEN string ("fen") 48 | // or the starting position ("startpos") and then makes the moves given in the 49 | // following move list ("moves"). 50 | 51 | void position(Position& pos, istringstream& is, StateListPtr& states) { 52 | 53 | Move m; 54 | string token, fen; 55 | 56 | is >> token; 57 | 58 | if (token == "startpos") 59 | { 60 | fen = StartFEN; 61 | is >> token; // Consume "moves" token if any 62 | } 63 | else if (token == "fen") 64 | while (is >> token && token != "moves") 65 | fen += token + " "; 66 | else 67 | return; 68 | 69 | states = StateListPtr(new std::deque(1)); // Drop old and create a new one 70 | pos.set(fen, Options["UCI_Chess960"], &states->back(), Threads.main()); 71 | 72 | // Parse move list (if any) 73 | while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE) 74 | { 75 | states->emplace_back(); 76 | pos.do_move(m, states->back()); 77 | } 78 | } 79 | 80 | 81 | // setoption() is called when engine receives the "setoption" UCI command. The 82 | // function updates the UCI option ("name") to the given value ("value"). 83 | 84 | void setoption(istringstream& is) { 85 | 86 | string token, name, value; 87 | 88 | is >> token; // Consume "name" token 89 | 90 | // Read option name (can contain spaces) 91 | while (is >> token && token != "value") 92 | name += (name.empty() ? "" : " ") + token; 93 | 94 | // Read option value (can contain spaces) 95 | while (is >> token) 96 | value += (value.empty() ? "" : " ") + token; 97 | 98 | if (Options.count(name)) 99 | Options[name] = value; 100 | else 101 | sync_cout << "No such option: " << name << sync_endl; 102 | } 103 | 104 | 105 | // go() is called when engine receives the "go" UCI command. The function sets 106 | // the thinking time and other parameters from the input string, then starts 107 | // the search. 108 | 109 | void go(Position& pos, istringstream& is, StateListPtr& states) { 110 | 111 | Search::LimitsType limits; 112 | string token; 113 | bool ponderMode = false; 114 | 115 | limits.startTime = now(); // As early as possible! 116 | 117 | while (is >> token) 118 | if (token == "searchmoves") 119 | while (is >> token) 120 | limits.searchmoves.push_back(UCI::to_move(pos, token)); 121 | 122 | else if (token == "wtime") is >> limits.time[WHITE]; 123 | else if (token == "btime") is >> limits.time[BLACK]; 124 | else if (token == "winc") is >> limits.inc[WHITE]; 125 | else if (token == "binc") is >> limits.inc[BLACK]; 126 | else if (token == "movestogo") is >> limits.movestogo; 127 | else if (token == "depth") is >> limits.depth; 128 | else if (token == "nodes") is >> limits.nodes; 129 | else if (token == "movetime") is >> limits.movetime; 130 | else if (token == "mate") is >> limits.mate; 131 | else if (token == "perft") is >> limits.perft; 132 | else if (token == "infinite") limits.infinite = 1; 133 | else if (token == "ponder") ponderMode = true; 134 | 135 | Threads.start_thinking(pos, states, limits, ponderMode); 136 | } 137 | 138 | 139 | // bench() is called when engine receives the "bench" command. Firstly 140 | // a list of UCI commands is setup according to bench parameters, then 141 | // it is run one by one printing a summary at the end. 142 | 143 | void bench(Position& pos, istream& args, StateListPtr& states) { 144 | 145 | string token; 146 | uint64_t num, nodes = 0, cnt = 1; 147 | 148 | vector list = setup_bench(pos, args); 149 | num = count_if(list.begin(), list.end(), [](string s) { return s.find("go ") == 0; }); 150 | 151 | TimePoint elapsed = now(); 152 | 153 | for (const auto& cmd : list) 154 | { 155 | istringstream is(cmd); 156 | is >> skipws >> token; 157 | 158 | if (token == "go") 159 | { 160 | cerr << "\nPosition: " << cnt++ << '/' << num << endl; 161 | go(pos, is, states); 162 | Threads.main()->wait_for_search_finished(); 163 | nodes += Threads.nodes_searched(); 164 | } 165 | else if (token == "setoption") setoption(is); 166 | else if (token == "position") position(pos, is, states); 167 | else if (token == "ucinewgame") Search::clear(); 168 | } 169 | 170 | elapsed = now() - elapsed + 1; // Ensure positivity to avoid a 'divide by zero' 171 | 172 | dbg_print(); // Just before exiting 173 | 174 | cerr << "\n===========================" 175 | << "\nTotal time (ms) : " << elapsed 176 | << "\nNodes searched : " << nodes 177 | << "\nNodes/second : " << 1000 * nodes / elapsed << endl; 178 | } 179 | 180 | } // namespace 181 | 182 | 183 | /// UCI::loop() waits for a command from stdin, parses it and calls the appropriate 184 | /// function. Also intercepts EOF from stdin to ensure gracefully exiting if the 185 | /// GUI dies unexpectedly. When called with some command line arguments, e.g. to 186 | /// run 'bench', once the command is executed the function returns immediately. 187 | /// In addition to the UCI ones, also some additional debug commands are supported. 188 | 189 | void UCI::loop(int argc, char* argv[]) { 190 | 191 | Position pos; 192 | string token, cmd; 193 | StateListPtr states(new std::deque(1)); 194 | auto uiThread = std::make_shared(0); 195 | 196 | pos.set(StartFEN, false, &states->back(), uiThread.get()); 197 | 198 | for (int i = 1; i < argc; ++i) 199 | cmd += std::string(argv[i]) + " "; 200 | 201 | do { 202 | if (argc == 1 && !getline(cin, cmd)) // Block here waiting for input or EOF 203 | cmd = "quit"; 204 | 205 | istringstream is(cmd); 206 | 207 | token.clear(); // Avoid a stale if getline() returns empty or blank line 208 | is >> skipws >> token; 209 | 210 | // The GUI sends 'ponderhit' to tell us the user has played the expected move. 211 | // So 'ponderhit' will be sent if we were told to ponder on the same move the 212 | // user has played. We should continue searching but switch from pondering to 213 | // normal search. In case Threads.stopOnPonderhit is set we are waiting for 214 | // 'ponderhit' to stop the search, for instance if max search depth is reached. 215 | if ( token == "quit" 216 | || token == "stop" 217 | || (token == "ponderhit" && Threads.stopOnPonderhit)) 218 | Threads.stop = true; 219 | 220 | else if (token == "ponderhit") 221 | Threads.ponder = false; // Switch to normal search 222 | 223 | else if (token == "uci") 224 | sync_cout << "id name " << engine_info(true) 225 | << "\n" << Options 226 | << "\nuciok" << sync_endl; 227 | 228 | else if (token == "setoption") setoption(is); 229 | else if (token == "go") go(pos, is, states); 230 | else if (token == "position") position(pos, is, states); 231 | else if (token == "ucinewgame") Search::clear(); 232 | else if (token == "isready") sync_cout << "readyok" << sync_endl; 233 | 234 | // Additional custom non-UCI commands, mainly for debugging 235 | else if (token == "flip") pos.flip(); 236 | else if (token == "bench") bench(pos, is, states); 237 | else if (token == "d") sync_cout << pos << sync_endl; 238 | else if (token == "eval") sync_cout << Eval::trace(pos) << sync_endl; 239 | else 240 | sync_cout << "Unknown command: " << cmd << sync_endl; 241 | 242 | } while (token != "quit" && argc == 1); // Command line args are one-shot 243 | } 244 | 245 | 246 | /// UCI::value() converts a Value to a string suitable for use with the UCI 247 | /// protocol specification: 248 | /// 249 | /// cp The score from the engine's point of view in centipawns. 250 | /// mate Mate in y moves, not plies. If the engine is getting mated 251 | /// use negative values for y. 252 | 253 | string UCI::value(Value v) { 254 | 255 | assert(-VALUE_INFINITE < v && v < VALUE_INFINITE); 256 | 257 | stringstream ss; 258 | 259 | if (abs(v) < VALUE_MATE - MAX_PLY) 260 | ss << "cp " << v * 100 / PawnValueEg; 261 | else 262 | ss << "mate " << (v > 0 ? VALUE_MATE - v + 1 : -VALUE_MATE - v) / 2; 263 | 264 | return ss.str(); 265 | } 266 | 267 | 268 | /// UCI::square() converts a Square to a string in algebraic notation (g1, a7, etc.) 269 | 270 | std::string UCI::square(Square s) { 271 | return std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) }; 272 | } 273 | 274 | 275 | /// UCI::move() converts a Move to a string in coordinate notation (g1f3, a7a8q). 276 | /// The only special case is castling, where we print in the e1g1 notation in 277 | /// normal chess mode, and in e1h1 notation in chess960 mode. Internally all 278 | /// castling moves are always encoded as 'king captures rook'. 279 | 280 | string UCI::move(Move m, bool chess960) { 281 | 282 | Square from = from_sq(m); 283 | Square to = to_sq(m); 284 | 285 | if (m == MOVE_NONE) 286 | return "(none)"; 287 | 288 | if (m == MOVE_NULL) 289 | return "0000"; 290 | 291 | if (type_of(m) == CASTLING && !chess960) 292 | to = make_square(to > from ? FILE_G : FILE_C, rank_of(from)); 293 | 294 | string move = UCI::square(from) + UCI::square(to); 295 | 296 | if (type_of(m) == PROMOTION) 297 | move += " pnbrqk"[promotion_type(m)]; 298 | 299 | return move; 300 | } 301 | 302 | 303 | /// UCI::to_move() converts a string representing a move in coordinate notation 304 | /// (g1f3, a7a8q) to the corresponding legal Move, if any. 305 | 306 | Move UCI::to_move(const Position& pos, string& str) { 307 | 308 | if (str.length() == 5) // Junior could send promotion piece in uppercase 309 | str[4] = char(tolower(str[4])); 310 | 311 | for (const auto& m : MoveList(pos)) 312 | if (str == UCI::move(m, pos.is_chess960())) 313 | return m; 314 | 315 | return MOVE_NONE; 316 | } 317 | -------------------------------------------------------------------------------- /stockfish-10-win/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-2019 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 | constexpr Bitboard AllSquares = ~Bitboard(0); 43 | constexpr Bitboard DarkSquares = 0xAA55AA55AA55AA55ULL; 44 | 45 | constexpr Bitboard FileABB = 0x0101010101010101ULL; 46 | constexpr Bitboard FileBBB = FileABB << 1; 47 | constexpr Bitboard FileCBB = FileABB << 2; 48 | constexpr Bitboard FileDBB = FileABB << 3; 49 | constexpr Bitboard FileEBB = FileABB << 4; 50 | constexpr Bitboard FileFBB = FileABB << 5; 51 | constexpr Bitboard FileGBB = FileABB << 6; 52 | constexpr Bitboard FileHBB = FileABB << 7; 53 | 54 | constexpr Bitboard Rank1BB = 0xFF; 55 | constexpr Bitboard Rank2BB = Rank1BB << (8 * 1); 56 | constexpr Bitboard Rank3BB = Rank1BB << (8 * 2); 57 | constexpr Bitboard Rank4BB = Rank1BB << (8 * 3); 58 | constexpr Bitboard Rank5BB = Rank1BB << (8 * 4); 59 | constexpr Bitboard Rank6BB = Rank1BB << (8 * 5); 60 | constexpr Bitboard Rank7BB = Rank1BB << (8 * 6); 61 | constexpr Bitboard Rank8BB = Rank1BB << (8 * 7); 62 | 63 | extern int SquareDistance[SQUARE_NB][SQUARE_NB]; 64 | 65 | extern Bitboard SquareBB[SQUARE_NB]; 66 | extern Bitboard FileBB[FILE_NB]; 67 | extern Bitboard RankBB[RANK_NB]; 68 | extern Bitboard AdjacentFilesBB[FILE_NB]; 69 | extern Bitboard ForwardRanksBB[COLOR_NB][RANK_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 ForwardFileBB[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 | extern Bitboard PawnAttacks[COLOR_NB][SQUARE_NB]; 78 | 79 | 80 | /// Magic holds all magic bitboards relevant data for a single square 81 | struct Magic { 82 | Bitboard mask; 83 | Bitboard magic; 84 | Bitboard* attacks; 85 | unsigned shift; 86 | 87 | // Compute the attack's index using the 'magic bitboards' approach 88 | unsigned index(Bitboard occupied) const { 89 | 90 | if (HasPext) 91 | return unsigned(pext(occupied, mask)); 92 | 93 | if (Is64Bit) 94 | return unsigned(((occupied & mask) * magic) >> shift); 95 | 96 | unsigned lo = unsigned(occupied) & unsigned(mask); 97 | unsigned hi = unsigned(occupied >> 32) & unsigned(mask >> 32); 98 | return (lo * unsigned(magic) ^ hi * unsigned(magic >> 32)) >> shift; 99 | } 100 | }; 101 | 102 | extern Magic RookMagics[SQUARE_NB]; 103 | extern Magic BishopMagics[SQUARE_NB]; 104 | 105 | 106 | /// Overloads of bitwise operators between a Bitboard and a Square for testing 107 | /// whether a given bit is set in a bitboard, and for setting and clearing bits. 108 | 109 | inline Bitboard operator&(Bitboard b, Square s) { 110 | assert(s >= SQ_A1 && s <= SQ_H8); 111 | return b & SquareBB[s]; 112 | } 113 | 114 | inline Bitboard operator|(Bitboard b, Square s) { 115 | assert(s >= SQ_A1 && s <= SQ_H8); 116 | return b | SquareBB[s]; 117 | } 118 | 119 | inline Bitboard operator^(Bitboard b, Square s) { 120 | assert(s >= SQ_A1 && s <= SQ_H8); 121 | return b ^ SquareBB[s]; 122 | } 123 | 124 | inline Bitboard& operator|=(Bitboard& b, Square s) { 125 | assert(s >= SQ_A1 && s <= SQ_H8); 126 | return b |= SquareBB[s]; 127 | } 128 | 129 | inline Bitboard& operator^=(Bitboard& b, Square s) { 130 | assert(s >= SQ_A1 && s <= SQ_H8); 131 | return b ^= SquareBB[s]; 132 | } 133 | 134 | constexpr bool more_than_one(Bitboard b) { 135 | return b & (b - 1); 136 | } 137 | 138 | /// rank_bb() and file_bb() return a bitboard representing all the squares on 139 | /// the given file or rank. 140 | 141 | inline Bitboard rank_bb(Rank r) { 142 | return RankBB[r]; 143 | } 144 | 145 | inline Bitboard rank_bb(Square s) { 146 | return RankBB[rank_of(s)]; 147 | } 148 | 149 | inline Bitboard file_bb(File f) { 150 | return FileBB[f]; 151 | } 152 | 153 | inline Bitboard file_bb(Square s) { 154 | return FileBB[file_of(s)]; 155 | } 156 | 157 | 158 | /// shift() moves a bitboard one step along direction D (mainly for pawns) 159 | 160 | template 161 | constexpr Bitboard shift(Bitboard b) { 162 | return D == NORTH ? b << 8 : D == SOUTH ? b >> 8 163 | : D == EAST ? (b & ~FileHBB) << 1 : D == WEST ? (b & ~FileABB) >> 1 164 | : D == NORTH_EAST ? (b & ~FileHBB) << 9 : D == NORTH_WEST ? (b & ~FileABB) << 7 165 | : D == SOUTH_EAST ? (b & ~FileHBB) >> 7 : D == SOUTH_WEST ? (b & ~FileABB) >> 9 166 | : 0; 167 | } 168 | 169 | 170 | /// pawn_attacks_bb() returns the pawn attacks for the given color from the 171 | /// squares in the given bitboard. 172 | 173 | template 174 | constexpr Bitboard pawn_attacks_bb(Bitboard b) { 175 | return C == WHITE ? shift(b) | shift(b) 176 | : shift(b) | shift(b); 177 | } 178 | 179 | 180 | /// adjacent_files_bb() returns a bitboard representing all the squares on the 181 | /// adjacent files of the given one. 182 | 183 | inline Bitboard adjacent_files_bb(File f) { 184 | return AdjacentFilesBB[f]; 185 | } 186 | 187 | 188 | /// between_bb() returns a bitboard representing all the squares between the two 189 | /// given ones. For instance, between_bb(SQ_C4, SQ_F7) returns a bitboard with 190 | /// the bits for square d5 and e6 set. If s1 and s2 are not on the same rank, file 191 | /// or diagonal, 0 is returned. 192 | 193 | inline Bitboard between_bb(Square s1, Square s2) { 194 | return BetweenBB[s1][s2]; 195 | } 196 | 197 | 198 | /// forward_ranks_bb() returns a bitboard representing the squares on all the ranks 199 | /// in front of the given one, from the point of view of the given color. For instance, 200 | /// forward_ranks_bb(BLACK, SQ_D3) will return the 16 squares on ranks 1 and 2. 201 | 202 | inline Bitboard forward_ranks_bb(Color c, Square s) { 203 | return ForwardRanksBB[c][rank_of(s)]; 204 | } 205 | 206 | 207 | /// forward_file_bb() returns a bitboard representing all the squares along the line 208 | /// in front of the given one, from the point of view of the given color: 209 | /// ForwardFileBB[c][s] = forward_ranks_bb(c, s) & file_bb(s) 210 | 211 | inline Bitboard forward_file_bb(Color c, Square s) { 212 | return ForwardFileBB[c][s]; 213 | } 214 | 215 | 216 | /// pawn_attack_span() returns a bitboard representing all the squares that can be 217 | /// attacked by a pawn of the given color when it moves along its file, starting 218 | /// from the given square: 219 | /// PawnAttackSpan[c][s] = forward_ranks_bb(c, s) & adjacent_files_bb(file_of(s)); 220 | 221 | inline Bitboard pawn_attack_span(Color c, Square s) { 222 | return PawnAttackSpan[c][s]; 223 | } 224 | 225 | 226 | /// passed_pawn_mask() returns a bitboard mask which can be used to test if a 227 | /// pawn of the given color and on the given square is a passed pawn: 228 | /// PassedPawnMask[c][s] = pawn_attack_span(c, s) | forward_file_bb(c, s) 229 | 230 | inline Bitboard passed_pawn_mask(Color c, Square s) { 231 | return PassedPawnMask[c][s]; 232 | } 233 | 234 | 235 | /// aligned() returns true if the squares s1, s2 and s3 are aligned either on a 236 | /// straight or on a diagonal line. 237 | 238 | inline bool aligned(Square s1, Square s2, Square s3) { 239 | return LineBB[s1][s2] & s3; 240 | } 241 | 242 | 243 | /// distance() functions return the distance between x and y, defined as the 244 | /// number of steps for a king in x to reach y. Works with squares, ranks, files. 245 | 246 | template inline int distance(T x, T y) { return x < y ? y - x : x - y; } 247 | template<> inline int distance(Square x, Square y) { return SquareDistance[x][y]; } 248 | 249 | template inline int distance(T2 x, T2 y); 250 | template<> inline int distance(Square x, Square y) { return distance(file_of(x), file_of(y)); } 251 | template<> inline int distance(Square x, Square y) { return distance(rank_of(x), rank_of(y)); } 252 | 253 | 254 | /// attacks_bb() returns a bitboard representing all the squares attacked by a 255 | /// piece of type Pt (bishop or rook) placed on 's'. 256 | 257 | template 258 | inline Bitboard attacks_bb(Square s, Bitboard occupied) { 259 | 260 | const Magic& m = Pt == ROOK ? RookMagics[s] : BishopMagics[s]; 261 | return m.attacks[m.index(occupied)]; 262 | } 263 | 264 | inline Bitboard attacks_bb(PieceType pt, Square s, Bitboard occupied) { 265 | 266 | assert(pt != PAWN); 267 | 268 | switch (pt) 269 | { 270 | case BISHOP: return attacks_bb(s, occupied); 271 | case ROOK : return attacks_bb< ROOK>(s, occupied); 272 | case QUEEN : return attacks_bb(s, occupied) | attacks_bb(s, occupied); 273 | default : return PseudoAttacks[pt][s]; 274 | } 275 | } 276 | 277 | 278 | /// popcount() counts the number of non-zero bits in a bitboard 279 | 280 | inline int popcount(Bitboard b) { 281 | 282 | #ifndef USE_POPCNT 283 | 284 | extern uint8_t PopCnt16[1 << 16]; 285 | union { Bitboard bb; uint16_t u[4]; } v = { b }; 286 | return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]]; 287 | 288 | #elif defined(_MSC_VER) || defined(__INTEL_COMPILER) 289 | 290 | return (int)_mm_popcnt_u64(b); 291 | 292 | #else // Assumed gcc or compatible compiler 293 | 294 | return __builtin_popcountll(b); 295 | 296 | #endif 297 | } 298 | 299 | 300 | /// lsb() and msb() return the least/most significant bit in a non-zero bitboard 301 | 302 | #if defined(__GNUC__) // GCC, Clang, ICC 303 | 304 | inline Square lsb(Bitboard b) { 305 | assert(b); 306 | return Square(__builtin_ctzll(b)); 307 | } 308 | 309 | inline Square msb(Bitboard b) { 310 | assert(b); 311 | return Square(63 ^ __builtin_clzll(b)); 312 | } 313 | 314 | #elif defined(_MSC_VER) // MSVC 315 | 316 | #ifdef _WIN64 // MSVC, WIN64 317 | 318 | inline Square lsb(Bitboard b) { 319 | assert(b); 320 | unsigned long idx; 321 | _BitScanForward64(&idx, b); 322 | return (Square) idx; 323 | } 324 | 325 | inline Square msb(Bitboard b) { 326 | assert(b); 327 | unsigned long idx; 328 | _BitScanReverse64(&idx, b); 329 | return (Square) idx; 330 | } 331 | 332 | #else // MSVC, WIN32 333 | 334 | inline Square lsb(Bitboard b) { 335 | assert(b); 336 | unsigned long idx; 337 | 338 | if (b & 0xffffffff) { 339 | _BitScanForward(&idx, int32_t(b)); 340 | return Square(idx); 341 | } else { 342 | _BitScanForward(&idx, int32_t(b >> 32)); 343 | return Square(idx + 32); 344 | } 345 | } 346 | 347 | inline Square msb(Bitboard b) { 348 | assert(b); 349 | unsigned long idx; 350 | 351 | if (b >> 32) { 352 | _BitScanReverse(&idx, int32_t(b >> 32)); 353 | return Square(idx + 32); 354 | } else { 355 | _BitScanReverse(&idx, int32_t(b)); 356 | return Square(idx); 357 | } 358 | } 359 | 360 | #endif 361 | 362 | #else // Compiler is neither GCC nor MSVC compatible 363 | 364 | #error "Compiler not supported." 365 | 366 | #endif 367 | 368 | 369 | /// pop_lsb() finds and clears the least significant bit in a non-zero bitboard 370 | 371 | inline Square pop_lsb(Bitboard* b) { 372 | const Square s = lsb(*b); 373 | *b &= *b - 1; 374 | return s; 375 | } 376 | 377 | 378 | /// frontmost_sq() and backmost_sq() return the square corresponding to the 379 | /// most/least advanced bit relative to the given color. 380 | 381 | inline Square frontmost_sq(Color c, Bitboard b) { return c == WHITE ? msb(b) : lsb(b); } 382 | inline Square backmost_sq(Color c, Bitboard b) { return c == WHITE ? lsb(b) : msb(b); } 383 | 384 | #endif // #ifndef BITBOARD_H_INCLUDED 385 | --------------------------------------------------------------------------------