render sideways correctly, added movement restrictions

sideways
Rostyslav Hnatyshyn 9 months ago
parent 164030424d
commit ded96cc4b9
  1. 6
      src/lib/ai.rs
  2. 45
      src/lib/point.rs
  3. 4
      src/lib/screen.rs
  4. 37
      src/lib/world.rs
  5. 15
      src/main.rs

@ -56,11 +56,7 @@ impl AI for Ant {
if !choice.is_none() { if !choice.is_none() {
let pos = choice.unwrap(); let pos = choice.unwrap();
if w.cleared.contains(&pos) { if w.cleared.contains(&pos) {
let old_pos = self.pos;
self.pos = pos; self.pos = pos;
w.update_occupied(&old_pos, &pos);
} else {
w.clear(pos);
} }
} }
@ -94,9 +90,7 @@ impl AI for Queen {
self.egg_count += 1; self.egg_count += 1;
return BoardCommand::LayEgg(pos, self.id); return BoardCommand::LayEgg(pos, self.id);
} else { } else {
let old_pos = self.pos;
self.pos = pos; self.pos = pos;
w.update_occupied(&old_pos, &pos);
} }
} }
} }

@ -6,12 +6,49 @@ pub struct Point(pub i32, pub i32);
impl Point { impl Point {
pub fn get_neighbors(&self) -> Vec<Point> { pub fn get_neighbors(&self) -> Vec<Point> {
vec![ vec![
Point(self.0, self.1 + 1), self.left(),
Point(self.0, self.1 - 1), self.right(),
Point(self.0 - 1, self.1), self.up(),
Point(self.0 + 1, self.1), 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 { fn manhattan(c1: &Point, c2: &Point) -> i32 {

@ -32,7 +32,7 @@ impl Screen {
} }
pub fn is_in_bounds(&self, pos: &Point) -> bool { 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<Point> { pub fn get_valid_movements(&self, pos: &Point) -> Vec<Point> {
@ -45,7 +45,7 @@ impl Screen {
} }
pub fn render(&self, p: &Point, char: &str) { 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) { pub fn get_dimensions(&self) -> (Point, Point) {

@ -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::point::Point;
use crate::lib::entity::{Entities, Queen, Egg, Ant, Food}; use crate::lib::screen::{BoardCommand, Screen};
use std::collections::HashSet; use std::collections::HashSet;
#[derive(Clone)] #[derive(Clone)]
pub struct World { pub struct World {
pub cleared: HashSet<Point>, pub cleared: HashSet<Point>,
pub occupied: HashSet<Point>, pub food: HashSet<u32>,
pub food: HashSet<u32>
} }
impl World { impl World {
pub fn new() -> World { pub fn new() -> World {
World { World {
cleared: HashSet::new(), cleared: HashSet::new(),
occupied: HashSet::new(), food: HashSet::new(),
food: HashSet::new()
} }
} }
@ -23,23 +21,34 @@ impl World {
self.cleared.insert(pos); self.cleared.insert(pos);
} }
pub fn is_valid_movement(&self, pos: &Point, b: &Screen) -> bool { pub fn is_valid_movement(&self, current_pos: &Point, target: &Point, b: &Screen) -> bool {
b.is_in_bounds(pos) && !self.occupied.contains(pos) 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<Point> { pub fn get_valid_movements(&self, pos: &Point, b: &Screen) -> Vec<Point> {
let moves = b.get_valid_movements(pos); let moves = b.get_valid_movements(pos);
moves moves
.iter() .iter()
.filter(|p| !self.occupied.contains(p)) .filter(|p| self.is_valid_movement(pos, p, b))
.map(|p| p.clone()) .map(|p| p.clone())
.collect() .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) { pub fn render(e: &Entities, w: &World, b: &Screen) {

@ -24,12 +24,17 @@ fn main() {
let mut world = World::new(); let mut world = World::new();
let mut entities = Entities::new(); let mut entities = Entities::new();
let q = Queen::new(0,0); let q = Queen::new(3,0);
entities.add_entity(&q); entities.add_entity(&q);
for i in -3..3 { for i in 0..6 {
for j in -3..3 { for j in 0..6 {
world.clear(Point(i, j)); 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 // TODO: add way to break out of the loop by hitting a random key
simulate(&mut entities, &mut world, &mut board); simulate(&mut entities, &mut world, &mut board);
render(&entities, &world, &board); render(&entities, &world, &board);
sleep(time::Duration::from_millis(100)); sleep(time::Duration::from_millis(1000));
refresh(); refresh();
} }
endwin(); endwin();

Loading…
Cancel
Save