Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SpDumbTacticalPlayer.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SpDumbTacticalPlayer.cpp
00003     See SpDumbTacticalPlayer.h */
00004 //----------------------------------------------------------------------------
00005 
00006 #include "SgSystem.h"
00007 #include "SpDumbTacticalPlayer.h"
00008 
00009 #include "GoBensonSolver.h"
00010 #include "GoBoardUtil.h"
00011 #include "GoLadder.h"
00012 #include "GoModBoard.h"
00013 #include "SgEvaluatedMoves.h"
00014 #include "SgNbIterator.h"
00015 
00016 using GoLadderUtil::LadderStatus;
00017 
00018 //----------------------------------------------------------------------------
00019 
00020 SpDumbTacticalMoveGenerator::SpDumbTacticalMoveGenerator(const GoBoard& board)
00021     : SpStaticMoveGenerator(board), m_useLadders(false)
00022 { }
00023     
00024 int SpDumbTacticalMoveGenerator::Score(SgPoint p)
00025 {
00026     SG_UNUSED(p);
00027     // DumbTacticalMoveGenerator uses whole-board move generation, 
00028     // it does not work by scoring individual moves.
00029     SG_ASSERT(false);
00030     return INT_MIN; 
00031 }
00032 
00033 void SpDumbTacticalMoveGenerator::GenerateMoves(SgEvaluatedMoves& eval,
00034                                                 SgBlackWhite toPlay)
00035 {
00036     GoModBoard modBoard(m_board);
00037     GoBoard& bd = modBoard.Board();
00038     GoRestoreToPlay restoreToPlay(bd);
00039     bd.SetToPlay(toPlay);
00040     // Don't permit player to kill its own groups.
00041     GoRestoreSuicide restoreSuicide(bd, false);
00042     GenerateDefendMoves(eval);
00043     GenerateAttackMoves(eval);
00044     // Otherwise make a random legal move that doesn't fill own eye
00045     // This will be done automatically by the simple player if no moves
00046     // have been generated.
00047 }
00048 
00049 void SpDumbTacticalMoveGenerator::GenerateDefendMoves(SgEvaluatedMoves& eval)
00050 {
00051     const int stoneweight = 1000;
00052     // Do any of own blocks have just one liberty?
00053     for (GoBlockIterator anchorit(m_board); anchorit; ++anchorit)
00054     {
00055         // Ignore opponent blocks
00056         if (m_board.IsColor(*anchorit, m_board.Opponent()))
00057             continue;
00058 
00059         // Try to save blocks in atari
00060         if (! m_board.InAtari(*anchorit))
00061             continue;
00062         
00063         // Don't waste saving blocks that will be laddered to death anyway
00064         if (m_useLadders)
00065         {
00066             GoLadderStatus status = LadderStatus(m_board, *anchorit, false);
00067             if (status == GO_LADDER_CAPTURED)
00068                 continue;
00069         }
00070         
00071         int score = stoneweight * m_board.NumStones(*anchorit);
00072 
00073         // Generate liberty
00074         eval.AddMove(m_board.TheLiberty(*anchorit), score);
00075         
00076         // Generate any captures that will save the group
00077         for (GoAdjBlockIterator<GoBoard> adjbit(m_board, *anchorit, 1);
00078              adjbit; ++adjbit)
00079         {
00080             int bonus = stoneweight * m_board.NumStones(*adjbit);
00081             if (m_board.InAtari(*adjbit)) 
00082             // should always be true but just in case
00083             {
00084                 eval.AddMove(m_board.TheLiberty(*adjbit), score + bonus);
00085             }
00086         }
00087     }
00088 }
00089 
00090 void SpDumbTacticalMoveGenerator::GenerateAttackMoves(SgEvaluatedMoves& eval)
00091 {
00092     const int capturestoneweight = 100;
00093     const int firstlibweight = 100;
00094     const int secondlibweight = 20;
00095     const int stoneweight = 1;
00096 
00097     // Do Benson life test
00098     SgBWSet safepoints;
00099     GoModBoard modBoard(m_board);
00100     GoBoard& bd = modBoard.Board();
00101     GoBensonSolver benson(bd);
00102     benson.FindSafePoints(&safepoints);
00103     
00104     // Find opponent blocks without two eyes (using Benson algorithm)
00105     for (GoBlockIterator anchorit(bd); anchorit; ++anchorit)
00106     {
00107         // Ignore own blocks
00108         if (bd.IsColor(*anchorit, bd.ToPlay()))
00109             continue;
00110         
00111         // Ignore opponent blocks that are unconditionally alive
00112         if (safepoints[bd.Opponent()].Contains(*anchorit))
00113             continue;
00114 
00115         // Generate all ladder captures
00116         if (m_useLadders)
00117         {
00118             SgPoint tocapture, toescape;
00119             GoLadderStatus status = LadderStatus(bd, *anchorit, false,
00120                                                  &tocapture, &toescape);
00121             if (status == GO_LADDER_CAPTURED)
00122             {
00123                 int score = bd.NumStones(*anchorit) * capturestoneweight;
00124                 eval.AddMove(tocapture, score);
00125             }
00126         }
00127             
00128         // Score according to:
00129         // 1. -First liberties
00130         // 2. +Second liberties
00131         // 3. +Size of group
00132         // [4]. Own liberties?
00133         int firstlibs = bd.NumLiberties(*anchorit);
00134         int size = bd.NumStones(*anchorit);
00135         for (GoBoard::LibertyIterator libit(bd, *anchorit); libit;
00136              ++libit)
00137         {
00138             int secondlibs = 0;
00139             for (SgNb4Iterator nbit(*libit); nbit; ++nbit)
00140             {
00141                 if (bd.IsValidPoint(*nbit) && bd.IsEmpty(*nbit))
00142                 {
00143                     secondlibs++;
00144                 }
00145             }
00146             int score   = size * stoneweight
00147                         + secondlibs * secondlibweight
00148                         - firstlibs * firstlibweight;
00149             eval.AddMove(*libit, score);
00150         }
00151     }
00152 }
00153 
00154 


Sun Mar 13 2011 Doxygen 1.7.1