00001 //---------------------------------------------------------------------------- 00002 /** @file BenzenePlayer.cpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "BenzenePlayer.hpp" 00007 #include "EndgameUtils.hpp" 00008 #include "BoardUtils.cpp" 00009 00010 using namespace benzene; 00011 00012 //---------------------------------------------------------------------------- 00013 00014 BenzenePlayer::BenzenePlayer() 00015 : HexPlayer(), 00016 m_search_singleton(false) 00017 { 00018 } 00019 00020 BenzenePlayer::~BenzenePlayer() 00021 { 00022 } 00023 00024 //---------------------------------------------------------------------------- 00025 00026 /** @bug Subtract time spent to here from max_time after each step. */ 00027 HexPoint BenzenePlayer::GenMove(const HexState& state, const Game& game, 00028 HexBoard& brd, double maxTime, 00029 double& score) 00030 { 00031 HexPoint move = INVALID_POINT; 00032 bitset_t consider; 00033 00034 move = InitSearch(brd, state.ToPlay(), consider, score); 00035 if (move != INVALID_POINT) 00036 return move; 00037 00038 move = CheckEndgame(brd, state.ToPlay(), consider, score); 00039 if (move != INVALID_POINT) 00040 return move; 00041 00042 LogInfo() << "Best move cannot be determined, must search state.\n"; 00043 return Search(state, game, brd, consider, maxTime, score); 00044 } 00045 00046 /** Finds inferior cells, builds vcs. Sets moves to consider to all 00047 empty cells. If fillin causes terminal state, sets 00048 m_fillinCausedWin to true and recomputes fillin/vcs with ice 00049 temporarily turned off (so it can pass the players a non-empty 00050 consider set). 00051 */ 00052 HexPoint BenzenePlayer::InitSearch(HexBoard& brd, HexColor color, 00053 bitset_t& consider, double& score) 00054 { 00055 // Resign if the game is already over 00056 Groups groups; 00057 GroupBuilder::Build(brd.GetPosition(), groups); 00058 if (groups.IsGameOver()) 00059 { 00060 score = IMMEDIATE_LOSS; 00061 return RESIGN; 00062 } 00063 StoneBoard original(brd.GetPosition()); 00064 brd.ComputeAll(color); 00065 m_fillinCausedWin = false; 00066 m_fillinWinner = EMPTY; 00067 if (brd.GetGroups().IsGameOver()) 00068 { 00069 // Fillin caused win, remove and re-compute without ice. 00070 m_fillinCausedWin = true; 00071 m_fillinWinner = brd.GetGroups().GetWinner(); 00072 LogInfo() << "Captured cells caused win! Removing...\n"; 00073 brd.GetPosition().SetPosition(original); 00074 bool oldUseIce = brd.UseICE(); 00075 brd.SetUseICE(false); 00076 brd.ComputeAll(color); 00077 brd.SetUseICE(oldUseIce); 00078 HexAssert(!brd.GetGroups().IsGameOver()); 00079 } 00080 consider = brd.GetPosition().GetEmpty(); 00081 score = 0; 00082 return INVALID_POINT; 00083 } 00084 00085 HexPoint BenzenePlayer::CheckEndgame(HexBoard& brd, HexColor color, 00086 bitset_t& consider, double& score) 00087 { 00088 if (EndgameUtils::IsDeterminedState(brd, color, score)) 00089 return EndgameUtils::PlayDeterminedState(brd, color); 00090 else 00091 { 00092 consider = EndgameUtils::MovesToConsider(brd, color); 00093 HexAssert(consider.any()); 00094 } 00095 00096 score = 0; 00097 if (consider.count() == 1 && !m_search_singleton) 00098 { 00099 HexPoint move = static_cast<HexPoint> 00100 (BitsetUtil::FindSetBit(consider)); 00101 LogInfo() << "Mustplay is singleton!\n"; 00102 return move; 00103 } 00104 return INVALID_POINT; 00105 } 00106 00107 //---------------------------------------------------------------------------- 00108