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.
221 lines
5.5 KiB
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);
|
|
}
|
|
|