boseiju/ability_tree/ability/statik/
alterative_casting_permissions.rs

1use crate::ability_tree::AbilityTreeNode;
2use crate::ability_tree::MAX_CHILDREN_PER_NODE;
3
4/// An alternative casting permissions grants the right to cast
5/// a card from another zone than your hand.
6///
7/// For example, gravecrawler says: "You may cast this card from your graveyard".
8#[derive(serde::Serialize, serde::Deserialize)]
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct AlternativeCastingPermissions {
11    pub player: crate::ability_tree::player::PlayerSpecifier,
12    pub object: crate::ability_tree::object::ObjectReference,
13    pub from_zone: crate::ability_tree::zone::ZoneReference,
14    pub additional_cost: Option<crate::ability_tree::cost::Cost>,
15    #[cfg(feature = "spanned_tree")]
16    pub span: crate::ability_tree::span::TreeSpan,
17}
18
19impl crate::ability_tree::AbilityTreeNode for AlternativeCastingPermissions {
20    fn node_id(&self) -> usize {
21        use idris::Idris;
22        crate::ability_tree::NodeKind::ContinuousEffect.id()
23    }
24
25    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
26        let mut children = arrayvec::ArrayVec::new_const();
27        children.push(&self.player as &dyn AbilityTreeNode);
28        children.push(&self.object as &dyn AbilityTreeNode);
29        children.push(&self.from_zone as &dyn AbilityTreeNode);
30        match self.additional_cost.as_ref() {
31            Some(cost) => children.push(cost as &dyn AbilityTreeNode),
32            None => {
33                children.push(crate::ability_tree::dummy_terminal::TreeNodeDummyTerminal::none_node() as &dyn AbilityTreeNode)
34            }
35        }
36        children
37    }
38
39    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
40        use std::io::Write;
41        write!(out, "alternative casting permission:")?;
42        out.push_inter_branch()?;
43        write!(out, "player specifier:")?;
44        out.push_final_branch()?;
45        self.player.display(out)?;
46        out.pop_branch();
47        out.next_inter_branch()?;
48        write!(out, "objects:")?;
49        out.push_final_branch()?;
50        self.object.display(out)?;
51        out.pop_branch();
52        out.next_inter_branch()?;
53        write!(out, "from zone:")?;
54        out.push_final_branch()?;
55        self.from_zone.display(out)?;
56        out.pop_branch();
57        out.next_final_branch()?;
58        write!(out, "additional cost:")?;
59        out.push_final_branch()?;
60        match self.additional_cost.as_ref() {
61            Some(cost) => cost.display(out)?,
62            None => write!(out, "none")?,
63        }
64        out.pop_branch();
65        out.pop_branch();
66        Ok(())
67    }
68
69    fn node_tag(&self) -> &'static str {
70        "alternative casting permissions"
71    }
72
73    #[cfg(feature = "spanned_tree")]
74    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
75        self.span
76    }
77}
78
79#[cfg(feature = "parser")]
80impl crate::utils::DummyInit for AlternativeCastingPermissions {
81    fn dummy_init() -> Self {
82        Self {
83            player: crate::utils::dummy(),
84            object: crate::utils::dummy(),
85            from_zone: crate::utils::dummy(),
86            additional_cost: None,
87            #[cfg(feature = "spanned_tree")]
88            span: Default::default(),
89        }
90    }
91}