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