de9d95a0355d3b5001528c86cf46a114f08ee068
[entelect-challenge-tower-defence.git] / src / engine / geometry.rs
1 use engine::constants::*;
2
3 //TODO: Change Point to be a single number, or stored as a bitfield
4 // (bitfield to x and y for writing move might be hard?
5
6 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
7 pub struct Point {
8     pub x: u8,
9     pub y: u8
10 }
11
12 impl Point {
13     pub fn new(x: u8, y: u8) -> Point {
14         Point { x, y }
15     }
16     pub fn move_left(&self) -> Option<Point> {
17         self.x.checked_sub(1).map(|x| Point {
18             x,
19             ..*self
20         })
21     }
22     pub fn move_right(&self, size: &Point) -> Option<Point> {
23         if self.x + 1 >= size.x {
24             None
25         } else {
26             Some(Point {
27                 x: self.x + 1,
28                 ..*self
29             })
30         }
31     }
32
33     pub fn wrapping_move_left(&mut self) {
34         self.x = self.x.wrapping_sub(1);
35     }
36     pub fn wrapping_move_right(&mut self) {
37         self.x = self.x.wrapping_add(1);
38     }
39
40     pub fn flip_x(&self) -> Point {
41         let flipped_x = if self.x >= SINGLE_MAP_WIDTH {
42             FULL_MAP_WIDTH - self.x - 1
43         } else {
44             self.x
45         };
46         Point::new(flipped_x, self.y)
47     }
48 }
49
50 impl Point {
51     /**
52      * # Bitfields
53      * 
54      * 0,0 is the top left point.
55      * >> (towards 0) moves bits towards the player that owns that side
56      * << (towards max) moves bits towards the opponent
57      * This involves mirroring the x dimension for the opponent's side
58      */
59
60
61     pub fn to_bitfield(&self) -> (u64, u64) {
62         (self.to_left_bitfield(), self.to_right_bitfield())
63     }
64     
65     pub fn to_left_bitfield(&self) -> u64 {
66         if self.x >= SINGLE_MAP_WIDTH {
67             0
68         } else {
69             let index = self.y * SINGLE_MAP_WIDTH + self.x;
70             1 << index
71         }
72     }
73
74     pub fn to_right_bitfield(&self) -> u64 {
75         if self.x < SINGLE_MAP_WIDTH {
76             0
77         } else {
78             let index = self.y * SINGLE_MAP_WIDTH + FULL_MAP_WIDTH - self.x - 1;
79             1 << index
80         }
81     }
82
83     pub fn to_either_bitfield(&self) -> u64 {
84         self.to_left_bitfield() | self.to_right_bitfield()
85     }
86 }
87
88 use std::cmp::Ord;
89 use std::cmp::Ordering;
90
91 impl PartialOrd for Point {
92     fn partial_cmp(&self, other: &Point) -> Option<Ordering> {
93         Some(self.cmp(other))
94     }
95 }
96 impl Ord for Point {
97     fn cmp(&self, other: &Point) -> Ordering {
98         let a = self.flip_x();
99         let b = other.flip_x();
100         a.y.cmp(&b.y).then(a.x.cmp(&b.x))
101     }
102 }