/* Hurry Curry! - a game about cooking Copyright (C) 2025 Hurry Curry! Contributors 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 crate::{Gamedata, ItemIndex, Recipe, RecipeIndex, TileIndex}; impl Gamedata { pub fn tile_name(&self, index: TileIndex) -> &str { &self.tile_names[index.0] } pub fn item_name(&self, index: ItemIndex) -> &str { &self.item_names[index.0] } pub fn recipe(&self, index: RecipeIndex) -> &Recipe { &self.recipes[index.0] } pub fn get_tile_by_name(&self, name: &str) -> Option { self.tile_names .iter() .position(|t| t == name) .map(TileIndex) } pub fn get_item_by_name(&self, name: &str) -> Option { self.item_names .iter() .position(|t| t == name) .map(ItemIndex) } pub fn recipes(&self) -> impl Iterator { self.recipes .iter() .enumerate() .map(|(i, e)| (RecipeIndex(i), e)) } } impl Recipe { pub fn tile(&self) -> Option { match self { Recipe::Passive { tile, .. } => *tile, Recipe::Active { tile, .. } => *tile, Recipe::Instant { tile, .. } => *tile, } } pub fn speed(&self) -> Option { match self { Recipe::Passive { speed, .. } => Some(*speed), Recipe::Active { speed, .. } => Some(*speed), _ => None, } } pub fn revert_speed(&self) -> Option { match self { Recipe::Passive { revert_speed, .. } => *revert_speed, _ => None, } } pub fn warn(&self) -> bool { match self { Recipe::Passive { warn, .. } => *warn, _ => false, } } pub fn inputs(&self) -> impl Iterator { let (a, b) = match self { Recipe::Passive { input, .. } | Recipe::Active { input, .. } => (Some(input), None), Recipe::Instant { inputs, .. } => (inputs[0].as_ref(), inputs[1].as_ref()), }; a.into_iter().chain(b).copied() } pub fn outputs(&self) -> impl Iterator { let (a, b) = match self { Recipe::Passive { output, .. } => (output, &None), Recipe::Active { outputs, .. } | Recipe::Instant { outputs, .. } => { (&outputs[0], &outputs[1]) } }; a.iter().chain(b.iter()).copied() } pub fn supports_tile(&self, tile: Option) -> bool { if let Some(tile_constraint) = self.tile() { if let Some(tile) = tile { tile == tile_constraint } else { false } } else { true } } } mod display { use crate::*; use std::fmt::Display; impl Display for ItemLocation { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ItemLocation::Tile(pos) => write!(f, "tile({}, {})", pos.x, pos.y), ItemLocation::Player(player, hand) => write!(f, "{player}-{hand}"), } } } impl Display for Hand { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "hand#{}", self.0) } } impl Display for PlayerID { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "player#{}", self.0) } } impl Display for TileIndex { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "tile#{}", self.0) } } impl Display for ItemIndex { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "item#{}", self.0) } } impl Display for RecipeIndex { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "recipe#{}", self.0) } } } mod enum_is { use crate::*; impl PlayerClass { pub fn is_cheflike(&self) -> bool { matches!(self, Self::Bot | Self::Chef) } } impl ItemLocation { pub fn is_tile(&self) -> bool { matches!(self, Self::Tile(..)) } pub fn is_player(&self) -> bool { matches!(self, Self::Player(..)) } } } pub mod deser { use crate::*; use serde::Deserializer; use std::collections::BTreeMap; pub(crate) fn deser_i64<'de, D: Deserializer<'de>>(deserializer: D) -> Result { let x = f64::deserialize(deserializer)?; Ok(x.trunc() as i64) } pub(crate) fn deser_i32<'de, D: Deserializer<'de>>(deserializer: D) -> Result { let x = f64::deserialize(deserializer)?; Ok(x.trunc() as i32) } pub(crate) fn deser_usize<'de, D: Deserializer<'de>>( deserializer: D, ) -> Result { let x = f64::deserialize(deserializer)?; Ok(x.trunc() as usize) } pub(crate) fn deser_tile_index_map<'de, D: Deserializer<'de>>( deserializer: D, ) -> Result>, D::Error> { let x = BTreeMap::>::deserialize(deserializer)?; Ok(x.into_iter() .map(|(k, v)| (TileIndex(k.parse().ok().unwrap_or_default()), v)) .collect()) } }