quiescenceRecord.h
Go to the documentation of this file.
00001 /* quiescenceRecord.h
00002  */
00003 #ifndef _QUIESCENCERECORD_H
00004 #define _QUIESCENCERECORD_H
00005 
00006 #include "osl/search/dualThreatmateState.h"
00007 #include "osl/ptype.h"
00008 #include "osl/move.h"
00009 #include "osl/container/moveVector.h"
00010 #include "osl/stl/vector.h"
00011 #include <iosfwd>
00012 #ifdef OSL_SMP
00013 #  include "osl/misc/lightMutex.h"
00014 #endif
00015 
00016 namespace osl
00017 {
00018   namespace search
00019   {
00020     struct QSearchTraits
00021     {
00022       enum { 
00024         MaxDepth = 8,
00026         CheckmateSpecialDepth = 127,
00028         HistorySpecialDepth = 126,
00029       };
00030       enum { FirstThreat = 6, SecondThreat = 2 };
00031       enum MoveType { 
00032         UNKNOWN, KING_ESCAPE, CAPTURE, PROMOTE, CHECK,
00033         ESCAPE, ATTACK, OTHER, 
00034       };
00035     };
00036 
00040     struct QuiescenceThreat
00041     {
00042       int value;
00043       Move move;
00044       explicit QuiescenceThreat(int v=0, Move m=Move::INVALID()) 
00045         : value(v), move(m)
00046       {
00047       }
00048     };    
00049 
00050     struct BestMoves : public CArray<Move,4>
00051     {
00052       BestMoves()
00053       {
00054         // automaticallyfilled by invalid data by constructor
00055       }
00056       size_t capacity() const { return size(); }
00057       size_t sizeFilled() const
00058       {
00059         for (size_t i=0; i<capacity(); ++i)
00060           if (! operator[](i).isNormal())
00061             return i;
00062         return capacity();
00063       }
00064       void add(Move m)
00065       {
00066         if (! m.isNormal())
00067           return;
00068         iterator p = std::find(begin(), end(), m);
00069         if (p != end()) {
00070           std::rotate(begin(), p, p+1);
00071           return;
00072         }
00073         size_t size = sizeFilled();
00074         if (size == capacity())
00075           operator[](capacity()-1) = m;
00076         else
00077           operator[](size++) = m;
00078         std::rotate(begin(), begin()+(int)size-1, begin()+(int)size);
00079       }
00080       void clear()
00081       {
00082         fill(Move());
00083       }
00084       void addSecondary(const MoveVector& v) 
00085       {
00086         CArray<Move,4> copy = *this;
00087         clear();
00088         size_t size = 0;
00089         if (copy[0].isNormal())
00090           operator[](size++) = copy[0];
00091         for (size_t i=0; i<v.size() && size<capacity(); ++i) {
00092           assert(v[i].isNormal());
00093           if (std::find(begin(), begin()+(int)size, v[i]) == begin()+(int)size)
00094             operator[](size++) = v[i];
00095         }
00096         for (size_t i=1; i<copy.size() && copy[i].isNormal() && size<capacity(); ++i)
00097           if (std::find(begin(), begin()+(int)size, copy[i]) == begin()+(int)size)
00098             operator[](size++) = copy[i];
00099       }
00100     };
00101     
00105     struct QuiescenceRecordBase
00106     {
00107       int upper_bound, lower_bound;
00108       BestMoves best_moves;
00110       QuiescenceThreat threat1, threat2;
00111       int static_value;
00112       int checkmate_nodes;
00113       DualThreatmateState threatmate;
00114       int threatmate_nodes;
00116       int8_t upper_depth, lower_depth, static_value_depth;
00117     public:
00122       enum { InitialDepth = -128, };
00123       enum StaticValueType { UNKNOWN, UPPER_BOUND, EXACT };
00124     protected:
00125       QuiescenceRecordBase() 
00126         : checkmate_nodes(0), threatmate_nodes(0),
00127           upper_depth(InitialDepth), lower_depth(InitialDepth),
00128           static_value_depth(InitialDepth)
00129       {
00130       }
00131       ~QuiescenceRecordBase() {}
00132     };
00133     class SimpleHashRecord;
00137     class QuiescenceRecord : public QuiescenceRecordBase
00138     {
00139     public:
00140       static const char *toString(StaticValueType);
00141     private:
00142 #ifdef OSL_SMP
00143       typedef osl::misc::LightMutexChar Mutex;
00144       mutable Mutex mutex;
00145 #endif
00146     public:
00147       QuiescenceRecord()
00148       {
00149       }
00153       QuiescenceRecord(const QuiescenceRecord& src)
00154         : QuiescenceRecordBase(src)
00155       {
00156       }
00157       QuiescenceRecord& operator=(const QuiescenceRecord& src)
00158       {
00159         if (this == &src)
00160           return *this;
00161         
00162         QuiescenceRecordBase::operator=(src);
00163         return *this;
00164       }
00165 
00166       template <Player Turn>
00167       const Square8 sendOffSquare(const NumEffectState& state) const
00168       {
00169 #ifdef OSL_SMP
00170         SCOPED_LOCK_CHAR(lk,mutex);
00171 #endif
00172         assert(Turn == state.turn());
00173         Square8 ret;
00174         const Square king_position = state.kingSquare(alt(Turn));
00175         if (threatmate.sendoffs == SendOffSquare::invalidData())
00176           threatmate.sendoffs = SendOffSquare::find<Turn>(state, king_position, ret);
00177         else
00178           SendOffSquare::unpack(threatmate.sendoffs, king_position, ret);
00179         return ret;
00180       }
00181       const Square8
00182       sendOffSquare(Player turn, const NumEffectState& state) const
00183       {
00184         if (turn == BLACK)
00185           return sendOffSquare<BLACK>(state);
00186         else
00187           return sendOffSquare<WHITE>(state);
00188       }
00193       int checkmateNodesLeft(int max)
00194       {
00195 #ifdef OSL_SMP
00196         SCOPED_LOCK_CHAR(lk,mutex);
00197 #endif
00198         if (max > checkmate_nodes)
00199         {
00200           const int left = max - checkmate_nodes;
00201           checkmate_nodes = max;
00202           return left;
00203         }
00204         return 0;
00205       }
00210       int threatmateNodesLeft(int max)
00211       {
00212 #ifdef OSL_SMP
00213         SCOPED_LOCK_CHAR(lk,mutex);
00214 #endif
00215         if (max > threatmate_nodes)
00216         {
00217           const int left = max - threatmate_nodes;
00218           threatmate_nodes = max;
00219           return left;
00220         }
00221         return 0;
00222       }
00224       int checkmateNodes() const { return checkmate_nodes; }
00225       int threatmateNodes() const { return threatmate_nodes; }
00226 
00227       void clear()
00228       {
00229 #ifdef OSL_SMP
00230         SCOPED_LOCK_CHAR(lk,mutex);
00231 #endif
00232         best_moves.clear();
00233         upper_depth = lower_depth = static_value_depth = InitialDepth;
00234       }
00235       void setStaticValue(StaticValueType type, int value, int depth,
00236                           const QuiescenceThreat& t1=QuiescenceThreat(),
00237                           const QuiescenceThreat& t2=QuiescenceThreat())
00238       {
00239 #ifdef OSL_SMP
00240         SCOPED_LOCK_CHAR(lk,mutex);
00241 #endif
00242         assert((depth <= QSearchTraits::MaxDepth)
00243                || (depth == QSearchTraits::CheckmateSpecialDepth));
00244         assert(value % 2 == 0);
00245         static_value = value;
00246         threat1 = t1;
00247         threat2 = t2;
00248         static_value_depth = depth;
00249         threatmate.flags.static_value_type = type;
00250       }
00251     public:
00252       void setLowerBound(int depth, int bound, Move best_move)
00253       {
00254 #ifdef OSL_SMP
00255         SCOPED_LOCK_CHAR(lk,mutex);
00256 #endif
00257         assert((depth <= QSearchTraits::MaxDepth)
00258                || (depth == QSearchTraits::CheckmateSpecialDepth));
00259         if (depth >= lower_depth)
00260         {
00261           best_moves.add(best_move);
00262           lower_bound = bound;
00263           lower_depth = depth;
00264         }
00265       }
00266       void setUpperBound(int depth, int bound)
00267       {
00268 #ifdef OSL_SMP
00269         SCOPED_LOCK_CHAR(lk,mutex);
00270 #endif
00271         assert((depth <= QSearchTraits::MaxDepth)
00272                || (depth == QSearchTraits::CheckmateSpecialDepth));
00273         if (depth >= upper_depth)
00274         {
00275           upper_bound = bound;
00276           upper_depth = depth;
00277         }
00278       }
00279       void setHistoryValue(int value)
00280       {
00281         lower_bound = upper_bound = value;
00282         lower_depth = upper_depth = QSearchTraits::HistorySpecialDepth;
00283       }
00284       void setHistoryValue(Move best_move, int value)
00285       {
00286 #ifdef OSL_SMP
00287         SCOPED_LOCK_CHAR(lk,mutex);
00288 #endif
00289         best_moves.add(best_move);
00290         setHistoryValue(value);
00291       }
00292     public:
00293       void addKillerMoves(const MoveVector& new_moves)
00294       {
00295 #ifdef OSL_SMP
00296         SCOPED_LOCK_CHAR(lk,mutex);
00297 #endif  
00298         best_moves.addSecondary(new_moves);
00299       }
00300       StaticValueType staticValueType() const { 
00301         return static_cast<StaticValueType>(threatmate.flags.static_value_type); 
00302       }
00303       bool hasStaticValue() const { return staticValueType() != UNKNOWN; }
00304       bool hasStaticValue(int& value, int& depth, StaticValueType& type) const {
00305         type = staticValueType();
00306         if (type == UNKNOWN)
00307           return false;
00308 #ifdef OSL_SMP
00309         SCOPED_LOCK_CHAR(lk,mutex);
00310 #endif  
00311         type = staticValueType();       
00312         value = static_value;
00313         depth = static_value_depth;
00314         return type != UNKNOWN;
00315       }
00316       int staticValue() const { assert(hasStaticValue()); return static_value; }
00317       int staticValueDepth() const { return static_value_depth; }
00318       int upperDepth() const { return upper_depth; }
00319       int lowerDepth() const { return lower_depth; }
00320       int upperBound() const { return upper_bound; }
00321       int lowerBound() const { return lower_bound; }
00322       const Move bestMove() const { return best_moves[0]; }
00323       int movesEmpty() const { return ! best_moves[1].isNormal(); }
00324       int movesSizeLessThan(size_t n) const { 
00325         return best_moves.capacity() < n || ! best_moves[n-1].isNormal(); 
00326       }
00327       int moves_size() const { 
00328         return std::max(0, (int)best_moves.sizeFilled()-1); 
00329       }
00330       void loadMoves(MoveVector& dst) const{
00331 #ifdef OSL_SMP
00332         SCOPED_LOCK_CHAR(lk,mutex);
00333 #endif
00334         dst.clear();
00335         for (size_t i=1; i<best_moves.capacity() && best_moves[i].isNormal(); ++i)
00336           dst.push_back(best_moves[i]);
00337       }
00338       void dump(std::ostream&) const;
00339       const QuiescenceThreat staticThreat(int index) const
00340       {
00341         return (index == 0) ? threat1 : threat2;
00342       }
00343       void updateThreatmate(Player turn, const DualThreatmateState *parent, bool in_check)
00344       {
00345 #ifdef OSL_SMP
00346         SCOPED_LOCK_CHAR(lk,mutex);
00347 #endif
00348         threatmate.updateInLock(turn, parent, in_check);
00349       }
00350       friend class SimpleHashRecord;
00351     };
00352     
00353   } // namespace search
00354 } // namespace osl
00355 
00356 #endif /* _QUIESCENCERECORD_H */
00357 // ;;; Local Variables:
00358 // ;;; mode:c++
00359 // ;;; c-basic-offset:2
00360 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines