Compare commits

...

8 Commits

Author SHA1 Message Date
Marco Costalba 86c2d2fc3b Stockfish 1.7.1
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 16:48:25 +01:00
Marco Costalba f9d3b48ad0 Introduce "Zugzwang detection" temporary hack for 1.7.1
Add an UCI option "Zugzwang detection" OFF by default that
enables correct detection of zugzwang.

This is just to let 1.7.1 be 100% compatible with 1.7 and
should be removed after release.

Verified 100% functional equivalent to 1.7

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 16:41:40 +01:00
Marco Costalba d720778b2b Revert HT detection
Fall back on 1.6.3 behaviour.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 11:35:30 +01:00
Marco Costalba e2880f9b8e Revert last patch
It fails in test position:

8/7P/8/8/K2b4/p7/1k6/1B6 b - -

Not clear why but we revert because it fixes the issue.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 11:16:55 +01:00
Marco Costalba 909e3adede Relax TT condition for zugzwang verified null values
In this case use a normal VALUE_TYPE_LOWER TT type instead of
VALUE_TYPE_NS_LO. This allow us to TT cut-off in a bit more nodes.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 10:48:08 +01:00
Marco Costalba 626b1f8c6a Avoid TT cutoffs at root of null zugzwang verification
This patch fixes an issue with zugzwang well explained by Tord:

"Assume that a zugzwang position occurs at iteration N,
at a search depth d, with d < 6*OnePly. The null move search
fails high, and no verification search is done, because the
depth is too small. The position gets stored in the transposition
table with a good score and a depth of d.

Now, consider what happens when the same position occurs at iteration
N+1, this time with a depth of d+OnePly (i.e. one ply deeper than at
the previous iteration). Once again, the null move search fails
high. The point is that the verification search will also fail high,
because of an instant transposition table cutoff caused by the value
stored in the TT during the previous iteration."

With this patch we simply do not allow TT cutoffs at the root node
of a null move verification search if the TT value was found by a
null search.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 10:35:29 +01:00
Marco Costalba 06a350f1ae Use a flag in TT to track null search values
Add VALUE_TYPE_NS_LO to enum ValueType and use it when
saving in TT a value from a null search.

Currently no action is performed, the next patch will enable
the new type.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-10 10:07:53 +01:00
Marco Costalba a9e9746495 Fix a warning under HP-UX ANSI C++
Reported warning is:

warning #2514-D: pointless comparison of unsigned
                 integer with a negative constant

Spotted by Richard Lloyd.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
2010-04-09 07:54:00 +01:00
6 changed files with 41 additions and 75 deletions
+2 -1
View File
@@ -27,7 +27,8 @@
enum Depth {
DEPTH_ZERO = 0,
DEPTH_MAX = 200 // 100 * OnePly;
DEPTH_MAX = 200, // 100 * OnePly;
DEPTH_ENSURE_SIGNED = -1
};
+10 -56
View File
@@ -41,20 +41,20 @@
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <sstream>
#include "bitcount.h"
#include "misc.h"
#include "thread.h"
using namespace std;
/// Version number. If this is left empty, the current date (in the format
/// YYMMDD) is used as a version number.
static const string EngineVersion = "1.7";
static const string EngineVersion = "1.7.1";
static const string AppName = "Stockfish";
static const string AppTag = "";
@@ -183,85 +183,39 @@ int get_system_time() {
}
/// builtin_cpu_count() tries to detect the number of CPU cores, if
/// hyper-threading is enabled this is the number of logical processors.
/// cpu_count() tries to detect the number of CPU cores.
#if !defined(_MSC_VER)
# if defined(_SC_NPROCESSORS_ONLN)
static int builtin_cpu_count() {
return Min(sysconf(_SC_NPROCESSORS_ONLN), 8);
int cpu_count() {
return Min(sysconf(_SC_NPROCESSORS_ONLN), MAX_THREADS);
}
# elif defined(__hpux)
static int builtin_cpu_count() {
int cpu_count() {
struct pst_dynamic psd;
if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) == -1)
return 1;
return Min(psd.psd_proc_cnt, 8);
return Min(psd.psd_proc_cnt, MAX_THREADS);
}
# else
static int builtin_cpu_count() {
int cpu_count() {
return 1;
}
# endif
#else
static int builtin_cpu_count() {
int cpu_count() {
SYSTEM_INFO s;
GetSystemInfo(&s);
return Min(s.dwNumberOfProcessors, 8);
return Min(s.dwNumberOfProcessors, MAX_THREADS);
}
#endif
/// HT_enabled() returns true if hyper-threading is enabled on current machine
static bool HT_enabled() {
char CPUString[0x20];
int CPUInfo[4] = {-1};
int nIds, nLogicalCPU, nCores;
// Detect CPU producer
__cpuid(CPUInfo, 0);
nIds = CPUInfo[0];
memset(CPUString, 0, sizeof(CPUString));
memcpy(&CPUString[0], &CPUInfo[1], sizeof(int));
memcpy(&CPUString[4], &CPUInfo[3], sizeof(int));
memcpy(&CPUString[8], &CPUInfo[2], sizeof(int));
// Not an Intel CPU or CPUID.4 not supported
if (strcmp(CPUString, "GenuineIntel") || nIds < 4)
return false;
// Detect if HT Technology is supported
__cpuid(CPUInfo, 1);
if (!((CPUInfo[3] >> 28) & 1))
return false;
nLogicalCPU = (CPUInfo[1] >> 16) & 0xFF;
// Detect number of cores
__cpuid(CPUInfo, 4);
nCores = 1 + ((CPUInfo[0] >> 26) & 0x3F);
return nLogicalCPU > nCores;
}
/// cpu_count() tries to detect the number of physical CPU cores taking
/// in account hyper-threading.
int cpu_count() {
return HT_enabled() ? builtin_cpu_count() / 2 : builtin_cpu_count();
}
/*
From Beowulf, from Olithink
*/
+15 -10
View File
@@ -257,7 +257,7 @@ namespace {
int SearchStartTime, MaxNodes, MaxDepth, MaxSearchTime;
int AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime;
bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
bool FirstRootMove, AbortSearch, Quit, AspirationFailLow;
bool FirstRootMove, AbortSearch, Quit, AspirationFailLow, ZugDetection;
// Log file
bool UseLogFile;
@@ -294,7 +294,7 @@ namespace {
Depth extension(const Position&, Move, bool, bool, bool, bool, bool, bool*);
bool ok_to_do_nullmove(const Position& pos);
bool ok_to_prune(const Position& pos, Move m, Move threat);
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply);
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply, bool allowNullmove);
Value refine_eval(const TTEntry* tte, Value defaultEval, int ply);
void update_history(const Position& pos, Move move, Depth depth, Move movesSearched[], int moveCount);
void update_killers(Move m, SearchStack& ss);
@@ -425,6 +425,7 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
MultiPV = get_option_value_int("MultiPV");
Chess960 = get_option_value_bool("UCI_Chess960");
UseLogFile = get_option_value_bool("Use Search Log");
ZugDetection = get_option_value_bool("Zugzwang detection"); // To be removed after 1.7.1
if (UseLogFile)
LogFile.open(get_option_value_string("Search Log Filename").c_str(), std::ios::out | std::ios::app);
@@ -1299,7 +1300,7 @@ namespace {
tte = TT.retrieve(posKey);
ttMove = (tte ? tte->move() : MOVE_NONE);
if (tte && ok_to_use_TT(tte, depth, beta, ply))
if (tte && ok_to_use_TT(tte, depth, beta, ply, allowNullmove))
{
ss[ply].currentMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
@@ -1388,7 +1389,7 @@ namespace {
{
assert(value_to_tt(nullValue, ply) == nullValue);
TT.store(posKey, nullValue, VALUE_TYPE_LOWER, depth, MOVE_NONE);
TT.store(posKey, nullValue, VALUE_TYPE_NS_LO, depth, MOVE_NONE);
return nullValue;
}
} else {
@@ -1625,7 +1626,7 @@ namespace {
tte = TT.retrieve(pos.get_key());
ttMove = (tte ? tte->move() : MOVE_NONE);
if (!pvNode && tte && ok_to_use_TT(tte, depth, beta, ply))
if (!pvNode && tte && ok_to_use_TT(tte, depth, beta, ply, true))
{
assert(tte->type() != VALUE_TYPE_EVAL);
@@ -1666,7 +1667,7 @@ namespace {
alpha = bestValue;
// If we are near beta then try to get a cutoff pushing checks a bit further
bool deepChecks = depth == -OnePly && staticValue >= beta - PawnValueMidgame / 8;
bool deepChecks = (depth == -OnePly && staticValue >= beta - PawnValueMidgame / 8);
// Initialize a MovePicker object for the current position, and prepare
// to search the moves. Because the depth is <= 0 here, only captures,
@@ -2306,14 +2307,18 @@ namespace {
}
// ok_to_use_TT() returns true if a transposition table score
// can be used at a given point in search.
// ok_to_use_TT() returns true if a transposition table score can be used at a
// given point in search. To avoid zugzwang issues TT cutoffs at the root node
// of a null move verification search are not allowed if the TT value was found
// by a null search, this is implemented testing allowNullmove and TT entry type.
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply) {
bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply, bool allowNullmove) {
Value v = value_from_tt(tte->value(), ply);
return ( tte->depth() >= depth
return (allowNullmove || !(tte->type() & VALUE_TYPE_NULL) || !ZugDetection)
&& ( tte->depth() >= depth
|| v >= Max(value_mate_in(PLY_MAX), beta)
|| v < Min(value_mated_in(PLY_MAX), beta))
+4 -4
View File
@@ -46,8 +46,8 @@
/// the 32 bits of the data field are so defined
///
/// bit 0-16: move
/// bit 17-19: not used
/// bit 20-22: value type
/// bit 17-18: not used
/// bit 19-22: value type
/// bit 23-31: generation
class TTEntry {
@@ -55,14 +55,14 @@ class TTEntry {
public:
TTEntry() {}
TTEntry(uint32_t k, Value v, ValueType t, Depth d, Move m, int generation)
: key_ (k), data((m & 0x1FFFF) | (t << 20) | (generation << 23)),
: key_ (k), data((m & 0x1FFFF) | (t << 19) | (generation << 23)),
value_(int16_t(v)), depth_(int16_t(d)) {}
uint32_t key() const { return key_; }
Depth depth() const { return Depth(depth_); }
Move move() const { return Move(data & 0x1FFFF); }
Value value() const { return Value(value_); }
ValueType type() const { return ValueType((data >> 20) & 7); }
ValueType type() const { return ValueType((data >> 19) & 0xF); }
int generation() const { return (data >> 23); }
private:
+3
View File
@@ -113,6 +113,9 @@ namespace {
o["UCI_Chess960"] = Option(false);
o["UCI_AnalyseMode"] = Option(false);
// Temporary hack for 1.7.1 to be removed in next release
o["Zugzwang detection"] = Option(false);
// Any option should know its name so to be easily printed
for (Options::iterator it = o.begin(); it != o.end(); ++it)
it->second.name = it->first;
+7 -4
View File
@@ -33,13 +33,16 @@
////
enum ValueType {
VALUE_TYPE_NONE = 0,
VALUE_TYPE_NONE = 0,
VALUE_TYPE_UPPER = 1, // Upper bound
VALUE_TYPE_LOWER = 2, // Lower bound
VALUE_TYPE_EXACT = 3, // Exact score
VALUE_TYPE_EVAL = 4, // Evaluation cache
VALUE_TYPE_EV_UP = 5, // Evaluation cache for upper bound
VALUE_TYPE_EV_LO = 6 // Evaluation cache for lower bound
VALUE_TYPE_EVAL = 4, // Static evaluation value
VALUE_TYPE_NULL = 8, // Null search value
VALUE_TYPE_EV_UP = VALUE_TYPE_EVAL | VALUE_TYPE_UPPER,
VALUE_TYPE_EV_LO = VALUE_TYPE_EVAL | VALUE_TYPE_LOWER,
VALUE_TYPE_NS_LO = VALUE_TYPE_NULL | VALUE_TYPE_LOWER,
};