Browse Source

Nearly there

ag-yep
Taylor Bockman 7 years ago
parent
commit
be2ca9fc75
  1. 15
      src/lib.rs
  2. 99
      src/options.rs
  3. 24
      tests/lib.rs

15
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 //! 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. //! 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::io::{BufRead, Write};
use std::vec; use std::vec;
@ -13,7 +19,7 @@ pub struct Engine<'a, R, W> {
pub author: &'a str, pub author: &'a str,
pub reader: R, pub reader: R,
pub writer: W, pub writer: W,
pub engine_options: Vec<EngineOption>, pub engine_options: Vec<options::EngineOption>,
} }
/// Notes to delete later: /// 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. /// 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 /// 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 <token, value>. For example it would parse `setoption` into an option constant /// and parses it into a tuple of <token, value>. For example it would parse `setoption` into an option constant
@ -45,7 +52,7 @@ where
W: Write, W: Write,
{ {
pub fn new(name: &'a str, author: &'a str, pub fn new(name: &'a str, author: &'a str,
reader: R, writer: W, engine_options: Vec<EngineOption>) -> Engine<'a, R, W> { reader: R, writer: W, engine_options: Vec<options::EngineOption>) -> Engine<'a, R, W> {
Engine { Engine {
name: name, name: name,
author: author, author: author,

99
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 //! and EngineOption tries to be flexible so it can be reused for each option, which also maintaining some
//! of the nicer parts of typechecking. //! of the nicer parts of typechecking.
/// Represents the hash option use std::collections::HashMap;
pub const HASH: &'static str = "Hash";
/// Represents the Nalimov Path option pub mod constants {
pub const NALIMOVPATH: &'static str = "NalimovPath";
/// Represents the Nalimov Cache option /// Represents the hash option
pub const NALIMOVCACHE: &'static str = "NalimovCache"; pub const HASH: &'static str = "Hash";
/// Represents the ponder option /// Represents the Nalimov Path option
pub const PONDER: &'static str = "Ponder"; pub const NALIMOVPATH: &'static str = "NalimovPath";
/// Represents the OwnBook option /// Represents the Nalimov Cache option
pub const OWNBOOK: &'static str = "OwnBook"; pub const NALIMOVCACHE: &'static str = "NalimovCache";
/// Represents the MultiPV option /// Represents the ponder option
pub const MULTIPV: &'static str = "MultiPV"; pub const PONDER: &'static str = "Ponder";
/// Represents the UCI_ShowCurrLine option /// Represents the OwnBook option
pub const UCISHOWCURRLINE: &'static str = "UCI_ShowCurrLine"; pub const OWNBOOK: &'static str = "OwnBook";
/// Represents the UCI_Refutations option /// Represents the MultiPV option
pub const UCISHOWREFUTATIONS: &'static str = "UCI_ShowRefutations"; pub const MULTIPV: &'static str = "MultiPV";
/// Represents the UCI_LimitStrength option /// Represents the UCI_ShowCurrLine option
pub const UCISHOWREFUTATIONS: &'static str = "UCI_LimitStrength"; pub const UCISHOWCURRLINE: &'static str = "UCI_ShowCurrLine";
/// Represents the UCI_Elo option /// Represents the UCI_Refutations option
pub const UCIELO: &'static str = "UCI_Elo"; pub const UCISHOWREFUTATIONS: &'static str = "UCI_ShowRefutations";
/// Represents the UCI_AnalysisMode option /// Represents the UCI_LimitStrength option
pub const UCIANALYSISMODE: &'static str = "UCI_AnalysisMode"; pub const UCILIMITSTRENGTH: &'static str = "UCI_LimitStrength";
/// Represents the UCI_Opponent option /// Represents the UCI_Elo option
pub const UCIOPPONENT: &'static str = "UCI_Opponent"; 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 /// The `EngineOptionType` type used to indicate what type of option the GUI should display
enum EngineOptionType { #[derive(Copy, Debug, Eq)]
pub enum EngineOptionType {
Check, Check,
Spin, Spin,
Combo, Combo,
@ -49,42 +55,45 @@ enum EngineOptionType {
TypeString, // `String` is a reserved word so `TypeString` is substituted 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 /// 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 DefaultVal, // `Default` is reserved so `DefaultVal` is used
Min, Min,
Max, Max,
Var, 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<T> {
value: T,
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
/// The `EngineOption` type is the overarching type representing a single configurable engine option /// The `EngineOption` type is the overarching type representing a single configurable engine option
struct EngineOption<T> { pub struct EngineOption {
name: &'static str, pub name: &'static str,
option_type: EngineOptionType, pub option_type: EngineOptionType,
option_data: HashMap<EngineOptionDataType, EngineOptionDataValue<T>>, pub option_data: HashMap<EngineOptionDataType, EngineOptionData>,
} }
impl PartialEq for EngineOption { impl EngineOption {
pub fn eq(&self, other: EngineOption) {
// TODO: Implement equality on the EngineOption struct and write tests for it. /// 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 }
} }
}
impl EngineOption {
pub fn option_string(&self) -> String { pub fn option_string(&self) -> String {
// TODO: Implement this to save this when looping through and sending options // TODO: Implement this to save this when looping through and sending options
// TODO: This should be tested in isolation as well // TODO: This should be tested in isolation as well
// This should handle the case where optional min max var are specified 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. // 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!")
} }
} }

24
tests/lib.rs

@ -1,6 +1,8 @@
extern crate uci; extern crate uci;
use uci::Engine; use uci::Engine;
use uci::options::constants;
use uci::options::{ EngineOption, EngineOptionType, EngineOptionDataType, EngineOptionData };
use std::str; use std::str;
#[test] #[test]
@ -8,7 +10,7 @@ fn instantiate_new_engine() {
let input = b"UNUSED"; let input = b"UNUSED";
let mut output = Vec::new(); 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.name, "test_name");
assert_eq!(e.author, "test"); 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 // 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(); e.identify();
} }
@ -36,10 +38,26 @@ fn send_readyok() {
let input = b"UNUSED"; let input = b"UNUSED";
let mut output = Vec::new(); 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(); e.ready();
} }
assert_eq!(str::from_utf8(&output).unwrap_or("Unwrapping output failed in send_readyok"), assert_eq!(str::from_utf8(&output).unwrap_or("Unwrapping output failed in send_readyok"),
"readyok\n"); "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);
}

Loading…
Cancel
Save