sideways #1
+40
-11
@@ -1,13 +1,14 @@
|
||||
use crate::lib::entity::{Ant, Egg, Queen};
|
||||
use crate::lib::point::{Direction, Point};
|
||||
use crate::lib::entity::{Ant, Egg, Food, FoodGenerator, Queen};
|
||||
use crate::lib::point::Point;
|
||||
use crate::lib::screen::{BoardCommand, Screen};
|
||||
use crate::lib::world::{Pheremone, World};
|
||||
use rand::Rng;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use std::iter::zip;
|
||||
|
||||
pub trait AI {
|
||||
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand;
|
||||
fn step(&mut self, b: &Screen, w: &mut World, step: u32) -> BoardCommand;
|
||||
fn plan(&mut self, b: &Screen, w: &mut World) -> BoardCommand {
|
||||
BoardCommand::Noop
|
||||
}
|
||||
@@ -29,8 +30,7 @@ impl AI for Ant {
|
||||
w.drop_pheremone(&p, &self.goal);
|
||||
}
|
||||
self.history.clear();
|
||||
self.cw();
|
||||
self.cw();
|
||||
self.about_face();
|
||||
self.goal = AIGoal::Return;
|
||||
}
|
||||
BoardCommand::Noop
|
||||
@@ -41,8 +41,7 @@ impl AI for Ant {
|
||||
w.drop_pheremone(&p, &self.goal);
|
||||
}
|
||||
self.history.clear();
|
||||
self.cw();
|
||||
self.cw();
|
||||
self.about_face();
|
||||
self.goal = AIGoal::Seek;
|
||||
return BoardCommand::SpawnAnt;
|
||||
} else {
|
||||
@@ -52,7 +51,7 @@ impl AI for Ant {
|
||||
}
|
||||
}
|
||||
|
||||
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand {
|
||||
fn step(&mut self, b: &Screen, w: &mut World, t: u32) -> BoardCommand {
|
||||
let valid = vec![
|
||||
(self.dir, self.dir.relative_point(&self.pos)),
|
||||
(self.dir.ccw(), self.dir.ccw().relative_point(&self.pos)),
|
||||
@@ -72,7 +71,7 @@ impl AI for Ant {
|
||||
let r: f32 = rand::random();
|
||||
|
||||
let mut dir = &valid[0].0;
|
||||
if r < 0.2 || ph.len() == 0 {
|
||||
if r < 0.1 || ph.len() == 0 {
|
||||
let mut rng = thread_rng();
|
||||
let choice = valid.choose(&mut rng).unwrap();
|
||||
dir = &choice.0;
|
||||
@@ -97,8 +96,27 @@ impl AI for Ant {
|
||||
}
|
||||
}
|
||||
|
||||
impl AI for FoodGenerator {
|
||||
fn step(&mut self, b: &Screen, w: &mut World, t: u32) -> BoardCommand {
|
||||
// eventually might want to use poisson disk distrib instead
|
||||
if t % 600 == 0 && self.counter < 10 {
|
||||
// generate random coords, if valid, spawn
|
||||
// if not, try again next step
|
||||
let (min, max) = b.get_dimensions();
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let r_x = rng.gen_range(min.0..max.0 + 1);
|
||||
let r_y = rng.gen_range(min.1..max.1 + 1);
|
||||
|
||||
self.counter += 1;
|
||||
return BoardCommand::SpawnFood(Point(r_x, r_y));
|
||||
}
|
||||
BoardCommand::Noop
|
||||
}
|
||||
}
|
||||
|
||||
impl AI for Egg {
|
||||
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand {
|
||||
fn step(&mut self, b: &Screen, w: &mut World, t: u32) -> BoardCommand {
|
||||
if self.counter > 0 {
|
||||
self.counter -= 1;
|
||||
return BoardCommand::Noop;
|
||||
@@ -109,7 +127,7 @@ impl AI for Egg {
|
||||
}
|
||||
|
||||
impl AI for Queen {
|
||||
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand {
|
||||
fn step(&mut self, b: &Screen, w: &mut World, t: u32) -> BoardCommand {
|
||||
let valid: Vec<Point> = self.pos.get_neighbors();
|
||||
let mut rng = thread_rng();
|
||||
|
||||
@@ -128,3 +146,14 @@ impl AI for Queen {
|
||||
BoardCommand::Noop
|
||||
}
|
||||
}
|
||||
|
||||
impl AI for Food {
|
||||
fn step(&mut self, b: &Screen, w: &mut World, t: u32) -> BoardCommand {
|
||||
for n in self.pos.get_neighbors() {
|
||||
w.drop_pheremone(&n, &AIGoal::Return);
|
||||
}
|
||||
w.drop_pheremone(&self.pos, &AIGoal::Return);
|
||||
|
||||
BoardCommand::Noop
|
||||
}
|
||||
}
|
||||
|
||||
+9
-37
@@ -1,8 +1,6 @@
|
||||
use crate::lib::ai::{AIGoal, AI};
|
||||
use crate::lib::point::{Direction, Point};
|
||||
use crate::lib::screen::{BoardCommand, Screen};
|
||||
use crate::lib::world::World;
|
||||
use rand::Rng;
|
||||
use crate::lib::screen::Screen;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
@@ -75,6 +73,11 @@ impl Ant {
|
||||
pub fn cw(&mut self) {
|
||||
self.dir = self.dir.cw();
|
||||
}
|
||||
|
||||
pub fn about_face(&mut self) {
|
||||
self.cw();
|
||||
self.cw();
|
||||
}
|
||||
}
|
||||
|
||||
impl_entity!(Ant);
|
||||
@@ -211,7 +214,7 @@ impl Entities {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Food {
|
||||
pos: Point,
|
||||
pub pos: Point,
|
||||
id: u32,
|
||||
}
|
||||
|
||||
@@ -224,17 +227,6 @@ impl Food {
|
||||
}
|
||||
}
|
||||
|
||||
impl AI for Food {
|
||||
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand {
|
||||
for n in self.pos.get_neighbors() {
|
||||
w.drop_pheremone(&n, &AIGoal::Seek);
|
||||
}
|
||||
w.drop_pheremone(&self.pos, &AIGoal::Seek);
|
||||
|
||||
BoardCommand::Noop
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderable for Food {
|
||||
fn representation(&self) -> &str {
|
||||
"f"
|
||||
@@ -244,10 +236,10 @@ impl Renderable for Food {
|
||||
// no position, does not get rendered yet acts per turn
|
||||
#[derive(Clone)]
|
||||
pub struct FoodGenerator {
|
||||
timer: u32,
|
||||
pub timer: u32,
|
||||
pos: Point,
|
||||
id: u32,
|
||||
counter: u32,
|
||||
pub counter: u32,
|
||||
}
|
||||
|
||||
impl FoodGenerator {
|
||||
@@ -261,26 +253,6 @@ impl FoodGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
impl AI for FoodGenerator {
|
||||
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 {
|
||||
// generate random coords, if valid, spawn
|
||||
// if not, try again next step
|
||||
let (min, max) = b.get_dimensions();
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let r_x = rng.gen_range(min.0..max.0 + 1);
|
||||
let r_y = rng.gen_range(min.1..max.1 + 1);
|
||||
|
||||
self.counter += 1;
|
||||
return BoardCommand::SpawnFood(Point(r_x, r_y));
|
||||
}
|
||||
self.timer += 1;
|
||||
BoardCommand::Noop
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderable for FoodGenerator {
|
||||
fn render(&self, b: &Screen) {}
|
||||
}
|
||||
|
||||
@@ -36,15 +36,6 @@ impl Screen {
|
||||
(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> {
|
||||
let binding = pos.get_neighbors();
|
||||
binding
|
||||
.iter()
|
||||
.filter(|e| self.is_in_bounds(e))
|
||||
.map(|e| e.clone())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn render(&self, p: &Point, char: &str) {
|
||||
mvprintw(p.1, p.0, char);
|
||||
}
|
||||
|
||||
+2
-2
@@ -81,7 +81,7 @@ pub fn render(e: &Entities, w: &World, b: &Screen) {
|
||||
|
||||
pub fn simulate(e: &mut Entities, w: &mut World, b: &mut Screen, step: u32) {
|
||||
let plan_cmds: Vec<BoardCommand> = e.data.values_mut().map(|a| a.plan(b, w)).collect();
|
||||
let mut cmds: Vec<BoardCommand> = e.data.values_mut().map(|a| a.step(b, w)).collect();
|
||||
let mut cmds: Vec<BoardCommand> = e.data.values_mut().map(|a| a.step(b, w, step)).collect();
|
||||
|
||||
cmds.extend(plan_cmds);
|
||||
|
||||
@@ -115,7 +115,7 @@ pub fn simulate(e: &mut Entities, w: &mut World, b: &mut Screen, step: u32) {
|
||||
}
|
||||
|
||||
// decay all pheremones by some amount
|
||||
if step % 60 == 0 {
|
||||
if step % 600 == 0 {
|
||||
for ph in w.pheremones.iter_mut() {
|
||||
ph.decay();
|
||||
}
|
||||
|
||||
@@ -26,9 +26,6 @@ fn main() {
|
||||
|
||||
let mut entities = Entities::new();
|
||||
|
||||
//let q = Queen::new(board.center.0,board.center.1);
|
||||
//entities.add_entity(&q);
|
||||
|
||||
let fg = FoodGenerator::new();
|
||||
entities.add_entity(&fg);
|
||||
|
||||
@@ -38,8 +35,6 @@ fn main() {
|
||||
entities.add_entity(&a);
|
||||
}
|
||||
|
||||
//world.create_chamber(Point(board.center.0, board.center.1), 3);
|
||||
|
||||
let mut t = 0;
|
||||
loop {
|
||||
// TODO: add way to break out of the loop by hitting a random key
|
||||
|
||||
Reference in New Issue
Block a user