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