00001 //---------------------------------------------------------------------------- 00002 /** @file GoStaticLadder.cpp 00003 See GoStaticLadder.h 00004 */ 00005 //---------------------------------------------------------------------------- 00006 00007 #include "SgSystem.h" 00008 #include "GoStaticLadder.h" 00009 00010 #include "GoBoard.h" 00011 00012 using namespace std; 00013 00014 //---------------------------------------------------------------------------- 00015 00016 bool GoStaticLadder::IsEdgeLadder(const GoBoard& bd, SgPoint target, 00017 SgBlackWhite toPlay) 00018 { 00019 SgBlackWhite defender = bd.GetColor(target); 00020 int nuLibs = bd.NumLiberties(target); 00021 if (nuLibs > 2) 00022 return false; 00023 00024 // Get attack and defense point 00025 SgPoint attackPoint = SG_NULLMOVE; 00026 SgPoint defensePoint = SG_NULLMOVE; 00027 if (nuLibs == 1) 00028 { 00029 if (toPlay != defender) 00030 return true; 00031 SgPoint theLiberty = bd.TheLiberty(target); 00032 for (SgNb4Iterator it(theLiberty); it; ++it) 00033 if (bd.IsEmpty(*it)) 00034 { 00035 if (attackPoint == SG_NULLMOVE) 00036 attackPoint = *it; 00037 else 00038 { 00039 SG_ASSERT(defensePoint == SG_NULLMOVE); 00040 defensePoint = *it; 00041 } 00042 } 00043 } 00044 else 00045 { 00046 SG_ASSERT(nuLibs == 2); 00047 if (toPlay == defender) 00048 return false; 00049 GoBoard::LibertyIterator it(bd, target); 00050 defensePoint = *it; 00051 ++it; 00052 attackPoint = *it; 00053 } 00054 if (bd.Line(defensePoint) != 1) 00055 { 00056 if (bd.Line(attackPoint) != 1) 00057 return false; 00058 swap(defensePoint, attackPoint); 00059 } 00060 00061 // Find direction to run ladder 00062 int col = SgPointUtil::Col(defensePoint); 00063 int delta; 00064 switch (defensePoint - attackPoint) 00065 { 00066 case SG_NS + SG_WE: 00067 delta = (col == bd.Size() ? SG_NS : SG_WE); 00068 break; 00069 case SG_NS - SG_WE: 00070 delta = (col == 1 ? SG_NS : -SG_WE); 00071 break; 00072 case -SG_NS + SG_WE: 00073 delta = (col == bd.Size() ? -SG_NS : SG_WE); 00074 break; 00075 case -SG_NS - SG_WE: 00076 delta = (col == 1 ? -SG_NS : -SG_WE); 00077 break; 00078 default: 00079 return false; 00080 } 00081 00082 // @todo Check that no block in atari is adjacent to target block (?) 00083 00084 // Compute ladder 00085 while (true) 00086 { 00087 SG_ASSERT(bd.IsEmpty(defensePoint)); 00088 SG_ASSERT(bd.IsEmpty(attackPoint)); 00089 int nuNeighborsDefender = bd.NumNeighbors(defensePoint, defender); 00090 if (nuNeighborsDefender > 1) 00091 return false; 00092 if (nuNeighborsDefender == 0 00093 && bd.NumEmptyNeighbors(defensePoint) < 3) 00094 return true; 00095 defensePoint += delta; 00096 attackPoint += delta; 00097 if (! bd.IsEmpty(defensePoint) || ! bd.IsEmpty(attackPoint)) 00098 return false; 00099 } 00100 00101 return true; 00102 } 00103 00104 bool GoStaticLadder::IsLadder(const GoBoard& bd, SgPoint target, 00105 SgBlackWhite toPlay) 00106 { 00107 return IsEdgeLadder(bd, target, toPlay); 00108 // @todo Handle ladder with target not on edge 00109 } 00110 00111 //----------------------------------------------------------------------------