diff options
Diffstat (limited to 'src/scenes/mod.rs')
| -rw-r--r-- | src/scenes/mod.rs | 159 |
1 files changed, 153 insertions, 6 deletions
diff --git a/src/scenes/mod.rs b/src/scenes/mod.rs index 60db647..1c20edf 100644 --- a/src/scenes/mod.rs +++ b/src/scenes/mod.rs @@ -1,9 +1,25 @@ -//! Scenes: the title screen, the name forge, and derelicts to board; -//! flight and ports later. +//! Scenes: the title screen, characters and their saves, the name forge, +//! derelicts to board, flight (around a place, across the system map, and +//! between systems on the star map), and what's on the ground: cities to +//! walk, and ports. +pub mod aboard; +pub mod character; pub mod derelict; +pub mod flight; pub mod forge; +pub mod galaxy_map; +pub mod inventory; +pub mod keys; +pub mod pause; +pub mod port; +pub mod saves; +pub mod sky; +pub mod system_map; pub mod title; +pub mod town; +#[cfg(test)] +mod zz_dump; use ratatui::Frame; use ratatui::crossterm::event::KeyEvent; @@ -15,8 +31,14 @@ pub enum Transition { None, /// Open a scene on top of this one. Popping it comes back here. Push(Box<dyn Scene>), + /// Open several scenes at once, each on top of the one before. + Open(Vec<Box<dyn Scene>>), /// Close this scene and return to the one beneath it. Pop, + /// Close this scene and open these in its place. + Replace(Vec<Box<dyn Scene>>), + /// Close every scene but the title screen, at the bottom of the stack. + Title, Quit, } @@ -33,10 +55,15 @@ pub trait Scene { } fn render(&self, frame: &mut Frame, ctx: &Ctx); + + /// This scene has come to the top of the stack: just opened, or + /// uncovered when the ones above it closed. What it shows may need + /// bringing up to date with what happened up there. + fn on_top(&mut self, _ctx: &Ctx) {} } #[cfg(test)] -mod tests { +pub(crate) mod tests { use ratatui::Terminal; use ratatui::backend::TestBackend; use ratatui::crossterm::event::{KeyCode, KeyModifiers}; @@ -53,13 +80,130 @@ mod tests { #[test] fn scenes_render_at_any_size() { let mut ctx = test_ctx(); + let esc = KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE); + let mut pausing = derelict::Derelict::new(2); + pausing.key(esc, &mut ctx); let mut abandoning = derelict::Derelict::new(2); - abandoning.key(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE), &mut ctx); - let scenes: [Box<dyn Scene>; 4] = [ - Box::new(title::Title::new(&ctx)), + abandoning.key(esc, &mut ctx); + abandoning.key(KeyEvent::new(KeyCode::Char('2'), KeyModifiers::NONE), &mut ctx); + let mut aiming = derelict::Derelict::new(2); + aiming.key(KeyEvent::new(KeyCode::Char('f'), KeyModifiers::NONE), &mut ctx); + aiming.key(KeyEvent::new(KeyCode::Char('l'), KeyModifiers::NONE), &mut ctx); + let mut packing = derelict::Derelict::new(2); + packing.key(KeyEvent::new(KeyCode::Char('i'), KeyModifiers::NONE), &mut ctx); + // Something of every kind, on you and in the lockers. + { + use crate::dungeon::armour; + use crate::dungeon::arms::Source; + use crate::items::{Food, Item, Salvage, Slot, Stack}; + let mut rng = crate::seed::rng(8); + let mut armor = |slot| { + let mut a = armour::find(&mut rng, Source::Armoury, false); + a.slot = slot; + a.durability = 1; + a + }; + let food = Food { + title: "ration brick".into(), + description: "dense and grey".into(), + nourishment: 10, + mass: 400, + }; + let scrap = Salvage { title: "coil of superconductor".into(), value: 30, mass: 6000 }; + let g = &mut ctx.hold.gear; + g.worn.insert(Slot::Body, armor(Slot::Body)); + g.add(Stack::one(Item::Armor(armor(Slot::Head)))); + g.add(Stack { item: Item::Food(food), count: 3 }); + g.add(Stack { item: Item::Medpatch, count: 2 }); + ctx.hold.lockers.push(Stack { item: Item::Salvage(scrap.clone()), count: 4 }); + ctx.hold.deck.push((crate::dungeon::Pos::new(0, 0), Stack::one(Item::Salvage(scrap)))); + } + let mut rummaging = derelict::Derelict::board(2, &mut ctx); + for code in [KeyCode::Char('i'), KeyCode::Char('j'), KeyCode::Enter] { + rummaging.key(KeyEvent::new(code, KeyModifiers::NONE), &mut ctx); + } + let home = ctx.system.home_place(); + let mut stowing = aboard::Aboard::landed(&ctx, home); + for code in [KeyCode::Char('i'), KeyCode::Char('l'), KeyCode::Char('/')] { + stowing.key(KeyEvent::new(code, KeyModifiers::NONE), &mut ctx); + } + let mut strolling = town::TownScene::new(&ctx, home); + strolling.key(KeyEvent::new(KeyCode::Char('i'), KeyModifiers::NONE), &mut ctx); + let mut leaving = town::TownScene::new(&ctx, home); + leaving.key(esc, &mut ctx); + let mut resting = aboard::Aboard::landed(&ctx, home); + resting.key(esc, &mut ctx); + let mut flying = flight::FlightScene::new(&ctx); + flying.key(KeyEvent::new(KeyCode::Tab, KeyModifiers::NONE), &mut ctx); + let mut holding = flight::FlightScene::new(&ctx); + holding.key(esc, &mut ctx); + let mut docked = port::Port::new(&ctx, 0); + docked.key(esc, &mut ctx); + let belt = ctx.system.places.len() - 1; + let mut trading = town::TownScene::new(&ctx, home); + for _ in 0..12 { + trading.key(KeyEvent::new(KeyCode::Right, KeyModifiers::NONE), &mut ctx); + } + let wreck = ctx.system.wrecks_on(ctx.day).pop(); + let mut renaming = character::Sheet::new(); + renaming.key(KeyEvent::new(KeyCode::Char('r'), KeyModifiers::NONE), &mut ctx); + let mut creating = character::Create::new(&ctx); + creating.key(KeyEvent::new(KeyCode::Down, KeyModifiers::NONE), &mut ctx); + let dir = crate::save::scratch("render"); + ctx.saves = Some(dir.clone()); + ctx.slot = Some(crate::save::new_slot(&dir, &ctx.character, ctx.seed)); + ctx.record.slain.insert("rust-mite".into(), 2); + ctx.bestiary.insert(("rust-mite", crate::dungeon::arms::Dmg::Blunt)); + ctx.autosave(); + std::fs::write(dir.join("broken.json"), "{").unwrap(); + let playing = title::Title::new(&ctx); + let mut plotting = galaxy_map::GalaxyMap::new(&ctx); + plotting.key(KeyEvent::new(KeyCode::Tab, KeyModifiers::NONE), &mut ctx); + let mut far = galaxy_map::GalaxyMap::new(&ctx); + for _ in 0..6 { + far.key(KeyEvent::new(KeyCode::Left, KeyModifiers::NONE), &mut ctx); + } + let mut stranded = test_ctx(); + let dead = (0..stranded.galaxy.sites.len()) + .find(|&i| !stranded.galaxy.sites[i].kind.sells_fuel()) + .unwrap(); + stranded.enter_system(dead); + stranded.hold.fuel = 0; + stranded.hold.debt = 120; + let scenes: [Box<dyn Scene>; 33] = [ + Box::new(title::Title::new(&test_ctx())), + Box::new(playing), + Box::new(character::Create::new(&ctx)), + Box::new(creating), + Box::new(character::Sheet::new()), + Box::new(renaming), + Box::new(saves::Saves::new(&ctx)), Box::new(forge::Forge::new(&ctx)), Box::new(derelict::Derelict::new(1)), + Box::new(pausing), Box::new(abandoning), + Box::new(holding), + Box::new(docked), + Box::new(leaving), + Box::new(resting), + Box::new(aiming), + Box::new(packing), + Box::new(rummaging), + Box::new(stowing), + Box::new(strolling), + Box::new(flying), + Box::new(system_map::SystemMap::new(&ctx)), + Box::new(galaxy_map::GalaxyMap::new(&ctx)), + Box::new(plotting), + Box::new(far), + Box::new(port::Port::new(&ctx, ctx.system.home_place())), + Box::new(port::Port::new(&ctx, belt)), + Box::new(port::Port::new(&ctx, 0)), + Box::new(town::TownScene::new(&ctx, home)), + Box::new(trading), + Box::new(aboard::Aboard::landed(&ctx, home)), + Box::new(aboard::Aboard::resumed(&ctx, home)), + Box::new(aboard::Aboard::adrift("in orbit around nowhere", wreck)), ]; for (width, height) in [(160, 50), (80, 24), (40, 12), (5, 3), (1, 1)] { let mut terminal = Terminal::new(TestBackend::new(width, height)).unwrap(); @@ -69,6 +213,9 @@ mod tests { terminal.draw(|frame| scene.render(frame, &ctx)).unwrap(); } } + let map = galaxy_map::GalaxyMap::new(&stranded); + terminal.draw(|frame| map.render(frame, &stranded)).unwrap(); } + let _ = std::fs::remove_dir_all(dir); } } |