1use std::{env, thread, time};
19
20use crate::{floor::Floor, unit::UnitType, Player};
21
22#[cfg(feature = "ncurses")]
23pub mod curses;
24pub mod systems;
25pub mod world;
26
27use systems::{player_system, shooter_system, sludge_system, ui_system};
28use world::World;
29
30const DEFAULT_GAME_LOOP_DELAY: u64 = 1000;
31
32pub fn start(
34 player_name: String,
35 warrior_level: usize,
36 floor: Floor,
37 player_generator: fn() -> Box<dyn Player + Send + Sync>,
38) -> Result<(), String> {
39 let player = player_generator();
40
41 #[cfg(feature = "ncurses")]
42 let mut c = curses::Curses::new();
43
44 #[cfg(not(feature = "ncurses"))]
45 println!("{}", floor.draw());
46
47 let mut step = 0;
48
49 let mut warrior = None;
50 let mut other_units = Vec::new();
51 for unit in &floor.units {
52 match unit.unit_type {
53 UnitType::Warrior => {
54 warrior = Some(unit.clone());
55 }
56 _ => {
57 other_units.push(unit.clone());
58 }
59 }
60 }
61 let warrior = warrior.unwrap();
62
63 let mut world = World::new(
64 player_name,
65 warrior_level,
66 floor,
67 player,
68 warrior,
69 other_units,
70 );
71
72 let override_delay = env::var("GAME_LOOP_DELAY")
73 .ok()
74 .and_then(|s| s.parse::<u64>().ok());
75
76 loop {
77 step += 1;
78
79 if step > 100 {
80 return Err(format!(
81 "{} seems to have gotten lost...",
82 &world.player_name
83 ));
84 }
85
86 let (current, _) = world.warrior.hp;
87 if current == 0 {
88 return Err(format!("{} died!", &world.player_name));
89 }
90 if world.warrior.position == world.floor.stairs {
91 return Ok(());
92 }
93
94 let mut events = Vec::new();
95
96 let mut player_events = player_system(&mut world);
97 events.append(&mut player_events);
98
99 let mut sludge_events = sludge_system(&mut world);
100 events.append(&mut sludge_events);
101
102 let mut shooter_events = shooter_system(&mut world);
103 events.append(&mut shooter_events);
104
105 let num_events = events.len() as u64;
106
107 #[cfg(feature = "ncurses")]
108 ui_system(&world, events, &mut c);
109
110 #[cfg(not(feature = "ncurses"))]
111 ui_system(&world, events);
112
113 let delay = match override_delay {
114 Some(delay) => delay,
115 None => DEFAULT_GAME_LOOP_DELAY + num_events * 200,
116 };
117 thread::sleep(time::Duration::from_millis(delay));
118 }
119}