/* Hurry Curry! - a game about cooking Copyright 2024 metamuffin This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License only. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ use super::Demand; use crate::interaction::Recipe; use hurrycurry_protocol::{ItemIndex, TileIndex}; use std::collections::{HashMap, HashSet}; pub fn generate_demands( tiles: HashSet, items: HashSet, raw_demands: &[(ItemIndex, Option, f32)], recipes: &[Recipe], ) -> Vec { let recipes = recipes .iter() .filter(|r| r.tile().map(|t| tiles.contains(&t)).unwrap_or(true)) .collect::>(); let mut producable = HashMap::new(); for i in &items { producable.insert(*i, 0.0); } loop { let prod_count = producable.len(); for r in &recipes { let output_count = r.outputs().iter().filter(|o| !items.contains(&o)).count(); let Some(ingred_cost) = r .inputs() .iter() .map(|i| producable.get(i).copied()) .reduce(|a, b| { if let (Some(a), Some(b)) = (a, b) { Some(a + b) } else { None } }) .unwrap_or(Some(0.)) else { continue; }; let base_cost = match r { Recipe::Passive { duration, .. } => 2. + duration * 0.1, Recipe::Active { duration, .. } => 2. + duration, Recipe::Instant { .. } => 1., }; let output_cost = (ingred_cost + base_cost) / output_count as f32; for o in r.outputs() { let cost = producable.entry(o).or_insert(f32::INFINITY); *cost = cost.min(output_cost); } } if prod_count == producable.len() { break; } } raw_demands .iter() .filter_map(|(i, o, d)| { if let Some(cost) = producable.get(i) { Some(Demand { from: *i, to: *o, duration: *d, points: *cost as i64, }) } else { None } }) .collect() }