historyToTable.cc
Go to the documentation of this file.
00001 /* historyToTable.cc
00002  */
00003 #include "osl/game_playing/historyToTable.h"
00004 #include "osl/game_playing/gameState.h"
00005 #include "osl/game_playing/pvHistory.h"
00006 #include "osl/search/hashRejections.h"
00007 #include "osl/hash/hashKeyStack.h"
00008 #include "osl/repetitionCounter.h"
00009 #include "osl/search/simpleHashTable.h"
00010 #include "osl/search/simpleHashRecord.h"
00011 #include "osl/container/moveStack.h"
00012 #include "osl/record/csa.h"
00013 #include <boost/foreach.hpp>
00014 #include <iostream>
00015 
00016 const int osl::game_playing::HistoryToTable::LIMIT
00017 = osl::search::SearchTable::HistorySpecialDepth;
00018 
00019 void osl::game_playing::
00020 HistoryToTable::adjustDominance(const HashKey& key, 
00021                                 search::SimpleHashTable& table,
00022                                 int black_win, int white_win,
00023                                 const Move& good_move)
00024 {
00025   const PieceStand black_stand = key.pieceStand();
00026   const Player turn = key.turn();
00027   BOOST_FOREACH(Ptype ptype, PieceStand::order)
00028   {
00029     if (black_stand.get(ptype))
00030     {
00031       // white win dominance
00032       PieceStand new_stand = black_stand;
00033       new_stand.sub(ptype);
00034       HashKey new_key = key;
00035       new_key.setPieceStand(new_stand);
00036       SimpleHashRecord *record = table.allocate(new_key, LIMIT);
00037       if (record)
00038       {
00039         const Move record_move = (turn == WHITE) ? good_move : Move::INVALID();
00040         record->setAbsoluteValue(record_move, white_win, LIMIT);
00041         record->qrecord.setHistoryValue(record_move, white_win);
00042       }
00043     }
00044     if (black_stand.canAdd(ptype))
00045     {
00046       // black win dominance
00047       // TODO:
00048       // - 加える持駒があるかどうかのチェックは本当は盤面を見る必要がある
00049       // - good_move がvalid であることの assert を入れる
00050       PieceStand new_stand = black_stand;
00051       new_stand.add(ptype);
00052       HashKey new_key = key;
00053       new_key.setPieceStand(new_stand);
00054       SimpleHashRecord *record = table.allocate(new_key, LIMIT);
00055       if (record)
00056       {
00057         const Move record_move = (turn == BLACK) ? good_move : Move::INVALID();
00058         record->setAbsoluteValue(record_move, black_win, LIMIT);
00059         record->qrecord.setHistoryValue(record_move, black_win);
00060       }
00061     }
00062   }
00063 }
00064 
00065 void osl::game_playing::
00066 HistoryToTable::adjustTable(const GameState& state, SimpleHashTable& table,
00067                             int black_win, int draw, int white_win)
00068 {
00069   const RepetitionCounter& counter = state.counter();
00070   // 優越関係より千日手が優先
00071   // 千日手は新しい局面優先
00072   HashKeyStack history = state.hashHistory(); // copy
00073   MoveStack move_history = state.moveHistory();
00074   move_history.push(Move::INVALID());
00075   assert(move_history.size() == history.size());
00076 
00077   HashKeyStack reverse_history;
00078   while (! history.empty())
00079   {
00080     const HashKey key = history.top();
00081     history.pop();
00082     assert(move_history.hasLastMove());
00083     const Move last_move = move_history.lastMove();
00084     move_history.pop();
00085 
00086     if (key != HashKey(state.state()))  // keep current state clean
00087       reverse_history.push(key);
00088 
00089     // set dominance
00090     adjustDominance(key, table, black_win, white_win, last_move);
00091   }
00092 
00093   while (! reverse_history.empty())
00094   {
00095     // set repetition
00096     const HashKey key = reverse_history.top();
00097     reverse_history.pop();
00098 
00099     SimpleHashRecord *record = table.allocate(key, LIMIT);
00100     const std::pair<Sennichite,int> result = counter.distanceToSennichite(key);
00101     if (result.first.isDraw())
00102     {
00103       record->setAbsoluteValue(Move::INVALID(), draw*result.second, LIMIT);
00104       record->qrecord.setHistoryValue(draw*result.second);
00105     }
00106     else
00107     {
00108       assert(result.first.hasWinner());
00109       const int value = (result.first.winner() == BLACK) ? black_win : white_win;
00110       record->setAbsoluteValue(Move::INVALID(), value, LIMIT);
00111       record->qrecord.setHistoryValue(value);
00112     }
00113   }
00114 }
00115 
00116 void osl::game_playing::
00117 HistoryToTable::setPV(const PVHistory& pv_history, const GameState& gstate, search::SimpleHashTable& table)
00118 {
00119   const Player Turn = gstate.state().turn();
00120   NumEffectState state(gstate.getInitialState());
00121   MoveStack history = gstate.moveHistory();
00122   HashKey key(state);
00123   for (int i=history.size(); i>0; --i) {
00124     const Move m = history.lastMove(i);
00125     if (! m.isNormal() || ! state.isValidMove(m)) {
00126       std::cerr << "setPV failed " << i << " " << m << "\n" << state;
00127 #ifndef NDEBUG
00128       for (int j=history.size(); j>0; --j)
00129         std::cerr << history.lastMove(j) << " ";
00130       std::cerr << std::endl;
00131 #endif
00132       return;
00133     }
00134     const MoveWithComment& pv = pv_history[(history.size()-i) % pv_history.size()];
00135     if (pv.root == key && state.turn() == Turn && !pv.moves.empty()) {
00136       if (table.isVerbose()) {
00137         std::cerr << "setPV " << record::csa::show(m) << " ";
00138         BOOST_FOREACH(Move p, pv.moves)
00139           std::cerr << record::csa::show(p);
00140         std::cerr << "\n";
00141       }
00142       if (! pv.move.isNormal() || ! state.isValidMove(pv.move)) 
00143       {
00144         std::cerr << "setPV failed (corrupt pv) " << pv.move << "\n";
00145       }
00146       else
00147       {
00148         NumEffectState state_copy = state;
00149         state_copy.makeMove(pv.move);
00150         HashKey cur = key.newHashWithMove(pv.move);
00151         BOOST_FOREACH(Move move, pv.moves) {
00152           SimpleHashRecord *record = table.allocate(cur, 1000);
00153           if (record) {
00154             if (move == Move::PASS(state_copy.turn()) // pass is allowed here
00155                 || state_copy.isValidMove(move)) {
00156               record->setBestMove(move);
00157             }
00158             else {
00159               std::cerr << "setPV failed (corrupt pv) " << i << " " << move << "\n";
00160               break;
00161             }
00162           }
00163           state_copy.makeMove(move);
00164           cur = cur.newHashWithMove(move);
00165         }
00166       }
00167     }
00168     key = key.newHashWithMove(m);
00169     state.makeMove(m);
00170   }
00171 }
00172 
00173 /* ------------------------------------------------------------------------- */
00174 // ;;; Local Variables:
00175 // ;;; mode:c++
00176 // ;;; c-basic-offset:2
00177 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines