multiple goal ai
This commit is contained in:
+19
-20
@@ -10,40 +10,46 @@ pub trait AI {
|
|||||||
fn plan(&mut self, w: &World) {}
|
fn plan(&mut self, w: &World) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum AIGoal {
|
pub enum AIGoal {
|
||||||
Reach(Point),
|
Reach(Point),
|
||||||
|
//Pickup(Point),
|
||||||
|
//Drop(),
|
||||||
Idle,
|
Idle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AI for Ant {
|
impl AI for Ant {
|
||||||
fn plan(&mut self, w: &World) {
|
fn plan(&mut self, w: &World) {
|
||||||
if self.plan.len() == 0 {
|
// check last part of plan
|
||||||
self.plan = match self.goal {
|
if let Some(goal) = self.plan.last() {
|
||||||
|
match goal {
|
||||||
AIGoal::Reach(target) => {
|
AIGoal::Reach(target) => {
|
||||||
if &self.pos == &target {
|
if self.pos == *target {
|
||||||
self.goal = AIGoal::Idle;
|
self.plan.pop();
|
||||||
vec![]
|
|
||||||
} else {
|
|
||||||
astar(&self.pos, &target)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AIGoal::Idle => vec![],
|
AIGoal::Idle => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the next move for this ant
|
// return the next move for this ant
|
||||||
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand {
|
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 => {
|
AIGoal::Idle => {
|
||||||
let valid = w.get_valid_movements(&self.pos, b);
|
let valid = w.get_valid_movements(&self.pos, b);
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
valid.choose(&mut rng).cloned()
|
valid.choose(&mut rng).cloned()
|
||||||
}
|
}
|
||||||
AIGoal::Reach(_) => {
|
AIGoal::Reach(target) => {
|
||||||
let movement = self.plan.pop();
|
let mut movements = astar(&self.pos, &target);
|
||||||
movement
|
movements.pop()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,13 +61,6 @@ impl AI for Ant {
|
|||||||
w.update_occupied(&old_pos, &pos);
|
w.update_occupied(&old_pos, &pos);
|
||||||
} else {
|
} else {
|
||||||
w.clear(pos);
|
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 => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -40,8 +40,7 @@ impl_downcast!(Renderable);
|
|||||||
pub struct Ant {
|
pub struct Ant {
|
||||||
pub pos: Point,
|
pub pos: Point,
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
pub goal: AIGoal,
|
pub plan: Vec<AIGoal>,
|
||||||
pub plan: Vec<Point>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ant {
|
impl Ant {
|
||||||
@@ -50,7 +49,6 @@ impl Ant {
|
|||||||
pos: Point(x, y),
|
pos: Point(x, y),
|
||||||
id: 0,
|
id: 0,
|
||||||
plan: vec![],
|
plan: vec![],
|
||||||
goal: AIGoal::Idle,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -45,7 +45,9 @@ pub fn astar(start: &Point, goal: &Point) -> Vec<Point> {
|
|||||||
answer.push(current.clone());
|
answer.push(current.clone());
|
||||||
while came_from.contains_key(¤t) {
|
while came_from.contains_key(¤t) {
|
||||||
current = came_from[¤t].clone();
|
current = came_from[¤t].clone();
|
||||||
answer.push(current.clone());
|
if current != *start {
|
||||||
|
answer.push(current.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-5
@@ -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::point::Point;
|
||||||
use antf::lib::ai::AIGoal;
|
use antf::lib::ai::AIGoal;
|
||||||
use antf::lib::world::{World, simulate, render};
|
use antf::lib::world::{World, simulate, render};
|
||||||
use antf::lib::entity::{Entities, Ant};
|
use antf::lib::entity::{Entities, Ant, Food, FoodGenerator};
|
||||||
|
|
||||||
use ncurses::*;
|
use ncurses::*;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
@@ -12,7 +12,7 @@ use std::time;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_reach_astar() {
|
fn test_reach_astar() {
|
||||||
let mut board = init_screen();
|
let mut board = init_screen();//Screen::new(40,40);
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
|
|
||||||
let mut entities = Entities::new();
|
let mut entities = Entities::new();
|
||||||
@@ -22,7 +22,39 @@ fn test_reach_astar() {
|
|||||||
|
|
||||||
let a = entities.data.get_mut(&id).unwrap();
|
let a = entities.data.get_mut(&id).unwrap();
|
||||||
let ant: &mut Ant = a.downcast_mut::<Ant>().unwrap();
|
let ant: &mut Ant = a.downcast_mut::<Ant>().unwrap();
|
||||||
ant.goal = 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)));
|
||||||
|
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 =
|
||||||
|
|
||||||
for _ in 0..60 {
|
for _ in 0..60 {
|
||||||
// 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
|
||||||
@@ -33,4 +65,4 @@ fn test_reach_astar() {
|
|||||||
}
|
}
|
||||||
clear();
|
clear();
|
||||||
endwin();
|
endwin();
|
||||||
}
|
}*/
|
||||||
|
|||||||
Reference in New Issue
Block a user