diff --git a/src/state.rs b/src/state.rs index 1e918cf..420cf65 100644 --- a/src/state.rs +++ b/src/state.rs @@ -16,8 +16,28 @@ impl Land { (x % self.width, y % self.height) } - pub fn derelativize(&self, tree: &Tree, relative_x: u16, relative_y: u16) -> (u16, u16) { - ((tree.position.0 + relative_x) % self.width, (tree.position.1 + relative_y) % self.height) + pub fn derelativize(&self, position: (u16, u16), relative_x: i16, relative_y: i16) -> (u16, u16) { + // Note: we don't need to worry about integer overflows directly + // because land itself cannot exceed integer limits in size and + // so that check's implicitly handled with the modulo operator. + // Underflows are a bit trickier to catch, though + let absolute_x = if relative_x < 0 && position.0 - relative_x.unsigned_abs() > position.0 { + (self.width - (relative_x.unsigned_abs() - position.0)) % self.width + } else if relative_x < 0 { + (position.0 - relative_x.unsigned_abs()) % self.height + } else { + (position.0 + relative_x.unsigned_abs()) % self.height + }; + + let absolute_y = if relative_y < 0 && position.1 - relative_y.unsigned_abs() > position.1 { + (self.height - (relative_y.unsigned_abs() - position.1)) % self.height + } else if relative_x < 0 { + (position.1 - relative_y.unsigned_abs()) % self.height + } else { + (position.1 + relative_y.unsigned_abs()) % self.height + }; + + return (absolute_x, absolute_y); } pub fn sow(&mut self, x: u16, y: u16, value: u16) {