use std::{iter::Sum, ops::{Not, Add, AddAssign, Sub, SubAssign, Deref, DerefMut}};
use rand::Rng;
use crate::deck::{Card, Suit, Name};
use crate::hand::Hand;
pub fn unknown_cards(known_cards: Vec<CardCollection>) -> CardCollection {
!known_cards.into_iter().sum::<CardCollection>()
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct CardCollection(u64);
pub trait CardCollectionContains<Rhs> {fn contains(&self, other: Rhs) -> bool;}
impl Deref for CardCollection {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.0
}
} impl DerefMut for CardCollection {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
} impl Add for CardCollection {
type Output = Self;
fn add(self, other: Self) -> Self {
CardCollection(self.0 | other.0)
}
} impl Add<Name> for CardCollection {
type Output = Self;
fn add(self, name: Name) -> Self {
CardCollection(self.0 | (1 << (name as u64)))
}
} impl Add<Suit> for CardCollection {
type Output = Self;
fn add(self, suit: Suit) -> Self {
if suit == Suit::Wild {
CardCollection(self.0 | (0b111 << 50))
} else {
CardCollection(self.0 | (0b11111 << (5 * (suit as u64))))
}
}
} impl Add<Card> for CardCollection {
type Output = Self;
fn add(self, card: Card) -> Self {
CardCollection(self.0 | (1 << (card.name as u64)))
}
} impl AddAssign for CardCollection {
fn add_assign(&mut self, other: Self) {
self.0 |= other.0;
}
} impl AddAssign<Name> for CardCollection {
fn add_assign(&mut self, name: Name) {
self.0 |= 1 << (name as u64)
}
} impl AddAssign<Suit> for CardCollection {
fn add_assign(&mut self, suit: Suit) {
if suit == Suit::Wild {
self.0 |= 0b111 << 50
} else {
self.0 |= 0b11111 << (5 * (suit as u64))
}
}
} impl AddAssign<Card> for CardCollection {
fn add_assign(&mut self, card: Card) {
self.0 |= 1 << (card.name as u64)
}
} impl Sum<CardCollection> for CardCollection {
fn sum<I: Iterator<Item = CardCollection>>(iter: I) -> Self {
iter.fold(CardCollection::new(), |acc, item| acc + item)
}
} impl Sub for CardCollection {
type Output = Self;
fn sub(self, other: Self) -> Self {
CardCollection(self.0 & !other.0)
}
} impl Sub<Name> for CardCollection {
type Output = Self;
fn sub(self, name: Name) -> Self {
CardCollection(self.0 & !(1 << (name as u64)))
}
} impl Sub<Suit> for CardCollection {
type Output = Self;
fn sub(self, suit: Suit) -> Self {
if suit == Suit::Wild {
CardCollection(self.0 & !(0b111 << 50))
} else {
CardCollection(self.0 & !(0b11111 << (5 * (suit as u64))))
}
}
} impl Sub<Card> for CardCollection {
type Output = Self;
fn sub(self, card: Card) -> Self {
CardCollection(self.0 & !(1 << (card.name as u64)))
}
} impl SubAssign for CardCollection {
fn sub_assign(&mut self, other: Self) {
self.0 &= !other.0;
}
} impl SubAssign<Name> for CardCollection {
fn sub_assign(&mut self, name: Name) {
self.0 &= !(1 << (name as u64))
}
} impl SubAssign<Suit> for CardCollection {
fn sub_assign(&mut self, suit: Suit) {
if suit == Suit::Wild {
self.0 &= !(0b111 << 50)
} else {
self.0 &= !(0b11111 << (5 * (suit as u64)))
}
}
} impl SubAssign<Card> for CardCollection {
fn sub_assign(&mut self, card: Card) {
self.0 &= !(1 << (card.name as u64))
}
} impl Not for CardCollection {
type Output = Self;
fn not(self) -> Self {
CardCollection((!self.0) - (0b11111111111 << 53))
}
} impl CardCollectionContains<CardCollection> for CardCollection {
fn contains(&self, other: CardCollection) -> bool {
self.0 & other.0 != 0
}
} impl CardCollectionContains<Name> for CardCollection {
fn contains(&self, name: Name) -> bool {
self.0 & (1 << (name as u64)) != 0
}
} impl CardCollectionContains<Suit> for CardCollection {
fn contains(&self, suit: Suit) -> bool {
if suit == Suit::Wild {
self.0 & (0b111 << 50) != 0
} else {
self.0 & (0b11111 << (5 * (suit as u64))) != 0
}
}
} impl CardCollectionContains<Card> for CardCollection {
fn contains(&self, card: Card) -> bool {
self.0 & (1 << (card.name as u64)) != 0
}
} impl IntoIterator for CardCollection {
type Item = Card;
type IntoIter = CardCollectionIterator;
fn into_iter(self) -> Self::IntoIter {
CardCollectionIterator {
remaining_bits: self.0,
}
}
} impl IntoIterator for &CardCollection {
type Item = Card;
type IntoIter = CardCollectionIterator;
fn into_iter(self) -> Self::IntoIter {
CardCollectionIterator {
remaining_bits: self.0,
}
}
} impl CardCollection {
pub fn new() -> Self {
CardCollection(0)
}
pub fn len(&self) -> u32 {
self.0.count_ones()
}
pub fn is_empty(&self) -> bool {
self.0 == 0
}
pub fn iter(&self) -> CardCollectionIterator {
CardCollectionIterator {
remaining_bits: self.0,
}
}
pub fn get_random_card(&self) -> Result<Card, String> {
let set_bits: Vec<u8> = self
.iter()
.map(|card| card.name as u8)
.collect();
if set_bits.is_empty() {
Err("No cards in collection.".to_string())
} else {
let random_index = rand::thread_rng().gen_range(0..set_bits.len());
Ok(Card::from(set_bits[random_index]))
}
}
pub fn draw_hand(&mut self) -> Hand {
let hand: Vec<Card> = (0..7)
.map(|_| {
let card = self.get_random_card().expect("Not enough cards in deck");
*self -= card;
card
})
.collect();
let hand_array: [Card; 7] = hand.try_into()
.map_err(|_| "Failed to convert to array")
.expect("Should have exactly 7 cards");
Hand::new(hand_array)
}
}
pub struct CardCollectionIterator {
remaining_bits: u64,
} impl Iterator for CardCollectionIterator {
type Item = Card;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining_bits == 0 {
return None;
}
let position = self.remaining_bits.trailing_zeros() as u8;
self.remaining_bits &= self.remaining_bits - 1;
Some(Card::from(position))
}
} impl From<Hand> for CardCollection {
fn from(hand: Hand) -> Self {
let mut new_hand = CardCollection::new();
for card in hand {
new_hand += card;
}
new_hand
}
} impl From<&Hand> for CardCollection {
fn from(hand: &Hand) -> Self {
let mut new_hand = CardCollection::new();
for card in hand {
new_hand += *card;
}
new_hand
}
}