multiple goal ai

master
Rostyslav Hnatyshyn 9 months ago
parent 1487614e86
commit 164030424d
  1. 39
      src/lib/ai.rs
  2. 4
      src/lib/entity.rs
  3. 4
      src/lib/point.rs
  4. 40
      tests/ai_test.rs

@ -10,40 +10,46 @@ pub trait AI {
fn plan(&mut self, w: &World) {}
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub enum AIGoal {
Reach(Point),
//Pickup(Point),
//Drop(),
Idle,
}
impl AI for Ant {
fn plan(&mut self, w: &World) {
if self.plan.len() == 0 {
self.plan = match self.goal {
// check last part of plan
if let Some(goal) = self.plan.last() {
match goal {
AIGoal::Reach(target) => {
if &self.pos == &target {
self.goal = AIGoal::Idle;
vec![]
} else {
astar(&self.pos, &target)
if self.pos == *target {
self.plan.pop();
}
}
AIGoal::Idle => vec![],
AIGoal::Idle => {}
}
}
}
// return the next move for this ant
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand {
let choice = match self.goal {
let goal = match self.plan.last() {
Some(g) => g,
None => &AIGoal::Idle,
};
let choice = match goal {
AIGoal::Idle => {
let valid = w.get_valid_movements(&self.pos, b);
let mut rng = thread_rng();
valid.choose(&mut rng).cloned()
}
AIGoal::Reach(_) => {
let movement = self.plan.pop();
movement
AIGoal::Reach(target) => {
let mut movements = astar(&self.pos, &target);
movements.pop()
}
};
@ -55,13 +61,6 @@ impl AI for Ant {
w.update_occupied(&old_pos, &pos);
} else {
w.clear(pos);
match self.goal {
// push plan back because we haven't actually moved towards it
AIGoal::Reach(_) => {
self.plan.push(pos);
}
AIGoal::Idle => {}
}
}
}

@ -40,8 +40,7 @@ impl_downcast!(Renderable);
pub struct Ant {
pub pos: Point,
pub id: u32,
pub goal: AIGoal,
pub plan: Vec<Point>,
pub plan: Vec<AIGoal>,
}
impl Ant {
@ -50,7 +49,6 @@ impl Ant {
pos: Point(x, y),
id: 0,
plan: vec![],
goal: AIGoal::Idle,
}
}
}

@ -45,7 +45,9 @@ pub fn astar(start: &Point, goal: &Point) -> Vec<Point> {
answer.push(current.clone());
while came_from.contains_key(&current) {
current = came_from[&current].clone();
answer.push(current.clone());
if current != *start {
answer.push(current.clone());
}
}
break;
}

@ -1,8 +1,8 @@
use antf::lib::screen::init_screen;
use antf::lib::screen::{Screen, init_screen};
use antf::lib::point::Point;
use antf::lib::ai::AIGoal;
use antf::lib::world::{World, simulate, render};
use antf::lib::entity::{Entities, Ant};
use antf::lib::entity::{Entities, Ant, Food, FoodGenerator};
use ncurses::*;
use std::thread::sleep;
@ -12,17 +12,49 @@ use std::time;
#[test]
fn test_reach_astar() {
let mut board = init_screen();//Screen::new(40,40);
let mut world = World::new();
let mut entities = Entities::new();
let a = Ant::new(0,0);
let id = entities.add_entity(&a);
let a = entities.data.get_mut(&id).unwrap();
let ant: &mut Ant = a.downcast_mut::<Ant>().unwrap();
ant.plan.push(AIGoal::Reach(Point(10,10)));
ant.plan.push(AIGoal::Reach(Point(-10,-10)));
ant.plan.push(AIGoal::Reach(Point(10,-10)));
ant.plan.push(AIGoal::Reach(Point(-10,10)));
// craps out... need to make sure unwrap() is safe
for _ in 0..420 {
// 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));
refresh();
}
clear();
endwin();
}
/*#[test]
fn test_drag() {
let mut board = init_screen();
let mut world = World::new();
let mut entities = Entities::new();
let f = Food::new(10,10);
let a = Ant::new(0,0);
let fid = entities.add_entity(&f);
let id = entities.add_entity(&a);
let a = entities.data.get_mut(&id).unwrap();
let ant: &mut Ant = a.downcast_mut::<Ant>().unwrap();
ant.goal = AIGoal::Reach(Point(10,10));
//ant.goal =
for _ in 0..60 {
// TODO: add way to break out of the loop by hitting a random key
@ -33,4 +65,4 @@ fn test_reach_astar() {
}
clear();
endwin();
}
}*/

Loading…
Cancel
Save