playtest mode

This commit is contained in:
2026-06-20 19:05:46 -05:00
parent e7c3ca1139
commit d32914d99d
10 changed files with 168 additions and 9 deletions
+24
View File
@@ -15,6 +15,7 @@ use crate::render::{BoardWidget, board_to_screen, screen_to_board};
use crate::ui::Ui;
use crate::utils::rgba8_to_color;
use kiln_core::cp437::tile_to_char;
use kiln_core::game::GameState;
use kiln_core::glyph::Glyph;
use kiln_core::log::LogLine;
use kiln_core::world::World;
@@ -89,6 +90,10 @@ pub(crate) struct EditorState {
last_board_area: Rect,
/// Editor-side log lines (the editor has no game log to draw from).
log: Vec<LogLine>,
/// A playtest game built by [`playtest`](EditorState::playtest), waiting for the
/// run loop to swap into [`Mode::Play`](crate::mode::Mode::Play). `Some` for only
/// the single frame between the menu action and the swap.
pub(crate) pending_playtest: Option<GameState>,
}
impl EditorState {
@@ -111,6 +116,7 @@ impl EditorState {
blink_timer: 0.0,
last_board_area: Rect::default(),
log: vec![LogLine::raw("editing — press [esc] for the menu")],
pending_playtest: None,
}
}
@@ -307,6 +313,24 @@ impl EditorState {
let max = total_w.saturating_sub(MIN_PANEL_WIDTH).max(MIN_PANEL_WIDTH);
self.sidebar_width = target.clamp(MIN_PANEL_WIDTH, max);
}
/// Playtest the board currently being edited, using its in-memory state.
///
/// Builds a [`GameState`] against a **deep copy** of the world ([`World::deep_clone`])
/// so nothing the playtest does (pushing crates, running scripts, …) touches the
/// boards being edited. The copy's start board is set to the edited board so play
/// begins here, not at the world's entry board. The game is parked in
/// [`pending_playtest`](EditorState::pending_playtest); the run loop swaps it into
/// [`Mode::Play`](crate::mode::Mode::Play) and stashes this editor for `Esc` to restore.
pub(crate) fn playtest(&mut self) {
let mut world = self.world.deep_clone();
// Start the playtest on the board open in the editor, not world.start.
world.start = self.board_name.clone();
let mut game = GameState::from_world(world);
game.log(LogLine::raw("[esc] to return to the editor"));
game.run_init();
self.pending_playtest = Some(game);
}
}
/// Handles an input event while a dialog is open ([`InputMode::Dialog`](crate::input::InputMode::Dialog)).