trioskosmos's picture
Upload folder using huggingface_hub
463f868 verified
use serde::{Deserialize, Serialize};
const HEART_COLOR_COUNT: usize = 7;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct HeartBoard(pub u64);
impl HeartBoard {
pub const MASK: u64 = 0xFF; // 8 bits per color
pub fn get_color_count(&self, color: usize) -> u8 {
if color >= HEART_COLOR_COUNT { return 0; }
((self.0 >> (color * 8)) & Self::MASK) as u8
}
pub fn set_color_count(&mut self, color: usize, val: u8) {
if color >= HEART_COLOR_COUNT { return; }
let mask = Self::MASK << (color * 8);
self.0 = (self.0 & !mask) | ((val as u64) << (color * 8));
}
pub fn add_to_color(&mut self, color: usize, val: i32) {
if color >= HEART_COLOR_COUNT { return; }
let current = self.get_color_count(color) as i32;
self.set_color_count(color, (current + val).max(0).min(255) as u8);
}
pub fn add_heart(&mut self, color: usize) {
self.add_to_color(color, 1);
}
pub fn get_total_count(&self) -> u32 {
let mut total = 0;
for i in 0..7 {
total += self.get_color_count(i) as u32;
}
total
}
pub fn from_array(arr: &[u8; 7]) -> Self {
let mut val = 0u64;
for i in 0..7 {
val |= (arr[i] as u64) << (i * 8);
}
Self(val)
}
pub fn from_array_u32(arr: &[u32; 7]) -> Self {
let mut val = 0u64;
for i in 0..7 {
val |= (arr[i].min(255) as u64) << (i * 8);
}
Self(val)
}
pub fn to_array(&self) -> [u8; 7] {
let mut arr = [0u8; 7];
for i in 0..7 {
arr[i] = ((self.0 >> (i * 8)) & Self::MASK) as u8;
}
arr
}
pub fn to_array_u32(&self) -> [u32; 7] {
let mut arr = [0u32; 7];
for i in 0..7 {
arr[i] = ((self.0 >> (i * 8)) & Self::MASK) as u32;
}
arr
}
/// Returns a bitmask of colors present (0-6).
/// Used for O(1) intersection check with color filters.
pub fn get_color_mask(&self) -> u8 {
let mut mask = 0u8;
for i in 0..7 {
if ((self.0 >> (i * 8)) & Self::MASK) != 0 {
mask |= 1 << i;
}
}
mask
}
pub fn add(&mut self, other: Self) {
// Simple addition per segment.
// Note: This relies on segments not overflowing 255.
// For safety, we can mask or use saturating logic, but for raw MCTS, speed is king.
self.0 += other.0;
}
pub fn satisfies(&self, req: Self) -> bool {
let mut pool = self.to_array();
let need = req.to_array();
let mut wildcards = pool[6] as i32;
let mut satisfied = 0;
let mut total_req = 0;
for i in 0..6 {
let n = need[i] as i32;
let h = pool[i] as i32;
total_req += n;
if h >= n {
satisfied += n;
pool[i] -= n as u8;
} else {
satisfied += h;
pool[i] = 0;
let deficit = n - h;
let used_wild = wildcards.min(deficit);
satisfied += used_wild;
wildcards -= used_wild;
}
}
let mut any_need = need[6] as i32;
total_req += any_need;
let used_wild = wildcards.min(any_need);
satisfied += used_wild;
any_need -= used_wild;
if any_need > 0 {
for i in 0..6 {
let used = (pool[i] as i32).min(any_need);
satisfied += used;
any_need -= used;
if any_need <= 0 {
break;
}
}
}
satisfied >= total_req
}
}
#[inline]
pub fn process_hearts(pool: &mut [u32; 7], need: &[u32; 7]) -> (u32, u32) {
let mut p8 = [0u8; 7];
let mut n8 = [0u8; 7];
for i in 0..7 {
p8[i] = pool[i].min(255) as u8;
n8[i] = need[i].min(255) as u8;
}
let mut satisfied = 0;
let mut wildcards = p8[6] as i32;
let mut total_req = 0;
for i in 0..6 {
let n = n8[i] as i32;
let h = p8[i] as i32;
total_req += n;
if h >= n {
satisfied += n;
p8[i] -= n as u8;
} else {
satisfied += h;
p8[i] = 0;
let deficit = n - h;
let used_wild = wildcards.min(deficit);
satisfied += used_wild;
wildcards -= used_wild;
}
}
let mut any_need = n8[6] as i32;
total_req += any_need;
let used_wild = wildcards.min(any_need);
satisfied += used_wild;
any_need -= used_wild;
if any_need > 0 {
for i in 0..6 {
let used = (p8[i] as i32).min(any_need);
satisfied += used;
p8[i] -= used as u8;
any_need -= used;
if any_need <= 0 {
break;
}
}
}
pool[6] = wildcards.max(0) as u32;
for i in 0..6 {
pool[i] = p8[i] as u32;
}
(satisfied as u32, total_req as u32)
}