collisions but queen can't spawn more than 3
This commit is contained in:
+77
-47
@@ -67,33 +67,49 @@ impl World {
|
||||
|
||||
fn get_valid_movements(&self, pos: &Point, b: &Board) -> Vec<Point> {
|
||||
let moves = b.get_valid_movements(pos);
|
||||
moves.iter().filter(|p| !self.occupied.contains(p)).map(|p| p.clone()).collect()
|
||||
moves
|
||||
.iter()
|
||||
.filter(|p| !self.occupied.contains(p))
|
||||
.map(|p| p.clone())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
trait Entity: AI + Renderable {}
|
||||
|
||||
struct Colony {
|
||||
ants: HashMap<Point, Box<dyn Entity>>,
|
||||
ants: HashMap<u32, Box<dyn Entity>>,
|
||||
id_counter: u32,
|
||||
}
|
||||
|
||||
impl Colony {
|
||||
fn new() -> Colony {
|
||||
Colony {
|
||||
ants: HashMap::new(),
|
||||
id_counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_entity<T: Entity + 'static>(&mut self, pos: &Point, e: T) {
|
||||
self.ants.insert(*pos, Box::new(e));
|
||||
fn add_entity<T: Entity + 'static>(&mut self, e: T) {
|
||||
self.ants.insert(self.id_counter, Box::new(e));
|
||||
self.id_counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
trait AI {
|
||||
fn step(&mut self, pos: &Point, b: &Board, w: &World) -> BoardCommand;
|
||||
fn step(&mut self, id: u32, b: &Board, w: &World) -> BoardCommand;
|
||||
fn get_position(&self) -> Point;
|
||||
}
|
||||
|
||||
struct Ant {}
|
||||
struct Ant {
|
||||
pos: Point,
|
||||
}
|
||||
|
||||
impl Ant {
|
||||
fn new(x: i32, y: i32) -> Ant {
|
||||
Ant { pos: Point(x, y) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for Ant {}
|
||||
|
||||
@@ -104,6 +120,7 @@ impl Renderable for Ant {
|
||||
}
|
||||
|
||||
struct Queen {
|
||||
pos: Point,
|
||||
egg_count: u8,
|
||||
}
|
||||
|
||||
@@ -120,13 +137,17 @@ trait Renderable {
|
||||
}
|
||||
|
||||
impl Queen {
|
||||
fn new() -> Queen {
|
||||
Queen { egg_count: 0 }
|
||||
fn new(x: i32, y: i32) -> Queen {
|
||||
Queen {
|
||||
pos: Point(x, y),
|
||||
egg_count: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Egg {
|
||||
pos: Point,
|
||||
counter: u8,
|
||||
}
|
||||
|
||||
@@ -137,34 +158,43 @@ impl Renderable for Egg {
|
||||
}
|
||||
|
||||
impl Egg {
|
||||
fn new() -> Egg {
|
||||
Egg { counter: 10 }
|
||||
}
|
||||
}
|
||||
|
||||
impl AI for Egg {
|
||||
fn step(&mut self, p: &Point, b: &Board, w: &World) -> BoardCommand {
|
||||
if self.counter > 0 {
|
||||
self.counter -= 1;
|
||||
return BoardCommand::Noop;
|
||||
} else {
|
||||
BoardCommand::Hatch(*p)
|
||||
fn new(x: i32, y: i32) -> Egg {
|
||||
Egg {
|
||||
pos: Point(x, y),
|
||||
counter: 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AI for Egg {
|
||||
fn step(&mut self, id: u32, b: &Board, w: &World) -> BoardCommand {
|
||||
if self.counter > 0 {
|
||||
self.counter -= 1;
|
||||
return BoardCommand::Noop;
|
||||
} else {
|
||||
BoardCommand::Hatch(id)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_position(&self) -> Point {
|
||||
self.pos.clone()
|
||||
}
|
||||
}
|
||||
|
||||
enum BoardCommand {
|
||||
Move(Point, Point),
|
||||
Dig(Point),
|
||||
LayEgg(Point),
|
||||
Hatch(Point),
|
||||
Hatch(u32),
|
||||
Noop,
|
||||
}
|
||||
|
||||
impl AI for Ant {
|
||||
fn get_position(&self) -> Point {
|
||||
self.pos.clone()
|
||||
}
|
||||
// return the next move for this ant
|
||||
fn step(&mut self, p: &Point, b: &Board, w: &World) -> BoardCommand {
|
||||
let valid = w.get_valid_movements(p, b);
|
||||
fn step(&mut self, id: u32, b: &Board, w: &World) -> BoardCommand {
|
||||
let valid = w.get_valid_movements(&self.pos, b);
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let choice = valid.choose(&mut rng).cloned();
|
||||
@@ -174,7 +204,8 @@ impl AI for Ant {
|
||||
} else {
|
||||
let pos = choice.unwrap();
|
||||
if w.cleared.contains(&pos) {
|
||||
return BoardCommand::Move(*p, pos);
|
||||
self.pos = pos;
|
||||
return BoardCommand::Noop;
|
||||
} else {
|
||||
return BoardCommand::Dig(pos);
|
||||
}
|
||||
@@ -186,9 +217,13 @@ impl Entity for Queen {}
|
||||
impl Entity for Egg {}
|
||||
|
||||
impl AI for Queen {
|
||||
fn step(&mut self, p: &Point, b: &Board, w: &World) -> BoardCommand {
|
||||
let valid: Vec<Point> = w.get_valid_movements(p, b);
|
||||
fn get_position(&self) -> Point {
|
||||
self.pos.clone()
|
||||
}
|
||||
fn step(&mut self, id: u32, b: &Board, w: &World) -> BoardCommand {
|
||||
let valid: Vec<Point> = w.get_valid_movements(&self.pos, b);
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let choice = valid.choose(&mut rng).cloned();
|
||||
|
||||
if choice.is_none() {
|
||||
@@ -201,7 +236,8 @@ impl AI for Queen {
|
||||
self.egg_count += 1;
|
||||
return BoardCommand::LayEgg(pos);
|
||||
} else {
|
||||
return BoardCommand::Move(*p, pos);
|
||||
self.pos = pos;
|
||||
return BoardCommand::Noop;
|
||||
}
|
||||
} else {
|
||||
return BoardCommand::Noop;
|
||||
@@ -215,7 +251,8 @@ fn render(c: &Colony, w: &World, b: &Board) {
|
||||
mvprintw(c.1 + b.center.1, c.0 + b.center.0, "x");
|
||||
}
|
||||
|
||||
for (pos, a) in c.ants.iter() {
|
||||
for a in c.ants.values() {
|
||||
let pos = a.get_position();
|
||||
mvprintw(pos.1 + b.center.1, pos.0 + b.center.0, a.render());
|
||||
}
|
||||
}
|
||||
@@ -239,35 +276,26 @@ mod tests {
|
||||
}
|
||||
|
||||
fn simulate(c: &mut Colony, w: &mut World, b: &mut Board) {
|
||||
let cmds: Vec<BoardCommand> = c
|
||||
.ants
|
||||
.iter_mut()
|
||||
.map(|(p, a)| {
|
||||
a.step(&p, b, &w)
|
||||
})
|
||||
.collect();
|
||||
let cmds: Vec<BoardCommand> = c.ants.iter_mut().map(|(id, a)| a.step(*id, b, &w)).collect();
|
||||
|
||||
for cmd in cmds {
|
||||
match cmd {
|
||||
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(&pos, Egg::new());
|
||||
c.add_entity(Egg::new(pos.0, pos.1));
|
||||
}
|
||||
BoardCommand::Hatch(pos) => {
|
||||
c.ants.remove(&pos);
|
||||
c.add_entity(&pos, Ant {});
|
||||
BoardCommand::Hatch(egg_id) => {
|
||||
let egg = c.ants.remove(&egg_id);
|
||||
let pos = egg.unwrap().get_position();
|
||||
c.add_entity(Ant::new(pos.0, pos.1));
|
||||
}
|
||||
BoardCommand::Noop => {}
|
||||
}
|
||||
}
|
||||
w.occupied.clear();
|
||||
let _ = c.ants.keys().map(|p| w.occupied.insert(*p));
|
||||
let _ = c.ants.values().map(|p| w.occupied.insert(p.get_position()));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -285,7 +313,11 @@ fn main() {
|
||||
|
||||
let mut board = Board::new(max_x, max_y);
|
||||
let mut world = World::new();
|
||||
|
||||
let q = Queen::new(0,0);
|
||||
|
||||
let mut colony = Colony::new();
|
||||
colony.add_entity(q);
|
||||
|
||||
for i in -3..3 {
|
||||
for j in -3..3 {
|
||||
@@ -293,8 +325,6 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
colony.add_entity(&Point(0, 0), Queen::new());
|
||||
|
||||
loop {
|
||||
// TODO: add way to break out of the loop by hitting a random key
|
||||
simulate(&mut colony, &mut world, &mut board);
|
||||
|
||||
Reference in New Issue
Block a user