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