Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

HandicapPlayer.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file HandicapPlayer.cpp
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 // NOTE: 'color' is currently used only in a few HexAsserts below. 
00039 // Remove this if it will be used outside of the HexAsserts!
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     /** Handicap player wins playing second, so in this case any random
00052     move will suffice. */
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     /** For future implementation: discard the naive responseMap and
00061     just do it here. Only build the responseMap for the places on
00062     the very edge of the board. Possibly edge and second row from
00063     edge...  Depends on whether the theory player will handle all
00064     the edge cases.
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     //Naive mirroring. Ignores handicap stones
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     //Handicap Stones mirroring
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 //----------------------------------------------------------------------------


6 Jan 2011 Doxygen 1.6.3