use serde::{Deserialize, Serialize};
use std::fmt::Display;
use std::path::Path;
use crate::tenx_programmer::TenXProgrammer;
#[cfg(feature = "lua")]
mod elegant_weapons;
#[cfg(feature = "lua")]
mod howl;
mod matchers;
pub mod means_of_production;
mod request;
mod response;
#[cfg(feature = "lua")]
pub use elegant_weapons::ElegantWeapons;
#[cfg(feature = "lua")]
pub use howl::Howl;
pub use matchers::Matcher;
pub use means_of_production::MeansOfProduction;
pub use request::{Request, SharedRequest};
pub use response::Response;
pub type NPC = Box<dyn SexDungeon + Send + Sync + 'static>;
pub trait SexDungeon {
fn new<P: AsRef<Path>, C: AsRef<Path>, S: Serialize>(
path: P,
compiler: Option<C>,
initial_seed: &str,
metrics: &TenXProgrammer,
config: Option<S>,
) -> anyhow::Result<Self>
where
Self: Sized + Send + Sync + 'static;
fn can_decide(&self) -> bool;
fn decide(&self, request: SharedRequest) -> Result<String, anyhow::Error>;
fn can_output(&self) -> bool;
fn output(
&self,
request: SharedRequest,
decision: Option<String>,
) -> Result<Response, anyhow::Error>;
fn run_tests(&mut self) -> anyhow::Result<()>;
}
#[derive(Clone, Copy, Debug, Deserialize, Default, Serialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum Language {
#[default]
Roto,
#[cfg(feature = "lua")]
Lua,
#[cfg(feature = "lua")]
Fennel,
}
impl Display for Language {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let lang = match self {
Self::Roto => "roto",
#[cfg(feature = "lua")]
Self::Lua => "lua",
#[cfg(feature = "lua")]
Self::Fennel => "fennel",
};
write!(f, "{lang}")
}
}
pub fn create<P: AsRef<Path>, C: AsRef<Path>, S: Serialize>(
language: Language,
compiler: Option<C>,
path: Option<P>,
initial_seed: &str,
metrics: &TenXProgrammer,
config: Option<S>,
) -> anyhow::Result<NPC> {
let Some(path) = path else {
#[cfg(feature = "lua")]
let dungeon: NPC = if language == Language::Lua {
Box::new(Howl::new_default(initial_seed, metrics, config)?)
} else {
Box::new(MeansOfProduction::new_default(
initial_seed,
metrics,
config,
)?)
};
#[cfg(not(feature = "lua"))]
let dungeon: NPC = Box::new(MeansOfProduction::new_default(
initial_seed,
metrics,
config,
)?);
return Ok(dungeon);
};
let dungeon: NPC = match language {
Language::Roto => Box::new(MeansOfProduction::new(
path,
compiler,
initial_seed,
metrics,
config,
)?),
#[cfg(feature = "lua")]
Language::Lua => Box::new(Howl::new(path, compiler, initial_seed, metrics, config)?),
#[cfg(feature = "lua")]
Language::Fennel => Box::new(ElegantWeapons::new(
path,
compiler,
initial_seed,
metrics,
config,
)?),
};
Ok(dungeon)
}