00001
00002
00003 #ifndef OSL_DFPN_H
00004 #define OSL_DFPN_H
00005 #include "osl/checkmate/proofDisproof.h"
00006 #include "osl/checkmate/checkMoveVector.h"
00007 #include "osl/state/numEffectState.h"
00008 #include "osl/container/moveVector.h"
00009 #include "osl/hash/hashKey.h"
00010 #include "osl/stl/vector.h"
00011 #include "osl/pathEncoding.h"
00012 #include "osl/config.h"
00013 #include <boost/scoped_array.hpp>
00014 #include <boost/scoped_ptr.hpp>
00015 #include <boost/noncopyable.hpp>
00016
00017 #ifdef OSL_SMP
00018 # ifndef OSL_DFPN_SMP
00019 # define OSL_DFPN_SMP
00020 # endif
00021 #endif
00022
00023 #ifdef OSL_DFPN_SMP
00024 # include "osl/misc/lightMutex.h"
00025 # include <boost/thread/mutex.hpp>
00026 #endif
00027
00028 #ifndef OSL_DFPN_MAX_DEPTH
00029 # if (OSL_WORDSIZE == 32)
00030 # define OSL_DFPN_MAX_DEPTH 256
00031 # elif defined MINIMAL
00032 # define OSL_DFPN_MAX_DEPTH 256
00033 # else
00034 # define OSL_DFPN_MAX_DEPTH 512
00035 # endif
00036 #endif
00037
00038 namespace osl
00039 {
00040 namespace checkmate
00041 {
00042 class DfpnRecord;
00044 class DfpnTable
00045 {
00046 struct Table;
00047 struct List;
00048 boost::scoped_array<Table> table;
00049 size_t total_size;
00050 public:
00051 DfpnTable(Player attack);
00052 DfpnTable();
00053 ~DfpnTable();
00054 template <Player Attack>
00055 const DfpnRecord probe(const HashKey& key, PieceStand white) const;
00056 const DfpnRecord probe(const HashKey& key, PieceStand white) const;
00057 template <Player Attack>
00058 const DfpnRecord findProofOracle(const HashKey& key, PieceStand white, Move last_move=Move()) const;
00059 const DfpnRecord findProofOracle(const HashKey& key, PieceStand white, Move last_move=Move()) const;
00060 template <Player Attack>
00061 void showProofOracles(const HashKey& key, PieceStand white, Move last_move=Move()) const;
00062 size_t
00063 #ifdef __GNUC__
00064 __attribute__ ((pure))
00065 #endif
00066 size() const;
00067 void showStats() const;
00068
00069 void setAttack(Player);
00070 void setWorking(const HashKey& key, const DfpnRecord& value, int thread_id);
00071 void leaveWorking(const HashKey& key, int thread_id);
00072 void store(const HashKey& key, DfpnRecord& value, int leaving_thread_id=-1);
00073 void addDag(const HashKey& key, DfpnRecord& value);
00074 void clear();
00075 size_t totalSize() { return total_size; }
00076 Player attack() const;
00077
00078 void testTable();
00079 size_t smallTreeGC(size_t threshold=10);
00080 private:
00081 #ifdef OSL_DFPN_SMP
00082 typedef osl::misc::LightMutex Mutex;
00083 # ifdef USE_TBB_HASH
00084 static const int DIVSIZE=1;
00085 # else
00086 static const int DIVSIZE=256;
00087 mutable CArray<Mutex,DIVSIZE> mutex;
00088 # endif
00089
00090
00091 LightMutex root_mutex;
00092 #else
00093 static const int DIVSIZE=1;
00094 #endif
00095 static int keyToIndex(const HashKey& key)
00096 {
00097 unsigned long val=key.signature();
00098 return (val>>24)%DIVSIZE;
00099 }
00100 template <Player Attack>
00101 List *find(const HashKey& key, int subindex);
00102 template <Player Attack>
00103 const List *find(const HashKey& key, int subindex) const;
00104 };
00106 class DfpnPathTable;
00108 class DfpnShared;
00110 class Dfpn : boost::noncopyable
00111 {
00112 public:
00113 enum { MaxDepth = OSL_DFPN_MAX_DEPTH };
00114 enum { DfpnMaxUniqMoves = CheckOrEscapeMaxUniqMoves };
00115 typedef CheckMoveVector DfpnMoveVector;
00116 typedef DfpnTable table_t;
00117 private:
00118 DfpnTable *table;
00119 struct NodeBase;
00120 struct Node;
00121 struct Tree;
00122 boost::scoped_ptr<Tree> tree;
00123 boost::scoped_ptr<DfpnPathTable> path_table;
00124 size_t node_count;
00125 size_t node_count_limit;
00126 DfpnShared *parallel_shared;
00127 int thread_id;
00128 bool blocking_verify;
00129 public:
00130 Dfpn();
00131 ~Dfpn();
00132 void setTable(DfpnTable *new_table) { table = new_table; }
00133 void setIllegal(const HashKey& key, PieceStand white);
00134 void setBlockingVerify(bool enable=true) { blocking_verify = enable; }
00135 void setParallel(int id, DfpnShared *s)
00136 {
00137 if (s)
00138 assert(id >= 0);
00139 thread_id = id;
00140 parallel_shared = s;
00141 }
00142 const ProofDisproof
00143 hasCheckmateMove(const NumEffectState& state, const HashKey& key,
00144 const PathEncoding& path, size_t limit, Move& best_move,
00145 Move last_move=Move::INVALID(), vector<Move> *pv=0);
00146 const ProofDisproof
00147 hasCheckmateMove(const NumEffectState& state, const HashKey& key,
00148 const PathEncoding& path, size_t limit, Move& best_move, PieceStand& proof,
00149 Move last_move=Move::INVALID(), vector<Move> *pv=0);
00150 const ProofDisproof
00151 hasEscapeMove(const NumEffectState& state,
00152 const HashKey& key, const PathEncoding& path,
00153 size_t limit, Move last_move);
00154
00155 size_t nodeCount() const { return node_count; }
00156 const DfpnTable& currentTable() const { return *table; }
00157 void analyze(const PathEncoding& path,
00158 const NumEffectState& state, const vector<Move>& moves) const;
00159 void clear();
00160
00161
00162 template <Player P> void attack();
00163 template <Player P> void defense();
00164 template <Player P> struct CallAttack;
00165 template <Player P> struct CallDefense;
00166 struct DepthLimitReached {};
00167
00168 struct ProofOracle;
00169 template <Player P, bool UseTable> void proofOracleAttack(const ProofOracle& oracle);
00170 template <Player P, bool UseTable> void proofOracleDefense(const ProofOracle& oracle);
00171 template <Player P, bool UseTable> struct CallProofOracleAttack;
00172 template <Player P, bool UseTable> struct CallProofOracleDefense;
00174 template <Player P> void blockingSimulation(int seed, const ProofOracle&);
00175 template <Player P> void grandParentSimulation(int cur_move, const Node& gparent, int gp_move);
00176 private:
00177 template <bool UseTable>
00178 const ProofDisproof
00179 tryProofMain(const NumEffectState& state, const HashKey& key,
00180 const PathEncoding& path, const ProofOracle&, size_t oracle_id, Move& best_move,
00181 Move last_move);
00182 public:
00183 const ProofDisproof
00184 tryProof(const NumEffectState& state, const HashKey& key,
00185 const PathEncoding& path, const ProofOracle&, size_t oracle_id, Move& best_move,
00186 Move last_move=Move::INVALID());
00187 const ProofDisproof
00188 tryProofLight(const NumEffectState& state, const HashKey& key,
00189 const PathEncoding& path, const ProofOracle&, size_t oracle_id, Move& best_move,
00190 Move last_move=Move::INVALID());
00191
00192
00193 int distance(const HashKey&) const;
00195 template <Player P>
00196 static void generateCheck(const NumEffectState&, DfpnMoveVector&, bool&);
00198 template <Player P>
00199 static void generateEscape(const NumEffectState&, bool need_full_width,
00200 Square grand_parent_delay_last_to, DfpnMoveVector&);
00202 bool grandParentSimulationSuitable() const;
00203 template <Player Turn>
00204 static void sort(const NumEffectState&, DfpnMoveVector&);
00205 private:
00206 void findDagSource();
00207 };
00208
00209 }
00210 }
00211
00212 struct osl::checkmate::Dfpn::ProofOracle
00213 {
00214 HashKey key;
00215 PieceStand white_stand;
00216 ProofOracle(const HashKey& k, PieceStand w) : key(k), white_stand(w)
00217 {
00218 }
00219 const ProofOracle newOracle(Player P, Move move) const
00220 {
00221 assert(P == move.player());
00222 return ProofOracle(key.newHashWithMove(move),
00223 (P == WHITE) ? white_stand.nextStand(P, move) : white_stand);
00224 }
00225 bool traceable(Player P, Move move) const
00226 {
00227 assert(P == move.player());
00228 if (! move.isDrop())
00229 return true;
00230 if (P == BLACK) {
00231 if (key.blackStand().get(move.ptype()) == 0)
00232 return false;
00233 }
00234 else {
00235 if (white_stand.get(move.ptype()) == 0)
00236 return false;
00237 }
00238 return true;
00239 }
00240 };
00241
00242 #endif
00243
00244
00245
00246