mod card_states;
mod line;
mod slot;
use crate::card_quantum::Variant;
use crate::game;
use slog;
pub use line::Line;
pub use line::LineScore;
pub use slot::Slot;
impl std::fmt::Debug for HyphenatedPlayer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("[")?;
for (pos, slot) in self.line.hands.iter_hand(0) {
if pos > 0 {
f.write_str(", ")?;
}
std::fmt::Display::fmt(&slot.quantum, f)?;
if slot.clued {
f.write_str("'")?;
}
if slot.trash {
f.write_str("kt")?;
}
if slot.play {
f.write_str("!")?;
}
}
f.write_str("]")?;
Ok(())
}
}
pub struct HyphenatedPlayer {
debug: bool,
variant: Variant,
turn: u8,
line: line::Line,
logger: slog::Logger,
}
impl HyphenatedPlayer {
pub fn new(debug: bool) -> Self {
Self::_new(debug, slog::Logger::root(slog::Discard, slog::o!()))
}
fn _new(debug: bool, logger: slog::Logger) -> Self {
Self {
debug,
variant: Variant {},
turn: 0,
line: line::Line::new(4, 0),
logger,
}
}
pub fn with_logger(logger: slog::Logger) -> Self {
Self::_new(false, logger)
}
pub fn line(&self) -> line::Line {
self.line.clone()
}
}
impl game::PlayerStrategy for HyphenatedPlayer {
fn init(&mut self, num_players: u8, own_player: u8) {
self.variant = Variant {};
self.turn = 0;
self.line = line::Line::with_logger(
num_players,
own_player,
self.logger.new(slog::o!("turn" => "0")),
);
}
fn drawn(&mut self, player: usize, card: game::Card) {
self.line.drawn(player, card);
}
fn own_drawn(&mut self) {
self.line.own_drawn();
}
fn played(&mut self, player: usize, pos: usize, card: game::Card, successful: bool) {
self.line.played(player, pos, card, successful);
self.turn += 1;
}
fn discarded(&mut self, player: usize, pos: usize, card: game::Card) {
self.line.discarded(player, pos, card);
self.turn += 1;
}
fn clued(&mut self, who: usize, whom: usize, clue: game::Clue, touched: game::PositionSet) {
self.line.clued(who, whom, clue, touched);
self.turn += 1;
}
fn act(&mut self, status: &game::GameStatus) -> game::Move {
if let Some(play_move) = self.line.play() {
return play_move;
}
if status.clues == 0 {
return self.line.discard();
}
let mut best_score = if status.clues == 8 {
LineScore::bad()
} else {
self.line.score(0)
};
let mut best_move = self.line.discard();
if self.debug {
println!("discarding score: {:?}", best_score);
}
for player in 1..self.line.hands.num_players {
for suit in self.variant.suits().iter() {
let clue = game::Clue::Color(suit.clue_color());
if let Some(score) = self.line.clone().clue(player as usize, clue) {
if self.debug {
println!("considered cluing {:?} to {player} with {:?}", clue, score);
}
if score > best_score {
best_move = game::Move::Clue(player, clue);
best_score = score;
}
}
}
for rank in 1..=5 {
let clue = game::Clue::Rank(rank);
if let Some(score) = self.line.clone().clue(player as usize, clue) {
if self.debug {
println!("considered cluingg {:?} to {player} with {:?}", clue, score);
}
if score > best_score {
best_move = game::Move::Clue(player, clue);
best_score = score;
}
}
}
}
best_move
}
}