Skip to main content

manabrew_engine/card/
activation_table.rs

1use std::collections::HashMap;
2
3use crate::ids::{CardId, PlayerId};
4use crate::spellability::SpellAbility;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7struct ActivationKey {
8    source: Option<CardId>,
9    hash: u64,
10}
11
12/// Rust parity utility for Java's `ActivationTable`.
13#[derive(Debug, Default, Clone)]
14pub struct ActivationTable {
15    data: HashMap<ActivationKey, Vec<PlayerId>>,
16}
17
18impl ActivationTable {
19    fn key_for(sa: &SpellAbility) -> ActivationKey {
20        // Use stable fields to identify "same" ability invocations.
21        // Java tracks original/root ability identity; this is the nearest
22        // equivalent in the current Rust engine.
23        let mut hash = 1469598103934665603u64; // FNV offset
24        for b in sa.ability_text.as_bytes() {
25            hash ^= *b as u64;
26            hash = hash.wrapping_mul(1099511628211);
27        }
28        ActivationKey {
29            source: sa.source,
30            hash,
31        }
32    }
33
34    /// Add a single activation instance for this spell ability.
35    pub fn add(&mut self, sa: &SpellAbility) {
36        let key = Self::key_for(sa);
37        self.data.entry(key).or_default().push(sa.activating_player);
38    }
39
40    /// Return activation count for this spell ability.
41    pub fn get(&self, sa: &SpellAbility) -> usize {
42        let key = Self::key_for(sa);
43        self.data.get(&key).map_or(0, Vec::len)
44    }
45
46    /// Return activators recorded for this spell ability.
47    pub fn get_activators(&self, sa: &SpellAbility) -> Vec<PlayerId> {
48        let key = Self::key_for(sa);
49        self.data.get(&key).cloned().unwrap_or_default()
50    }
51
52    pub fn clear(&mut self) {
53        self.data.clear();
54    }
55}