github.com/frankkopp/FrankyGo@v1.0.3/internal/uci/ucioption.go (about) 1 // 2 // FrankyGo - UCI chess engine in GO for learning purposes 3 // 4 // MIT License 5 // 6 // Copyright (c) 2018-2020 Frank Kopp 7 // 8 // Permission is hereby granted, free of charge, to any person obtaining a copy 9 // of this software and associated documentation files (the "Software"), to deal 10 // in the Software without restriction, including without limitation the rights 11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 // copies of the Software, and to permit persons to whom the Software is 13 // furnished to do so, subject to the following conditions: 14 // 15 // The above copyright notice and this permission notice shall be included in all 16 // copies or substantial portions of the Software. 17 // 18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 // SOFTWARE. 25 // 26 27 package uci 28 29 import ( 30 "fmt" 31 "reflect" 32 "strconv" 33 "strings" 34 35 . "github.com/frankkopp/FrankyGo/internal/config" 36 ) 37 38 // init will define all available uci options and store them into the uciOption map 39 func init() { 40 uciOptions = map[string]*uciOption{ 41 "Print Config": {NameID: "Print Config", HandlerFunc: printConfig, OptionType: Button}, 42 "Clear Hash": {NameID: "Clear Hash", HandlerFunc: clearCache, OptionType: Button}, 43 "Use_Hash": {NameID: "Use_Hash", HandlerFunc: useCache, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseTT), CurrentValue: strconv.FormatBool(Settings.Search.UseTT)}, 44 "Hash": {NameID: "Hash", HandlerFunc: cacheSize, OptionType: Spin, DefaultValue: strconv.Itoa(Settings.Search.TTSize), CurrentValue: strconv.Itoa(Settings.Search.TTSize), MinValue: "0", MaxValue: "65000"}, 45 46 "Use_Book": {NameID: "Use_Book", HandlerFunc: useBook, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseBook), CurrentValue: strconv.FormatBool(Settings.Search.UseBook)}, 47 48 "Ponder": {NameID: "Ponder", HandlerFunc: usePonder, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UsePonder), CurrentValue: strconv.FormatBool(Settings.Search.UsePonder)}, 49 50 "Quiescence": {NameID: "Quiescence", HandlerFunc: useQuiescence, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseQuiescence), CurrentValue: strconv.FormatBool(Settings.Search.UseQuiescence)}, 51 "Use_QHash": {NameID: "Use_QHash", HandlerFunc: useQSHash, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseQSTT), CurrentValue: strconv.FormatBool(Settings.Search.UseQSTT)}, 52 "Use_SEE": {NameID: "Use_SEE", HandlerFunc: useSee, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseSEE), CurrentValue: strconv.FormatBool(Settings.Search.UseSEE)}, 53 "Use_PromNonQuiet": {NameID: "Use_PromNonQuiet", HandlerFunc: usePromNonQuiet, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UsePromNonQuiet), CurrentValue: strconv.FormatBool(Settings.Search.UsePromNonQuiet)}, 54 55 "Use_PVS": {NameID: "Use_PVS", HandlerFunc: usePvs, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UsePVS), CurrentValue: strconv.FormatBool(Settings.Search.UsePVS)}, 56 "Use_ASP": {NameID: "Use_ASP", HandlerFunc: useAsp, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseAspiration), CurrentValue: strconv.FormatBool(Settings.Search.UseAspiration)}, 57 "Use_MTDf": {NameID: "Use_MTDf", HandlerFunc: useMtdf, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseMTDf), CurrentValue: strconv.FormatBool(Settings.Search.UseMTDf)}, 58 59 "Use_IID": {NameID: "Use_IID", HandlerFunc: useIID, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseIID), CurrentValue: strconv.FormatBool(Settings.Search.UseIID)}, 60 "Use_Killer": {NameID: "Use_Killer", HandlerFunc: useKiller, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseKiller), CurrentValue: strconv.FormatBool(Settings.Search.UseKiller)}, 61 "Use_HistCount": {NameID: "Use_HistCount", HandlerFunc: useHC, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseHistoryCounter), CurrentValue: strconv.FormatBool(Settings.Search.UseHistoryCounter)}, 62 "Use_CounterMove": {NameID: "Use_CounterMove", HandlerFunc: useCM, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseCounterMoves), CurrentValue: strconv.FormatBool(Settings.Search.UseCounterMoves)}, 63 64 "Use_Rfp": {NameID: "Use_Rfp", HandlerFunc: useRfp, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseRFP), CurrentValue: strconv.FormatBool(Settings.Search.UseRFP)}, 65 "Use_NullMove": {NameID: "Use_NullMove", HandlerFunc: useNullMove, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseNullMove), CurrentValue: strconv.FormatBool(Settings.Search.UseNullMove)}, 66 "Use_Mdp": {NameID: "Use_Mdp", HandlerFunc: useMdp, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseMDP), CurrentValue: strconv.FormatBool(Settings.Search.UseMDP)}, 67 "Use_Fp": {NameID: "Use_Fp", HandlerFunc: useFp, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseFP), CurrentValue: strconv.FormatBool(Settings.Search.UseFP)}, 68 "Use_Lmr": {NameID: "Use_Lmr", HandlerFunc: useLmr, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseLmr), CurrentValue: strconv.FormatBool(Settings.Search.UseLmr)}, 69 "Use_Lmp": {NameID: "Use_Lmp", HandlerFunc: useLmp, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseLmp), CurrentValue: strconv.FormatBool(Settings.Search.UseLmp)}, 70 71 "Use_Ext": {NameID: "Use_Ext", HandlerFunc: useExt, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseExt), CurrentValue: strconv.FormatBool(Settings.Search.UseExt)}, 72 "Use_ExtAddDepth": {NameID: "Use_ExtAddDepth", HandlerFunc: useExtAddDepth, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseExtAddDepth), CurrentValue: strconv.FormatBool(Settings.Search.UseExtAddDepth)}, 73 "Use_CheckExt": {NameID: "Use_CheckExt", HandlerFunc: useCheckExt, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseCheckExt), CurrentValue: strconv.FormatBool(Settings.Search.UseCheckExt)}, 74 "Use_ThreatExt": {NameID: "Use_ThreatExt", HandlerFunc: useThreatExt, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Search.UseThreatExt), CurrentValue: strconv.FormatBool(Settings.Search.UseThreatExt)}, 75 76 "Eval_Lazy": {NameID: "Eval_Lazy", HandlerFunc: evalLazy, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Eval.UseLazyEval), CurrentValue: strconv.FormatBool(Settings.Eval.UseLazyEval)}, 77 "Eval_Mobility": {NameID: "Eval_Mobility", HandlerFunc: evalMob, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Eval.UseMobility), CurrentValue: strconv.FormatBool(Settings.Eval.UseMobility)}, 78 "Eval_AdvPiece": {NameID: "Eval_AdvPiece", HandlerFunc: evalAdv, OptionType: Check, DefaultValue: strconv.FormatBool(Settings.Eval.UseAdvancedPieceEval), CurrentValue: strconv.FormatBool(Settings.Eval.UseAdvancedPieceEval)}, 79 } 80 81 // as Go does not let us sort maps manually (e.g. insertion order) we need a 82 // list to control order of the entries 83 sortOrderUciOptions = []string{ 84 "Print Config", 85 "Clear Hash", 86 "Use_Hash", 87 "Hash", 88 "Use_Book", 89 "Ponder", 90 91 "Quiescence", 92 "Use_QHash", 93 "Use_SEE", 94 "Use_PromNonQuiet", 95 96 "Use_PVS", 97 "Use_ASP", 98 99 "Use_IID", 100 "Use_Killer", 101 "Use_HistCount", 102 "Use_CounterMove", 103 104 "Use_Mdp", 105 "Use_Rfp", 106 "Use_NullMove", 107 "Use_Fp", 108 "Use_Lmr", 109 "Use_Lmp", 110 111 "Use_Ext", 112 "Use_ExtAddDepth", 113 "Use_CheckExt", 114 "Use_ThreatExt", 115 116 "Eval_Mobility", 117 "Eval_AdvPiece", 118 } 119 } 120 121 // GetOptions returns all available uci options as a slice of strings 122 // to be send to the UCI user interface during the initialization 123 // phase of the UCI protocol 124 func (o *optionMap) GetOptions() *[]string { 125 var options []string 126 for _, opt := range sortOrderUciOptions { 127 options = append(options, uciOptions[opt].String()) 128 } 129 return &options 130 } 131 132 // String for uciOption will return a representation of the uci option as required by 133 // the UCI protocol during the initialization phase of the UCI protocol 134 func (o *uciOption) String() string { 135 var os strings.Builder 136 os.WriteString("option name ") 137 os.WriteString(o.NameID) 138 os.WriteString(" type ") 139 switch o.OptionType { 140 case Check: 141 os.WriteString("check ") 142 os.WriteString("default ") 143 os.WriteString(o.DefaultValue) 144 case Spin: 145 os.WriteString("spin ") 146 os.WriteString("default ") 147 os.WriteString(o.DefaultValue) 148 os.WriteString(" min ") 149 os.WriteString(o.MinValue) 150 os.WriteString(" max ") 151 os.WriteString(o.MaxValue) 152 case Combo: 153 os.WriteString("combo ") 154 os.WriteString("default ") 155 os.WriteString(o.DefaultValue) 156 os.WriteString(" var ") 157 os.WriteString(o.VarValue) 158 case Button: 159 os.WriteString("button") 160 case String: 161 os.WriteString("string ") 162 os.WriteString("default ") 163 os.WriteString(o.DefaultValue) 164 } 165 166 return os.String() 167 } 168 169 // uciOptionType is a enum representing the different UCI Option types 170 type uciOptionType int 171 172 // uci option types constants 173 const ( 174 Check uciOptionType = 0 175 Spin uciOptionType = 1 176 Combo uciOptionType = 2 177 Button uciOptionType = 3 178 String uciOptionType = 4 179 ) 180 181 // optionHandler is a function type to by used as function pointer 182 // in each uci option defined. This is called when the uci option 183 // is changed by the "setoption" command 184 type optionHandler func(*UciHandler, *uciOption) 185 186 // uciOption defines UCI Options as described in the UCI protocol. 187 // Each options has a function pointer to a handler which will be 188 // called when the "setoption" command changes the option. 189 type uciOption struct { 190 NameID string 191 HandlerFunc optionHandler 192 OptionType uciOptionType 193 DefaultValue string 194 MinValue string 195 MaxValue string 196 VarValue string 197 CurrentValue string 198 } 199 200 // optionMap convenience type for a map of pointers to uci options 201 type optionMap map[string]*uciOption 202 203 // uciOptions stores all available uci options 204 var uciOptions optionMap 205 206 // to control the sort order of all options 207 var sortOrderUciOptions []string 208 209 // //////////////////////////////////////////////////////////////// 210 // HandlerFunc for uci options changes 211 // //////////////////////////////////////////////////////////////// 212 213 func printConfig(handler *UciHandler, option *uciOption) { 214 s := reflect.ValueOf(&Settings.Eval).Elem() 215 typeOfT := s.Type() 216 for i := s.NumField() - 1; i >= 0; i-- { 217 f := s.Field(i) 218 handler.SendInfoString(fmt.Sprintf("%-2d: %-22s %-6s = %v\n", i, typeOfT.Field(i).Name, f.Type(), f.Interface())) 219 } 220 handler.SendInfoString("Evaluation Config:\n") 221 s = reflect.ValueOf(&Settings.Search).Elem() 222 typeOfT = s.Type() 223 for i := s.NumField() - 1; i >= 0; i-- { 224 f := s.Field(i) 225 handler.SendInfoString(fmt.Sprintf("%-2d: %-22s %-6s = %v\n", i, typeOfT.Field(i).Name, f.Type(), f.Interface())) 226 } 227 handler.SendInfoString("Search Config:\n") 228 log.Debug(Settings.String()) 229 230 } 231 232 func clearCache(u *UciHandler, o *uciOption) { 233 u.mySearch.ClearHash() 234 log.Debug("Cleared Cache") 235 } 236 237 func useCache(u *UciHandler, o *uciOption) { 238 v, _ := strconv.ParseBool(o.CurrentValue) 239 Settings.Search.UseTT = v 240 log.Debugf("Set Use Hash to %v", Settings.Search.UseTT) 241 } 242 243 func cacheSize(u *UciHandler, o *uciOption) { 244 v, _ := strconv.Atoi(o.CurrentValue) 245 Settings.Search.TTSize = v 246 u.mySearch.ResizeCache() 247 } 248 249 func useBook(u *UciHandler, o *uciOption) { 250 v, _ := strconv.ParseBool(o.CurrentValue) 251 Settings.Search.UseBook = v 252 log.Debugf("Set Use Book to %v", Settings.Search.UseBook) 253 } 254 255 func usePonder(u *UciHandler, o *uciOption) { 256 v, _ := strconv.ParseBool(o.CurrentValue) 257 Settings.Search.UsePonder = v 258 log.Debugf("Set Use Ponder to %v", Settings.Search.UsePonder) 259 } 260 261 func useQuiescence(u *UciHandler, o *uciOption) { 262 v, _ := strconv.ParseBool(o.CurrentValue) 263 Settings.Search.UseQuiescence = v 264 log.Debugf("Set Use Quiescence to %v", Settings.Search.UseQuiescence) 265 } 266 267 func useQSHash(u *UciHandler, o *uciOption) { 268 v, _ := strconv.ParseBool(o.CurrentValue) 269 Settings.Search.UseQSTT = v 270 log.Debugf("Set Use Hash in Quiescence to %v", Settings.Search.UseQSTT) 271 } 272 273 func usePvs(u *UciHandler, o *uciOption) { 274 v, _ := strconv.ParseBool(o.CurrentValue) 275 Settings.Search.UsePVS = v 276 log.Debugf("Set Use Principal Variation Search to %v", Settings.Search.UsePVS) 277 } 278 279 func useAsp(u *UciHandler, o *uciOption) { 280 v, _ := strconv.ParseBool(o.CurrentValue) 281 Settings.Search.UseAspiration = v 282 log.Debugf("Set Use Aspiration Search to %v", Settings.Search.UseAspiration) 283 } 284 285 func useMtdf(u *UciHandler, o *uciOption) { 286 v, _ := strconv.ParseBool(o.CurrentValue) 287 Settings.Search.UseMTDf = v 288 log.Debugf("Set Use MDTf Search to %v", Settings.Search.UseMTDf) 289 } 290 291 func useMdp(u *UciHandler, o *uciOption) { 292 v, _ := strconv.ParseBool(o.CurrentValue) 293 Settings.Search.UseMDP = v 294 log.Debugf("Set Use MDP to %v", Settings.Search.UseMDP) 295 } 296 297 func useKiller(u *UciHandler, o *uciOption) { 298 v, _ := strconv.ParseBool(o.CurrentValue) 299 Settings.Search.UseKiller = v 300 log.Debugf("Set Use Killer Moves to %v", Settings.Search.UseKiller) 301 } 302 303 func useHC(u *UciHandler, o *uciOption) { 304 v, _ := strconv.ParseBool(o.CurrentValue) 305 Settings.Search.UseHistoryCounter = v 306 log.Debugf("Set Use History Counter to %v", Settings.Search.UseHistoryCounter) 307 } 308 309 func useCM(u *UciHandler, o *uciOption) { 310 v, _ := strconv.ParseBool(o.CurrentValue) 311 Settings.Search.UseCounterMoves = v 312 log.Debugf("Set Use Counter Moves to %v", Settings.Search.UseCounterMoves) 313 } 314 315 func useNullMove(u *UciHandler, o *uciOption) { 316 v, _ := strconv.ParseBool(o.CurrentValue) 317 Settings.Search.UseNullMove = v 318 log.Debugf("Set Use Null Move Pruning to %v", Settings.Search.UseNullMove) 319 } 320 321 func useIID(u *UciHandler, o *uciOption) { 322 v, _ := strconv.ParseBool(o.CurrentValue) 323 Settings.Search.UseIID = v 324 log.Debugf("Set Use IID to %v", Settings.Search.UseIID) 325 } 326 327 func useLmr(u *UciHandler, o *uciOption) { 328 v, _ := strconv.ParseBool(o.CurrentValue) 329 Settings.Search.UseLmr = v 330 log.Debugf("Set use Late Move Reduction to %v", Settings.Search.UseLmr) 331 } 332 333 func useLmp(u *UciHandler, o *uciOption) { 334 v, _ := strconv.ParseBool(o.CurrentValue) 335 Settings.Search.UseLmp = v 336 log.Debugf("Set use Late Move Pruning to %v", Settings.Search.UseLmp) 337 } 338 339 func useSee(u *UciHandler, o *uciOption) { 340 v, _ := strconv.ParseBool(o.CurrentValue) 341 Settings.Search.UseSEE = v 342 log.Debugf("Set use SEE to %v", Settings.Search.UseSEE) 343 } 344 345 func usePromNonQuiet(u *UciHandler, o *uciOption) { 346 v, _ := strconv.ParseBool(o.CurrentValue) 347 Settings.Search.UsePromNonQuiet = v 348 log.Debugf("Set use Promotion as Non-quiet to %v", Settings.Search.UsePromNonQuiet) 349 } 350 351 func useExt(u *UciHandler, o *uciOption) { 352 v, _ := strconv.ParseBool(o.CurrentValue) 353 Settings.Search.UseExt = v 354 log.Debugf("Set use Extensions to %v", Settings.Search.UseExt) 355 } 356 357 func useExtAddDepth(u *UciHandler, o *uciOption) { 358 v, _ := strconv.ParseBool(o.CurrentValue) 359 Settings.Search.UseExtAddDepth = v 360 log.Debugf("Set use Extensions Add to Depth to %v", Settings.Search.UseExtAddDepth) 361 } 362 363 func useCheckExt(u *UciHandler, o *uciOption) { 364 v, _ := strconv.ParseBool(o.CurrentValue) 365 Settings.Search.UseCheckExt = v 366 log.Debugf("Set use Check Extension to %v", Settings.Search.UseCheckExt) 367 } 368 369 func useThreatExt(u *UciHandler, o *uciOption) { 370 v, _ := strconv.ParseBool(o.CurrentValue) 371 Settings.Search.UseThreatExt = v 372 log.Debugf("Set use Threat Extension to %v", Settings.Search.UseThreatExt) 373 } 374 375 func useRfp(u *UciHandler, o *uciOption) { 376 v, _ := strconv.ParseBool(o.CurrentValue) 377 Settings.Search.UseRFP = v 378 log.Debugf("Set use Reverse Futility Pruning (RFP) to %v", Settings.Search.UseRFP) 379 } 380 381 func useFp(u *UciHandler, o *uciOption) { 382 v, _ := strconv.ParseBool(o.CurrentValue) 383 Settings.Search.UseFP = v 384 log.Debugf("Set use Futility Pruning (FP) to %v", Settings.Search.UseFP) 385 } 386 387 func evalLazy(u *UciHandler, o *uciOption) { 388 v, _ := strconv.ParseBool(o.CurrentValue) 389 Settings.Eval.UseLazyEval = v 390 log.Debugf("Set use Lazy Eval to %v", Settings.Eval.UseLazyEval) 391 } 392 393 func evalMob(u *UciHandler, o *uciOption) { 394 v, _ := strconv.ParseBool(o.CurrentValue) 395 Settings.Eval.UseMobility = v 396 log.Debugf("Set use Eval Mobility to %v", Settings.Eval.UseMobility) 397 } 398 399 func evalAdv(u *UciHandler, o *uciOption) { 400 v, _ := strconv.ParseBool(o.CurrentValue) 401 Settings.Eval.UseAdvancedPieceEval = v 402 log.Debugf("Set use Adv Piece Eval to %v", Settings.Eval.UseAdvancedPieceEval) 403 }