00001
00002
00003 #ifndef _SEARCH_SIMPLEHASHRECORD_H
00004 #define _SEARCH_SIMPLEHASHRECORD_H
00005
00006 #include "osl/search/quiescenceRecord.h"
00007 #include "osl/search/searchTable.h"
00008 #include "osl/eval/evalTraits.h"
00009 #include "osl/moveLogProb.h"
00010 #ifdef OSL_SMP
00011 # include "osl/misc/lightMutex.h"
00012 #endif
00013 #include <cassert>
00014
00015 namespace osl
00016 {
00017 namespace search
00018 {
00022 class SimpleHashRecord
00023 {
00024 public:
00026 QuiescenceRecord qrecord;
00027 private:
00028 MoveLogProb best_move;
00029 int upper_bound;
00030 int lower_bound;
00031 signed short upper_limit;
00032 signed short lower_limit;
00034 unsigned int search_nodes;
00035 public:
00036 SimpleHashRecord()
00037 : upper_limit(-1), lower_limit(-1), search_nodes(0)
00038 {
00039 }
00040 void addNodeCount(size_t diff)
00041 {
00042 #ifdef OSL_SMP
00043 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00044 #endif
00045 search_nodes += diff;
00046 }
00047
00051 void setAbsoluteValue(Move best_move, int value, int limit)
00052 {
00053 #ifdef OSL_SMP
00054 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00055 #endif
00056 lower_limit = limit;
00057 lower_bound = value;
00058 upper_limit = limit;
00059 upper_bound = value;
00060 if (best_move.isNormal())
00061 this->best_move = MoveLogProb(best_move, 100);
00062 else
00063 this->best_move = MoveLogProb();
00064 }
00065 void setBestMove(Move m)
00066 {
00067 assert(! m.isInvalid());
00068
00069 best_move = MoveLogProb(m, 100);
00070 qrecord.best_moves.add(m);
00071 }
00072 void setAbsoluteValue(MoveLogProb best_move, int value, int limit)
00073 {
00074 #ifdef OSL_SMP
00075 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00076 #endif
00077 lower_limit = limit;
00078 lower_bound = value;
00079 upper_limit = limit;
00080 upper_bound = value;
00081 this->best_move = best_move;
00082 }
00083
00089 void setLowerBound(Player P, int limit, const MoveLogProb& best_move,
00090 int value)
00091 {
00092 #ifdef OSL_SMP
00093 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00094 #endif
00095 assert((value % 2) == 0);
00096 assert(limit >= 0);
00097 if (limit < lower_limit)
00098 return;
00099 if (best_move.validMove())
00100 this->best_move= best_move;
00101 lower_bound = value;
00102 lower_limit = limit;
00103 if (hasUpperBound(0))
00104 makeConsistent<true>(P);
00105 }
00106
00112 void setUpperBound(Player P, int limit, const MoveLogProb& best_move,
00113 int value)
00114 {
00115 #ifdef OSL_SMP
00116 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00117 #endif
00118 assert((value % 2) == 0);
00119 assert(limit >= 0);
00120 if (limit < upper_limit)
00121 return;
00122 if (best_move.validMove()
00123 && (! this->best_move.validMove()))
00124 {
00125
00126 this->best_move= best_move;
00127 }
00128 upper_bound = value;
00129 upper_limit = limit;
00130 if (hasLowerBound(0))
00131 makeConsistent<false>(P);
00132 }
00133 private:
00139 template <bool PreferLowerBound>
00140 void makeConsistent(Player P)
00141 {
00142 assert(hasLowerBound(0) && hasUpperBound(0));
00143 if (! eval::betterThan(P, lower_bound, upper_bound))
00144 return;
00145 if ((upper_limit < lower_limit)
00146 || (PreferLowerBound && (upper_limit == lower_limit)))
00147 {
00148 upper_bound = lower_bound;
00149 assert((upper_bound % 2) == 0);
00150 }
00151 else
00152 {
00153 lower_bound = upper_bound;
00154 assert((lower_bound % 2) == 0);
00155 }
00156 }
00157 public:
00159 int upperLimit() const { return upper_limit; }
00161 int upperBound() const { return upper_bound; }
00163 int lowerLimit() const { return lower_limit; }
00165 int lowerBound() const { return lower_bound; }
00167 int checkmateNodes() const { return qrecord.checkmate_nodes; }
00168 int threatmateNodes() const { return qrecord.threatmate_nodes; }
00169 const MoveLogProb bestMove() const {
00170 #ifdef OSL_SMP
00171 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00172 #endif
00173 return best_move;
00174 }
00175
00176 bool hasUpperBound(int limit) const
00177 {
00178 return (upperLimit() >= limit);
00179 }
00180 bool hasLowerBound(int limit) const
00181 {
00182 return (lowerLimit() >= limit);
00183 }
00184 bool hasAbsoluteUpperBound(Player p, int limit) const
00185 {
00186 return (p == BLACK) ? hasUpperBound(limit) : hasLowerBound(limit);
00187 }
00188 bool hasAbsoluteLowerBound(Player p, int limit) const
00189 {
00190 return (p == BLACK) ? hasLowerBound(limit) : hasUpperBound(limit);
00191 }
00192 int absoluteUpperBound(Player p) const
00193 {
00194 return (p == BLACK) ? upperBound() : lowerBound();
00195 }
00196 int absoluteLowerBound(Player p) const
00197 {
00198 return (p == BLACK) ? lowerBound() : upperBound();
00199 }
00200 void resetValue()
00201 {
00202 #ifdef OSL_SMP
00203 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00204 #endif
00205 lower_limit = -1;
00206 upper_limit = -1;
00207 }
00209 template <Player P>
00210 bool hasGreaterLowerBound(int limit, int threshold, int& val) const
00211 {
00212 #ifdef OSL_SMP
00213 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00214 #endif
00215 if ((lowerLimit() < limit)
00216 || (EvalTraits<P>::betterThan(threshold, lowerBound())))
00217 return false;
00218 val = lowerBound();
00219 return true;
00220 }
00222 template <Player P>
00223 bool hasLesserUpperBound(int limit, int threshold, int& val) const
00224 {
00225 #ifdef OSL_SMP
00226 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00227 #endif
00228 if ((upperLimit() < limit)
00229 || (EvalTraits<P>::betterThan(upperBound(), threshold)))
00230 return false;
00231 val = upperBound();
00232 return true;
00233 }
00234
00235 const DualThreatmateState& threatmate() const { return qrecord.threatmate; }
00236 DualThreatmateState& threatmate() { return qrecord.threatmate; }
00237
00238 void dump(std::ostream&) const;
00239
00240 size_t nodeCount() const { return search_nodes; }
00241 bool inCheck() const
00242 {
00243 #ifdef OSL_USE_RACE_DETECTOR
00244 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00245 #endif
00246 return qrecord.threatmate.flags.is_king_in_check;
00247 }
00248 void setInCheck(bool new_value)
00249 {
00250 #ifdef OSL_USE_RACE_DETECTOR
00251 SCOPED_LOCK_CHAR(lk,qrecord.mutex);
00252 #endif
00253 qrecord.threatmate.flags.is_king_in_check = new_value;
00254 }
00255 };
00256 }
00257
00258 using search::SimpleHashRecord;
00259 }
00260
00261
00262 #endif
00263
00264
00265
00266