sideways
Rostyslav Hnatyshyn 9 months ago
parent 1e3032c51b
commit 47c6eff011
  1. 39
      src/lib/ai.rs
  2. 1
      src/lib/entity.rs
  3. 43
      src/lib/world.rs
  4. 14
      src/main.rs

@ -12,7 +12,7 @@ pub trait AI {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum AIGoal { pub enum AIGoal {
Reach(Point), Seek,
//Pickup(Point), //Pickup(Point),
//Drop(), //Drop(),
Idle, Idle,
@ -23,8 +23,9 @@ impl AI for Ant {
// check last part of plan // check last part of plan
if let Some(goal) = self.plan.last() { if let Some(goal) = self.plan.last() {
match goal { match goal {
AIGoal::Reach(target) => { AIGoal::Seek => {
if self.pos == *target { // if we reach food, we change state
if w.food.contains(&self.pos) {
self.plan.pop(); self.plan.pop();
} }
} }
@ -40,31 +41,23 @@ impl AI for Ant {
None => &AIGoal::Idle, None => &AIGoal::Idle,
}; };
let choice = match goal { let valid = w.get_valid_movements(&self.pos, b, true);
AIGoal::Idle => { let mut rng = thread_rng();
// valid_movements does not return any diggables! let choice = valid.choose(&mut rng).cloned();
let valid = w.get_valid_movements(&self.pos, b, true);
let mut rng = thread_rng();
valid.choose(&mut rng).cloned()
}
AIGoal::Reach(target) => {
// here astar only produces a path between the target & pos without digging
let result = astar(&self.pos, &target, Some(w), Some(b));
let mut movements = match result {
Ok(m) => m,
Err(_) => vec![]
};
movements.pop()
}
};
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) {
self.pos = pos; self.pos = pos;
} else { } else {
if w.is_safe_to_dig(&pos, &b) {
w.clear(pos); match goal {
AIGoal::Seek => {
if w.is_safe_to_dig(&pos, &b) {
w.clear(pos);
}
},
AIGoal::Idle => {}
} }
} }
} }

@ -217,6 +217,7 @@ impl FoodGenerator {
impl AI for FoodGenerator { impl AI for FoodGenerator {
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand { fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand {
// eventually might want to use poisson disk distrib instead
if self.timer % 600 == 0 && self.counter < 10 { if self.timer % 600 == 0 && self.counter < 10 {
// generate random coords, if valid, spawn // generate random coords, if valid, spawn
// if not, try again next step // if not, try again next step

@ -6,7 +6,7 @@ use std::collections::HashSet;
#[derive(Clone)] #[derive(Clone)]
pub struct World { pub struct World {
pub cleared: HashSet<Point>, pub cleared: HashSet<Point>,
pub food: HashSet<u32>, pub food: HashSet<Point>,
} }
impl World { impl World {
@ -22,27 +22,27 @@ impl World {
} }
pub fn create_chamber(&mut self, center: Point, radius: i32) { pub fn create_chamber(&mut self, center: Point, radius: i32) {
let cx = center.0; let cx = center.0;
let cy = center.1; let cy = center.1;
for i in cx-radius..cx+radius { for i in cx - radius..cx + radius {
for j in cy-radius..cy+radius { for j in cy - radius..cy + radius {
self.clear(Point(i,j)); self.clear(Point(i, j));
} }
} }
} }
pub fn is_valid_movement(&self, current: &Point, target: &Point, b: &Screen) -> bool { pub fn is_valid_movement(&self, current: &Point, target: &Point, b: &Screen) -> bool {
// should allow down movements always // should allow down movements always
let safe = target.is_below(*current) || ( let safe = target.is_below(*current)
!self.cleared.contains(&target.down()) || (!self.cleared.contains(&target.down())
|| !self.cleared.contains(&target.left()) || !self.cleared.contains(&target.left())
|| !self.cleared.contains(&target.right()) || !self.cleared.contains(&target.right())
|| !self.cleared.contains(&target.bldiag()) || !self.cleared.contains(&target.bldiag())
|| !self.cleared.contains(&target.uldiag()) || !self.cleared.contains(&target.uldiag())
|| !self.cleared.contains(&target.brdiag()) || !self.cleared.contains(&target.brdiag())
|| !self.cleared.contains(&target.urdiag())); || !self.cleared.contains(&target.urdiag()));
// of course, its only a valid move if you can walk there! // of course, its only a valid move if you can walk there!
b.is_in_bounds(target) && self.cleared.contains(target) && safe b.is_in_bounds(target) && self.cleared.contains(target) && safe
@ -55,7 +55,7 @@ impl World {
pub fn is_safe_to_dig(&self, target: &Point, b: &Screen) -> bool { pub fn is_safe_to_dig(&self, target: &Point, b: &Screen) -> bool {
let mut hypothetical_world = self.clone(); let mut hypothetical_world = self.clone();
hypothetical_world.clear(*target); hypothetical_world.clear(*target);
let result = astar(target, &Point(0, 0), Some(&hypothetical_world), Some(b)); let result = astar(target, &b.center, Some(&hypothetical_world), Some(b));
b.is_in_bounds(target) && result.is_ok() b.is_in_bounds(target) && result.is_ok()
} }
@ -82,10 +82,12 @@ impl World {
.collect(); .collect();
if return_diggables { if return_diggables {
ans.extend(self.get_diggable(b, pos)); let digs = self.get_diggable(b, pos);
ans.extend(digs);
} }
ans ans
} }
} }
@ -131,6 +133,7 @@ pub fn simulate(e: &mut Entities, w: &mut World, b: &mut Screen) {
BoardCommand::SpawnFood(pos) => { BoardCommand::SpawnFood(pos) => {
let food = Food::new(pos.0, pos.1); let food = Food::new(pos.0, pos.1);
e.add_entity(&food); e.add_entity(&food);
w.food.insert(pos);
} }
BoardCommand::Noop => {} BoardCommand::Noop => {}
} }

@ -17,16 +17,24 @@ mod lib {
use lib::point::Point; use lib::point::Point;
use lib::screen::init_screen; use lib::screen::init_screen;
use lib::world::{World, simulate, render}; use lib::world::{World, simulate, render};
use lib::entity::{Entities, Queen}; use lib::entity::{Entities, Ant, FoodGenerator};
fn main() { fn main() {
let mut board = init_screen(); let mut board = init_screen();
let mut world = World::new(); let mut world = World::new();
let mut entities = Entities::new(); let mut entities = Entities::new();
let q = Queen::new(board.center.0,board.center.1);
entities.add_entity(&q);
//let q = Queen::new(board.center.0,board.center.1);
//entities.add_entity(&q);
let fg = FoodGenerator::new();
entities.add_entity(&fg);
let mut a = Ant::new(board.center.0, board.center.1);
a.plan.push(lib::ai::AIGoal::Seek);
entities.add_entity(&a);
world.create_chamber(Point(board.center.0, board.center.1), 3); world.create_chamber(Point(board.center.0, board.center.1), 3);
loop { loop {

Loading…
Cancel
Save