diff options
-rw-r--r-- | src/main.rs | 135 |
1 files changed, 77 insertions, 58 deletions
diff --git a/src/main.rs b/src/main.rs index 7af07bf..d1014f9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,32 +2,48 @@ use std::{collections::HashMap, fmt::Display}; use rand::{seq::SliceRandom, thread_rng}; -const MIN_CARD: u8 = 0; +const MIN_CARD: u8 = 1; const MAX_CARD: u8 = 104; fn main() { let mut players = Vec::from([ Player { + name: String::from("Curie"), value_function: |card, line| line.push_cost(card).unwrap_or_default(), hand: Default::default(), score: 0, }, Player { + name: String::from("Joe"), value_function: |card, line| line.push_cost(card).unwrap_or_default(), hand: Default::default(), score: 0, }, Player { + name: String::from("Jim"), + value_function: |card, line| line.push_cost(card).unwrap_or_default(), + hand: Default::default(), + score: 0, + }, + Player { + name: String::from("Jill"), value_function: |card, line| line.push_cost(card).unwrap_or_default(), hand: Default::default(), score: 0, }, ]); - round(&mut players); - round(&mut players); - round(&mut players); - round(&mut players); + let mut n = 0; + while players.iter().all(|p| p.score < 66) { + n += 1; + round(&mut players); + + println!("Round {n}"); + println!("Name Score"); + for player in &mut *players { + println!("{:<6} {:02}", player.name, player.score); + } + } } fn round(players: &mut [Player]) { @@ -35,51 +51,72 @@ fn round(players: &mut [Player]) { cards.shuffle(&mut thread_rng()); let deck = &mut cards.iter(); - let mut state = deck.take(5).copied().map(Line::from).collect::<Vec<Line>>(); + let mut state = deck + .take(5) + .copied() + .enumerate() + .map(Line::from) + .collect::<Vec<Line>>(); for player in &mut *players { player.set_hand(deck.take(10).copied().collect()); - println!("Player: {player}"); + println!("{}: {:?}", player.name, player.hand); } for (i, line) in state.iter().enumerate() { println!("Line {i}: {line}"); } - while !players.iter().any(|p| p.hand.is_empty() || p.score > 66) { + while !players.iter().any(|p| p.hand.is_empty()) { let cards: Vec<u8> = players.iter_mut().map(|p| p.evaluate(&state)).collect(); + let mut played: Vec<(&mut Player, u8)> = players.iter_mut().zip(cards).collect(); + + played.sort_by_key(|p| p.1); + + let mut actions = vec![HashMap::new(); state.len()]; + let mut player_names = Vec::new(); + print!("{:37}", "Table"); + + for (player, card) in played { + print!("{:>10}", player.name); + player_names.push(&player.name); - for (player, card) in players.iter_mut().zip(cards) { let line = state .iter_mut() .min_by_key(|line| (player.value_function)(card, line)) .unwrap(); + actions[line.id].insert(&player.name, card); + if let Some(score) = line.push(card) { player.score += score; } } - for (i, line) in state.iter().enumerate() { - println!("Line {i}: {line}"); - } - } + println!(); + for (line, actions) in state.iter().zip(actions) { + let cards: String = line + .cards + .iter() + .fold(String::new(), |buf, c| format!("{buf}[{c:>3}]")); + + print!("Line {cards:<32}"); + for name in &player_names { + let card = actions + .get(name) + .map(|c| format!("[{c:>3}]")) + .unwrap_or("".to_string()); + print!("{:>10}", card); + } - for player in &mut *players { - println!("Player: {player}"); + println!(); + } } } -fn display_cards(cards: &[u8]) -> String { - cards - .iter() - .map(|c| format!("{c}")) - .collect::<Vec<_>>() - .join("][") -} - #[derive(Debug, Default)] struct Line { + id: usize, cards: Vec<u8>, } @@ -110,38 +147,24 @@ impl Line { impl Display for Line { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let cards = self - .cards + write!(f, "{}: ", self.id)?; + self.cards .iter() - .map(|c| format!("{c}")) - .collect::<Vec<_>>() - .join("]["); - write!(f, "[{cards}]") + .try_for_each(|card| write!(f, "[{card:03}]")) } } -impl From<u8> for Line { - fn from(value: u8) -> Self { +impl From<(usize, u8)> for Line { + fn from((id, value): (usize, u8)) -> Self { Self { + id, cards: Vec::from([value]), } } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] -struct Move { - value: u8, - line: usize, - card: u8, -} - -impl Display for Move { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "[{}] to line {}", self.card, self.line) - } -} - struct Player { + name: String, value_function: fn(card: u8, line: &Line) -> u8, hand: Vec<u8>, score: u8, @@ -157,8 +180,15 @@ impl Player { let value_function = self.value_function; let mut cards = HashMap::new(); - for line in state { - for card in &self.hand { + for card in &self.hand { + let mut valid_play_found = false; + for line in state { + if line.head() < card { + valid_play_found = true + } else if valid_play_found { + continue; + } + let value = value_function(*card, line); cards .entry(card) @@ -172,19 +202,8 @@ impl Player { cards .iter() .max_by_key(|e| e.1) - .and_then(|e| self.hand.iter().position(|c| c == e.1)) + .and_then(|e| self.hand.iter().position(|c| c == *e.0)) .map(|index| self.hand.remove(index)) .unwrap() } } - -impl Display for Player { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Score: {}, Hand: {}", - self.score, - display_cards(&self.hand) - ) - } -} |