00001
00002
00003
00004
00005
00006 #include "SgSystem.h"
00007 #include "HandicapPlayer.hpp"
00008 #include "BoardUtils.hpp"
00009
00010 using namespace benzene;
00011
00012
00013
00014 HandicapPlayer::HandicapPlayer(ICEngine* ice)
00015 : BenzenePlayer(),
00016 m_ice(ice),
00017 m_assume_added_stones(true)
00018 {
00019 LogFine() << "--- HandicapPlayer" << '\n';
00020 }
00021
00022 HandicapPlayer::~HandicapPlayer()
00023 {
00024 }
00025
00026
00027
00028 HexPoint HandicapPlayer::Search(HexBoard& brd,
00029 const Game& game_state,
00030 HexColor color,
00031 const bitset_t& consider,
00032 double max_time,
00033 double& score)
00034 {
00035 UNUSED(consider);
00036 UNUSED(max_time);
00037 UNUSED(score);
00038
00039
00040 #ifdef NDEBUG
00041 UNUSED(color);
00042 #endif
00043
00044 HexPoint lastMove, response;
00045 HexAssert(color == !VERTICAL_COLOR);
00046
00047 m_width = (m_assume_added_stones) ? brd.Width()-1 : brd.Width();
00048 if (m_width == brd.Height())
00049 return RESIGN;
00050
00051
00052
00053 if (game_state.History().empty()) {
00054 HexAssert(color == FIRST_TO_PLAY);
00055 return BoardUtils::RandomEmptyCell(brd.GetPosition());
00056 }
00057
00058 lastMove = game_state.History().back().point();
00059 LogInfo() << "Last move: " << lastMove << '\n';
00060
00061
00062
00063
00064
00065
00066 buildResponseMap(brd.GetPosition());
00067 response = m_responseMap[lastMove];
00068 if (!brd.GetPosition().IsPlayed(response) && response != INVALID_POINT)
00069 return response;
00070
00071 LogInfo() << "Playing random move" << '\n';
00072 return BoardUtils::RandomEmptyCell(brd.GetPosition());
00073 }
00074
00075 void HandicapPlayer::buildResponseMap(const StoneBoard& brd)
00076 {
00077 int x, y, offset;
00078 m_responseMap.clear();
00079 offset = (m_width > brd.Height()) ? 1 : -1;
00080
00081 for (BoardIterator it = brd.Const().Interior(); it; ++it)
00082 {
00083 HexPointUtil::pointToCoords(*it, x, y);
00084 if (y > x)
00085 y = y + offset;
00086 else
00087 x = x - offset;
00088 if (y >= m_width || x >= brd.Height())
00089 m_responseMap[*it] = INVALID_POINT;
00090 else
00091 m_responseMap[*it] = HexPointUtil::coordsToPoint(y, x);
00092 }
00093
00094 if (m_assume_added_stones)
00095 {
00096 x = brd.Width() - 1;
00097 y = 0;
00098 makeMiai(HexPointUtil::coordsToPoint(x, y),
00099 HexPointUtil::coordsToPoint(x, y+1));
00100 for (y = 6; y < brd.Height() - 1; y = y + 6)
00101 {
00102 makeMiai(HexPointUtil::coordsToPoint(x, y),
00103 HexPointUtil::coordsToPoint(x, y+1));
00104 threeToOne(brd,
00105 HexPointUtil::coordsToPoint(x-1, y-3),
00106 HexPointUtil::coordsToPoint(x-1, y-4),
00107 HexPointUtil::coordsToPoint(x, y-4),
00108 HexPointUtil::coordsToPoint(x, y-3));
00109 threeToOne(brd,
00110 HexPointUtil::coordsToPoint(x-1, y-1),
00111 HexPointUtil::coordsToPoint(x-1, y),
00112 HexPointUtil::coordsToPoint(x, y-1),
00113 HexPointUtil::coordsToPoint(x, y-2));
00114 }
00115 y = y - 6;
00116 if (y == brd.Height() - 6 || y == brd.Height() - 7)
00117 {
00118 y = y + 2;
00119 makeMiai(HexPointUtil::coordsToPoint(x, y),
00120 HexPointUtil::coordsToPoint(x, y+1));
00121 }
00122 if (y + 3 < brd.Height())
00123 {
00124 threeToOne(brd,
00125 HexPointUtil::coordsToPoint(x-1, y+3),
00126 HexPointUtil::coordsToPoint(x-1, y+2),
00127 HexPointUtil::coordsToPoint(x, y+2),
00128 HexPointUtil::coordsToPoint(x, y+3));
00129 }
00130 if (y + 4 < brd.Height())
00131 {
00132 if (brd.IsPlayed(HexPointUtil::coordsToPoint(x-1, y+3)))
00133 {
00134 m_responseMap[HexPointUtil::coordsToPoint(x, y+4)] =
00135 HexPointUtil::coordsToPoint(x, y+3);
00136 }
00137 else
00138 {
00139 m_responseMap[HexPointUtil::coordsToPoint(x, y+4)] =
00140 HexPointUtil::coordsToPoint(x-1, y+3);
00141 }
00142 }
00143 }
00144 }
00145
00146 void HandicapPlayer::makeMiai(HexPoint p1, HexPoint p2)
00147 {
00148 m_responseMap[p1] = p2;
00149 m_responseMap[p2] = p1;
00150 }
00151
00152 void HandicapPlayer::threeToOne(const StoneBoard& brd,
00153 HexPoint dest, HexPoint p1, HexPoint p2,
00154 HexPoint p3)
00155 {
00156 if (brd.IsPlayed(dest) && brd.IsBlack(dest))
00157 {
00158 m_responseMap[p3] = (p3 > p2)
00159 ? static_cast<HexPoint>(p3 + MAX_WIDTH)
00160 : static_cast<HexPoint>(p3 - MAX_WIDTH);
00161 }
00162 else if (brd.IsPlayed(dest))
00163 {
00164 if (brd.IsPlayed(p2) && brd.IsPlayed(p3))
00165 {
00166 m_responseMap[p2] = p1;
00167 m_responseMap[p3] = p1;
00168 return;
00169 }
00170 else if (brd.IsPlayed(p1) && brd.IsPlayed(p3))
00171 {
00172 m_responseMap[p1] = p2;
00173 m_responseMap[p3] = p2;
00174 return;
00175 }
00176 else if (brd.IsPlayed(p1) && brd.IsPlayed(p2))
00177 {
00178 m_responseMap[p1] = p3;
00179 m_responseMap[p2] = p3;
00180 return;
00181 }
00182 else
00183 {
00184 makeMiai(p1, p2);
00185 m_responseMap[p3] = (p3 > p2)
00186 ? static_cast<HexPoint>(p3 + MAX_WIDTH)
00187 : static_cast<HexPoint>(p3 - MAX_WIDTH);
00188 }
00189 }
00190 else if (brd.IsWhite(p1) || brd.IsWhite(p2) || brd.IsWhite(p3))
00191 {
00192 m_responseMap[p3] = (p3 > p2)
00193 ? static_cast<HexPoint>(p3 + MAX_WIDTH)
00194 : static_cast<HexPoint>(p3 - MAX_WIDTH);
00195 }
00196 else
00197 {
00198 m_responseMap[p1] = dest;
00199 m_responseMap[p2] = dest;
00200 m_responseMap[p3] = dest;
00201 }
00202 }
00203
00204