Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SwapCheck.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SwapCheck.cpp
00003  */
00004 //----------------------------------------------------------------------------
00005 
00006 #include "BoardUtils.hpp"
00007 #include "SwapCheck.hpp"
00008 
00009 using namespace benzene;
00010 
00011 //----------------------------------------------------------------------------
00012 
00013 namespace {
00014 
00015 //----------------------------------------------------------------------------
00016 
00017 bool s_swapLoaded = false;
00018     
00019 /** Contains moves to swap for each boardsize. 
00020     Use strings of the form "nxn" to index the map for an (n, n)
00021     board. */
00022 std::map<std::string, std::set<HexPoint> > s_swapMoves;
00023 
00024 /** Loads swap moves for each boardsize from the given file.
00025     Ignores lines begining with '#'. On lines not begining with '#',
00026     expects a string of the form "nxn" and the name of a HexPoint:
00027     this pair denotes a move to swap on an nxn board. The remainder of
00028     the line is not looked at. */
00029 void LoadSwapMoves(const std::string& name)
00030 {
00031     using namespace boost::filesystem;
00032     path swap_path = path(ABS_TOP_SRCDIR) / "share";
00033     path swap_list = swap_path / name;
00034     swap_list.normalize();
00035     std::string swap_file = swap_list.native_file_string();
00036     LogInfo() << "SwapCheck: Loading swap moves: '" << swap_file << "'...\n";
00037     s_swapMoves.clear();
00038     std::ifstream s(swap_file.c_str());
00039     if (!s)
00040         throw BenzeneException("SwapCheck: could not open list!\n");
00041     std::string line;
00042     std::size_t lineNumber = 0;
00043     while (std::getline(s, line))
00044     {
00045         lineNumber++;
00046         if (line[0] == '#')
00047             continue;
00048         if (line.size() < 6) // skip (nearly) empty lines
00049             continue;
00050         std::string boardSizeStr;
00051         std::string pointStr;
00052         std::istringstream ss(line);
00053         ss >> boardSizeStr;
00054         ss >> pointStr;
00055         HexPoint point = HexPointUtil::FromString(pointStr);
00056         if (point == INVALID_POINT)
00057             LogWarning() << "SwapCheck: line " << lineNumber 
00058                          << ": invalid cell!\n";
00059         else
00060             s_swapMoves[boardSizeStr].insert(point);
00061     }
00062     s.close();
00063     s_swapLoaded = true;
00064 }
00065 
00066 //----------------------------------------------------------------------------
00067 
00068 } // anonymous namespace
00069 
00070 //----------------------------------------------------------------------------
00071 
00072 bool SwapCheck::PlaySwap(const Game& gameState, HexColor toPlay)
00073 {
00074     if (gameState.AllowSwap()
00075         && (1 == gameState.History().size())
00076         && (!FIRST_TO_PLAY == toPlay))
00077     {
00078         const StoneBoard& brd = gameState.Board();
00079     HexAssert(1 == brd.NumStones());
00080     
00081     // If board has unequal dimensions, we want to traverse the
00082     // shorter distance.
00083     if (brd.Width() != brd.Height()) 
00084         {
00085         if ((brd.Width() > brd.Height() && toPlay == !VERTICAL_COLOR) ||
00086         (brd.Width() < brd.Height() && toPlay == VERTICAL_COLOR))
00087             {
00088                 LogInfo() << "SwapCheck: swapping to get shorter side.\n";
00089         return true;
00090             }
00091     }
00092         else 
00093         {
00094             if (!s_swapLoaded)
00095                 LoadSwapMoves("swap-moves.txt");
00096         HexPoint firstMove = gameState.History().back().point();
00097         if (toPlay == VERTICAL_COLOR)
00098                 // Swap decisions assume VERTICAL_COLOR was FIRST_TO_PLAY,
00099                 // so we mirror the first move if this is not the case
00100                 // (i.e. to consider an equivalent decision).
00101                 firstMove = BoardUtils::Mirror(brd.Const(), firstMove);
00102             std::ostringstream os;
00103             os << brd.Width() << 'x' << brd.Height();
00104             if (s_swapMoves[os.str()].count(firstMove) > 0)
00105             {
00106                 LogInfo() << "SwapCheck: playing swap.\n";
00107                 return true;
00108             }
00109         }
00110         LogInfo() << "SwapCheck: opting not to swap.\n";
00111     }
00112     return false;
00113 }
00114 
00115 //----------------------------------------------------------------------------


6 Jan 2011 Doxygen 1.6.3