repetitionCounter.cc
Go to the documentation of this file.
00001 /* repetitionCounter.cc
00002  */
00003 #include "osl/repetitionCounter.h"
00004 #include "osl/hash/hashKey.h"
00005 #include "osl/state/simpleState.h"
00006 #include "osl/effect_util/effectUtil.h"
00007 #include "osl/move_classifier/check_.h"
00008 #include "osl/move_classifier/moveAdaptor.h"
00009 #include "osl/stl/hash_map.h"
00010 #include <boost/foreach.hpp>
00011 #include <iostream>
00012 
00013 #if (__GNUC__ < 3 || (__GNUC__ ==3 && __GNUC_MINOR__ < 4) ) && defined(USE_GPL_POOL_ALLOCATOR)
00014 template class osl::__gnu_cxx::__pool_alloc<true,0>;
00015 #endif
00016 
00017 typedef osl::RepetitionCounter::list_t list_t;
00018 typedef osl::hash_map<osl::HashKey,list_t> map_t;
00019 
00020 struct osl::RepetitionCounter::Table : public map_t
00021 {
00022 };
00023 
00024 static const int initial_capacity = 256;
00025 
00026 void osl::RepetitionCounter::
00027 clear() 
00028 {
00029   table->clear();
00030   continuous_check[0].clear();
00031   continuous_check[1].clear();
00032   hash_history.clear();
00033 
00034   continuous_check[0].reserve(initial_capacity);
00035   continuous_check[1].reserve(initial_capacity);
00036   
00037   continuous_check[0].push_back(0);
00038   continuous_check[1].push_back(0);
00039 }
00040 
00041 osl::RepetitionCounter::
00042 RepetitionCounter() : table(new Table()), hash_history(initial_capacity)
00043 {
00044   clear();
00045 }
00046 
00047 osl::RepetitionCounter::
00048 RepetitionCounter(const RepetitionCounter& c)
00049   : continuous_check(c.continuous_check), 
00050     hash_history(c.hash_history)
00051 {
00052   if (c.table)
00053     table.reset(new Table(*c.table));
00054   assert(isConsistent());
00055 }
00056 
00057 
00058 osl::RepetitionCounter::
00059 RepetitionCounter(const NumEffectState& initial)
00060   : table(new Table()), hash_history(initial_capacity)
00061 {
00062   clear();
00063   const HashKey key(initial);
00064   push(key, initial);
00065 }
00066 
00067 osl::RepetitionCounter::
00068 ~RepetitionCounter()
00069 {
00070 }
00071 
00072 void osl::RepetitionCounter::
00073 push(const HashKey& new_key, bool is_check)
00074 {
00075   const Player last_turn = alt(new_key.turn());
00076   if (is_check)
00077   {
00078     continuous_check[last_turn].push_back(checkCount(last_turn)+1);
00079   }
00080   else
00081   {
00082     continuous_check[last_turn].push_back(0);
00083   }
00084 
00085   const Table::iterator p=table->find(new_key);
00086   if (p == table->end())
00087   {
00088     (*table)[new_key].push_front(order());
00089   }
00090   else
00091   {
00092     list_t& l = p->second;
00093     l.push_front(order());
00094   }
00095   hash_history.push(new_key);
00096 }
00097 
00098 void osl::RepetitionCounter::
00099 push(const HashKey& key, const NumEffectState& state)
00100 {
00101   const bool is_check = state.inCheck();
00102   push(key, is_check);
00103 }
00104 
00105 void osl::RepetitionCounter::
00106 push(const NumEffectState& state)
00107 {
00108   push(HashKey(state), state);
00109 }
00110 
00111 void osl::RepetitionCounter::
00112 push(const NumEffectState& state, Move move)
00113 {
00114   assert(move.isValidOrPass());
00115   assert(state.turn() == move.player());
00116   
00117   HashKey key(state);
00118   key = key.newHashWithMove(move);
00119 
00120   // 指した後の王手を検出
00121   using namespace move_classifier;
00122   const bool is_check 
00123     = (!move.isPass()) && PlayerMoveAdaptor<Check>::isMember(state, move);
00124   push(key, is_check);
00125 }
00126 
00127 void osl::RepetitionCounter::
00128 pop()
00129 {
00130   assert(order());
00131   assert(hash_history.size()>0);
00132   const HashKey last_key = hash_history.top();
00133   hash_history.pop();
00134   
00135   const Player last_turn = alt(last_key.turn());
00136   assert(! continuous_check[last_turn].empty());
00137   continuous_check[last_turn].pop_back();
00138 
00139   const Table::iterator p=table->find(last_key);
00140   assert(p != table->end());
00141 
00142 #ifndef NDEBUG
00143   const list_t::iterator q = p->second.begin();
00144   assert(q != p->second.end());
00145   assert(*q == order());
00146 #endif
00147   p->second.pop_front();
00148   if (p->second.empty())
00149     table->erase(p);
00150 }
00151 
00152 int osl::RepetitionCounter::
00153 getLastMove(const HashKey& key) const
00154 {
00155   const Table::const_iterator p=table->find(key);
00156   if (p == table->end())
00157     return -1;
00158   return p->second.front();
00159 }
00160 int osl::RepetitionCounter::
00161 getFirstMove(const HashKey& key) const
00162 {
00163   const Table::const_iterator p=table->find(key);
00164   if (p == table->end())
00165     return -1;
00166   list_t::const_iterator q = p->second.begin();
00167   assert(q != p->second.end());
00168   int result = *q++;
00169   while (q != p->second.end())
00170     result = *q++;
00171   return result;
00172 }
00173 
00174 const osl::Sennichite osl::RepetitionCounter::
00175 isSennichite(const NumEffectState& state, Move move) const
00176 {
00177   HashKey key(state);
00178   key = key.newHashWithMove(move);
00179   const Table::const_iterator p=table->find(key);
00180   if (p == table->end())
00181     return Sennichite::NORMAL();
00182 
00183   // 現在3だと次で4
00184   if (p->second.size() < 3)
00185     return Sennichite::NORMAL();
00186   return isAlmostSennichite(key);
00187 }
00188 
00189 const std::pair<osl::Sennichite,int> osl::RepetitionCounter::
00190 distanceToSennichite(const HashKey& key) const
00191 {
00192   const Table::const_iterator p=table->find(key);
00193   if (p == table->end())
00194     return std::make_pair(Sennichite::NORMAL(), 0);
00195   return std::make_pair(isAlmostSennichite(key), p->second.size());
00196 }
00197 
00198 unsigned int osl::RepetitionCounter::
00199 countRepetition(const HashKey& key) const
00200 {
00201   const Table::const_iterator p=table->find(key);
00202   if (p == table->end())
00203     return 0;
00204   return p->second.size();
00205 }
00206 
00207 const list_t osl::RepetitionCounter::
00208 getRepetitions(const HashKey& key) const
00209 {
00210   Table::const_iterator p=table->find(key);
00211   if (p == table->end())
00212     return list_t();
00213   return p->second;
00214 }
00215 
00216 #ifndef MINIMAL
00217 void osl::RepetitionCounter::
00218 printMatches(const HashKey& key) const
00219 {
00220   Table::const_iterator p=table->find(key);
00221   if (p == table->end())
00222     return;
00223   BOOST_FOREACH(int q, p->second)
00224   {
00225     std::cerr << q << " ";
00226   }
00227   std::cerr << "\n";
00228 }
00229 
00230 bool osl::RepetitionCounter::
00231 isConsistent() const
00232 {
00233   HashKeyStack history = hash_history;
00234   Table table(*this->table);
00235   CArray<osl::vector<int>, 2> continuous_check = this->continuous_check;
00236   while (history.empty())
00237   {
00238     const HashKey last_key = history.top();
00239     history.pop();
00240   
00241     const Player last_turn = alt(last_key.turn());
00242     assert(! continuous_check[last_turn].empty());
00243     continuous_check[last_turn].pop_back();
00244 
00245     const Table::iterator p=table.find(last_key);
00246     if (p == table.end())
00247     {
00248       std::cerr << "oops, " << this << "\n";
00249       return false;
00250     }
00251     assert(p != table.end());
00252 
00253 #ifndef NDEBUG
00254     const list_t::iterator q = p->second.begin();
00255     assert(q != p->second.end());
00256     assert(*q == order());
00257 #endif
00258     p->second.pop_front();
00259     if (p->second.empty())
00260       table.erase(p);
00261   }
00262   return true;
00263 }
00264 
00265 bool osl::RepetitionCounter::maybeEqual(const RepetitionCounter& l, const RepetitionCounter& r)
00266 {
00267 #if ! (__GNUC__ >= 4 && __GNUC_MINOR__ >=3)
00268   // oops
00269   if (*l.table != *r.table)
00270     return false;
00271 #endif
00272   if (l.continuous_check[0] != r.continuous_check[0])
00273     return false;
00274   if (l.continuous_check[1] != r.continuous_check[1])
00275     return false;
00276   return l.hash_history == r.hash_history;
00277 }
00278 #endif
00279 
00280 /* ------------------------------------------------------------------------- */
00281 // ;;; Local Variables:
00282 // ;;; mode:c++
00283 // ;;; c-basic-offset:2
00284 // ;;; coding:utf-8
00285 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines