An implementation of the Universal Chess Interface in Rust.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
5.2 KiB

//! 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<EngineOptionDataType, EngineOptionData>,
}
impl EngineOption {
/// Constructs a new EngineOption of type T
pub fn new(name: &'static str, option_type: EngineOptionType,
option_data: HashMap<EngineOptionDataType, EngineOptionData>) -> 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)
}
}