1#![allow(dead_code, unused_imports, unused_variables, unused_must_use)]
2
3extern crate rand;
4
5mod color;
6mod peg;
7
8pub use color::Color;
9use rand::Rng;
10use std::fmt;
11use std::io;
12use io::Write;
13pub use peg::Peg;
14
15
16
17#[cfg(test)]
18mod tests {
19 use super::*;
20
21 #[test]
22 fn test_game_step() {
23
24 let mut state = GameState::new(4);
25 let guess = vec![Peg::new(Color::Red), Peg::new(Color::Red), Peg::new(Color::Red), Peg::new(Color::Red)];
26 let validity = state.step(guess);
27
28 println!("{:?}", validity);
29 }
31}
32
33
34#[derive(Debug)]
35pub enum Correctness {
36 Partial,
37 Total,
38}
39
40impl fmt::Display for Correctness {
41 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42 write!(f, "{:?}", self)
43 }
44}
45
46pub struct GameState {
47 answer: Vec<Peg>,
48 current_turn: u32,
49}
50
51impl GameState {
52 pub fn new(num_pegs: usize) -> GameState {
53 let answer: Vec<Peg> = (0..num_pegs)
54 .map(|x: usize| Peg::new_random())
55 .collect();
56
57 GameState::new_with_answer(answer)
58 }
59
60 pub fn new_with_answer(answer: Vec<Peg>) -> GameState {
61 GameState {
62 answer,
63 current_turn: 0,
64 }
65 }
66
67 pub fn step(&mut self, guess: Vec<Peg>) -> Vec<Correctness> {
68 self.current_turn += 1;
69
70 self.make_guess_response(guess)
71 }
72
73 fn make_guess_response(&mut self, mut guess: Vec<Peg>) -> Vec<Correctness> {
74 use Correctness::*;
75
76 let mut answer = self.answer.clone();
77 let mut result: Vec<Correctness> = Vec::new();
79
80 for i in 0..guess.len() {
81 if guess[i].color() == answer[i].color() && !answer[i].found() {
82 result.push(Total);
83 answer[i].find();
84 guess[i].find();
85 }
86 }
87
88 guess.retain(|p| !p.found());
89 answer.retain(|p| !p.found());
90
91 for g in guess.iter() {
92 answer.iter()
93 .position(|p| p.color() == g.color())
94 .map(|index| {
95 if !answer[index].found() {
96 result.push(Partial);
97 answer[index].find();
98 }
99 });
100 }
101 result
102 }
103}