use crate::city::City;
use crate::error::Result;
use crate::infrastructure::Infrastructure;
use crate::npc::bot::{Bot, BotId, BotManager};
use crate::with_random_level;
use crate::world::World;
use num_traits::ToPrimitive;
use tap::Conv;
impl World {
#[inline]
pub fn bot_manager(&self) -> &BotManager {
&self.bot_manager
}
#[inline]
pub fn bot(&self, id: &BotId) -> Result<&Bot> {
self.bot_manager.bot(id)
}
#[inline]
pub(crate) fn bot_mut(&mut self, id: &BotId) -> Result<&mut Bot> {
self.bot_manager.bot_mut(id)
}
pub fn bots(&self) -> impl Iterator<Item = &Bot> {
self.bot_manager.bots()
}
pub(crate) fn spawn_bots(&mut self) -> Result<()> {
let size = self.continent.size();
let density = self.config().bot_density();
let amount = (f64::from(size) * density)
.floor()
.max(0.0)
.to_usize()
.unwrap_or_else(|| usize::from(size).saturating_mul(2));
let advanced_start_ratio = self
.config
.bot_advanced_start_ratio()
.conv::<f64>();
for name in nil_namegen::generate(amount) {
let infrastructure = if rand::random::<f64>() > advanced_start_ratio {
Infrastructure::default()
} else {
Infrastructure::builder()
.farm(with_random_level!(Farm, 1, 10))
.iron_mine(with_random_level!(IronMine, 1, 10))
.prefecture(with_random_level!(Prefecture, 1, 5))
.quarry(with_random_level!(Quarry, 1, 10))
.sawmill(with_random_level!(Sawmill, 1, 10))
.silo(with_random_level!(Silo, 10, 15))
.warehouse(with_random_level!(Warehouse, 10, 15))
.build()
};
self.spawn_bot(name, infrastructure)?;
}
Ok(())
}
pub(crate) fn spawn_bot(
&mut self,
id: impl Into<BotId>,
infrastructure: Infrastructure,
) -> Result<BotId> {
let id: BotId = id.into();
self.bot_manager.manage(id.clone())?;
let (coord, field) = self.find_spawn_point()?;
*field = City::builder(coord)
.name(id.as_ref())
.owner(id.clone())
.infrastructure(infrastructure)
.build()
.into();
Ok(id)
}
}