dcss_scenario_builder/lib.rs
1//! A crate to create scenarios in DCSS (wizmode) from a yaml file.
2
3mod common;
4mod lua_builder;
5mod scenario_errors;
6mod wizmode;
7
8pub use scenario_errors::{Error, YamlParsingError};
9use wizmode::{enable_wiz, setup_map};
10
11use dcss_api::Webtile;
12use std::fs;
13
14use crate::lua_builder::process_scenario;
15
16/// Start a game, using [dcss_api::Webtile::start_game_seeded], with a scenario yaml file.
17///
18/// # Arguments
19///
20/// * `webtile` - A [dcss_api::Webtile] connection.
21/// * `game_id` - A string slice of the game's ID.
22/// * `species` - A string slice for the character's species.
23/// * `background` - A string slice for the character's background.
24/// * `weapon` - A string slice for the character's weapon.
25/// * `scenario_file` - a path to a YAML scenario file.
26///
27/// # Example
28///
29/// ```no_run
30/// // Start a scenario game, for a Minotaur (b), Berserker (f), with a mace (b) using the
31/// // branches.yaml scenario.
32/// start_game_with_scenario(&mut webtile, "dcss-0.33", "b", "f", "b", "./scenarios/branches.yaml")?;
33/// ```
34pub fn start_game_with_scenario(
35 webtile: &mut Webtile,
36 game_id: &str,
37 species: &str,
38 background: &str,
39 weapon: &str,
40 scenario_file: &str,
41) -> Result<(), Error> {
42 // Process the scenario into Lua
43 let (player_pos_d1, levels) = process_scenario(scenario_file)?;
44
45 // Write RC File (prevent "more" error)
46 webtile.set_rc_file(game_id, "show_more = false\nrest_delay = -1")?;
47
48 // Start game
49 webtile.start_game_seeded(game_id, "1", false, species, background, weapon)?;
50
51 // Read the messages and if player["wizard"] == 1 it means that wizmode is already
52 // set up, meaning this code has already been run -- skip the setup code
53 while let Some(message) = webtile.get_message() {
54 if message["msg"].as_str().unwrap() == "player"
55 && message.as_object().unwrap().contains_key("wizard")
56 && message["wizard"].as_u64().unwrap() == 1
57 {
58 return Ok(());
59 }
60 }
61
62 // Enable the wizmode
63 enable_wiz(webtile)?;
64
65 // Set up the map
66 setup_map(webtile, player_pos_d1, levels)?;
67
68 // Empty message queue
69 while webtile.get_message().is_some() {}
70
71 // Since it's "start game with" -- the game should continue
72 webtile.continue_game(game_id)?;
73
74 Ok(())
75}
76
77/// Print the created lua from the scenario_file to the log, to help debug issues in the YAML.
78///
79/// # Arguments
80///
81/// * `scenario_file` - a path to a YAML scenario file.
82///
83/// # Example
84///
85/// ```no_run
86/// // Print the lua using the `branches.yaml` scenario.
87/// debug_print_lua("./scenarios/branches.yaml")?;
88/// ```
89pub fn debug_print_lua(scenario_file: &str) -> Result<(), Error> {
90 let (_player_pos_d1, levels) = process_scenario(scenario_file)?;
91
92 for level in levels {
93 println!("\n\n========= {} ========\n\n{}", level.0, level.1);
94 }
95
96 Ok(())
97}
98
99/// Save a txt of the created lua from the scenario_file, to help debug issues in the YAML.
100///
101/// # Arguments
102///
103/// * `scenario_file` - a path to a YAML scenario file.
104/// * `save_file` - a path to a the txt output file.
105///
106/// # Example
107///
108/// ```no_run
109/// // Save the lua using the `branches.yaml` scenario, to `branches.txt`
110/// debug_save_lua("./scenarios/branches.yaml", "branches.txt")?;
111/// ```
112pub fn debug_save_lua(scenario_file: &str, save_file: &str) -> Result<(), Error> {
113 let (_player_pos_d1, levels) = process_scenario(scenario_file)?;
114
115 let mut content = String::new();
116
117 for level in levels {
118 content.push_str(&format!(
119 "\n\n========= {} ========\n\n{}",
120 level.0, level.1
121 ));
122 }
123
124 fs::write(save_file, content)?;
125
126 Ok(())
127}