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() {
|
fn main() {
|
||||||
let player: Vec<Box<dyn PlayerBuilder>> = vec![
|
let player: Vec<Box<dyn PlayerBuilder>> = vec![
|
||||||
Box::new(player::highest::Highest {}),
|
Box::new(player::random::Random { seed: 0 }),
|
||||||
Box::new(player::highest::Highest {}),
|
Box::new(player::random::Random { seed: 1 }),
|
||||||
Box::new(player::highest::Highest {}),
|
Box::new(player::random::Random { seed: 2 }),
|
||||||
Box::new(player::highest::Highest {}),
|
Box::new(player::single_look_ahead::SingleLookAhead {}),
|
||||||
];
|
];
|
||||||
|
|
||||||
compare(&player, 10000000);
|
compare(&player, 10000000);
|
||||||
|
|
|
||||||
30
src/game.rs
30
src/game.rs
|
|
@ -14,7 +14,20 @@ pub trait PlayerBuilder: Sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub enum Color {
|
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())
|
.map(|i| full_deck[(hand_size * i)..(hand_size * (i + 1))].to_vec())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let remainder = &full_deck[hand_size * player.len()..];
|
||||||
|
|
||||||
let mut round_starting_player = starting_player;
|
let mut round_starting_player = starting_player;
|
||||||
|
|
||||||
let mut points = vec![0; player.len()];
|
let mut points = vec![0; player.len()];
|
||||||
|
|
@ -136,7 +151,17 @@ pub fn herzen<const OUTPUT: bool>(
|
||||||
println!("# Player {index}");
|
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);
|
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;
|
round_starting_player = winner;
|
||||||
}
|
}
|
||||||
|
|
||||||
let remainder = &full_deck[hand_size * player.len()..];
|
|
||||||
let remainder_cost = remainder.iter().map(|c| c.cost()).sum::<u8>();
|
let remainder_cost = remainder.iter().map(|c| c.cost()).sum::<u8>();
|
||||||
|
|
||||||
if OUTPUT {
|
if OUTPUT {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
pub mod single_look_ahead;
|
||||||
|
|
||||||
pub mod cli {
|
pub mod cli {
|
||||||
|
|
||||||
use crate::game::{playeble, Player, PlayerBuilder};
|
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