path_of_exile/crop_rot/src/model.rs
2024-10-09 03:51:35 +02:00

194 lines
5.5 KiB
Rust

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<f64, &'static str>;
fn upgrade(&mut self, config: &Config);
fn wilt(&mut self);
fn is_wilted(&self) -> bool;
}
#[derive(Debug, Clone)]
pub struct Harvest<T: Harvestable> {
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<f64, &'static str> {
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<f64, &'static str> {
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<T> Harvest<T> where
T: Harvestable + Debug + Clone + Display
{
pub fn new(color_weights: &ColorWeights, config: &Config) -> Harvest<T> {
let rolled_fields: usize = rand::distributions::Uniform::new(3, 6).sample(&mut thread_rng()) * 2;
let mut fields: Vec<T> = 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<f64, &'static str> {
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<T: fmt::Display + Harvestable> fmt::Display for Harvest<T> {
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, "")
}
}