use gin_rummy::{Card, Hand, Meld, Melds, Phase, Player, Round, Rules, best_melds, deadwood};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub(crate) struct Knowledge {
pub(crate) opponent_known: Hand,
pub(crate) opponent_shed: Hand,
pub(crate) opponent_passed: Hand,
pub(crate) taken_discard: Option<Card>,
pub(crate) forced_stock: bool,
}
pub struct View<'a> {
round: &'a Round,
seat: Player,
know: &'a Knowledge,
scores: [u16; 2],
}
impl<'a> View<'a> {
pub(crate) const fn new(
round: &'a Round,
seat: Player,
know: &'a Knowledge,
scores: [u16; 2],
) -> Self {
Self {
round,
seat,
know,
scores,
}
}
#[must_use]
pub const fn seat(&self) -> Player {
self.seat
}
#[must_use]
pub const fn game_scores(&self) -> [u16; 2] {
self.scores
}
#[must_use]
pub const fn rules(&self) -> &'a Rules {
self.round.rules()
}
#[must_use]
pub const fn dealer(&self) -> Player {
self.round.dealer()
}
#[must_use]
pub const fn knock_limit(&self) -> u8 {
self.round.knock_limit()
}
#[must_use]
pub const fn phase(&self) -> Phase {
self.round.phase()
}
#[must_use]
pub fn discard_pile(&self) -> &'a [Card] {
self.round.discard_pile()
}
#[must_use]
pub fn upcard(&self) -> Option<Card> {
self.round.discard_pile().last().copied()
}
#[must_use]
pub fn stock_len(&self) -> usize {
self.round.stock().len()
}
pub fn spread(&self) -> impl Iterator<Item = Meld> + 'a {
self.round.spread()
}
#[must_use]
pub const fn knocker(&self) -> Option<Player> {
self.round.knocker()
}
#[must_use]
pub const fn hand(&self) -> Hand {
self.round.hand(self.seat)
}
#[must_use]
pub const fn taken_discard(&self) -> Option<Card> {
self.know.taken_discard
}
#[must_use]
pub const fn can_take_discard(&self) -> bool {
match self.round.phase() {
Phase::Upcard => true,
Phase::Draw => !self.know.forced_stock,
Phase::Discard | Phase::Layoff | Phase::Finished => false,
}
}
#[must_use]
pub const fn opponent_known(&self) -> Hand {
self.know.opponent_known
}
#[must_use]
pub const fn opponent_shed(&self) -> Hand {
self.know.opponent_shed
}
#[must_use]
pub const fn opponent_passed(&self) -> Hand {
self.know.opponent_passed
}
#[must_use]
pub const fn opponent_hand_len(&self) -> usize {
self.round.hand(self.seat.opponent()).len()
}
#[must_use]
pub fn unseen(&self) -> Hand {
let seen = self
.round
.discard_pile()
.iter()
.fold(self.hand() | self.know.opponent_known, |acc, &card| {
acc | card.into()
});
let seen = self
.round
.spread()
.fold(seen, |acc, meld| acc | meld.cards());
Hand::ALL - seen
}
#[must_use]
pub fn deadwood(&self) -> u8 {
deadwood(self.hand())
}
#[must_use]
pub fn best_melds(&self) -> Melds {
best_melds(self.hand())
}
}