From 4a31994ac9cade53217a0c8e07ce8e361b22a730 Mon Sep 17 00:00:00 2001 From: Joachim Lusiardi Date: Mon, 22 Jan 2024 20:47:35 +0100 Subject: [PATCH] add a basic manual --- Cargo.lock | 193 +++++++++++++++++++++++++-- Cargo.toml | 3 +- src/main.rs | 374 +++++++++++++++++++++++++++++----------------------- 3 files changed, 395 insertions(+), 175 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bf5700..7b3d5ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,54 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "anstream" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -56,6 +104,52 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "crossterm" version = "0.27.0" @@ -91,6 +185,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" name = "el_diabolo" version = "0.1.0" dependencies = [ + "clap", "crossterm", "petgraph", "rand", @@ -211,7 +306,7 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -240,7 +335,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -399,6 +494,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.25.0" @@ -461,6 +562,12 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "version_check" version = "0.9.4" @@ -575,7 +682,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -584,13 +700,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -599,42 +730,84 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "zerocopy" version = "0.7.19" diff --git a/Cargo.toml b/Cargo.toml index 1693a21..320b57b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,5 @@ ratatui = "0.25.0" crossterm = "0.27.0" rand = "0.8.5" petgraph = "0.6.4" -whoami = "1.4.1" \ No newline at end of file +whoami = "1.4.1" +clap = { version = "4.4.11", features = ["derive"] } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 6cd4240..3ddc738 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ use std::io::Result; use std::io::stdout; +use std::string::ToString; use std::time::Instant; +use clap::Parser; use crossterm::{ event::{self, KeyCode, KeyEventKind}, ExecutableCommand, @@ -35,8 +37,18 @@ mod dungeon_slayer; /// length of a game frame in ms pub const FRAME_LENGTH: u64 = 100; +#[derive(Parser)] +#[command(author, version, about = "A small game in the tradition of rogue.", long_about = None)] +struct CliOptions { + #[arg(short, long, action)] + manual: bool, +} + // fn main() -> Result<()> { + let cli_options = CliOptions::parse(); + + let player_stats = PlayerStats::create_random(); let mut game = Game::new(Player::new(realname().as_str(), player_stats)); @@ -45,185 +57,219 @@ fn main() -> Result<()> { let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; terminal.clear()?; - let start_time = Instant::now(); - let mut ticks = 0; - loop { - terminal.draw(|frame| { - let mut area = frame.size(); - frame.render_widget(Block::default().style(Style::default().bg(Color::Green)), area); - - // don't draw stuff except an info box if the terminal is too small (less than 80x25) - // to prevent the read drawing code from crashing the game. - if area.width < 80 || area.height < 25 { + if cli_options.manual { + loop { + let _ = terminal.draw(|frame| { + let mut area = frame.size(); + let w = area.width / 2; + let h = area.height / 2; + area.x += w - 20; + area.y += h - 10; + area.width = 40; + area.height = 20; let block = Block::default() - .title("Info") + .title(Title::from(" Manual ").alignment(Alignment::Center).position(Position::Top)) + .title(Title::from("Press `q` to quit!").position(Position::Bottom)) .borders(Borders::ALL) .border_style(Style::default().fg(Color::White)) .border_type(BorderType::Rounded) .style(Style::default().bg(Color::Black)); - let paragraph = Paragraph::new("Terminal needs to be at leas 80x25!") - .block(block) - .wrap(Wrap { trim: true }); + let mut text = "To control your character (depicted by the 8) you can use the cursor keys. \n\n\ + To interact simply walk into the entity to interact with. Possible entities are creates \ + (depicted by C), potions (depicted by P) or enemies.".to_string(); + let paragraph = Paragraph::new(text).block(block).wrap(Wrap { trim: true }); frame.render_widget(paragraph, area); - return; - } - - if area.width > 80 { - area.x = (area.width - 80) / 2; - area.width = 80; - } - if area.height > 25 { - area.y = (area.height - 25) / 2; - area.height = 25; - } - - let map_area = Rect { - x: area.x, - y: area.y, - width: level::LEVEL_WIDTH as u16, - height: level::LEVEL_HEIGHT as u16, - }; - frame.render_stateful_widget(LevelWidget::new(game.uses_fog_of_war()), map_area, &mut game); - - let stats_area = Rect { - x: area.x + 50, - y: area.y, - width: 30, - height: 15, - }; - let block = Block::default() - .title( - Title::from( - format!(" {} ", game.get_player().get_name())) - .alignment(Alignment::Center) - .position(Position::Top) - ) - .borders(Borders::TOP) - .border_style(Style::default().fg(Color::White)) - .border_type(BorderType::Rounded) - .style(Style::default().bg(Color::Blue)); - frame.render_widget( - Paragraph::new(format!("Health: {}/{}\nExp: {}\nGold: {}\nLevel: {}", - game.get_player().get_life(), - game.get_player().get_max_life(), - game.get_player().get_experience(), - game.get_player().get_gold(), - game.get_player().get_immutable_position().get_level())) - .block(block).wrap(Wrap { trim: true }), - stats_area, - ); - let messages_area = Rect { - x: area.x + 50, - y: area.y + 15, - width: 30, - height: 10, - }; - // Display the latest messages from the game to the user - let block = Block::default() - .title(Title::from(" messages ").alignment(Alignment::Center).position(Position::Top)) - .borders(Borders::TOP) - .border_style(Style::default().fg(Color::White)) - .border_type(BorderType::Rounded) - .style(Style::default().bg(Color::Blue)); - - let paragraph1 = if game.messages.is_empty() { "".to_string() } else { format!("> {}", game.messages.join("\n> ")) }; - frame.render_widget( - Paragraph::new(paragraph1).block(block).wrap(Wrap { trim: true }), - messages_area, - ); - })?; - let mut player_moved = false; - if event::poll(std::time::Duration::from_millis(FRAME_LENGTH))? { - if let event::Event::Key(key) = event::read()? { - if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('v') { - game.messages.insert(0, format!("You are playing version '{}'.", env!("GIT_HASH")).to_string()); - } - // disabling the d key (disable fog of war) in release builds! - #[cfg(debug_assertions)] - if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('d') { - game.messages.insert(0, "toggle fog of war!".to_string()); - game.toggle_fog_of_war(); - } - - if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { - break; - } - if key.kind == KeyEventKind::Press { - let new_pos = match key.code { - KeyCode::Left => { - player_moved = true; - game.move_player(-1, 0) - } - KeyCode::Right => { - player_moved = true; - game.move_player(1, 0) - } - KeyCode::Up => { - player_moved = true; - game.move_player(0, -1) - } - KeyCode::Down => { - player_moved = true; - game.move_player(0, 1) - } - _ => { (0, 0) } - }; - if !game.player_fights_monster() { - // player attacked monster but did not kill it - game.move_player(new_pos.0, new_pos.1); + }); + if event::poll(std::time::Duration::from_millis(16))? { + if let event::Event::Key(key) = event::read()? { + if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { + break; } - game.player_collects_artifact(); } } } - game.update_level(ticks, player_moved); - if game.get_game_state() != GameState::RUNNING { - break; + } else { + let start_time = Instant::now(); + let mut ticks = 0; + loop { + terminal.draw(|frame| { + let mut area = frame.size(); + frame.render_widget(Block::default().style(Style::default().bg(Color::Green)), area); + + // don't draw stuff except an info box if the terminal is too small (less than 80x25) + // to prevent the read drawing code from crashing the game. + if area.width < 80 || area.height < 25 { + let block = Block::default() + .title("Info") + .borders(Borders::ALL) + .border_style(Style::default().fg(Color::White)) + .border_type(BorderType::Rounded) + .style(Style::default().bg(Color::Black)); + let paragraph = Paragraph::new("Terminal needs to be at leas 80x25!") + .block(block) + .wrap(Wrap { trim: true }); + frame.render_widget(paragraph, area); + return; + } + + if area.width > 80 { + area.x = (area.width - 80) / 2; + area.width = 80; + } + if area.height > 25 { + area.y = (area.height - 25) / 2; + area.height = 25; + } + + let map_area = Rect { + x: area.x, + y: area.y, + width: level::LEVEL_WIDTH as u16, + height: level::LEVEL_HEIGHT as u16, + }; + frame.render_stateful_widget(LevelWidget::new(game.uses_fog_of_war()), map_area, &mut game); + + let stats_area = Rect { + x: area.x + 50, + y: area.y, + width: 30, + height: 15, + }; + let block = Block::default() + .title( + Title::from( + format!(" {} ", game.get_player().get_name())) + .alignment(Alignment::Center) + .position(Position::Top) + ) + .borders(Borders::TOP) + .border_style(Style::default().fg(Color::White)) + .border_type(BorderType::Rounded) + .style(Style::default().bg(Color::Blue)); + frame.render_widget( + Paragraph::new(format!("Health: {}/{}\nExp: {}\nGold: {}\nLevel: {}", + game.get_player().get_life(), + game.get_player().get_max_life(), + game.get_player().get_experience(), + game.get_player().get_gold(), + game.get_player().get_immutable_position().get_level())) + .block(block).wrap(Wrap { trim: true }), + stats_area, + ); + let messages_area = Rect { + x: area.x + 50, + y: area.y + 15, + width: 30, + height: 10, + }; + // Display the latest messages from the game to the user + let block = Block::default() + .title(Title::from(" messages ").alignment(Alignment::Center).position(Position::Top)) + .borders(Borders::TOP) + .border_style(Style::default().fg(Color::White)) + .border_type(BorderType::Rounded) + .style(Style::default().bg(Color::Blue)); + + let paragraph1 = if game.messages.is_empty() { "".to_string() } else { format!("> {}", game.messages.join("\n> ")) }; + frame.render_widget( + Paragraph::new(paragraph1).block(block).wrap(Wrap { trim: true }), + messages_area, + ); + })?; + let mut player_moved = false; + if event::poll(std::time::Duration::from_millis(FRAME_LENGTH))? { + if let event::Event::Key(key) = event::read()? { + if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('v') { + game.messages.insert(0, format!("You are playing version '{}'.", env!("GIT_HASH")).to_string()); + } + // disabling the d key (disable fog of war) in release builds! + #[cfg(debug_assertions)] + if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('d') { + game.messages.insert(0, "toggle fog of war!".to_string()); + game.toggle_fog_of_war(); + } + + if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { + break; + } + if key.kind == KeyEventKind::Press { + let new_pos = match key.code { + KeyCode::Left => { + player_moved = true; + game.move_player(-1, 0) + } + KeyCode::Right => { + player_moved = true; + game.move_player(1, 0) + } + KeyCode::Up => { + player_moved = true; + game.move_player(0, -1) + } + KeyCode::Down => { + player_moved = true; + game.move_player(0, 1) + } + _ => { (0, 0) } + }; + if !game.player_fights_monster() { + // player attacked monster but did not kill it + game.move_player(new_pos.0, new_pos.1); + } + game.player_collects_artifact(); + } + } + } + game.update_level(ticks, player_moved); + if game.get_game_state() != GameState::RUNNING { + break; + } + ticks += 1; } - ticks += 1; - } - let playtime = start_time.elapsed(); - loop { - let _ = terminal.draw(|frame| { - let mut area = frame.size(); - let w = area.width / 2; - let h = area.height / 2; - area.x += w - 20; - area.y += h - 10; - area.width = 40; - area.height = 20; - let block = Block::default() - .title(Title::from(" Game ended ").alignment(Alignment::Center).position(Position::Top)) - .title(Title::from("Press `q` to quit!").position(Position::Bottom)) - .borders(Borders::ALL) - .border_style(Style::default().fg(Color::White)) - .border_type(BorderType::Rounded) - .style(Style::default().bg(Color::Black)); - let mut text = match game.get_game_state() { - GameState::RUNNING => { - "Quitting is for cowards! You'll better try again!".to_string() - } - GameState::LOST => { - format!("Sorry, you died in the dungeon. Better luck next time!\nLast message:\n{}", game.messages[0]).to_string() - } - GameState::WON => { - "Congratulation! You mastered your way through the dungeon and won the game.".to_string() - } - }; - text += format!("\n\nYou gained {} experience.", game.get_player().get_experience()).as_str(); - text += format!("\nYou collected {} gold.", game.get_player().get_gold()).as_str(); - text += format!("\nYou played {} seconds.", playtime.as_secs()).as_str(); - let paragraph = Paragraph::new(text).block(block).wrap(Wrap { trim: true }); - frame.render_widget(paragraph, area); - }); - if event::poll(std::time::Duration::from_millis(16))? { - if let event::Event::Key(key) = event::read()? { - if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { - break; + let playtime = start_time.elapsed(); + loop { + let _ = terminal.draw(|frame| { + let mut area = frame.size(); + let w = area.width / 2; + let h = area.height / 2; + area.x += w - 20; + area.y += h - 10; + area.width = 40; + area.height = 20; + let block = Block::default() + .title(Title::from(" Game ended ").alignment(Alignment::Center).position(Position::Top)) + .title(Title::from("Press `q` to quit!").position(Position::Bottom)) + .borders(Borders::ALL) + .border_style(Style::default().fg(Color::White)) + .border_type(BorderType::Rounded) + .style(Style::default().bg(Color::Black)); + let mut text = match game.get_game_state() { + GameState::RUNNING => { + "Quitting is for cowards! You'll better try again!".to_string() + } + GameState::LOST => { + format!("Sorry, you died in the dungeon. Better luck next time!\nLast message:\n{}", game.messages[0]).to_string() + } + GameState::WON => { + "Congratulation! You mastered your way through the dungeon and won the game.".to_string() + } + }; + text += format!("\n\nYou gained {} experience.", game.get_player().get_experience()).as_str(); + text += format!("\nYou collected {} gold.", game.get_player().get_gold()).as_str(); + text += format!("\nYou played {} seconds.", playtime.as_secs()).as_str(); + let paragraph = Paragraph::new(text).block(block).wrap(Wrap { trim: true }); + frame.render_widget(paragraph, area); + }); + if event::poll(std::time::Duration::from_millis(16))? { + if let event::Event::Key(key) = event::read()? { + if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { + break; + } } } } } + stdout().execute(LeaveAlternateScreen)?; disable_raw_mode()?; Ok(())