use serde::{Serialize, de::DeserializeOwned};
use crate::tui::Terminal;
mod snake;
pub mod wallet;
pub use snake::Snake;
use wallet::Wallet;
pub trait Game: Sync {
type State: Serialize + DeserializeOwned + Default;
fn id(&self) -> &'static str;
fn name(&self) -> &'static str;
fn description(&self) -> &'static str;
fn cost(&self) -> u64;
fn clear_color(&self) -> (u8, u8, u8);
fn run(
&self,
terminal: &mut Terminal,
wallet: &'_ mut dyn Wallet,
state: &mut Self::State,
) -> anyhow::Result<()>;
}
pub trait GameObject: Sync {
fn id(&self) -> &'static str;
fn name(&self) -> &'static str;
fn description(&self) -> &'static str;
fn cost(&self) -> u64;
fn clear_color(&self) -> (u8, u8, u8);
fn run(
&self,
terminal: &mut Terminal,
wallet: &mut dyn Wallet,
state_json: &mut Option<String>,
) -> anyhow::Result<()>;
}
impl std::fmt::Debug for dyn GameObject {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Game: {}", self.name())
}
}
impl PartialEq for dyn GameObject {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
pub type GameRef = &'static dyn GameObject;
impl<G: Game> GameObject for G {
fn id(&self) -> &'static str {
self.id()
}
fn name(&self) -> &'static str {
self.name()
}
fn description(&self) -> &'static str {
self.description()
}
fn cost(&self) -> u64 {
self.cost()
}
fn clear_color(&self) -> (u8, u8, u8) {
self.clear_color()
}
fn run(
&self,
terminal: &mut Terminal,
wallet: &mut dyn Wallet,
state_json: &mut Option<String>,
) -> anyhow::Result<()> {
let mut state: G::State = if let Some(state_json) = state_json {
serde_json::from_str(state_json)?
} else {
G::State::default()
};
self.run(terminal, wallet, &mut state)?;
*state_json = Some(serde_json::to_string(&state)?);
Ok(())
}
}
pub static SNAKE: Snake = Snake;
pub static ALL_GAMES: &[GameRef] = &[&SNAKE];