From 04f4a91c0ed707bb017a8c7ff39dcce84bb6e57f Mon Sep 17 00:00:00 2001 From: Rostyslav Hnatyshyn Date: Tue, 2 Jan 2024 15:12:15 -0700 Subject: [PATCH] works but ants overwrite eachother --- src/main.rs | 164 +++++++++++++++++++++++++++------------------------- 1 file changed, 85 insertions(+), 79 deletions(-) diff --git a/src/main.rs b/src/main.rs index cd8daff..a833a04 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ extern crate ncurses; use ncurses::*; use rand::seq::SliceRandom; use rand::thread_rng; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::thread::sleep; use std::time; @@ -50,112 +50,121 @@ impl Board { #[derive(Clone)] struct World { cleared: HashSet, + occupied: HashSet, } impl World { fn new() -> World { World { cleared: HashSet::new(), + occupied: HashSet::new(), } } fn clear(&mut self, pos: Point) { self.cleared.insert(pos); } + + fn get_valid_movements(&self, pos: &Point, b: &Board) -> Vec { + let moves = b.get_valid_movements(pos); + moves.iter().filter(|p| !self.occupied.contains(p)).map(|p| p.clone()).collect() + } } +trait Entity: AI + Renderable {} + struct Colony { - ants: Vec>, + ants: HashMap>, } impl Colony { fn new() -> Colony { - Colony { ants: vec![] } - } - - fn add_ant(&mut self, x: i32, y: i32) { - self.ants.push(Box::new(Ant::new(x, y))); + Colony { + ants: HashMap::new(), + } } - fn add_entity(&mut self, e: T) { - self.ants.push(Box::new(e)); + fn add_entity(&mut self, pos: &Point, e: T) { + self.ants.insert(*pos, Box::new(e)); } } trait AI { - fn step(&mut self, b: &Board, w: &World) -> BoardCommand; - fn get_position(&self) -> Point; - fn set_position(&mut self, p: Point); + fn step(&mut self, pos: &Point, b: &Board, w: &World) -> BoardCommand; } -struct Ant { - pos: Point, -} +struct Ant {} -impl Ant { - fn new(x: i32, y: i32) -> Ant { - Ant { pos: Point(x, y) } +impl Entity for Ant {} + +impl Renderable for Ant { + fn render(&self) -> &str { + "o" } } struct Queen { - pos: Point, egg_count: u8, } +impl Renderable for Queen { + fn render(&self) -> &str { + "q" + } +} + +trait Renderable { + fn render(&self) -> &str { + "z" + } +} + impl Queen { - fn new(x: i32, y: i32) -> Queen { - Queen { - pos: Point(x, y), - egg_count: 0, - } + fn new() -> Queen { + Queen { egg_count: 0 } } } #[derive(Debug)] struct Egg { - pos: Point, counter: u8, } +impl Renderable for Egg { + fn render(&self) -> &str { + "e" + } +} + impl Egg { - fn new(x: i32, y: i32) -> Egg { - Egg { - pos: Point(x, y), - counter: 10, - } + fn new() -> Egg { + Egg { counter: 10 } } } impl AI for Egg { - fn step(&mut self, b: &Board, w: &World) -> BoardCommand { + fn step(&mut self, p: &Point, b: &Board, w: &World) -> BoardCommand { if self.counter > 0 { self.counter -= 1; return BoardCommand::Noop; } else { - BoardCommand::Hatch + BoardCommand::Hatch(*p) } } - fn get_position(&self) -> Point { - self.pos.clone() - } - fn set_position(&mut self, p: Point) { - self.pos = p; - } } -enum BoardCommand<'a> { - Move(Box<&'a mut dyn AI>, Point), +enum BoardCommand { + Move(Point, Point), Dig(Point), LayEgg(Point), - Hatch, + Hatch(Point), Noop, } impl AI for Ant { // return the next move for this ant - fn step(&mut self, b: &Board, w: &World) -> BoardCommand { - let valid = b.get_valid_movements(&self.pos); + fn step(&mut self, p: &Point, b: &Board, w: &World) -> BoardCommand { + let valid = w.get_valid_movements(p, b); let mut rng = thread_rng(); let choice = valid.choose(&mut rng).cloned(); @@ -165,25 +174,20 @@ impl AI for Ant { } else { let pos = choice.unwrap(); if w.cleared.contains(&pos) { - return BoardCommand::Move(Box::new(self), pos); + return BoardCommand::Move(*p, pos); } else { return BoardCommand::Dig(pos); } } } - - fn get_position(&self) -> Point { - self.pos.clone() - } - - fn set_position(&mut self, p: Point) { - self.pos = p - } } +impl Entity for Queen {} +impl Entity for Egg {} + impl AI for Queen { - fn step(&mut self, b: &Board, w: &World) -> BoardCommand { - let valid = b.get_valid_movements(&self.pos); + fn step(&mut self, p: &Point, b: &Board, w: &World) -> BoardCommand { + let valid: Vec = w.get_valid_movements(p, b); let mut rng = thread_rng(); let choice = valid.choose(&mut rng).cloned(); @@ -194,24 +198,16 @@ impl AI for Queen { if w.cleared.contains(&pos) { // choose between laying an egg and moving if self.egg_count < 3 { - self.egg_count -= 1; + self.egg_count += 1; return BoardCommand::LayEgg(pos); } else { - return BoardCommand::Move(Box::new(self), pos); + return BoardCommand::Move(*p, pos); } } else { return BoardCommand::Noop; } } } - - fn get_position(&self) -> Point { - self.pos.clone() - } - - fn set_position(&mut self, p: Point) { - self.pos = p - } } fn render(c: &Colony, w: &World, b: &Board) { @@ -219,9 +215,8 @@ fn render(c: &Colony, w: &World, b: &Board) { mvprintw(c.1 + b.center.1, c.0 + b.center.0, "x"); } - for a in c.ants.iter() { - let pos = a.get_position(); - mvprintw(pos.1 + b.center.1, pos.0 + b.center.0, "o"); + for (pos, a) in c.ants.iter() { + mvprintw(pos.1 + b.center.1, pos.0 + b.center.0, a.render()); } } @@ -240,33 +235,39 @@ mod tests { dbg!(board.is_in_bounds(&Point(0, 0))); dbg!(board.get_valid_movements(&Point(0, 0))); - - let mut ant = Ant { pos: Point(0, 0) }; - } } -use std::iter::zip; - fn simulate(c: &mut Colony, w: &mut World, b: &mut Board) { - let world = w.clone(); - let cmds: Vec = c.ants.iter_mut().map(|a| a.step(b, &world)).collect(); + let cmds: Vec = c + .ants + .iter_mut() + .map(|(p, a)| { + a.step(&p, b, &w) + }) + .collect(); for cmd in cmds { match cmd { - BoardCommand::Move(a, pos) => { - a.set_position(pos); + BoardCommand::Move(old_pos, pos) => { + let a = c.ants.remove(&old_pos).unwrap(); + c.ants.insert(pos, a); } BoardCommand::Dig(pos) => { w.clear(pos); } BoardCommand::LayEgg(pos) => { - //c.add_entity(Egg::new(pos.0, pos.1)); + c.add_entity(&pos, Egg::new()); + } + BoardCommand::Hatch(pos) => { + c.ants.remove(&pos); + c.add_entity(&pos, Ant {}); } - BoardCommand::Hatch => {} BoardCommand::Noop => {} } } + w.occupied.clear(); + let _ = c.ants.keys().map(|p| w.occupied.insert(*p)); } fn main() { @@ -286,8 +287,13 @@ fn main() { let mut world = World::new(); let mut colony = Colony::new(); - colony.add_ant(0,0); + for i in -3..3 { + for j in -3..3 { + world.clear(Point(i, j)); + } + } + colony.add_entity(&Point(0, 0), Queen::new()); loop { // TODO: add way to break out of the loop by hitting a random key