use super::*;
use colored::*;
use core::fmt::Debug;
const GRASS_DELTA: u8 = 4; const INITIAL_HEIGHT: u8 = 48;
const SPREAD_HEIGHT: u8 = 48;
#[derive(Debug)]
struct Grass {
height: u8,
}
register_type!(Grass);
pub fn add_grass(world: &mut World, store: &Store, loc: Point) {
let mut component = Component::new("grass");
add_object!(
component,
Grass,
Grass::new(INITIAL_HEIGHT),
[Action, Render, Fodder],
[Debug]
);
world.add_front(store, loc, component);
}
pub fn spread_grass(world: &mut World, store: &Store, loc: Point) {
let mut component = Component::new("grass");
add_object!(component, Grass, Grass::new(1), [Action, Render, Fodder]);
world.add_front(store, loc, component);
}
impl Grass {
pub fn new(height: u8) -> Grass {
Grass { height }
}
}
impl Fodder for Grass {
fn height(&self) -> u8 {
self.height
}
fn eat<'a, 'b>(&mut self, context: Context<'a, 'b>, percent: i32) {
let delta = (percent * 255 / 100) as u8;
if self.height <= delta {
if context.world.verbose >= 2 {
println!(" grass is now gone");
}
context.world.remove(context.store, context.id, context.loc);
} else {
self.height -= delta;
if context.world.verbose >= 2 {
println!(
" grass went from height {} to {}",
self.height + delta,
self.height
);
}
}
}
}
impl Action for Grass {
fn act<'a, 'b>(&mut self, context: Context<'a, 'b>) -> LifeCycle {
let mut details = String::new();
if self.height < u8::MAX - GRASS_DELTA {
self.height += GRASS_DELTA;
if context.world.verbose >= 3 {
details += &format!(" grew to {}", self.height);
}
}
if self.height > SPREAD_HEIGHT {
for neighbor in context.world.all(context.loc, 1, |pt| {
context
.world
.cell(pt)
.iter()
.all(|id| pt != context.loc && !has_trait!(context.store.get(*id), Fodder))
}) {
if context.world.rng().gen_range(0..16) == 0 {
spread_grass(context.world, context.store, neighbor);
if context.world.verbose >= 2 {
details += &format!(" spread to {neighbor}");
}
}
}
}
if !details.is_empty() {
println!("grass at {} {}", context.loc, details);
}
LifeCycle::Alive
}
}
impl Render for Grass {
fn render(&self) -> ColoredString {
assert!(self.height > 0);
if self.height < SPREAD_HEIGHT {
"~".normal()
} else {
"|".normal()
}
}
}