00001 #include "osl/record/opening/openingBook.h"
00002 #include "osl/record/record.h"
00003 #include "osl/record/compactBoard.h"
00004 #include "osl/apply_move/applyMove.h"
00005 #include <boost/random/mersenne_twister.hpp>
00006 #include <boost/random/uniform_int.hpp>
00007 #include <boost/foreach.hpp>
00008 #include <algorithm>
00009 #include <iostream>
00010 #include <stdexcept>
00011
00012 #ifndef MINIMAL
00013 osl::record::opening::
00014 WinCountBook::WinCountBook(const char *filename)
00015 : ifs(filename, std::ios_base::binary)
00016 {
00017 if (! ifs)
00018 {
00019 const char *message = "WinCountBook: open failed ";
00020 std::cerr << message << filename << std::endl;
00021 throw std::runtime_error(std::string(message) + filename);
00022 }
00023 nStates=readInt();
00024 }
00025
00026 osl::record::opening::
00027 WinCountBook::~WinCountBook()
00028 {
00029 }
00030
00031 int osl::record::opening::
00032 WinCountBook::readInt()
00033 {
00034 int ret=0;
00035 CArray<char,4> cs;
00036 ifs.read(&cs[0],4);
00037 for (int i=0;i<4;i++) {
00038 ret = (ret<<8)|(cs[i]&255);
00039 }
00040 return ret;
00041 }
00042
00043 void osl::record::opening::
00044 WinCountBook::seek(int offset)
00045 {
00046 ifs.seekg(offset,std::ios::beg);
00047 }
00048
00049 osl::vector<osl::record::opening::OBMove> osl::record::opening::
00050 WinCountBook::getMoves(int stateIndex)
00051 {
00052 assert(stateIndex >= 0);
00053 seek(4+16*stateIndex+8);
00054 int nMoves=readInt();
00055 int moveIndex=readInt();
00056 seek(4+16*nStates+8*moveIndex);
00057 vector<OBMove> moves;
00058 moves.reserve(nMoves);
00059 for(int i=0;i<nMoves;i++)
00060 {
00061 Move move=Move::makeDirect(readInt());
00062 int stateIndex=readInt();
00063 moves.push_back(OBMove(move,stateIndex));
00064 }
00065 return moves;
00066 }
00067
00068 int osl::record::opening::
00069 WinCountBook::getWinCount(int stateIndex)
00070 {
00071 seek(4+16*stateIndex);
00072 return readInt();
00073 }
00074
00075 int osl::record::opening::
00076 WinCountBook::getLoseCount(int stateIndex)
00077 {
00078 seek(4+16*stateIndex+4);
00079 return readInt();
00080 }
00081
00082 std::ostream& osl::record::opening::operator<<(std::ostream& os, const WMove& w)
00083 {
00084 osl::record::writeInt(os, osl::record::opening::OMove(w.getMove()));
00085 osl::record::writeInt(os, w.getStateIndex());
00086 osl::record::writeInt(os, w.getWeight());
00087 return os;
00088 }
00089 #endif
00090
00091 std::istream& osl::record::opening::operator>>(std::istream& is, WMove& w)
00092 {
00093 w.move = OMove(osl::record::readInt(is)).operator Move();
00094 w.stateIndex = osl::record::readInt(is);
00095 w.weight = osl::record::readInt(is);
00096 return is;
00097 }
00098
00099 osl::record::opening::
00100 WeightedBook::WeightedBook(const char *filename)
00101 : ifs(filename, std::ios_base::binary)
00102 {
00103 if (! ifs)
00104 {
00105 const char *message = "WeightedBook: open failed ";
00106 std::cerr << message << filename << std::endl;
00107 throw std::runtime_error(std::string(message) + filename);
00108 }
00109 #ifndef NDEBUG
00110 int version =
00111 #endif
00112 readInt(ifs);
00113 assert(version == 1);
00114 nStates = osl::record::readInt(ifs);
00115 nMoves = osl::record::readInt(ifs);
00116 startState = osl::record::readInt(ifs);
00117 }
00118
00119 osl::record::opening::
00120 WeightedBook::~WeightedBook()
00121 {
00122 }
00123
00124 void osl::record::opening::
00125 WeightedBook::seek(int offset)
00126 {
00127 ifs.seekg(offset,std::ios::beg);
00128 }
00129
00130 osl::record::opening::WeightedBook::WMoveContainer osl::record::opening::
00131 WeightedBook::getMoves(int stateIndex, const bool visit_zero)
00132 {
00133 assert(stateIndex >= 0);
00134 seek(HEADER_SIZE + STATE_SIZE * stateIndex);
00135 int moveIndex=readInt(ifs);
00136 int nWMoves=readInt(ifs);
00137 seek(HEADER_SIZE + STATE_SIZE * nStates + MOVE_SIZE * moveIndex);
00138 vector<WMove> moves;
00139 moves.reserve(nWMoves);
00140 for(int i=0;i<nWMoves;i++)
00141 {
00142 WMove wm;
00143 ifs >> wm;
00144 if (!visit_zero && wm.getWeight() == 0) continue;
00145 moves.push_back(wm);
00146 }
00147 return moves;
00148 }
00149
00150 osl::record::CompactBoard osl::record::opening::
00151 WeightedBook::getCompactBoard(int stateIndex)
00152 {
00153 seek(HEADER_SIZE + STATE_SIZE * nStates + MOVE_SIZE * nMoves
00154 + BOARD_SIZE * stateIndex);
00155 CompactBoard board;
00156 ifs >> board;
00157 return board;
00158 }
00159
00160 osl::SimpleState osl::record::opening::
00161 WeightedBook::getBoard(int stateIndex)
00162 {
00163 const CompactBoard board = getCompactBoard(stateIndex);
00164 return board.getState();
00165 }
00166
00167 int osl::record::opening::
00168 WeightedBook::getWhiteWinCount(int stateIndex)
00169 {
00170 seek(HEADER_SIZE + STATE_SIZE * stateIndex);
00171 readInt(ifs);
00172 readInt(ifs);
00173 readInt(ifs);
00174 return readInt(ifs);
00175 }
00176
00177 int osl::record::opening::
00178 WeightedBook::getBlackWinCount(int stateIndex)
00179 {
00180 seek(HEADER_SIZE + STATE_SIZE * stateIndex);
00181 readInt(ifs);
00182 readInt(ifs);
00183 return readInt(ifs);
00184 }
00185
00186 void osl::record::opening::
00187 WeightedBook::validate()
00188 {
00189 {
00190 osl::SimpleState state(osl::HIRATE);
00191 osl::SimpleState start = getBoard(startState);
00192 assert(state == start);
00193 }
00194
00195 vector<char> visited(nStates);
00196 std::fill(visited.begin(), visited.end(), false);
00197
00198 osl::vector<int> stateToCheck;
00199 stateToCheck.push_back(startState);
00200 visited[startState] = true;
00201
00202 while (!stateToCheck.empty())
00203 {
00204 const int index = stateToCheck.back();
00205 stateToCheck.pop_back();
00206 osl::SimpleState state = getBoard(index);
00207 osl::vector<osl::record::opening::WMove> moves = getMoves(index);
00208 BOOST_FOREACH(WMove move, moves)
00209 {
00210 osl::SimpleState newState(state);
00211 osl::ApplyMoveOfTurn::doMove(newState, move.getMove());
00212 const int nextIndex = move.getStateIndex();
00213
00214 osl::SimpleState stateInFile = getBoard(nextIndex);
00215 assert(newState == stateInFile);
00216 if (!visited[nextIndex])
00217 {
00218 stateToCheck.push_back(nextIndex);
00219 visited[nextIndex] = true;
00220 }
00221 }
00222 }
00223 }
00224
00225 int osl::record::opening::
00226 WeightedBook::getStateIndex(const SimpleState& state_to_look_for,
00227 const bool visit_zero,
00228 const Player player)
00229 {
00230 int ret = -1;
00231 const CompactBoard board_to_look_for(state_to_look_for);
00232
00233 const CompactBoard start_state = getCompactBoard(getStartState());
00234 if (start_state == board_to_look_for)
00235 {
00236 ret = getStartState();
00237 return ret;
00238 }
00239
00240 vector<char> states(getTotalState(), false);
00241 vector<int> stateToVisit;
00242 stateToVisit.push_back(getStartState());
00243
00244 while (!stateToVisit.empty())
00245 {
00246 const int stateIndex = stateToVisit.back();
00247 stateToVisit.pop_back();
00248 states[stateIndex] = true;
00249
00250 WMoveContainer moves;
00251 if (visit_zero)
00252 moves = getMoves(stateIndex);
00253 else
00254 {
00255 const CompactBoard stateIndexCB = getCompactBoard(stateIndex);
00256 const Player turn = stateIndexCB.getTurn();
00257 const bool zero_include = turn == player ? false : true;
00258 moves = getMoves(stateIndex, zero_include);
00259 }
00260 BOOST_FOREACH(WMove move, moves)
00261 {
00262 const int nextIndex = move.getStateIndex();
00263 if (! states[nextIndex])
00264 {
00265 const CompactBoard state = getCompactBoard(nextIndex);
00266 if (state == board_to_look_for)
00267 {
00268 ret = nextIndex;
00269 return ret;
00270 }
00271
00272 stateToVisit.push_back(nextIndex);
00273 }
00274 }
00275 }
00276
00277 return ret;
00278 }
00279
00280 int osl::record::opening::
00281 WeightedBook::getStateIndex(const osl::vector<osl::Move>& moves)
00282 {
00283 int state_index = getStartState();
00284 BOOST_FOREACH(Move move, moves)
00285 {
00286 const WMoveContainer wmoves = getMoves(state_index);
00287 WMoveContainer::const_iterator it = wmoves.begin();
00288 for (; it != wmoves.end(); ++it)
00289 if (it->getMove() == move) break;
00290 if (it != wmoves.end())
00291 {
00292 state_index = it->getStateIndex();
00293 continue;
00294 }
00295 return -1;
00296 }
00297 return state_index;
00298 }
00299
00300
00301 std::vector<int> osl::record::opening::
00302 WeightedBook::getParents(const int target_state_index)
00303 {
00304 std::vector<int> ret;
00305
00306 if (getStartState() == target_state_index)
00307 return ret;
00308
00309 vector<char> states(getTotalState(), false);
00310 vector<int> stateToVisit;
00311 stateToVisit.push_back(getStartState());
00312
00313 while (!stateToVisit.empty())
00314 {
00315 const int stateIndex = stateToVisit.back();
00316 stateToVisit.pop_back();
00317 states[stateIndex] = true;
00318
00319 const WMoveContainer moves = getMoves(stateIndex);
00320 BOOST_FOREACH(WMove move, moves)
00321 {
00322 const int nextIndex = move.getStateIndex();
00323
00324 if (nextIndex == target_state_index)
00325 ret.push_back(stateIndex);
00326
00327 if (! states[nextIndex])
00328 stateToVisit.push_back(nextIndex);
00329 }
00330 }
00331
00332 return ret;
00333 }
00334
00335
00336
00337
00338