Add simple player
This commit is contained in:
parent
ecec35b20f
commit
2d9ecd55b6
4 changed files with 125 additions and 7 deletions
|
|
@ -48,10 +48,10 @@ fn compare(player_builders: &[Box<dyn PlayerBuilder>], games: usize) {
|
|||
|
||||
fn main() {
|
||||
let player: Vec<Box<dyn PlayerBuilder>> = vec![
|
||||
Box::new(player::highest::Highest {}),
|
||||
Box::new(player::highest::Highest {}),
|
||||
Box::new(player::highest::Highest {}),
|
||||
Box::new(player::highest::Highest {}),
|
||||
Box::new(player::random::Random { seed: 0 }),
|
||||
Box::new(player::random::Random { seed: 1 }),
|
||||
Box::new(player::random::Random { seed: 2 }),
|
||||
Box::new(player::single_look_ahead::SingleLookAhead {}),
|
||||
];
|
||||
|
||||
compare(&player, 10000000);
|
||||
|
|
|
|||
30
src/game.rs
30
src/game.rs
|
|
@ -14,7 +14,20 @@ pub trait PlayerBuilder: Sync {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AdditionalInformation {}
|
||||
pub struct AdditionalInformation {
|
||||
num_player: usize,
|
||||
not_seen_cards: Vec<Card>,
|
||||
}
|
||||
|
||||
impl AdditionalInformation {
|
||||
pub fn get_num_player(&self) -> usize {
|
||||
self.num_player
|
||||
}
|
||||
|
||||
pub fn get_not_seen_cards(&self) -> &[Card] {
|
||||
&self.not_seen_cards
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub enum Color {
|
||||
|
|
@ -118,6 +131,8 @@ pub fn herzen<const OUTPUT: bool>(
|
|||
.map(|i| full_deck[(hand_size * i)..(hand_size * (i + 1))].to_vec())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let remainder = &full_deck[hand_size * player.len()..];
|
||||
|
||||
let mut round_starting_player = starting_player;
|
||||
|
||||
let mut points = vec![0; player.len()];
|
||||
|
|
@ -136,7 +151,17 @@ pub fn herzen<const OUTPUT: bool>(
|
|||
println!("# Player {index}");
|
||||
}
|
||||
|
||||
let ai = AdditionalInformation {};
|
||||
let ai = AdditionalInformation {
|
||||
num_player: player.len(),
|
||||
not_seen_cards: hands
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, h)| if i != index { Some(h) } else { None })
|
||||
.flatten()
|
||||
.chain(remainder.iter())
|
||||
.copied()
|
||||
.collect::<Vec<_>>(),
|
||||
};
|
||||
|
||||
let played_card = player[index].select_card(&hands[index], &stack, &ai);
|
||||
|
||||
|
|
@ -183,7 +208,6 @@ pub fn herzen<const OUTPUT: bool>(
|
|||
round_starting_player = winner;
|
||||
}
|
||||
|
||||
let remainder = &full_deck[hand_size * player.len()..];
|
||||
let remainder_cost = remainder.iter().map(|c| c.cost()).sum::<u8>();
|
||||
|
||||
if OUTPUT {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
pub mod single_look_ahead;
|
||||
|
||||
pub mod cli {
|
||||
|
||||
use crate::game::{playeble, Player, PlayerBuilder};
|
||||
|
|
|
|||
92
src/player/single_look_ahead.rs
Normal file
92
src/player/single_look_ahead.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
use crate::game::{playeble, Player, PlayerBuilder};
|
||||
|
||||
pub struct SingleLookAhead {}
|
||||
|
||||
impl PlayerBuilder for SingleLookAhead {
|
||||
fn build(&self) -> Box<dyn crate::game::Player> {
|
||||
Box::new(SingleLookAhead {})
|
||||
}
|
||||
}
|
||||
|
||||
impl Player for SingleLookAhead {
|
||||
fn select_card(
|
||||
&mut self,
|
||||
hand: &[crate::game::Card],
|
||||
stack: &[crate::game::Card],
|
||||
additional_information: &crate::game::AdditionalInformation,
|
||||
) -> crate::game::Card {
|
||||
let _ = additional_information;
|
||||
|
||||
if stack.is_empty() {
|
||||
// first card
|
||||
|
||||
// Play card that is least likely to get the stack.
|
||||
// For each card calculate likelihood of getting the stack
|
||||
|
||||
hand.iter()
|
||||
.map(|&c| {
|
||||
// likelyhood that player can play a card that is lower
|
||||
// = likelyhood that player does not have card of the color
|
||||
// + likelyhood that player has card of color that is lower than c given that he has card of color
|
||||
|
||||
// let individual_card_probability = hand.len() as f64
|
||||
// / additional_information.get_not_seen_cards().len() as f64;
|
||||
|
||||
(
|
||||
c,
|
||||
additional_information
|
||||
.get_not_seen_cards()
|
||||
.iter()
|
||||
.filter(|&d| c.color == d.color)
|
||||
.count(),
|
||||
)
|
||||
})
|
||||
.max_by(|(_, va), (_, vb)| va.partial_cmp(vb).unwrap())
|
||||
.unwrap()
|
||||
.0
|
||||
} else if hand.iter().any(|c| c.color == stack[0].color) {
|
||||
// serve
|
||||
let mut playable_cards = hand.to_vec();
|
||||
|
||||
playable_cards.sort();
|
||||
|
||||
playable_cards.retain(|&c| playeble(c, hand, stack.first().map(|d| d.color)));
|
||||
|
||||
let highest_card_played = stack
|
||||
.iter()
|
||||
.filter(|c| c.color == stack[0].color)
|
||||
.max_by_key(|c| c.color)
|
||||
.unwrap();
|
||||
|
||||
playable_cards
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|c| c.value < highest_card_played.value)
|
||||
.max_by_key(|c| c.value)
|
||||
.unwrap_or(playable_cards[0])
|
||||
} else {
|
||||
// throw
|
||||
hand.iter()
|
||||
.map(|&c| {
|
||||
// likelyhood that player can play a card that is lower
|
||||
// = likelyhood that player does not have card of the color
|
||||
// + likelyhood that player has card of color that is lower than c given that he has card of color
|
||||
|
||||
// let individual_card_probability = hand.len() as f64
|
||||
// / additional_information.get_not_seen_cards().len() as f64;
|
||||
|
||||
(
|
||||
c,
|
||||
additional_information
|
||||
.get_not_seen_cards()
|
||||
.iter()
|
||||
.filter(|&d| c.color == d.color && d.value < c.value)
|
||||
.count(),
|
||||
)
|
||||
})
|
||||
.max_by(|(_, va), (_, vb)| va.partial_cmp(vb).unwrap())
|
||||
.unwrap()
|
||||
.0
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue