None => self.used_pegging_cards.last().map(|(username, _)| (*username, PeggingScore::one_for_a_go())),
Some((username, _)) => {
let cards: Vec<_> = self.pegging_cards.iter().map(|(_, card)| *card).collect();
- let score = score_pegging(&cards, false);
+ let score = score_pegging(&cards, self.all_hands_are_empty());
if score.points() > 0 {
Some((*username, score))
} else {
}
fn unrevealed_card(&self, username: Username) -> Option<Card> {
- self.hands.get(&username).and_then(|hand| hand.iter().filter(|card| !self.revealed.contains(*card)).next().copied())
+ self.hands.get(&username).and_then(|hand| hand.iter().filter(|card| !self.revealed.contains(*card)).min().copied())
}
fn four_card_hand(&self, username: Username) -> Option<[Card; 4]> {
Ok(())
}
(State::Pegging, Action::PlayCard { card }) => {
+ if Some(username) != self.active {
+ error!("Username taking action must be active");
+ return Err(ActionError::OutOfTurn);
+ }
if let Some(hand) = self.hands.get_mut(&username) {
hand.remove(&card);
if hand.is_empty() {
self.pegging_cards.push((username, card));
if self.last_pegging_score().is_some() {
self.state = State::ScoringPegging;
+ } else {
+ self.active = self.next_player_still_in();
}
- self.active = self.next_player_still_in();
Ok(())
}
(State::Pegging, Action::Pass) => {
},
active => self.active = active,
}
- if self.all_hands_are_empty() {
- for (username, card) in self.used_pegging_cards.drain(..) {
- self.hands.entry(username).or_default().insert(card);
- }
- self.active = self.dealer.and_then(|dealer| self.seats.player_after(dealer));
- self.state = State::Scoring;
- }
Ok(())
}
(State::ScoringPegging, Action::Score { points, .. }) => {
*self.points.entry(username).or_default() += points as u32;
- if self.next_player_still_in().is_none() {
+ if self.next_player_still_in().is_none() || self.pegging_total() == 31 {
self.used_pegging_cards.extend(self.pegging_cards.drain(..));
self.players_still_in = self.hands.iter().filter(|(_, cards)| !cards.is_empty()).map(|(&username, _)| username).collect();
- self.active = Some(username);
- if !self.players_still_in.contains(&username) {
- self.active = self.next_player_still_in();
- }
}
if self.player_has_won(username) {
self.state = State::ScoringPegging;
self.active = self.dealer.and_then(|dealer| self.seats.player_after(dealer));
self.state = State::Scoring;
} else {
+ self.active = self.next_player_still_in();
self.state = State::Pegging;
}
Ok(())
let mut game = Cribbage::new(0, settings, seed);
for action in actions {
match action.action {
- Action::Join { .. } | Action::PutInBox { .. } | Action::PlayCard { .. } => {
+ Action::Join { .. } | Action::PutInBox { .. } | Action::PlayCard { .. } | Action::Pass => {
let validated = game.validate_action(action.clone()).unwrap();
assert_eq!(ValidatedUserAction(action), validated);
game.take_action(validated).unwrap();
{"timestamp":1685308376248,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"King","suit":"Diamonds"}}},
{"timestamp":1685308376248,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Two","suit":"Spades"}}},
{"timestamp":1685308376248,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Three","suit":"Hearts"}}},
- {"timestamp":1685309372399,"username":"Aga","action":{"action":"Score","points":2,"reason":"Fifteen for two"}}
+ {"timestamp":1685309372399,"username":"Aga","action":{"action":"Score","points":2,"reason":"Fifteen for two"}},
+ {"timestamp":1685308376248,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Nine","suit":"Clubs"}}},
+ {"timestamp":1685308376248,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"Four","suit":"Clubs"}}},
+ {"timestamp":1685308376248,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Three","suit":"Clubs"}}},
+ {"timestamp":1685567770541,"username":"Geoff","action":{"action":"Score","points":2,"reason":"Thirty-one for two"}},
+ {"timestamp":1685308376248,"username":"Aga","action":{"action":"PlayCard","card":{"rank":"King","suit":"Hearts"}}},
+ {"timestamp":1685308376248,"username":"Geoff","action":{"action":"PlayCard","card":{"rank":"Seven","suit":"Clubs"}}},
+ {"timestamp":1685568658530,"username":"Geoff","action":{"action":"Score","points":1,"reason":"One for a go"}},
+ {"timestamp":1685568658532,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Three","suit":"Hearts"}}},
+ {"timestamp":1685568658533,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"Four","suit":"Clubs"}}},
+ {"timestamp":1685568658531,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"King","suit":"Diamonds"}}},
+ {"timestamp":1685568658532,"username":"Aga","action":{"action":"RevealCard","card":{"rank":"King","suit":"Hearts"}}},
+ {"timestamp":1685568658563,"username":"Aga","action":{"action":"Score","points":2,"reason":"Two"}},
+ {"timestamp":1685568658567,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Two","suit":"Spades"}}},
+ {"timestamp":1685568658565,"username":"Geoff","action":{"action":"RevealCard","card":{"rank":"Three","suit":"Clubs"}}},
+ {"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":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"}}
]"#;
let actions = serde_json::from_str(actions).unwrap();
- let settings = r#"{"format":"Cribbage","title":"Cribbage Testing","max_players":2,"target_score":181,"start_time":null}"#;
+ let settings = r#"{"format":"Cribbage","title":"Cribbage Testing","max_players":2,"target_score":121,"start_time":null}"#;
let settings = serde_json::from_str(settings).unwrap();
let seed = r#"{"rng":"ChaCha20","seed":"3789582e9d1a9229bd22d2a61b156bcf907e4cb44d613f97c08b16ec73ff0d90"}"#;