//! Options contains everything related to engine options. The idea behind this is to take as much //! advantage of the typechecker as possible. As a result, engine option names are constant static strings, //! and EngineOption tries to be flexible so it can be reused for each option, which also maintaining some //! of the nicer parts of typechecking. use std::collections::HashMap; use commands; /// These constants can be used for naming options easily. Option name is fairly flexible. pub mod constants { /// Represents the hash option pub const HASH: &'static str = "Hash"; /// Represents the Nalimov Path option pub const NALIMOVPATH: &'static str = "NalimovPath"; /// Represents the Nalimov Cache option pub const NALIMOVCACHE: &'static str = "NalimovCache"; /// Represents the ponder option pub const PONDER: &'static str = "Ponder"; /// Represents the OwnBook option pub const OWNBOOK: &'static str = "OwnBook"; /// Represents the MultiPV option pub const MULTIPV: &'static str = "MultiPV"; /// Represents the UCI_ShowCurrLine option pub const UCISHOWCURRLINE: &'static str = "UCI_ShowCurrLine"; /// Represents the UCI_Refutations option pub const UCISHOWREFUTATIONS: &'static str = "UCI_ShowRefutations"; /// Represents the UCI_LimitStrength option pub const UCILIMITSTRENGTH: &'static str = "UCI_LimitStrength"; /// Represents the UCI_Elo option pub const UCIELO: &'static str = "UCI_Elo"; /// Represents the UCI_AnalysisMode option pub const UCIANALYSISMODE: &'static str = "UCI_AnalysisMode"; /// Represents the UCI_Opponent option pub const UCIOPPONENT: &'static str = "UCI_Opponent"; } /// The `EngineOptionType` type used to indicate what type of option the GUI should display #[derive(Copy, Clone, Debug, PartialEq)] pub enum EngineOptionType { Check, Spin, Combo, Button, TypeString, // `String` is a reserved word so `TypeString` is substituted } #[derive(Clone, Debug, PartialEq, PartialOrd)] /// The `EngineOptionData` makes the data type generic so one `EngineOption` can represent everything /// This would be set to the type of the engine option (ex. i32) pub enum EngineOptionData { Int(i32), Float(f64), Text(String), } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] /// The `EngineOptionDataType` type used to indicate the type of the `EngineOption` setting pub enum EngineOptionDataType { DefaultVal, // `Default` is reserved so `DefaultVal` is used Min, Max, Var, } #[derive(Debug, PartialEq)] /// The `EngineOption` type is the overarching type representing a single configurable engine option pub struct EngineOption { pub name: &'static str, pub option_type: EngineOptionType, pub option_data: HashMap, } impl EngineOption { /// Constructs a new EngineOption of type T pub fn new(name: &'static str, option_type: EngineOptionType, option_data: HashMap) -> EngineOption { EngineOption { name, option_type, option_data, } } fn engine_option_data_string(d: &EngineOptionData) -> String { match d { &EngineOptionData::Int(v) => v.to_string(), &EngineOptionData::Float(v) => v.to_string(), &EngineOptionData::Text(ref v) => v.clone(), } } /// Turns the EngineOption into a string that can be sent to the GUI pub fn to_string(&self) -> String { let mut option_data_string: String = String::new(); // NOTE: The user is left to understand what option takes which of these data type values. There's some // work that can be done later switching based on the option type, but for now it's reasonable to // expect the user understands the standard well enough to know which options take what kind // of settings. if self.option_data.contains_key(&EngineOptionDataType::DefaultVal) { let data = self.option_data.get(&EngineOptionDataType::DefaultVal); option_data_string.push_str(&format!(" {} {}", "default", EngineOption::engine_option_data_string(&data.unwrap()))); } if self.option_data.contains_key(&EngineOptionDataType::Min) { let data = self.option_data.get(&EngineOptionDataType::Min); option_data_string.push_str(&format!(" {} {}", "min", EngineOption::engine_option_data_string(&data.unwrap()))); } if self.option_data.contains_key(&EngineOptionDataType::Max) { let data = self.option_data.get(&EngineOptionDataType::Max); option_data_string.push_str(&format!(" {} {}", "max", EngineOption::engine_option_data_string(&data.unwrap()))); } if self.option_data.contains_key(&EngineOptionDataType::Var) { let data = self.option_data.get(&EngineOptionDataType::Var); option_data_string.push_str(&format!(" {} {}", "var", EngineOption::engine_option_data_string(&data.unwrap()))); } let ots = match self.option_type { EngineOptionType::Check => "check", EngineOptionType::Spin => "spin", EngineOptionType::Combo => "combo", EngineOptionType::Button => "button", EngineOptionType::TypeString => "string", }; format!("{} {} {} {} {}{}\n", commands::OPTION, commands::OPTIONNAME, self.name, commands::TYPE, ots, option_data_string) } }