1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
//! Policy for in-game user selection with stdio //! //! Input format is "{row lowercase}{col uppercase}" such as "sS" or "aC". //! If invalid format or position is given, policy will write retrying message to stdout. //! *Note* if given position raise Err from `Game` like `already set position`, game will be terminated by `Agent`. //! //! *Note* We suggest that if you use IoPolicy, construct `Agent` with `Agent::debug`. //! IoPolicy doesn't displaying the board when you make the choice, //! so that if you want to confirm the board, you have to construct `Agent` in debug mode. //! //! # Examples //! ```ignore //! # extern crate connect6; //! # use connect6::{policy::IoPolicy, agent::Agent}; //! let mut stdin = std::io::stdin(); //! let mut stdout = std::io::stdout(); //! let mut io_policy = IoPolicy::new(&mut stdin, &mut stdout); //! Agent::debug(&mut io_policy).play().unwrap(); //! ``` use game::Game; use policy::Policy; use BOARD_SIZE; use std::io; #[cfg(test)] mod tests; /// Policy for in-game user selection with io /// /// Input format is {row lowercase}{col uppercase} such as "sS" or "aC". /// If invalid format or position is given, policy will write retrying message to stdout. /// /// *Note* if given position raise Err from Game, game will be terminated by `Agent`. /// /// *Note* We suggest that if you use IoPolicy, construct `Agent` with `Agent::debug`. /// IoPolicy doesn't displaying the board when you make the choice, /// so that if you want to confirm the board, you have to construct `Agent` in debug mode. /// /// # Examples /// ```ignore /// # #[macro_use] extern crate connect6; /// # use connect6::agent::Agent; /// io_policy_stdio!(io_policy); /// Agent::debug(&mut io_policy).play().unwrap(); /// ``` pub struct IoPolicy<'a, 'b> { reader: &'a mut io::Read, writer: &'b mut io::Write, } impl<'a, 'b> IoPolicy<'a, 'b> { /// Construct a new IoPolicy /// /// # Examples /// ```rust /// # extern crate connect6; /// # use connect6::policy::IoPolicy; /// let mut stdin = std::io::stdin(); /// let mut stdout = std::io::stdout(); /// let mut io_policy = IoPolicy::new(&mut stdin, &mut stdout); /// ``` pub fn new(reader: &'a mut io::Read, writer: &'b mut io::Write) -> IoPolicy<'a, 'b> { IoPolicy { reader, writer } } } impl<'a, 'b> Policy for IoPolicy<'a, 'b> { /// validate user input from stdin and passing it to `Agent` fn next(&mut self, _game: &Game) -> Option<(usize, usize)> { let mut pos = None; // until make the possible selection loop { // get from buffer let mut buffer = [0; 10]; self.reader .read(&mut buffer) .expect("io_policy::next - couldn't read from self.reader"); let query: String = buffer .iter() .filter(|x| x.is_ascii_alphabetic()) .map(|x| *x as char) .collect(); if query.len() == 2 { // parse position let mut chars = query.chars(); let row = chars.next(); let col = chars.next(); if row.is_some() || col.is_some() { // validation let row = row.unwrap() as usize - 0x61; let col = col.unwrap() as usize - 0x41; if row < BOARD_SIZE && col < BOARD_SIZE { pos = Some((row, col)); break; } } } self.writer .write(b"invalid input, retry\n") .expect("agent_io::play - write invalid query msg fail"); } pos } }