diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/character.rs | 95 | ||||
-rw-r--r-- | src/list.rs | 37 | ||||
-rw-r--r-- | src/location.rs | 1 | ||||
-rw-r--r-- | src/main.rs | 16 | ||||
-rw-r--r-- | src/map.rs | 5 | ||||
-rw-r--r-- | src/view.rs | 5 |
6 files changed, 110 insertions, 49 deletions
diff --git a/src/character.rs b/src/character.rs index 1e68dc9..8a3cb2f 100644 --- a/src/character.rs +++ b/src/character.rs @@ -1,39 +1,36 @@ extern crate rand; use character::rand::Rng; -extern crate pathfinding; -use self::pathfinding::astar; use constants::Orders; use location::Location; #[derive(Clone)] pub struct Character { - pub symbol : char, - pub color : u8, - pub order : u8, - pub location : Location, - pub needs_path : bool, + symbol : char, + color : u8, + order : u8, + location : Location, desired_location : Option<Location>, path : Option<Vec<Location>>, } impl Character { + pub fn new(symbol : char, color : u8, location : Location) -> Character { Character { symbol : symbol, color : color, order : Orders::Wander as u8, location : location, - needs_path : false, desired_location : None, path : None, } } + pub fn action(&mut self, free_spaces : Vec<(Location,usize)>) { if self.order == Orders::Wander as u8 { - self.needs_path = false; self.wander(free_spaces); } else if self.order == Orders::Move as u8 { @@ -41,27 +38,47 @@ impl Character { } } - pub fn calculate_path(&mut self, impassable : Vec<(Location, usize)>) { - match self.desired_location { - None => self.order = Orders::Wander as u8, - Some(target) => { - let location = self.location; - let result = astar(&location, - |l| l.neighbours(impassable.clone()), - |l| l.distance(&target), - |l| *l == target); - self.path = match result { - Some(mut result) => { - result.0.reverse(); - result.0.pop(); - Some(result.0) - } - None => { - self.order = Orders::Wander as u8; - None - } - }; - } + pub fn up(&mut self) { + self.location.0 -= 1; + } + + pub fn down(&mut self) { + self.location.0 += 1; + } + + pub fn right(&mut self) { + self.location.1 += 1; + } + + pub fn left(&mut self) { + self.location.1 -= 1; + } + + pub fn get_symbol(&self) -> char { + self.symbol + } + + pub fn get_color(&self) -> u8 { + self.color + } + + pub fn get_location(&self) -> Location { + self.location + } + + pub fn get_desired_location(&self) -> Option<Location> { + self.desired_location + } + + pub fn give_path(&mut self, path : Option<Vec<Location>>) { + match path { + Some(path) => { + self.path = Some(path); + }, + None => { + self.path = None; + self.order = Orders::Wander as u8; + }, } } @@ -70,6 +87,21 @@ impl Character { self.order = Orders::Move as u8; } + pub fn needs_path(&self) -> bool { + if self.order == Orders::Wander as u8 { + false + } + else if self.path.is_some() { + false + } + else if self.desired_location.is_some() && self.path.is_none() { + true + } + else { + false + } + } + fn wander(&mut self, free_spaces : Vec<(Location, usize)>) { let direction = rand::thread_rng().gen_range(0, free_spaces.len()); self.location = free_spaces[direction].0; @@ -78,9 +110,8 @@ impl Character { fn move_along_path(&mut self, free_spaces : Vec<(Location, usize)>) { let mut moved = false; match self.path { - None => self.needs_path = true, + None => (), Some(ref mut calculated_path) => { - self.needs_path = false; if calculated_path.len() > 0 { let next_location = calculated_path.pop().unwrap(); for free_space in free_spaces { diff --git a/src/list.rs b/src/list.rs index 2340385..6292a2f 100644 --- a/src/list.rs +++ b/src/list.rs @@ -1,5 +1,8 @@ extern crate pancurses; +extern crate pathfinding; +use self::pathfinding::astar; + use location::Location; use character::Character; use constants::Colors; @@ -23,16 +26,40 @@ impl List { pub fn action(&mut self) { for i in 0..self.men.len() { - let location = self.men[i].location.clone(); + let location = self.men[i].get_location(); let free_locations = self.get_free_locations(location); self.men[i].action(free_locations); } let impassable = self.get_all_impassable(); for i in 0..self.men.len() { - if self.men[i].needs_path { - self.men[i].calculate_path(impassable.to_vec()); + if self.men[i].needs_path() { + let man = self.men[i].clone(); + let path = self.calculate_path(man, impassable.clone()); + self.men[i].give_path(path); + } + } + } + + fn calculate_path(&mut self, man : Character, impassable : Vec<(Location, usize)>) -> Option<Vec<Location>> { + let desired_location = man.get_desired_location(); + match desired_location { + Some(target) => { + let location = man.get_location(); + let result = astar(&location, + |l| l.neighbours(impassable.clone()), + |l| l.distance(&target), + |l| *l == target); + match result { + Some(mut result) => { + result.0.reverse(); + result.0.pop(); + Some(result.0) + } + None => None, + } } + None => None, } } @@ -84,7 +111,7 @@ impl List { potential_locations.retain(|potential_location| { let mut keep = true; for man in self.men.iter() { - if potential_location.0 == man.location { + if potential_location.0 == man.get_location() { keep = false; } } @@ -102,7 +129,7 @@ impl List { fn get_all_impassable(&mut self) -> Vec<(Location, usize)> { let mut impassable = Vec::new(); for man in self.men.iter() { - impassable.push((man.location, 1)); + impassable.push((man.get_location(), 1)); } for impassable_location in self.impassable_locations.iter() { impassable.push((*impassable_location,1)); diff --git a/src/location.rs b/src/location.rs index ca40700..a6ac623 100644 --- a/src/location.rs +++ b/src/location.rs @@ -5,6 +5,7 @@ impl Location { pub fn distance(&self, other: &Location) -> usize { (((self.0 - other.0).pow(2) + (self.1 - other.1).pow(2)) as f64).sqrt() as usize } + pub fn neighbours(self, impassable : Vec<(Location, usize)>) -> Vec<(Location, usize)> { let mut nearby = vec![Location(self.0 + 1, self.1), Location(self.0 - 1, self.1), Location(self.0, self.1 + 1), Location(self.0, self.1 - 1), diff --git a/src/main.rs b/src/main.rs index 6148aac..81ce270 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,10 +47,10 @@ fn main() { let command = match main.getch() { Some(Input::Character(ch)) => { match ch { - 'h' => {cursor.location.1 -= 1; None} - 'l' => {cursor.location.1 += 1; None} - 'k' => {cursor.location.0 -= 1; None} - 'j' => {cursor.location.0 += 1; None} + 'k' => {cursor.up(); None} + 'j' => {cursor.down(); None} + 'h' => {cursor.left(); None} + 'l' => {cursor.right();None} 'q' => break, 'o' => Some(Commands::Go), 's' => Some(Commands::Grid), @@ -65,17 +65,17 @@ fn main() { map.fill(); match command { - Some(Commands::Go) => list.give_destination(cursor.location), + Some(Commands::Go) => list.give_destination(cursor.get_location()), Some(Commands::Grid) => { paused = true; draw_box = true; - first_location = Some(cursor.location); + first_location = Some(cursor.get_location()); }, Some(Commands::Finish) => { paused = false; draw_box = false; match first_location { - Some(first_location) => list.give_grid(first_location, cursor.location), + Some(first_location) => list.give_grid(first_location, cursor.get_location()), None => (), } }, @@ -90,7 +90,7 @@ fn main() { if draw_box { match first_location { - Some(first_location) => map.draw_box(first_location, cursor.location), + Some(first_location) => map.draw_box(first_location, cursor.get_location()), None => (), } } @@ -60,8 +60,9 @@ impl Map { } pub fn draw(&self, character : &Character) { - self.window.attron(ColorPair(character.color)); - self.window.mvaddch(character.location.0, character.location.1, character.symbol); + self.window.attron(ColorPair(character.get_color())); + let location = character.get_location(); + self.window.mvaddch(location.0, location.1, character.get_symbol()); } pub fn draw_box(&self, first_location : Location, second_location : Location) { diff --git a/src/view.rs b/src/view.rs index d62454b..f464da9 100644 --- a/src/view.rs +++ b/src/view.rs @@ -23,8 +23,9 @@ impl View { } pub fn center(&mut self, character : Character, map_window : &pancurses::Window) { - let c = character.location.0 - self.width/2; - let r = character.location.1 - self.height/2; + let location = character.get_location(); + let c = location.0 - self.width/2; + let r = location.1 - self.height/2; let (hh, ww) = map_window.get_max_yx(); |