use serde::Deserialize;
use std::collections::HashMap;
use std::fmt::Display;
use std::path::Path;
use crate::tenx_programmer::TenXProgrammerCounters;
mod elegant_weapons;
mod howl;
pub mod means_of_production;
mod outcome;
mod request;
pub use elegant_weapons::ElegantWeapons;
pub use howl::Howl;
pub use means_of_production::MeansOfProduction;
pub use outcome::Outcome;
pub use request::Request;
pub type NPC = Box<dyn SexDungeon + Send + Sync + 'static>;
pub trait SexDungeon {
fn new<P: AsRef<Path>>(
path: P,
counters: Option<&TenXProgrammerCounters>,
options: &LanguageOptions,
) -> anyhow::Result<Self>
where
Self: Sized + Send + Sync + 'static;
fn decide(&self, request: Request) -> Result<Outcome, Outcome>;
fn run_tests(&mut self) -> anyhow::Result<()>;
}
#[derive(Clone, Copy, Debug, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum Language {
#[default]
Roto,
Lua,
Fennel,
}
impl Display for Language {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let lang = match self {
Self::Roto => "roto",
Self::Lua => "lua",
Self::Fennel => "fennel",
};
write!(f, "{lang}")
}
}
pub type LanguageOptions = HashMap<String, String>;
pub fn create<P: AsRef<Path>>(
language: Language,
options: &LanguageOptions,
path: P,
counters: Option<&TenXProgrammerCounters>,
) -> anyhow::Result<NPC> {
let dungeon: NPC = match language {
Language::Roto => Box::new(MeansOfProduction::new(path, counters, options)?),
Language::Lua => Box::new(Howl::new(path, counters, options)?),
Language::Fennel => Box::new(ElegantWeapons::new(path, counters, options)?),
};
Ok(dungeon)
}