use std::fmt::Display;
use rustorio_engine::{
ResourceType, bundle,
mod_reexports::{Bundle, Resource, Tick},
resource,
};
use crate::resources::{Copper, Iron};
pub const MINING_TICK_LENGTH: u64 = 2;
const fn tick_to_mining_tick(tick: u64) -> u64 {
tick / MINING_TICK_LENGTH
}
#[derive(Debug)]
#[non_exhaustive]
pub struct Miner;
impl Miner {
pub const fn build(iron: Bundle<Iron, 10>, copper: Bundle<Copper, 5>) -> Self {
let _ = (iron, copper);
Miner
}
}
#[derive(Debug)]
pub struct TerritoryFullError {
pub max_miners: u32,
pub miner: Miner,
}
impl Display for TerritoryFullError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Territory is full: maximum number of miners is {}",
self.max_miners
)
}
}
#[derive(Debug)]
#[non_exhaustive]
pub struct Territory<OreType: ResourceType> {
mining_tick: u64,
max_miners: u32,
miners: u32,
resources: Resource<OreType>,
}
impl<OreType: ResourceType> Territory<OreType> {
pub(crate) const fn new(tick: &Tick, max_miners: u32) -> Self {
Self {
mining_tick: tick_to_mining_tick(tick.cur()),
max_miners,
miners: 0,
resources: Resource::new_empty(),
}
}
pub const fn max_miners(&self) -> u32 {
self.max_miners
}
pub const fn num_miners(&self) -> u32 {
self.miners
}
fn tick(&mut self, tick: &Tick) {
let mining_tick = tick_to_mining_tick(tick.cur());
assert!(self.mining_tick <= mining_tick, "Tick went backwards");
let mining_tick_delta = mining_tick - self.mining_tick;
self.resources += resource(
u32::try_from(mining_tick_delta).expect("Mining tick delta too large") * self.miners,
);
self.mining_tick = mining_tick;
}
pub fn hand_mine<const AMOUNT: u32>(&mut self, tick: &mut Tick) -> Bundle<OreType, AMOUNT> {
self.tick(tick);
tick.advance_by((u64::from(AMOUNT)) * MINING_TICK_LENGTH);
bundle()
}
pub fn add_miner(&mut self, tick: &Tick, miner: Miner) -> Result<(), TerritoryFullError> {
self.tick(tick);
if self.miners < self.max_miners {
self.miners += 1;
Ok(())
} else {
Err(TerritoryFullError {
max_miners: self.max_miners,
miner,
})
}
}
pub fn take_miner(&mut self, tick: &Tick) -> Option<Miner> {
self.tick(tick);
if self.miners > 0 {
self.miners -= 1;
Some(Miner)
} else {
None
}
}
pub fn resources(&mut self, tick: &Tick) -> &mut Resource<OreType> {
self.tick(tick);
&mut self.resources
}
}