thedes_app/
root.rs

1use std::fmt;
2
3use thedes_tui::{
4    core::event::Key,
5    menu::{self, Menu},
6};
7use thiserror::Error;
8
9use crate::session;
10
11pub mod new_game;
12pub mod game_creation;
13
14#[derive(Debug, Error)]
15pub enum InitError {
16    #[error("Failed to initialize main menu")]
17    MainMenu(
18        #[from]
19        #[source]
20        menu::Error,
21    ),
22    #[error("Failed to initialize new game component")]
23    NewGame(
24        #[from]
25        #[source]
26        new_game::InitError,
27    ),
28    #[error("Inconsistent main menu, missing quit")]
29    MissingQuit,
30}
31
32#[derive(Debug, Error)]
33pub enum Error {
34    #[error("Failed to run main menu")]
35    MainMenu(
36        #[from]
37        #[source]
38        menu::Error,
39    ),
40    #[error("Failed to run new game component")]
41    NewGame(
42        #[from]
43        #[source]
44        new_game::Error,
45    ),
46    #[error("Failed to run game creation")]
47    GameCreation(
48        #[from]
49        #[source]
50        game_creation::Error,
51    ),
52    #[error("Failed to run game session component")]
53    Session(
54        #[from]
55        #[source]
56        session::Error,
57    ),
58    #[error("Failed to create a game session")]
59    SessionInit(
60        #[from]
61        #[source]
62        session::InitError,
63    ),
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67enum MainMenuItem {
68    NewGame,
69    LoadGame,
70    Settings,
71    Quit,
72}
73
74impl fmt::Display for MainMenuItem {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        f.write_str(match self {
77            Self::NewGame => "New Game",
78            Self::LoadGame => "Load Game",
79            Self::Settings => "Settings",
80            Self::Quit => "Quit",
81        })
82    }
83}
84
85#[derive(Debug, Clone)]
86pub struct Component {
87    main_menu: Menu<MainMenuItem>,
88    new_game: new_game::Component,
89    game_creation: game_creation::Component,
90    session_config: session::Config,
91}
92
93impl Component {
94    pub fn new() -> Result<Self, InitError> {
95        let main_menu_items = [
96            MainMenuItem::NewGame,
97            MainMenuItem::LoadGame,
98            MainMenuItem::Settings,
99            MainMenuItem::Quit,
100        ];
101
102        let quit_position = main_menu_items
103            .iter()
104            .position(|item| *item == MainMenuItem::Quit)
105            .ok_or(InitError::MissingQuit)?;
106
107        let main_menu_bindings = menu::default_key_bindings()
108            .with(Key::Char('q'), menu::Command::SelectConfirm(quit_position));
109
110        let main_menu = Menu::new("=== T H E D E S ===", main_menu_items)?
111            .with_keybindings(main_menu_bindings);
112
113        let new_game = new_game::Component::new()?;
114        let game_creation = game_creation::Component::new();
115
116        Ok(Self {
117            main_menu,
118            new_game,
119            game_creation,
120            session_config: session::Config::new(),
121        })
122    }
123
124    pub async fn run(
125        &mut self,
126        app: &mut thedes_tui::core::App,
127    ) -> Result<(), Error> {
128        loop {
129            self.main_menu.run(app).await?;
130
131            match self.main_menu.output() {
132                MainMenuItem::NewGame => {
133                    self.new_game.run(app).await?;
134                    let seed = self.new_game.form().seed;
135                    let config = thedes_gen::Config::new().with_seed(seed);
136                    if let Some(game) =
137                        self.game_creation.run(app, config).await?
138                    {
139                        let mut session =
140                            self.session_config.clone().finish(game)?;
141                        session.run(app).await?;
142                    }
143                },
144
145                MainMenuItem::LoadGame => {},
146                MainMenuItem::Settings => {},
147                MainMenuItem::Quit => break,
148            }
149        }
150
151        Ok(())
152    }
153}