diff --git a/src/card.rs b/src/card.rs index e91f728..1340851 100644 --- a/src/card.rs +++ b/src/card.rs @@ -1,5 +1,7 @@ //! TODO: module doc :v +use std::ops::Deref; + /// Value for the "sub tiles" inside a room tile #[derive(Clone, Copy, Debug, Default, PartialEq)] enum Cell { @@ -50,11 +52,11 @@ enum RotationDir { #[derive(Clone, Copy, Debug, Default, PartialEq)] struct Card { cells: [Cell; 9], - e: bool, - ne: bool, - n: bool, nw: bool, + n: bool, + ne: bool, w: bool, + e: bool, sw: bool, s: bool, se: bool, @@ -63,7 +65,53 @@ struct Card { impl Card { /// Produces a new card by stacking another on top of this one. pub fn merge(self, top: Self) -> (Self, Option) { - todo!(); + let mut new_card = Self::default(); + let mut doors: Option = None; + + new_card.cells = std::iter::zip(&self.cells, &top.cells) + .map(|(lower, upper)| { + if (lower == &Cell::Filled || upper == &Cell::Filled) + || (lower == &Cell::SW && upper == &Cell::NE) + || (lower == &Cell::SE && upper == &Cell::NW) + || (lower == &Cell::NE && upper == &Cell::SW) + || (lower == &Cell::NW && upper == &Cell::SE) + { + Cell::Filled + } else if upper != &Cell::Empty { + *upper + } else { + *lower + } + }) + .collect::>() + .try_into() + .unwrap(); + + // Check for doors + macro_rules! check_door { + ( $dir:ident, $index:literal ) => { + if self.$dir { + if top.cells[$index] == Cell::Empty || top.$dir { + new_card.$dir = true; + } else { + doors.get_or_insert_default().$dir = true; + } + } else if top.$dir && new_card.cells[$index] != Cell::Empty { + new_card.$dir = true; + } + }; + } + + check_door!(nw, 0); + check_door!(n, 1); + check_door!(ne, 2); + check_door!(w, 3); + check_door!(e, 5); + check_door!(sw, 6); + check_door!(s, 7); + check_door!(se, 8); + + (new_card, doors) } /// Cuts this Card on the given line. Returns two cards @@ -124,9 +172,15 @@ mod test { // For now, triangular cells from the top-most Card survive the merge. let expected = Card { cells: [ - Cell::NW, Cell::Filled, Cell::NE, - Cell::Filled, Cell::Filled, Cell::Filled, - Cell::SW, Cell::Filled, Cell::Filled, + Cell::NW, + Cell::Filled, + Cell::NE, + Cell::Filled, + Cell::Filled, + Cell::Filled, + Cell::SW, + Cell::Filled, + Cell::Filled, ], ..Default::default() };