simple ant colony program written in rust i originally started with C but then started to miss data structures so I re-wrote it in rust
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
antf/src/lib/world.rs

123 lines
3.3 KiB

use crate::lib::ai::AIGoal;
use crate::lib::entity::{Ant, Egg, Entities, Food, Queen};
use crate::lib::point::Point;
use crate::lib::screen::{BoardCommand, Screen};
use std::collections::HashSet;
use ncurses::*;
#[derive(Clone)]
pub struct World {
pub pheremones: Vec<Pheremone>,
pub food: HashSet<Point>,
pub home: HashSet<Point>,
width: usize,
}
#[derive(Clone, PartialEq, PartialOrd, Debug)]
pub struct Pheremone {
pub home: u32,
pub food: u32,
}
impl Pheremone {
pub fn new() -> Pheremone {
Pheremone { home: 0, food: 0 }
}
pub fn decay(&mut self) {
if self.home > 0 {
self.home -= 1;
}
if self.food > 0 {
self.food -= 1;
}
}
}
impl World {
pub fn new(grid_size: &Point) -> World {
let x = grid_size.0;
let y = grid_size.1;
let ph: Vec<Pheremone> = vec![Pheremone::new(); (x+1) as usize * (y+1) as usize];
World {
pheremones: ph,
food: HashSet::new(),
home: HashSet::new(), // should be a property per colony
width: (y as usize), // width of map for Pheremone calculation
}
}
pub fn get_mut_pheremone(&mut self, pos: &Point) -> &mut Pheremone {
&mut self.pheremones[((pos.0 as usize) * self.width) + (pos.1 as usize)]
}
pub fn get_pheremone(&self, pos: &Point) -> &Pheremone {
&self.pheremones[((pos.0 as usize) * self.width) + (pos.1 as usize)]
}
pub fn drop_pheremone(&mut self, pos: &Point, state: &AIGoal) {
let ph = self.get_mut_pheremone(pos);
match state {
AIGoal::Seek => ph.home += 1,
AIGoal::Return => ph.food += 1,
}
}
}
pub fn render(e: &Entities, w: &World, b: &Screen) {
erase();
for h in w.home.iter() {
b.render(h, "x");
}
for a in e.data.values() {
a.render(b);
}
}
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, step)).collect();
cmds.extend(plan_cmds);
for cmd in cmds {
match cmd {
BoardCommand::SpawnAnt => {
let ant = Ant::new(b.center.0, b.center.1);
e.add_entity(&ant);
}
BoardCommand::LayEgg(pos, id) => {
let egg = Egg::new(pos.0, pos.1, id);
e.add_entity(&egg);
}
BoardCommand::Hatch(egg_id, queen_id) => {
let egg = e.data.remove(&egg_id);
let pos = egg.unwrap().get_position();
let q = e.data.get_mut(&queen_id).unwrap();
let queen: &mut Queen = q.downcast_mut::<Queen>().unwrap();
queen.egg_count -= 1;
let ant = Ant::new(pos.0, pos.1);
e.add_entity(&ant);
}
BoardCommand::SpawnFood(pos) => {
let food = Food::new(pos.0, pos.1);
e.add_entity(&food);
w.food.insert(pos);
}
BoardCommand::Noop => {}
}
}
// decay all pheremones by some amount
if step % 600 == 0 {
for ph in w.pheremones.iter_mut() {
ph.decay();
}
}
}