PerfectPlayer.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006 #include "SgSystem.h"
00007 #include "SgRandom.h"
00008 #include "BitsetIterator.hpp"
00009 #include "PerfectPlayer.hpp"
00010
00011 using namespace benzene;
00012
00013
00014
00015 namespace
00016 {
00017
00018 HexPoint RandomBit(const bitset_t& bs, SgRandom& random)
00019 {
00020 HexAssert(bs.any());
00021 int index = random.Int(bs.count());
00022 for (BitsetIterator it(bs); it; ++it)
00023 {
00024 if (index == 0)
00025 return *it;
00026 --index;
00027 }
00028 HexAssert(false);
00029 return static_cast<HexPoint>(BitsetUtil::FirstSetBit(bs));
00030 }
00031
00032 }
00033
00034
00035
00036 PerfectPlayer::PerfectPlayer(DfpnSolver& solver, DfpnStates& positions)
00037 : BenzenePlayer(),
00038 m_solver(solver),
00039 m_positions(positions),
00040 m_maxTime(60.0),
00041 m_propagateBackwards(true)
00042 {
00043 }
00044
00045 PerfectPlayer::~PerfectPlayer()
00046 {
00047 }
00048
00049
00050
00051 HexPoint PerfectPlayer::Search(const HexState& state, const Game& game,
00052 HexBoard& brd, const bitset_t& consider,
00053 double maxTime, double& score)
00054 {
00055 SG_UNUSED(consider);
00056 SG_UNUSED(score);
00057 LogInfo() << "PerfectPlayer::Search()\n";
00058 LogInfo() << state.Position() << '\n';
00059 if (FillinCausedWin())
00060 {
00061 LogInfo() << "PerfectPlayer: Fillin caused win!\n";
00062 HexColor color = state.ToPlay();
00063 brd.GetPosition().SetPosition(state.Position());
00064 brd.ComputeAll(color);
00065 const InferiorCells& inf = brd.GetInferiorCells();
00066 if (m_fillinWinner == color && inf.Captured(color).any())
00067 {
00068 LogInfo() << "PerfectPlayer: Playing into our fillin...\n";
00069 return RandomBit(inf.Captured(color), SgRandom::Global());
00070 }
00071 else if (m_fillinWinner == !color && inf.Captured(!color).any())
00072 {
00073 LogInfo() << "PerfectPlayer: Playing into opponent fillin...\n";
00074 return RandomBit(inf.Captured(color), SgRandom::Global());
00075 }
00076 LogInfo() << "PerfectPlayer: Playing random empty cell...\n";
00077 return RandomBit(state.Position().GetEmpty(), SgRandom::Global());
00078 }
00079 double timeForMove = std::min(m_maxTime, maxTime);
00080 LogInfo() << "TimeForMove=" << timeForMove << '\n';
00081 double oldTimelimit = m_solver.Timelimit();
00082 m_solver.SetTimelimit(timeForMove);
00083 PointSequence pv;
00084 HexColor winner = m_solver.StartSearch(state, brd, m_positions, pv);
00085 m_solver.SetTimelimit(oldTimelimit);
00086 if (m_propagateBackwards)
00087 m_solver.PropagateBackwards(game, m_positions);
00088
00089 if (winner != EMPTY && !pv.empty())
00090 return pv[0];
00091
00092
00093
00094
00095
00096
00097
00098
00099 if (winner != EMPTY && pv.empty())
00100 {
00101 boost::scoped_ptr<DfpnHashTable> myTable(new DfpnHashTable(10));
00102 boost::scoped_ptr<DfpnDB> myDB(0);
00103 SolverDBParameters myParam;
00104 DfpnStates myStates(myTable, myDB, myParam);
00105 LogInfo() << "PerfectPlayer: Found win with empty pv at this state:\n";
00106 LogInfo() << brd << '\n';
00107 LogInfo() << "PerfectPlayer: Re-solving with temporary hash table.\n";
00108 winner = m_solver.StartSearch(state, brd, myStates, pv);
00109 HexAssert(winner != EMPTY);
00110 HexAssert(!pv.empty());
00111 return pv[0];
00112 }
00113
00114 DfpnData data;
00115 if (!m_positions.Get(state, data))
00116 throw BenzeneException("Root node not in database!?!");
00117 std::size_t maxWork = 0;
00118 HexPoint bestMove = pv[0];
00119 HexState myState(state);
00120 for (std::size_t i = 0; i < data.m_children.Size(); ++i)
00121 {
00122 data.m_children.PlayMove(i, myState);
00123 DfpnData child;
00124 if (m_positions.Get(myState, child))
00125 {
00126
00127
00128 if (!child.m_bounds.IsWinning() && child.m_work > maxWork)
00129 {
00130 bestMove = data.m_children.FirstMove(i);
00131 maxWork = child.m_work;
00132 }
00133 }
00134 data.m_children.UndoMove(i, myState);
00135 }
00136 LogInfo() << "bestMove=" << bestMove << " (" << maxWork << ")\n";
00137 return bestMove;
00138 }
00139
00140