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, pub food: HashSet, pub home: HashSet, 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 = 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 = e.data.values_mut().map(|a| a.plan(b, w)).collect(); let mut cmds: Vec = 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::().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(); } } }