boseiju/
ability_tree.rs

1pub mod ability;
2pub mod card_layout;
3pub mod colors;
4pub mod conditional;
5pub mod cost;
6pub mod event;
7pub mod imperative;
8pub mod number;
9pub mod object;
10pub mod player;
11pub mod statement;
12pub mod terminals;
13pub mod time;
14pub mod type_line;
15pub mod zone;
16
17mod dummy_terminal;
18mod root;
19mod tree_node;
20
21#[cfg(feature = "spanned_tree")]
22pub mod span;
23
24pub use root::AbilityTree;
25pub use tree_node::NodeKind;
26
27/// Maximum number of children a single node can have.
28///
29/// This constant strongly impact the size of the tree, and is mostly bottom-limited by exisiting MTG cards.
30pub const MAX_CHILDREN_PER_NODE: usize = 24;
31
32/// Maximim size for the node data.
33pub const MAX_NODE_DATA_SIZE: usize = 32;
34
35/// Trait to reunite all the types of the ability trees to a single "node" type.
36///
37/// The ability tree is using hard types, to preserve strong semantics in the tree.
38/// This allow the abilities to be clearly defined, and prohibits invalid trees
39/// from even existing. However, we then loose generality of the nodes.
40///
41/// The goal of this trait is to keep these generalities:
42/// All nodes of the trees implement the AbilityTreeNode trait, and can be interpreted
43/// as a generic node. This gives abstract access to its id, its children, and its optionnal data.
44///
45/// The only kinds of nodes that are allowed as tree nodes are:
46///
47/// - Plain structs, that can have data and / or children:
48/// ```rust
49/// struct SomeNode {
50///     child_1: SomeChildNode1,
51///     child_2: SomeChildNode2,
52///     data: f32,
53/// }
54/// ```
55/// These nodes are the ones that can have multiple children and data,
56/// and can be empty to be marker nodes, or end of variants.
57///
58/// - Enums, where each variant is unnamed with a single field:
59/// ```rust
60/// enum SomeOtherNode {
61///     Variant1(SomeVariant1),
62///     Variant2(SomeVariant2),
63/// }
64/// ```
65/// These nodes regroups kinds of nodes together, but do not provide any data,
66/// and will always have a single child (although the child kind can vary).
67///
68/// It is possible to create an enum whith no fields.
69/// These basically act like a single field with a struct with no fields,
70/// but we allow them to avoid bloating the code with unecessary nodes. For example:
71/// ```rust
72/// enum YetAnotherNode {
73///     EmptyVariant,
74///     VariantWithData(Data),
75/// }
76/// ```
77/// Here, this is a shortcut for having a `EmptyVariant(EmptyVariantData)` where the
78/// data would be an empty struct.
79pub trait AbilityTreeNode {
80    /// Get the node id.
81    ///
82    /// This identifier is unique to the kind of node it is, allowing to rebuild the node kind
83    /// from it. This allows to create a mapping for all node kinds to other objects.
84    fn node_id(&self) -> usize;
85
86    /// Get all of the nodes children, as abstract ability tree node.
87    ///
88    /// This allows to recursively descend the ability tree over abstract nodes types.
89    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE>;
90
91    /// Get the node data, if any.
92    ///
93    /// Some nodes may carry arbitrary data that are not children, like numbers or booleans.
94    /// This function allow to retrieve them, although for now an array of bytes may not be the best pick.
95    fn data(&self) -> arrayvec::ArrayVec<u8, MAX_NODE_DATA_SIZE> {
96        arrayvec::ArrayVec::new_const()
97    }
98
99    /// Display the ability tree in a human readable manner into the given output.
100    ///
101    /// This is mostly for debug purpuses, and it is not recommanded to use this in production.
102    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()>;
103
104    /// The node tag is a simple one word string that indicates what kind of node it is.
105    ///
106    /// It is primarly used for display and debug purpuses.
107    fn node_tag(&self) -> &'static str;
108
109    /// The node name is more advanced version of the tag, and can allocate memory to dynamically
110    /// changed based on the nodes internals.
111    ///
112    /// It is primarly used for display and debug purpuses.
113    ///
114    /// By default, this is the same as the node tag.
115    /// Nodes that need to provide a more interesting description can override this.
116    fn node_description(&self) -> String {
117        format!("the {} node.", self.node_tag())
118    }
119
120    /// Get the span in the original oracle text that built this node.
121    ///
122    /// This is only available under the spanned_tree feature, and is useful for
123    /// visualisation of the tree and debug purpuses.
124    #[cfg(feature = "spanned_tree")]
125    fn node_span(&self) -> span::TreeSpan;
126}