Rust implementation of the animal guessing game, where the computer learns about animals and then guesses them with yes/no answers.
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.
animals.rs/src/main.rs

221 lines
5.5 KiB

use std::collections::HashMap;
mod animals;
mod slot;
struct AnswerMachine<'a> {
answer: String,
yes_no: HashMap<&'a str, bool>,
distinguish: HashMap<&'a str, (&'a str, bool)>,
}
impl<'a> AnswerMachine<'a> {
fn abort(&self, msg: String) -> ! {
println!("{}", msg);
std::process::exit(1);
}
}
impl<'a> animals::UserAPI for AnswerMachine<'a> {
fn notify_new_game(&self) {
println!("----- NEW GAME -----");
println!("Secret animal is: {}", self.answer);
}
fn notify_game_ended(&self) {
println!("Game ended.\n");
}
fn notify_new_animal(&self, animal: &str) {
println!("Learned a new animal: {}", animal);
}
fn notify_victory(&self) {
println!("Yay, found an answer!");
}
fn answer_yes_no(&self, question: &str) -> bool {
println!("{}", question);
let answer = match self.yes_no.get(question) {
Some(a) => *a,
None => {
self.abort(format!("* Missing answer for {}! *", &self.answer));
}
};
println!("> {}", match answer { true => "yes", false => "no" });
answer
}
fn is_it_a(&self, animal: &str) -> bool {
println!("Is it a {}?", animal);
let answer = animal == &self.answer;
println!("> {}", match answer { true => "yes", false => "no" });
answer
}
fn what_is_it(&self) -> String {
println!("What animal is it?");
println!("> {}", self.answer);
self.answer.clone()
}
fn how_to_tell_apart(&self, other: &str) -> (String, bool) {
println!("How to tell apart {} and {}?", self.answer, other);
let (s, b) = self.distinguish.get(other).unwrap_or_else(|| {
self.abort(format!("* I don't know how to tell apart {} and {}! *", self.answer, other));
});
println!("> {}", s);
println!("What is the answer for {}?", self.answer);
println!(
"> {}",
match *b { true => "yes", false => "no" }
);
(s.to_string(), *b)
}
}
// a little hack for map initializer literals
macro_rules! map(
{ $($key:expr => $value:expr),* } => {
{
let mut m = std::collections::HashMap::new();
$( m.insert($key, $value); )*
m
}
};
);
fn main() {
let mut db = animals::AnimalDB::new();
let duck = AnswerMachine {
answer: "duck".to_string(),
yes_no: map! {
"Does it quack?" => true
},
distinguish: map! {
"cow" => ("Does it moo?", false)
},
};
db.start_game(&duck);
let dog = AnswerMachine {
answer: "dog".to_string(),
yes_no: map! {
"Does it quack?" => false,
"Does it woof?" => true,
"Is it wild?" => false
},
distinguish: map! {
"duck" => ("Does it quack?", false),
"wolf" => ("Is it wild?", false)
},
};
db.start_game(&dog);
let wolf = AnswerMachine {
answer: "wolf".to_string(),
yes_no: map! {
"Does it quack?" => false,
"Is it wild?" => true,
"Does it fly?" => false,
"Does it eat acorns?" => false
},
distinguish: map! {
"dog" => ("Is it wild?", true)
},
};
db.start_game(&wolf);
let cow = AnswerMachine {
answer: "cow".to_string(),
yes_no: map! {
"Does it quack?" => false,
"Is it wild?" => false,
"Does it woof?" => false,
"Does it give milk?" => true,
"Is it grown for meat?" => true
},
distinguish: map! {
"dog" => ("Does it woof?", false)
},
};
db.start_game(&cow);
let pig = AnswerMachine {
answer: "pig".to_string(),
yes_no: map! {
"Does it quack?" => false,
"Is it wild?" => false,
"Does it woof?" => false,
"Does it give milk?" => false
},
distinguish: map! {
"cow" => ("Does it give milk?", false)
},
};
db.start_game(&pig);
let goat = AnswerMachine {
answer: "goat".to_string(),
yes_no: map! {
"Does it quack?" => false,
"Is it wild?" => false,
"Does it woof?" => false,
"Does it give milk?" => true,
"Is it grown for meat?" => false
},
distinguish: map! {
"cow" => ("Is it grown for meat?", false)
},
};
db.start_game(&goat);
let raven = AnswerMachine {
answer: "raven".to_string(),
yes_no: map! {
"Does it quack?" => false,
"Is it wild?" => true,
"Does it woof?" => false,
"Does it fly?" => true
},
distinguish: map! {
"wolf" => ("Does it fly?", true)
},
};
db.start_game(&raven);
let boar = AnswerMachine {
answer: "boar".to_string(),
yes_no: map! {
"Does it quack?" => false,
"Is it wild?" => true,
"Does it woof?" => false,
"Does it fly?" => false
},
distinguish: map! {
"wolf" => ("Does it eat acorns?", true)
},
};
db.start_game(&boar);
// try how the DB works with the learned animals
println!("===== Testing known animals =====");
db.start_game(&cow);
db.start_game(&dog);
db.start_game(&wolf);
db.start_game(&duck);
db.start_game(&pig);
db.start_game(&goat);
db.start_game(&raven);
}