aboutsummaryrefslogtreecommitdiff
path: root/server/src/data/demands.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-07-13 23:27:18 +0200
committermetamuffin <metamuffin@disroot.org>2024-07-13 23:27:18 +0200
commit0c77e0938de43a970e03c6dcef019c87745f0ee4 (patch)
tree76212988078d18edd59330061eeecb38b6ab7fc5 /server/src/data/demands.rs
parentcd3a3989901d877426cbd64622b93367eaf81d4a (diff)
downloadhurrycurry-0c77e0938de43a970e03c6dcef019c87745f0ee4.tar
hurrycurry-0c77e0938de43a970e03c6dcef019c87745f0ee4.tar.bz2
hurrycurry-0c77e0938de43a970e03c6dcef019c87745f0ee4.tar.zst
automatically generate demands from map and recipes. added icecream and sushi.
Diffstat (limited to 'server/src/data/demands.rs')
-rw-r--r--server/src/data/demands.rs94
1 files changed, 94 insertions, 0 deletions
diff --git a/server/src/data/demands.rs b/server/src/data/demands.rs
new file mode 100644
index 00000000..2501e225
--- /dev/null
+++ b/server/src/data/demands.rs
@@ -0,0 +1,94 @@
+/*
+ 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 <https://www.gnu.org/licenses/>.
+
+*/
+use super::Demand;
+use crate::interaction::Recipe;
+use hurrycurry_protocol::{ItemIndex, TileIndex};
+use std::collections::{HashMap, HashSet};
+
+pub fn generate_demands(
+ tiles: HashSet<TileIndex>,
+ items: HashSet<ItemIndex>,
+ raw_demands: &[(ItemIndex, Option<ItemIndex>, f32)],
+ recipes: &[Recipe],
+) -> Vec<Demand> {
+ let recipes = recipes
+ .iter()
+ .filter(|r| r.tile().map(|t| tiles.contains(&t)).unwrap_or(true))
+ .collect::<Vec<_>>();
+
+ 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()
+}