From be2ca9fc75513e2329126d2b2bafc9e1c6575e38 Mon Sep 17 00:00:00 2001 From: Taylor Bockman Date: Thu, 14 Dec 2017 16:19:48 -0800 Subject: [PATCH] Nearly there --- src/lib.rs | 15 ++++++--- src/options.rs | 99 ++++++++++++++++++++++++++++++++-------------------------- tests/lib.rs | 24 ++++++++++++-- 3 files changed, 86 insertions(+), 52 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5d06957..8ba9e47 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,13 @@ //! The engine is fully generic. By specifying a valid reader and writing you can send the messages to STDIN //! and STDOUT, per the standard - or to memory for testing. -mod commands; + +// BIG TODO: Change pub struct members to private and use getters/setters. DO THIS FOR EVERYTHING AFTER YOU +// IMPLEMENT OPTION SENDING. +// ALSO CHANGE COMMANDS TO HAVE A CONSTANTS SUBMODULE LIKE OPTIONS + +pub mod commands; +pub mod options; use std::io::{BufRead, Write}; use std::vec; @@ -13,7 +19,7 @@ pub struct Engine<'a, R, W> { pub author: &'a str, pub reader: R, pub writer: W, - pub engine_options: Vec, + pub engine_options: Vec, } /// Notes to delete later: @@ -32,7 +38,8 @@ pub struct Engine<'a, R, W> { /// worry about calling "boot up" prior to their main engine loop. /// /// -/// TODO: THE NEXT THING - THE PARSER! +/// TODO: THE NEXT THING - THE PARSER! (after putting in getters but _no_ setters and taking away pub fields +/// for all structs in the app if that is idiomatic) /// /// Additionally this code should have a parser. You call it with the reader supplied and it waits for a command /// and parses it into a tuple of . For example it would parse `setoption` into an option constant @@ -45,7 +52,7 @@ where W: Write, { pub fn new(name: &'a str, author: &'a str, - reader: R, writer: W, engine_options: Vec) -> Engine<'a, R, W> { + reader: R, writer: W, engine_options: Vec) -> Engine<'a, R, W> { Engine { name: name, author: author, diff --git a/src/options.rs b/src/options.rs index c6e1e55..fa8c8e3 100644 --- a/src/options.rs +++ b/src/options.rs @@ -3,45 +3,51 @@ //! and EngineOption tries to be flexible so it can be reused for each option, which also maintaining some //! of the nicer parts of typechecking. -/// Represents the hash option -pub const HASH: &'static str = "Hash"; +use std::collections::HashMap; -/// Represents the Nalimov Path option -pub const NALIMOVPATH: &'static str = "NalimovPath"; +pub mod constants { -/// Represents the Nalimov Cache option -pub const NALIMOVCACHE: &'static str = "NalimovCache"; + /// Represents the hash option + pub const HASH: &'static str = "Hash"; -/// Represents the ponder option -pub const PONDER: &'static str = "Ponder"; + /// Represents the Nalimov Path option + pub const NALIMOVPATH: &'static str = "NalimovPath"; -/// Represents the OwnBook option -pub const OWNBOOK: &'static str = "OwnBook"; + /// Represents the Nalimov Cache option + pub const NALIMOVCACHE: &'static str = "NalimovCache"; -/// Represents the MultiPV option -pub const MULTIPV: &'static str = "MultiPV"; + /// Represents the ponder option + pub const PONDER: &'static str = "Ponder"; -/// Represents the UCI_ShowCurrLine option -pub const UCISHOWCURRLINE: &'static str = "UCI_ShowCurrLine"; + /// Represents the OwnBook option + pub const OWNBOOK: &'static str = "OwnBook"; -/// Represents the UCI_Refutations option -pub const UCISHOWREFUTATIONS: &'static str = "UCI_ShowRefutations"; + /// Represents the MultiPV option + pub const MULTIPV: &'static str = "MultiPV"; -/// Represents the UCI_LimitStrength option -pub const UCISHOWREFUTATIONS: &'static str = "UCI_LimitStrength"; + /// Represents the UCI_ShowCurrLine option + pub const UCISHOWCURRLINE: &'static str = "UCI_ShowCurrLine"; -/// Represents the UCI_Elo option -pub const UCIELO: &'static str = "UCI_Elo"; + /// Represents the UCI_Refutations option + pub const UCISHOWREFUTATIONS: &'static str = "UCI_ShowRefutations"; -/// Represents the UCI_AnalysisMode option -pub const UCIANALYSISMODE: &'static str = "UCI_AnalysisMode"; + /// Represents the UCI_LimitStrength option + pub const UCILIMITSTRENGTH: &'static str = "UCI_LimitStrength"; -/// Represents the UCI_Opponent option -pub const UCIOPPONENT: &'static str = "UCI_Opponent"; + /// 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"; + +} -#[derive(Debug)] /// The `EngineOptionType` type used to indicate what type of option the GUI should display -enum EngineOptionType { +#[derive(Copy, Debug, Eq)] +pub enum EngineOptionType { Check, Spin, Combo, @@ -49,42 +55,45 @@ enum EngineOptionType { TypeString, // `String` is a reserved word so `TypeString` is substituted } -#[derive(Debug)] +#[derive(Copy, 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(Debug, Hash, PartialEq)] /// The `EngineOptionDataType` type used to indicate the type of the `EngineOption` setting -enum EngineOptionDataType { +pub enum EngineOptionDataType { DefaultVal, // `Default` is reserved so `DefaultVal` is used Min, Max, Var, } -#[derive(Debug)] -/// The `EngineOptionDataValue` makes the data type generic so one `EngineOption` can represent everything -/// This would be set to the type of the engine option (ex. i32) -struct EngineOptionDataValue { - value: T, -} - #[derive(Debug, PartialEq)] /// The `EngineOption` type is the overarching type representing a single configurable engine option -struct EngineOption { - name: &'static str, - option_type: EngineOptionType, - option_data: HashMap>, +pub struct EngineOption { + pub name: &'static str, + pub option_type: EngineOptionType, + pub option_data: HashMap, } -impl PartialEq for EngineOption { - pub fn eq(&self, other: EngineOption) { - // TODO: Implement equality on the EngineOption struct and write tests for it. +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 } } -} -impl EngineOption { pub fn option_string(&self) -> String { // TODO: Implement this to save this when looping through and sending options // TODO: This should be tested in isolation as well // This should handle the case where optional min max var are specified as well. // pattern match the engine option type and convert it to the correct string. - format!("PUT THE FULL COMMAND STRING HERE!"); + format!("PUT THE FULL COMMAND STRING HERE!") } } diff --git a/tests/lib.rs b/tests/lib.rs index 1321868..dbc3d7d 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,6 +1,8 @@ extern crate uci; use uci::Engine; +use uci::options::constants; +use uci::options::{ EngineOption, EngineOptionType, EngineOptionDataType, EngineOptionData }; use std::str; #[test] @@ -8,7 +10,7 @@ fn instantiate_new_engine() { let input = b"UNUSED"; let mut output = Vec::new(); - let e = Engine::new("test_name", "test", &input[..], &mut output); + let e = Engine::new("test_name", "test", &input[..], &mut output, vec!()); assert_eq!(e.name, "test_name"); assert_eq!(e.author, "test"); } @@ -20,7 +22,7 @@ fn send_identification_data() { // We need to scope this so that the mutable borrow ends and we can test it safely { - let mut e = Engine::new("test_name", "test", &input[..], &mut output); + let mut e = Engine::new("test_name", "test", &input[..], &mut output, vec!()); e.identify(); } @@ -36,10 +38,26 @@ fn send_readyok() { let input = b"UNUSED"; let mut output = Vec::new(); { - let mut e = Engine::new("test_name", "test", &input[..], &mut output); + let mut e = Engine::new("test_name", "test", &input[..], &mut output, vec!()); e.ready(); } assert_eq!(str::from_utf8(&output).unwrap_or("Unwrapping output failed in send_readyok"), "readyok\n"); } + +#[test] +fn engine_option_equality() { + let name = constants::HASH; + let option_type = EngineOptionType::Check; + let option_data = + [(EngineOptionDataType::DefaultVal, EngineOptionData::Int(1)), + (EngineOptionDataType::Min, EngineOptionData::Int(1)), + (EngineOptionDataType::Max, EngineOptionData::Int(128)) + ].iter().cloned().collect(); + + let o1 = EngineOption { name, option_type, option_data }; + let o2 = EngineOption { name, option_type, option_data }; + + assert_eq!(o1, o2); +}