use crate::Card; use crate::CardField; use crate::Icon; use crate::Painting; #[derive(Debug, Default, Clone, PartialEq, Eq)] pub(crate) struct IconBitfield { circle: u8, square: u8, triangle: u8, color: u8, points: u8, } impl IconBitfield { pub fn get_icon_bits(&self, icon: Icon) -> u8 { match icon { Icon::Circle => self.circle, Icon::Square => self.square, Icon::Triangle => self.triangle, Icon::Color => self.color, } } pub fn get_point_bits(&self) -> u8 { self.points } fn add_icon(&mut self, icon: Icon, index: u8) { let field = match icon { Icon::Circle => &mut self.circle, Icon::Square => &mut self.square, Icon::Triangle => &mut self.triangle, Icon::Color => &mut self.color, }; *field |= 1 << index; } pub fn add_field(&mut self, field: CardField, index: u8) { debug_assert!(index < 5); match field { CardField::Icon(icon) => self.add_icon(icon, index), CardField::DoubleIcon(icon1, icon2) => { self.add_icon(icon1, index); self.add_icon(icon2, index); } CardField::PointsPer(_) => self.points |= 1 << index, CardField::Empty => (), } } pub fn new(card: &Card) -> Self { let mut result = Self::default(); (0u8..) .zip(card.field_iter()) .for_each(|(index, field)| result.add_field(field, index)); result } pub fn from_painting(painting: &Painting) -> Self { let mut bits = Self::new(&painting[0]); bits.layer_below(&Self::new(&painting[1])) .layer_below(&Self::new(&painting[2])); bits } pub fn all_fields(&self) -> u8 { self.circle | self.square | self.triangle | self.color | self.points } /// Result of putting the other card below this one pub fn layer_below(&mut self, other: &Self) -> &mut Self { // 1 x 0 = 0 // 0 x 0 = 0 // 0 x 1 = 1 // 1 x 1 = 0 // Should be !a & b let bitmask = !self.all_fields() & other.all_fields(); self.circle |= other.circle & bitmask; self.square |= other.square & bitmask; self.triangle |= other.triangle & bitmask; self.color |= other.color & bitmask; self.points |= other.points & bitmask; self } } #[cfg(test)] mod tests { use crate::{Icon, icon_bitfield::IconBitfield}; #[test] fn test_add_field() { let mut x: IconBitfield = Default::default(); x.add_icon(Icon::Circle, 2); let expected = IconBitfield { circle: 0b00100, ..Default::default() }; assert_eq!(x, expected); } #[test] fn test_layer_below() { let mut a: IconBitfield = IconBitfield { color: 0b00010, points: 0b01000, ..Default::default() }; let b = IconBitfield { triangle: a.get_point_bits(), square: 0b10000, ..Default::default() }; let expected = IconBitfield { color: a.get_icon_bits(Icon::Color), points: a.get_point_bits(), square: b.get_icon_bits(Icon::Square), ..Default::default() }; a.layer_below(&b); assert_eq!(a, expected); } }