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}