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/apply_move/applyMove.h"
00013 #include "osl/record/csa.h"
00014 #include <boost/foreach.hpp>
00015 #include <iostream>
00016
00017 const int osl::game_playing::HistoryToTable::LIMIT
00018 = osl::search::SearchTable::HistorySpecialDepth;
00019
00020 void osl::game_playing::
00021 HistoryToTable::adjustDominance(const HashKey& key,
00022 search::SimpleHashTable& table,
00023 int black_win, int white_win,
00024 const Move& good_move)
00025 {
00026 const PieceStand black_stand = key.pieceStand();
00027 const Player turn = key.turn();
00028 BOOST_FOREACH(Ptype ptype, PieceStand::order)
00029 {
00030 if (black_stand.get(ptype))
00031 {
00032
00033 PieceStand new_stand = black_stand;
00034 new_stand.sub(ptype);
00035 HashKey new_key = key;
00036 new_key.setPieceStand(new_stand);
00037 SimpleHashRecord *record = table.allocate(new_key, LIMIT);
00038 if (record)
00039 {
00040 const Move record_move = (turn == WHITE) ? good_move : Move::INVALID();
00041 record->setAbsoluteValue(record_move, white_win, LIMIT);
00042 record->qrecord.setHistoryValue(record_move, white_win);
00043 }
00044 }
00045 if (black_stand.canAdd(ptype))
00046 {
00047
00048
00049
00050
00051 PieceStand new_stand = black_stand;
00052 new_stand.add(ptype);
00053 HashKey new_key = key;
00054 new_key.setPieceStand(new_stand);
00055 SimpleHashRecord *record = table.allocate(new_key, LIMIT);
00056 if (record)
00057 {
00058 const Move record_move = (turn == BLACK) ? good_move : Move::INVALID();
00059 record->setAbsoluteValue(record_move, black_win, LIMIT);
00060 record->qrecord.setHistoryValue(record_move, black_win);
00061 }
00062 }
00063 }
00064 }
00065
00066 void osl::game_playing::
00067 HistoryToTable::adjustTable(const GameState& state, SimpleHashTable& table,
00068 int black_win, int draw, int white_win)
00069 {
00070 const RepetitionCounter& counter = state.counter();
00071
00072
00073 HashKeyStack history = state.hashHistory();
00074 MoveStack move_history = state.moveHistory();
00075 move_history.push(Move::INVALID());
00076 assert(move_history.size() == history.size());
00077
00078 HashKeyStack reverse_history;
00079 while (! history.empty())
00080 {
00081 const HashKey key = history.top();
00082 history.pop();
00083 assert(move_history.hasLastMove());
00084 const Move last_move = move_history.lastMove();
00085 move_history.pop();
00086
00087 if (key != HashKey(state.state()))
00088 reverse_history.push(key);
00089
00090
00091 adjustDominance(key, table, black_win, white_win, last_move);
00092 }
00093
00094 while (! reverse_history.empty())
00095 {
00096
00097 const HashKey key = reverse_history.top();
00098 reverse_history.pop();
00099
00100 SimpleHashRecord *record = table.allocate(key, LIMIT);
00101 const std::pair<Sennichite,int> result = counter.distanceToSennichite(key);
00102 if (result.first.isDraw())
00103 {
00104 record->setAbsoluteValue(Move::INVALID(), draw*result.second, LIMIT);
00105 record->qrecord.setHistoryValue(draw*result.second);
00106 }
00107 else
00108 {
00109 assert(result.first.hasWinner());
00110 const int value = (result.first.winner() == BLACK) ? black_win : white_win;
00111 record->setAbsoluteValue(Move::INVALID(), value, LIMIT);
00112 record->qrecord.setHistoryValue(value);
00113 }
00114 }
00115 }
00116
00117 void osl::game_playing::
00118 HistoryToTable::setPV(const PVHistory& pv_history, const GameState& gstate, search::SimpleHashTable& table)
00119 {
00120 const Player Turn = gstate.state().getTurn();
00121 NumEffectState state(gstate.getInitialState());
00122 MoveStack history = gstate.moveHistory();
00123 HashKey key(state);
00124 for (int i=history.size(); i>0; --i) {
00125 const Move m = history.lastMove(i);
00126 if (! m.isNormal() || ! state.isValidMove(m)) {
00127 std::cerr << "setPV failed " << i << " " << m << "\n" << state;
00128 #ifndef NDEBUG
00129 for (int j=history.size(); j>0; --j)
00130 std::cerr << history.lastMove(j) << " ";
00131 std::cerr << std::endl;
00132 #endif
00133 return;
00134 }
00135 const MoveWithComment& pv = pv_history[(history.size()-i) % pv_history.size()];
00136 if (pv.root == key && state.getTurn() == Turn && !pv.moves.empty()) {
00137 if (table.isVerbose()) {
00138 std::cerr << "setPV " << record::csa::show(m) << " ";
00139 BOOST_FOREACH(Move p, pv.moves)
00140 std::cerr << record::csa::show(p);
00141 std::cerr << "\n";
00142 }
00143 if (! pv.move.isNormal() || ! state.isValidMove(pv.move))
00144 {
00145 std::cerr << "setPV failed (corrupt pv) " << pv.move << "\n";
00146 }
00147 else
00148 {
00149 NumEffectState state_copy = state;
00150 ApplyMoveOfTurn::doMove(state_copy, pv.move);
00151 HashKey cur = key.newHashWithMove(pv.move);
00152 BOOST_FOREACH(Move move, pv.moves) {
00153 SimpleHashRecord *record = table.allocate(cur, 1000);
00154 if (record) {
00155 if (move == Move::PASS(state_copy.getTurn())
00156 || state_copy.isValidMove(move)) {
00157 record->setBestMove(move);
00158 }
00159 else {
00160 std::cerr << "setPV failed (corrupt pv) " << i << " " << move << "\n";
00161 break;
00162 }
00163 }
00164 ApplyMoveOfTurn::doMove(state_copy, move);
00165 cur = cur.newHashWithMove(move);
00166 }
00167 }
00168 }
00169 key = key.newHashWithMove(m);
00170 ApplyMoveOfTurn::doMove(state, m);
00171 }
00172 }
00173
00174
00175
00176
00177
00178