Fix clippy warnings
This commit is contained in:
parent
b8a82294d1
commit
d65b7616f1
7 changed files with 78 additions and 94 deletions
32
src/game.rs
32
src/game.rs
|
@ -188,7 +188,7 @@ pub enum Hinted {
|
||||||
}
|
}
|
||||||
impl fmt::Display for Hinted {
|
impl fmt::Display for Hinted {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match *self {
|
||||||
Hinted::Color(color) => {
|
Hinted::Color(color) => {
|
||||||
write!(f, "{}", color)
|
write!(f, "{}", color)
|
||||||
}
|
}
|
||||||
|
@ -355,16 +355,10 @@ impl BoardState {
|
||||||
// can be discarded without necessarily sacrificing score, based on discard + fireworks
|
// can be discarded without necessarily sacrificing score, based on discard + fireworks
|
||||||
pub fn is_dispensable(&self, card: &Card) -> bool {
|
pub fn is_dispensable(&self, card: &Card) -> bool {
|
||||||
let firework = self.fireworks.get(&card.color).unwrap();
|
let firework = self.fireworks.get(&card.color).unwrap();
|
||||||
if firework.complete() {
|
firework.complete()
|
||||||
true
|
|| card.value < firework.needed_value().unwrap()
|
||||||
} else {
|
|| card.value > self.highest_attainable(card.color)
|
||||||
let needed = firework.needed_value().unwrap();
|
|| self.discard.remaining(card) != 1
|
||||||
if card.value < needed || card.value > self.highest_attainable(card.color) {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
self.discard.remaining(card) != 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_players(&self) -> Range<Player> {
|
pub fn get_players(&self) -> Range<Player> {
|
||||||
|
@ -372,10 +366,7 @@ impl BoardState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn score(&self) -> Score {
|
pub fn score(&self) -> Score {
|
||||||
self.fireworks
|
self.fireworks.values().map(Firework::score).sum()
|
||||||
.iter()
|
|
||||||
.map(|(_, firework)| firework.score())
|
|
||||||
.sum()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn discard_size(&self) -> u32 {
|
pub fn discard_size(&self) -> u32 {
|
||||||
|
@ -449,8 +440,7 @@ pub trait GameView {
|
||||||
fn has_card(&self, player: &Player, card: &Card) -> bool {
|
fn has_card(&self, player: &Player, card: &Card) -> bool {
|
||||||
self.get_hand(player)
|
self.get_hand(player)
|
||||||
.iter()
|
.iter()
|
||||||
.position(|other_card| card == other_card)
|
.any(|other_card| card == other_card)
|
||||||
.is_some()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_other_players(&self) -> Vec<Player> {
|
fn get_other_players(&self) -> Vec<Player> {
|
||||||
|
@ -624,12 +614,12 @@ impl GameState {
|
||||||
|
|
||||||
// takes a card from the player's hand, and replaces it if possible
|
// takes a card from the player's hand, and replaces it if possible
|
||||||
fn take_from_hand(&mut self, index: usize) -> Card {
|
fn take_from_hand(&mut self, index: usize) -> Card {
|
||||||
let ref mut hand = self.hands.get_mut(&self.board.player).unwrap();
|
let hand = &mut self.hands.get_mut(&self.board.player).unwrap();
|
||||||
hand.remove(index)
|
hand.remove(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replenish_hand(&mut self) {
|
fn replenish_hand(&mut self) {
|
||||||
let ref mut hand = self.hands.get_mut(&self.board.player).unwrap();
|
let hand = &mut self.hands.get_mut(&self.board.player).unwrap();
|
||||||
if (hand.len() as u32) < self.board.hand_size {
|
if (hand.len() as u32) < self.board.hand_size {
|
||||||
if let Some(new_card) = self.deck.pop() {
|
if let Some(new_card) = self.deck.pop() {
|
||||||
self.board.deck_size -= 1;
|
self.board.deck_size -= 1;
|
||||||
|
@ -650,8 +640,8 @@ impl GameState {
|
||||||
self.board.hints_remaining -= 1;
|
self.board.hints_remaining -= 1;
|
||||||
debug!("Hint to player {}, about {}", hint.player, hint.hinted);
|
debug!("Hint to player {}, about {}", hint.player, hint.hinted);
|
||||||
|
|
||||||
assert!(
|
assert_ne!(
|
||||||
self.board.player != hint.player,
|
self.board.player, hint.player,
|
||||||
"Player {} gave a hint to himself",
|
"Player {} gave a hint to himself",
|
||||||
hint.player
|
hint.player
|
||||||
);
|
);
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub trait CardInfo {
|
||||||
// get probability weight for the card
|
// get probability weight for the card
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn get_weight(&self, card: &Card) -> f32 {
|
fn get_weight(&self, card: &Card) -> f32 {
|
||||||
1.
|
1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_weighted_possibilities(&self) -> Vec<(Card, f32)> {
|
fn get_weighted_possibilities(&self) -> Vec<(Card, f32)> {
|
||||||
|
@ -135,7 +135,7 @@ pub trait CardInfo {
|
||||||
// Represents hinted information about possible values of type T
|
// Represents hinted information about possible values of type T
|
||||||
pub trait Info<T>
|
pub trait Info<T>
|
||||||
where
|
where
|
||||||
T: Hash + Eq + Clone,
|
T: Hash + Eq + Clone + Copy,
|
||||||
{
|
{
|
||||||
// get all a-priori possibilities
|
// get all a-priori possibilities
|
||||||
fn get_all_possibilities() -> Vec<T>;
|
fn get_all_possibilities() -> Vec<T>;
|
||||||
|
@ -149,7 +149,7 @@ where
|
||||||
fn get_possibilities(&self) -> Vec<T> {
|
fn get_possibilities(&self) -> Vec<T> {
|
||||||
self.get_possibility_set()
|
self.get_possibility_set()
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.copied()
|
||||||
.collect::<Vec<T>>()
|
.collect::<Vec<T>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ where
|
||||||
fn initialize() -> HashSet<T> {
|
fn initialize() -> HashSet<T> {
|
||||||
Self::get_all_possibilities()
|
Self::get_all_possibilities()
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.copied()
|
||||||
.collect::<HashSet<_>>()
|
.collect::<HashSet<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,10 +301,10 @@ impl CardPossibilityTable {
|
||||||
|
|
||||||
pub fn decrement_weight(&mut self, card: &Card) {
|
pub fn decrement_weight(&mut self, card: &Card) {
|
||||||
let remove = {
|
let remove = {
|
||||||
let weight = self.possible.get_mut(card).expect(&format!(
|
let weight = self
|
||||||
"Decrementing weight for impossible card: {}",
|
.possible
|
||||||
card
|
.get_mut(card)
|
||||||
));
|
.unwrap_or_else(|| panic!("Decrementing weight for impossible card: {}", card));
|
||||||
*weight -= 1;
|
*weight -= 1;
|
||||||
*weight == 0
|
*weight == 0
|
||||||
};
|
};
|
||||||
|
@ -425,15 +425,15 @@ where
|
||||||
|
|
||||||
// update for hint to me
|
// update for hint to me
|
||||||
pub fn update_for_hint(&mut self, hinted: &Hinted, matches: &[bool]) {
|
pub fn update_for_hint(&mut self, hinted: &Hinted, matches: &[bool]) {
|
||||||
match hinted {
|
match *hinted {
|
||||||
Hinted::Color(color) => {
|
Hinted::Color(color) => {
|
||||||
for (card_info, &matched) in self.hand_info.iter_mut().zip(matches.iter()) {
|
for (card_info, &matched) in self.hand_info.iter_mut().zip(matches.iter()) {
|
||||||
card_info.mark_color(*color, matched);
|
card_info.mark_color(color, matched);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Hinted::Value(value) => {
|
Hinted::Value(value) => {
|
||||||
for (card_info, &matched) in self.hand_info.iter_mut().zip(matches.iter()) {
|
for (card_info, &matched) in self.hand_info.iter_mut().zip(matches.iter()) {
|
||||||
card_info.mark_value(*value, matched);
|
card_info.mark_value(value, matched);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -105,7 +105,8 @@ fn main() {
|
||||||
return print!("{}", get_results_table());
|
return print!("{}", get_results_table());
|
||||||
}
|
}
|
||||||
|
|
||||||
let log_level_str: &str = &matches.opt_str("l").unwrap_or("info".to_string());
|
let l_opt = matches.opt_str("l");
|
||||||
|
let log_level_str = l_opt.as_deref().unwrap_or("info");
|
||||||
let log_level = match log_level_str {
|
let log_level = match log_level_str {
|
||||||
"trace" => log::LogLevelFilter::Trace,
|
"trace" => log::LogLevelFilter::Trace,
|
||||||
"debug" => log::LogLevelFilter::Debug,
|
"debug" => log::LogLevelFilter::Debug,
|
||||||
|
@ -124,16 +125,17 @@ fn main() {
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let n_trials = u32::from_str(&matches.opt_str("n").unwrap_or("1".to_string())).unwrap();
|
let n_trials = u32::from_str(matches.opt_str("n").as_deref().unwrap_or("1")).unwrap();
|
||||||
let seed = matches
|
let seed = matches
|
||||||
.opt_str("s")
|
.opt_str("s")
|
||||||
.map(|seed_str| u32::from_str(&seed_str).unwrap());
|
.map(|seed_str| u32::from_str(&seed_str).unwrap());
|
||||||
let progress_info = matches
|
let progress_info = matches
|
||||||
.opt_str("o")
|
.opt_str("o")
|
||||||
.map(|freq_str| u32::from_str(&freq_str).unwrap());
|
.map(|freq_str| u32::from_str(&freq_str).unwrap());
|
||||||
let n_threads = u32::from_str(&matches.opt_str("t").unwrap_or("1".to_string())).unwrap();
|
let n_threads = u32::from_str(matches.opt_str("t").as_deref().unwrap_or("1")).unwrap();
|
||||||
let n_players = u32::from_str(&matches.opt_str("p").unwrap_or("4".to_string())).unwrap();
|
let n_players = u32::from_str(matches.opt_str("p").as_deref().unwrap_or("4")).unwrap();
|
||||||
let strategy_str: &str = &matches.opt_str("g").unwrap_or("cheat".to_string());
|
let g_opt = matches.opt_str("g");
|
||||||
|
let strategy_str: &str = g_opt.as_deref().unwrap_or("cheat");
|
||||||
|
|
||||||
sim_games(
|
sim_games(
|
||||||
n_players,
|
n_players,
|
||||||
|
|
|
@ -85,7 +85,7 @@ impl Histogram {
|
||||||
fn insert_many(&mut self, val: Score, count: u32) {
|
fn insert_many(&mut self, val: Score, count: u32) {
|
||||||
let new_count = self.get_count(&val) + count;
|
let new_count = self.get_count(&val) + count;
|
||||||
self.hist.insert(val, new_count);
|
self.hist.insert(val, new_count);
|
||||||
self.sum += val * (count as u32);
|
self.sum += val * count;
|
||||||
self.total_count += count;
|
self.total_count += count;
|
||||||
}
|
}
|
||||||
pub fn insert(&mut self, val: Score) {
|
pub fn insert(&mut self, val: Score) {
|
||||||
|
@ -195,11 +195,11 @@ where
|
||||||
lives_histogram.merge(thread_lives_histogram);
|
lives_histogram.merge(thread_lives_histogram);
|
||||||
}
|
}
|
||||||
|
|
||||||
non_perfect_seeds.sort();
|
non_perfect_seeds.sort_unstable();
|
||||||
SimResult {
|
SimResult {
|
||||||
scores: score_histogram,
|
scores: score_histogram,
|
||||||
lives: lives_histogram,
|
lives: lives_histogram,
|
||||||
non_perfect_seed: non_perfect_seeds.get(0).cloned(),
|
non_perfect_seed: non_perfect_seeds.first().cloned(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,7 +253,7 @@ pub trait PublicInformation: Clone {
|
||||||
fn get_private_info(&self, view: &OwnedGameView) -> HandInfo<CardPossibilityTable> {
|
fn get_private_info(&self, view: &OwnedGameView) -> HandInfo<CardPossibilityTable> {
|
||||||
let mut info = self.get_player_info(&view.player);
|
let mut info = self.get_player_info(&view.player);
|
||||||
for card_table in info.iter_mut() {
|
for card_table in info.iter_mut() {
|
||||||
for (_, hand) in &view.other_hands {
|
for hand in view.other_hands.values() {
|
||||||
for card in hand {
|
for card in hand {
|
||||||
card_table.decrement_weight_if_possible(card);
|
card_table.decrement_weight_if_possible(card);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ impl Question for CardHasProperty {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
fn answer(&self, hand: &Cards, board: &BoardState) -> u32 {
|
fn answer(&self, hand: &Cards, board: &BoardState) -> u32 {
|
||||||
let ref card = hand[self.index];
|
let card = &hand[self.index];
|
||||||
if (self.property)(board, card) {
|
if (self.property)(board, card) {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
|
@ -36,21 +36,19 @@ impl Question for CardHasProperty {
|
||||||
hand_info: &mut HandInfo<CardPossibilityTable>,
|
hand_info: &mut HandInfo<CardPossibilityTable>,
|
||||||
board: &BoardState,
|
board: &BoardState,
|
||||||
) {
|
) {
|
||||||
let ref mut card_table = hand_info[self.index];
|
let card_table = &mut hand_info[self.index];
|
||||||
let possible = card_table.get_possibilities();
|
let possible = card_table.get_possibilities();
|
||||||
for card in &possible {
|
for card in &possible {
|
||||||
if (self.property)(board, card) {
|
if (self.property)(board, card) {
|
||||||
if answer == 0 {
|
if answer == 0 {
|
||||||
card_table.mark_false(card);
|
card_table.mark_false(card);
|
||||||
}
|
}
|
||||||
} else {
|
} else if answer == 1 {
|
||||||
if answer == 1 {
|
|
||||||
card_table.mark_false(card);
|
card_table.mark_false(card);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
fn q_is_playable(index: usize) -> CardHasProperty {
|
fn q_is_playable(index: usize) -> CardHasProperty {
|
||||||
CardHasProperty {
|
CardHasProperty {
|
||||||
index,
|
index,
|
||||||
|
@ -184,7 +182,7 @@ impl Question for CardPossibilityPartition {
|
||||||
self.n_partitions
|
self.n_partitions
|
||||||
}
|
}
|
||||||
fn answer(&self, hand: &Cards, _: &BoardState) -> u32 {
|
fn answer(&self, hand: &Cards, _: &BoardState) -> u32 {
|
||||||
let ref card = hand[self.index];
|
let card = &hand[self.index];
|
||||||
*self.partition.get(card).unwrap()
|
*self.partition.get(card).unwrap()
|
||||||
}
|
}
|
||||||
fn acknowledge_answer(
|
fn acknowledge_answer(
|
||||||
|
@ -193,7 +191,7 @@ impl Question for CardPossibilityPartition {
|
||||||
hand_info: &mut HandInfo<CardPossibilityTable>,
|
hand_info: &mut HandInfo<CardPossibilityTable>,
|
||||||
_: &BoardState,
|
_: &BoardState,
|
||||||
) {
|
) {
|
||||||
let ref mut card_table = hand_info[self.index];
|
let card_table = &mut hand_info[self.index];
|
||||||
let possible = card_table.get_possibilities();
|
let possible = card_table.get_possibilities();
|
||||||
for card in &possible {
|
for card in &possible {
|
||||||
if *self.partition.get(card).unwrap() != answer {
|
if *self.partition.get(card).unwrap() != answer {
|
||||||
|
@ -220,10 +218,7 @@ impl MyPublicInformation {
|
||||||
|
|
||||||
fn get_other_players_starting_after(&self, player: Player) -> Vec<Player> {
|
fn get_other_players_starting_after(&self, player: Player) -> Vec<Player> {
|
||||||
let n = self.board.num_players;
|
let n = self.board.num_players;
|
||||||
(0..n - 1)
|
(0..n - 1).map(|i| (player + 1 + i) % n).collect()
|
||||||
.into_iter()
|
|
||||||
.map(|i| (player + 1 + i) % n)
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of ways to hint the player.
|
// Returns the number of ways to hint the player.
|
||||||
|
@ -232,7 +227,7 @@ impl MyPublicInformation {
|
||||||
// - it is public that there are at least two colors
|
// - it is public that there are at least two colors
|
||||||
// - it is public that there are at least two numbers
|
// - it is public that there are at least two numbers
|
||||||
|
|
||||||
let ref info = self.hand_info[&player];
|
let info = &self.hand_info[&player];
|
||||||
|
|
||||||
let may_be_all_one_color = COLORS
|
let may_be_all_one_color = COLORS
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -276,7 +271,7 @@ impl MyPublicInformation {
|
||||||
(-score, i)
|
(-score, i)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
scores.sort();
|
scores.sort_unstable();
|
||||||
scores[0].1
|
scores[0].1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,10 +406,7 @@ impl MyPublicInformation {
|
||||||
|
|
||||||
let player_amt = (n + hint.player - hinter - 1) % n;
|
let player_amt = (n + hint.player - hinter - 1) % n;
|
||||||
|
|
||||||
let amt_from_prev_players = info_per_player
|
let amt_from_prev_players: u32 = info_per_player.iter().take(player_amt as usize).sum();
|
||||||
.iter()
|
|
||||||
.take(player_amt as usize)
|
|
||||||
.sum::<u32>();
|
|
||||||
let hint_info_we_can_give_to_this_player = info_per_player[player_amt as usize];
|
let hint_info_we_can_give_to_this_player = info_per_player[player_amt as usize];
|
||||||
|
|
||||||
let card_index = self.get_index_for_hint(&hint.player);
|
let card_index = self.get_index_for_hint(&hint.player);
|
||||||
|
@ -427,8 +419,7 @@ impl MyPublicInformation {
|
||||||
} else {
|
} else {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
} else {
|
} else if result[card_index] {
|
||||||
if result[card_index] {
|
|
||||||
match hint.hinted {
|
match hint.hinted {
|
||||||
Hinted::Value(_) => 0,
|
Hinted::Value(_) => 0,
|
||||||
Hinted::Color(_) => 1,
|
Hinted::Color(_) => 1,
|
||||||
|
@ -438,7 +429,6 @@ impl MyPublicInformation {
|
||||||
Hinted::Value(_) => 2,
|
Hinted::Value(_) => 2,
|
||||||
Hinted::Color(_) => 3,
|
Hinted::Color(_) => 3,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let hint_value = amt_from_prev_players + hint_type;
|
let hint_value = amt_from_prev_players + hint_type;
|
||||||
|
@ -571,10 +561,10 @@ impl PublicInformation for MyPublicInformation {
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, card_table)| {
|
.map(|(i, card_table)| {
|
||||||
let p_play = card_table.probability_is_playable(&self.board);
|
let p_play = card_table.probability_is_playable(&self.board);
|
||||||
let p_dead = card_table.probability_is_dead(&self.board);
|
let p_dead = card_table.probability_is_dead(&self.board);
|
||||||
Some((i, p_play, p_dead))
|
(i, p_play, p_dead)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let know_playable_card = augmented_hand_info_raw
|
let know_playable_card = augmented_hand_info_raw
|
||||||
|
@ -588,10 +578,10 @@ impl PublicInformation for MyPublicInformation {
|
||||||
let augmented_hand_info = augmented_hand_info_raw
|
let augmented_hand_info = augmented_hand_info_raw
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|&(i, _, p_dead)| {
|
.filter(|&(i, _, p_dead)| {
|
||||||
if p_dead == 1.0 || hand_info[i].is_determined() {
|
if p_dead == 1.0 {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
true
|
!hand_info[i].is_determined()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -655,14 +645,14 @@ impl PublicInformation for MyPublicInformation {
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
ask_play.sort_by_key(|&(i, p_play, _)| (ask_play_score(p_play), i));
|
ask_play.sort_by_key(|&(i, p_play, _)| (ask_play_score(p_play), i));
|
||||||
if let Some(&(i, _, _)) = ask_play.get(0) {
|
if let Some(&(i, _, _)) = ask_play.first() {
|
||||||
return Some(Box::new(q_is_playable(i)));
|
return Some(Box::new(q_is_playable(i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ask_partition = augmented_hand_info;
|
let mut ask_partition = augmented_hand_info;
|
||||||
// sort by probability of death (lowest first), then by index
|
// sort by probability of death (lowest first), then by index
|
||||||
ask_partition.sort_by_key(|&(i, _, p_death)| (FloatOrd(p_death), i));
|
ask_partition.sort_by_key(|&(i, _, p_death)| (FloatOrd(p_death), i));
|
||||||
if let Some(&(i, _, _)) = ask_partition.get(0) {
|
if let Some(&(i, _, _)) = ask_partition.first() {
|
||||||
let question = CardPossibilityPartition::new(i, total_info, &hand_info[i], &self.board);
|
let question = CardPossibilityPartition::new(i, total_info, &hand_info[i], &self.board);
|
||||||
Some(Box::new(question))
|
Some(Box::new(question))
|
||||||
} else {
|
} else {
|
||||||
|
@ -739,6 +729,8 @@ impl InformationPlayerStrategy {
|
||||||
board: &BoardState,
|
board: &BoardState,
|
||||||
hand: &HandInfo<CardPossibilityTable>,
|
hand: &HandInfo<CardPossibilityTable>,
|
||||||
) -> Vec<usize> {
|
) -> Vec<usize> {
|
||||||
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
|
|
||||||
let mut useless: FnvHashSet<usize> = FnvHashSet::default();
|
let mut useless: FnvHashSet<usize> = FnvHashSet::default();
|
||||||
let mut seen: FnvHashMap<Card, usize> = FnvHashMap::default();
|
let mut seen: FnvHashMap<Card, usize> = FnvHashMap::default();
|
||||||
|
|
||||||
|
@ -746,17 +738,20 @@ impl InformationPlayerStrategy {
|
||||||
if card_table.probability_is_dead(board) == 1.0 {
|
if card_table.probability_is_dead(board) == 1.0 {
|
||||||
useless.insert(i);
|
useless.insert(i);
|
||||||
} else if let Some(card) = card_table.get_card() {
|
} else if let Some(card) = card_table.get_card() {
|
||||||
if seen.contains_key(&card) {
|
match seen.entry(card) {
|
||||||
|
Occupied(e) => {
|
||||||
// found a duplicate card
|
// found a duplicate card
|
||||||
useless.insert(i);
|
useless.insert(i);
|
||||||
useless.insert(*seen.get(&card).unwrap());
|
useless.insert(*e.get());
|
||||||
} else {
|
}
|
||||||
seen.insert(card, i);
|
Vacant(e) => {
|
||||||
|
e.insert(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut useless_vec: Vec<usize> = useless.into_iter().collect();
|
let mut useless_vec: Vec<usize> = useless.into_iter().collect();
|
||||||
useless_vec.sort();
|
useless_vec.sort_unstable();
|
||||||
useless_vec
|
useless_vec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,7 +854,7 @@ impl InformationPlayerStrategy {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
playable_cards.sort_by_key(|&(i, play_score)| (FloatOrd(-play_score), i));
|
playable_cards.sort_by_key(|&(i, play_score)| (FloatOrd(-play_score), i));
|
||||||
if let Some(&(play_index, _)) = playable_cards.get(0) {
|
if let Some(&(play_index, _)) = playable_cards.first() {
|
||||||
return TurnChoice::Play(play_index);
|
return TurnChoice::Play(play_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,12 +907,9 @@ impl InformationPlayerStrategy {
|
||||||
// (probably because it stalls the deck-drawing).
|
// (probably because it stalls the deck-drawing).
|
||||||
else if view.board.hints_remaining > 0 && view.someone_else_can_play() {
|
else if view.board.hints_remaining > 0 && view.someone_else_can_play() {
|
||||||
true
|
true
|
||||||
} else if view.board.hints_remaining > 4 {
|
} else {
|
||||||
true
|
// this being false is the only case in which we discard a potentially useful card.
|
||||||
}
|
view.board.hints_remaining > 4
|
||||||
// this is the only case in which we discard a potentially useful card.
|
|
||||||
else {
|
|
||||||
false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if will_hint {
|
if will_hint {
|
||||||
|
@ -1014,7 +1006,7 @@ impl PlayerStrategy for InformationPlayerStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, turn_record: &TurnRecord, view: &BorrowedGameView) {
|
fn update(&mut self, turn_record: &TurnRecord, view: &BorrowedGameView) {
|
||||||
let hint_matches = if let &TurnResult::Hint(ref matches) = &turn_record.result {
|
let hint_matches = if let TurnResult::Hint(matches) = &turn_record.result {
|
||||||
Some(matches)
|
Some(matches)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -1030,7 +1022,7 @@ impl PlayerStrategy for InformationPlayerStrategy {
|
||||||
}
|
}
|
||||||
match turn_record.choice {
|
match turn_record.choice {
|
||||||
TurnChoice::Hint(ref hint) => {
|
TurnChoice::Hint(ref hint) => {
|
||||||
if let &TurnResult::Hint(ref matches) = &turn_record.result {
|
if let TurnResult::Hint(matches) = &turn_record.result {
|
||||||
self.public_info.update_from_hint_matches(hint, matches);
|
self.public_info.update_from_hint_matches(hint, matches);
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
|
@ -1040,7 +1032,7 @@ impl PlayerStrategy for InformationPlayerStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TurnChoice::Discard(index) => {
|
TurnChoice::Discard(index) => {
|
||||||
if let &TurnResult::Discard(ref card) = &turn_record.result {
|
if let TurnResult::Discard(card) = &turn_record.result {
|
||||||
self.public_info.update_from_discard_or_play_result(
|
self.public_info.update_from_discard_or_play_result(
|
||||||
view,
|
view,
|
||||||
&turn_record.player,
|
&turn_record.player,
|
||||||
|
@ -1055,7 +1047,7 @@ impl PlayerStrategy for InformationPlayerStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TurnChoice::Play(index) => {
|
TurnChoice::Play(index) => {
|
||||||
if let &TurnResult::Play(ref card, _) = &turn_record.result {
|
if let TurnResult::Play(card, _) = &turn_record.result {
|
||||||
self.public_info.update_from_discard_or_play_result(
|
self.public_info.update_from_discard_or_play_result(
|
||||||
view,
|
view,
|
||||||
&turn_record.player,
|
&turn_record.player,
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub trait PlayerStrategy {
|
||||||
// Shouldn't do much, except store configuration parameters and
|
// Shouldn't do much, except store configuration parameters and
|
||||||
// possibility initialize some shared randomness between players
|
// possibility initialize some shared randomness between players
|
||||||
pub trait GameStrategy {
|
pub trait GameStrategy {
|
||||||
fn initialize(&self, player: Player, view: &BorrowedGameView) -> Box<dyn PlayerStrategy>;
|
fn initialize(&self, me: Player, view: &BorrowedGameView) -> Box<dyn PlayerStrategy>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents configuration for a strategy.
|
// Represents configuration for a strategy.
|
||||||
|
|
Loading…
Reference in a new issue