use crate::reaction::{Reaction, ReactionDetail};
use enum_map::Enum;
use enumset::{enum_set, EnumSet, EnumSetType};
use Element::*;
#[repr(u8)]
#[derive(Enum, EnumSetType, Debug)]
pub enum Element {
OMNI,
PYRO,
HYDRO,
ANEMO,
ELECTRO,
DENDRO,
CRYO,
GEO,
PHYSICAL,
PIERCING,
ANY,
}
impl Element {
pub fn is_pure(self) -> bool {
!matches!(self, OMNI | PHYSICAL | PIERCING | ANY)
}
}
pub const PURE_ELEMENTS: ElementSet = elem_set!(PYRO, HYDRO, ANEMO, ELECTRO, DENDRO, CRYO, GEO);
pub const ORDERED_AURA_ELEMENTS: [Element; 5] = [PYRO, HYDRO, ELECTRO, CRYO, DENDRO];
pub const AURA_ELEMENTS: ElementSet = elem_set!(PYRO, HYDRO, ELECTRO, CRYO, DENDRO);
pub const ORDERED_LEGAL_ACTUAL_DICE_ELEMENTS: [Element; 8] =
[OMNI, CRYO, HYDRO, PYRO, ELECTRO, GEO, DENDRO, ANEMO];
pub const LEGAL_ACTUAL_DICE_ELEMENTS: ElementSet =
elem_set!(OMNI, PYRO, HYDRO, ANEMO, ELECTRO, DENDRO, CRYO, GEO);
pub const LEGAL_ABSTRACT_DICE_ELEMENTS: ElementSet =
elem_set!(OMNI, PYRO, HYDRO, ANEMO, ELECTRO, DENDRO, CRYO, GEO, ANY);
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct ElementalAura(ElementSet);
impl ElementalAura {
pub fn aurable(elem: Element) -> bool {
AURA_ELEMENTS.contains(elem)
}
pub fn peek(self) -> Option<Element> {
for elem in ORDERED_AURA_ELEMENTS.iter() {
if self.0.contains(*elem) {
return Some(*elem);
}
}
None
}
pub fn remove(self, elem: Element) -> ElementalAura {
assert!(Self::aurable(elem));
ElementalAura(self.0 - elem)
}
pub fn add(self, elem: Element) -> ElementalAura {
assert!(Self::aurable(elem));
ElementalAura(self.0 | elem)
}
pub fn contains(self, elem: Element) -> bool {
assert!(Self::aurable(elem));
self.0.contains(elem)
}
pub fn has_aura(self) -> bool {
!self.0.is_empty()
}
pub fn elem_auras(self) -> ElementSet {
self.0
}
pub fn consult_reaction(self, income: Element) -> Option<ReactionDetail> {
for elem in ORDERED_AURA_ELEMENTS.into_iter() {
if self.contains(elem) {
if let Some(detail) = Reaction::consult_reaction_detail(elem, income) {
return Some(detail);
}
}
}
None
}
}
pub type ElementSet = EnumSet<Element>;
#[macro_export]
macro_rules! _elem_set {
($(|)*) => { { use enumset::enum_set; enum_set!() } };
($value:path $(,)*) => { { use enumset::enum_set; enum_set!($value) } };
($value:path , $($rest:path),* $(,)*) => { { use enumset::enum_set; enum_set!($value $(| $rest)*) } };
}
pub(crate) use _elem_set as elem_set;