mirror of
https://github.com/opelly27/Stockfish.git
synced 2026-05-20 15:37:47 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48cfdfcc46 | |||
| fa7b244dc9 | |||
| 29ad6a73fc | |||
| ac48b16708 | |||
| 38b1c4b6b8 | |||
| 162dbeaee8 | |||
| 85146ca0a9 | |||
| 02e12a69a7 | |||
| 6e8116e38f | |||
| 29f7fab2a9 | |||
| 2af986bf31 | |||
| b67146b100 | |||
| c1b1a94d81 | |||
| 17212e5fcc | |||
| 46921dff27 | |||
| 941016e7a2 | |||
| 290caf9960 | |||
| 43fa3a4d64 | |||
| 64b4836d12 | |||
| 5df7d62eb9 | |||
| 82179c70dc | |||
| de17652e47 | |||
| 647b79b556 | |||
| e0a8b36436 | |||
| 8d724220a7 | |||
| 0973cc2ef6 | |||
| 3f14f9a478 | |||
| aa86d81f79 | |||
| b884351cc7 | |||
| 4d9e9ac3d4 | |||
| 3dc9f95225 | |||
| bc0871acbc | |||
| 2643f1552f | |||
| ba07b95ee0 | |||
| ef58551a2d |
@@ -80,6 +80,7 @@ help:
|
|||||||
@echo "Makefile options:"
|
@echo "Makefile options:"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "make > Default: Compiler = g++"
|
@echo "make > Default: Compiler = g++"
|
||||||
|
@echo "make gcc-popcnt > Compiler = g++ + popcnt-support"
|
||||||
@echo "make icc > Compiler = icpc"
|
@echo "make icc > Compiler = icpc"
|
||||||
@echo "make icc-profile > Compiler = icpc + automatic pgo-build"
|
@echo "make icc-profile > Compiler = icpc + automatic pgo-build"
|
||||||
@echo "make icc-profile-popcnt > Compiler = icpc + automatic pgo-build + popcnt-support"
|
@echo "make icc-profile-popcnt > Compiler = icpc + automatic pgo-build + popcnt-support"
|
||||||
@@ -108,6 +109,13 @@ gcc:
|
|||||||
CXXFLAGS="$(GCCFLAGS)" \
|
CXXFLAGS="$(GCCFLAGS)" \
|
||||||
all
|
all
|
||||||
|
|
||||||
|
gcc-popcnt:
|
||||||
|
$(MAKE) \
|
||||||
|
CXX='g++' \
|
||||||
|
CXXFLAGS="$(GCCFLAGS) -DUSE_POPCNT" \
|
||||||
|
all
|
||||||
|
|
||||||
|
|
||||||
icc:
|
icc:
|
||||||
$(MAKE) \
|
$(MAKE) \
|
||||||
CXX='icpc' \
|
CXX='icpc' \
|
||||||
|
|||||||
+1
-1
@@ -155,7 +155,7 @@ void benchmark(const string& commandLine) {
|
|||||||
cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl;
|
cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl;
|
||||||
if (limitType == "perft")
|
if (limitType == "perft")
|
||||||
totalNodes += perft(pos, maxDepth * OnePly);
|
totalNodes += perft(pos, maxDepth * OnePly);
|
||||||
else if (!think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
|
else if (!think(pos, false, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
|
||||||
break;
|
break;
|
||||||
totalNodes += nodes_searched();
|
totalNodes += nodes_searched();
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-7
@@ -348,19 +348,21 @@ union b_union {
|
|||||||
|
|
||||||
Square pop_1st_bit(Bitboard* bb) {
|
Square pop_1st_bit(Bitboard* bb) {
|
||||||
|
|
||||||
b_union* u;
|
b_union u;
|
||||||
Square ret;
|
Square ret;
|
||||||
|
|
||||||
u = (b_union*)bb;
|
u.b = *bb;
|
||||||
|
|
||||||
if (u->dw.l)
|
if (u.dw.l)
|
||||||
{
|
{
|
||||||
ret = Square(BitTable[((u->dw.l ^ (u->dw.l - 1)) * 0x783a9b23) >> 26]);
|
ret = Square(BitTable[((u.dw.l ^ (u.dw.l - 1)) * 0x783a9b23) >> 26]);
|
||||||
u->dw.l &= (u->dw.l - 1);
|
u.dw.l &= (u.dw.l - 1);
|
||||||
|
*bb = u.b;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ret = Square(BitTable[((~(u->dw.h ^ (u->dw.h - 1))) * 0x783a9b23) >> 26]);
|
ret = Square(BitTable[((~(u.dw.h ^ (u.dw.h - 1))) * 0x783a9b23) >> 26]);
|
||||||
u->dw.h &= (u->dw.h - 1);
|
u.dw.h &= (u.dw.h - 1);
|
||||||
|
*bb = u.b;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,30 @@ inline bool cpu_has_popcnt() {
|
|||||||
|
|
||||||
#define POPCNT_INTRINSIC(x) __popcnt64(x)
|
#define POPCNT_INTRINSIC(x) __popcnt64(x)
|
||||||
|
|
||||||
|
#elif defined(__GNUC__) && defined(USE_POPCNT) // Gcc compiler
|
||||||
|
|
||||||
|
inline void __cpuid(unsigned int op,
|
||||||
|
unsigned int *eax, unsigned int *ebx,
|
||||||
|
unsigned int *ecx, unsigned int *edx)
|
||||||
|
{
|
||||||
|
*eax = op;
|
||||||
|
*ecx = 0;
|
||||||
|
__asm__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
|
||||||
|
: "0" (*eax), "2" (*ecx));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool cpu_has_popcnt() {
|
||||||
|
|
||||||
|
unsigned int eax, ebx, ecx, edx;
|
||||||
|
__cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||||
|
return (ecx >> 23) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define POPCNT_INTRINSIC(x) ({ \
|
||||||
|
unsigned long __ret; \
|
||||||
|
__asm__("popcnt %1, %0" : "=r" (__ret) : "r" (x)); \
|
||||||
|
__ret; })
|
||||||
|
|
||||||
#else // Safe fallback for unsupported compilers or when USE_POPCNT is disabled
|
#else // Safe fallback for unsupported compilers or when USE_POPCNT is disabled
|
||||||
|
|
||||||
inline bool cpu_has_popcnt() { return false; }
|
inline bool cpu_has_popcnt() { return false; }
|
||||||
|
|||||||
+4
-3
@@ -251,9 +251,10 @@ namespace {
|
|||||||
// in init_safety().
|
// in init_safety().
|
||||||
Value SafetyTable[100];
|
Value SafetyTable[100];
|
||||||
|
|
||||||
// Pawn and material hash tables, indexed by the current thread id
|
// Pawn and material hash tables, indexed by the current thread id.
|
||||||
MaterialInfoTable* MaterialTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
// Note that they will be initialized at 0 being global variables.
|
||||||
PawnInfoTable* PawnTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
MaterialInfoTable* MaterialTable[THREAD_MAX];
|
||||||
|
PawnInfoTable* PawnTable[THREAD_MAX];
|
||||||
|
|
||||||
// Sizes of pawn and material hash tables
|
// Sizes of pawn and material hash tables
|
||||||
const int PawnTableSize = 16384;
|
const int PawnTableSize = 16384;
|
||||||
|
|||||||
@@ -374,7 +374,6 @@ EndgameFunctions::EndgameFunctions() {
|
|||||||
add<ScalingFunction<KBPPKB> >("KBPPKB");
|
add<ScalingFunction<KBPPKB> >("KBPPKB");
|
||||||
add<ScalingFunction<KBPKN> >("KBPKN");
|
add<ScalingFunction<KBPKN> >("KBPKN");
|
||||||
add<ScalingFunction<KRPPKRP> >("KRPPKRP");
|
add<ScalingFunction<KRPPKRP> >("KRPPKRP");
|
||||||
add<ScalingFunction<KRPPKRP> >("KRPPKRP");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EndgameFunctions::~EndgameFunctions() {
|
EndgameFunctions::~EndgameFunctions() {
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ using namespace std;
|
|||||||
/// Version number. If this is left empty, the current date (in the format
|
/// Version number. If this is left empty, the current date (in the format
|
||||||
/// YYMMDD) is used as a version number.
|
/// YYMMDD) is used as a version number.
|
||||||
|
|
||||||
static const string EngineVersion = "1.6";
|
static const string EngineVersion = "1.6.3";
|
||||||
static const string AppName = "Stockfish";
|
static const string AppName = "Stockfish";
|
||||||
static const string AppTag = "";
|
static const string AppTag = "";
|
||||||
|
|
||||||
|
|||||||
+105
-66
@@ -143,72 +143,77 @@ void Position::from_fen(const string& fen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
while(strchr("KQkqabcdefghABCDEFGH-", fen[i])) {
|
while (strchr("KQkqabcdefghABCDEFGH-", fen[i])) {
|
||||||
if (fen[i] == '-')
|
if (fen[i] == '-')
|
||||||
{
|
{
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (fen[i] == 'K') allow_oo(WHITE);
|
||||||
|
else if (fen[i] == 'Q') allow_ooo(WHITE);
|
||||||
|
else if (fen[i] == 'k') allow_oo(BLACK);
|
||||||
|
else if (fen[i] == 'q') allow_ooo(BLACK);
|
||||||
|
else if (fen[i] >= 'A' && fen[i] <= 'H') {
|
||||||
|
File rookFile, kingFile = FILE_NONE;
|
||||||
|
for (Square square = SQ_B1; square <= SQ_G1; square++)
|
||||||
|
if (piece_on(square) == WK)
|
||||||
|
kingFile = square_file(square);
|
||||||
|
if (kingFile == FILE_NONE) {
|
||||||
|
std::cout << "Error in FEN at character " << i << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialKFile = kingFile;
|
||||||
|
rookFile = File(fen[i] - 'A') + FILE_A;
|
||||||
|
if (rookFile < initialKFile) {
|
||||||
|
allow_ooo(WHITE);
|
||||||
|
initialQRFile = rookFile;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
allow_oo(WHITE);
|
||||||
|
initialKRFile = rookFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fen[i] >= 'a' && fen[i] <= 'h') {
|
||||||
|
File rookFile, kingFile = FILE_NONE;
|
||||||
|
for (Square square = SQ_B8; square <= SQ_G8; square++)
|
||||||
|
if (piece_on(square) == BK)
|
||||||
|
kingFile = square_file(square);
|
||||||
|
if (kingFile == FILE_NONE) {
|
||||||
|
std::cout << "Error in FEN at character " << i << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initialKFile = kingFile;
|
||||||
|
rookFile = File(fen[i] - 'a') + FILE_A;
|
||||||
|
if (rookFile < initialKFile) {
|
||||||
|
allow_ooo(BLACK);
|
||||||
|
initialQRFile = rookFile;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
allow_oo(BLACK);
|
||||||
|
initialKRFile = rookFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "Error in FEN at character " << i << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if(fen[i] == 'K') allow_oo(WHITE);
|
|
||||||
else if(fen[i] == 'Q') allow_ooo(WHITE);
|
|
||||||
else if(fen[i] == 'k') allow_oo(BLACK);
|
|
||||||
else if(fen[i] == 'q') allow_ooo(BLACK);
|
|
||||||
else if(fen[i] >= 'A' && fen[i] <= 'H') {
|
|
||||||
File rookFile, kingFile = FILE_NONE;
|
|
||||||
for(Square square = SQ_B1; square <= SQ_G1; square++)
|
|
||||||
if(piece_on(square) == WK)
|
|
||||||
kingFile = square_file(square);
|
|
||||||
if(kingFile == FILE_NONE) {
|
|
||||||
std::cout << "Error in FEN at character " << i << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
initialKFile = kingFile;
|
|
||||||
rookFile = File(fen[i] - 'A') + FILE_A;
|
|
||||||
if(rookFile < initialKFile) {
|
|
||||||
allow_ooo(WHITE);
|
|
||||||
initialQRFile = rookFile;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
allow_oo(WHITE);
|
|
||||||
initialKRFile = rookFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(fen[i] >= 'a' && fen[i] <= 'h') {
|
|
||||||
File rookFile, kingFile = FILE_NONE;
|
|
||||||
for(Square square = SQ_B8; square <= SQ_G8; square++)
|
|
||||||
if(piece_on(square) == BK)
|
|
||||||
kingFile = square_file(square);
|
|
||||||
if(kingFile == FILE_NONE) {
|
|
||||||
std::cout << "Error in FEN at character " << i << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
initialKFile = kingFile;
|
|
||||||
rookFile = File(fen[i] - 'a') + FILE_A;
|
|
||||||
if(rookFile < initialKFile) {
|
|
||||||
allow_ooo(BLACK);
|
|
||||||
initialQRFile = rookFile;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
allow_oo(BLACK);
|
|
||||||
initialKRFile = rookFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << "Error in FEN at character " << i << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip blanks
|
// Skip blanks
|
||||||
while (fen[i] == ' ')
|
while (fen[i] == ' ')
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
// En passant square
|
// En passant square -- ignore if no capture is possible
|
||||||
if ( i <= fen.length() - 2
|
if ( i <= fen.length() - 2
|
||||||
&& (fen[i] >= 'a' && fen[i] <= 'h')
|
&& (fen[i] >= 'a' && fen[i] <= 'h')
|
||||||
&& (fen[i+1] == '3' || fen[i+1] == '6'))
|
&& (fen[i+1] == '3' || fen[i+1] == '6'))
|
||||||
st->epSquare = square_from_string(fen.substr(i, 2));
|
{
|
||||||
|
Square fenEpSquare = square_from_string(fen.substr(i, 2));
|
||||||
|
Color them = opposite_color(sideToMove);
|
||||||
|
if (attacks_from<PAWN>(fenEpSquare, them) & this->pieces(PAWN, sideToMove))
|
||||||
|
st->epSquare = square_from_string(fen.substr(i, 2));
|
||||||
|
}
|
||||||
|
|
||||||
// Various initialisation
|
// Various initialisation
|
||||||
for (Square sq = SQ_A1; sq <= SQ_H8; sq++)
|
for (Square sq = SQ_A1; sq <= SQ_H8; sq++)
|
||||||
@@ -266,10 +271,24 @@ const string Position::to_fen() const {
|
|||||||
fen += (sideToMove == WHITE ? "w " : "b ");
|
fen += (sideToMove == WHITE ? "w " : "b ");
|
||||||
if (st->castleRights != NO_CASTLES)
|
if (st->castleRights != NO_CASTLES)
|
||||||
{
|
{
|
||||||
if (can_castle_kingside(WHITE)) fen += 'K';
|
if (initialKFile == FILE_E && initialQRFile == FILE_A && initialKRFile == FILE_H)
|
||||||
if (can_castle_queenside(WHITE)) fen += 'Q';
|
{
|
||||||
if (can_castle_kingside(BLACK)) fen += 'k';
|
if (can_castle_kingside(WHITE)) fen += 'K';
|
||||||
if (can_castle_queenside(BLACK)) fen += 'q';
|
if (can_castle_queenside(WHITE)) fen += 'Q';
|
||||||
|
if (can_castle_kingside(BLACK)) fen += 'k';
|
||||||
|
if (can_castle_queenside(BLACK)) fen += 'q';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (can_castle_kingside(WHITE))
|
||||||
|
fen += char(toupper(file_to_char(initialKRFile)));
|
||||||
|
if (can_castle_queenside(WHITE))
|
||||||
|
fen += char(toupper(file_to_char(initialQRFile)));
|
||||||
|
if (can_castle_kingside(BLACK))
|
||||||
|
fen += file_to_char(initialKRFile);
|
||||||
|
if (can_castle_queenside(BLACK))
|
||||||
|
fen += file_to_char(initialQRFile);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
fen += '-';
|
fen += '-';
|
||||||
|
|
||||||
@@ -671,7 +690,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
|
|||||||
Key pawnKey, materialKey;
|
Key pawnKey, materialKey;
|
||||||
int castleRights, rule50, pliesFromNull;
|
int castleRights, rule50, pliesFromNull;
|
||||||
Square epSquare;
|
Square epSquare;
|
||||||
Value value;
|
Score value;
|
||||||
Value npMaterial[2];
|
Value npMaterial[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1553,7 +1572,7 @@ Key Position::compute_pawn_key() const {
|
|||||||
for (Color c = WHITE; c <= BLACK; c++)
|
for (Color c = WHITE; c <= BLACK; c++)
|
||||||
{
|
{
|
||||||
b = pieces(PAWN, c);
|
b = pieces(PAWN, c);
|
||||||
while(b)
|
while (b)
|
||||||
{
|
{
|
||||||
s = pop_1st_bit(&b);
|
s = pop_1st_bit(&b);
|
||||||
result ^= zobrist[c][PAWN][s];
|
result ^= zobrist[c][PAWN][s];
|
||||||
@@ -1597,7 +1616,7 @@ Score Position::compute_value() const {
|
|||||||
for (PieceType pt = PAWN; pt <= KING; pt++)
|
for (PieceType pt = PAWN; pt <= KING; pt++)
|
||||||
{
|
{
|
||||||
b = pieces(pt, c);
|
b = pieces(pt, c);
|
||||||
while(b)
|
while (b)
|
||||||
{
|
{
|
||||||
s = pop_1st_bit(&b);
|
s = pop_1st_bit(&b);
|
||||||
assert(piece_on(s) == piece_of_color_and_type(c, pt));
|
assert(piece_on(s) == piece_of_color_and_type(c, pt));
|
||||||
@@ -1843,6 +1862,7 @@ bool Position::is_ok(int* failedStep) const {
|
|||||||
static const bool debugNonPawnMaterial = false;
|
static const bool debugNonPawnMaterial = false;
|
||||||
static const bool debugPieceCounts = false;
|
static const bool debugPieceCounts = false;
|
||||||
static const bool debugPieceList = false;
|
static const bool debugPieceList = false;
|
||||||
|
static const bool debugCastleSquares = false;
|
||||||
|
|
||||||
if (failedStep) *failedStep = 1;
|
if (failedStep) *failedStep = 1;
|
||||||
|
|
||||||
@@ -1968,9 +1988,9 @@ bool Position::is_ok(int* failedStep) const {
|
|||||||
if (failedStep) (*failedStep)++;
|
if (failedStep) (*failedStep)++;
|
||||||
if (debugPieceList)
|
if (debugPieceList)
|
||||||
{
|
{
|
||||||
for(Color c = WHITE; c <= BLACK; c++)
|
for (Color c = WHITE; c <= BLACK; c++)
|
||||||
for(PieceType pt = PAWN; pt <= KING; pt++)
|
for (PieceType pt = PAWN; pt <= KING; pt++)
|
||||||
for(int i = 0; i < pieceCount[c][pt]; i++)
|
for (int i = 0; i < pieceCount[c][pt]; i++)
|
||||||
{
|
{
|
||||||
if (piece_on(piece_list(c, pt, i)) != piece_of_color_and_type(c, pt))
|
if (piece_on(piece_list(c, pt, i)) != piece_of_color_and_type(c, pt))
|
||||||
return false;
|
return false;
|
||||||
@@ -1979,6 +1999,25 @@ bool Position::is_ok(int* failedStep) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (failedStep) (*failedStep)++;
|
||||||
|
if (debugCastleSquares) {
|
||||||
|
for (Color c = WHITE; c <= BLACK; c++) {
|
||||||
|
if (can_castle_kingside(c) && piece_on(initial_kr_square(c)) != piece_of_color_and_type(c, ROOK))
|
||||||
|
return false;
|
||||||
|
if (can_castle_queenside(c) && piece_on(initial_qr_square(c)) != piece_of_color_and_type(c, ROOK))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (castleRightsMask[initial_kr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OO))
|
||||||
|
return false;
|
||||||
|
if (castleRightsMask[initial_qr_square(WHITE)] != (ALL_CASTLES ^ WHITE_OOO))
|
||||||
|
return false;
|
||||||
|
if (castleRightsMask[initial_kr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OO))
|
||||||
|
return false;
|
||||||
|
if (castleRightsMask[initial_qr_square(BLACK)] != (ALL_CASTLES ^ BLACK_OOO))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (failedStep) *failedStep = 0;
|
if (failedStep) *failedStep = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+132
-87
@@ -227,14 +227,9 @@ namespace {
|
|||||||
int MaxNodes, MaxDepth;
|
int MaxNodes, MaxDepth;
|
||||||
int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime;
|
int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime;
|
||||||
int RootMoveNumber;
|
int RootMoveNumber;
|
||||||
bool InfiniteSearch;
|
bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
|
||||||
bool PonderSearch;
|
bool AbortSearch, Quit;
|
||||||
bool StopOnPonderhit;
|
bool FailHigh, FailLow, Problem;
|
||||||
bool AbortSearch; // heavy SMP read access
|
|
||||||
bool Quit;
|
|
||||||
bool FailHigh;
|
|
||||||
bool FailLow;
|
|
||||||
bool Problem;
|
|
||||||
|
|
||||||
// Show current line?
|
// Show current line?
|
||||||
bool ShowCurrentLine;
|
bool ShowCurrentLine;
|
||||||
@@ -368,8 +363,20 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
|
|||||||
int time[], int increment[], int movesToGo, int maxDepth,
|
int time[], int increment[], int movesToGo, int maxDepth,
|
||||||
int maxNodes, int maxTime, Move searchMoves[]) {
|
int maxNodes, int maxTime, Move searchMoves[]) {
|
||||||
|
|
||||||
// Look for a book move
|
// Initialize global search variables
|
||||||
if (!infinite && !ponder && get_option_value_bool("OwnBook"))
|
Idle = StopOnPonderhit = AbortSearch = Quit = false;
|
||||||
|
FailHigh = FailLow = Problem = false;
|
||||||
|
NodesSincePoll = 0;
|
||||||
|
SearchStartTime = get_system_time();
|
||||||
|
ExactMaxTime = maxTime;
|
||||||
|
MaxDepth = maxDepth;
|
||||||
|
MaxNodes = maxNodes;
|
||||||
|
InfiniteSearch = infinite;
|
||||||
|
PonderSearch = ponder;
|
||||||
|
UseTimeManagement = !ExactMaxTime && !MaxDepth && !MaxNodes && !InfiniteSearch;
|
||||||
|
|
||||||
|
// Look for a book move, only during games, not tests
|
||||||
|
if (UseTimeManagement && !ponder && get_option_value_bool("OwnBook"))
|
||||||
{
|
{
|
||||||
Move bookMove;
|
Move bookMove;
|
||||||
if (get_option_value_string("Book File") != OpeningBook.file_name())
|
if (get_option_value_string("Book File") != OpeningBook.file_name())
|
||||||
@@ -384,8 +391,6 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize global search variables
|
// Initialize global search variables
|
||||||
Idle = false;
|
|
||||||
SearchStartTime = get_system_time();
|
|
||||||
for (int i = 0; i < THREAD_MAX; i++)
|
for (int i = 0; i < THREAD_MAX; i++)
|
||||||
{
|
{
|
||||||
Threads[i].nodes = 0ULL;
|
Threads[i].nodes = 0ULL;
|
||||||
@@ -452,6 +457,10 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
|
|||||||
{
|
{
|
||||||
ActiveThreads = newActiveThreads;
|
ActiveThreads = newActiveThreads;
|
||||||
init_eval(ActiveThreads);
|
init_eval(ActiveThreads);
|
||||||
|
// HACK: init_eval() destroys the static castleRightsMask[] array in the
|
||||||
|
// Position class. The below line repairs the damage.
|
||||||
|
Position p(pos.to_fen());
|
||||||
|
assert(pos.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wake up sleeping threads
|
// Wake up sleeping threads
|
||||||
@@ -463,48 +472,45 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
|
|||||||
// Set thinking time
|
// Set thinking time
|
||||||
int myTime = time[side_to_move];
|
int myTime = time[side_to_move];
|
||||||
int myIncrement = increment[side_to_move];
|
int myIncrement = increment[side_to_move];
|
||||||
|
if (UseTimeManagement)
|
||||||
if (!movesToGo) // Sudden death time control
|
|
||||||
{
|
{
|
||||||
if (myIncrement)
|
if (!movesToGo) // Sudden death time control
|
||||||
{
|
{
|
||||||
MaxSearchTime = myTime / 30 + myIncrement;
|
if (myIncrement)
|
||||||
AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
|
{
|
||||||
} else { // Blitz game without increment
|
MaxSearchTime = myTime / 30 + myIncrement;
|
||||||
MaxSearchTime = myTime / 30;
|
AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
|
||||||
AbsoluteMaxSearchTime = myTime / 8;
|
}
|
||||||
|
else // Blitz game without increment
|
||||||
|
{
|
||||||
|
MaxSearchTime = myTime / 30;
|
||||||
|
AbsoluteMaxSearchTime = myTime / 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else // (x moves) / (y minutes)
|
||||||
else // (x moves) / (y minutes)
|
|
||||||
{
|
|
||||||
if (movesToGo == 1)
|
|
||||||
{
|
{
|
||||||
MaxSearchTime = myTime / 2;
|
if (movesToGo == 1)
|
||||||
AbsoluteMaxSearchTime =
|
{
|
||||||
(myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4);
|
MaxSearchTime = myTime / 2;
|
||||||
} else {
|
AbsoluteMaxSearchTime = (myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4);
|
||||||
MaxSearchTime = myTime / Min(movesToGo, 20);
|
}
|
||||||
AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3);
|
else
|
||||||
|
{
|
||||||
|
MaxSearchTime = myTime / Min(movesToGo, 20);
|
||||||
|
AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PonderingEnabled)
|
||||||
|
{
|
||||||
|
MaxSearchTime += MaxSearchTime / 4;
|
||||||
|
MaxSearchTime = Min(MaxSearchTime, AbsoluteMaxSearchTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PonderingEnabled)
|
// Set best NodesBetweenPolls interval
|
||||||
{
|
|
||||||
MaxSearchTime += MaxSearchTime / 4;
|
|
||||||
MaxSearchTime = Min(MaxSearchTime, AbsoluteMaxSearchTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fixed depth or fixed number of nodes?
|
|
||||||
MaxDepth = maxDepth;
|
|
||||||
if (MaxDepth)
|
|
||||||
InfiniteSearch = true; // HACK
|
|
||||||
|
|
||||||
MaxNodes = maxNodes;
|
|
||||||
if (MaxNodes)
|
if (MaxNodes)
|
||||||
{
|
|
||||||
NodesBetweenPolls = Min(MaxNodes, 30000);
|
NodesBetweenPolls = Min(MaxNodes, 30000);
|
||||||
InfiniteSearch = true; // HACK
|
|
||||||
}
|
|
||||||
else if (myTime && myTime < 1000)
|
else if (myTime && myTime < 1000)
|
||||||
NodesBetweenPolls = 1000;
|
NodesBetweenPolls = 1000;
|
||||||
else if (myTime && myTime < 5000)
|
else if (myTime && myTime < 5000)
|
||||||
@@ -569,6 +575,7 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
|
|||||||
void init_threads() {
|
void init_threads() {
|
||||||
|
|
||||||
volatile int i;
|
volatile int i;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
pthread_t pthread[1];
|
pthread_t pthread[1];
|
||||||
@@ -604,12 +611,18 @@ void init_threads() {
|
|||||||
for(i = 1; i < THREAD_MAX; i++)
|
for(i = 1; i < THREAD_MAX; i++)
|
||||||
{
|
{
|
||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
pthread_create(pthread, NULL, init_thread, (void*)(&i));
|
ok = (pthread_create(pthread, NULL, init_thread, (void*)(&i)) == 0);
|
||||||
#else
|
#else
|
||||||
DWORD iID[1];
|
DWORD iID[1];
|
||||||
CreateThread(NULL, 0, init_thread, (LPVOID)(&i), 0, iID);
|
ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&i), 0, iID) != NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to create thread number " << i << std::endl;
|
||||||
|
Application::exit_with_failure();
|
||||||
|
}
|
||||||
|
|
||||||
// Wait until the thread has finished launching
|
// Wait until the thread has finished launching
|
||||||
while (!Threads[i].running);
|
while (!Threads[i].running);
|
||||||
}
|
}
|
||||||
@@ -782,7 +795,7 @@ namespace {
|
|||||||
|
|
||||||
Problem = false;
|
Problem = false;
|
||||||
|
|
||||||
if (!InfiniteSearch)
|
if (UseTimeManagement)
|
||||||
{
|
{
|
||||||
// Time to stop?
|
// Time to stop?
|
||||||
bool stopSearch = false;
|
bool stopSearch = false;
|
||||||
@@ -835,9 +848,9 @@ namespace {
|
|||||||
|
|
||||||
rml.sort();
|
rml.sort();
|
||||||
|
|
||||||
// If we are pondering, we shouldn't print the best move before we
|
// If we are pondering or in infinite search, we shouldn't print the
|
||||||
// are told to do so
|
// best move before we are told to do so.
|
||||||
if (PonderSearch)
|
if (!AbortSearch && (PonderSearch || InfiniteSearch))
|
||||||
wait_for_stop_or_ponderhit();
|
wait_for_stop_or_ponderhit();
|
||||||
else
|
else
|
||||||
// Print final search statistics
|
// Print final search statistics
|
||||||
@@ -1142,9 +1155,6 @@ namespace {
|
|||||||
search_pv(pos, ss, alpha, beta, depth-2*OnePly, ply, threadID);
|
search_pv(pos, ss, alpha, beta, depth-2*OnePly, ply, threadID);
|
||||||
ttMove = ss[ply].pv[ply];
|
ttMove = ss[ply].pv[ply];
|
||||||
tte = TT.retrieve(pos.get_key());
|
tte = TT.retrieve(pos.get_key());
|
||||||
|
|
||||||
// If tte->move() != MOVE_NONE then it equals ttMove
|
|
||||||
assert(!(tte && tte->move()) || tte->move() == ttMove);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a MovePicker object for the current position, and prepare
|
// Initialize a MovePicker object for the current position, and prepare
|
||||||
@@ -2009,7 +2019,14 @@ namespace {
|
|||||||
if (sp->ply == 1 && RootMoveNumber == 1)
|
if (sp->ply == 1 && RootMoveNumber == 1)
|
||||||
Threads[threadID].failHighPly1 = true;
|
Threads[threadID].failHighPly1 = true;
|
||||||
|
|
||||||
value = -search_pv(pos, ss, -sp->beta, -sp->alpha, newDepth, sp->ply+1, threadID);
|
// If another thread has failed high then sp->alpha has been increased
|
||||||
|
// to be higher or equal then beta, if so, avoid to start a PV search.
|
||||||
|
Value localAlpha = sp->alpha;
|
||||||
|
if (localAlpha < sp->beta)
|
||||||
|
value = -search_pv(pos, ss, -sp->beta, -localAlpha, newDepth, sp->ply+1, threadID);
|
||||||
|
else
|
||||||
|
assert(thread_should_stop(threadID));
|
||||||
|
|
||||||
Threads[threadID].failHighPly1 = false;
|
Threads[threadID].failHighPly1 = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2027,11 +2044,7 @@ namespace {
|
|||||||
sp->bestValue = value;
|
sp->bestValue = value;
|
||||||
if (value > sp->alpha)
|
if (value > sp->alpha)
|
||||||
{
|
{
|
||||||
sp->alpha = value;
|
// Ask threads to stop before to modify sp->alpha
|
||||||
sp_update_pv(sp->parentSstack, ss, sp->ply);
|
|
||||||
if (value == value_mate_in(sp->ply + 1))
|
|
||||||
ss[sp->ply].mateKiller = move;
|
|
||||||
|
|
||||||
if (value >= sp->beta)
|
if (value >= sp->beta)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ActiveThreads; i++)
|
for (int i = 0; i < ActiveThreads; i++)
|
||||||
@@ -2040,6 +2053,12 @@ namespace {
|
|||||||
|
|
||||||
sp->finished = true;
|
sp->finished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sp->alpha = value;
|
||||||
|
|
||||||
|
sp_update_pv(sp->parentSstack, ss, sp->ply);
|
||||||
|
if (value == value_mate_in(sp->ply + 1))
|
||||||
|
ss[sp->ply].mateKiller = move;
|
||||||
}
|
}
|
||||||
// If we are at ply 1, and we are searching the first root move at
|
// If we are at ply 1, and we are searching the first root move at
|
||||||
// ply 0, set the 'Problem' variable if the score has dropped a lot
|
// ply 0, set the 'Problem' variable if the score has dropped a lot
|
||||||
@@ -2645,16 +2664,26 @@ namespace {
|
|||||||
if (ShowCurrentLine)
|
if (ShowCurrentLine)
|
||||||
Threads[0].printCurrentLine = true;
|
Threads[0].printCurrentLine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should we stop the search?
|
// Should we stop the search?
|
||||||
if (PonderSearch)
|
if (PonderSearch)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool overTime = t > AbsoluteMaxSearchTime
|
bool stillAtFirstMove = RootMoveNumber == 1
|
||||||
|| (RootMoveNumber == 1 && t > MaxSearchTime + ExtraSearchTime && !FailLow) //FIXME: We are not checking any problem flags, BUG?
|
&& !FailLow
|
||||||
|| ( !FailHigh && !FailLow && !fail_high_ply_1() && !Problem
|
&& t > MaxSearchTime + ExtraSearchTime;
|
||||||
&& t > 6*(MaxSearchTime + ExtraSearchTime));
|
|
||||||
|
|
||||||
if ( (Iteration >= 3 && (!InfiniteSearch && overTime))
|
bool noProblemFound = !FailHigh
|
||||||
|
&& !FailLow
|
||||||
|
&& !fail_high_ply_1()
|
||||||
|
&& !Problem
|
||||||
|
&& t > 6 * (MaxSearchTime + ExtraSearchTime);
|
||||||
|
|
||||||
|
bool noMoreTime = t > AbsoluteMaxSearchTime
|
||||||
|
|| stillAtFirstMove //FIXME: We are not checking any problem flags, BUG?
|
||||||
|
|| noProblemFound;
|
||||||
|
|
||||||
|
if ( (Iteration >= 3 && UseTimeManagement && noMoreTime)
|
||||||
|| (ExactMaxTime && t >= ExactMaxTime)
|
|| (ExactMaxTime && t >= ExactMaxTime)
|
||||||
|| (Iteration >= 3 && MaxNodes && nodes_searched() >= MaxNodes))
|
|| (Iteration >= 3 && MaxNodes && nodes_searched() >= MaxNodes))
|
||||||
AbortSearch = true;
|
AbortSearch = true;
|
||||||
@@ -2669,14 +2698,23 @@ namespace {
|
|||||||
|
|
||||||
int t = current_search_time();
|
int t = current_search_time();
|
||||||
PonderSearch = false;
|
PonderSearch = false;
|
||||||
if (Iteration >= 3 &&
|
|
||||||
(!InfiniteSearch && (StopOnPonderhit ||
|
bool stillAtFirstMove = RootMoveNumber == 1
|
||||||
t > AbsoluteMaxSearchTime ||
|
&& !FailLow
|
||||||
(RootMoveNumber == 1 &&
|
&& t > MaxSearchTime + ExtraSearchTime;
|
||||||
t > MaxSearchTime + ExtraSearchTime && !FailLow) ||
|
|
||||||
(!FailHigh && !FailLow && !fail_high_ply_1() && !Problem &&
|
bool noProblemFound = !FailHigh
|
||||||
t > 6*(MaxSearchTime + ExtraSearchTime)))))
|
&& !FailLow
|
||||||
AbortSearch = true;
|
&& !fail_high_ply_1()
|
||||||
|
&& !Problem
|
||||||
|
&& t > 6 * (MaxSearchTime + ExtraSearchTime);
|
||||||
|
|
||||||
|
bool noMoreTime = t > AbsoluteMaxSearchTime
|
||||||
|
|| stillAtFirstMove
|
||||||
|
|| noProblemFound;
|
||||||
|
|
||||||
|
if (Iteration >= 3 && UseTimeManagement && (noMoreTime || StopOnPonderhit))
|
||||||
|
AbortSearch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2770,13 +2808,15 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If this thread has been assigned work, launch a search
|
// If this thread has been assigned work, launch a search
|
||||||
if(Threads[threadID].workIsWaiting) {
|
if (Threads[threadID].workIsWaiting)
|
||||||
Threads[threadID].workIsWaiting = false;
|
{
|
||||||
if(Threads[threadID].splitPoint->pvNode)
|
Threads[threadID].workIsWaiting = false;
|
||||||
sp_search_pv(Threads[threadID].splitPoint, threadID);
|
if (Threads[threadID].splitPoint->pvNode)
|
||||||
else
|
sp_search_pv(Threads[threadID].splitPoint, threadID);
|
||||||
sp_search(Threads[threadID].splitPoint, threadID);
|
else
|
||||||
Threads[threadID].idle = true;
|
sp_search(Threads[threadID].splitPoint, threadID);
|
||||||
|
|
||||||
|
Threads[threadID].idle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this thread is the master of a split point and all threads have
|
// If this thread is the master of a split point and all threads have
|
||||||
@@ -2850,17 +2890,22 @@ namespace {
|
|||||||
if(!Threads[slave].idle || slave == master)
|
if(!Threads[slave].idle || slave == master)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(Threads[slave].activeSplitPoints == 0)
|
// Make a local copy to be sure doesn't change under our feet
|
||||||
// No active split points means that the thread is available as a slave
|
int localActiveSplitPoints = Threads[slave].activeSplitPoints;
|
||||||
// for any other thread.
|
|
||||||
return true;
|
if (localActiveSplitPoints == 0)
|
||||||
|
// No active split points means that the thread is available as
|
||||||
|
// a slave for any other thread.
|
||||||
|
return true;
|
||||||
|
|
||||||
if(ActiveThreads == 2)
|
if(ActiveThreads == 2)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Apply the "helpful master" concept if possible.
|
// Apply the "helpful master" concept if possible. Use localActiveSplitPoints
|
||||||
if(SplitPointStack[slave][Threads[slave].activeSplitPoints-1].slaves[master])
|
// that is known to be > 0, instead of Threads[slave].activeSplitPoints that
|
||||||
return true;
|
// could have been set to 0 by another thread leading to an out of bound access.
|
||||||
|
if (SplitPointStack[slave][localActiveSplitPoints - 1].slaves[master])
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ struct SplitPoint {
|
|||||||
|
|
||||||
struct Thread {
|
struct Thread {
|
||||||
SplitPoint *splitPoint;
|
SplitPoint *splitPoint;
|
||||||
int activeSplitPoints;
|
volatile int activeSplitPoints;
|
||||||
uint64_t nodes;
|
uint64_t nodes;
|
||||||
uint64_t betaCutOffs[2];
|
uint64_t betaCutOffs[2];
|
||||||
bool failHighPly1;
|
bool failHighPly1;
|
||||||
|
|||||||
+3
-3
@@ -53,11 +53,11 @@ TranspositionTable::~TranspositionTable() {
|
|||||||
/// TranspositionTable::set_size sets the size of the transposition table,
|
/// TranspositionTable::set_size sets the size of the transposition table,
|
||||||
/// measured in megabytes.
|
/// measured in megabytes.
|
||||||
|
|
||||||
void TranspositionTable::set_size(unsigned mbSize) {
|
void TranspositionTable::set_size(size_t mbSize) {
|
||||||
|
|
||||||
assert(mbSize >= 4 && mbSize <= 4096);
|
assert(mbSize >= 4 && mbSize <= 8192);
|
||||||
|
|
||||||
unsigned newSize = 1024;
|
size_t newSize = 1024;
|
||||||
|
|
||||||
// We store a cluster of ClusterSize number of TTEntry for each position
|
// We store a cluster of ClusterSize number of TTEntry for each position
|
||||||
// and newSize is the maximum number of storable positions.
|
// and newSize is the maximum number of storable positions.
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ class TranspositionTable {
|
|||||||
public:
|
public:
|
||||||
TranspositionTable();
|
TranspositionTable();
|
||||||
~TranspositionTable();
|
~TranspositionTable();
|
||||||
void set_size(unsigned mbSize);
|
void set_size(size_t mbSize);
|
||||||
void clear();
|
void clear();
|
||||||
void store(const Key posKey, Value v, ValueType type, Depth d, Move m);
|
void store(const Key posKey, Value v, ValueType type, Depth d, Move m);
|
||||||
TTEntry* retrieve(const Key posKey) const;
|
TTEntry* retrieve(const Key posKey) const;
|
||||||
@@ -114,7 +114,7 @@ private:
|
|||||||
unsigned writes; // heavy SMP read/write access here
|
unsigned writes; // heavy SMP read/write access here
|
||||||
unsigned char pad_after[64];
|
unsigned char pad_after[64];
|
||||||
|
|
||||||
unsigned size;
|
size_t size;
|
||||||
TTCluster* entries;
|
TTCluster* entries;
|
||||||
uint8_t generation;
|
uint8_t generation;
|
||||||
};
|
};
|
||||||
|
|||||||
+25
-43
@@ -107,7 +107,8 @@ namespace {
|
|||||||
UCIInputParser uip(command);
|
UCIInputParser uip(command);
|
||||||
string token;
|
string token;
|
||||||
|
|
||||||
uip >> token; // operator>>() skips any whitespace
|
if (!(uip >> token)) // operator>>() skips any whitespace
|
||||||
|
return true;
|
||||||
|
|
||||||
if (token == "quit")
|
if (token == "quit")
|
||||||
return false;
|
return false;
|
||||||
@@ -159,14 +160,8 @@ namespace {
|
|||||||
else if (token == "perft")
|
else if (token == "perft")
|
||||||
perft(uip);
|
perft(uip);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
cout << "Unknown command: " << command << endl;
|
cout << "Unknown command: " << command << endl;
|
||||||
while (!uip.eof())
|
|
||||||
{
|
|
||||||
uip >> token;
|
|
||||||
cout << token << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,33 +176,33 @@ namespace {
|
|||||||
|
|
||||||
string token;
|
string token;
|
||||||
|
|
||||||
uip >> token; // operator>>() skips any whitespace
|
if (!(uip >> token)) // operator>>() skips any whitespace
|
||||||
|
return;
|
||||||
|
|
||||||
if (token == "startpos")
|
if (token == "startpos")
|
||||||
RootPosition.from_fen(StartPosition);
|
RootPosition.from_fen(StartPosition);
|
||||||
else if (token == "fen")
|
else if (token == "fen")
|
||||||
{
|
{
|
||||||
string fen;
|
string fen;
|
||||||
while (token != "moves" && !uip.eof())
|
while (uip >> token && token != "moves")
|
||||||
{
|
{
|
||||||
uip >> token;
|
|
||||||
fen += token;
|
fen += token;
|
||||||
fen += ' ';
|
fen += ' ';
|
||||||
}
|
}
|
||||||
RootPosition.from_fen(fen);
|
RootPosition.from_fen(fen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uip.eof())
|
if (uip.good())
|
||||||
{
|
{
|
||||||
if (token != "moves")
|
if (token != "moves")
|
||||||
uip >> token;
|
uip >> token;
|
||||||
|
|
||||||
if (token == "moves")
|
if (token == "moves")
|
||||||
{
|
{
|
||||||
Move move;
|
Move move;
|
||||||
StateInfo st;
|
StateInfo st;
|
||||||
while (!uip.eof())
|
while (uip >> token)
|
||||||
{
|
{
|
||||||
uip >> token;
|
|
||||||
move = move_from_string(RootPosition, token);
|
move = move_from_string(RootPosition, token);
|
||||||
RootPosition.do_move(move, st);
|
RootPosition.do_move(move, st);
|
||||||
if (RootPosition.rule_50_counter() == 0)
|
if (RootPosition.rule_50_counter() == 0)
|
||||||
@@ -229,27 +224,22 @@ namespace {
|
|||||||
|
|
||||||
void set_option(UCIInputParser& uip) {
|
void set_option(UCIInputParser& uip) {
|
||||||
|
|
||||||
string token, name;
|
string token, name, value;
|
||||||
|
|
||||||
uip >> token;
|
if (!(uip >> token)) // operator>>() skips any whitespace
|
||||||
if (token == "name")
|
return;
|
||||||
|
|
||||||
|
if (token == "name" && uip >> name)
|
||||||
{
|
{
|
||||||
uip >> name;
|
while (uip >> token && token != "value")
|
||||||
while (!uip.eof())
|
|
||||||
{
|
|
||||||
uip >> token;
|
|
||||||
if (token == "value")
|
|
||||||
break;
|
|
||||||
|
|
||||||
name += (" " + token);
|
name += (" " + token);
|
||||||
}
|
|
||||||
if (token == "value")
|
|
||||||
{
|
|
||||||
// Reads until end of line and left trim white space
|
|
||||||
getline(uip, token);
|
|
||||||
token.erase(0, token.find_first_not_of(" \n\r\t"));
|
|
||||||
|
|
||||||
set_option_value(name, token);
|
if (token == "value" && uip >> value)
|
||||||
|
{
|
||||||
|
while (uip >> token)
|
||||||
|
value += (" " + token);
|
||||||
|
|
||||||
|
set_option_value(name, value);
|
||||||
} else
|
} else
|
||||||
push_button(name);
|
push_button(name);
|
||||||
}
|
}
|
||||||
@@ -276,10 +266,8 @@ namespace {
|
|||||||
|
|
||||||
searchMoves[0] = MOVE_NONE;
|
searchMoves[0] = MOVE_NONE;
|
||||||
|
|
||||||
while (!uip.eof())
|
while (uip >> token)
|
||||||
{
|
{
|
||||||
uip >> token;
|
|
||||||
|
|
||||||
if (token == "infinite")
|
if (token == "infinite")
|
||||||
infinite = true;
|
infinite = true;
|
||||||
else if (token == "ponder")
|
else if (token == "ponder")
|
||||||
@@ -303,18 +291,13 @@ namespace {
|
|||||||
else if (token == "searchmoves")
|
else if (token == "searchmoves")
|
||||||
{
|
{
|
||||||
int numOfMoves = 0;
|
int numOfMoves = 0;
|
||||||
while (!uip.eof())
|
while (uip >> token)
|
||||||
{
|
|
||||||
uip >> token;
|
|
||||||
searchMoves[numOfMoves++] = move_from_string(RootPosition, token);
|
searchMoves[numOfMoves++] = move_from_string(RootPosition, token);
|
||||||
}
|
|
||||||
searchMoves[numOfMoves] = MOVE_NONE;
|
searchMoves[numOfMoves] = MOVE_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moveTime)
|
|
||||||
infinite = true; // HACK
|
|
||||||
|
|
||||||
assert(RootPosition.is_ok());
|
assert(RootPosition.is_ok());
|
||||||
|
|
||||||
return think(RootPosition, infinite, ponder, RootPosition.side_to_move(),
|
return think(RootPosition, infinite, ponder, RootPosition.side_to_move(),
|
||||||
@@ -327,10 +310,9 @@ namespace {
|
|||||||
int depth, tm, n;
|
int depth, tm, n;
|
||||||
Position pos = RootPosition;
|
Position pos = RootPosition;
|
||||||
|
|
||||||
if (uip.eof())
|
if (!(uip >> depth))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uip >> depth;
|
|
||||||
tm = get_system_time();
|
tm = get_system_time();
|
||||||
|
|
||||||
n = perft(pos, depth * OnePly);
|
n = perft(pos, depth * OnePly);
|
||||||
|
|||||||
+32
-11
@@ -122,8 +122,8 @@ namespace {
|
|||||||
o["Randomness"] = Option(0, 0, 10);
|
o["Randomness"] = Option(0, 0, 10);
|
||||||
o["Minimum Split Depth"] = Option(4, 4, 7);
|
o["Minimum Split Depth"] = Option(4, 4, 7);
|
||||||
o["Maximum Number of Threads per Split Point"] = Option(5, 4, 8);
|
o["Maximum Number of Threads per Split Point"] = Option(5, 4, 8);
|
||||||
o["Threads"] = Option(1, 1, 8);
|
o["Threads"] = Option(1, 1, THREAD_MAX);
|
||||||
o["Hash"] = Option(32, 4, 4096);
|
o["Hash"] = Option(32, 4, 8192);
|
||||||
o["Clear Hash"] = Option(false, BUTTON);
|
o["Clear Hash"] = Option(false, BUTTON);
|
||||||
o["New Game"] = Option(false, BUTTON);
|
o["New Game"] = Option(false, BUTTON);
|
||||||
o["Ponder"] = Option(true);
|
o["Ponder"] = Option(true);
|
||||||
@@ -196,15 +196,18 @@ void init_uci_options() {
|
|||||||
|
|
||||||
load_defaults(options);
|
load_defaults(options);
|
||||||
|
|
||||||
// Limit the default value of "Threads" to 7 even if we have 8 CPU cores.
|
// Set optimal value for parameter "Minimum Split Depth"
|
||||||
// According to Ken Dail's tests, Glaurung plays much better with 7 than
|
// according to number of available cores.
|
||||||
// with 8 threads. This is weird, but it is probably difficult to find out
|
|
||||||
// why before I have a 8-core computer to experiment with myself.
|
|
||||||
assert(options.find("Threads") != options.end());
|
assert(options.find("Threads") != options.end());
|
||||||
assert(options.find("Minimum Split Depth") != options.end());
|
assert(options.find("Minimum Split Depth") != options.end());
|
||||||
|
|
||||||
options["Threads"].defaultValue = stringify(Min(cpu_count(), 7));
|
Option& thr = options["Threads"];
|
||||||
options["Threads"].currentValue = stringify(Min(cpu_count(), 7));
|
Option& msd = options["Minimum Split Depth"];
|
||||||
|
|
||||||
|
thr.defaultValue = thr.currentValue = stringify(cpu_count());
|
||||||
|
|
||||||
|
if (cpu_count() >= 8)
|
||||||
|
msd.defaultValue = msd.currentValue = stringify(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -292,10 +295,28 @@ void set_option_value(const string& name, const string& value) {
|
|||||||
else if (v == "false")
|
else if (v == "false")
|
||||||
v = "0";
|
v = "0";
|
||||||
|
|
||||||
if (options.find(name) != options.end())
|
if (options.find(name) == options.end())
|
||||||
options[name].currentValue = v;
|
{
|
||||||
else
|
|
||||||
std::cout << "No such option: " << name << std::endl;
|
std::cout << "No such option: " << name << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normally it's up to the GUI to check for option's limits,
|
||||||
|
// but we could receive the new value directly from the user
|
||||||
|
// by teminal window. So let's check the bounds anyway.
|
||||||
|
Option& opt = options[name];
|
||||||
|
|
||||||
|
if (opt.type == CHECK && v != "0" && v != "1")
|
||||||
|
return;
|
||||||
|
|
||||||
|
else if (opt.type == SPIN)
|
||||||
|
{
|
||||||
|
int val = atoi(v.c_str());
|
||||||
|
if (val < opt.minValue || val > opt.maxValue)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
opt.currentValue = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+19
-5
@@ -48,17 +48,31 @@ enum Value {
|
|||||||
VALUE_KNOWN_WIN = 15000,
|
VALUE_KNOWN_WIN = 15000,
|
||||||
VALUE_MATE = 30000,
|
VALUE_MATE = 30000,
|
||||||
VALUE_INFINITE = 30001,
|
VALUE_INFINITE = 30001,
|
||||||
VALUE_NONE = 30002
|
VALUE_NONE = 30002,
|
||||||
|
VALUE_ENSURE_SIGNED = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Score struct keeps a midgame and an endgame value in a single
|
/// Score enum keeps a midgame and an endgame value in a single
|
||||||
/// ScoreValue 64 bit union.
|
/// integer (enum), first LSB 16 bits are used to store endgame
|
||||||
|
/// value, while upper bits are used for midgame value.
|
||||||
|
|
||||||
enum Score {};
|
// Compiler is free to choose the enum type as long as can keep
|
||||||
|
// its data, so ensure Score to be an integer type.
|
||||||
|
enum Score { ENSURE_32_BITS_SIZE_P = (1 << 16), ENSURE_32_BITS_SIZE_N = -(1 << 16)};
|
||||||
|
|
||||||
|
// Extracting the _signed_ lower and upper 16 bits it not so trivial
|
||||||
|
// because according to the standard a simple cast to short is
|
||||||
|
// implementation defined and so is a right shift of a signed integer.
|
||||||
|
inline Value mg_value(Score s) { return Value(((int(s) + 32768) & ~0xffff) / 0x10000); }
|
||||||
|
|
||||||
|
// Unfortunatly on Intel 64 bit we have a small speed regression, so use a faster code in
|
||||||
|
// this case, although not 100% standard compliant it seems to work for Intel and MSVC.
|
||||||
|
#if defined(IS_64BIT) && (!defined(__GNUC__) || defined(__INTEL_COMPILER))
|
||||||
inline Value eg_value(Score s) { return Value(int16_t(s & 0xffff)); }
|
inline Value eg_value(Score s) { return Value(int16_t(s & 0xffff)); }
|
||||||
inline Value mg_value(Score s) { return Value((int(s) + 32768) >> 16); }
|
#else
|
||||||
|
inline Value eg_value(Score s) { return Value((int)(unsigned(s) & 0x7fffu) - (int)(unsigned(s) & 0x8000u)); }
|
||||||
|
#endif
|
||||||
|
|
||||||
inline Score make_score(int mg, int eg) { return Score((mg << 16) + eg); }
|
inline Score make_score(int mg, int eg) { return Score((mg << 16) + eg); }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user