weightTracer.cc
Go to the documentation of this file.
00001 /* weightTracer.cc
00002  */
00003 #include "osl/game_playing/weightTracer.h"
00004 #include "osl/game_playing/openingBookTracer.h"
00005 #include "osl/record/opening/openingBook.h"
00006 #include "osl/record/csa.h"
00007 #include "osl/stl/vector.h"
00008 #include "osl/misc/random.h"
00009 #include "osl/misc/ctime.h"
00010 #include <boost/utility.hpp>
00011 #include <iostream>
00012 #include <ctime>
00013 
00014 osl::game_playing::
00015 WeightTracer::WeightTracer(WeightedBook& b, bool v,
00016                            const int weight_coef_for_the_initial_move,
00017                            const int weight_coef)
00018   : book(b), state_index(b.getStartState()), start_index(b.getStartState()),
00019     turn(BLACK), 
00020     weight_coef_for_the_initial_move(weight_coef_for_the_initial_move),
00021     weight_coef(weight_coef)
00022 {
00023   verbose = v;
00024 }
00025 
00026 osl::game_playing::
00027 WeightTracer::WeightTracer(const WeightTracer& copy)
00028   : OpeningBookTracer(copy),
00029     book(copy.book), state_index(copy.state_index), 
00030     start_index(copy.start_index), turn(copy.turn), 
00031     state_stack(copy.state_stack),
00032     weight_coef_for_the_initial_move(copy.weight_coef_for_the_initial_move),
00033     weight_coef(copy.weight_coef)
00034 {
00035 }
00036 
00037 osl::game_playing::OpeningBookTracer* osl::game_playing::
00038 WeightTracer::clone() const
00039 {
00040   return new WeightTracer(*this);
00041 }
00042 
00043 void osl::game_playing::
00044 WeightTracer::update(Move move)
00045 {
00046   if (verbose) {
00047     std::cerr << "WeightTracer "
00048               << " Move: " << record::csa::show(move) << " ";
00049     const time_t now = time(0);
00050     char ctime_buf[64];
00051     std::cerr << ctime_r(&now, ctime_buf) 
00052               << std::endl;
00053   }
00054 
00055   state_stack.push(state_index);
00056   assert(move.player() == turn);
00057   turn = alt(turn);
00058 
00059   if (! isOutOfBook())
00060   {
00061     const vector<record::opening::WMove>& moves = book.getMoves(state_index);
00062     for (size_t i=0; i<moves.size(); i++)
00063     {
00064       if(moves[i].getMove() == move)
00065       {
00066         state_index = moves[i].getStateIndex();
00067         if (verbose)
00068           std::cerr << "book: " 
00069                     << state_stack.top() << "->" << state_index << "\n";
00070         return;
00071       }
00072     }
00073     if (verbose)
00074       std::cerr << "book: end" << "\n";
00075   }
00076   state_index = -1;
00077 }
00078 
00079 void osl::game_playing::
00080 WeightTracer::popMove()
00081 {
00082   state_index = state_stack.top();
00083   state_stack.pop();
00084   turn = alt(turn);
00085   if (verbose)
00086     std::cerr << "WeightTracer " << this << " pop: " << turn << std::endl;
00087 }
00088 
00089 bool osl::game_playing::
00090 WeightTracer::isOutOfBook() const
00091 {
00092   return state_index < 0; 
00093 }
00094 
00095 const osl::Move osl::game_playing::
00096 WeightTracer::selectMoveAtRandom(const std::vector<osl::record::opening::WMove>& moves) const
00097 {
00098   if (verbose)
00099     std::cerr << "book " << moves.size() << " candidates\n" << std::endl;
00100 
00101   int max_weight_index = 0;
00102   int max_weight = 0;
00103   int sum = 0;
00104   for (size_t i=0; i<moves.size(); ++i) {
00105     sum += moves[i].getWeight();
00106     if (max_weight < moves[i].getWeight()) {
00107       max_weight = moves[i].getWeight();
00108       max_weight_index = i;
00109     }
00110   }
00111 
00112   const int random_value = time_seeded_random() % sum;
00113   if (verbose)
00114     std::cerr << "random number: " << random_value << std::endl;
00115 
00116   int maxIndex = -1;
00117   int weight = 0;
00118   for (size_t index = 0; index < moves.size(); index++)
00119   {
00120     weight += moves[index].getWeight();
00121     if (random_value <= weight)
00122     {
00123       maxIndex = index;
00124       break;
00125     }
00126   }
00127 
00128   if (maxIndex >= 0) {
00129     if (verbose) {
00130       const int weight = moves[maxIndex].getWeight();
00131       std::cerr << "book " 
00132                 << 100.0*weight/sum << '%';
00133       if (weight != max_weight)
00134         std::cerr << " (c.f. " << 100.0*max_weight/sum
00135                   << " " << record::csa::show(moves[max_weight_index].getMove())
00136                   << ")";
00137       std::cerr << std::endl;
00138     }
00139     return moves[maxIndex].getMove();
00140   }
00141   return Move::INVALID();
00142 }
00143 
00144 const osl::Move osl::game_playing::
00145 WeightTracer::selectMove() const
00146 {
00147   const vector<record::opening::WMove> raw_moves = book.getMoves(state_index);
00148   vector<record::opening::WMove> moves;
00149 
00150   int max_weight = 0;
00151   for (size_t i=0; i<raw_moves.size(); ++i) {
00152     if (max_weight < raw_moves[i].getWeight()) {
00153       max_weight = raw_moves[i].getWeight();
00154     }
00155   }
00156   int sum = 0;
00157   const int coef = ((state_index == start_index) ? 
00158                     weight_coef_for_the_initial_move : weight_coef);
00159   for (size_t i=0; i<raw_moves.size(); ++i) {
00160     if (raw_moves[i].getWeight()*coef < max_weight)
00161       continue;
00162     moves.push_back(raw_moves[i]);
00163     sum += raw_moves[i].getWeight();
00164   }
00165 
00166   if (sum == 0)
00167     return Move::INVALID();
00168   
00169   return selectMoveAtRandom(moves);
00170 }
00171 
00172 
00173 osl::game_playing::OpeningBookTracer* osl::game_playing::
00174 DeterminateWeightTracer::clone() const
00175 {
00176   return new DeterminateWeightTracer(*this);
00177 }
00178 
00179 const osl::Move osl::game_playing::
00180 DeterminateWeightTracer::selectMove() const
00181 {
00182   vector<record::opening::WMove> moves = book.getMoves(state_index);
00183   const int original_size = moves.size();
00184   std::sort(moves.begin(), moves.end(), osl::record::opening::WMoveSort());
00185 
00186   /*
00187    * Select top_n moves. 
00188    *   - WMoves with the same weight are included in the result. 
00189    *   The size of the result vector might be greater than topn.
00190    *   - Zero-weighed WMoves are exluded. The size of the result vector
00191    *   might be less than topn.
00192    */
00193   int top = topn;
00194   vector<record::opening::WMove>::iterator it = moves.begin();
00195   for (/*none*/; it != moves.end() && top > 0; ++it) {
00196     if (it->getWeight() == 0)
00197       break;
00198 
00199     if (it->getWeight() != boost::next(it)->getWeight())
00200       top -= 1;
00201   }
00202   moves.erase(it, moves.end());
00203 
00204   if (verbose) {
00205     std::cerr << "book: there remain " << moves.size() << " candidates of " 
00206       << original_size << " moves\n";
00207   }
00208 
00209   if (moves.empty())
00210     return Move::INVALID();
00211 
00212   return selectMoveAtRandom(moves);
00213 }
00214 
00215 /* ------------------------------------------------------------------------- */
00216 // ;;; Local Variables:
00217 // ;;; mode:c++
00218 // ;;; c-basic-offset:2
00219 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines