use crate::core::*;
#[derive(Debug)]
pub struct MonteCarloGame {
deck: FlatDeck,
board: Vec<Card>,
hands: Vec<Hand>,
current_offset: usize,
}
impl MonteCarloGame {
pub fn new_with_hands(hands: Vec<Hand>) -> Result<MonteCarloGame, String> {
let mut d = Deck::default();
for h in &hands {
if h.len() != 2 {
return Err(String::from("Hand passed in doesn't have 2 cards."));
}
for c in h.iter() {
if !d.remove(c) {
return Err(format!("Card {} was already removed from the deck.", c));
}
}
}
Ok(MonteCarloGame {
deck: d.flatten(),
hands: hands,
board: vec![],
current_offset: 52,
})
}
pub fn simulate(&mut self) -> Result<(usize, Rank), String> {
if self.hands.is_empty() {
return Err(String::from("There are no hands."));
}
for c in &self.board {
for h in &mut self.hands {
h.push(*c);
}
}
let num_cards = 5 - self.board.len();
self.shuffle_if_needed();
for c in &self.deck[self.current_offset..self.current_offset + num_cards] {
for h in &mut self.hands {
h.push(*c);
}
}
self.current_offset += num_cards;
let best_rank = self.hands
.iter()
.map(|h| h.rank())
.enumerate()
.max_by_key(|&(_, ref rank)| rank.clone())
.ok_or_else(|| String::from("Unable to determine best rank."));
Ok(best_rank?)
}
pub fn reset(&mut self) {
for h in &mut self.hands {
h.truncate(2 + self.board.len());
}
}
fn shuffle_if_needed(&mut self) {
if self.current_offset + 5 > self.deck.len() {
self.current_offset = 0;
self.deck.shuffle();
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::core::Hand;
use crate::core::Rank;
#[test]
fn test_simulate_pocket_pair() {
let hands = ["AdAh", "2c2s"]
.iter()
.map(|s| Hand::new_from_str(s).unwrap())
.collect();
let mut g = MonteCarloGame::new_with_hands(hands).unwrap();
let result = g.simulate().unwrap();
assert!(result.1 >= Rank::OnePair(0));
}
}