use std::fmt::{self, Debug, Display}; use rand::prelude::*; use crate::weights::{Config, ColorWeights, Color}; #[derive(Debug, Clone)] pub struct Field { pub color: Color, pub wilted: bool, pub t1_seeds: i8, pub t2_seeds: i8, pub t3_seeds: i8, pub t4_seeds: i8, } #[derive(Debug, Clone)] pub struct FakeField { color: Color, wilted: bool, upgrades: usize, } pub trait Harvestable { fn new(color_weights: &ColorWeights) -> Self; fn new_ungenerated() -> Self; fn harvest(&mut self, config: &Config) -> Result; fn upgrade(&mut self, config: &Config); fn wilt(&mut self); fn is_wilted(&self) -> bool; } #[derive(Debug, Clone)] pub struct Harvest { fields: [T; 10], value: f64, } impl Harvestable for Field { fn new(color_weights: &ColorWeights) -> Self { Field { color: color_weights.color(), wilted: false, t1_seeds: 23, t2_seeds: 0, t3_seeds: 0, t4_seeds: 0 } } fn new_ungenerated() -> Self { Field { color: Color::NotGenerated, wilted: true, t1_seeds: 0, t2_seeds: 0, t3_seeds: 0, t4_seeds: 0 } } fn harvest(&mut self, config: &Config) -> Result { match self.wilted { false => { self.wilted = true; Ok(self.t1_seeds as f64 * config.seed_lifeforce.t1 + self.t2_seeds as f64 * config.seed_lifeforce.t2 + self.t3_seeds as f64 * config.seed_lifeforce.t3 + self.t4_seeds as f64 * config.seed_lifeforce.t4) }, true => Err("cannot harvest wilted crop") } } fn upgrade(&mut self, config: &Config) { if !self.wilted { let t2 = config.seed_upgrade_chance.t1_to_t2(self.t1_seeds); let t3 = config.seed_upgrade_chance.t2_to_t3(self.t2_seeds); let t4 = config.seed_upgrade_chance.t3_to_t4(self.t3_seeds); self.t1_seeds += - t2; self.t2_seeds += t2 - t3; self.t3_seeds += t3 - t4; self.t4_seeds += t4; } } fn wilt(&mut self) { self.wilted = true; } fn is_wilted(&self) -> bool { self.wilted } } impl Harvestable for FakeField { fn new(color_weights: &ColorWeights) -> FakeField { FakeField { color: color_weights.color(), wilted: false, upgrades: 0 } } fn new_ungenerated() -> Self { FakeField {color: Color::NotGenerated, wilted: true, upgrades: 0} } fn harvest(&mut self, config: &Config) -> Result { match self.wilted { false => { self.wilted = true; Ok(config.expected_lifeforce[self.upgrades] * config.lifeforce_value.from_color(&self.color)) } true => Err("cannot harvest wilted crop"), } } fn upgrade(&mut self, config: &Config) { if !self.wilted { self.upgrades += 1; } } fn wilt(&mut self) { self.wilted = true; } fn is_wilted(&self) -> bool { self.wilted } } impl Harvest where T: Harvestable + Debug + Clone + Display { pub fn new(color_weights: &ColorWeights, config: &Config) -> Harvest { let rolled_fields: usize = rand::distributions::Uniform::new(3, 6).sample(&mut thread_rng()) * 2; let mut fields: Vec = Vec::new(); for _ in 0..rolled_fields { fields.push(T::new(color_weights)); } for _ in rolled_fields..10 { fields.push(T::new_ungenerated()) } Harvest { value: 0.0, fields: fields.try_into().unwrap() } } pub fn harvest(&mut self, n: usize, config: &Config) -> Result { match self.fields[n].harvest(config) { Err(x) => Err(x), Ok(gained_val) => { self.value += gained_val; let neighbor = n + 1 - n % 2; if thread_rng().gen_bool(0.4) {self.fields[neighbor].wilt();} self.fields.iter_mut().for_each(|field| field.upgrade(config)); Ok(gained_val) } } } pub fn recursive_harvest(self, config: &Config) -> f64 { if self.fields.iter().all(|field| field.is_wilted()) { return self.value; } else { return self.fields.iter().enumerate().filter(|(_, field)| !field.is_wilted()).map(|(i, field)| { let mut clone = self.clone(); clone.harvest(i, config); clone.recursive_harvest(config) }).reduce(f64::max).unwrap() } } } impl Display for Field { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.wilted { false => write!(f, "{}:{}:{}:{}:{}", match self.color { Color::Yellow => "Y", Color::Blue => "B", Color::Red => "R", Color::NotGenerated => "N/A" }, self.t1_seeds, self.t2_seeds, self.t3_seeds, self.t4_seeds), true => write!(f, "Wilted") } } } impl Display for FakeField { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Up:{}", self.upgrades) } } impl fmt::Display for Harvest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for (i, field) in self.fields.iter().enumerate() { write!(f, "{}", field)?; if i % 2 == 0 { write!(f, " <-> ")?; } else { write!(f, " ")?; } } write!(f, "") } }