simpleHashRecord.h
Go to the documentation of this file.
00001 /* simpleHashRecord.h
00002  */
00003 #ifndef OSL_SEARCH_SIMPLEHASHRECORD_H
00004 #define OSL_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, int logprob=100) 
00066       {
00067         assert(! m.isInvalid());
00068         // 普通の更新はsetLowerBoundで。
00069         best_move = MoveLogProb(m, logprob);
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           // best move はupper boundでは基本的には更新しない
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   } // namespace search
00257 
00258   using search::SimpleHashRecord;
00259 } // namespace osl
00260 
00261 
00262 #endif /* OSL_SEARCH_SIMPLEHASHRECORD_H */
00263 // ;;; Local Variables:
00264 // ;;; mode:c++
00265 // ;;; c-basic-offset:2
00266 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines