diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 2bc5f4f6..3b14e4cf 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,3 +1,5 @@ +use rand::Rng; + use crate::{model::{Galaxy, Pos, COURSES, EndPosition, self, Enterprise, systems}, view, input}; pub fn perform_short_range_scan(galaxy: &Galaxy) { @@ -66,9 +68,53 @@ pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec if galaxy.enterprise.destroyed { return; } + + repair_systems(&mut galaxy.enterprise, speed); + repair_or_damage_random_system(&mut galaxy.enterprise); + move_enterprise(course, speed, galaxy); } +fn repair_systems(enterprise: &mut Enterprise, amount: f32) { + + let keys: Vec = enterprise.damaged.keys().map(|k| k.to_string()).collect(); + let mut repaired = Vec::new(); + for key in keys { + let fully_fixed = enterprise.repair_system(&key, amount); + if fully_fixed { + repaired.push(systems::name_for(&key)); + } + } + + if repaired.len() <= 0 { + return; + } + + view::damage_control_report(); + for name in repaired { + view::system_repair_completed(name); + } +} + +fn repair_or_damage_random_system(enterprise: &mut Enterprise) { + let mut rng = rand::thread_rng(); + + if rng.gen::() > 0.2 { + return; + } + + let system = systems::KEYS[rng.gen_range(0..systems::KEYS.len())].to_string(); + let system_name = &systems::name_for(&system); + + if rng.gen::() >= 0.6 { + enterprise.repair_system(&system, rng.gen::() * 3.0 + 1.0); + view::random_repair_report_for(system_name, false); + } else { + enterprise.damage_system(&system, rng.gen::() * 5.0 + 1.0); + view::random_repair_report_for(system_name, true); + } +} + fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { let ship = &mut galaxy.enterprise; @@ -154,9 +200,9 @@ pub fn display_damage_control(enterprise: &Enterprise) { } println!("Device State of Repair"); - for i in 0..systems::NAMES.len() { - let damage = enterprise.damaged.get(systems::ALL[i]).unwrap_or(&0.0); - println!("{:<25}{}", systems::NAMES[i], damage) + for key in systems::KEYS { + let damage = enterprise.damaged.get(key).unwrap_or(&0.0); + println!("{:<25}{}", systems::name_for(key), damage) } println!(); } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 675ac8ec..515b7fb2 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -74,27 +74,47 @@ impl Enterprise { return } - let system = systems::ALL[rng.gen_range(0..systems::ALL.len())].to_string(); + let system = systems::KEYS[rng.gen_range(0..systems::KEYS.len())].to_string(); let damage = hit_past_shield + rng.gen::() * 0.5; - self.damaged.entry(system).and_modify(|d| *d -= damage).or_insert(-damage); + self.damage_system(&system, damage); + } + + pub fn damage_system(&mut self, system: &str, damage: f32) { + self.damaged.entry(system.to_string()).and_modify(|d| *d -= damage).or_insert(-damage); + } + + pub fn repair_system(&mut self, system: &str, amount: f32) -> bool { + let existing_damage = self.damaged[system]; + if existing_damage + amount >= 0.0 { + self.damaged.remove(system); + return true; + } + + self.damaged.entry(system.to_string()).and_modify(|d| *d += amount); + return false; } } pub mod systems { - use std::collections::HashMap; pub const SHORT_RANGE_SCAN: &str = "SRS"; pub const WARP_ENGINES: &str = "NAV"; pub const SHIELD_CONTROL: &str = "SHE"; pub const DAMAGE_CONTROL: &str = "DAM"; - pub const ALL: [&str; 4] = [ + pub const KEYS: [&str; 4] = [ SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL, DAMAGE_CONTROL ]; - pub const NAMES: [&str; 4] = [ - "Short Range Scanners", "Warp Engines", "Shield Control", "Damage Control" - ]; + pub fn name_for(key: &str) -> String { + match key { + SHORT_RANGE_SCAN => "Short Range Scanners".into(), + WARP_ENGINES => "Warp Engines".into(), + SHIELD_CONTROL => "Shield Control".into(), + DAMAGE_CONTROL => "Damage Control".into(), + _ => "Unknown".into() + } + } } pub struct EndPosition { diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index e7bc5516..e34c44d4 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -208,3 +208,19 @@ pub fn damaged_engines(max_warp: f32, warp_factor: f32) { println!("Warp engines are damaged. Maximum speed = warp {max_warp} Chief Engineer Scott reports, 'The engines won't take warp {warp_factor} !'") } + +pub fn damage_control_report() { + println!("Damage Control report:") +} + +pub fn random_repair_report_for(name: &str, damaged: bool) { + let mut message = "state of repair improved"; + if damaged { + message = "damaged"; + } + println!("Damage Control report: {name} {message}") +} + +pub fn system_repair_completed(name: String) { + println!(" {name} repair completed.") +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index e6c68ce1..0c81bce1 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -13,7 +13,7 @@ Started after movement and display of stats was finished (no energy management o - [x] shield hit absorption - [x] subsystem damage - [x] and support for reports -- [ ] random system damage on move +- [x] random system damage or repairs on move - [ ] lrs? - [ ] stranded... - [ ] stop before hitting an object