00001 //---------------------------------------------------------------------------- 00002 /** @file GoLadder.h 00003 Fast ladder algorithm, computes ladders and snapbacks. 00004 00005 @note 00006 Will become obsolete when class GoBoard is fast enough for computing 00007 ladders. 00008 */ 00009 //---------------------------------------------------------------------------- 00010 00011 #ifndef GO_LADDER_H 00012 #define GO_LADDER_H 00013 00014 #include "GoBoard.h" 00015 #include "SgBoardColor.h" 00016 #include "GoModBoard.h" 00017 #include "SgPoint.h" 00018 #include "SgPointSet.h" 00019 #include "SgVector.h" 00020 00021 //---------------------------------------------------------------------------- 00022 00023 enum GoLadderStatus 00024 { 00025 /** Don't know anything about the status of this block. */ 00026 GO_LADDER_UNKNOWN, 00027 00028 /** Definitely captured, regardless of who plays first. */ 00029 GO_LADDER_CAPTURED, 00030 00031 /** Capture or escape depends on who plays first. */ 00032 GO_LADDER_UNSETTLED, 00033 00034 /** Definitely escaped, regardless of who plays first. */ 00035 GO_LADDER_ESCAPED 00036 }; 00037 00038 //---------------------------------------------------------------------------- 00039 00040 /** This class contains all the ladder-specific stuff. */ 00041 class GoLadder 00042 { 00043 public: 00044 GoLadder(); 00045 00046 /** Main ladder routine. 00047 twoLibIsEscape: if prey is to play and has two libs, does it count as 00048 an immediate escape, or shall we keep trying to capture? 00049 @return Positive value if ladder is good for prey, negative, if good 00050 for hunter. 00051 */ 00052 int Ladder(const GoBoard& bd, SgPoint prey, SgBlackWhite toPlay, 00053 SgVector<SgPoint>* sequence, bool twoLibIsEscape = false); 00054 00055 private: 00056 /** Maximum number of moves in ladder. 00057 If board has simple ko rule, ladders could not terminate. 00058 */ 00059 static const int MAX_LADDER_MOVES = 200; 00060 00061 /** Maximum move number before ladder should be aborted. */ 00062 int m_maxMoveNumber; 00063 00064 GoBoard* m_bd; 00065 00066 SgPointSet m_partOfPrey; 00067 00068 SgBlackWhite m_preyColor; 00069 00070 SgBlackWhite m_hunterColor; 00071 00072 bool CheckMoveOverflow() const; 00073 00074 void InitMaxMoveNumber(); 00075 00076 bool PointIsAdjToPrey(SgPoint p); 00077 00078 bool BlockIsAdjToPrey(SgPoint p, int numAdj); 00079 00080 void MarkStonesAsPrey(SgPoint p, SgVector<SgPoint>* stones = 0); 00081 00082 void FilterAdjacent(GoPointList& adjBlocks); 00083 00084 int PlayHunterMove(int depth, SgPoint move, SgPoint lib1, SgPoint lib2, 00085 const GoPointList& adjBlk, 00086 SgVector<SgPoint>* sequence); 00087 00088 int PlayPreyMove(int depth, SgPoint move, SgPoint lib1, 00089 const GoPointList& adjBlk, SgVector<SgPoint>* sequence); 00090 00091 bool IsSnapback(SgPoint prey); 00092 00093 int PreyLadder(int depth, SgPoint lib1, const GoPointList& adjBlk, 00094 SgVector<SgPoint>* sequence); 00095 00096 int HunterLadder(int depth, SgPoint lib1, const GoPointList& adjBlk, 00097 SgVector<SgPoint>* sequence); 00098 00099 int HunterLadder(int depth, SgPoint lib1, SgPoint lib2, 00100 const GoPointList& adjBlk, SgVector<SgPoint>* sequence); 00101 00102 void ReduceToBlocks(GoPointList& stones); 00103 }; 00104 00105 //---------------------------------------------------------------------------- 00106 00107 namespace GoLadderUtil { 00108 00109 /** Return whether or not the block at 'prey' can be captured in a ladder when 00110 'toPlay' plays first. 00111 True means capture, false means escape. If 'sequence' is not 0, return a 00112 sequence of moves to capture or escape (need not be the optimal sequence). 00113 Return an empty sequence if the prey is already captured or has escaped, 00114 without needing to play a move. 00115 If the prey can be temporarily removed from the board but can capture 00116 back immediately (snapback), return that the prey cannot be captured. 00117 */ 00118 bool Ladder(const GoBoard& board, SgPoint prey, SgBlackWhite toPlay, 00119 bool fTwoLibIsEscape = false, SgVector<SgPoint>* sequence = 0); 00120 00121 /** Return whether the block at 'prey' is captured, escaped, or unsettled 00122 with regards to capture in a ladder. 00123 If it is unsettled, set '*toCapture' and '*toEscape' (if not 0) to the 00124 capturing/escaping move to play. 00125 Otherwise, leave '*toCapture' and '*toEscape' unchanged. The point at 00126 'prey' must be occupied. 00127 */ 00128 GoLadderStatus LadderStatus(const GoBoard& bd, SgPoint prey, 00129 bool fTwoLibIsEscape = false, 00130 SgPoint* toCapture = 0, SgPoint* toEscape = 0); 00131 00132 /** Check if this is a chain connection point, or a ko cut point. 00133 Try to play there as opponent, then check: 00134 - Suicide 00135 - self removal, self atari 00136 - can be captured by ladder? 00137 - is it a Ko? 00138 */ 00139 bool IsProtectedLiberty(const GoBoard& bd, SgPoint liberty, SgBlackWhite col, 00140 bool& byLadder, bool& isKoCut, bool tryLadder = true); 00141 00142 /** Simple form, calls the complex form and ignores bool results */ 00143 bool IsProtectedLiberty(const GoBoard& bd, SgPoint liberty, SgBlackWhite col); 00144 00145 SgPoint TryLadder(const GoBoard& bd, SgPoint prey, SgBlackWhite firstPlayer); 00146 00147 } // namespace GoLadderUtil 00148 00149 //---------------------------------------------------------------------------- 00150 00151 #endif // GO_LADDER_H 00152