|
|
@ -1,6 +1,8 @@ |
|
|
|
use crate::lib::ai::{AI, AIGoal}; |
|
|
|
use crate::lib::ai::{AIGoal, AI}; |
|
|
|
use crate::lib::point::Point; |
|
|
|
use crate::lib::point::Point; |
|
|
|
use crate::lib::screen::Screen; |
|
|
|
use crate::lib::screen::{BoardCommand, Screen}; |
|
|
|
|
|
|
|
use crate::lib::world::World; |
|
|
|
|
|
|
|
use rand::Rng; |
|
|
|
|
|
|
|
|
|
|
|
use std::collections::HashMap; |
|
|
|
use std::collections::HashMap; |
|
|
|
|
|
|
|
|
|
|
@ -8,28 +10,55 @@ use ncurses::*; |
|
|
|
|
|
|
|
|
|
|
|
use downcast_rs::{impl_downcast, Downcast}; |
|
|
|
use downcast_rs::{impl_downcast, Downcast}; |
|
|
|
|
|
|
|
|
|
|
|
pub trait Entity: AI + Renderable + Downcast {} |
|
|
|
pub trait Entity: AI + Downcast { |
|
|
|
impl_downcast!(Entity); |
|
|
|
fn get_position(&self) -> Point; |
|
|
|
|
|
|
|
fn get_id(&self) -> u32; |
|
|
|
|
|
|
|
fn set_id(&mut self, id: u32); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
macro_rules! impl_entity { |
|
|
|
|
|
|
|
($t: ident) => { |
|
|
|
|
|
|
|
impl Entity for $t { |
|
|
|
|
|
|
|
fn get_position(&self) -> Point { |
|
|
|
|
|
|
|
self.pos.clone() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn get_id(&self) -> u32 { |
|
|
|
|
|
|
|
self.id |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn set_id(&mut self, id: u32) { |
|
|
|
|
|
|
|
self.id = id; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl_downcast!(Renderable); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)] |
|
|
|
pub struct Ant { |
|
|
|
pub struct Ant { |
|
|
|
pub pos: Point, |
|
|
|
pub pos: Point, |
|
|
|
pub id: u32, |
|
|
|
pub id: u32, |
|
|
|
pub goal: AIGoal, |
|
|
|
pub goal: AIGoal, |
|
|
|
pub plan: Vec<Point> |
|
|
|
pub plan: Vec<Point>, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Ant { |
|
|
|
impl Ant { |
|
|
|
pub fn new(x: i32, y: i32, id: u32) -> Ant { |
|
|
|
pub fn new(x: i32, y: i32) -> Ant { |
|
|
|
Ant { |
|
|
|
Ant { |
|
|
|
pos: Point(x, y), |
|
|
|
pos: Point(x, y), |
|
|
|
id, |
|
|
|
id: 0, |
|
|
|
plan: vec![],
|
|
|
|
plan: vec![], |
|
|
|
goal: AIGoal::Idle |
|
|
|
goal: AIGoal::Idle, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl_entity!(Ant); |
|
|
|
impl Entity for Ant {} |
|
|
|
impl_entity!(Food); |
|
|
|
|
|
|
|
impl_entity!(FoodGenerator); |
|
|
|
|
|
|
|
impl_entity!(Egg); |
|
|
|
|
|
|
|
impl_entity!(Queen); |
|
|
|
|
|
|
|
|
|
|
|
impl Renderable for Ant { |
|
|
|
impl Renderable for Ant { |
|
|
|
fn representation(&self) -> &str { |
|
|
|
fn representation(&self) -> &str { |
|
|
@ -44,6 +73,7 @@ impl Renderable for Ant { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)] |
|
|
|
pub struct Queen { |
|
|
|
pub struct Queen { |
|
|
|
pub pos: Point, |
|
|
|
pub pos: Point, |
|
|
|
pub egg_count: u8, |
|
|
|
pub egg_count: u8, |
|
|
@ -64,8 +94,10 @@ impl Renderable for Queen { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub trait Renderable: AI { |
|
|
|
pub trait Renderable: Entity { |
|
|
|
fn representation(&self) -> &str; |
|
|
|
fn representation(&self) -> &str { |
|
|
|
|
|
|
|
"X" |
|
|
|
|
|
|
|
} |
|
|
|
fn before_render(&self) {} |
|
|
|
fn before_render(&self) {} |
|
|
|
fn after_render(&self) {} |
|
|
|
fn after_render(&self) {} |
|
|
|
fn render(&self, b: &Screen) { |
|
|
|
fn render(&self, b: &Screen) { |
|
|
@ -76,16 +108,16 @@ pub trait Renderable: AI { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Queen { |
|
|
|
impl Queen { |
|
|
|
pub fn new(x: i32, y: i32, id: u32) -> Queen { |
|
|
|
pub fn new(x: i32, y: i32) -> Queen { |
|
|
|
Queen { |
|
|
|
Queen { |
|
|
|
pos: Point(x, y), |
|
|
|
pos: Point(x, y), |
|
|
|
egg_count: 0, |
|
|
|
egg_count: 0, |
|
|
|
id, |
|
|
|
id: 0, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
|
|
#[derive(Debug, Clone)] |
|
|
|
pub struct Egg { |
|
|
|
pub struct Egg { |
|
|
|
pub pos: Point, |
|
|
|
pub pos: Point, |
|
|
|
pub counter: u8, |
|
|
|
pub counter: u8, |
|
|
@ -108,21 +140,18 @@ impl Renderable for Egg { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Egg { |
|
|
|
impl Egg { |
|
|
|
pub fn new(x: i32, y: i32, id: u32, queen_id: u32) -> Egg { |
|
|
|
pub fn new(x: i32, y: i32, queen_id: u32) -> Egg { |
|
|
|
Egg { |
|
|
|
Egg { |
|
|
|
pos: Point(x, y), |
|
|
|
pos: Point(x, y), |
|
|
|
counter: 10, |
|
|
|
counter: 10, |
|
|
|
id, |
|
|
|
id: 0, |
|
|
|
queen_id, |
|
|
|
queen_id, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Entity for Queen {} |
|
|
|
|
|
|
|
impl Entity for Egg {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub struct Entities { |
|
|
|
pub struct Entities { |
|
|
|
pub data: HashMap<u32, Box<dyn Entity>>, |
|
|
|
pub data: HashMap<u32, Box<dyn Renderable>>, |
|
|
|
id_counter: u32, |
|
|
|
id_counter: u32, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -134,27 +163,77 @@ impl Entities { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn add_ant(&mut self, x: i32, y: i32) -> u32 { |
|
|
|
pub fn add_entity<T: Renderable + Clone>(&mut self, e: &T) -> u32 { |
|
|
|
let a = Ant::new(x, y, self.id_counter); |
|
|
|
let mut clone = e.clone(); |
|
|
|
let id = a.id; |
|
|
|
clone.set_id(self.id_counter); |
|
|
|
self.data.insert(a.id, Box::new(a)); |
|
|
|
let id = clone.get_id(); |
|
|
|
|
|
|
|
self.data.insert(id, Box::new(clone)); |
|
|
|
self.id_counter += 1; |
|
|
|
self.id_counter += 1; |
|
|
|
id |
|
|
|
e.get_id() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn add_queen(&mut self, x: i32, y: i32) -> u32 { |
|
|
|
#[derive(Clone)] |
|
|
|
let q = Queen::new(x, y, self.id_counter); |
|
|
|
pub struct Food { |
|
|
|
let id = q.id; |
|
|
|
pos: Point, |
|
|
|
self.data.insert(q.id, Box::new(q)); |
|
|
|
id: u32, |
|
|
|
self.id_counter += 1; |
|
|
|
} |
|
|
|
id |
|
|
|
|
|
|
|
|
|
|
|
impl Food { |
|
|
|
|
|
|
|
pub fn new(x: i32, y: i32) -> Food { |
|
|
|
|
|
|
|
Food { |
|
|
|
|
|
|
|
pos: Point(x, y), |
|
|
|
|
|
|
|
id: 0, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl AI for Food { |
|
|
|
|
|
|
|
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand { |
|
|
|
|
|
|
|
// perhaps check if we're in target?
|
|
|
|
|
|
|
|
// implement drag logic?
|
|
|
|
|
|
|
|
BoardCommand::Noop |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn add_egg(&mut self, x: i32, y: i32, queen_id: u32) -> u32 { |
|
|
|
impl Renderable for Food { |
|
|
|
let e = Egg::new(x, y, self.id_counter, queen_id); |
|
|
|
fn representation(&self) -> &str { |
|
|
|
let id = e.id; |
|
|
|
"f" |
|
|
|
self.data.insert(e.id, Box::new(e)); |
|
|
|
} |
|
|
|
self.id_counter += 1; |
|
|
|
} |
|
|
|
id |
|
|
|
|
|
|
|
|
|
|
|
// no position, does not get rendered yet acts per turn
|
|
|
|
|
|
|
|
#[derive(Clone)] |
|
|
|
|
|
|
|
pub struct FoodGenerator { |
|
|
|
|
|
|
|
counter: u32, |
|
|
|
|
|
|
|
pos: Point, |
|
|
|
|
|
|
|
id: u32 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl FoodGenerator { |
|
|
|
|
|
|
|
pub fn new() -> FoodGenerator { |
|
|
|
|
|
|
|
FoodGenerator { counter: 0, id: 0, pos: Point(0,0) } |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl AI for FoodGenerator { |
|
|
|
|
|
|
|
fn step(&mut self, b: &Screen, w: &mut World) -> BoardCommand { |
|
|
|
|
|
|
|
if self.counter % 600 == 0 { |
|
|
|
|
|
|
|
// 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); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return BoardCommand::SpawnFood(Point(r_x, r_y)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
self.counter += 1; |
|
|
|
|
|
|
|
BoardCommand::Noop |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Renderable for FoodGenerator { |
|
|
|
|
|
|
|
fn render(&self, b: &Screen) {} |
|
|
|
|
|
|
|
} |
|
|
|