dualDfpn.cc
Go to the documentation of this file.
00001 /* dualDfpn.cc
00002  */
00003 #include "osl/checkmate/dualDfpn.h"
00004 #include "osl/checkmate/dfpn.h"
00005 #include "osl/checkmate/dfpnRecord.h"
00006 #ifdef OSL_DFPN_SMP
00007 #  include "osl/checkmate/dfpnParallel.h"
00008 #endif
00009 #include "osl/repetitionCounter.h"
00010 #include "osl/stl/hash_map.h"
00011 #include "osl/stl/slist.h"
00012 #include "osl/stat/average.h"
00013 #include "osl/centering3x3.h"
00014 #include "osl/centering5x3.h"
00015 #ifdef OSL_SMP
00016 #  include "osl/misc/lightMutex.h"
00017 #  include <boost/thread/condition.hpp>
00018 #endif
00019 #ifdef OSL_SHOW_PROOF_TREE_MIGRATION_STAT
00020 #  include "osl/stat/ratio.h"
00021 #endif
00022 #include "osl/misc/milliSeconds.h"
00023 #include "osl/oslConfig.h"
00024 #include <boost/foreach.hpp>
00025 #include <iostream>
00026 #include <iomanip>
00027 
00028 #define DFPN_SHARE_TABLE
00029 
00030 static const int max_oracle_list_size = 2;
00031 static const size_t local_table_growth_limit = 40000;
00032 struct osl::checkmate::DualDfpn::OraclePool
00033 {
00034   struct Element
00035   {
00036     Dfpn::ProofOracle oracle;
00037     PieceStand proof_pieces;
00038     unsigned int id;
00039     bool in_check;
00040     Element() : oracle(HashKey(), PieceStand()), id((unsigned int)-1), in_check(false)
00041     {
00042     }
00043     Element(const Dfpn::ProofOracle& o, PieceStand p, size_t i, bool c) : oracle(o), proof_pieces(p), id(i), in_check(c)
00044     {
00045     }
00046   };
00047   struct List : FixedCapacityVector<Element, max_oracle_list_size>
00048   {
00049     void add(const Element& e)
00050     {
00051       if (size() == capacity())
00052         back() = e;
00053       else
00054         push_back(e);
00055     }
00056   };
00057 #ifdef OSL_SMP
00058   mutable boost::mutex mutex;
00059 #endif  
00060   typedef hash_map<HashKey, List> table_t;
00061   table_t table;
00062   Player defender;
00063   void setAttack(Player attack) 
00064   {
00065     defender = alt(attack);
00066   }
00067   void addProof(const NumEffectState& state, const HashKey& key, PieceStand proof_pieces) 
00068   {
00069     const Dfpn::ProofOracle oracle(key, PieceStand(WHITE, state));
00070     const std::pair<HashKey,HashKey> king = makeLargeKey(state);
00071 #ifdef OSL_SMP
00072     boost::mutex::scoped_lock lk(mutex);;
00073 #endif
00074     const Element e(oracle, proof_pieces, table.size(), state.inCheck());
00075     table[king.first].add(e);
00076     table[king.second].add(e);
00077   }
00078   const List probe(const NumEffectState& state) const
00079   {
00080     const std::pair<HashKey,HashKey> key = makeLargeKey(state);
00081 #ifdef OSL_SMP
00082     boost::mutex::scoped_lock lk(mutex);;
00083 #endif
00084     table_t::const_iterator p = table.find(key.first);
00085     if (p != table.end())
00086       return p->second;
00087     p = table.find(key.second);
00088     if (p != table.end())
00089       return p->second;
00090     return List();
00091   }
00092 
00093   template <Direction DIR>
00094   static void addKey(HashKey& key, const SimpleState& state, Square target)
00095   {
00096     const Offset offset = DirectionTraits<DIR>::blackOffset();
00097     target += offset;   // 8 近傍全て試すなら手番による符合変換は不要
00098     const Piece piece = state.pieceOnBoard(target);
00099     hash::Hash_Gen_Table.addHashKey(key, target, piece.ptypeO());
00100   }
00101   template <Direction DIR, Direction DIR2>
00102   static void addKey(HashKey& key, const SimpleState& state, Square target)
00103   {
00104     const Offset offset = DirectionTraits<DIR>::blackOffset()
00105       + DirectionTraits<DIR2>::blackOffset();
00106     target += offset;
00107     const Piece piece = state.pieceOnBoard(target);
00108     hash::Hash_Gen_Table.addHashKey(key, target, piece.ptypeO());
00109   }
00110   const HashKey makeKey(const SimpleState& state) const
00111   {
00112     const Square target_king=state.kingSquare(defender);
00113     const Square center = Centering3x3::adjustCenter(target_king);
00114     HashKey key;
00115     hash::Hash_Gen_Table.addHashKey(key, center, 
00116                                     state.pieceOnBoard(center).ptypeO());
00117     addKey<UL>(key, state, center); addKey<U> (key, state, center);
00118     addKey<UR>(key, state, center);
00119     addKey<L> (key, state, center); addKey<R> (key, state, center);
00120     addKey<DL>(key, state, center); addKey<D> (key, state, center);
00121     addKey<DR>(key, state, center);
00122     return key;
00123   }
00124   const std::pair<HashKey,HashKey> makeLargeKey(const SimpleState& state) const
00125   {
00126     HashKey key_small = makeKey(state), key_large;
00127     const Square target_king=state.kingSquare(defender);
00128     const Square center = Centering5x3::adjustCenter(target_king);
00129     hash::Hash_Gen_Table.addHashKey(key_large, center, 
00130                                     state.pieceOnBoard(center).ptypeO());
00131     addKey<UL>(key_large, state, center); addKey<U> (key_large, state, center);
00132     addKey<UR>(key_large, state, center);
00133     addKey<L> (key_large, state, center); addKey<R> (key_large, state, center);
00134     addKey<DL>(key_large, state, center); addKey<D> (key_large, state, center);
00135     addKey<DR>(key_large, state, center);
00136     addKey<L,UL>(key_large, state, center); addKey<L,L> (key_large, state, center);
00137     addKey<L,DL>(key_large, state, center);
00138     addKey<R,UR>(key_large, state, center); addKey<R,R> (key_large, state, center);
00139     addKey<R,DR>(key_large, state, center);
00140     return std::make_pair(key_large, key_small);
00141   }
00142 };
00143 
00144 struct osl::checkmate::DualDfpn::Shared
00145 {
00146   CArray<DfpnTable,2> table;
00147   CArray<OraclePool,2> pool;
00148   size_t main_node_count;
00149   size_t simulation_count;
00150   volatile size_t last_gc, gc_threshold;
00151   CArray<stat::Average,max_oracle_list_size> proof_by_oracle;
00152   CArray<bool,2> blocking_verify;
00153 #ifdef OSL_SMP
00154   boost::mutex mutex;
00155   boost::condition condition;
00156   CArray<LightMutex,max_oracle_list_size> proof_by_oracle_mutex;
00157 #endif
00158   volatile int shared_table_user, shared_table_gc_wait;
00159 #ifdef OSL_DFPN_SMP
00160   boost::scoped_ptr<DfpnParallel> parallel_search;
00161 #endif
00162   typedef slist<PathEncoding> disproof_list_t;
00163   typedef hash_map<HashKey, disproof_list_t> disproof_table_t;
00164   disproof_table_t disproof_table;
00165 
00166   Shared() : main_node_count(0), simulation_count(0), last_gc(0), gc_threshold(10),
00167              shared_table_user(0), shared_table_gc_wait(0)
00168   {
00169     table[BLACK].setAttack(BLACK);
00170     table[WHITE].setAttack(WHITE);
00171     pool[BLACK].setAttack(BLACK);
00172     pool[WHITE].setAttack(WHITE);
00173     blocking_verify.fill(true);
00174   }
00175   ~Shared()
00176   {
00177     showStats();
00178   }
00179   void showStats()
00180   {
00181     if (main_node_count || simulation_count) {
00182 #ifdef DFPN_DEBUG
00183       std::cerr << "shared " << main_node_count << " " << simulation_count << "\n";
00184       BOOST_FOREACH(stat::Average& a, proof_by_oracle)
00185         std::cerr << a.getAverage() 
00186                   << " " << (int)(a.getAverage()*a.numElements()) << "\n";
00187       std::cerr << "oracles " << pool[BLACK].table.size() << " " << pool[WHITE].table.size() << "\n";
00188       std::cerr << "table " << table[0].totalSize() << " " << table[1].totalSize() << "\n";
00189       table[0].showStats();
00190       table[1].showStats();
00191 #endif
00192     }
00193   }
00194   void addMainNodeCount(int add)
00195   {
00196 #ifdef OSL_SMP
00197     boost::mutex::scoped_lock lk(mutex);;
00198 #endif
00199     main_node_count += add;
00200   }
00201   void addSimulationNodeCount(int add)
00202   {
00203 #ifdef OSL_SMP
00204     boost::mutex::scoped_lock lk(mutex);;
00205 #endif
00206     simulation_count += add;
00207   }
00208   struct TableUseLock : boost::noncopyable
00209   {
00210     Shared *shared;
00211     explicit TableUseLock(Shared *s) : shared(s)
00212     {
00213 #  ifdef OSL_SMP
00214       boost::mutex::scoped_lock lk(shared->mutex);
00215       while (shared->shared_table_user < 0) // in gc
00216         shared->condition.wait(lk);
00217       shared->shared_table_user++;
00218 #  endif
00219     }
00220     ~TableUseLock()
00221     {
00222 #  ifdef OSL_SMP
00223       boost::mutex::scoped_lock lk(shared->mutex);
00224       assert(shared->shared_table_user > 0);
00225       shared->shared_table_user--;
00226       if (shared->shared_table_user == 0 && shared->shared_table_gc_wait)
00227         shared->condition.notify_all();
00228 #  endif
00229     }
00230   };
00231 };
00232 
00233 struct osl::checkmate::DualDfpn::Local
00234 {
00235   Dfpn dfpn;
00236 #ifndef DFPN_SHARE_TABLE
00237   CArray<DfpnTable,2> table;
00238 #endif
00239   CArray<DfpnTable,2> table_small;
00240   size_t local_node_count;
00241   Local() : local_node_count(0)
00242   {
00243 #ifndef DFPN_SHARE_TABLE
00244     table[BLACK].setAttack(BLACK);
00245     table[WHITE].setAttack(WHITE);
00246 #endif
00247     table_small[BLACK].setAttack(BLACK);
00248     table_small[WHITE].setAttack(WHITE);
00249   }
00250   ~Local()
00251   {
00252 #ifdef DFPN_DEBUG
00253     std::cerr << "local " << table_small[0].totalSize()
00254               << " " << table_small[1].totalSize() << "\n";
00255 #endif
00256   }
00257 };
00258 
00259 /* ------------------------------------------------------------------------- */
00260 
00261 osl::checkmate::
00262 DualDfpn::DualDfpn(uint64_t /*limit*/)
00263   : shared(new Shared), local(new Local)
00264 {
00265 }
00266 
00267 osl::checkmate::
00268 DualDfpn::DualDfpn(const DualDfpn& src)
00269   : shared(src.shared), local(new Local)
00270 {
00271 }
00272 
00273 osl::checkmate::
00274 DualDfpn::~DualDfpn()
00275 {
00276 }
00277 
00278 osl::checkmate::Dfpn& osl::checkmate::
00279 DualDfpn::prepareDfpn(Player attack)
00280 {
00281 #ifdef DFPN_SHARE_TABLE
00282   local->dfpn.setTable(&(shared->table[attack]));
00283 #else
00284   local->dfpn.setTable(&(local->table[attack]));
00285 #endif
00286   local->dfpn.setBlockingVerify(shared->blocking_verify[attack]);
00287   return local->dfpn;
00288 }
00289 
00290 osl::checkmate::Dfpn& osl::checkmate::
00291 DualDfpn::prepareDfpnSmall(Player attack)
00292 {
00293   local->dfpn.setTable(&(local->table_small[attack]));
00294   local->dfpn.setBlockingVerify(shared->blocking_verify[attack]);
00295   return local->dfpn;
00296 }
00297 
00298 void osl::checkmate::
00299 DualDfpn::runGC(bool verbose, size_t memory_use_ratio_1000)
00300 {
00301 #ifdef DFPN_SHARE_TABLE
00302   const size_t unit_size = (sizeof(HashKey)+sizeof(DfpnRecord)+sizeof(char*)*2);
00303   size_t removed = 0;
00304   size_t total = shared->table[BLACK].size() + shared->table[WHITE].size();
00305   size_t current_use = memory_use_ratio_1000*(OslConfig::memoryUseLimit()/1000);
00306   if (total < local_table_growth_limit*8
00307       || total*unit_size*64 < OslConfig::memoryUseLimit()
00308       || (total*unit_size*3 < current_use
00309           && total*unit_size*8 < OslConfig::memoryUseLimit()))
00310     return;
00311   MilliSeconds start = MilliSeconds::now();
00312   {
00313     {
00314 #  ifdef OSL_SMP
00315       boost::mutex::scoped_lock lk(shared->mutex);
00316 #  endif
00317       total = shared->table[BLACK].size() + shared->table[WHITE].size();
00318       if (total < local_table_growth_limit*8
00319           || (total*unit_size*3 < current_use
00320               && total*unit_size*6 < OslConfig::memoryUseLimit()))
00321         return;
00322       if (total < shared->last_gc + local_table_growth_limit*2)
00323         return;
00324       if (shared->shared_table_user > 0
00325           && memory_use_ratio_1000 < 650
00326           && total < shared->last_gc*2)
00327         return;
00328       if (shared->shared_table_user < 0 || shared->shared_table_gc_wait > 0)
00329         return;
00330 #  ifdef OSL_SMP
00331       while (shared->shared_table_user > 0) {
00332         ++shared->shared_table_gc_wait;
00333         shared->condition.wait(lk);
00334         --shared->shared_table_gc_wait;
00335       }
00336       if (shared->shared_table_user < 0)
00337         return;
00338 #  endif
00339       shared->shared_table_user--;
00340     }
00341     removed += shared->table[BLACK].smallTreeGC(shared->gc_threshold);
00342     removed += shared->table[WHITE].smallTreeGC(shared->gc_threshold);
00343     {
00344 #  ifdef OSL_SMP
00345       boost::mutex::scoped_lock lk(shared->mutex);
00346 #  endif
00347       if (total > shared->last_gc*2) {
00348         if (100.0*removed/total < 70)
00349           shared->gc_threshold += 15;
00350         else if (100.0*removed/total < 90)
00351           shared->gc_threshold += 5;
00352       }
00353       shared->last_gc = total - removed;
00354       shared->shared_table_user++;
00355       assert(shared->shared_table_user == 0);
00356 #  ifdef OSL_SMP
00357       shared->condition.notify_all();
00358 #  endif
00359     }
00360   }
00361   if (! verbose) 
00362     return;
00363   const double elapsed = start.elapsedSeconds();
00364   if (removed > 10000 || elapsed > 0.1)
00365     std::cerr << " GC " << removed
00366               << " entries " << std::setprecision(3)
00367               << (unit_size * removed / (1<<20)) << "MB "
00368               << 100.0*removed/total << "%"
00369               << " (" << elapsed << " s)\n";
00370 #endif
00371 }
00372 
00373 
00374 template <osl::Player P>
00375 osl::ProofDisproof osl::checkmate::
00376 DualDfpn::findProof(int node_limit, const NumEffectState& state, 
00377                     const HashKey& key, const PathEncoding& path,
00378                     Move& best_move, Move last_move)
00379 {
00380   assert(state.turn() == P);
00381   // oracle
00382   Dfpn& dfpn = prepareDfpn(P);
00383   const OraclePool::List l = shared->pool[P].probe(state);
00384   const PieceStand attack_stand = (P==BLACK) ? key.blackStand() : PieceStand(WHITE, state);
00385   int num_tried = 0;
00386   for (size_t i=0; i<l.size(); ++i)
00387   {
00388     if (! attack_stand.isSuperiorOrEqualTo(l[i].proof_pieces)
00389         || l[i].in_check != state.inCheck())
00390       continue;
00391     ++num_tried;
00392     const ProofDisproof pdp = (node_limit > 20)
00393       ? dfpn.tryProof(state, key, path, l[i].oracle, l[i].id, best_move, last_move)
00394       : dfpn.tryProofLight(state, key, path, l[i].oracle, l[i].id, best_move, last_move);
00395     const size_t count = dfpn.nodeCount();
00396     local->local_node_count += count;
00397     shared->addSimulationNodeCount(count);
00398     if (count) {
00399 #ifdef OSL_SMP
00400       SCOPED_LOCK(lk,shared->proof_by_oracle_mutex[i]);
00401 #endif
00402       shared->proof_by_oracle[i].add(pdp.isCheckmateSuccess());
00403     }
00404     if (pdp.isCheckmateSuccess()) 
00405       assert(best_move.isNormal());
00406     if (pdp.isFinal())
00407       return pdp;
00408   }
00409   if (node_limit == 0 && num_tried) 
00410     return ProofDisproof(1,1);                  // already tested table
00411   const ProofDisproof table_pdp = dfpn.hasCheckmateMove(state, key, path, 0, best_move, last_move);
00412   if (table_pdp.isCheckmateSuccess())
00413     return table_pdp;
00414   {
00415 #ifdef OSL_SMP
00416     boost::mutex::scoped_lock lk(shared->mutex);
00417 #endif
00418     Shared::disproof_table_t::const_iterator p = shared->disproof_table.find(key);
00419     if (p != shared->disproof_table.end()) {
00420       BOOST_FOREACH(const PathEncoding& ppath, p->second)
00421         if (ppath == path)
00422           return ProofDisproof::LoopDetection();
00423     }
00424   }
00425 #ifdef OSL_SHOW_PROOF_TREE_MIGRATION_STAT
00426   static stat::Ratio migration_success("migration_success", true);
00427   bool need_migration = false;
00428 #endif
00429   // local
00430   if (node_limit < 80) {
00431     if (local->table_small[P].totalSize() >= local_table_growth_limit) {
00432       local->table_small[P].clear();
00433     }
00434     Dfpn& dfpn_small = prepareDfpnSmall(P);
00435     const ProofDisproof pdp = dfpn_small.hasCheckmateMove(state, key, path, node_limit, best_move, last_move);
00436     const size_t count = dfpn_small.nodeCount();
00437     local->local_node_count += count;
00438     shared->addMainNodeCount(count);
00439     if (pdp.isLoopDetection()) {
00440 #ifdef OSL_SMP
00441       boost::mutex::scoped_lock lk(shared->mutex);
00442 #endif
00443       shared->disproof_table[key].push_front(path);
00444     }
00445     if (! pdp.isCheckmateSuccess())
00446       return pdp;
00447     assert(best_move.isNormal());
00448     // fall through if checkmate success (TODO: efficient proof tree migration)
00449 #ifdef OSL_SHOW_PROOF_TREE_MIGRATION_STAT
00450     need_migration = true;
00451 #endif
00452   }
00453   // main
00454   Shared::TableUseLock lk(&*shared);
00455   PieceStand proof_pieces;
00456   const ProofDisproof pdp = dfpn.hasCheckmateMove(state, key, path, node_limit, best_move, proof_pieces, last_move);
00457   const size_t count = dfpn.nodeCount();
00458   local->local_node_count += count;
00459   shared->addMainNodeCount(count);
00460   if (pdp.isCheckmateSuccess())
00461     shared->pool[P].addProof(state, key, proof_pieces);
00462 #ifdef OSL_SHOW_PROOF_TREE_MIGRATION_STAT
00463   if (need_migration)
00464     migration_success.add(pdp.isCheckmateSuccess());
00465 #endif
00466   if (pdp.isLoopDetection()) {
00467 #ifdef OSL_SMP
00468     boost::mutex::scoped_lock lk(shared->mutex);
00469 #endif
00470     shared->disproof_table[key].push_front(path);
00471   }
00472   if (pdp.isCheckmateSuccess())
00473     assert(best_move.isNormal());
00474   return pdp;
00475 }
00476 
00477 osl::checkmate::ProofDisproof osl::checkmate::
00478 DualDfpn::findProof(int node_limit, const NumEffectState& state, 
00479                     const HashKey& key, const PathEncoding& path,
00480                     Move& best_move, Move last_move)
00481 {
00482   if (state.turn() == BLACK)
00483     return findProof<BLACK>(node_limit, state, key, path, best_move, last_move);
00484   else
00485     return findProof<WHITE>(node_limit, state, key, path, best_move, last_move);
00486 }
00487 
00488 bool osl::checkmate::
00489 DualDfpn::isWinningState(int node_limit, const NumEffectState& state, 
00490                            const HashKey& key, const PathEncoding& path,
00491                            Move& best_move, Move last_move)
00492 {
00493   return findProof(node_limit, state, key, path, best_move, last_move)
00494     .isCheckmateSuccess();
00495 }
00496 
00497 #ifdef OSL_DFPN_SMP
00498 template <osl::Player P>
00499 bool osl::checkmate::
00500 DualDfpn::isWinningStateParallel(int node_limit, const NumEffectState& state, 
00501                                  const HashKey& key, const PathEncoding& path,
00502                                  Move& best_move, Move last_move)
00503 {
00504   PieceStand proof_pieces;
00505   size_t count;
00506   ProofDisproof pdp;
00507   {
00508 #ifdef OSL_SMP
00509     boost::mutex::scoped_lock lk(shared->mutex);
00510 #endif
00511     if (! shared->parallel_search)
00512       shared->parallel_search.reset(new DfpnParallel(std::min(OslConfig::numCPUs(), 8)));
00513 #ifdef DFPN_SHARE_TABLE
00514     shared->parallel_search->setTable(&(shared->table[P]));
00515 #else
00516     shared->parallel_search->setTable(&(local->table[P]));
00517 #endif
00518 
00519     pdp = shared->parallel_search->hasCheckmateMove
00520       (state, key, path, node_limit, best_move, proof_pieces, last_move);
00521     count = shared->parallel_search->nodeCount();
00522   }
00523   shared->addMainNodeCount(count);
00524   if (pdp.isCheckmateSuccess())
00525     shared->pool[P].addProof(state, key, proof_pieces);
00526   if (pdp.isLoopDetection()) {
00527     shared->disproof_table[key].push_front(path);
00528   }
00529   if (pdp.isCheckmateSuccess())
00530     assert(best_move.isNormal());
00531   return pdp.isCheckmateSuccess();
00532 }
00533 
00534 bool osl::checkmate::
00535 DualDfpn::isWinningStateParallel(int node_limit, const NumEffectState& state, 
00536                                  const HashKey& key, const PathEncoding& path,
00537                                  Move& best_move, Move last_move)
00538 {
00539   if (state.turn() == BLACK)
00540     return isWinningStateParallel<BLACK>(node_limit, state, key, path, best_move, last_move);
00541   else
00542     return isWinningStateParallel<WHITE>(node_limit, state, key, path, best_move, last_move);
00543 }
00544 #endif
00545 
00546 template <osl::Player P>
00547 bool
00548  osl::checkmate::
00549 DualDfpn::isLosingState(int node_limit, const NumEffectState& state, 
00550                         const HashKey& key, const PathEncoding& path,
00551                         Move last_move)
00552 {
00553   Shared::TableUseLock lk(&*shared);
00554   assert(state.turn() == P);
00555   Dfpn& dfpn = prepareDfpn(alt(P));
00556   const ProofDisproof pdp = dfpn.hasEscapeMove(state, key, path, node_limit, last_move);
00557   const size_t count = dfpn.nodeCount();
00558   local->local_node_count += count;
00559   shared->addMainNodeCount(count);
00560   return pdp.isCheckmateSuccess();
00561 }
00562 
00563 bool osl::checkmate::
00564 DualDfpn::isLosingState(int node_limit, const NumEffectState& state, 
00565                           const HashKey& key, const PathEncoding& path,
00566                           Move last_move)
00567 {
00568   if (state.turn() == BLACK)
00569     return isLosingState<BLACK>(node_limit, state, key, path, last_move);
00570   else
00571     return isLosingState<WHITE>(node_limit, state, key, path, last_move);
00572 }
00573 
00574 void osl::checkmate::
00575 DualDfpn::writeRootHistory(const RepetitionCounter& counter,
00576                            const MoveStack& moves,
00577                            const SimpleState& state, Player attack)
00578 {
00579   // TODO: 局面表をクリアしてしまうと忘れられる => DualDfpn 内で記憶した方が良い
00580   Shared::TableUseLock lk(&*shared);
00581   Dfpn& dfpn = prepareDfpn(attack);
00582   PieceStand white_stand(WHITE, state);
00583   for (int i=0; i<counter.checkCount(attack); ++i)
00584   {
00585     const HashKey& key = counter.history().top(i);
00586     if (key != counter.history().top(0)) // ignore current state
00587     {
00588       dfpn.setIllegal(key, white_stand);
00589     }
00590     assert(moves.hasLastMove(i+1)); // oops, different index
00591     if (! moves.hasLastMove(i+1))
00592       break;
00593     const Move last_move = moves.lastMove(i+1);
00594     if (last_move.isNormal())
00595       white_stand = white_stand.previousStand(WHITE, last_move);
00596   }
00597 }
00598 
00599 void osl::checkmate::
00600 DualDfpn::setRootPlayer(Player root)
00601 {
00602   shared->blocking_verify[root] = true;
00603   shared->blocking_verify[alt(root)] = true; // TODO: set false when issues around proof pieces are corrected
00604 }
00605 
00606 void osl::checkmate::
00607 DualDfpn::setVerbose(int /*level*/)
00608 {
00609 }
00610 
00611 int osl::checkmate::
00612 DualDfpn::distance(Player attack, const HashKey& key)
00613 {
00614   Shared::TableUseLock lk(&*shared);
00615   return prepareDfpn(attack).distance(key);
00616 }
00617 
00618 size_t osl::checkmate::
00619 DualDfpn::mainNodeCount() const
00620 {
00621 #ifdef OSL_USE_RACE_DETECTOR
00622   boost::mutex::scoped_lock lk(shared->mutex);
00623 #endif
00624   return shared->main_node_count;
00625   // return shared->table[BLACK].totalSize() + shared->table[WHITE].totalSize();
00626 }
00627 
00628 size_t osl::checkmate::
00629 DualDfpn::totalNodeCount() const
00630 {
00631 #ifdef OSL_USE_RACE_DETECTOR
00632   boost::mutex::scoped_lock lk(shared->mutex);
00633 #endif
00634   return shared->main_node_count + shared->simulation_count;
00635 }
00636 
00637 const osl::checkmate::DfpnTable& osl::checkmate::
00638 DualDfpn::table(Player attack) const
00639 {
00640   return shared->table[attack];
00641 }
00642 
00643 namespace osl
00644 {
00645   template ProofDisproof checkmate::DualDfpn::findProof<BLACK>
00646   (int, const NumEffectState&, const HashKey&, const PathEncoding&,
00647    Move&, Move);
00648   template ProofDisproof checkmate::DualDfpn::findProof<WHITE>
00649   (int, const NumEffectState&, const HashKey&, const PathEncoding&,
00650    Move&, Move);
00651 
00652 
00653   template bool checkmate::DualDfpn::isLosingState<BLACK>
00654   (int, const NumEffectState&, const HashKey&, const PathEncoding&, Move);
00655   template bool checkmate::DualDfpn::isLosingState<WHITE>
00656   (int, const NumEffectState&, const HashKey&, const PathEncoding&, Move);
00657 
00658 #ifdef OSL_DFPN_SMP
00659   template bool checkmate::DualDfpn::isWinningStateParallel<BLACK>
00660   (int, const NumEffectState&, const HashKey&, const PathEncoding&, Move&, Move);
00661   template bool checkmate::DualDfpn::isWinningStateParallel<WHITE>
00662   (int, const NumEffectState&, const HashKey&, const PathEncoding&, Move&, Move);
00663 #endif
00664 }
00665 
00666 /* ------------------------------------------------------------------------- */
00667 // ;;; Local Variables:
00668 // ;;; mode:c++
00669 // ;;; c-basic-offset:2
00670 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines