ai goal - reach works
This commit is contained in:
+37
-5
@@ -1,5 +1,5 @@
|
|||||||
use crate::lib::entity::{Ant, Egg, Queen};
|
use crate::lib::entity::{Ant, Egg, Queen};
|
||||||
use crate::lib::point::Point;
|
use crate::lib::point::{astar, Point};
|
||||||
use crate::lib::screen::{BoardCommand, Screen};
|
use crate::lib::screen::{BoardCommand, Screen};
|
||||||
use crate::lib::world::World;
|
use crate::lib::world::World;
|
||||||
use rand::prelude::SliceRandom;
|
use rand::prelude::SliceRandom;
|
||||||
@@ -8,18 +8,42 @@ use rand::thread_rng;
|
|||||||
pub trait AI {
|
pub trait AI {
|
||||||
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand;
|
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand;
|
||||||
fn get_position(&self) -> Point;
|
fn get_position(&self) -> Point;
|
||||||
|
fn plan(&mut self, w: &World) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum AIGoal {
|
||||||
|
Reach(Point),
|
||||||
|
Idle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AI for Ant {
|
impl AI for Ant {
|
||||||
fn get_position(&self) -> Point {
|
fn get_position(&self) -> Point {
|
||||||
self.pos.clone()
|
self.pos.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn plan(&mut self, w: &World) {
|
||||||
|
if self.plan.len() == 0 {
|
||||||
|
self.plan = match self.goal {
|
||||||
|
AIGoal::Reach(target) => astar(&self.pos, &target),
|
||||||
|
AIGoal::Idle => vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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 valid = w.get_valid_movements(&self.pos, b);
|
let choice = match self.goal {
|
||||||
let mut rng = thread_rng();
|
AIGoal::Idle => {
|
||||||
|
let valid = w.get_valid_movements(&self.pos, b);
|
||||||
let choice = valid.choose(&mut rng).cloned();
|
let mut rng = thread_rng();
|
||||||
|
valid.choose(&mut rng).cloned()
|
||||||
|
},
|
||||||
|
AIGoal::Reach(_) => {
|
||||||
|
let movement = self.plan.pop();
|
||||||
|
movement
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
if !choice.is_none() {
|
if !choice.is_none() {
|
||||||
let pos = choice.unwrap();
|
let pos = choice.unwrap();
|
||||||
@@ -29,8 +53,16 @@ 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 {
|
||||||
|
AIGoal::Reach(_) => {
|
||||||
|
self.plan.push(pos);
|
||||||
|
}
|
||||||
|
AIGoal::Idle => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// need to check if progress has been made towards the plan
|
||||||
BoardCommand::Noop
|
BoardCommand::Noop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -1,6 +1,7 @@
|
|||||||
use crate::lib::ai::AI;
|
use crate::lib::ai::{AI, AIGoal};
|
||||||
use crate::lib::point::Point;
|
use crate::lib::point::Point;
|
||||||
use crate::lib::screen::Screen;
|
use crate::lib::screen::Screen;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use ncurses::*;
|
use ncurses::*;
|
||||||
@@ -13,6 +14,8 @@ impl_downcast!(Entity);
|
|||||||
pub struct Ant {
|
pub struct Ant {
|
||||||
pub pos: Point,
|
pub pos: Point,
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
|
pub goal: AIGoal,
|
||||||
|
pub plan: Vec<Point>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ant {
|
impl Ant {
|
||||||
@@ -20,6 +23,8 @@ impl Ant {
|
|||||||
Ant {
|
Ant {
|
||||||
pos: Point(x, y),
|
pos: Point(x, y),
|
||||||
id,
|
id,
|
||||||
|
plan: vec![],
|
||||||
|
goal: AIGoal::Idle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ fn manhattan(c1: &Point, c2: &Point) -> i32 {
|
|||||||
return (c2.0 - c1.0).abs() + (c2.1 - c1.1).abs();
|
return (c2.0 - c1.0).abs() + (c2.1 - c1.1).abs();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn astar(start: &Point, goal: &Point) -> Vec<Point> {
|
pub fn astar(start: &Point, goal: &Point) -> Vec<Point> {
|
||||||
let mut open_set : HashSet<Point> = HashSet::new();
|
let mut open_set : HashSet<Point> = HashSet::new();
|
||||||
open_set.insert(*start);
|
open_set.insert(*start);
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -21,6 +21,10 @@ impl World {
|
|||||||
self.cleared.insert(pos);
|
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 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
|
||||||
@@ -50,7 +54,10 @@ pub fn simulate(e: &mut Entities, w: &mut World, b: &mut Screen) {
|
|||||||
let cmds: Vec<BoardCommand> = e
|
let cmds: Vec<BoardCommand> = e
|
||||||
.data
|
.data
|
||||||
.values_mut()
|
.values_mut()
|
||||||
.map(|a| a.step(b, w))
|
.map(|a| {
|
||||||
|
a.plan(w);
|
||||||
|
a.step(b, w)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for cmd in cmds {
|
for cmd in cmds {
|
||||||
|
|||||||
Reference in New Issue
Block a user