00001 //---------------------------------------------------------------------------- 00002 /** @file SgSearchValue.h 00003 Scalar values used in search tasks derived from class SgSearch. */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef SG_SEARCHVALUE_H 00007 #define SG_SEARCHVALUE_H 00008 00009 #include <cstdlib> 00010 #include <string> 00011 #include "SgBlackWhite.h" 00012 #include "SgSearch.h" 00013 00014 //---------------------------------------------------------------------------- 00015 00016 /** Value used in search tasks derived from class SgSearch. 00017 There's a range of values that indicate that the problem has been 00018 solved (at a certain depth), a range of values for solutions that involve 00019 ko, and a range of values for problems that have not been solved yet. 00020 Value is always stored with positive values being good for black, negative 00021 values being good for white. 00022 <pre> 00023 int v = Board().ToPlay() == SG_WHITE ? -value : +value; 00024 </pre> */ 00025 class SgSearchValue 00026 { 00027 public: 00028 enum { 00029 00030 MAX_LEVEL = 125, 00031 00032 /** The best possible search result - highest possible value. 00033 A win in n ply is encoded with a value of MAX_VALUE - n. 00034 A loss is encoded as -value if the win would be encoded as value. 00035 MAX_VALUE==32000. */ 00036 MAX_VALUE = MAX_LEVEL * SgSearch::MAX_DEPTH, 00037 00038 /** The worst possible search result. 00039 All search results are in the range [MIN_VALUE..MAX_VALUE]. */ 00040 MIN_VALUE = -MAX_VALUE, 00041 00042 /** The maximum number of Ko recaptures allowed in a search. */ 00043 MAX_KO_LEVEL = 3, 00044 00045 /** KO_VALUE is the result for win by ko. 00046 Similarly with MAX_VALUE, a win by Ko in n ply is encoded as 00047 KO_VALUE - n. 00048 KO_VALUE==32000 - 256 = 31744. */ 00049 KO_VALUE = MAX_VALUE - SgSearch::MAX_DEPTH, 00050 00051 /** MIN_PROVEN_VALUE is the lowest score that indicates a proven win. 00052 1. values in the range [MIN_VALUE..-MIN_PROVEN_VALUE] are 00053 proven losses (possibly by ko). 00054 2. values in the range [-MIN_PROVEN_VALUE+1..MIN_PROVEN_VALUE-1] 00055 are heuristic scores. 00056 3. values in range [MIN_PROVEN_VALUE..MAX_VALUE] 00057 are proven wins (possibly by ko). */ 00058 MIN_PROVEN_VALUE = MAX_VALUE 00059 - (MAX_KO_LEVEL + 1) * SgSearch::MAX_DEPTH 00060 }; 00061 00062 SgSearchValue(); 00063 00064 explicit SgSearchValue(int v); 00065 00066 SgSearchValue(SgBlackWhite goodForPlayer, int depth); 00067 00068 SgSearchValue(SgBlackWhite goodForPlayer, int depth, int koLevel); 00069 00070 /** Return current value as an integer. */ 00071 operator int() const; 00072 00073 int Depth() const; 00074 00075 /** Convert 'string' to a value and set this value. 00076 Return true if the string could be converted to a valid value, 00077 otherwise false. */ 00078 bool FromString(const std::string& s); 00079 00080 bool IsEstimate() const; 00081 00082 bool IsKoValue() const; 00083 00084 bool IsPositive() const; 00085 00086 /** is value == +MAX_VALUE or -MAX_VALUE? */ 00087 static inline bool IsSolved(int value); 00088 00089 bool IsSureValue() const; 00090 00091 int KoLevel() const; 00092 00093 void SetValueForPlayer(SgBlackWhite player); 00094 00095 int ValueForBlack() const; 00096 00097 int ValueForPlayer(SgBlackWhite player) const; 00098 00099 int ValueForWhite() const; 00100 00101 /** Set '*s' to the string for this value, e.g. "B+3.5", "W+20", 00102 or "W+(ko)[12]". The value is divided by 'unitPerPoint' to determine 00103 the number of points. */ 00104 std::string ToString(int unitPerPoint = 1) const; 00105 00106 private: 00107 int m_value; 00108 }; 00109 00110 inline SgSearchValue::SgSearchValue() 00111 : m_value(0) 00112 { } 00113 00114 inline SgSearchValue::SgSearchValue(int v) 00115 : m_value(v) 00116 { 00117 SG_ASSERT(-MAX_VALUE <= v && v <= MAX_VALUE); 00118 } 00119 00120 inline SgSearchValue::SgSearchValue(SgBlackWhite goodForPlayer, int depth) 00121 : m_value(MAX_VALUE - depth) 00122 { 00123 SG_ASSERT_BW(goodForPlayer); 00124 SG_ASSERT(0 <= depth && depth < SgSearch::MAX_DEPTH); 00125 SetValueForPlayer(goodForPlayer); 00126 // Make sure value gets encoded/decoded consistently. 00127 SG_ASSERT(KoLevel() == 0); 00128 SG_ASSERT(Depth() == depth); 00129 } 00130 00131 inline SgSearchValue::SgSearchValue(SgBlackWhite goodForPlayer, int depth, int koLevel) 00132 : m_value(MAX_VALUE - depth - koLevel * SgSearch::MAX_DEPTH) 00133 { 00134 SG_ASSERT_BW(goodForPlayer); 00135 SG_ASSERT(0 <= depth && depth < SgSearch::MAX_DEPTH); 00136 SG_ASSERT(0 <= koLevel && koLevel <= MAX_KO_LEVEL); 00137 SetValueForPlayer(goodForPlayer); 00138 // Make sure value gets encoded/decoded consistently. 00139 SG_ASSERT(KoLevel() == koLevel); 00140 SG_ASSERT(Depth() == depth); 00141 } 00142 00143 inline SgSearchValue::operator int() const 00144 { 00145 return m_value; 00146 } 00147 00148 inline int SgSearchValue::Depth() const 00149 { 00150 if (IsEstimate()) 00151 return 0; 00152 else return (SgSearch::MAX_DEPTH - 1) 00153 - (std::abs(m_value) - 1) % SgSearch::MAX_DEPTH; 00154 } 00155 00156 inline bool SgSearchValue::IsEstimate() const 00157 { 00158 return -MIN_PROVEN_VALUE < m_value && m_value < MIN_PROVEN_VALUE; 00159 } 00160 00161 inline bool SgSearchValue::IsKoValue() const 00162 { 00163 return IsSureValue() && -KO_VALUE < m_value && m_value < KO_VALUE; 00164 } 00165 00166 inline bool SgSearchValue::IsPositive() const 00167 { 00168 return 0 <= m_value; 00169 } 00170 00171 inline bool SgSearchValue::IsSureValue() const 00172 { 00173 return m_value <= -MIN_PROVEN_VALUE || MIN_PROVEN_VALUE <= m_value; 00174 } 00175 00176 inline bool SgSearchValue::IsSolved(int value) 00177 { 00178 return abs(value) == MAX_VALUE; 00179 } 00180 00181 inline void SgSearchValue::SetValueForPlayer(SgBlackWhite player) 00182 { 00183 if (player == SG_WHITE) 00184 m_value = -m_value; 00185 } 00186 00187 inline int SgSearchValue::ValueForBlack() const 00188 { 00189 return +m_value; 00190 } 00191 00192 inline int SgSearchValue::ValueForPlayer(SgBlackWhite player) const 00193 { 00194 SG_ASSERT_BW(player); 00195 return player == SG_WHITE ? -m_value : +m_value; 00196 } 00197 00198 inline int SgSearchValue::ValueForWhite() const 00199 { 00200 return -m_value; 00201 } 00202 00203 //---------------------------------------------------------------------------- 00204 00205 #endif // SG_SEARCHVALUE_H