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


17 Jun 2010 Doxygen 1.4.7