00001 //---------------------------------------------------------------------------- 00002 /** @file PlayAndSolve.cpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "PlayAndSolve.hpp" 00007 00008 using namespace benzene; 00009 00010 //---------------------------------------------------------------------------- 00011 00012 PlayAndSolve::PlayAndSolve(HexBoard& playerBrd, HexBoard& solverBrd, 00013 BenzenePlayer& player, DfpnSolver& solver, 00014 DfpnStates& positions, const Game& game) 00015 : m_playerBrd(playerBrd), 00016 m_solverBrd(solverBrd), 00017 m_player(player), 00018 m_solver(solver), 00019 m_positions(positions), 00020 m_game(game) 00021 { 00022 } 00023 00024 HexPoint PlayAndSolve::GenMove(const HexState& state, double maxTime) 00025 { 00026 { 00027 // HACK: The player and solver threads could race to call 00028 // VCPattern::GetPatterns(), which constructs the patterns for 00029 // the first time. Force the player to build the vcs first so 00030 // this is not a problem. 00031 LogInfo() << "PlayAndSolve: Building VCs to avoid race condition.\n"; 00032 m_playerBrd.GetPosition().SetPosition(state.Position()); 00033 m_playerBrd.ComputeAll(state.ToPlay()); 00034 LogInfo() << "PlayAndSolve: Continuing on as usual.\n"; 00035 } 00036 00037 boost::mutex mutex; 00038 boost::barrier barrier(3); 00039 m_parallelResult = INVALID_POINT; 00040 boost::thread playerThread(PlayerThread(*this, mutex, barrier, 00041 state, maxTime)); 00042 boost::thread solverThread(SolverThread(*this, mutex, barrier, state)); 00043 barrier.wait(); 00044 playerThread.join(); 00045 solverThread.join(); 00046 return m_parallelResult; 00047 } 00048 00049 00050 void PlayAndSolve::PlayerThread::operator()() 00051 { 00052 LogInfo() << "*** PlayerThread ***\n"; 00053 HexBoard& brd = m_ps.m_playerBrd; 00054 brd.GetPosition().SetPosition(m_state.Position()); 00055 double score; 00056 HexPoint move = m_ps.m_player.GenMove(m_state, m_ps.m_game, brd, 00057 m_maxTime, score); 00058 { 00059 boost::mutex::scoped_lock lock(m_mutex); 00060 if (m_ps.m_parallelResult == INVALID_POINT) 00061 { 00062 LogInfo() << "*** Player move: " << move << '\n'; 00063 m_ps.m_parallelResult = move; 00064 } 00065 } 00066 SgSetUserAbort(true); 00067 m_barrier.wait(); 00068 } 00069 00070 00071 void PlayAndSolve::SolverThread::operator()() 00072 { 00073 LogInfo() << "*** SolverThread ***\n"; 00074 HexBoard& brd = m_ps.m_solverBrd; 00075 brd.GetPosition().SetPosition(m_state.Position()); 00076 PointSequence pv; 00077 HexColor winner = m_ps.m_solver.StartSearch(m_state, m_ps.m_solverBrd, 00078 m_ps.m_positions, pv); 00079 00080 if (winner != EMPTY) 00081 { 00082 if (!pv.empty() && pv[0] != INVALID_POINT) 00083 { 00084 boost::mutex::scoped_lock lock(m_mutex); 00085 m_ps.m_parallelResult = pv[0]; 00086 if (winner == m_state.ToPlay()) 00087 { 00088 LogInfo() << "*** FOUND WIN!!! ***\n" 00089 << "PV: " << HexPointUtil::ToString(pv) << '\n'; 00090 } 00091 else 00092 { 00093 LogInfo() << "*** FOUND LOSS!! ***\n" 00094 << "PV: " << HexPointUtil::ToString(pv) << '\n'; 00095 } 00096 SgSetUserAbort(true); 00097 } 00098 } 00099 m_barrier.wait(); 00100 } 00101 00102 //----------------------------------------------------------------------------