diff --git a/src/lib/ai.rs b/src/lib/ai.rs index 0aebb09..5347289 100644 --- a/src/lib/ai.rs +++ b/src/lib/ai.rs @@ -56,12 +56,8 @@ impl AI for Ant { if !choice.is_none() { let pos = choice.unwrap(); if w.cleared.contains(&pos) { - let old_pos = self.pos; self.pos = pos; - w.update_occupied(&old_pos, &pos); - } else { - w.clear(pos); - } + } } BoardCommand::Noop @@ -94,9 +90,7 @@ impl AI for Queen { self.egg_count += 1; return BoardCommand::LayEgg(pos, self.id); } else { - let old_pos = self.pos; self.pos = pos; - w.update_occupied(&old_pos, &pos); } } } diff --git a/src/lib/point.rs b/src/lib/point.rs index 084e3c7..3727ba4 100644 --- a/src/lib/point.rs +++ b/src/lib/point.rs @@ -6,12 +6,49 @@ pub struct Point(pub i32, pub i32); impl Point { pub fn get_neighbors(&self) -> Vec { vec![ - Point(self.0, self.1 + 1), - Point(self.0, self.1 - 1), - Point(self.0 - 1, self.1), - Point(self.0 + 1, self.1), + self.left(), + self.right(), + self.up(), + self.down() ] } + + pub fn is_above(&self, other: &Point) -> bool { + other.up() == *self + } + + pub fn is_below(&self, other: &Point) -> bool { + other.down() == *self + } + + pub fn is_left(&self, other: &Point) -> bool { + other.left() == *self + } + + pub fn is_right(&self, other:&Point) -> bool { + other.right() == *self + } + + pub fn is_adjacent(&self, other: &Point) -> bool { + other.is_left(self) || other.is_right(self) + } + + pub fn left(&self) -> Point { + Point(self.0 - 1, self.1) + } + + pub fn right(&self) -> Point { + Point(self.0 + 1, self.1) + } + + // y values are reversed in ncurses + pub fn down(&self) -> Point { + Point(self.0, self.1 + 1) + } + + pub fn up(&self) -> Point { + Point(self.0, self.1 - 1) + } } fn manhattan(c1: &Point, c2: &Point) -> i32 { diff --git a/src/lib/screen.rs b/src/lib/screen.rs index 8b07159..0a2d911 100644 --- a/src/lib/screen.rs +++ b/src/lib/screen.rs @@ -32,7 +32,7 @@ impl Screen { } pub fn is_in_bounds(&self, pos: &Point) -> bool { - (pos.0 > -self.max_x && pos.0 < self.max_x) && (pos.1 > -self.max_y && pos.1 < self.max_y) + (pos.0 >= 0 && pos.0 < self.max_x) && (pos.1 >= 0 && pos.1 < self.max_y) } pub fn get_valid_movements(&self, pos: &Point) -> Vec { @@ -45,7 +45,7 @@ impl Screen { } pub fn render(&self, p: &Point, char: &str) { - mvprintw(p.1 + self.center.1, p.0 + self.center.0, char); + mvprintw(p.1, p.0, char); } pub fn get_dimensions(&self) -> (Point, Point) { diff --git a/src/lib/world.rs b/src/lib/world.rs index b851498..9c009b5 100644 --- a/src/lib/world.rs +++ b/src/lib/world.rs @@ -1,21 +1,19 @@ -use crate::lib::screen::{Screen, BoardCommand}; +use crate::lib::entity::{Ant, Egg, Entities, Food, Queen}; use crate::lib::point::Point; -use crate::lib::entity::{Entities, Queen, Egg, Ant, Food}; +use crate::lib::screen::{BoardCommand, Screen}; use std::collections::HashSet; #[derive(Clone)] pub struct World { pub cleared: HashSet, - pub occupied: HashSet, - pub food: HashSet + pub food: HashSet, } impl World { pub fn new() -> World { World { cleared: HashSet::new(), - occupied: HashSet::new(), - food: HashSet::new() + food: HashSet::new(), } } @@ -23,23 +21,34 @@ impl World { self.cleared.insert(pos); } - pub fn is_valid_movement(&self, pos: &Point, b: &Screen) -> bool { - b.is_in_bounds(pos) && !self.occupied.contains(pos) + pub fn is_valid_movement(&self, current_pos: &Point, target: &Point, b: &Screen) -> bool { + let mut safe = true; + + if target.is_above(current_pos) { + safe = + !self.cleared.contains(&target.left()) || !self.cleared.contains(&target.right()); + } + + if target.is_adjacent(current_pos) { + let target_down = target.down(); + if self.cleared.contains(&target_down) { + safe = !self.cleared.contains(&target_down.left()) + || !self.cleared.contains(&target_down.right()); + } else { + safe = !self.cleared.contains(&target.down()); + } + } + b.is_in_bounds(target) && safe } pub fn get_valid_movements(&self, pos: &Point, b: &Screen) -> Vec { let moves = b.get_valid_movements(pos); moves .iter() - .filter(|p| !self.occupied.contains(p)) + .filter(|p| self.is_valid_movement(pos, p, b)) .map(|p| p.clone()) .collect() } - - pub fn update_occupied(&mut self, old: &Point, new: &Point) { - self.occupied.remove(old); - self.occupied.insert(*new); - } } pub fn render(e: &Entities, w: &World, b: &Screen) { @@ -56,9 +65,9 @@ pub fn simulate(e: &mut Entities, w: &mut World, b: &mut Screen) { let cmds: Vec = e .data .values_mut() - .map(|a| { + .map(|a| { a.plan(w); - a.step(b, w) + a.step(b, w) }) .collect(); @@ -83,7 +92,7 @@ pub fn simulate(e: &mut Entities, w: &mut World, b: &mut Screen) { } BoardCommand::SpawnFood(pos) => { let food = Food::new(pos.0, pos.1); - e.add_entity(&food); + e.add_entity(&food); } BoardCommand::Noop => {} } diff --git a/src/main.rs b/src/main.rs index 2bfef4a..9d66608 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,12 +24,17 @@ fn main() { let mut world = World::new(); let mut entities = Entities::new(); - let q = Queen::new(0,0); + let q = Queen::new(3,0); entities.add_entity(&q); - for i in -3..3 { - for j in -3..3 { - world.clear(Point(i, j)); + for i in 0..6 { + for j in 0..6 { + if j != 1 { + world.clear(Point(i, j)); + } else { + world.clear(Point(0, j)); + world.clear(Point(5, j)); + } } } @@ -37,7 +42,7 @@ fn main() { // TODO: add way to break out of the loop by hitting a random key simulate(&mut entities, &mut world, &mut board); render(&entities, &world, &board); - sleep(time::Duration::from_millis(100)); + sleep(time::Duration::from_millis(1000)); refresh(); } endwin();