Go to the documentation of this file.00001
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
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
00047
00048
00049
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();
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()))
00087 reverse_history.push(key);
00088
00089
00090 adjustDominance(key, table, black_win, white_win, last_move);
00091 }
00092
00093 while (! reverse_history.empty())
00094 {
00095
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())
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
00175
00176
00177