}
fn next_player_still_in(&self) -> Option<Username> {
- self.active.and_then(|player| self.seats.player_after_where(player, |player| self.players_still_in.contains(&player)))
+ self.active.and_then(|player| self.seats.player_after_where(player, |player| self.players_still_in.contains(&player))
+ .or_else(|| self.players_still_in.get(&player).copied()))
}
fn last_pegging_score(&self) -> Option<(Username, PeggingScore)> {
})
}
+ fn unrevealed_box_card(&self) -> Option<Card> {
+ self.box_cards.iter().filter(|card| !self.revealed.contains(*card)).min().copied()
+ }
+
+ fn four_card_box(&self) -> Option<[Card; 4]> {
+ let hand: Vec<_> = self.box_cards.iter().collect();
+ if let [a, b, c, d] = hand[..] {
+ Some([*a, *b, *c, *d])
+ } else {
+ None
+ }
+ }
+
fn player_has_won(&self, username: Username) -> bool {
self.points.get(&username).map_or(false, |points| *points >= self.settings.target_score)
}
Ok(())
}
(State::Pegging, Action::Pass) => {
+ if Some(username) != self.active {
+ error!("Username taking action must be active");
+ return Err(ActionError::OutOfTurn);
+ }
self.players_still_in.remove(&username);
match self.next_player_still_in() {
None => {
DealerAction::Leave
}
}
- State::Scoring | State::ScoringBox => {
+ State::Scoring => {
if let Some(username) = self.winner() {
DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::WinGame }))
} else if let Some(username) = self.active {
if let Some(card) = self.unrevealed_card(username) {
DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::RevealCard { card } }))
} else if let (Some(hand), Some(turn_up)) = (self.four_card_hand(username), self.turn_up) {
- let score = score_4_card_cribbage_hand(hand, turn_up, self.state == State::ScoringBox);
+ let score = score_4_card_cribbage_hand(hand, turn_up, false);
DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::Score { points: score.points() as u64, reason: format!("{}", score) } }))
} else {
error!("Found no 4-card hand for scoring user");
DealerAction::Leave
}
}
+ State::ScoringBox => {
+ if let Some(username) = self.winner() {
+ DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::WinGame }))
+ } else if let Some(username) = self.active {
+ if let Some(card) = self.unrevealed_box_card() {
+ DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::RevealCard { card } }))
+ } else if let (Some(hand), Some(turn_up)) = (self.four_card_box(), self.turn_up) {
+ let score = score_4_card_cribbage_hand(hand, turn_up, true);
+ DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::Score { points: score.points() as u64, reason: format!("{}", score) } }))
+ } else {
+ error!("Found no 4-card box for scoring user");
+ DealerAction::Leave
+ }
+ } else if let Some(username) = self.dealer.and_then(|dealer| self.seats.player_after(dealer)) {
+ DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::NextToDeal }))
+ } else {
+ error!("Could not find next dealer");
+ DealerAction::Leave
+ }
+ }
State::Completed => DealerAction::Leave,
}
}
{"timestamp":1685568658568,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Seven","suit":"Clubs"}}},
{"timestamp":1685568658564,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Nine","suit":"Clubs"}}},
{"timestamp":1685568658569,"username":"Geoff","action":{"action":"Score","points":4,"reason":"Fifteen two, fifteen four, look all day, see no more"}},
- {"timestamp":1685568658570,"username":"Geoff","action":{"action":"Score","points":4,"reason":"Fifteen two, fifteen four, look all day, see no more"}},
+ {"timestamp":1685568658569,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Five","suit":"Clubs"}}},
+ {"timestamp":1685568658569,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Ten","suit":"Clubs"}}},
+ {"timestamp":1685568658569,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Jack","suit":"Diamonds"}}},
+ {"timestamp":1685568658569,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"King","suit":"Clubs"}}},
+ {"timestamp":1685568658570,"username":"Geoff","action":{"action":"Score","points":7,"reason":"Fifteen two, fifteen four, fifteen six and one for his nob is 7"}},
{"timestamp":1685568658571,"username":"Aga","action":{"action":"NextToDeal"}},
- {"timestamp":1685568658572,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Clubs"}}},
- {"timestamp":1685568658572,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Five","suit":"Diamonds"}}},
- {"timestamp":1685568658573,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Ten","suit":"Diamonds"}}},
- {"timestamp":1685568658574,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Diamonds"}}},
- {"timestamp":1685568658575,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"King","suit":"Spades"}}},
- {"timestamp":1685568658576,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Ace","suit":"Hearts"}}},
- {"timestamp":1685568658576,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Jack","suit":"Diamonds"}}},
- {"timestamp":1685568658577,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Seven","suit":"Spades"}}},
- {"timestamp":1685568658578,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Hearts"}}},
- {"timestamp":1685568658579,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Seven","suit":"Diamonds"}}},
- {"timestamp":1685568658580,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Spades"}}},
- {"timestamp":1685568658581,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Four","suit":"Diamonds"}}},
- {"timestamp":1685568658582,"username":"Aga","action":{"action":"EndDeal"}}
+ {"timestamp":1685653386239,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Queen","suit":"Spades"}}},
+ {"timestamp":1685653386240,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"King","suit":"Hearts"}}},
+ {"timestamp":1685653386240,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Ten","suit":"Diamonds"}}},
+ {"timestamp":1685653386241,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Seven","suit":"Diamonds"}}},
+ {"timestamp":1685653386241,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Diamonds"}}},
+ {"timestamp":1685653386242,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Six","suit":"Spades"}}},
+ {"timestamp":1685653386242,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Eight","suit":"Clubs"}}},
+ {"timestamp":1685653386243,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Four","suit":"Clubs"}}},
+ {"timestamp":1685653386243,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Five","suit":"Diamonds"}}},
+ {"timestamp":1685653386244,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Three","suit":"Hearts"}}},
+ {"timestamp":1685653386244,"username":"Geoff","action":{"action":"ReceiveCard","card":{"rank":"Six","suit":"Hearts"}}},
+ {"timestamp":1685653386244,"username":"Aga","action":{"action":"ReceiveCard","card":{"rank":"Jack","suit":"Diamonds"}}},
+ {"timestamp":1685653386245,"username":"Aga","action":{"action":"EndDeal"}},
+ {"timestamp":1685653386245,"username":"Geoff","action":{"action":"PutInBox","card":{"rank":"Five","suit":"Diamonds"}}},
+ {"timestamp":1685653386245,"username":"Aga","action":{"action":"PutInBox","card":{"rank":"Jack","suit":"Diamonds"}}},
+ {"timestamp":1685653386245,"username":"Aga","action":{"action":"PutInBox","card":{"rank":"King","suit":"Hearts"}}},
+ {"timestamp":1685653386245,"username":"Geoff","action":{"action":"PutInBox","card":{"rank":"Queen","suit":"Spades"}}},
+ {"timestamp":1685653386245,"username":"Aga","action":{"action":"CommunityCard","card":{"rank":"Eight","suit":"Hearts"}}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Eight","suit":"Clubs"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Seven","suit":"Diamonds"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"Score","points":2,"reason":"Fifteen for two"}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Six","suit":"Hearts"}}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"Score","points":3,"reason":"Three"}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Four","suit":"Clubs"}}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Three","suit":"Diamonds"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Three","suit":"Hearts"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"Score","points":4,"reason":"Thirty-one for two and two is four"}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Ten","suit":"Diamonds"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Six","suit":"Spades"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"Score","points":1,"reason":"One for a go"}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Three","suit":"Diamonds"}}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Six","suit":"Hearts"}}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Eight","suit":"Clubs"}}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Ten","suit":"Diamonds"}}},
+ {"timestamp":1685653387245,"username":"Geoff","action":{"action":"Score","points":2,"reason":"Two"}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Three","suit":"Hearts"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Four","suit":"Clubs"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Six","suit":"Spades"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Seven","suit":"Diamonds"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"Score","points":7,"reason":"Fifteen two, fifteen four and three is 7"}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Five","suit":"Diamonds"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Jack","suit":"Diamonds"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Queen","suit":"Spades"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"King","suit":"Hearts"}}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"Score","points":9,"reason":"Fifteen two, fifteen four, fifteen six and three is 9"}},
+ {"timestamp":1685653387245,"username":"Aga","action":{"action":"WinGame"}}
]"#;
let actions = serde_json::from_str(actions).unwrap();
- let settings = r#"{"format":"Cribbage","title":"Cribbage Testing","max_players":2,"target_score":121,"start_time":null}"#;
+ let settings = r#"{"format":"Cribbage","title":"Cribbage Testing","max_players":2,"target_score":21,"start_time":null}"#;
let settings = serde_json::from_str(settings).unwrap();
let seed = r#"{"rng":"ChaCha20","seed":"3789582e9d1a9229bd22d2a61b156bcf907e4cb44d613f97c08b16ec73ff0d90"}"#;