From c4b8da053bc37e940ab998593cf0fb8cd136eb11 Mon Sep 17 00:00:00 2001 From: Christopher Date: Tue, 28 Feb 2023 11:37:54 +1300 Subject: [PATCH 01/72] started work on a rust implementation of super star trek --- 84_Super_Star_Trek/rust/Cargo.toml | 8 ++++++ 84_Super_Star_Trek/rust/src/main.rs | 34 ++++++++++++++++++++++ 84_Super_Star_Trek/rust/src/model.rs | 43 ++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 84_Super_Star_Trek/rust/Cargo.toml create mode 100644 84_Super_Star_Trek/rust/src/main.rs create mode 100644 84_Super_Star_Trek/rust/src/model.rs diff --git a/84_Super_Star_Trek/rust/Cargo.toml b/84_Super_Star_Trek/rust/Cargo.toml new file mode 100644 index 00000000..1ec69633 --- /dev/null +++ b/84_Super_Star_Trek/rust/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs new file mode 100644 index 00000000..673b6700 --- /dev/null +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -0,0 +1,34 @@ +use model::{Galaxy, GameStatus, Pos, Quadrant}; + +mod model; + +fn main() { + let mut galaxy = Galaxy::generate_new(); + // create the model + // start the loop + loop { + view(&galaxy); + galaxy = wait_for_command(&galaxy); + } + // rather than using a loop, recursion and passing the ownership might be better +} + +fn view(model: &Galaxy) { + match model.game_status { + GameStatus::ShortRangeScan => { + let quadrant = &model.quadrants[model.enterprise.sector.as_index()]; + render_quadrant(&model.enterprise.sector, quadrant) + } + } +} + +fn render_quadrant(enterprise_sector: &Pos, quadrant: &Quadrant) { + +} + +fn wait_for_command(galaxy: &Galaxy) -> Galaxy { + // listen for command from readline + // handle bad commands + // update model + Galaxy::generate_new() +} \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs new file mode 100644 index 00000000..9ca50189 --- /dev/null +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -0,0 +1,43 @@ + +pub struct Galaxy { + pub quadrants: Vec, + pub enterprise: Enterprise, + pub game_status: GameStatus +} + +pub struct Pos(u8, u8); + +impl Pos { + pub fn as_index(&self) -> usize { + (self.0 * 8 + self.1).into() + } +} + +pub struct Quadrant { + pub stars: Vec, + pub star_bases: Vec, + pub klingons: Vec +} + +pub struct Klingon { + pub sector: Pos +} + +pub struct Enterprise { + pub quadrant: Pos, + pub sector: Pos, +} + +pub enum GameStatus { + ShortRangeScan +} + +impl Galaxy { + pub fn generate_new() -> Self { + Galaxy { + quadrants: Vec::new(), + enterprise: Enterprise { quadrant: Pos(0,0), sector: Pos(0,0) }, + game_status: GameStatus::ShortRangeScan + } + } +} \ No newline at end of file From 92b4d60e84da5f0c310c22a1a4550352623cfb5a Mon Sep 17 00:00:00 2001 From: Christopher Date: Tue, 28 Feb 2023 12:36:29 +1300 Subject: [PATCH 02/72] work aligning with mvu, along with a render quadrant view function --- 84_Super_Star_Trek/rust/src/main.rs | 56 ++++++++++++++++++--------- 84_Super_Star_Trek/rust/src/model.rs | 3 +- 84_Super_Star_Trek/rust/src/update.rs | 15 +++++++ 84_Super_Star_Trek/rust/src/view.rs | 35 +++++++++++++++++ 4 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 84_Super_Star_Trek/rust/src/update.rs create mode 100644 84_Super_Star_Trek/rust/src/view.rs diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 673b6700..86bc2d85 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,34 +1,54 @@ -use model::{Galaxy, GameStatus, Pos, Quadrant}; +use std::io::stdin; + +use model::{Galaxy, GameStatus}; +use update::Message; mod model; +mod view; +mod update; fn main() { let mut galaxy = Galaxy::generate_new(); - // create the model - // start the loop loop { - view(&galaxy); - galaxy = wait_for_command(&galaxy); + view::view(&galaxy); + let command = wait_for_command(&galaxy.game_status); + galaxy = update::update(command, galaxy) } - // rather than using a loop, recursion and passing the ownership might be better } -fn view(model: &Galaxy) { - match model.game_status { - GameStatus::ShortRangeScan => { - let quadrant = &model.quadrants[model.enterprise.sector.as_index()]; - render_quadrant(&model.enterprise.sector, quadrant) +fn wait_for_command(game_status: &GameStatus) -> Message { + let stdin = stdin(); + loop { + match game_status { + _ => { + println!("Command?"); + let mut buffer = String::new(); + if let Ok(_) = stdin.read_line(&mut buffer) { + let text = buffer.trim_end(); + if let Some(msg) = as_message(text, game_status) { + return msg + } + print_command_help(); + } + } } } } -fn render_quadrant(enterprise_sector: &Pos, quadrant: &Quadrant) { - +fn as_message(text: &str, game_status: &GameStatus) -> Option { + if text == "" { + return None + } + match game_status { + _ => { + match text { + "SRS" => Some(Message::RequestShortRangeScan), + _ => None + } + } + } } -fn wait_for_command(galaxy: &Galaxy) -> Galaxy { - // listen for command from readline - // handle bad commands - // update model - Galaxy::generate_new() +fn print_command_help() { + println!("valid commands are just SRS at the mo") } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 9ca50189..2a03bbd9 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -5,7 +5,8 @@ pub struct Galaxy { pub game_status: GameStatus } -pub struct Pos(u8, u8); +#[derive(PartialEq)] +pub struct Pos(pub u8, pub u8); impl Pos { pub fn as_index(&self) -> usize { diff --git a/84_Super_Star_Trek/rust/src/update.rs b/84_Super_Star_Trek/rust/src/update.rs new file mode 100644 index 00000000..cf30c83e --- /dev/null +++ b/84_Super_Star_Trek/rust/src/update.rs @@ -0,0 +1,15 @@ +use crate::model::{Galaxy, GameStatus}; + +pub enum Message { + RequestShortRangeScan +} + +pub fn update(message: Message, model: Galaxy) -> Galaxy { + match message { + Message::RequestShortRangeScan => + Galaxy { + game_status: GameStatus::ShortRangeScan, + ..model + } + } +} \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs new file mode 100644 index 00000000..2f6bdf22 --- /dev/null +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -0,0 +1,35 @@ +use crate::model::{Galaxy, GameStatus, Quadrant, Pos, Klingon}; + + +pub fn view(model: &Galaxy) { + match model.game_status { + GameStatus::ShortRangeScan => { + let quadrant = &model.quadrants[model.enterprise.sector.as_index()]; + render_quadrant(&model.enterprise.sector, quadrant) + } + } +} + +fn render_quadrant(enterprise_sector: &Pos, quadrant: &Quadrant) { + println!("{:-^33}", ""); + for y in 0..=7 { + for x in 0..=7 { + let pos = Pos(x, y); + if &pos == enterprise_sector { + print!("<*> ") + } else if quadrant.stars.contains(&pos) { + print!(" * ") + } else if quadrant.star_bases.contains(&pos) { + print!(">!< ") + } else if let Some(_) = find_klingon(&pos, &quadrant.klingons) { + print!("+K+ ") + } + } + print!("\n") + } + println!("{:-^33}", ""); +} + +fn find_klingon<'a>(sector: &Pos, klingons: &'a Vec) -> Option<&'a Klingon> { + klingons.into_iter().find(|k| &k.sector == sector) +} \ No newline at end of file From c35736c5c8cc61f9bf070e65ab776f73fa92b297 Mon Sep 17 00:00:00 2001 From: Christopher Date: Tue, 28 Feb 2023 13:28:08 +1300 Subject: [PATCH 03/72] enterprise now starts in a random quadrant and empty sector --- 84_Super_Star_Trek/rust/Cargo.toml | 1 + 84_Super_Star_Trek/rust/src/main.rs | 7 ++- 84_Super_Star_Trek/rust/src/model.rs | 85 +++++++++++++++++++++++++++- 84_Super_Star_Trek/rust/src/view.rs | 21 +++---- 4 files changed, 97 insertions(+), 17 deletions(-) diff --git a/84_Super_Star_Trek/rust/Cargo.toml b/84_Super_Star_Trek/rust/Cargo.toml index 1ec69633..3b1d02f5 100644 --- a/84_Super_Star_Trek/rust/Cargo.toml +++ b/84_Super_Star_Trek/rust/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +rand = "0.8.5" diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 86bc2d85..20cd7ea3 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,4 +1,4 @@ -use std::io::stdin; +use std::io::{stdin, stdout, Write}; use model::{Galaxy, GameStatus}; use update::Message; @@ -18,10 +18,13 @@ fn main() { fn wait_for_command(game_status: &GameStatus) -> Message { let stdin = stdin(); + let mut stdout = stdout(); loop { match game_status { _ => { - println!("Command?"); + print!("Command? "); + let _ = stdout.flush(); + let mut buffer = String::new(); if let Ok(_) = stdin.read_line(&mut buffer) { let text = buffer.trim_end(); diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 2a03bbd9..4468e6f9 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -1,3 +1,4 @@ +use rand::Rng; pub struct Galaxy { pub quadrants: Vec, @@ -14,9 +15,14 @@ impl Pos { } } +#[derive(PartialEq)] +pub enum SectorStatus { + Empty, Star, StarBase, Klingon +} + pub struct Quadrant { pub stars: Vec, - pub star_bases: Vec, + pub star_base: Option, pub klingons: Vec } @@ -35,10 +41,83 @@ pub enum GameStatus { impl Galaxy { pub fn generate_new() -> Self { + let quadrants = Self::generate_quadrants(); + + let mut rng = rand::thread_rng(); + let enterprise_quadrant = Pos(rng.gen_range(0..8), rng.gen_range(0..8)); + let enterprise_sector = quadrants[enterprise_quadrant.as_index()].find_empty_sector(); + Galaxy { - quadrants: Vec::new(), - enterprise: Enterprise { quadrant: Pos(0,0), sector: Pos(0,0) }, + quadrants: quadrants, + enterprise: Enterprise { quadrant: enterprise_quadrant, sector: enterprise_sector }, game_status: GameStatus::ShortRangeScan } } + + fn generate_quadrants() -> Vec { + let mut rng = rand::thread_rng(); + let mut result = Vec::new(); + for _ in 0..64 { + + let mut quadrant = Quadrant { stars: Vec::new(), star_base: None, klingons: Vec::new() }; + let star_count = rng.gen_range(0..=7); + for _ in 0..star_count { + quadrant.stars.push(quadrant.find_empty_sector()); + } + + if rng.gen::() > 0.96 { + quadrant.star_base = Some(quadrant.find_empty_sector()); + } + + let klingon_count = + match rng.gen::() { + n if n > 0.98 => 3, + n if n > 0.95 => 2, + n if n > 0.8 => 1, + _ => 0 + }; + for _ in 0..klingon_count { + quadrant.klingons.push(Klingon { sector: quadrant.find_empty_sector() }); + } + + result.push(quadrant); + } + result + } +} + +impl Quadrant { + pub fn sector_status(&self, sector: &Pos) -> SectorStatus { + if self.stars.contains(§or) { + SectorStatus::Star + } else if self.is_starbase(§or) { + SectorStatus::StarBase + } else if self.has_klingon(§or) { + SectorStatus::Klingon + } else { + SectorStatus::Empty + } + } + + fn is_starbase(&self, sector: &Pos) -> bool { + match &self.star_base { + None => false, + Some(p) => p == sector + } + } + + fn has_klingon(&self, sector: &Pos) -> bool { + let klingons = &self.klingons; + klingons.into_iter().find(|k| &k.sector == sector).is_some() + } + + fn find_empty_sector(&self) -> Pos { + let mut rng = rand::thread_rng(); + loop { + let pos = Pos(rng.gen_range(0..8), rng.gen_range(0..8)); + if self.sector_status(&pos) == SectorStatus::Empty { + return pos + } + } + } } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 2f6bdf22..4f0975cf 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,4 +1,4 @@ -use crate::model::{Galaxy, GameStatus, Quadrant, Pos, Klingon}; +use crate::model::{Galaxy, GameStatus, Quadrant, Pos, SectorStatus}; pub fn view(model: &Galaxy) { @@ -17,19 +17,16 @@ fn render_quadrant(enterprise_sector: &Pos, quadrant: &Quadrant) { let pos = Pos(x, y); if &pos == enterprise_sector { print!("<*> ") - } else if quadrant.stars.contains(&pos) { - print!(" * ") - } else if quadrant.star_bases.contains(&pos) { - print!(">!< ") - } else if let Some(_) = find_klingon(&pos, &quadrant.klingons) { - print!("+K+ ") - } + } else { + match quadrant.sector_status(&pos) { + SectorStatus::Star => print!(" * "), + SectorStatus::StarBase => print!(">!< "), + SectorStatus::Klingon => print!("+K+ "), + _ => print!(" "), + } + } } print!("\n") } println!("{:-^33}", ""); } - -fn find_klingon<'a>(sector: &Pos, klingons: &'a Vec) -> Option<&'a Klingon> { - klingons.into_iter().find(|k| &k.sector == sector) -} \ No newline at end of file From 31b9834a7c1967d56f5634329742c7bc9885a44f Mon Sep 17 00:00:00 2001 From: Christopher Date: Tue, 28 Feb 2023 13:53:38 +1300 Subject: [PATCH 04/72] work on nav command this involves architectural shifts --- 84_Super_Star_Trek/rust/src/main.rs | 62 +++++++++++++++++++-------- 84_Super_Star_Trek/rust/src/model.rs | 4 +- 84_Super_Star_Trek/rust/src/update.rs | 23 +++++++++- 84_Super_Star_Trek/rust/src/view.rs | 5 ++- 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 20cd7ea3..43e3045c 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -17,35 +17,63 @@ fn main() { } fn wait_for_command(game_status: &GameStatus) -> Message { - let stdin = stdin(); - let mut stdout = stdout(); loop { match game_status { - _ => { - print!("Command? "); - let _ = stdout.flush(); - - let mut buffer = String::new(); - if let Ok(_) = stdin.read_line(&mut buffer) { - let text = buffer.trim_end(); - if let Some(msg) = as_message(text, game_status) { - return msg - } - print_command_help(); + GameStatus::NeedDirectionForNav => { + let text = prompt("Course (1-9)?"); + if let Some(msg) = as_message(&text, game_status) { + return msg } + }, + GameStatus::NeedSpeedForNav(_) => { + let text = prompt("Warp Factor (0-8)?"); + if let Some(msg) = as_message(&text, game_status) { + return msg + } + }, + _ => { + let text = prompt("Command?"); + if let Some(msg) = as_message(&text, game_status) { + return msg + } + print_command_help(); } } } } -fn as_message(text: &str, game_status: &GameStatus) -> Option { - if text == "" { - return None +fn prompt(prompt: &str) -> String { + let stdin = stdin(); + let mut stdout = stdout(); + + print!("{prompt} "); + let _ = stdout.flush(); + + let mut buffer = String::new(); + if let Ok(_) = stdin.read_line(&mut buffer) { + return buffer.trim_end().into(); } + "".into() +} + +fn as_message(text: &str, game_status: &GameStatus) -> Option { match game_status { + GameStatus::NeedDirectionForNav => { + match text.parse::() { + Ok(n) if (n >= 1 && n <= 8) => Some(Message::DirectionForNav(n)), + _ => None + } + }, + GameStatus::NeedSpeedForNav(dir) => { + match text.parse::() { + Ok(n) if (n >= 1 && n <= 8) => Some(Message::DirectionAndSpeedForNav(*dir, n)), + _ => None + } + } _ => { match text { "SRS" => Some(Message::RequestShortRangeScan), + "NAV" => Some(Message::RequestNavigation), _ => None } } @@ -53,5 +81,5 @@ fn as_message(text: &str, game_status: &GameStatus) -> Option { } fn print_command_help() { - println!("valid commands are just SRS at the mo") + println!("valid commands are just SRS and NAV at the mo") } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 4468e6f9..a05d8566 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -36,7 +36,9 @@ pub struct Enterprise { } pub enum GameStatus { - ShortRangeScan + ShortRangeScan, + NeedDirectionForNav, + NeedSpeedForNav(u8), } impl Galaxy { diff --git a/84_Super_Star_Trek/rust/src/update.rs b/84_Super_Star_Trek/rust/src/update.rs index cf30c83e..5788c778 100644 --- a/84_Super_Star_Trek/rust/src/update.rs +++ b/84_Super_Star_Trek/rust/src/update.rs @@ -1,7 +1,10 @@ use crate::model::{Galaxy, GameStatus}; pub enum Message { - RequestShortRangeScan + RequestShortRangeScan, + RequestNavigation, + DirectionForNav (u8), + DirectionAndSpeedForNav (u8, u8), } pub fn update(message: Message, model: Galaxy) -> Galaxy { @@ -10,6 +13,24 @@ pub fn update(message: Message, model: Galaxy) -> Galaxy { Galaxy { game_status: GameStatus::ShortRangeScan, ..model + }, + Message::RequestNavigation => { + Galaxy { + game_status: GameStatus::NeedDirectionForNav, + ..model } + }, + Message::DirectionForNav(dir) => { + Galaxy { + game_status: GameStatus::NeedSpeedForNav(dir), + ..model + } + }, + Message::DirectionAndSpeedForNav(dir, speed) => { + Galaxy { + game_status: GameStatus::ShortRangeScan, + ..model + } + } } } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 4f0975cf..9527289d 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -5,8 +5,9 @@ pub fn view(model: &Galaxy) { match model.game_status { GameStatus::ShortRangeScan => { let quadrant = &model.quadrants[model.enterprise.sector.as_index()]; - render_quadrant(&model.enterprise.sector, quadrant) - } + render_quadrant(&model.enterprise.sector, quadrant); + }, + _ => () } } From 8903e77d838e21c221a482a450a7a16ced314fca Mon Sep 17 00:00:00 2001 From: Christopher Date: Tue, 28 Feb 2023 19:45:54 +1300 Subject: [PATCH 05/72] reduced down to command and response (collapsed MVU) --- 84_Super_Star_Trek/rust/Cargo.toml | 1 + .../rust/src/{view.rs => commands.rs} | 17 +--- 84_Super_Star_Trek/rust/src/main.rs | 80 +++++-------------- 84_Super_Star_Trek/rust/src/model.rs | 12 +-- 84_Super_Star_Trek/rust/src/update.rs | 36 --------- 5 files changed, 29 insertions(+), 117 deletions(-) rename 84_Super_Star_Trek/rust/src/{view.rs => commands.rs} (54%) delete mode 100644 84_Super_Star_Trek/rust/src/update.rs diff --git a/84_Super_Star_Trek/rust/Cargo.toml b/84_Super_Star_Trek/rust/Cargo.toml index 3b1d02f5..01457249 100644 --- a/84_Super_Star_Trek/rust/Cargo.toml +++ b/84_Super_Star_Trek/rust/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +ctrlc = "3.2.5" rand = "0.8.5" diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/commands.rs similarity index 54% rename from 84_Super_Star_Trek/rust/src/view.rs rename to 84_Super_Star_Trek/rust/src/commands.rs index 9527289d..264f7909 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,22 +1,13 @@ -use crate::model::{Galaxy, GameStatus, Quadrant, Pos, SectorStatus}; +use crate::model::{Galaxy, Pos, SectorStatus}; +pub fn short_range_scan(model: &Galaxy) { + let quadrant = &model.quadrants[model.enterprise.sector.as_index()]; -pub fn view(model: &Galaxy) { - match model.game_status { - GameStatus::ShortRangeScan => { - let quadrant = &model.quadrants[model.enterprise.sector.as_index()]; - render_quadrant(&model.enterprise.sector, quadrant); - }, - _ => () - } -} - -fn render_quadrant(enterprise_sector: &Pos, quadrant: &Quadrant) { println!("{:-^33}", ""); for y in 0..=7 { for x in 0..=7 { let pos = Pos(x, y); - if &pos == enterprise_sector { + if &pos == &model.enterprise.sector { print!("<*> ") } else { match quadrant.sector_status(&pos) { diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 43e3045c..cc6948ac 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,44 +1,27 @@ -use std::io::{stdin, stdout, Write}; +use std::{io::{stdin, stdout, Write}, process::exit}; -use model::{Galaxy, GameStatus}; -use update::Message; +use model::Galaxy; mod model; -mod view; -mod update; +mod commands; fn main() { - let mut galaxy = Galaxy::generate_new(); - loop { - view::view(&galaxy); - let command = wait_for_command(&galaxy.game_status); - galaxy = update::update(command, galaxy) - } -} + ctrlc::set_handler(move || { exit(0) }) + .expect("Error setting Ctrl-C handler"); + + let galaxy = Galaxy::generate_new(); + // init ops, starting state and notes + commands::short_range_scan(&galaxy); -fn wait_for_command(game_status: &GameStatus) -> Message { loop { - match game_status { - GameStatus::NeedDirectionForNav => { - let text = prompt("Course (1-9)?"); - if let Some(msg) = as_message(&text, game_status) { - return msg - } - }, - GameStatus::NeedSpeedForNav(_) => { - let text = prompt("Warp Factor (0-8)?"); - if let Some(msg) = as_message(&text, game_status) { - return msg - } - }, - _ => { - let text = prompt("Command?"); - if let Some(msg) = as_message(&text, game_status) { - return msg - } - print_command_help(); - } + match prompt("Command?").as_str() { + "SRS" => commands::short_range_scan(&galaxy), + _ => print_command_help() } + + // process the next command, based on it render something or update the galaxy or whatever + // this would be: read command, and based on it run dedicated function + // the function might get passed a mutable reference to the galaxy } } @@ -56,30 +39,11 @@ fn prompt(prompt: &str) -> String { "".into() } -fn as_message(text: &str, game_status: &GameStatus) -> Option { - match game_status { - GameStatus::NeedDirectionForNav => { - match text.parse::() { - Ok(n) if (n >= 1 && n <= 8) => Some(Message::DirectionForNav(n)), - _ => None - } - }, - GameStatus::NeedSpeedForNav(dir) => { - match text.parse::() { - Ok(n) if (n >= 1 && n <= 8) => Some(Message::DirectionAndSpeedForNav(*dir, n)), - _ => None - } - } - _ => { - match text { - "SRS" => Some(Message::RequestShortRangeScan), - "NAV" => Some(Message::RequestNavigation), - _ => None - } - } - } -} - fn print_command_help() { println!("valid commands are just SRS and NAV at the mo") -} \ No newline at end of file +} + +// match text.parse::() { +// Ok(n) if (n >= 1 && n <= 8) => Some(Message::DirectionForNav(n)), +// _ => None +// } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index a05d8566..a0f80751 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -2,8 +2,7 @@ use rand::Rng; pub struct Galaxy { pub quadrants: Vec, - pub enterprise: Enterprise, - pub game_status: GameStatus + pub enterprise: Enterprise } #[derive(PartialEq)] @@ -35,12 +34,6 @@ pub struct Enterprise { pub sector: Pos, } -pub enum GameStatus { - ShortRangeScan, - NeedDirectionForNav, - NeedSpeedForNav(u8), -} - impl Galaxy { pub fn generate_new() -> Self { let quadrants = Self::generate_quadrants(); @@ -51,8 +44,7 @@ impl Galaxy { Galaxy { quadrants: quadrants, - enterprise: Enterprise { quadrant: enterprise_quadrant, sector: enterprise_sector }, - game_status: GameStatus::ShortRangeScan + enterprise: Enterprise { quadrant: enterprise_quadrant, sector: enterprise_sector } } } diff --git a/84_Super_Star_Trek/rust/src/update.rs b/84_Super_Star_Trek/rust/src/update.rs deleted file mode 100644 index 5788c778..00000000 --- a/84_Super_Star_Trek/rust/src/update.rs +++ /dev/null @@ -1,36 +0,0 @@ -use crate::model::{Galaxy, GameStatus}; - -pub enum Message { - RequestShortRangeScan, - RequestNavigation, - DirectionForNav (u8), - DirectionAndSpeedForNav (u8, u8), -} - -pub fn update(message: Message, model: Galaxy) -> Galaxy { - match message { - Message::RequestShortRangeScan => - Galaxy { - game_status: GameStatus::ShortRangeScan, - ..model - }, - Message::RequestNavigation => { - Galaxy { - game_status: GameStatus::NeedDirectionForNav, - ..model - } - }, - Message::DirectionForNav(dir) => { - Galaxy { - game_status: GameStatus::NeedSpeedForNav(dir), - ..model - } - }, - Message::DirectionAndSpeedForNav(dir, speed) => { - Galaxy { - game_status: GameStatus::ShortRangeScan, - ..model - } - } - } -} \ No newline at end of file From 7c8c420d4435f8afcc52c5aba0ddcfd1c84f8ee6 Mon Sep 17 00:00:00 2001 From: Christopher Date: Tue, 28 Feb 2023 20:15:46 +1300 Subject: [PATCH 06/72] work on nav command under new model --- 84_Super_Star_Trek/rust/src/main.rs | 44 +++++++++++++++---- 84_Super_Star_Trek/rust/src/text_constants.rs | 2 + 2 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 84_Super_Star_Trek/rust/src/text_constants.rs diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index cc6948ac..3fcf9632 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,21 +1,25 @@ -use std::{io::{stdin, stdout, Write}, process::exit}; +use std::{io::{stdin, stdout, Write}, process::exit, str::FromStr}; use model::Galaxy; +use crate::text_constants::BAD_NAV; + mod model; mod commands; +mod text_constants; fn main() { ctrlc::set_handler(move || { exit(0) }) .expect("Error setting Ctrl-C handler"); - let galaxy = Galaxy::generate_new(); + let mut galaxy = Galaxy::generate_new(); // init ops, starting state and notes commands::short_range_scan(&galaxy); loop { match prompt("Command?").as_str() { "SRS" => commands::short_range_scan(&galaxy), + "NAV" => gather_dir_and_speed_then_move(&mut galaxy), _ => print_command_help() } @@ -25,11 +29,31 @@ fn main() { } } -fn prompt(prompt: &str) -> String { +fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { + let dir = prompt_value::("Course (1-9)?", 1, 9); + if dir.is_none() { + println!("{}", BAD_NAV); + return; + } + + let speed = prompt_value::("Course (1-9)?", 0.0, 8.0); + if speed.is_none() { + println!("{}", BAD_NAV); + return; + } + + let distance = (speed.unwrap() * 8.0) as i32; + // could be done with a step function - while distance > 0, move by digit. + // if passing a boundary, test for the next quadrant in that direction + // if present, change quadrant and move to border + // else stop. +} + +fn prompt(prompt_text: &str) -> String { let stdin = stdin(); let mut stdout = stdout(); - print!("{prompt} "); + print!("{prompt_text} "); let _ = stdout.flush(); let mut buffer = String::new(); @@ -39,11 +63,15 @@ fn prompt(prompt: &str) -> String { "".into() } +fn prompt_value(prompt_text: &str, min: T, max: T) -> Option { + let passed = prompt(prompt_text); + match passed.parse::() { + Ok(n) if (n >= min && n <= max) => Some(n), + _ => None + } +} + fn print_command_help() { println!("valid commands are just SRS and NAV at the mo") } -// match text.parse::() { -// Ok(n) if (n >= 1 && n <= 8) => Some(Message::DirectionForNav(n)), -// _ => None -// } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/text_constants.rs b/84_Super_Star_Trek/rust/src/text_constants.rs new file mode 100644 index 00000000..36339abe --- /dev/null +++ b/84_Super_Star_Trek/rust/src/text_constants.rs @@ -0,0 +1,2 @@ + +pub const BAD_NAV: &str = " Lt. Sulu reports, 'Incorrect course data, sir!'"; \ No newline at end of file From 183ec6fde3df1475622d32570491c710fdf4b4e0 Mon Sep 17 00:00:00 2001 From: Christopher Date: Tue, 28 Feb 2023 20:19:54 +1300 Subject: [PATCH 07/72] added a note on how to calculate --- 84_Super_Star_Trek/rust/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 3fcf9632..46e932c3 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -47,6 +47,8 @@ fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { // if passing a boundary, test for the next quadrant in that direction // if present, change quadrant and move to border // else stop. + // one way to sort this would be to convert current pos to a galaxy pos (e.g. sector.x, y * 8), + // add dist, then mod/divide to get quadrant and new sector } fn prompt(prompt_text: &str) -> String { From 615438a2676cf3e4dadf74e2a948d9f4b425b851 Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 08:29:47 +1300 Subject: [PATCH 08/72] more work on nav, almost done basics! --- 84_Super_Star_Trek/rust/src/main.rs | 44 ++++++++++++++++--- 84_Super_Star_Trek/rust/src/model.rs | 44 ++++++++++++++++++- 84_Super_Star_Trek/rust/src/text_constants.rs | 2 - 3 files changed, 82 insertions(+), 8 deletions(-) delete mode 100644 84_Super_Star_Trek/rust/src/text_constants.rs diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 46e932c3..481d2378 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,12 +1,9 @@ use std::{io::{stdin, stdout, Write}, process::exit, str::FromStr}; -use model::Galaxy; - -use crate::text_constants::BAD_NAV; +use model::{Galaxy, Pos}; mod model; mod commands; -mod text_constants; fn main() { ctrlc::set_handler(move || { exit(0) }) @@ -30,6 +27,8 @@ fn main() { } fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { + const BAD_NAV: &str = " Lt. Sulu reports, 'Incorrect course data, sir!'"; + let dir = prompt_value::("Course (1-9)?", 1, 9); if dir.is_none() { println!("{}", BAD_NAV); @@ -42,7 +41,42 @@ fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { return; } - let distance = (speed.unwrap() * 8.0) as i32; + let distance = (speed.unwrap() * 8.0) as u8; + let galaxy_pos = galaxy.enterprise.quadrant * 8u8 + galaxy.enterprise.sector; + let (mut nx, mut ny) = galaxy_pos.translate(dir.unwrap(), distance); + + let mut hit_edge = false; + if nx < 0 { + nx = 0; + hit_edge = true; + } + if ny < 0 { + ny = 0; + hit_edge = true; + } + if nx >= 64 { + ny = 63; + hit_edge = true; + } + if nx >= 64 { + ny = 63; + hit_edge = true; + } + + let new_quadrant = Pos((nx / 8) as u8, (ny / 8) as u8); + let new_sector = Pos((nx % 8) as u8, (ny % 8) as u8); + + if hit_edge { + println!("Lt. Uhura report message from Starfleet Command: + 'Permission to attempt crossing of galactic perimeter + is hereby *Denied*. Shut down your engines.' + Chief Engineer Scott reports, 'Warp engines shut down + at sector {} of quadrant {}.'", new_quadrant, new_sector); + } + + galaxy.enterprise.quadrant = new_quadrant; + galaxy.enterprise.sector = new_sector; + // could be done with a step function - while distance > 0, move by digit. // if passing a boundary, test for the next quadrant in that direction // if present, change quadrant and move to border diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index a0f80751..36ec9628 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -1,3 +1,5 @@ +use std::{ops::{Mul, Add}, fmt::Display}; + use rand::Rng; pub struct Galaxy { @@ -5,13 +7,53 @@ pub struct Galaxy { pub enterprise: Enterprise } -#[derive(PartialEq)] +#[derive(PartialEq, Clone, Copy)] pub struct Pos(pub u8, pub u8); impl Pos { + const DIRECTIONS : [(i8, i8); 8] = [ + (1, 0), + (1, -1), + (0, -1), + (-1, -1), + (-1, 0), + (-1, 1), + (0, 1), + (1, 1), + ]; + pub fn as_index(&self) -> usize { (self.0 * 8 + self.1).into() } + + pub fn translate(&self, dir: u8, dist: u8) -> (i8, i8) { + let (dx, dy): (i8, i8) = Self::DIRECTIONS[dir as usize]; + let x = (self.0 as i8) + dx * dist as i8; + let y = (self.1 as i8) + dy * dist as i8; + (x, y) + } +} + +impl Mul for Pos { + type Output = Self; + + fn mul(self, rhs: u8) -> Self::Output { + Pos(self.0 * rhs, self.1 * rhs) + } +} + +impl Add for Pos { + type Output = Self; + + fn add(self, rhs: Pos) -> Self::Output { + Pos(self.0 + rhs.0, self.1 + rhs.1) + } +} + +impl Display for Pos { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + todo!() + } } #[derive(PartialEq)] diff --git a/84_Super_Star_Trek/rust/src/text_constants.rs b/84_Super_Star_Trek/rust/src/text_constants.rs deleted file mode 100644 index 36339abe..00000000 --- a/84_Super_Star_Trek/rust/src/text_constants.rs +++ /dev/null @@ -1,2 +0,0 @@ - -pub const BAD_NAV: &str = " Lt. Sulu reports, 'Incorrect course data, sir!'"; \ No newline at end of file From 80ac05e0053f9a38eba2b8e0177afe81077cc9fb Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 08:54:39 +1300 Subject: [PATCH 09/72] semi working nav (going weird directions) --- 84_Super_Star_Trek/rust/src/main.rs | 24 +++++++++++---------- 84_Super_Star_Trek/rust/src/model.rs | 31 +++++++++++----------------- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 481d2378..a7265116 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -2,6 +2,8 @@ use std::{io::{stdin, stdout, Write}, process::exit, str::FromStr}; use model::{Galaxy, Pos}; +use crate::model::DIRECTIONS; + mod model; mod commands; @@ -14,7 +16,7 @@ fn main() { commands::short_range_scan(&galaxy); loop { - match prompt("Command?").as_str() { + match prompt("Command?").to_uppercase().as_str() { "SRS" => commands::short_range_scan(&galaxy), "NAV" => gather_dir_and_speed_then_move(&mut galaxy), _ => print_command_help() @@ -28,22 +30,25 @@ fn main() { fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { const BAD_NAV: &str = " Lt. Sulu reports, 'Incorrect course data, sir!'"; - + let dir = prompt_value::("Course (1-9)?", 1, 9); if dir.is_none() { println!("{}", BAD_NAV); return; } - let speed = prompt_value::("Course (1-9)?", 0.0, 8.0); + let speed = prompt_value::("Warp Factor (0-8)?", 0.0, 8.0); if speed.is_none() { println!("{}", BAD_NAV); return; } - let distance = (speed.unwrap() * 8.0) as u8; + let distance = (speed.unwrap() * 8.0) as i8; let galaxy_pos = galaxy.enterprise.quadrant * 8u8 + galaxy.enterprise.sector; - let (mut nx, mut ny) = galaxy_pos.translate(dir.unwrap(), distance); + + let (dx, dy): (i8, i8) = DIRECTIONS[(dir.unwrap() - 1) as usize]; + let mut nx = (galaxy_pos.0 as i8) + dx * distance; + let mut ny = (galaxy_pos.1 as i8) + dy * distance; let mut hit_edge = false; if nx < 0 { @@ -77,12 +82,9 @@ fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { galaxy.enterprise.quadrant = new_quadrant; galaxy.enterprise.sector = new_sector; - // could be done with a step function - while distance > 0, move by digit. - // if passing a boundary, test for the next quadrant in that direction - // if present, change quadrant and move to border - // else stop. - // one way to sort this would be to convert current pos to a galaxy pos (e.g. sector.x, y * 8), - // add dist, then mod/divide to get quadrant and new sector + // if new_quadrant isnt old quadrant print intro + + commands::short_range_scan(&galaxy) } fn prompt(prompt_text: &str) -> String { diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 36ec9628..2e097b9c 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -11,27 +11,9 @@ pub struct Galaxy { pub struct Pos(pub u8, pub u8); impl Pos { - const DIRECTIONS : [(i8, i8); 8] = [ - (1, 0), - (1, -1), - (0, -1), - (-1, -1), - (-1, 0), - (-1, 1), - (0, 1), - (1, 1), - ]; - pub fn as_index(&self) -> usize { (self.0 * 8 + self.1).into() } - - pub fn translate(&self, dir: u8, dist: u8) -> (i8, i8) { - let (dx, dy): (i8, i8) = Self::DIRECTIONS[dir as usize]; - let x = (self.0 as i8) + dx * dist as i8; - let y = (self.1 as i8) + dy * dist as i8; - (x, y) - } } impl Mul for Pos { @@ -52,10 +34,21 @@ impl Add for Pos { impl Display for Pos { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - todo!() + write!(f, "{} , {}", self.0, self.1) } } +pub const DIRECTIONS : [(i8, i8); 8] = [ + (1, 0), + (1, -1), + (0, -1), + (-1, -1), + (-1, 0), + (-1, 1), + (0, 1), + (1, 1), +]; + #[derive(PartialEq)] pub enum SectorStatus { Empty, Star, StarBase, Klingon From ab26776d61e60d20bf8fed252e60dc8f7453561d Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 09:16:00 +1300 Subject: [PATCH 10/72] moved nav function bulk to commands module --- 84_Super_Star_Trek/rust/src/commands.rs | 48 ++++++++++++++++++++- 84_Super_Star_Trek/rust/src/main.rs | 57 +++---------------------- 84_Super_Star_Trek/rust/src/model.rs | 2 +- 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 264f7909..e87dd9c0 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,4 +1,4 @@ -use crate::model::{Galaxy, Pos, SectorStatus}; +use crate::model::{Galaxy, Pos, SectorStatus, COURSES}; pub fn short_range_scan(model: &Galaxy) { let quadrant = &model.quadrants[model.enterprise.sector.as_index()]; @@ -22,3 +22,49 @@ pub fn short_range_scan(model: &Galaxy) { } println!("{:-^33}", ""); } + +pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { + let distance = (warp_speed * 8.0) as i8; + let galaxy_pos = galaxy.enterprise.quadrant * 8u8 + galaxy.enterprise.sector; + + let (dx, dy): (i8, i8) = COURSES[(course - 1) as usize]; + + let mut nx = (galaxy_pos.0 as i8) + dx * distance; + let mut ny = (galaxy_pos.1 as i8) + dy * distance; + + let mut hit_edge = false; + if nx < 0 { + nx = 0; + hit_edge = true; + } + if ny < 0 { + ny = 0; + hit_edge = true; + } + if nx >= 64 { + ny = 63; + hit_edge = true; + } + if nx >= 64 { + ny = 63; + hit_edge = true; + } + + let new_quadrant = Pos((nx / 8) as u8, (ny / 8) as u8); + let new_sector = Pos((nx % 8) as u8, (ny % 8) as u8); + + if hit_edge { + println!("Lt. Uhura report message from Starfleet Command: + 'Permission to attempt crossing of galactic perimeter + is hereby *Denied*. Shut down your engines.' + Chief Engineer Scott reports, 'Warp engines shut down + at sector {} of quadrant {}.'", new_quadrant, new_sector); + } + + galaxy.enterprise.quadrant = new_quadrant; + galaxy.enterprise.sector = new_sector; + + // if new_quadrant isnt old quadrant print intro + + short_range_scan(&galaxy) +} diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index a7265116..a9b5f4ce 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,8 +1,6 @@ use std::{io::{stdin, stdout, Write}, process::exit, str::FromStr}; -use model::{Galaxy, Pos}; - -use crate::model::DIRECTIONS; +use model::Galaxy; mod model; mod commands; @@ -12,7 +10,7 @@ fn main() { .expect("Error setting Ctrl-C handler"); let mut galaxy = Galaxy::generate_new(); - // init ops, starting state and notes + // init options, starting state and notes commands::short_range_scan(&galaxy); loop { @@ -21,18 +19,14 @@ fn main() { "NAV" => gather_dir_and_speed_then_move(&mut galaxy), _ => print_command_help() } - - // process the next command, based on it render something or update the galaxy or whatever - // this would be: read command, and based on it run dedicated function - // the function might get passed a mutable reference to the galaxy } } fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { const BAD_NAV: &str = " Lt. Sulu reports, 'Incorrect course data, sir!'"; - let dir = prompt_value::("Course (1-9)?", 1, 9); - if dir.is_none() { + let course = prompt_value::("Course (1-9)?", 1, 9); + if course.is_none() { println!("{}", BAD_NAV); return; } @@ -43,48 +37,7 @@ fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { return; } - let distance = (speed.unwrap() * 8.0) as i8; - let galaxy_pos = galaxy.enterprise.quadrant * 8u8 + galaxy.enterprise.sector; - - let (dx, dy): (i8, i8) = DIRECTIONS[(dir.unwrap() - 1) as usize]; - let mut nx = (galaxy_pos.0 as i8) + dx * distance; - let mut ny = (galaxy_pos.1 as i8) + dy * distance; - - let mut hit_edge = false; - if nx < 0 { - nx = 0; - hit_edge = true; - } - if ny < 0 { - ny = 0; - hit_edge = true; - } - if nx >= 64 { - ny = 63; - hit_edge = true; - } - if nx >= 64 { - ny = 63; - hit_edge = true; - } - - let new_quadrant = Pos((nx / 8) as u8, (ny / 8) as u8); - let new_sector = Pos((nx % 8) as u8, (ny % 8) as u8); - - if hit_edge { - println!("Lt. Uhura report message from Starfleet Command: - 'Permission to attempt crossing of galactic perimeter - is hereby *Denied*. Shut down your engines.' - Chief Engineer Scott reports, 'Warp engines shut down - at sector {} of quadrant {}.'", new_quadrant, new_sector); - } - - galaxy.enterprise.quadrant = new_quadrant; - galaxy.enterprise.sector = new_sector; - - // if new_quadrant isnt old quadrant print intro - - commands::short_range_scan(&galaxy) + commands::move_enterprise(course.unwrap(), speed.unwrap(), galaxy); } fn prompt(prompt_text: &str) -> String { diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 2e097b9c..2ea85548 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -38,7 +38,7 @@ impl Display for Pos { } } -pub const DIRECTIONS : [(i8, i8); 8] = [ +pub const COURSES : [(i8, i8); 8] = [ (1, 0), (1, -1), (0, -1), From 09cb10eeb718528480f065744bf0bfc414007c28 Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 09:39:08 +1300 Subject: [PATCH 11/72] added some unit tests for movement --- 84_Super_Star_Trek/rust/src/commands.rs | 128 ++++++++++++++++++++---- 84_Super_Star_Trek/rust/src/model.rs | 2 +- 2 files changed, 111 insertions(+), 19 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index e87dd9c0..485f57af 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -24,11 +24,41 @@ pub fn short_range_scan(model: &Galaxy) { } pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { - let distance = (warp_speed * 8.0) as i8; - let galaxy_pos = galaxy.enterprise.quadrant * 8u8 + galaxy.enterprise.sector; + + let end = find_end_quadrant_sector(galaxy.enterprise.quadrant, galaxy.enterprise.sector, course, warp_speed); + if end.hit_edge { + println!("Lt. Uhura report message from Starfleet Command: + 'Permission to attempt crossing of galactic perimeter + is hereby *Denied*. Shut down your engines.' + Chief Engineer Scott reports, 'Warp engines shut down + at sector {} of quadrant {}.'", end.quadrant, end.sector); + } + + galaxy.enterprise.quadrant = end.quadrant; + galaxy.enterprise.sector = end.sector; + + // if new_quadrant isnt old quadrant print intro + + short_range_scan(&galaxy) +} + +struct EndPosition { + quadrant: Pos, + sector: Pos, + hit_edge: bool +} + +fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, warp_speed: f32) -> EndPosition { let (dx, dy): (i8, i8) = COURSES[(course - 1) as usize]; + let mut distance = (warp_speed * 8.0) as i8; + if distance == 0 { + distance = 1; + } + + let galaxy_pos = start_quadrant * 8u8 + start_sector; + let mut nx = (galaxy_pos.0 as i8) + dx * distance; let mut ny = (galaxy_pos.1 as i8) + dy * distance; @@ -42,29 +72,91 @@ pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { hit_edge = true; } if nx >= 64 { - ny = 63; + nx = 63; hit_edge = true; } - if nx >= 64 { + if ny >= 64 { ny = 63; hit_edge = true; } - let new_quadrant = Pos((nx / 8) as u8, (ny / 8) as u8); - let new_sector = Pos((nx % 8) as u8, (ny % 8) as u8); + let quadrant = Pos((nx / 8) as u8, (ny / 8) as u8); + let sector = Pos((nx % 8) as u8, (ny % 8) as u8); - if hit_edge { - println!("Lt. Uhura report message from Starfleet Command: - 'Permission to attempt crossing of galactic perimeter - is hereby *Denied*. Shut down your engines.' - Chief Engineer Scott reports, 'Warp engines shut down - at sector {} of quadrant {}.'", new_quadrant, new_sector); + EndPosition { quadrant, sector, hit_edge } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_course_east() { + let start_quadrant = Pos(0,0); + let start_sector = Pos(0,0); + let end = find_end_quadrant_sector(start_quadrant, start_sector, 1, 0.1); + assert_eq!(end.quadrant, start_quadrant, "right quadrant"); + assert_eq!(end.sector, Pos(1,0), "right sector"); + assert!(!end.hit_edge) } - galaxy.enterprise.quadrant = new_quadrant; - galaxy.enterprise.sector = new_sector; - - // if new_quadrant isnt old quadrant print intro + #[test] + fn test_course_far_east() { + let start_quadrant = Pos(0,0); + let start_sector = Pos(0,0); + let end = find_end_quadrant_sector(start_quadrant, start_sector, 1, 1.0); + assert_eq!(end.quadrant, Pos(1,0), "right quadrant"); + assert_eq!(end.sector, start_sector, "right sector"); + assert!(!end.hit_edge) + } - short_range_scan(&galaxy) -} + #[test] + fn test_course_too_far_east() { + let start_quadrant = Pos(0,0); + let start_sector = Pos(0,0); + let end = find_end_quadrant_sector(start_quadrant, start_sector, 1, 8.0); + assert_eq!(end.quadrant, Pos(7,0), "right quadrant"); + assert_eq!(end.sector, Pos(7,0), "right sector"); + assert!(end.hit_edge) + } + + #[test] + fn test_course_south() { + let start_quadrant = Pos(0,0); + let start_sector = Pos(0,0); + let end = find_end_quadrant_sector(start_quadrant, start_sector, 7, 0.1); + assert_eq!(end.quadrant, start_quadrant, "right quadrant"); + assert_eq!(end.sector, Pos(0,1), "right sector"); + assert!(!end.hit_edge) + } + + #[test] + fn test_course_far_south() { + let start_quadrant = Pos(0,0); + let start_sector = Pos(0,0); + let end = find_end_quadrant_sector(start_quadrant, start_sector, 7, 1.0); + assert_eq!(end.quadrant, Pos(0,1), "right quadrant"); + assert_eq!(end.sector, start_sector, "right sector"); + assert!(!end.hit_edge) + } + + #[test] + fn test_course_too_far_south() { + let start_quadrant = Pos(0,0); + let start_sector = Pos(0,0); + let end = find_end_quadrant_sector(start_quadrant, start_sector, 7, 8.0); + assert_eq!(end.quadrant, Pos(0,7), "right quadrant"); + assert_eq!(end.sector, Pos(0,7), "right sector"); + assert!(end.hit_edge) + } + + #[test] + fn test_course_north_east() { + let start_quadrant = Pos(0,0); + let start_sector = Pos(0,1); + let end = find_end_quadrant_sector(start_quadrant, start_sector, 2, 0.1); + assert_eq!(end.quadrant, start_quadrant, "right quadrant"); + assert_eq!(end.sector, Pos(1,0), "right sector"); + assert!(!end.hit_edge) + } +} \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 2ea85548..fa0ca4c2 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -7,7 +7,7 @@ pub struct Galaxy { pub enterprise: Enterprise } -#[derive(PartialEq, Clone, Copy)] +#[derive(PartialEq, Clone, Copy, Debug)] pub struct Pos(pub u8, pub u8); impl Pos { From bc4470999c7f9499a43c50b90e1cc9e2ea2ed331 Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 09:42:44 +1300 Subject: [PATCH 12/72] bug fix - used sector instead of quadrant as index in srs --- 84_Super_Star_Trek/rust/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 485f57af..34c30136 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,7 +1,7 @@ use crate::model::{Galaxy, Pos, SectorStatus, COURSES}; pub fn short_range_scan(model: &Galaxy) { - let quadrant = &model.quadrants[model.enterprise.sector.as_index()]; + let quadrant = &model.quadrants[model.enterprise.quadrant.as_index()]; println!("{:-^33}", ""); for y in 0..=7 { From c23449fac320c6ccf3b4d3b44615ab62c12a7645 Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 09:44:14 +1300 Subject: [PATCH 13/72] just reorged some code --- 84_Super_Star_Trek/rust/src/model.rs | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index fa0ca4c2..d1c937ab 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -7,6 +7,21 @@ pub struct Galaxy { pub enterprise: Enterprise } +pub struct Quadrant { + pub stars: Vec, + pub star_base: Option, + pub klingons: Vec +} + +pub struct Klingon { + pub sector: Pos +} + +pub struct Enterprise { + pub quadrant: Pos, + pub sector: Pos, +} + #[derive(PartialEq, Clone, Copy, Debug)] pub struct Pos(pub u8, pub u8); @@ -54,21 +69,6 @@ pub enum SectorStatus { Empty, Star, StarBase, Klingon } -pub struct Quadrant { - pub stars: Vec, - pub star_base: Option, - pub klingons: Vec -} - -pub struct Klingon { - pub sector: Pos -} - -pub struct Enterprise { - pub quadrant: Pos, - pub sector: Pos, -} - impl Galaxy { pub fn generate_new() -> Self { let quadrants = Self::generate_quadrants(); From 60f0492c2814deaf619f1123e06c8f30417503c6 Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 11:43:58 +1300 Subject: [PATCH 14/72] displaying stats properly aligned next to scan --- 84_Super_Star_Trek/rust/src/commands.rs | 15 +++++++++++++-- 84_Super_Star_Trek/rust/src/model.rs | 24 +++++++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 34c30136..100803a3 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -3,6 +3,17 @@ use crate::model::{Galaxy, Pos, SectorStatus, COURSES}; pub fn short_range_scan(model: &Galaxy) { let quadrant = &model.quadrants[model.enterprise.quadrant.as_index()]; + let data : [String; 8] = [ + format!("Stardate {}", model.stardate), + format!("Condition {:?}", model.enterprise.condition), + format!("Quadrant {}", model.enterprise.quadrant), + format!("Sector {}", model.enterprise.sector), + format!("Photon torpedoes {}", model.enterprise.photon_torpedoes), + format!("Total energy {}", model.enterprise.total_energy), + format!("Shields {}", model.enterprise.shields), + format!("Klingons remaining {}", model.remaining_klingons()), + ]; + println!("{:-^33}", ""); for y in 0..=7 { for x in 0..=7 { @@ -14,11 +25,11 @@ pub fn short_range_scan(model: &Galaxy) { SectorStatus::Star => print!(" * "), SectorStatus::StarBase => print!(">!< "), SectorStatus::Klingon => print!("+K+ "), - _ => print!(" "), + _ => print!(" "), } } } - print!("\n") + println!("{:>9}{}", "", data[y as usize]) } println!("{:-^33}", ""); } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index d1c937ab..7fffd81f 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -3,6 +3,7 @@ use std::{ops::{Mul, Add}, fmt::Display}; use rand::Rng; pub struct Galaxy { + pub stardate: f32, pub quadrants: Vec, pub enterprise: Enterprise } @@ -18,8 +19,17 @@ pub struct Klingon { } pub struct Enterprise { + pub condition: Condition, pub quadrant: Pos, pub sector: Pos, + pub photon_torpedoes: u8, + pub total_energy: u16, + pub shields: u16, +} + +#[derive(Debug)] +pub enum Condition { + Green, Yellow, Red } #[derive(PartialEq, Clone, Copy, Debug)] @@ -70,6 +80,11 @@ pub enum SectorStatus { } impl Galaxy { + pub fn remaining_klingons(&self) -> u8 { + let quadrants = &self.quadrants; + quadrants.into_iter().map(|q| { q.klingons.len() as u8 }).sum::() + } + pub fn generate_new() -> Self { let quadrants = Self::generate_quadrants(); @@ -78,8 +93,15 @@ impl Galaxy { let enterprise_sector = quadrants[enterprise_quadrant.as_index()].find_empty_sector(); Galaxy { + stardate: 3800.0, quadrants: quadrants, - enterprise: Enterprise { quadrant: enterprise_quadrant, sector: enterprise_sector } + enterprise: Enterprise { + condition: Condition::Green, + quadrant: enterprise_quadrant, + sector: enterprise_sector, + photon_torpedoes: 28, + total_energy: 3000, + shields: 0 } } } From 4b326547e4d4441bd3c1099d29ae0683e6c5527b Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 11:53:19 +1300 Subject: [PATCH 15/72] added a tasks tracking doc --- 84_Super_Star_Trek/rust/tasks.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 84_Super_Star_Trek/rust/tasks.md diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md new file mode 100644 index 00000000..3fcb826a --- /dev/null +++ b/84_Super_Star_Trek/rust/tasks.md @@ -0,0 +1,7 @@ +# Tasks + +Started after movement and display of stats was finished (no energy management or collision detection or anything). + +- [ ] stop before hitting an object +- [ ] remove energy on move +- [ ] klingon movement \ No newline at end of file From b56819aadffe74fb53d3dd8ab7de51a1cb161045 Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 15:36:42 +1300 Subject: [PATCH 16/72] implemented taking damage and dying --- 84_Super_Star_Trek/rust/src/commands.rs | 4 +- 84_Super_Star_Trek/rust/src/main.rs | 27 ++++++++++++- 84_Super_Star_Trek/rust/src/model.rs | 50 ++++++++++++++++++++++--- 84_Super_Star_Trek/rust/tasks.md | 9 ++++- 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 100803a3..ffbdad61 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,4 +1,4 @@ -use crate::model::{Galaxy, Pos, SectorStatus, COURSES}; +use crate::model::{Galaxy, Pos, SectorStatus, COURSES, Quadrant}; pub fn short_range_scan(model: &Galaxy) { let quadrant = &model.quadrants[model.enterprise.quadrant.as_index()]; @@ -35,7 +35,7 @@ pub fn short_range_scan(model: &Galaxy) { } pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { - + let end = find_end_quadrant_sector(galaxy.enterprise.quadrant, galaxy.enterprise.sector, course, warp_speed); if end.hit_edge { diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index a9b5f4ce..9c2ea606 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -2,6 +2,8 @@ use std::{io::{stdin, stdout, Write}, process::exit, str::FromStr}; use model::Galaxy; +use crate::model::Condition; + mod model; mod commands; @@ -10,7 +12,7 @@ fn main() { .expect("Error setting Ctrl-C handler"); let mut galaxy = Galaxy::generate_new(); - // init options, starting state and notes + // todo: init options, starting state and notes commands::short_range_scan(&galaxy); loop { @@ -19,6 +21,14 @@ fn main() { "NAV" => gather_dir_and_speed_then_move(&mut galaxy), _ => print_command_help() } + + if galaxy.enterprise.condition == Condition::Destroyed { // todo: also check if stranded + println!("Is is stardate {}. + There were {} Klingon battle cruisers left at + the end of your mission. + ", galaxy.stardate, galaxy.remaining_klingons()); + break; + } } } @@ -37,6 +47,21 @@ fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { return; } + let quadrant = &mut galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; + for k in 0..quadrant.klingons.len() { + let new_sector = quadrant.find_empty_sector(); + quadrant.klingons[k].sector = new_sector; + } + + // todo: check if enterprise is protected by a starbase + + for k in 0..quadrant.klingons.len() { + quadrant.klingons[k].fire_on(&mut galaxy.enterprise); + } + + if galaxy.enterprise.condition == Condition::Destroyed { + return; + } commands::move_enterprise(course.unwrap(), speed.unwrap(), galaxy); } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 7fffd81f..94e9128f 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -15,7 +15,21 @@ pub struct Quadrant { } pub struct Klingon { - pub sector: Pos + pub sector: Pos, + energy: f32 +} + +impl Klingon { + pub fn fire_on(&mut self, enterprise: &mut Enterprise) { + let mut rng = rand::thread_rng(); + let attack_strength = rng.gen::(); + let dist_to_enterprise = self.sector.abs_diff(enterprise.sector) as f32; + let hit_strength = self.energy * (2.0 + attack_strength) / dist_to_enterprise; + + self.energy /= 3.0 + attack_strength; + + enterprise.take_hit(self.sector, hit_strength as u16); + } } pub struct Enterprise { @@ -26,10 +40,30 @@ pub struct Enterprise { pub total_energy: u16, pub shields: u16, } +impl Enterprise { + fn take_hit(&mut self, sector: Pos, hit_strength: u16) { + if self.condition == Condition::Destroyed { + return; + } + + println!("{hit_strength} unit hit on Enterprise from sector {sector}"); -#[derive(Debug)] + // absorb into shields + + if self.shields <= 0 { + println!("The Enterprise has been destroyed. The Federation will be conquered."); + self.condition = Condition::Destroyed; + } + + // report shields + // take damage if strength is greater than 20 + } +} + +#[derive(PartialEq, Debug)] pub enum Condition { - Green, Yellow, Red + Green, Yellow, Red, + Destroyed, } #[derive(PartialEq, Clone, Copy, Debug)] @@ -39,6 +73,10 @@ impl Pos { pub fn as_index(&self) -> usize { (self.0 * 8 + self.1).into() } + + fn abs_diff(&self, other: Pos) -> u8 { + self.0.abs_diff(other.0) + self.1.abs_diff(other.1) + } } impl Mul for Pos { @@ -128,7 +166,7 @@ impl Galaxy { _ => 0 }; for _ in 0..klingon_count { - quadrant.klingons.push(Klingon { sector: quadrant.find_empty_sector() }); + quadrant.klingons.push(Klingon { sector: quadrant.find_empty_sector(), energy: rng.gen_range(100..=300) as f32 }); } result.push(quadrant); @@ -162,7 +200,7 @@ impl Quadrant { klingons.into_iter().find(|k| &k.sector == sector).is_some() } - fn find_empty_sector(&self) -> Pos { + pub fn find_empty_sector(&self) -> Pos { let mut rng = rand::thread_rng(); loop { let pos = Pos(rng.gen_range(0..8), rng.gen_range(0..8)); @@ -171,4 +209,4 @@ impl Quadrant { } } } -} \ No newline at end of file +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 3fcb826a..8a9951b5 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -2,6 +2,11 @@ Started after movement and display of stats was finished (no energy management or collision detection or anything). -- [ ] stop before hitting an object +- [x] klingon movement +- [x] klingon firing, game over etc - [ ] remove energy on move -- [ ] klingon movement \ No newline at end of file +- [ ] shields +- [ ] stranded... +- [ ] stop before hitting an object + - when moving across a sector, the enterprise should stop before it runs into something + - the current move is a jump, which makes this problematic. would need to rewrite it From 1732d950328b0f2ec723c554db5b0753d6ce06fe Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 15:41:00 +1300 Subject: [PATCH 17/72] added proper help --- 84_Super_Star_Trek/rust/src/commands.rs | 16 +++++++++++++++- 84_Super_Star_Trek/rust/src/main.rs | 25 ++++++++++++------------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index ffbdad61..5cd90150 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -97,6 +97,20 @@ fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, EndPosition { quadrant, sector, hit_edge } } +pub fn move_klingons_and_fire(galaxy: &mut Galaxy) { + let quadrant = &mut galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; + for k in 0..quadrant.klingons.len() { + let new_sector = quadrant.find_empty_sector(); + quadrant.klingons[k].sector = new_sector; + } + + // todo: check if enterprise is protected by a starbase + + for k in 0..quadrant.klingons.len() { + quadrant.klingons[k].fire_on(&mut galaxy.enterprise); + } +} + #[cfg(test)] mod tests { use super::*; @@ -170,4 +184,4 @@ mod tests { assert_eq!(end.sector, Pos(1,0), "right sector"); assert!(!end.hit_edge) } -} \ No newline at end of file +} diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 9c2ea606..c91ca8bc 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -47,18 +47,7 @@ fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { return; } - let quadrant = &mut galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; - for k in 0..quadrant.klingons.len() { - let new_sector = quadrant.find_empty_sector(); - quadrant.klingons[k].sector = new_sector; - } - - // todo: check if enterprise is protected by a starbase - - for k in 0..quadrant.klingons.len() { - quadrant.klingons[k].fire_on(&mut galaxy.enterprise); - } - + commands::move_klingons_and_fire(galaxy); if galaxy.enterprise.condition == Condition::Destroyed { return; } @@ -88,6 +77,16 @@ fn prompt_value(prompt_text: &str, min: T, max: T) -> O } fn print_command_help() { - println!("valid commands are just SRS and NAV at the mo") + println!("Enter one of the following: + NAV (To set course) + SRS (For short range sensor scan) + LRS (For long range sensor scan) + PHA (To fire phasers) + TOR (To fire photon torpedoes) + SHE (To raise or lower shields) + DAM (For damage control reports) + COM (To call on library-computer) + XXX (To resign your command) + ") } From ec3b0697bb91927d8e94d1aee3f558d1cefa275f Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 19:05:38 +1300 Subject: [PATCH 18/72] moved blobs of text into text_display mod --- 84_Super_Star_Trek/rust/src/commands.rs | 14 +------ 84_Super_Star_Trek/rust/src/main.rs | 28 +++----------- 84_Super_Star_Trek/rust/src/model.rs | 12 +++++- 84_Super_Star_Trek/rust/src/text_display.rs | 42 +++++++++++++++++++++ 4 files changed, 59 insertions(+), 37 deletions(-) create mode 100644 84_Super_Star_Trek/rust/src/text_display.rs diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 5cd90150..5251109e 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,4 +1,4 @@ -use crate::model::{Galaxy, Pos, SectorStatus, COURSES, Quadrant}; +use crate::{model::{Galaxy, Pos, SectorStatus, COURSES, Quadrant, EndPosition}, text_display}; pub fn short_range_scan(model: &Galaxy) { let quadrant = &model.quadrants[model.enterprise.quadrant.as_index()]; @@ -39,11 +39,7 @@ pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { let end = find_end_quadrant_sector(galaxy.enterprise.quadrant, galaxy.enterprise.sector, course, warp_speed); if end.hit_edge { - println!("Lt. Uhura report message from Starfleet Command: - 'Permission to attempt crossing of galactic perimeter - is hereby *Denied*. Shut down your engines.' - Chief Engineer Scott reports, 'Warp engines shut down - at sector {} of quadrant {}.'", end.quadrant, end.sector); + text_display::hit_edge(&end); } galaxy.enterprise.quadrant = end.quadrant; @@ -54,12 +50,6 @@ pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { short_range_scan(&galaxy) } -struct EndPosition { - quadrant: Pos, - sector: Pos, - hit_edge: bool -} - fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, warp_speed: f32) -> EndPosition { let (dx, dy): (i8, i8) = COURSES[(course - 1) as usize]; diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index c91ca8bc..bf6f5b96 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -6,6 +6,7 @@ use crate::model::Condition; mod model; mod commands; +mod text_display; fn main() { ctrlc::set_handler(move || { exit(0) }) @@ -19,31 +20,27 @@ fn main() { match prompt("Command?").to_uppercase().as_str() { "SRS" => commands::short_range_scan(&galaxy), "NAV" => gather_dir_and_speed_then_move(&mut galaxy), - _ => print_command_help() + _ => text_display::print_command_help() } if galaxy.enterprise.condition == Condition::Destroyed { // todo: also check if stranded - println!("Is is stardate {}. - There were {} Klingon battle cruisers left at - the end of your mission. - ", galaxy.stardate, galaxy.remaining_klingons()); + text_display::end_game_failure(&galaxy); break; } } } fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { - const BAD_NAV: &str = " Lt. Sulu reports, 'Incorrect course data, sir!'"; let course = prompt_value::("Course (1-9)?", 1, 9); if course.is_none() { - println!("{}", BAD_NAV); + text_display::bad_nav(); return; } let speed = prompt_value::("Warp Factor (0-8)?", 0.0, 8.0); if speed.is_none() { - println!("{}", BAD_NAV); + text_display::bad_nav(); return; } @@ -75,18 +72,3 @@ fn prompt_value(prompt_text: &str, min: T, max: T) -> O _ => None } } - -fn print_command_help() { - println!("Enter one of the following: - NAV (To set course) - SRS (For short range sensor scan) - LRS (For long range sensor scan) - PHA (To fire phasers) - TOR (To fire photon torpedoes) - SHE (To raise or lower shields) - DAM (For damage control reports) - COM (To call on library-computer) - XXX (To resign your command) - ") -} - diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 94e9128f..5026bdd9 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -2,6 +2,8 @@ use std::{ops::{Mul, Add}, fmt::Display}; use rand::Rng; +use crate::text_display; + pub struct Galaxy { pub stardate: f32, pub quadrants: Vec, @@ -46,12 +48,12 @@ impl Enterprise { return; } - println!("{hit_strength} unit hit on Enterprise from sector {sector}"); + text_display::enterprise_hit(&hit_strength, §or); // absorb into shields if self.shields <= 0 { - println!("The Enterprise has been destroyed. The Federation will be conquered."); + text_display::enterprise_destroyed(); self.condition = Condition::Destroyed; } @@ -66,6 +68,12 @@ pub enum Condition { Destroyed, } +pub struct EndPosition { + pub quadrant: Pos, + pub sector: Pos, + pub hit_edge: bool +} + #[derive(PartialEq, Clone, Copy, Debug)] pub struct Pos(pub u8, pub u8); diff --git a/84_Super_Star_Trek/rust/src/text_display.rs b/84_Super_Star_Trek/rust/src/text_display.rs new file mode 100644 index 00000000..17ffcab1 --- /dev/null +++ b/84_Super_Star_Trek/rust/src/text_display.rs @@ -0,0 +1,42 @@ +use crate::model::{Galaxy, Pos, EndPosition}; + +pub fn print_command_help() { + println!("Enter one of the following: + NAV (To set course) + SRS (For short range sensor scan) + LRS (For long range sensor scan) + PHA (To fire phasers) + TOR (To fire photon torpedoes) + SHE (To raise or lower shields) + DAM (For damage control reports) + COM (To call on library-computer) + XXX (To resign your command) + ") +} + +pub fn end_game_failure(galaxy: &Galaxy) { + println!("Is is stardate {}. +There were {} Klingon battle cruisers left at +the end of your mission. +", galaxy.stardate, galaxy.remaining_klingons()); +} + +pub fn enterprise_destroyed() { + println!("The Enterprise has been destroyed. The Federation will be conquered."); +} + +pub fn bad_nav() { + println!(" Lt. Sulu reports, 'Incorrect course data, sir!'") +} + +pub fn enterprise_hit(hit_strength: &u16, from_sector: &Pos) { + println!("{hit_strength} unit hit on Enterprise from sector {from_sector}"); +} + +pub fn hit_edge(end: &EndPosition) { + println!("Lt. Uhura report message from Starfleet Command: + 'Permission to attempt crossing of galactic perimeter + is hereby *Denied*. Shut down your engines.' + Chief Engineer Scott reports, 'Warp engines shut down + at sector {} of quadrant {}.'", end.quadrant, end.sector); +} \ No newline at end of file From efba9423969af07b3a2eac360c028f1e90fc2379 Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 19:07:46 +1300 Subject: [PATCH 19/72] renamed text_display to view, and moved srs into it --- 84_Super_Star_Trek/rust/src/commands.rs | 40 +---------- 84_Super_Star_Trek/rust/src/main.rs | 14 ++-- 84_Super_Star_Trek/rust/src/model.rs | 6 +- 84_Super_Star_Trek/rust/src/text_display.rs | 42 ------------ 84_Super_Star_Trek/rust/src/view.rs | 76 +++++++++++++++++++++ 5 files changed, 89 insertions(+), 89 deletions(-) delete mode 100644 84_Super_Star_Trek/rust/src/text_display.rs create mode 100644 84_Super_Star_Trek/rust/src/view.rs diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 5251109e..c27c6505 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,45 +1,11 @@ -use crate::{model::{Galaxy, Pos, SectorStatus, COURSES, Quadrant, EndPosition}, text_display}; - -pub fn short_range_scan(model: &Galaxy) { - let quadrant = &model.quadrants[model.enterprise.quadrant.as_index()]; - - let data : [String; 8] = [ - format!("Stardate {}", model.stardate), - format!("Condition {:?}", model.enterprise.condition), - format!("Quadrant {}", model.enterprise.quadrant), - format!("Sector {}", model.enterprise.sector), - format!("Photon torpedoes {}", model.enterprise.photon_torpedoes), - format!("Total energy {}", model.enterprise.total_energy), - format!("Shields {}", model.enterprise.shields), - format!("Klingons remaining {}", model.remaining_klingons()), - ]; - - println!("{:-^33}", ""); - for y in 0..=7 { - for x in 0..=7 { - let pos = Pos(x, y); - if &pos == &model.enterprise.sector { - print!("<*> ") - } else { - match quadrant.sector_status(&pos) { - SectorStatus::Star => print!(" * "), - SectorStatus::StarBase => print!(">!< "), - SectorStatus::Klingon => print!("+K+ "), - _ => print!(" "), - } - } - } - println!("{:>9}{}", "", data[y as usize]) - } - println!("{:-^33}", ""); -} +use crate::{model::{Galaxy, Pos, COURSES, EndPosition}, view}; pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { let end = find_end_quadrant_sector(galaxy.enterprise.quadrant, galaxy.enterprise.sector, course, warp_speed); if end.hit_edge { - text_display::hit_edge(&end); + view::hit_edge(&end); } galaxy.enterprise.quadrant = end.quadrant; @@ -47,7 +13,7 @@ pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { // if new_quadrant isnt old quadrant print intro - short_range_scan(&galaxy) + view::short_range_scan(&galaxy) } fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, warp_speed: f32) -> EndPosition { diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index bf6f5b96..ec923c8c 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -6,7 +6,7 @@ use crate::model::Condition; mod model; mod commands; -mod text_display; +mod view; fn main() { ctrlc::set_handler(move || { exit(0) }) @@ -14,17 +14,17 @@ fn main() { let mut galaxy = Galaxy::generate_new(); // todo: init options, starting state and notes - commands::short_range_scan(&galaxy); + view::short_range_scan(&galaxy); loop { match prompt("Command?").to_uppercase().as_str() { - "SRS" => commands::short_range_scan(&galaxy), + "SRS" => view::short_range_scan(&galaxy), "NAV" => gather_dir_and_speed_then_move(&mut galaxy), - _ => text_display::print_command_help() + _ => view::print_command_help() } if galaxy.enterprise.condition == Condition::Destroyed { // todo: also check if stranded - text_display::end_game_failure(&galaxy); + view::end_game_failure(&galaxy); break; } } @@ -34,13 +34,13 @@ fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { let course = prompt_value::("Course (1-9)?", 1, 9); if course.is_none() { - text_display::bad_nav(); + view::bad_nav(); return; } let speed = prompt_value::("Warp Factor (0-8)?", 0.0, 8.0); if speed.is_none() { - text_display::bad_nav(); + view::bad_nav(); return; } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 5026bdd9..2e54555c 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -2,7 +2,7 @@ use std::{ops::{Mul, Add}, fmt::Display}; use rand::Rng; -use crate::text_display; +use crate::view; pub struct Galaxy { pub stardate: f32, @@ -48,12 +48,12 @@ impl Enterprise { return; } - text_display::enterprise_hit(&hit_strength, §or); + view::enterprise_hit(&hit_strength, §or); // absorb into shields if self.shields <= 0 { - text_display::enterprise_destroyed(); + view::enterprise_destroyed(); self.condition = Condition::Destroyed; } diff --git a/84_Super_Star_Trek/rust/src/text_display.rs b/84_Super_Star_Trek/rust/src/text_display.rs deleted file mode 100644 index 17ffcab1..00000000 --- a/84_Super_Star_Trek/rust/src/text_display.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::model::{Galaxy, Pos, EndPosition}; - -pub fn print_command_help() { - println!("Enter one of the following: - NAV (To set course) - SRS (For short range sensor scan) - LRS (For long range sensor scan) - PHA (To fire phasers) - TOR (To fire photon torpedoes) - SHE (To raise or lower shields) - DAM (For damage control reports) - COM (To call on library-computer) - XXX (To resign your command) - ") -} - -pub fn end_game_failure(galaxy: &Galaxy) { - println!("Is is stardate {}. -There were {} Klingon battle cruisers left at -the end of your mission. -", galaxy.stardate, galaxy.remaining_klingons()); -} - -pub fn enterprise_destroyed() { - println!("The Enterprise has been destroyed. The Federation will be conquered."); -} - -pub fn bad_nav() { - println!(" Lt. Sulu reports, 'Incorrect course data, sir!'") -} - -pub fn enterprise_hit(hit_strength: &u16, from_sector: &Pos) { - println!("{hit_strength} unit hit on Enterprise from sector {from_sector}"); -} - -pub fn hit_edge(end: &EndPosition) { - println!("Lt. Uhura report message from Starfleet Command: - 'Permission to attempt crossing of galactic perimeter - is hereby *Denied*. Shut down your engines.' - Chief Engineer Scott reports, 'Warp engines shut down - at sector {} of quadrant {}.'", end.quadrant, end.sector); -} \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs new file mode 100644 index 00000000..5d8c1fd6 --- /dev/null +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -0,0 +1,76 @@ +use crate::model::{Galaxy, Pos, EndPosition, SectorStatus}; + +pub fn short_range_scan(model: &Galaxy) { + let quadrant = &model.quadrants[model.enterprise.quadrant.as_index()]; + + let data : [String; 8] = [ + format!("Stardate {}", model.stardate), + format!("Condition {:?}", model.enterprise.condition), + format!("Quadrant {}", model.enterprise.quadrant), + format!("Sector {}", model.enterprise.sector), + format!("Photon torpedoes {}", model.enterprise.photon_torpedoes), + format!("Total energy {}", model.enterprise.total_energy), + format!("Shields {}", model.enterprise.shields), + format!("Klingons remaining {}", model.remaining_klingons()), + ]; + + println!("{:-^33}", ""); + for y in 0..=7 { + for x in 0..=7 { + let pos = Pos(x, y); + if &pos == &model.enterprise.sector { + print!("<*> ") + } else { + match quadrant.sector_status(&pos) { + SectorStatus::Star => print!(" * "), + SectorStatus::StarBase => print!(">!< "), + SectorStatus::Klingon => print!("+K+ "), + _ => print!(" "), + } + } + } + println!("{:>9}{}", "", data[y as usize]) + } + println!("{:-^33}", ""); +} + +pub fn print_command_help() { + println!("Enter one of the following: + NAV (To set course) + SRS (For short range sensor scan) + LRS (For long range sensor scan) + PHA (To fire phasers) + TOR (To fire photon torpedoes) + SHE (To raise or lower shields) + DAM (For damage control reports) + COM (To call on library-computer) + XXX (To resign your command) + ") +} + +pub fn end_game_failure(galaxy: &Galaxy) { + println!("Is is stardate {}. +There were {} Klingon battle cruisers left at +the end of your mission. +", galaxy.stardate, galaxy.remaining_klingons()); +} + +pub fn enterprise_destroyed() { + println!("The Enterprise has been destroyed. The Federation will be conquered."); +} + +pub fn bad_nav() { + println!(" Lt. Sulu reports, 'Incorrect course data, sir!'") +} + +pub fn enterprise_hit(hit_strength: &u16, from_sector: &Pos) { + println!("{hit_strength} unit hit on Enterprise from sector {from_sector}"); +} + +pub fn hit_edge(end: &EndPosition) { + println!("Lt. Uhura report message from Starfleet Command: + 'Permission to attempt crossing of galactic perimeter + is hereby *Denied*. Shut down your engines.' + Chief Engineer Scott reports, 'Warp engines shut down + at sector {} of quadrant {}.'", end.quadrant, end.sector); +} From a18112767dfd0e587958623e5d0abe224ac439ac Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 19:51:50 +1300 Subject: [PATCH 20/72] added intro section with quadrant name --- 84_Super_Star_Trek/rust/src/main.rs | 8 +++-- 84_Super_Star_Trek/rust/src/model.rs | 10 ++++++- 84_Super_Star_Trek/rust/src/view.rs | 45 ++++++++++++++++++++++++++++ 84_Super_Star_Trek/rust/tasks.md | 2 ++ 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index ec923c8c..8af85b77 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,4 +1,4 @@ -use std::{io::{stdin, stdout, Write}, process::exit, str::FromStr}; +use std::{io::{stdin, stdout, Write, Read}, process::exit, str::FromStr}; use model::Galaxy; @@ -13,7 +13,11 @@ fn main() { .expect("Error setting Ctrl-C handler"); let mut galaxy = Galaxy::generate_new(); - // todo: init options, starting state and notes + + view::intro(&galaxy); + let _ = prompt("Press Enter when ready to accept command"); + + view::starting_quadrant(&galaxy.enterprise.quadrant); view::short_range_scan(&galaxy); loop { diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 2e54555c..dd959220 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -6,6 +6,7 @@ use crate::view; pub struct Galaxy { pub stardate: f32, + pub final_stardate: f32, pub quadrants: Vec, pub enterprise: Enterprise } @@ -131,15 +132,22 @@ impl Galaxy { quadrants.into_iter().map(|q| { q.klingons.len() as u8 }).sum::() } + pub fn remaining_starbases(&self) -> u8 { + let quadrants = &self.quadrants; + quadrants.into_iter().filter(|q| q.star_base.is_some()).count() as u8 + } + pub fn generate_new() -> Self { let quadrants = Self::generate_quadrants(); let mut rng = rand::thread_rng(); let enterprise_quadrant = Pos(rng.gen_range(0..8), rng.gen_range(0..8)); let enterprise_sector = quadrants[enterprise_quadrant.as_index()].find_empty_sector(); + let stardate = rng.gen_range(20..=40) as f32 * 100.0; Galaxy { - stardate: 3800.0, + stardate, + final_stardate: stardate + rng.gen_range(25..=35) as f32, quadrants: quadrants, enterprise: Enterprise { condition: Condition::Green, diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 5d8c1fd6..62d22eea 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,5 +1,50 @@ use crate::model::{Galaxy, Pos, EndPosition, SectorStatus}; +pub fn intro(model: &Galaxy) { + let star_bases = model.remaining_starbases(); + let mut star_base_message: String = "There is 1 starbase".into(); + if star_bases > 1 { + star_base_message = format!("There are {} starbases", star_bases); + } + println!("Your orders are as follows: + Destroy the {} Klingon warships which have invaded + the galaxy before they can attack federation headquarters + on stardate {}. This gives you {} days. {} in the galaxy for resupplying your ship.", + model.remaining_klingons(), model.final_stardate, model.final_stardate - model.stardate, star_base_message) +} + +const REGION_NAMES: [&str; 16] = [ + "Antares", + "Sirius", + "Rigel", + "Deneb", + "Procyon", + "Capella", + "Vega", + "Betelgeuse", + "Canopus", + "Aldebaran", + "Altair", + "Regulus", + "Sagittarius", + "Arcturus", + "Pollux", + "Spica" +]; + +const SUB_REGION_NAMES: [&str; 4] = ["I", "II", "III", "IV"]; + +fn quadrant_name(quadrant: &Pos) -> String { + format!("{} {}", + REGION_NAMES[(quadrant.0 << 1 + quadrant.1 >> 1) as usize], + SUB_REGION_NAMES[(quadrant.1 % 4) as usize]) +} + +pub fn starting_quadrant(quadrant: &Pos) { + println!("Your mission begins with your starship located +in the galactic quadrant, '{}'.", quadrant_name(quadrant)) +} + pub fn short_range_scan(model: &Galaxy) { let quadrant = &model.quadrants[model.enterprise.quadrant.as_index()]; diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 8a9951b5..3da9cf93 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -4,6 +4,8 @@ Started after movement and display of stats was finished (no energy management o - [x] klingon movement - [x] klingon firing, game over etc +- [ ] add intro +- [ ] add entering (and starting in) sector headers - [ ] remove energy on move - [ ] shields - [ ] stranded... From 41ca9c3c709425809668f7ff9fbedd4dafdf06a2 Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 20:36:01 +1300 Subject: [PATCH 21/72] added enterprise to intro, entering quadrant names, and fixed bug in name indexing --- 84_Super_Star_Trek/rust/src/commands.rs | 6 ++-- 84_Super_Star_Trek/rust/src/main.rs | 1 + 84_Super_Star_Trek/rust/src/model.rs | 2 +- 84_Super_Star_Trek/rust/src/view.rs | 40 ++++++++++++++++++++++--- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index c27c6505..00ab1377 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -8,10 +8,12 @@ pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { view::hit_edge(&end); } + if galaxy.enterprise.quadrant != end.quadrant { + view::enter_quadrant(&end.quadrant); + } + galaxy.enterprise.quadrant = end.quadrant; galaxy.enterprise.sector = end.sector; - - // if new_quadrant isnt old quadrant print intro view::short_range_scan(&galaxy) } diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 8af85b77..2c1c06be 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -14,6 +14,7 @@ fn main() { let mut galaxy = Galaxy::generate_new(); + view::enterprise(); view::intro(&galaxy); let _ = prompt("Press Enter when ready to accept command"); diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index dd959220..d79089dd 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -106,7 +106,7 @@ impl Add for Pos { impl Display for Pos { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{} , {}", self.0, self.1) + write!(f, "{} , {}", self.0 + 1, self.1 + 1) } } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 62d22eea..774505f5 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,5 +1,33 @@ use crate::model::{Galaxy, Pos, EndPosition, SectorStatus}; +pub fn enterprise() { + println!(" + + + + + + + + + + + ,------*------, + ,------------- '--- ------' + '-------- --' / / + ,---' '-------/ /--, + '----------------' + + THE USS ENTERPRISE --- NCC-1701 + + + + + + +") +} + pub fn intro(model: &Galaxy) { let star_bases = model.remaining_starbases(); let mut star_base_message: String = "There is 1 starbase".into(); @@ -9,7 +37,7 @@ pub fn intro(model: &Galaxy) { println!("Your orders are as follows: Destroy the {} Klingon warships which have invaded the galaxy before they can attack federation headquarters - on stardate {}. This gives you {} days. {} in the galaxy for resupplying your ship.", + on stardate {}. This gives you {} days. {} in the galaxy for resupplying your ship.\n", model.remaining_klingons(), model.final_stardate, model.final_stardate - model.stardate, star_base_message) } @@ -36,13 +64,17 @@ const SUB_REGION_NAMES: [&str; 4] = ["I", "II", "III", "IV"]; fn quadrant_name(quadrant: &Pos) -> String { format!("{} {}", - REGION_NAMES[(quadrant.0 << 1 + quadrant.1 >> 1) as usize], + REGION_NAMES[((quadrant.0 << 1) + (quadrant.1 >> 2)) as usize], SUB_REGION_NAMES[(quadrant.1 % 4) as usize]) } pub fn starting_quadrant(quadrant: &Pos) { - println!("Your mission begins with your starship located -in the galactic quadrant, '{}'.", quadrant_name(quadrant)) + println!("\nYour mission begins with your starship located +in the galactic quadrant, '{}'.\n", quadrant_name(quadrant)) +} + +pub fn enter_quadrant(quadrant: &Pos) { + println!("\nNow entering {} quadrant . . .\n", quadrant_name(quadrant)) } pub fn short_range_scan(model: &Galaxy) { From dee8a96f3cd46f88b8f6da461c30c5c2e1307759 Mon Sep 17 00:00:00 2001 From: Christopher Date: Wed, 1 Mar 2023 20:42:51 +1300 Subject: [PATCH 22/72] working on tasks --- 84_Super_Star_Trek/rust/tasks.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 3da9cf93..2b532d48 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -4,8 +4,9 @@ Started after movement and display of stats was finished (no energy management o - [x] klingon movement - [x] klingon firing, game over etc -- [ ] add intro -- [ ] add entering (and starting in) sector headers +- [x] add intro +- [x] add entering (and starting in) sector headers +- [ ] conditions and danger messages - [ ] remove energy on move - [ ] shields - [ ] stranded... From 4cda6be184beea9568bebd542aec192574886b2d Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 10:02:56 +1300 Subject: [PATCH 23/72] added warning messages when entering a sector --- 84_Super_Star_Trek/rust/src/commands.rs | 7 +++++++ 84_Super_Star_Trek/rust/src/main.rs | 6 ++---- 84_Super_Star_Trek/rust/src/model.rs | 16 ++++++---------- 84_Super_Star_Trek/rust/src/view.rs | 16 +++++++++++++++- 84_Super_Star_Trek/rust/tasks.md | 8 +++++++- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 00ab1377..d55b08ff 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -10,6 +10,13 @@ pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { if galaxy.enterprise.quadrant != end.quadrant { view::enter_quadrant(&end.quadrant); + + if galaxy.quadrants[end.quadrant.as_index()].klingons.len() > 0 { + view::condition_red(); + if galaxy.enterprise.shields <= 200 { + view::danger_shields(); + } + } } galaxy.enterprise.quadrant = end.quadrant; diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 2c1c06be..498c5bd2 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -2,8 +2,6 @@ use std::{io::{stdin, stdout, Write, Read}, process::exit, str::FromStr}; use model::Galaxy; -use crate::model::Condition; - mod model; mod commands; mod view; @@ -28,7 +26,7 @@ fn main() { _ => view::print_command_help() } - if galaxy.enterprise.condition == Condition::Destroyed { // todo: also check if stranded + if galaxy.enterprise.destroyed { // todo: also check if stranded view::end_game_failure(&galaxy); break; } @@ -50,7 +48,7 @@ fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { } commands::move_klingons_and_fire(galaxy); - if galaxy.enterprise.condition == Condition::Destroyed { + if galaxy.enterprise.destroyed { return; } commands::move_enterprise(course.unwrap(), speed.unwrap(), galaxy); diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index d79089dd..9caa100a 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -36,7 +36,8 @@ impl Klingon { } pub struct Enterprise { - pub condition: Condition, + pub destroyed: bool, + pub damaged: bool, // later this could be by subsystem pub quadrant: Pos, pub sector: Pos, pub photon_torpedoes: u8, @@ -45,7 +46,7 @@ pub struct Enterprise { } impl Enterprise { fn take_hit(&mut self, sector: Pos, hit_strength: u16) { - if self.condition == Condition::Destroyed { + if self.destroyed { return; } @@ -55,7 +56,7 @@ impl Enterprise { if self.shields <= 0 { view::enterprise_destroyed(); - self.condition = Condition::Destroyed; + self.destroyed = true } // report shields @@ -63,12 +64,6 @@ impl Enterprise { } } -#[derive(PartialEq, Debug)] -pub enum Condition { - Green, Yellow, Red, - Destroyed, -} - pub struct EndPosition { pub quadrant: Pos, pub sector: Pos, @@ -150,7 +145,8 @@ impl Galaxy { final_stardate: stardate + rng.gen_range(25..=35) as f32, quadrants: quadrants, enterprise: Enterprise { - condition: Condition::Green, + destroyed: false, + damaged: false, quadrant: enterprise_quadrant, sector: enterprise_sector, photon_torpedoes: 28, diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 774505f5..320cb4eb 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -79,10 +79,16 @@ pub fn enter_quadrant(quadrant: &Pos) { pub fn short_range_scan(model: &Galaxy) { let quadrant = &model.quadrants[model.enterprise.quadrant.as_index()]; + let mut condition = "GREEN"; + if quadrant.klingons.len() > 0 { + condition = "*RED*"; + } else if model.enterprise.damaged { + condition = "YELLOW"; + } let data : [String; 8] = [ format!("Stardate {}", model.stardate), - format!("Condition {:?}", model.enterprise.condition), + format!("Condition {}", condition), format!("Quadrant {}", model.enterprise.quadrant), format!("Sector {}", model.enterprise.sector), format!("Photon torpedoes {}", model.enterprise.photon_torpedoes), @@ -151,3 +157,11 @@ pub fn hit_edge(end: &EndPosition) { Chief Engineer Scott reports, 'Warp engines shut down at sector {} of quadrant {}.'", end.quadrant, end.sector); } + +pub fn condition_red() { + println!("COMBAT AREA CONDITION RED") +} + +pub fn danger_shields() { + println!(" SHIELDS DANGEROUSLY LOW ") +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 2b532d48..374c1a29 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -6,10 +6,16 @@ Started after movement and display of stats was finished (no energy management o - [x] klingon firing, game over etc - [x] add intro - [x] add entering (and starting in) sector headers -- [ ] conditions and danger messages +- [x] conditions and danger messages - [ ] remove energy on move - [ ] shields + - [ ] shield control + - [ ] shield hit absorption +- [ ] subsystem damage + - and support for reports +- [ ] lrs? - [ ] stranded... - [ ] stop before hitting an object - when moving across a sector, the enterprise should stop before it runs into something - the current move is a jump, which makes this problematic. would need to rewrite it +- [ ] better command reading - support entering multiple values on a line (e.g. nav 3 0.1) From 7aec8284c03a866adff95e7040ee7e987d89d795 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 10:24:13 +1300 Subject: [PATCH 24/72] can now specify positional params on the nav command --- 84_Super_Star_Trek/rust/src/main.rs | 36 +++++++++++++++++++++-------- 84_Super_Star_Trek/rust/tasks.md | 2 +- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 498c5bd2..4212c6a7 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -20,9 +20,13 @@ fn main() { view::short_range_scan(&galaxy); loop { - match prompt("Command?").to_uppercase().as_str() { + let command = prompt("Command?"); + if command.len() == 0 { + continue; + } + match command[0].to_uppercase().as_str() { "SRS" => view::short_range_scan(&galaxy), - "NAV" => gather_dir_and_speed_then_move(&mut galaxy), + "NAV" => gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), _ => view::print_command_help() } @@ -33,15 +37,15 @@ fn main() { } } -fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { +fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec) { - let course = prompt_value::("Course (1-9)?", 1, 9); + let course = param_or_prompt_value(&provided, 0, "Course (1-9)?", 1, 9); if course.is_none() { view::bad_nav(); return; } - let speed = prompt_value::("Warp Factor (0-8)?", 0.0, 8.0); + let speed = param_or_prompt_value(&provided, 1, "Warp Factor (0-8)?", 0.0, 8.0); if speed.is_none() { view::bad_nav(); return; @@ -54,7 +58,7 @@ fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy) { commands::move_enterprise(course.unwrap(), speed.unwrap(), galaxy); } -fn prompt(prompt_text: &str) -> String { +fn prompt(prompt_text: &str) -> Vec { let stdin = stdin(); let mut stdout = stdout(); @@ -63,15 +67,29 @@ fn prompt(prompt_text: &str) -> String { let mut buffer = String::new(); if let Ok(_) = stdin.read_line(&mut buffer) { - return buffer.trim_end().into(); + return buffer.trim_end().split(" ").map(|s| s.to_string()).collect(); } - "".into() + Vec::new() } fn prompt_value(prompt_text: &str, min: T, max: T) -> Option { let passed = prompt(prompt_text); - match passed.parse::() { + if passed.len() != 1 { + return None + } + match passed[0].parse::() { Ok(n) if (n >= min && n <= max) => Some(n), _ => None } } + +fn param_or_prompt_value(params: &Vec, param_pos: usize, prompt_text: &str, min: T, max: T) -> Option { + if params.len() > param_pos { + match params[param_pos].parse::() { + Ok(n) => Some(n), + _ => None + } + } else { + return prompt_value::(prompt_text, min, max); + } +} \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 374c1a29..da2b9c1b 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -18,4 +18,4 @@ Started after movement and display of stats was finished (no energy management o - [ ] stop before hitting an object - when moving across a sector, the enterprise should stop before it runs into something - the current move is a jump, which makes this problematic. would need to rewrite it -- [ ] better command reading - support entering multiple values on a line (e.g. nav 3 0.1) +- [x] better command reading - support entering multiple values on a line (e.g. nav 3 0.1) From ca89609c3e91470a959ac9a25533db80e8e4ce32 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 11:26:43 +1300 Subject: [PATCH 25/72] energy is now removed with travel --- 84_Super_Star_Trek/rust/src/commands.rs | 31 ++++++++++++++++++++----- 84_Super_Star_Trek/rust/src/model.rs | 3 ++- 84_Super_Star_Trek/rust/src/view.rs | 9 +++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index d55b08ff..3cc4aff5 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -2,25 +2,43 @@ use crate::{model::{Galaxy, Pos, COURSES, EndPosition}, view}; pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { - let end = find_end_quadrant_sector(galaxy.enterprise.quadrant, galaxy.enterprise.sector, course, warp_speed); + let ship = &mut galaxy.enterprise; + + // todo account for being blocked + + let end = find_end_quadrant_sector(ship.quadrant, ship.sector, course, warp_speed); + + // todo account for engine damage + + if end.energy_cost > ship.total_energy { + view::insuffient_warp_energy(warp_speed); + return + } if end.hit_edge { view::hit_edge(&end); } + - if galaxy.enterprise.quadrant != end.quadrant { + if ship.quadrant != end.quadrant { view::enter_quadrant(&end.quadrant); if galaxy.quadrants[end.quadrant.as_index()].klingons.len() > 0 { view::condition_red(); - if galaxy.enterprise.shields <= 200 { + if ship.shields <= 200 { view::danger_shields(); } } } - galaxy.enterprise.quadrant = end.quadrant; - galaxy.enterprise.sector = end.sector; + ship.quadrant = end.quadrant; + ship.sector = end.sector; + + ship.total_energy = (ship.total_energy - end.energy_cost).max(0); + if ship.shields > ship.total_energy { + view::divert_energy_from_shields(); + ship.shields = ship.total_energy; + } view::short_range_scan(&galaxy) } @@ -58,8 +76,9 @@ fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, let quadrant = Pos((nx / 8) as u8, (ny / 8) as u8); let sector = Pos((nx % 8) as u8, (ny % 8) as u8); + let energy_cost = distance as u16 + 10; - EndPosition { quadrant, sector, hit_edge } + EndPosition { quadrant, sector, hit_edge, energy_cost } } pub fn move_klingons_and_fire(galaxy: &mut Galaxy) { diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 9caa100a..103887f5 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -67,7 +67,8 @@ impl Enterprise { pub struct EndPosition { pub quadrant: Pos, pub sector: Pos, - pub hit_edge: bool + pub hit_edge: bool, + pub energy_cost: u16, } #[derive(PartialEq, Clone, Copy, Debug)] diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 320cb4eb..f460eaa7 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -165,3 +165,12 @@ pub fn condition_red() { pub fn danger_shields() { println!(" SHIELDS DANGEROUSLY LOW ") } + +pub fn insuffient_warp_energy(warp_speed: f32) { + println!("Engineering reports, 'Insufficient energy available + for maneuvering at warp {warp_speed} !'") +} + +pub fn divert_energy_from_shields() { + println!("Shield Control supplies energy to complete the maneuver.") +} From 2feb1a9c6532cd4c3dcbb93aa45aefc513989fad Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 11:37:58 +1300 Subject: [PATCH 26/72] implemented setting shields --- 84_Super_Star_Trek/rust/src/main.rs | 22 ++++++++++++++++++++++ 84_Super_Star_Trek/rust/src/view.rs | 17 +++++++++++++++++ 84_Super_Star_Trek/rust/tasks.md | 6 +++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 4212c6a7..477a0594 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -27,6 +27,7 @@ fn main() { match command[0].to_uppercase().as_str() { "SRS" => view::short_range_scan(&galaxy), "NAV" => gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), + "SHE" => get_amount_and_set_shields(&mut galaxy, command[1..].into()), _ => view::print_command_help() } @@ -37,6 +38,27 @@ fn main() { } } +fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { + + // todo check for damaged module + + view::energy_available(galaxy.enterprise.total_energy); + let value = param_or_prompt_value(&provided, 0, "Number of units to shields", 0, i32::MAX); + if value.is_none() { + view::shields_unchanged(); + return; + } + let value = value.unwrap() as u16; + if value > galaxy.enterprise.total_energy { + view::ridiculous(); + view::shields_unchanged(); + return; + } + + galaxy.enterprise.shields = value; + view::shields_set(value); +} + fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec) { let course = param_or_prompt_value(&provided, 0, "Course (1-9)?", 1, 9); diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index f460eaa7..95cad41d 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -174,3 +174,20 @@ pub fn insuffient_warp_energy(warp_speed: f32) { pub fn divert_energy_from_shields() { println!("Shield Control supplies energy to complete the maneuver.") } + +pub fn energy_available(total_energy: u16) { + println!("Energy available = {{{total_energy}}}") +} + +pub fn shields_unchanged() { + println!("") +} + +pub fn ridiculous() { + println!("Shield Control reports, 'This is not the Federation Treasury.'") +} + +pub fn shields_set(value: u16) { + println!("Deflector control room report: + 'Shields now at {value} units per your command.'") +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index da2b9c1b..7c7e1df8 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -7,9 +7,9 @@ Started after movement and display of stats was finished (no energy management o - [x] add intro - [x] add entering (and starting in) sector headers - [x] conditions and danger messages -- [ ] remove energy on move -- [ ] shields - - [ ] shield control +- [x] remove energy on move +- [x] shields + - [x] shield control - [ ] shield hit absorption - [ ] subsystem damage - and support for reports From 2898e701c3504192816172192e16c5c868e0cbd5 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 11:41:43 +1300 Subject: [PATCH 27/72] shield hit absorbtion --- 84_Super_Star_Trek/rust/src/model.rs | 4 ++-- 84_Super_Star_Trek/rust/src/view.rs | 4 ++++ 84_Super_Star_Trek/rust/tasks.md | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 103887f5..4f5a65ac 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -52,14 +52,14 @@ impl Enterprise { view::enterprise_hit(&hit_strength, §or); - // absorb into shields + self.shields = (self.shields - hit_strength).max(0); if self.shields <= 0 { view::enterprise_destroyed(); self.destroyed = true } - // report shields + view::shields_hit(self.shields); // take damage if strength is greater than 20 } } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 95cad41d..02c72815 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -191,3 +191,7 @@ pub fn shields_set(value: u16) { println!("Deflector control room report: 'Shields now at {value} units per your command.'") } + +pub fn shields_hit(shields: u16) { + println!(" ") +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 7c7e1df8..918a0395 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -10,7 +10,7 @@ Started after movement and display of stats was finished (no energy management o - [x] remove energy on move - [x] shields - [x] shield control - - [ ] shield hit absorption + - [x] shield hit absorption - [ ] subsystem damage - and support for reports - [ ] lrs? From 5b560f929ce66cb0884f9df2b5eb2cb1864fa3e6 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 11:48:24 +1300 Subject: [PATCH 28/72] trimmed edge tests in nav, and removed no longer needed unit tests --- 84_Super_Star_Trek/rust/src/commands.rs | 95 +------------------------ 1 file changed, 3 insertions(+), 92 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 3cc4aff5..2f42edd5 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -56,23 +56,9 @@ fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, let mut nx = (galaxy_pos.0 as i8) + dx * distance; let mut ny = (galaxy_pos.1 as i8) + dy * distance; - let mut hit_edge = false; - if nx < 0 { - nx = 0; - hit_edge = true; - } - if ny < 0 { - ny = 0; - hit_edge = true; - } - if nx >= 64 { - nx = 63; - hit_edge = true; - } - if ny >= 64 { - ny = 63; - hit_edge = true; - } + let hit_edge = nx < 0 || ny < 0 || nx >= 64 || ny >= 64; + nx = nx.min(63).max(0); + ny = ny.min(63).max(0); let quadrant = Pos((nx / 8) as u8, (ny / 8) as u8); let sector = Pos((nx % 8) as u8, (ny % 8) as u8); @@ -94,78 +80,3 @@ pub fn move_klingons_and_fire(galaxy: &mut Galaxy) { quadrant.klingons[k].fire_on(&mut galaxy.enterprise); } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_course_east() { - let start_quadrant = Pos(0,0); - let start_sector = Pos(0,0); - let end = find_end_quadrant_sector(start_quadrant, start_sector, 1, 0.1); - assert_eq!(end.quadrant, start_quadrant, "right quadrant"); - assert_eq!(end.sector, Pos(1,0), "right sector"); - assert!(!end.hit_edge) - } - - #[test] - fn test_course_far_east() { - let start_quadrant = Pos(0,0); - let start_sector = Pos(0,0); - let end = find_end_quadrant_sector(start_quadrant, start_sector, 1, 1.0); - assert_eq!(end.quadrant, Pos(1,0), "right quadrant"); - assert_eq!(end.sector, start_sector, "right sector"); - assert!(!end.hit_edge) - } - - #[test] - fn test_course_too_far_east() { - let start_quadrant = Pos(0,0); - let start_sector = Pos(0,0); - let end = find_end_quadrant_sector(start_quadrant, start_sector, 1, 8.0); - assert_eq!(end.quadrant, Pos(7,0), "right quadrant"); - assert_eq!(end.sector, Pos(7,0), "right sector"); - assert!(end.hit_edge) - } - - #[test] - fn test_course_south() { - let start_quadrant = Pos(0,0); - let start_sector = Pos(0,0); - let end = find_end_quadrant_sector(start_quadrant, start_sector, 7, 0.1); - assert_eq!(end.quadrant, start_quadrant, "right quadrant"); - assert_eq!(end.sector, Pos(0,1), "right sector"); - assert!(!end.hit_edge) - } - - #[test] - fn test_course_far_south() { - let start_quadrant = Pos(0,0); - let start_sector = Pos(0,0); - let end = find_end_quadrant_sector(start_quadrant, start_sector, 7, 1.0); - assert_eq!(end.quadrant, Pos(0,1), "right quadrant"); - assert_eq!(end.sector, start_sector, "right sector"); - assert!(!end.hit_edge) - } - - #[test] - fn test_course_too_far_south() { - let start_quadrant = Pos(0,0); - let start_sector = Pos(0,0); - let end = find_end_quadrant_sector(start_quadrant, start_sector, 7, 8.0); - assert_eq!(end.quadrant, Pos(0,7), "right quadrant"); - assert_eq!(end.sector, Pos(0,7), "right sector"); - assert!(end.hit_edge) - } - - #[test] - fn test_course_north_east() { - let start_quadrant = Pos(0,0); - let start_sector = Pos(0,1); - let end = find_end_quadrant_sector(start_quadrant, start_sector, 2, 0.1); - assert_eq!(end.quadrant, start_quadrant, "right quadrant"); - assert_eq!(end.sector, Pos(1,0), "right sector"); - assert!(!end.hit_edge) - } -} From d7e3feff54689f5830a5c39d25ec263dde26f108 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 11:53:33 +1300 Subject: [PATCH 29/72] some reorganisation of code --- 84_Super_Star_Trek/rust/src/commands.rs | 48 ++++++++++++- 84_Super_Star_Trek/rust/src/input.rs | 37 ++++++++++ 84_Super_Star_Trek/rust/src/main.rs | 92 +++---------------------- 3 files changed, 91 insertions(+), 86 deletions(-) create mode 100644 84_Super_Star_Trek/rust/src/input.rs diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 2f42edd5..3239b45e 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,6 +1,48 @@ -use crate::{model::{Galaxy, Pos, COURSES, EndPosition}, view}; +use crate::{model::{Galaxy, Pos, COURSES, EndPosition}, view, input}; -pub fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { +pub fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { + + // todo check for damaged module + + view::energy_available(galaxy.enterprise.total_energy); + let value = input::param_or_prompt_value(&provided, 0, "Number of units to shields", 0, i32::MAX); + if value.is_none() { + view::shields_unchanged(); + return; + } + let value = value.unwrap() as u16; + if value > galaxy.enterprise.total_energy { + view::ridiculous(); + view::shields_unchanged(); + return; + } + + galaxy.enterprise.shields = value; + view::shields_set(value); +} + +pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec) { + + let course = input::param_or_prompt_value(&provided, 0, "Course (1-9)?", 1, 9); + if course.is_none() { + view::bad_nav(); + return; + } + + let speed = input::param_or_prompt_value(&provided, 1, "Warp Factor (0-8)?", 0.0, 8.0); + if speed.is_none() { + view::bad_nav(); + return; + } + + move_klingons_and_fire(galaxy); + if galaxy.enterprise.destroyed { + return; + } + move_enterprise(course.unwrap(), speed.unwrap(), galaxy); +} + +fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { let ship = &mut galaxy.enterprise; @@ -67,7 +109,7 @@ fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, EndPosition { quadrant, sector, hit_edge, energy_cost } } -pub fn move_klingons_and_fire(galaxy: &mut Galaxy) { +fn move_klingons_and_fire(galaxy: &mut Galaxy) { let quadrant = &mut galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; for k in 0..quadrant.klingons.len() { let new_sector = quadrant.find_empty_sector(); diff --git a/84_Super_Star_Trek/rust/src/input.rs b/84_Super_Star_Trek/rust/src/input.rs new file mode 100644 index 00000000..75f12102 --- /dev/null +++ b/84_Super_Star_Trek/rust/src/input.rs @@ -0,0 +1,37 @@ +use std::{io::{stdin, stdout, Write}, str::FromStr}; + +pub fn prompt(prompt_text: &str) -> Vec { + let stdin = stdin(); + let mut stdout = stdout(); + + print!("{prompt_text} "); + let _ = stdout.flush(); + + let mut buffer = String::new(); + if let Ok(_) = stdin.read_line(&mut buffer) { + return buffer.trim_end().split(" ").map(|s| s.to_string()).collect(); + } + Vec::new() +} + +pub fn prompt_value(prompt_text: &str, min: T, max: T) -> Option { + let passed = prompt(prompt_text); + if passed.len() != 1 { + return None + } + match passed[0].parse::() { + Ok(n) if (n >= min && n <= max) => Some(n), + _ => None + } +} + +pub fn param_or_prompt_value(params: &Vec, param_pos: usize, prompt_text: &str, min: T, max: T) -> Option { + if params.len() > param_pos { + match params[param_pos].parse::() { + Ok(n) => Some(n), + _ => None + } + } else { + return prompt_value::(prompt_text, min, max); + } +} \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 477a0594..1b9a0522 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,7 +1,8 @@ -use std::{io::{stdin, stdout, Write, Read}, process::exit, str::FromStr}; +use std::process::exit; use model::Galaxy; +mod input; mod model; mod commands; mod view; @@ -14,104 +15,29 @@ fn main() { view::enterprise(); view::intro(&galaxy); - let _ = prompt("Press Enter when ready to accept command"); + let _ = input::prompt("Press Enter when ready to accept command"); view::starting_quadrant(&galaxy.enterprise.quadrant); view::short_range_scan(&galaxy); loop { - let command = prompt("Command?"); + let command = input::prompt("Command?"); if command.len() == 0 { continue; } match command[0].to_uppercase().as_str() { "SRS" => view::short_range_scan(&galaxy), - "NAV" => gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), - "SHE" => get_amount_and_set_shields(&mut galaxy, command[1..].into()), + "NAV" => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), + "SHE" => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), _ => view::print_command_help() } if galaxy.enterprise.destroyed { // todo: also check if stranded view::end_game_failure(&galaxy); + // todo check if can restart break; } + + // todo check for victory } } - -fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { - - // todo check for damaged module - - view::energy_available(galaxy.enterprise.total_energy); - let value = param_or_prompt_value(&provided, 0, "Number of units to shields", 0, i32::MAX); - if value.is_none() { - view::shields_unchanged(); - return; - } - let value = value.unwrap() as u16; - if value > galaxy.enterprise.total_energy { - view::ridiculous(); - view::shields_unchanged(); - return; - } - - galaxy.enterprise.shields = value; - view::shields_set(value); -} - -fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec) { - - let course = param_or_prompt_value(&provided, 0, "Course (1-9)?", 1, 9); - if course.is_none() { - view::bad_nav(); - return; - } - - let speed = param_or_prompt_value(&provided, 1, "Warp Factor (0-8)?", 0.0, 8.0); - if speed.is_none() { - view::bad_nav(); - return; - } - - commands::move_klingons_and_fire(galaxy); - if galaxy.enterprise.destroyed { - return; - } - commands::move_enterprise(course.unwrap(), speed.unwrap(), galaxy); -} - -fn prompt(prompt_text: &str) -> Vec { - let stdin = stdin(); - let mut stdout = stdout(); - - print!("{prompt_text} "); - let _ = stdout.flush(); - - let mut buffer = String::new(); - if let Ok(_) = stdin.read_line(&mut buffer) { - return buffer.trim_end().split(" ").map(|s| s.to_string()).collect(); - } - Vec::new() -} - -fn prompt_value(prompt_text: &str, min: T, max: T) -> Option { - let passed = prompt(prompt_text); - if passed.len() != 1 { - return None - } - match passed[0].parse::() { - Ok(n) if (n >= min && n <= max) => Some(n), - _ => None - } -} - -fn param_or_prompt_value(params: &Vec, param_pos: usize, prompt_text: &str, min: T, max: T) -> Option { - if params.len() > param_pos { - match params[param_pos].parse::() { - Ok(n) => Some(n), - _ => None - } - } else { - return prompt_value::(prompt_text, min, max); - } -} \ No newline at end of file From bcb1c68cb54293090b77253071226c33a0745f53 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 11:55:55 +1300 Subject: [PATCH 30/72] added some tasks --- 84_Super_Star_Trek/rust/tasks.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 918a0395..29f47cd3 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -19,3 +19,9 @@ Started after movement and display of stats was finished (no energy management o - when moving across a sector, the enterprise should stop before it runs into something - the current move is a jump, which makes this problematic. would need to rewrite it - [x] better command reading - support entering multiple values on a line (e.g. nav 3 0.1) +- [ ] starbases + - [ ] repair +- [ ] weapons + - [ ] phasers + - [ ] torpedoes +- [ ] restarting the game From 0581fe38f81b42bc81f8dd8d1b80b7ba80781aa8 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 13:36:30 +1300 Subject: [PATCH 31/72] basic damage to systems and restricted warp speed --- 84_Super_Star_Trek/rust/src/commands.rs | 33 ++++++++++++++++++++++--- 84_Super_Star_Trek/rust/src/main.rs | 6 ++--- 84_Super_Star_Trek/rust/src/model.rs | 6 ++--- 84_Super_Star_Trek/rust/src/view.rs | 25 ++++++++++++++++++- 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 3239b45e..0675ee4f 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,8 +1,20 @@ use crate::{model::{Galaxy, Pos, COURSES, EndPosition}, view, input}; +pub fn perform_short_range_scan(galaxy: &Galaxy) { + if galaxy.enterprise.damaged.contains_key(view::keys::SHORT_RANGE_SCAN) { + view::scanners_out(); + return; + } + + view::short_range_scan(&galaxy) +} + pub fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { - // todo check for damaged module + if galaxy.enterprise.damaged.contains_key(view::keys::SHIELD_CONTROL) { + view::inoperable("Shield Control"); + return; + } view::energy_available(galaxy.enterprise.total_energy); let value = input::param_or_prompt_value(&provided, 0, "Number of units to shields", 0, i32::MAX); @@ -10,6 +22,7 @@ pub fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { view::shields_unchanged(); return; } + let value = value.unwrap() as u16; if value > galaxy.enterprise.total_energy { view::ridiculous(); @@ -29,17 +42,31 @@ pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec return; } - let speed = input::param_or_prompt_value(&provided, 1, "Warp Factor (0-8)?", 0.0, 8.0); + let course = course.unwrap(); + + let mut max_warp = 8.0; + if galaxy.enterprise.damaged.contains_key(view::keys::NAVIGATION) { + max_warp = 0.2; + } + + let speed = input::param_or_prompt_value(&provided, 1, format!("Warp Factor (0-{})?", max_warp).as_str(), 0.0, 8.0); if speed.is_none() { view::bad_nav(); return; } + + let speed = speed.unwrap(); + + if speed > max_warp { + view::damaged_engines(max_warp, speed); + return; + } move_klingons_and_fire(galaxy); if galaxy.enterprise.destroyed { return; } - move_enterprise(course.unwrap(), speed.unwrap(), galaxy); + move_enterprise(course, speed, galaxy); } fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 1b9a0522..ecde0476 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -26,9 +26,9 @@ fn main() { continue; } match command[0].to_uppercase().as_str() { - "SRS" => view::short_range_scan(&galaxy), - "NAV" => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), - "SHE" => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), + view::keys::SHORT_RANGE_SCAN => commands::perform_short_range_scan(&galaxy), + view::keys::NAVIGATION => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), + view::keys::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), _ => view::print_command_help() } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 4f5a65ac..a078df05 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -1,4 +1,4 @@ -use std::{ops::{Mul, Add}, fmt::Display}; +use std::{ops::{Mul, Add}, fmt::Display, collections::HashMap}; use rand::Rng; @@ -37,7 +37,7 @@ impl Klingon { pub struct Enterprise { pub destroyed: bool, - pub damaged: bool, // later this could be by subsystem + pub damaged: HashMap, pub quadrant: Pos, pub sector: Pos, pub photon_torpedoes: u8, @@ -147,7 +147,7 @@ impl Galaxy { quadrants: quadrants, enterprise: Enterprise { destroyed: false, - damaged: false, + damaged: HashMap::new(), quadrant: enterprise_quadrant, sector: enterprise_sector, photon_torpedoes: 28, diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 02c72815..68934549 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,5 +1,15 @@ use crate::model::{Galaxy, Pos, EndPosition, SectorStatus}; +pub mod keys { + pub const SHORT_RANGE_SCAN: &str = "SRS"; + pub const NAVIGATION: &str = "NAV"; + pub const SHIELD_CONTROL: &str = "SHE"; + + pub const ALL_SYSTEMS: [&str; 3] = [ + SHORT_RANGE_SCAN, NAVIGATION, SHIELD_CONTROL + ]; +} + pub fn enterprise() { println!(" @@ -82,7 +92,7 @@ pub fn short_range_scan(model: &Galaxy) { let mut condition = "GREEN"; if quadrant.klingons.len() > 0 { condition = "*RED*"; - } else if model.enterprise.damaged { + } else if model.enterprise.damaged.len() > 0 { condition = "YELLOW"; } @@ -195,3 +205,16 @@ pub fn shields_set(value: u16) { pub fn shields_hit(shields: u16) { println!(" ") } + +pub fn inoperable(arg: &str) { + println!("{} inoperable", arg) +} + +pub fn scanners_out() { + println!("*** Short Range Sensors are out ***") +} + +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} !'") +} From f253ff7155a140c5903f1a1bd742ad46f175d585 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 13:39:12 +1300 Subject: [PATCH 32/72] moved where system keys are defined --- 84_Super_Star_Trek/rust/src/commands.rs | 10 ++++------ 84_Super_Star_Trek/rust/src/main.rs | 6 +++--- 84_Super_Star_Trek/rust/src/model.rs | 10 ++++++++++ 84_Super_Star_Trek/rust/src/view.rs | 10 ---------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 0675ee4f..86c72f98 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,7 +1,7 @@ -use crate::{model::{Galaxy, Pos, COURSES, EndPosition}, view, input}; +use crate::{model::{Galaxy, Pos, COURSES, EndPosition, self}, view, input}; pub fn perform_short_range_scan(galaxy: &Galaxy) { - if galaxy.enterprise.damaged.contains_key(view::keys::SHORT_RANGE_SCAN) { + if galaxy.enterprise.damaged.contains_key(model::systems::SHORT_RANGE_SCAN) { view::scanners_out(); return; } @@ -11,7 +11,7 @@ pub fn perform_short_range_scan(galaxy: &Galaxy) { pub fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { - if galaxy.enterprise.damaged.contains_key(view::keys::SHIELD_CONTROL) { + if galaxy.enterprise.damaged.contains_key(model::systems::SHIELD_CONTROL) { view::inoperable("Shield Control"); return; } @@ -45,7 +45,7 @@ pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec let course = course.unwrap(); let mut max_warp = 8.0; - if galaxy.enterprise.damaged.contains_key(view::keys::NAVIGATION) { + if galaxy.enterprise.damaged.contains_key(model::systems::WARP_ENGINES) { max_warp = 0.2; } @@ -77,8 +77,6 @@ fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { let end = find_end_quadrant_sector(ship.quadrant, ship.sector, course, warp_speed); - // todo account for engine damage - if end.energy_cost > ship.total_energy { view::insuffient_warp_energy(warp_speed); return diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index ecde0476..5db8350c 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -26,9 +26,9 @@ fn main() { continue; } match command[0].to_uppercase().as_str() { - view::keys::SHORT_RANGE_SCAN => commands::perform_short_range_scan(&galaxy), - view::keys::NAVIGATION => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), - view::keys::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), + model::systems::SHORT_RANGE_SCAN => commands::perform_short_range_scan(&galaxy), + model::systems::WARP_ENGINES => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), + model::systems::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), _ => view::print_command_help() } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index a078df05..f46cc548 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -64,6 +64,16 @@ impl Enterprise { } } +pub mod systems { + pub const SHORT_RANGE_SCAN: &str = "SRS"; + pub const WARP_ENGINES: &str = "NAV"; + pub const SHIELD_CONTROL: &str = "SHE"; + + pub const ALL: [&str; 3] = [ + SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL + ]; +} + pub struct EndPosition { pub quadrant: Pos, pub sector: Pos, diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 68934549..e7bc5516 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,15 +1,5 @@ use crate::model::{Galaxy, Pos, EndPosition, SectorStatus}; -pub mod keys { - pub const SHORT_RANGE_SCAN: &str = "SRS"; - pub const NAVIGATION: &str = "NAV"; - pub const SHIELD_CONTROL: &str = "SHE"; - - pub const ALL_SYSTEMS: [&str; 3] = [ - SHORT_RANGE_SCAN, NAVIGATION, SHIELD_CONTROL - ]; -} - pub fn enterprise() { println!(" From cb685efe0cc32112242d4f657ee802505d2e6dc4 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 13:48:42 +1300 Subject: [PATCH 33/72] random system damage on hit --- 84_Super_Star_Trek/rust/src/commands.rs | 1 - 84_Super_Star_Trek/rust/src/model.rs | 17 +++++++++++++++++ 84_Super_Star_Trek/rust/tasks.md | 5 +++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 86c72f98..c5e59c12 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -86,7 +86,6 @@ fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { view::hit_edge(&end); } - if ship.quadrant != end.quadrant { view::enter_quadrant(&end.quadrant); diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index f46cc548..c968c08a 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -60,7 +60,24 @@ impl Enterprise { } view::shields_hit(self.shields); + // take damage if strength is greater than 20 + if hit_strength >= 20 { + self.take_damage(hit_strength) + } + } + + fn take_damage(&mut self, hit_strength: u16) { + let mut rng = rand::thread_rng(); + + let hit_past_shield = hit_strength as f32 / self.shields as f32; + if rng.gen::() > 0.6 || hit_past_shield < 0.02 { + return + } + + let system = systems::ALL[rng.gen_range(0..systems::ALL.len())].to_string(); + let damage = hit_past_shield + rng.gen::() * 0.5; + self.damaged.entry(system).and_modify(|d| *d += damage).or_insert(damage); } } diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 29f47cd3..c55914df 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -11,8 +11,9 @@ Started after movement and display of stats was finished (no energy management o - [x] shields - [x] shield control - [x] shield hit absorption -- [ ] subsystem damage - - and support for reports +- [x] subsystem damage + - [ ] and support for reports +- [ ] random system damage on move - [ ] lrs? - [ ] stranded... - [ ] stop before hitting an object From 33fc2b4c5a9a833fe73794e74a8c1c071c72afb5 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 14:11:49 +1300 Subject: [PATCH 34/72] implemented damage command --- 84_Super_Star_Trek/rust/src/commands.rs | 16 +++++++++++++++- 84_Super_Star_Trek/rust/src/main.rs | 1 + 84_Super_Star_Trek/rust/src/model.rs | 14 ++++++++++---- 84_Super_Star_Trek/rust/tasks.md | 2 +- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index c5e59c12..2bc5f4f6 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,4 +1,4 @@ -use crate::{model::{Galaxy, Pos, COURSES, EndPosition, self}, view, input}; +use crate::{model::{Galaxy, Pos, COURSES, EndPosition, self, Enterprise, systems}, view, input}; pub fn perform_short_range_scan(galaxy: &Galaxy) { if galaxy.enterprise.damaged.contains_key(model::systems::SHORT_RANGE_SCAN) { @@ -146,3 +146,17 @@ fn move_klingons_and_fire(galaxy: &mut Galaxy) { quadrant.klingons[k].fire_on(&mut galaxy.enterprise); } } + +pub fn display_damage_control(enterprise: &Enterprise) { + if enterprise.damaged.contains_key(model::systems::DAMAGE_CONTROL) { + view::inoperable("Damage Control"); + return; + } + + 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) + } + println!(); +} diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 5db8350c..0809ec23 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -29,6 +29,7 @@ fn main() { model::systems::SHORT_RANGE_SCAN => commands::perform_short_range_scan(&galaxy), model::systems::WARP_ENGINES => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), model::systems::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), + model::systems::DAMAGE_CONTROL => commands::display_damage_control(&galaxy.enterprise), _ => view::print_command_help() } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index c968c08a..675ac8ec 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -61,7 +61,6 @@ impl Enterprise { view::shields_hit(self.shields); - // take damage if strength is greater than 20 if hit_strength >= 20 { self.take_damage(hit_strength) } @@ -77,17 +76,24 @@ impl Enterprise { let system = systems::ALL[rng.gen_range(0..systems::ALL.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.damaged.entry(system).and_modify(|d| *d -= damage).or_insert(-damage); } } 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; 3] = [ - SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL + pub const ALL: [&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" ]; } diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index c55914df..e6c68ce1 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -12,7 +12,7 @@ Started after movement and display of stats was finished (no energy management o - [x] shield control - [x] shield hit absorption - [x] subsystem damage - - [ ] and support for reports + - [x] and support for reports - [ ] random system damage on move - [ ] lrs? - [ ] stranded... From 51663ea0b168b2ee6915b9b198a6b74ec864c9fb Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 17:13:52 +1300 Subject: [PATCH 35/72] implemented random system movement changes damage and repair, with changes to how this is implemented / reported --- 84_Super_Star_Trek/rust/src/commands.rs | 52 +++++++++++++++++++++++-- 84_Super_Star_Trek/rust/src/model.rs | 34 ++++++++++++---- 84_Super_Star_Trek/rust/src/view.rs | 16 ++++++++ 84_Super_Star_Trek/rust/tasks.md | 2 +- 4 files changed, 93 insertions(+), 11 deletions(-) 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 From 4644a91024b2e0d5dfd70d68bf8b3cca61e01b66 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 18:56:47 +1300 Subject: [PATCH 36/72] implemented long range scanners --- 84_Super_Star_Trek/rust/src/commands.rs | 9 +++++++++ 84_Super_Star_Trek/rust/src/main.rs | 3 ++- 84_Super_Star_Trek/rust/src/model.rs | 6 ++++-- 84_Super_Star_Trek/rust/src/view.rs | 27 +++++++++++++++++++++++++ 84_Super_Star_Trek/rust/tasks.md | 3 +++ 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 3b14e4cf..25c2954d 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -206,3 +206,12 @@ pub fn display_damage_control(enterprise: &Enterprise) { } println!(); } + +pub fn perform_long_range_scan(galaxy: &Galaxy) { + if galaxy.enterprise.damaged.contains_key(model::systems::SHORT_RANGE_SCAN) { + view::inoperable("Long Range Scanners"); + return; + } + + view::long_range_scan(galaxy); +} \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 0809ec23..fd01b9b5 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -25,11 +25,12 @@ fn main() { if command.len() == 0 { continue; } - match command[0].to_uppercase().as_str() { + match command[0].to_uppercase().as_str() { // order is weird because i built it in this order :) model::systems::SHORT_RANGE_SCAN => commands::perform_short_range_scan(&galaxy), model::systems::WARP_ENGINES => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), model::systems::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), model::systems::DAMAGE_CONTROL => commands::display_damage_control(&galaxy.enterprise), + model::systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&galaxy), _ => view::print_command_help() } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 515b7fb2..f502a13f 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -101,9 +101,10 @@ pub mod systems { pub const WARP_ENGINES: &str = "NAV"; pub const SHIELD_CONTROL: &str = "SHE"; pub const DAMAGE_CONTROL: &str = "DAM"; + pub const LONG_RANGE_SCAN: &str = "LRS"; - pub const KEYS: [&str; 4] = [ - SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL, DAMAGE_CONTROL + pub const KEYS: [&str; 5] = [ + SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL, DAMAGE_CONTROL, LONG_RANGE_SCAN ]; pub fn name_for(key: &str) -> String { @@ -112,6 +113,7 @@ pub mod systems { WARP_ENGINES => "Warp Engines".into(), SHIELD_CONTROL => "Shield Control".into(), DAMAGE_CONTROL => "Damage Control".into(), + LONG_RANGE_SCAN => "Long Range Scanners".into(), _ => "Unknown".into() } } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index e34c44d4..26daf070 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -224,3 +224,30 @@ pub fn random_repair_report_for(name: &str, damaged: bool) { pub fn system_repair_completed(name: String) { println!(" {name} repair completed.") } + +pub fn long_range_scan(galaxy: &Galaxy) { + + let cx = galaxy.enterprise.quadrant.0 as i8; + let cy = galaxy.enterprise.quadrant.1 as i8; + + println!("Long range scan for quadrant {}", galaxy.enterprise.quadrant); + println!("{:-^19}", ""); + for y in cy - 1..=cy + 1 { + for x in cx - 1..=cx + 1 { + let mut klingons = "*".into(); + let mut star_bases = "*".into(); + let mut stars = "*".into(); + + if y >= 0 && y < 8 && x >= 0 && x < 8 { + let quadrant = &galaxy.quadrants[Pos(x as u8, y as u8).as_index()]; + klingons = format!("{}", quadrant.klingons.len()); + star_bases = quadrant.star_base.map_or("0", |_| "1"); + stars = format!("{}", quadrant.stars.len()); + } + + print!(": {}{}{} ", klingons, stars, star_bases) + } + println!(":"); + println!("{:-^19}", ""); + } +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 0c81bce1..8dd2d166 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -19,6 +19,7 @@ Started after movement and display of stats was finished (no energy management o - [ ] stop before hitting an object - when moving across a sector, the enterprise should stop before it runs into something - the current move is a jump, which makes this problematic. would need to rewrite it + - also, movement courses could be floats, according to the instructions, allowing for more precise movement and aiming - [x] better command reading - support entering multiple values on a line (e.g. nav 3 0.1) - [ ] starbases - [ ] repair @@ -26,3 +27,5 @@ Started after movement and display of stats was finished (no energy management o - [ ] phasers - [ ] torpedoes - [ ] restarting the game +- [ ] time progression + - check all areas where time should move, and adjust accordingly From 460dcd7ab44ca6c3df435b33a43e698f17335c3b Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 18:57:53 +1300 Subject: [PATCH 37/72] slight tweak to allow close to fixed to be fixed --- 84_Super_Star_Trek/rust/src/model.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index f502a13f..a55eb62f 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -85,7 +85,7 @@ impl Enterprise { pub fn repair_system(&mut self, system: &str, amount: f32) -> bool { let existing_damage = self.damaged[system]; - if existing_damage + amount >= 0.0 { + if existing_damage + amount >= -0.1 { self.damaged.remove(system); return true; } From d76b0482369cff2c82a83ac9804d78f3aaad6835 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 19:01:48 +1300 Subject: [PATCH 38/72] revised random repair or damage to only repair damaged systems --- 84_Super_Star_Trek/rust/src/commands.rs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 25c2954d..099b5496 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -103,16 +103,25 @@ fn repair_or_damage_random_system(enterprise: &mut Enterprise) { return; } + if rng.gen::() >= 0.6 { + if enterprise.damaged.len() == 0 { + return; + } + + let damaged: Vec = enterprise.damaged.keys().map(|k| k.to_string()).collect(); + let system = damaged[rng.gen_range(0..damaged.len())].to_string(); + let system_name = &systems::name_for(&system); + + enterprise.repair_system(&system, rng.gen::() * 3.0 + 1.0); + view::random_repair_report_for(system_name, false); + 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); - } + 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) { From 2360bfd0c2dd869025a4ff46490852178f785ac7 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 19:08:21 +1300 Subject: [PATCH 39/72] implemented getting stranded --- 84_Super_Star_Trek/rust/src/main.rs | 2 +- 84_Super_Star_Trek/rust/src/model.rs | 8 ++++++++ 84_Super_Star_Trek/rust/src/view.rs | 6 ++++++ 84_Super_Star_Trek/rust/tasks.md | 5 +++-- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index fd01b9b5..385d122c 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -34,7 +34,7 @@ fn main() { _ => view::print_command_help() } - if galaxy.enterprise.destroyed { // todo: also check if stranded + if galaxy.enterprise.destroyed || galaxy.enterprise.check_stranded() { view::end_game_failure(&galaxy); // todo check if can restart break; diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index a55eb62f..f231124c 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -93,6 +93,14 @@ impl Enterprise { self.damaged.entry(system.to_string()).and_modify(|d| *d += amount); return false; } + + pub fn check_stranded(&self) -> bool { + if self.total_energy < 10 || (self.total_energy - self.shields < 10 && self.damaged.contains_key(systems::SHIELD_CONTROL)) { + view::stranded(); + return true; + } + return false; + } } pub mod systems { diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 26daf070..fc4a4735 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -251,3 +251,9 @@ pub fn long_range_scan(galaxy: &Galaxy) { println!("{:-^19}", ""); } } + +pub fn stranded() { + println!("** FATAL ERROR ** You've just stranded your ship in space +You have insufficient maneuvering energy, and shield control +is presently incapable of cross-circuiting to engine room!!") +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 8dd2d166..a2729d9b 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -14,8 +14,8 @@ Started after movement and display of stats was finished (no energy management o - [x] subsystem damage - [x] and support for reports - [x] random system damage or repairs on move -- [ ] lrs? -- [ ] stranded... +- [x] lrs? +- [x] stranded... - [ ] stop before hitting an object - when moving across a sector, the enterprise should stop before it runs into something - the current move is a jump, which makes this problematic. would need to rewrite it @@ -29,3 +29,4 @@ Started after movement and display of stats was finished (no energy management o - [ ] restarting the game - [ ] time progression - check all areas where time should move, and adjust accordingly +- [ ] intro instructions From 134b17f77e1feb2bc5d1f56452605d69fc9b5490 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 19:59:57 +1300 Subject: [PATCH 40/72] implemented computer with region map --- 84_Super_Star_Trek/rust/src/commands.rs | 31 ++++- 84_Super_Star_Trek/rust/src/main.rs | 1 + 84_Super_Star_Trek/rust/src/model.rs | 6 +- 84_Super_Star_Trek/rust/src/view.rs | 166 ++++++++++++++++++++++-- 84_Super_Star_Trek/rust/tasks.md | 9 ++ 5 files changed, 194 insertions(+), 19 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 099b5496..db3d4a32 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -14,7 +14,7 @@ pub fn perform_short_range_scan(galaxy: &Galaxy) { pub fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { if galaxy.enterprise.damaged.contains_key(model::systems::SHIELD_CONTROL) { - view::inoperable("Shield Control"); + view::inoperable(&systems::name_for(systems::SHIELD_CONTROL)); return; } @@ -204,7 +204,7 @@ fn move_klingons_and_fire(galaxy: &mut Galaxy) { pub fn display_damage_control(enterprise: &Enterprise) { if enterprise.damaged.contains_key(model::systems::DAMAGE_CONTROL) { - view::inoperable("Damage Control"); + view::inoperable(&systems::name_for(systems::DAMAGE_CONTROL)); return; } @@ -217,10 +217,33 @@ pub fn display_damage_control(enterprise: &Enterprise) { } pub fn perform_long_range_scan(galaxy: &Galaxy) { - if galaxy.enterprise.damaged.contains_key(model::systems::SHORT_RANGE_SCAN) { - view::inoperable("Long Range Scanners"); + if galaxy.enterprise.damaged.contains_key(model::systems::LONG_RANGE_SCAN) { + view::inoperable(&systems::name_for(systems::LONG_RANGE_SCAN)); return; } view::long_range_scan(galaxy); +} + +pub fn access_computer(galaxy: &Galaxy, provided: Vec) { + if galaxy.enterprise.damaged.contains_key(model::systems::COMPUTER) { + view::inoperable(&systems::name_for(systems::COMPUTER)); + return; + } + + let operation : i32; + loop { + let entered = input::param_or_prompt_value(&provided, 0, "Computer active and waiting command?", 0, 5); + if entered.is_none() { + view::computer_options(); + } else { + operation = entered.unwrap(); + break; + } + } + + match operation { + 5 => view::galaxy_region_map(), + _ => todo!() // todo implement others + } } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 385d122c..f7db0845 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -31,6 +31,7 @@ fn main() { model::systems::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), model::systems::DAMAGE_CONTROL => commands::display_damage_control(&galaxy.enterprise), model::systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&galaxy), + model::systems::COMPUTER => commands::access_computer(&galaxy, command[1..].into()), _ => view::print_command_help() } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index f231124c..549031db 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -110,9 +110,10 @@ pub mod systems { pub const SHIELD_CONTROL: &str = "SHE"; pub const DAMAGE_CONTROL: &str = "DAM"; pub const LONG_RANGE_SCAN: &str = "LRS"; + pub const COMPUTER: &str = "COM"; - pub const KEYS: [&str; 5] = [ - SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL, DAMAGE_CONTROL, LONG_RANGE_SCAN + pub const KEYS: [&str; 6] = [ + SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL, DAMAGE_CONTROL, LONG_RANGE_SCAN, COMPUTER ]; pub fn name_for(key: &str) -> String { @@ -122,6 +123,7 @@ pub mod systems { SHIELD_CONTROL => "Shield Control".into(), DAMAGE_CONTROL => "Damage Control".into(), LONG_RANGE_SCAN => "Long Range Scanners".into(), + COMPUTER => "Library-Computer".into(), _ => "Unknown".into() } } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index fc4a4735..e4fbed20 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,5 +1,114 @@ use crate::model::{Galaxy, Pos, EndPosition, SectorStatus}; +pub fn full_instructions() { + println!( +" INSTRUCTIONS FOR 'SUPER STAR TREK' + + 1. When you see \"Command ?\" printed, enter one of the legal + commands (NAV, SRS, LRS, PHA, TOR, SHE, DAM, COM, OR XXX). + 2. If you should type in an illegal command, you'll get a short + list of the legal commands printed out. + 3. Some commands require you to enter data (for example, the + 'NAV' command comes back with 'Course (1-9) ?'.) If you + type in illegal data (like negative numbers), then command + will be aborted. + + The galaxy is divided into an 8 X 8 quadrant grid, + and each quadrant is further divided into an 8 X 8 sector grid. + + You will be assigned a starting point somewhere in the + galaxy to begin a tour of duty as commander of the starship + Enterprise; your mission: to seek and destroy the fleet of + Klingon warships which are menacing the United Federation of + Planets. + + You have the following commands available to you as captain + of the starship Enterprise: + + NAV command = Warp Engine Control + Course is in a circular numerical 4 3 2 + vector arrangement as shown . . . + integer and real values may be ... + used. (Thus course 1.5 is half- 5 ---*--- 1 + way between 1 and 2. ... + . . . + Values may approach 9.0, which 6 7 8 + itself is equivalent to 1.0 + COURSE + One warp factor is the size of + one quadrant. Therefore, to get + from quadrant 6,5 to 5,5, you WOULD + use course 3, warp factor 1. + + SRS command = Short Range Sensor Scan + Shows you a scan of your present quadrant. + + Symbology on your sensor screen is as follows: + <*> = Your starship's position + +K+ = Klingon battle cruiser + >!< = Federation starbase (refuel/repair/re-arm here!) + * = Star + + A condensed 'status report' will also be presented. + + LRS command = Long Range Sensor Scan + Shows conditions in space for one quadrant on each side + of the Enterprise (which is in the middle of the scan). + The scan is coded in the form ###, where the units digit + is the number of stars, the tens digit is the number of + starbases, and the hundreds digit is the number of + Klingons. + + Example - 207 = 2 Klingons, No starbases, & 7 stars. + + PHA command = Phaser Control + Allows you to destroy the Klingon battle cruisers by + zapping them with suitably large units of energy to + deplete their shield power. (Remember, Klingons have + phasers, too!) + + TOR command = Photon Torpedo Control + Torpedo course is the same as used in warp engine control. + If you hit the Klingon vessel, he is destroyed and + cannot fire back at you. If you miss, you are subject to + his phaser fire. In either case, you are also subject to + the phaser fire of all other Klingons in the quadrant. + + The library-computer (COM command) has an option to + compute torpedo trajectory for you (Option 2). + + SHE command = Shield Control + Defines the number of energy units to be assigned to the + shields. Energy is taken from total ship's energy. Note + that the status display total energy includes shield energy. + + DAM command = Damage Control Report + Gives the state of repair of all devices. Where a negative + 'state of repair' shows that the device is temporarily + damaged. + + COM command = Library-Computer + The library-computer contains six options: + Option 0 = Cumulative Galactic Record + This option shows computer memory of the results of all + previous short and long range sensor scans. + Option 1 = Status Report + This option shows the number of Klingons, Stardates, + and starbases remaining in the game. + Option 2 = Photon Torpedo Data + Which gives directions and distance from the Enterprise + to all Klingons in your quadrant. + Option 3 = Starbase Nav Data + This option gives direction and distance to any + starbase within your quadrant. + Option 4 = Direction/Distance Calculator + This option allows you to enter coordinates for + direction/distance calculations. + Option 5 = Galactic Region Name Map + This option prints the names of the sixteen major + galactic regions referred to in the game.") +} + pub fn enterprise() { println!(" @@ -34,10 +143,11 @@ pub fn intro(model: &Galaxy) { if star_bases > 1 { star_base_message = format!("There are {} starbases", star_bases); } - println!("Your orders are as follows: + println!( +"Your orders are as follows: Destroy the {} Klingon warships which have invaded - the galaxy before they can attack federation headquarters - on stardate {}. This gives you {} days. {} in the galaxy for resupplying your ship.\n", + the galaxy before they can attack federation headquarters + on stardate {}. This gives you {} days. {} in the galaxy for resupplying your ship.\n", model.remaining_klingons(), model.final_stardate, model.final_stardate - model.stardate, star_base_message) } @@ -69,7 +179,8 @@ fn quadrant_name(quadrant: &Pos) -> String { } pub fn starting_quadrant(quadrant: &Pos) { - println!("\nYour mission begins with your starship located + println!( +"\nYour mission begins with your starship located in the galactic quadrant, '{}'.\n", quadrant_name(quadrant)) } @@ -118,7 +229,8 @@ pub fn short_range_scan(model: &Galaxy) { } pub fn print_command_help() { - println!("Enter one of the following: + println!( +"Enter one of the following: NAV (To set course) SRS (For short range sensor scan) LRS (For long range sensor scan) @@ -132,7 +244,8 @@ pub fn print_command_help() { } pub fn end_game_failure(galaxy: &Galaxy) { - println!("Is is stardate {}. + println!( +"Is is stardate {}. There were {} Klingon battle cruisers left at the end of your mission. ", galaxy.stardate, galaxy.remaining_klingons()); @@ -151,10 +264,11 @@ pub fn enterprise_hit(hit_strength: &u16, from_sector: &Pos) { } pub fn hit_edge(end: &EndPosition) { - println!("Lt. Uhura report message from Starfleet Command: - 'Permission to attempt crossing of galactic perimeter + println!( +"Lt. Uhura report message from Starfleet Command: + 'Permission to attempt crossing of galactic perimeter is hereby *Denied*. Shut down your engines.' - Chief Engineer Scott reports, 'Warp engines shut down + Chief Engineer Scott reports, 'Warp engines shut down at sector {} of quadrant {}.'", end.quadrant, end.sector); } @@ -167,7 +281,8 @@ pub fn danger_shields() { } pub fn insuffient_warp_energy(warp_speed: f32) { - println!("Engineering reports, 'Insufficient energy available + println!( +"Engineering reports, 'Insufficient energy available for maneuvering at warp {warp_speed} !'") } @@ -188,7 +303,8 @@ pub fn ridiculous() { } pub fn shields_set(value: u16) { - println!("Deflector control room report: + println!( +"Deflector control room report: 'Shields now at {value} units per your command.'") } @@ -205,7 +321,8 @@ pub fn scanners_out() { } pub fn damaged_engines(max_warp: f32, warp_factor: f32) { - println!("Warp engines are damaged. Maximum speed = warp {max_warp} + println!( +"Warp engines are damaged. Maximum speed = warp {max_warp} Chief Engineer Scott reports, 'The engines won't take warp {warp_factor} !'") } @@ -253,7 +370,30 @@ pub fn long_range_scan(galaxy: &Galaxy) { } pub fn stranded() { - println!("** FATAL ERROR ** You've just stranded your ship in space + println!( +"** FATAL ERROR ** You've just stranded your ship in space You have insufficient maneuvering energy, and shield control is presently incapable of cross-circuiting to engine room!!") } + +pub fn computer_options() { + println!( +" 0 = Cumulative galactic record + 1 = Status report + 2 = Photon torpedo data + 3 = Starbase nav data + 4 = Direction/distance calculator + 5 = Galaxy 'region name' map") +} + +pub fn galaxy_region_map() { + println!( +" The Galaxy + 1 2 3 4 5 6 7 8 + ----- ----- ----- ----- ----- ----- ----- -----"); + for i in (0..REGION_NAMES.len()-1).step_by(2) { + println!( +"{} {:^23} {:^23} + ----- ----- ----- ----- ----- ----- ----- -----", (i/2)+1, REGION_NAMES[i], REGION_NAMES[i+1]); + } +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index a2729d9b..46ba7d6a 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -26,7 +26,16 @@ Started after movement and display of stats was finished (no energy management o - [ ] weapons - [ ] phasers - [ ] torpedoes +- [ ] computer + - [ ] 0 - output of all short and long range scans (requires tracking if a system has been scanned) + - [ ] 1 - klingons, starbases, stardate and damage control + - [ ] 2 - photon torpedo data: direction and distance to all local klingons + - [ ] 3 - starbase distance and dir locally + - [ ] 4 - direction/distance calculator (useful for nav actions I guess) + - [x] 5 - galactic name map + - [ ] restarting the game - [ ] time progression - check all areas where time should move, and adjust accordingly - [ ] intro instructions +- [ ] victory From 765fa239018778d22995f185845dfe82100680c3 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 20:29:08 +1300 Subject: [PATCH 41/72] implemented scan history --- 84_Super_Star_Trek/rust/src/commands.rs | 9 +++++-- 84_Super_Star_Trek/rust/src/main.rs | 2 +- 84_Super_Star_Trek/rust/src/model.rs | 9 +++++-- 84_Super_Star_Trek/rust/src/view.rs | 34 ++++++++++++++++++++++--- 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index db3d4a32..20e694e0 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -143,6 +143,7 @@ fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { if ship.quadrant != end.quadrant { view::enter_quadrant(&end.quadrant); + galaxy.scanned.insert(end.quadrant); if galaxy.quadrants[end.quadrant.as_index()].klingons.len() > 0 { view::condition_red(); @@ -216,13 +217,16 @@ pub fn display_damage_control(enterprise: &Enterprise) { println!(); } -pub fn perform_long_range_scan(galaxy: &Galaxy) { +pub fn perform_long_range_scan(galaxy: &mut Galaxy) { if galaxy.enterprise.damaged.contains_key(model::systems::LONG_RANGE_SCAN) { view::inoperable(&systems::name_for(systems::LONG_RANGE_SCAN)); return; } - view::long_range_scan(galaxy); + let seen = view::long_range_scan(galaxy); + for pos in seen { + galaxy.scanned.insert(pos); + } } pub fn access_computer(galaxy: &Galaxy, provided: Vec) { @@ -243,6 +247,7 @@ pub fn access_computer(galaxy: &Galaxy, provided: Vec) { } match operation { + 0 => view::galaxy_scanned_map(galaxy), 5 => view::galaxy_region_map(), _ => todo!() // todo implement others } diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index f7db0845..4b809b97 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -30,7 +30,7 @@ fn main() { model::systems::WARP_ENGINES => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), model::systems::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), model::systems::DAMAGE_CONTROL => commands::display_damage_control(&galaxy.enterprise), - model::systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&galaxy), + model::systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&mut galaxy), model::systems::COMPUTER => commands::access_computer(&galaxy, command[1..].into()), _ => view::print_command_help() } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 549031db..9bb386f1 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -1,4 +1,4 @@ -use std::{ops::{Mul, Add}, fmt::Display, collections::HashMap}; +use std::{ops::{Mul, Add}, fmt::Display, collections::{HashMap, HashSet}}; use rand::Rng; @@ -8,6 +8,7 @@ pub struct Galaxy { pub stardate: f32, pub final_stardate: f32, pub quadrants: Vec, + pub scanned: HashSet, pub enterprise: Enterprise } @@ -136,7 +137,7 @@ pub struct EndPosition { pub energy_cost: u16, } -#[derive(PartialEq, Clone, Copy, Debug)] +#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq)] pub struct Pos(pub u8, pub u8); impl Pos { @@ -206,10 +207,14 @@ impl Galaxy { let enterprise_sector = quadrants[enterprise_quadrant.as_index()].find_empty_sector(); let stardate = rng.gen_range(20..=40) as f32 * 100.0; + let mut scanned = HashSet::new(); + scanned.insert(enterprise_quadrant); + Galaxy { stardate, final_stardate: stardate + rng.gen_range(25..=35) as f32, quadrants: quadrants, + scanned: scanned, enterprise: Enterprise { destroyed: false, damaged: HashMap::new(), diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index e4fbed20..fec5434c 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -174,7 +174,7 @@ const SUB_REGION_NAMES: [&str; 4] = ["I", "II", "III", "IV"]; fn quadrant_name(quadrant: &Pos) -> String { format!("{} {}", - REGION_NAMES[((quadrant.0 << 1) + (quadrant.1 >> 2)) as usize], + REGION_NAMES[((quadrant.1 << 1) + (quadrant.0 >> 2)) as usize], SUB_REGION_NAMES[(quadrant.1 % 4) as usize]) } @@ -342,11 +342,13 @@ pub fn system_repair_completed(name: String) { println!(" {name} repair completed.") } -pub fn long_range_scan(galaxy: &Galaxy) { +pub fn long_range_scan(galaxy: &Galaxy) -> Vec { let cx = galaxy.enterprise.quadrant.0 as i8; let cy = galaxy.enterprise.quadrant.1 as i8; + let mut seen = Vec::new(); + println!("Long range scan for quadrant {}", galaxy.enterprise.quadrant); println!("{:-^19}", ""); for y in cy - 1..=cy + 1 { @@ -356,7 +358,10 @@ pub fn long_range_scan(galaxy: &Galaxy) { let mut stars = "*".into(); if y >= 0 && y < 8 && x >= 0 && x < 8 { - let quadrant = &galaxy.quadrants[Pos(x as u8, y as u8).as_index()]; + let pos = Pos(x as u8, y as u8); + seen.push(pos); + + let quadrant = &galaxy.quadrants[pos.as_index()]; klingons = format!("{}", quadrant.klingons.len()); star_bases = quadrant.star_base.map_or("0", |_| "1"); stars = format!("{}", quadrant.stars.len()); @@ -367,6 +372,8 @@ pub fn long_range_scan(galaxy: &Galaxy) { println!(":"); println!("{:-^19}", ""); } + + seen } pub fn stranded() { @@ -397,3 +404,24 @@ pub fn galaxy_region_map() { ----- ----- ----- ----- ----- ----- ----- -----", (i/2)+1, REGION_NAMES[i], REGION_NAMES[i+1]); } } + +pub(crate) fn galaxy_scanned_map(galaxy: &Galaxy) { + println!( +"Computer record of galaxy for quadrant {} + 1 2 3 4 5 6 7 8 + ----- ----- ----- ----- ----- ----- ----- -----", galaxy.enterprise.quadrant); + for y in 0..8 { + print!("{} ", y+1); + for x in 0..8 { + let pos = Pos(x, y); + if galaxy.scanned.contains(&pos) { + let quadrant = &galaxy.quadrants[pos.as_index()]; + print!(" {}{}{} ", quadrant.klingons.len(), quadrant.stars.len(), quadrant.star_base.map_or("0", |_| "1")) + } else { + print!(" *** "); + } + } + println!( +"\n ----- ----- ----- ----- ----- ----- ----- -----") + } +} From 873b974473d94dfdc7941f8e5baacbd95d189ddd Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 21:34:04 +1300 Subject: [PATCH 42/72] work on phaser control everything but destruction of klingons --- 84_Super_Star_Trek/rust/src/commands.rs | 62 ++++++++++++++++++++++--- 84_Super_Star_Trek/rust/src/main.rs | 15 +++--- 84_Super_Star_Trek/rust/src/model.rs | 8 +++- 84_Super_Star_Trek/rust/src/view.rs | 14 ++++++ 84_Super_Star_Trek/rust/tasks.md | 6 ++- 5 files changed, 87 insertions(+), 18 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 20e694e0..52ca5daf 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,9 +1,9 @@ use rand::Rng; -use crate::{model::{Galaxy, Pos, COURSES, EndPosition, self, Enterprise, systems}, view, input}; +use crate::{model::{Galaxy, Pos, COURSES, EndPosition, self, Enterprise, systems}, view, input::{self, prompt_value, param_or_prompt_value}}; pub fn perform_short_range_scan(galaxy: &Galaxy) { - if galaxy.enterprise.damaged.contains_key(model::systems::SHORT_RANGE_SCAN) { + if galaxy.enterprise.damaged.contains_key(systems::SHORT_RANGE_SCAN) { view::scanners_out(); return; } @@ -13,7 +13,7 @@ pub fn perform_short_range_scan(galaxy: &Galaxy) { pub fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { - if galaxy.enterprise.damaged.contains_key(model::systems::SHIELD_CONTROL) { + if galaxy.enterprise.damaged.contains_key(systems::SHIELD_CONTROL) { view::inoperable(&systems::name_for(systems::SHIELD_CONTROL)); return; } @@ -47,7 +47,7 @@ pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec let course = course.unwrap(); let mut max_warp = 8.0; - if galaxy.enterprise.damaged.contains_key(model::systems::WARP_ENGINES) { + if galaxy.enterprise.damaged.contains_key(systems::WARP_ENGINES) { max_warp = 0.2; } @@ -204,7 +204,7 @@ fn move_klingons_and_fire(galaxy: &mut Galaxy) { } pub fn display_damage_control(enterprise: &Enterprise) { - if enterprise.damaged.contains_key(model::systems::DAMAGE_CONTROL) { + if enterprise.damaged.contains_key(systems::DAMAGE_CONTROL) { view::inoperable(&systems::name_for(systems::DAMAGE_CONTROL)); return; } @@ -218,7 +218,7 @@ pub fn display_damage_control(enterprise: &Enterprise) { } pub fn perform_long_range_scan(galaxy: &mut Galaxy) { - if galaxy.enterprise.damaged.contains_key(model::systems::LONG_RANGE_SCAN) { + if galaxy.enterprise.damaged.contains_key(systems::LONG_RANGE_SCAN) { view::inoperable(&systems::name_for(systems::LONG_RANGE_SCAN)); return; } @@ -230,7 +230,7 @@ pub fn perform_long_range_scan(galaxy: &mut Galaxy) { } pub fn access_computer(galaxy: &Galaxy, provided: Vec) { - if galaxy.enterprise.damaged.contains_key(model::systems::COMPUTER) { + if galaxy.enterprise.damaged.contains_key(systems::COMPUTER) { view::inoperable(&systems::name_for(systems::COMPUTER)); return; } @@ -251,4 +251,52 @@ pub fn access_computer(galaxy: &Galaxy, provided: Vec) { 5 => view::galaxy_region_map(), _ => todo!() // todo implement others } +} + +pub fn get_power_and_fire_phasers(galaxy: &mut Galaxy, provided: Vec) { + if galaxy.enterprise.damaged.contains_key(systems::PHASERS) { + view::inoperable(&systems::name_for(systems::PHASERS)); + return; + } + + let quadrant = &mut galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; + if quadrant.klingons.len() == 0 { + view::no_local_enemies(); + return; + } + + let computer_damaged = galaxy.enterprise.damaged.contains_key(systems::COMPUTER); + if computer_damaged { + view::computer_accuracy_issue(); + } + + let available_energy = galaxy.enterprise.total_energy - galaxy.enterprise.shields; + view::phasers_locked(available_energy); + let mut power: f32; + loop { + let setting = param_or_prompt_value(&provided, 0, "Number of units to fire", 0, available_energy); + if setting.is_some() { + power = setting.unwrap() as f32; + break; + } + } + + if power == 0.0 { + return; + } + + galaxy.enterprise.total_energy -= power as u16; + + let mut rng = rand::thread_rng(); + if computer_damaged { + power *= rng.gen::(); + } + + let per_enemy = power / quadrant.klingons.len() as f32; + + // fire on each klingon + + for klingon in &mut quadrant.klingons { + klingon.fire_on(&mut galaxy.enterprise) + } } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 4b809b97..1bd1d652 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,6 +1,6 @@ use std::process::exit; -use model::Galaxy; +use model::{Galaxy, systems}; mod input; mod model; @@ -26,12 +26,13 @@ fn main() { continue; } match command[0].to_uppercase().as_str() { // order is weird because i built it in this order :) - model::systems::SHORT_RANGE_SCAN => commands::perform_short_range_scan(&galaxy), - model::systems::WARP_ENGINES => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), - model::systems::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), - model::systems::DAMAGE_CONTROL => commands::display_damage_control(&galaxy.enterprise), - model::systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&mut galaxy), - model::systems::COMPUTER => commands::access_computer(&galaxy, command[1..].into()), + systems::SHORT_RANGE_SCAN => commands::perform_short_range_scan(&galaxy), + systems::WARP_ENGINES => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), + systems::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), + systems::DAMAGE_CONTROL => commands::display_damage_control(&galaxy.enterprise), + systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&mut galaxy), + systems::COMPUTER => commands::access_computer(&galaxy, command[1..].into()), + systems::PHASERS => commands::get_power_and_fire_phasers(&mut galaxy, command[1..].into()), _ => view::print_command_help() } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 9bb386f1..dbd23522 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -25,6 +25,8 @@ pub struct Klingon { impl Klingon { pub fn fire_on(&mut self, enterprise: &mut Enterprise) { + // todo check if enterprise is protected + let mut rng = rand::thread_rng(); let attack_strength = rng.gen::(); let dist_to_enterprise = self.sector.abs_diff(enterprise.sector) as f32; @@ -112,9 +114,10 @@ pub mod systems { pub const DAMAGE_CONTROL: &str = "DAM"; pub const LONG_RANGE_SCAN: &str = "LRS"; pub const COMPUTER: &str = "COM"; + pub const PHASERS: &str = "PHA"; - pub const KEYS: [&str; 6] = [ - SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL, DAMAGE_CONTROL, LONG_RANGE_SCAN, COMPUTER + pub const KEYS: [&str; 7] = [ + SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL, DAMAGE_CONTROL, LONG_RANGE_SCAN, COMPUTER, PHASERS ]; pub fn name_for(key: &str) -> String { @@ -125,6 +128,7 @@ pub mod systems { DAMAGE_CONTROL => "Damage Control".into(), LONG_RANGE_SCAN => "Long Range Scanners".into(), COMPUTER => "Library-Computer".into(), + PHASERS => "Phaser Control".into(), _ => "Unknown".into() } } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index fec5434c..1c904958 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -425,3 +425,17 @@ pub(crate) fn galaxy_scanned_map(galaxy: &Galaxy) { "\n ----- ----- ----- ----- ----- ----- ----- -----") } } + +pub fn no_local_enemies() { + println!( +"Science Officer Spock reports, 'Sensors show no enemy ships + in this quadrant'") +} + +pub fn computer_accuracy_issue() { + println!("Computer failure hampers accuracy") +} + +pub fn phasers_locked(available_energy: u16) { + println!("Phasers locked on target; Energy available = {available_energy} units") +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 46ba7d6a..8f5b3bab 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -22,12 +22,14 @@ Started after movement and display of stats was finished (no energy management o - also, movement courses could be floats, according to the instructions, allowing for more precise movement and aiming - [x] better command reading - support entering multiple values on a line (e.g. nav 3 0.1) - [ ] starbases - - [ ] repair + - [ ] proximity detection for docking + - [ ] repair on damage control + - [ ] protection from shots - [ ] weapons - [ ] phasers - [ ] torpedoes - [ ] computer - - [ ] 0 - output of all short and long range scans (requires tracking if a system has been scanned) + - [x] 0 - output of all short and long range scans (requires tracking if a system has been scanned) - [ ] 1 - klingons, starbases, stardate and damage control - [ ] 2 - photon torpedo data: direction and distance to all local klingons - [ ] 3 - starbase distance and dir locally From 5973d97a16ed00a94e786a8e79557ed6125c6065 Mon Sep 17 00:00:00 2001 From: Christopher Date: Thu, 2 Mar 2023 21:35:45 +1300 Subject: [PATCH 43/72] some more reorg --- 84_Super_Star_Trek/rust/src/commands.rs | 7 +------ 84_Super_Star_Trek/rust/src/view.rs | 11 ++++++++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 52ca5daf..911f88f5 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -209,12 +209,7 @@ pub fn display_damage_control(enterprise: &Enterprise) { return; } - println!("Device State of Repair"); - for key in systems::KEYS { - let damage = enterprise.damaged.get(key).unwrap_or(&0.0); - println!("{:<25}{}", systems::name_for(key), damage) - } - println!(); + view::damage_control(enterprise); } pub fn perform_long_range_scan(galaxy: &mut Galaxy) { diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 1c904958..290fa37b 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,4 +1,4 @@ -use crate::model::{Galaxy, Pos, EndPosition, SectorStatus}; +use crate::model::{Galaxy, Pos, EndPosition, SectorStatus, Enterprise, systems}; pub fn full_instructions() { println!( @@ -342,6 +342,15 @@ pub fn system_repair_completed(name: String) { println!(" {name} repair completed.") } +pub fn damage_control(enterprise: &Enterprise) { + println!("Device State of Repair"); + for key in systems::KEYS { + let damage = enterprise.damaged.get(key).unwrap_or(&0.0); + println!("{:<25}{}", systems::name_for(key), damage) + } + println!(); +} + pub fn long_range_scan(galaxy: &Galaxy) -> Vec { let cx = galaxy.enterprise.quadrant.0 as i8; From 21ccbc0f9b8a7510300c054c62bc819cfa25833b Mon Sep 17 00:00:00 2001 From: Christopher Date: Fri, 3 Mar 2023 07:14:25 +1300 Subject: [PATCH 44/72] work on starbases --- 84_Super_Star_Trek/rust/src/commands.rs | 54 ++++++++++++++++++------- 84_Super_Star_Trek/rust/src/main.rs | 2 +- 84_Super_Star_Trek/rust/src/model.rs | 15 ++++--- 84_Super_Star_Trek/rust/src/view.rs | 9 ++++- 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 911f88f5..255ced43 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,6 +1,6 @@ use rand::Rng; -use crate::{model::{Galaxy, Pos, COURSES, EndPosition, self, Enterprise, systems}, view, input::{self, prompt_value, param_or_prompt_value}}; +use crate::{model::*, view, input::{self, param_or_prompt_value}}; pub fn perform_short_range_scan(galaxy: &Galaxy) { if galaxy.enterprise.damaged.contains_key(systems::SHORT_RANGE_SCAN) { @@ -64,7 +64,9 @@ pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec return; } - move_klingons_and_fire(galaxy); + klingons_move(galaxy); + klingons_fire(galaxy); + if galaxy.enterprise.destroyed { return; } @@ -156,10 +158,17 @@ fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { ship.quadrant = end.quadrant; ship.sector = end.sector; - ship.total_energy = (ship.total_energy - end.energy_cost).max(0); - if ship.shields > ship.total_energy { - view::divert_energy_from_shields(); - ship.shields = ship.total_energy; + let quadrant = &galaxy.quadrants[end.quadrant.as_index()]; + if quadrant.docked_at_starbase(ship.sector) { + ship.shields = 0; + ship.photon_torpedoes = MAX_PHOTON_TORPEDOES; + ship.total_energy = MAX_ENERGY; + } else { + ship.total_energy = (ship.total_energy - end.energy_cost).max(0); + if ship.shields > ship.total_energy { + view::divert_energy_from_shields(); + ship.shields = ship.total_energy; + } } view::short_range_scan(&galaxy) @@ -189,27 +198,46 @@ fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, EndPosition { quadrant, sector, hit_edge, energy_cost } } -fn move_klingons_and_fire(galaxy: &mut Galaxy) { +fn klingons_move(galaxy: &mut Galaxy) { let quadrant = &mut galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; for k in 0..quadrant.klingons.len() { let new_sector = quadrant.find_empty_sector(); quadrant.klingons[k].sector = new_sector; } +} - // todo: check if enterprise is protected by a starbase +fn klingons_fire(galaxy: &mut Galaxy) { + let quadrant = &mut galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; + if quadrant.docked_at_starbase(galaxy.enterprise.sector) { + view::starbase_shields(); + return; + } for k in 0..quadrant.klingons.len() { quadrant.klingons[k].fire_on(&mut galaxy.enterprise); } } -pub fn display_damage_control(enterprise: &Enterprise) { - if enterprise.damaged.contains_key(systems::DAMAGE_CONTROL) { +pub fn run_damage_control(galaxy: &mut Galaxy) { + + let ship = &mut galaxy.enterprise; + + if ship.damaged.contains_key(systems::DAMAGE_CONTROL) { view::inoperable(&systems::name_for(systems::DAMAGE_CONTROL)); return; } - view::damage_control(enterprise); + view::damage_control(&ship); + + if ship.damaged.len() == 0 || !galaxy.quadrants[ship.quadrant.as_index()].docked_at_starbase(ship.sector) { + return; + } + + // try repeair + // if so write dam report + // and increment elapsed time + + view::damage_control(&ship); } pub fn perform_long_range_scan(galaxy: &mut Galaxy) { @@ -291,7 +319,5 @@ pub fn get_power_and_fire_phasers(galaxy: &mut Galaxy, provided: Vec) { // fire on each klingon - for klingon in &mut quadrant.klingons { - klingon.fire_on(&mut galaxy.enterprise) - } + klingons_fire(galaxy); } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 1bd1d652..589e43e0 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -29,7 +29,7 @@ fn main() { systems::SHORT_RANGE_SCAN => commands::perform_short_range_scan(&galaxy), systems::WARP_ENGINES => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), systems::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), - systems::DAMAGE_CONTROL => commands::display_damage_control(&galaxy.enterprise), + systems::DAMAGE_CONTROL => commands::run_damage_control(&mut galaxy), systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&mut galaxy), systems::COMPUTER => commands::access_computer(&galaxy, command[1..].into()), systems::PHASERS => commands::get_power_and_fire_phasers(&mut galaxy, command[1..].into()), diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index dbd23522..31fb3191 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -25,8 +25,6 @@ pub struct Klingon { impl Klingon { pub fn fire_on(&mut self, enterprise: &mut Enterprise) { - // todo check if enterprise is protected - let mut rng = rand::thread_rng(); let attack_strength = rng.gen::(); let dist_to_enterprise = self.sector.abs_diff(enterprise.sector) as f32; @@ -149,7 +147,7 @@ impl Pos { (self.0 * 8 + self.1).into() } - fn abs_diff(&self, other: Pos) -> u8 { + pub fn abs_diff(&self, other: Pos) -> u8 { self.0.abs_diff(other.0) + self.1.abs_diff(other.1) } } @@ -192,6 +190,9 @@ pub enum SectorStatus { Empty, Star, StarBase, Klingon } +pub const MAX_PHOTON_TORPEDOES: u8 = 28; +pub const MAX_ENERGY: u16 = 3000; + impl Galaxy { pub fn remaining_klingons(&self) -> u8 { let quadrants = &self.quadrants; @@ -224,8 +225,8 @@ impl Galaxy { damaged: HashMap::new(), quadrant: enterprise_quadrant, sector: enterprise_sector, - photon_torpedoes: 28, - total_energy: 3000, + photon_torpedoes: MAX_PHOTON_TORPEDOES, + total_energy: MAX_ENERGY, shields: 0 } } } @@ -296,4 +297,8 @@ impl Quadrant { } } } + + pub fn docked_at_starbase(&self, enterprise_sector: Pos) -> bool { + self.star_base.is_some() && self.star_base.unwrap().abs_diff(enterprise_sector) == 1 + } } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 290fa37b..c7cc836d 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -191,7 +191,10 @@ pub fn enter_quadrant(quadrant: &Pos) { pub fn short_range_scan(model: &Galaxy) { let quadrant = &model.quadrants[model.enterprise.quadrant.as_index()]; let mut condition = "GREEN"; - if quadrant.klingons.len() > 0 { + if quadrant.docked_at_starbase(model.enterprise.sector) { + println!("Shields dropped for docking purposes"); + condition = "DOCKED"; + } else if quadrant.klingons.len() > 0 { condition = "*RED*"; } else if model.enterprise.damaged.len() > 0 { condition = "YELLOW"; @@ -448,3 +451,7 @@ pub fn computer_accuracy_issue() { pub fn phasers_locked(available_energy: u16) { println!("Phasers locked on target; Energy available = {available_energy} units") } + +pub fn starbase_shields() { + println!("Starbase shields protect the Enterprise") +} From 5b58b37ad1f1caf95dfcfd6f236f945069a50244 Mon Sep 17 00:00:00 2001 From: Christopher Date: Fri, 3 Mar 2023 07:59:12 +1300 Subject: [PATCH 45/72] finished implementing starbases --- 84_Super_Star_Trek/rust/src/commands.rs | 15 +++++++++++---- 84_Super_Star_Trek/rust/src/input.rs | 16 ++++++++++++++++ 84_Super_Star_Trek/rust/src/model.rs | 21 +++++++++++++-------- 84_Super_Star_Trek/rust/src/view.rs | 12 +++++++++--- 84_Super_Star_Trek/rust/tasks.md | 8 ++++---- 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 255ced43..60dcb9b9 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -229,14 +229,21 @@ pub fn run_damage_control(galaxy: &mut Galaxy) { view::damage_control(&ship); - if ship.damaged.len() == 0 || !galaxy.quadrants[ship.quadrant.as_index()].docked_at_starbase(ship.sector) { + let quadrant = &galaxy.quadrants[ship.quadrant.as_index()]; + if ship.damaged.len() == 0 || !quadrant.docked_at_starbase(ship.sector) { return; } - // try repeair - // if so write dam report - // and increment elapsed time + let repair_delay = quadrant.star_base.as_ref().unwrap().repair_delay; + let repair_time = (ship.damaged.len() as f32 * 0.1 + repair_delay).max(0.9); + view::repair_estimate(repair_time); + if !input::prompt_yes_no("Will you authorize the repair order") { + return; + } + + ship.damaged.clear(); + galaxy.stardate += repair_time; view::damage_control(&ship); } diff --git a/84_Super_Star_Trek/rust/src/input.rs b/84_Super_Star_Trek/rust/src/input.rs index 75f12102..5bd35fb3 100644 --- a/84_Super_Star_Trek/rust/src/input.rs +++ b/84_Super_Star_Trek/rust/src/input.rs @@ -14,6 +14,22 @@ pub fn prompt(prompt_text: &str) -> Vec { Vec::new() } +pub fn prompt_yes_no(prompt_text: &str) -> bool { + loop { + let response = prompt(&format!("{prompt_text} (Y/N)")); + if response.len() == 0 { + continue; + } + let first_word = response[0].to_uppercase(); + if first_word.starts_with("Y") { + return true; + } + if first_word.starts_with("N") { + return false; + } + } +} + pub fn prompt_value(prompt_text: &str, min: T, max: T) -> Option { let passed = prompt(prompt_text); if passed.len() != 1 { diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 31fb3191..a12673af 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -14,10 +14,15 @@ pub struct Galaxy { pub struct Quadrant { pub stars: Vec, - pub star_base: Option, + pub star_base: Option, pub klingons: Vec } +pub struct StarBase { + pub sector: Pos, + pub repair_delay: f32, +} + pub struct Klingon { pub sector: Pos, energy: f32 @@ -243,7 +248,7 @@ impl Galaxy { } if rng.gen::() > 0.96 { - quadrant.star_base = Some(quadrant.find_empty_sector()); + quadrant.star_base = Some(StarBase { sector: quadrant.find_empty_sector(), repair_delay: rng.gen::() * 0.5 }); } let klingon_count = @@ -264,10 +269,10 @@ impl Galaxy { } impl Quadrant { - pub fn sector_status(&self, sector: &Pos) -> SectorStatus { + pub fn sector_status(&self, sector: Pos) -> SectorStatus { if self.stars.contains(§or) { SectorStatus::Star - } else if self.is_starbase(§or) { + } else if self.is_starbase(sector) { SectorStatus::StarBase } else if self.has_klingon(§or) { SectorStatus::Klingon @@ -276,10 +281,10 @@ impl Quadrant { } } - fn is_starbase(&self, sector: &Pos) -> bool { + fn is_starbase(&self, sector: Pos) -> bool { match &self.star_base { None => false, - Some(p) => p == sector + Some(p) => p.sector == sector } } @@ -292,13 +297,13 @@ impl Quadrant { let mut rng = rand::thread_rng(); loop { let pos = Pos(rng.gen_range(0..8), rng.gen_range(0..8)); - if self.sector_status(&pos) == SectorStatus::Empty { + if self.sector_status(pos) == SectorStatus::Empty { return pos } } } pub fn docked_at_starbase(&self, enterprise_sector: Pos) -> bool { - self.star_base.is_some() && self.star_base.unwrap().abs_diff(enterprise_sector) == 1 + self.star_base.is_some() && self.star_base.as_ref().unwrap().sector.abs_diff(enterprise_sector) == 1 } } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index c7cc836d..77b70057 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -218,7 +218,7 @@ pub fn short_range_scan(model: &Galaxy) { if &pos == &model.enterprise.sector { print!("<*> ") } else { - match quadrant.sector_status(&pos) { + match quadrant.sector_status(pos) { SectorStatus::Star => print!(" * "), SectorStatus::StarBase => print!(">!< "), SectorStatus::Klingon => print!("+K+ "), @@ -375,7 +375,7 @@ pub fn long_range_scan(galaxy: &Galaxy) -> Vec { let quadrant = &galaxy.quadrants[pos.as_index()]; klingons = format!("{}", quadrant.klingons.len()); - star_bases = quadrant.star_base.map_or("0", |_| "1"); + star_bases = quadrant.star_base.as_ref().map_or("0", |_| "1"); stars = format!("{}", quadrant.stars.len()); } @@ -428,7 +428,7 @@ pub(crate) fn galaxy_scanned_map(galaxy: &Galaxy) { let pos = Pos(x, y); if galaxy.scanned.contains(&pos) { let quadrant = &galaxy.quadrants[pos.as_index()]; - print!(" {}{}{} ", quadrant.klingons.len(), quadrant.stars.len(), quadrant.star_base.map_or("0", |_| "1")) + print!(" {}{}{} ", quadrant.klingons.len(), quadrant.stars.len(), quadrant.star_base.as_ref().map_or("0", |_| "1")) } else { print!(" *** "); } @@ -455,3 +455,9 @@ pub fn phasers_locked(available_energy: u16) { pub fn starbase_shields() { println!("Starbase shields protect the Enterprise") } + +pub fn repair_estimate(repair_time: f32) { + println!( +"Technicians standing by to effect repairs to your ship; +Estimated time to repair: {repair_time} stardates.") +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 8f5b3bab..bdd44481 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -21,10 +21,10 @@ Started after movement and display of stats was finished (no energy management o - the current move is a jump, which makes this problematic. would need to rewrite it - also, movement courses could be floats, according to the instructions, allowing for more precise movement and aiming - [x] better command reading - support entering multiple values on a line (e.g. nav 3 0.1) -- [ ] starbases - - [ ] proximity detection for docking - - [ ] repair on damage control - - [ ] protection from shots +- [x] starbases + - [x] proximity detection for docking + - [x] repair on damage control + - [x] protection from shots - [ ] weapons - [ ] phasers - [ ] torpedoes From 188b17d1523db62761716dd8cddbd97bd62ca0d2 Mon Sep 17 00:00:00 2001 From: Christopher Date: Fri, 3 Mar 2023 08:04:32 +1300 Subject: [PATCH 46/72] small fix so klingons can't move on top of enterprise --- 84_Super_Star_Trek/rust/src/commands.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 60dcb9b9..3cc68cbc 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -201,7 +201,14 @@ fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, fn klingons_move(galaxy: &mut Galaxy) { let quadrant = &mut galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; for k in 0..quadrant.klingons.len() { - let new_sector = quadrant.find_empty_sector(); + let new_sector: Pos; + loop { + let candidate = quadrant.find_empty_sector(); + if candidate != galaxy.enterprise.sector { + new_sector = candidate; + break; + } + } quadrant.klingons[k].sector = new_sector; } } From a8c55988ade850b8294782d0603007f58752d016 Mon Sep 17 00:00:00 2001 From: Christopher Date: Fri, 3 Mar 2023 14:49:06 +1300 Subject: [PATCH 47/72] phasers! completed this --- 84_Super_Star_Trek/rust/src/commands.rs | 18 +++++++++++++++++- 84_Super_Star_Trek/rust/src/model.rs | 2 +- 84_Super_Star_Trek/rust/src/view.rs | 16 ++++++++++++++++ 84_Super_Star_Trek/rust/tasks.md | 2 +- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 3cc68cbc..6b2d4b08 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -331,7 +331,23 @@ pub fn get_power_and_fire_phasers(galaxy: &mut Galaxy, provided: Vec) { let per_enemy = power / quadrant.klingons.len() as f32; - // fire on each klingon + for k in &mut quadrant.klingons { + let dist = k.sector.abs_diff(galaxy.enterprise.sector) as f32; + let hit_strength = per_enemy / dist * (2.0 + rng.gen::()); + if hit_strength < 0.15 * k.energy { + view::no_damage(k.sector); + } else { + k.energy -= hit_strength; + view::hit_on_klingon(hit_strength, k.sector); + if k.energy > 0.0 { + view::klingon_remaining_energy(k.energy); + } else { + view::klingon_destroyed(); + } + } + } + + quadrant.klingons.retain(|k| k.energy > 0.0); klingons_fire(galaxy); } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index a12673af..151b85d3 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -25,7 +25,7 @@ pub struct StarBase { pub struct Klingon { pub sector: Pos, - energy: f32 + pub energy: f32 } impl Klingon { diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 77b70057..5372cc6b 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -461,3 +461,19 @@ pub fn repair_estimate(repair_time: f32) { "Technicians standing by to effect repairs to your ship; Estimated time to repair: {repair_time} stardates.") } + +pub fn no_damage(sector: Pos) { + println!("Sensors show no damage to enemy at {sector}") +} + +pub fn hit_on_klingon(hit_strength: f32, sector: Pos) { + println!("{hit_strength} unit hit on Klingon at sector {sector}") +} + +pub fn klingon_remaining_energy(energy: f32) { + println!(" (sensors show {energy} units remaining)") +} + +pub fn klingon_destroyed() { + println!(" Target Destroyed!") // not standard for game but feedback is good. Sorry Mr. Roddenberry +} diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index bdd44481..06bcf57a 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -26,7 +26,7 @@ Started after movement and display of stats was finished (no energy management o - [x] repair on damage control - [x] protection from shots - [ ] weapons - - [ ] phasers + - [x] phasers - [ ] torpedoes - [ ] computer - [x] 0 - output of all short and long range scans (requires tracking if a system has been scanned) From f7afb36cc7f67b651b34ba7f05b3f4dfdb399884 Mon Sep 17 00:00:00 2001 From: Christopher Date: Fri, 3 Mar 2023 16:16:01 +1300 Subject: [PATCH 48/72] work on victory and retry conditions --- 84_Super_Star_Trek/rust/src/main.rs | 20 +++++++++++++---- 84_Super_Star_Trek/rust/src/model.rs | 33 +++++++++++++++++----------- 84_Super_Star_Trek/rust/src/view.rs | 19 +++++++++++++++- 84_Super_Star_Trek/rust/tasks.md | 3 +++ 4 files changed, 57 insertions(+), 18 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 589e43e0..2afded1c 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,5 +1,6 @@ use std::process::exit; +use input::prompt; use model::{Galaxy, systems}; mod input; @@ -12,6 +13,8 @@ fn main() { .expect("Error setting Ctrl-C handler"); let mut galaxy = Galaxy::generate_new(); + let initial_klingons = galaxy.remaining_klingons(); + let initial_stardate = galaxy.stardate; view::enterprise(); view::intro(&galaxy); @@ -36,12 +39,21 @@ fn main() { _ => view::print_command_help() } - if galaxy.enterprise.destroyed || galaxy.enterprise.check_stranded() { + if galaxy.enterprise.destroyed || galaxy.enterprise.check_stranded() || galaxy.stardate >= galaxy.final_stardate { view::end_game_failure(&galaxy); - // todo check if can restart + if galaxy.remaining_klingons() > 0 && galaxy.remaining_starbases() > 0 && galaxy.stardate < galaxy.final_stardate { + view::replay(); + let result = prompt(""); + if result.len() > 0 && result[0].to_uppercase() == "AYE" { + galaxy.enterprise = Galaxy::new_captain(&galaxy.quadrants); + continue; + } + } + break; + } else if galaxy.remaining_klingons() == 0 { + let efficiency = 1000.0 * f32::powi(initial_klingons as f32 / (galaxy.stardate - initial_stardate), 2); + view::congratulations(efficiency); break; } - - // todo check for victory } } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 151b85d3..2985f28a 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -101,7 +101,7 @@ impl Enterprise { } pub fn check_stranded(&self) -> bool { - if self.total_energy < 10 || (self.total_energy - self.shields < 10 && self.damaged.contains_key(systems::SHIELD_CONTROL)) { + if self.total_energy < 10 || (self.shields + 10 > self.total_energy && self.damaged.contains_key(systems::SHIELD_CONTROL)) { view::stranded(); return true; } @@ -213,28 +213,35 @@ impl Galaxy { let quadrants = Self::generate_quadrants(); let mut rng = rand::thread_rng(); - let enterprise_quadrant = Pos(rng.gen_range(0..8), rng.gen_range(0..8)); - let enterprise_sector = quadrants[enterprise_quadrant.as_index()].find_empty_sector(); let stardate = rng.gen_range(20..=40) as f32 * 100.0; + let enterprise = Self::new_captain(&quadrants); + let mut scanned = HashSet::new(); - scanned.insert(enterprise_quadrant); + scanned.insert(enterprise.quadrant); Galaxy { stardate, final_stardate: stardate + rng.gen_range(25..=35) as f32, quadrants: quadrants, scanned: scanned, - enterprise: Enterprise { - destroyed: false, - damaged: HashMap::new(), - quadrant: enterprise_quadrant, - sector: enterprise_sector, - photon_torpedoes: MAX_PHOTON_TORPEDOES, - total_energy: MAX_ENERGY, - shields: 0 } + enterprise: enterprise } - } + } + + pub fn new_captain(quadrants: &Vec) -> Enterprise { + let mut rng = rand::thread_rng(); + let enterprise_quadrant = Pos(rng.gen_range(0..8), rng.gen_range(0..8)); + let enterprise_sector = quadrants[enterprise_quadrant.as_index()].find_empty_sector(); + Enterprise { + destroyed: false, + damaged: HashMap::new(), + quadrant: enterprise_quadrant, + sector: enterprise_sector, + photon_torpedoes: MAX_PHOTON_TORPEDOES, + total_energy: MAX_ENERGY, + shields: 0 } + } fn generate_quadrants() -> Vec { let mut rng = rand::thread_rng(); diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 5372cc6b..f54bd4cc 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -417,7 +417,7 @@ pub fn galaxy_region_map() { } } -pub(crate) fn galaxy_scanned_map(galaxy: &Galaxy) { +pub fn galaxy_scanned_map(galaxy: &Galaxy) { println!( "Computer record of galaxy for quadrant {} 1 2 3 4 5 6 7 8 @@ -477,3 +477,20 @@ pub fn klingon_remaining_energy(energy: f32) { pub fn klingon_destroyed() { println!(" Target Destroyed!") // not standard for game but feedback is good. Sorry Mr. Roddenberry } + +pub fn congratulations(efficiency: f32) { + println!(" +Congratulations, Captain! The last Klingon battle cruiser +menacing the Federation has been destroyed. + +Your efficiency rating is {efficiency}. + ") +} + +pub fn replay() { + println!(" + +The Federation is in need of a new starship commander +for a similar mission -- if there is a volunteer +let him step forward and enter 'Aye'") +} \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 06bcf57a..5dc79803 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -37,7 +37,10 @@ Started after movement and display of stats was finished (no energy management o - [x] 5 - galactic name map - [ ] restarting the game + - after defeat + - and by resigning - [ ] time progression - check all areas where time should move, and adjust accordingly + - [ ] defeat due to time expired - [ ] intro instructions - [ ] victory From 7008127806f5ae4d52290ecc0a044fa57445c5fb Mon Sep 17 00:00:00 2001 From: Christopher Date: Fri, 3 Mar 2023 16:17:09 +1300 Subject: [PATCH 49/72] made it so you can still repair at starbases with a broken damage control --- 84_Super_Star_Trek/rust/src/commands.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 6b2d4b08..c878ae26 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -231,11 +231,10 @@ pub fn run_damage_control(galaxy: &mut Galaxy) { if ship.damaged.contains_key(systems::DAMAGE_CONTROL) { view::inoperable(&systems::name_for(systems::DAMAGE_CONTROL)); - return; + } else { + view::damage_control(&ship); } - view::damage_control(&ship); - let quadrant = &galaxy.quadrants[ship.quadrant.as_index()]; if ship.damaged.len() == 0 || !quadrant.docked_at_starbase(ship.sector) { return; From 51cfce4fb8dfc965eb52058bd05b3e92cfdbdf2c Mon Sep 17 00:00:00 2001 From: Christopher Date: Sat, 4 Mar 2023 09:07:51 +1300 Subject: [PATCH 50/72] minor tweak to fix another underflow issue --- 84_Super_Star_Trek/rust/src/main.rs | 2 +- 84_Super_Star_Trek/rust/src/model.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 2afded1c..5c9e1058 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -39,7 +39,7 @@ fn main() { _ => view::print_command_help() } - if galaxy.enterprise.destroyed || galaxy.enterprise.check_stranded() || galaxy.stardate >= galaxy.final_stardate { + if galaxy.enterprise.destroyed || galaxy.enterprise.is_stranded() || galaxy.stardate >= galaxy.final_stardate { view::end_game_failure(&galaxy); if galaxy.remaining_klingons() > 0 && galaxy.remaining_starbases() > 0 && galaxy.stardate < galaxy.final_stardate { view::replay(); diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 2985f28a..144a7e93 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -58,13 +58,13 @@ impl Enterprise { view::enterprise_hit(&hit_strength, §or); - self.shields = (self.shields - hit_strength).max(0); - - if self.shields <= 0 { + if self.shields <= hit_strength { view::enterprise_destroyed(); self.destroyed = true } + self.shields -= hit_strength; + view::shields_hit(self.shields); if hit_strength >= 20 { @@ -100,7 +100,7 @@ impl Enterprise { return false; } - pub fn check_stranded(&self) -> bool { + pub fn is_stranded(&self) -> bool { if self.total_energy < 10 || (self.shields + 10 > self.total_energy && self.damaged.contains_key(systems::SHIELD_CONTROL)) { view::stranded(); return true; From 32c1508a5138dba883cb6b09cea42734abc02664 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sat, 4 Mar 2023 09:10:43 +1300 Subject: [PATCH 51/72] can now resign --- 84_Super_Star_Trek/rust/src/main.rs | 1 + 84_Super_Star_Trek/rust/src/view.rs | 1 - 84_Super_Star_Trek/rust/tasks.md | 10 +++++----- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 5c9e1058..a7f11d2a 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -36,6 +36,7 @@ fn main() { systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&mut galaxy), systems::COMPUTER => commands::access_computer(&galaxy, command[1..].into()), systems::PHASERS => commands::get_power_and_fire_phasers(&mut galaxy, command[1..].into()), + "XXX" => galaxy.enterprise.destroyed = true, _ => view::print_command_help() } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index f54bd4cc..73ec39d7 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -489,7 +489,6 @@ Your efficiency rating is {efficiency}. pub fn replay() { println!(" - The Federation is in need of a new starship commander for a similar mission -- if there is a volunteer let him step forward and enter 'Aye'") diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 5dc79803..7a663304 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -36,11 +36,11 @@ Started after movement and display of stats was finished (no energy management o - [ ] 4 - direction/distance calculator (useful for nav actions I guess) - [x] 5 - galactic name map -- [ ] restarting the game - - after defeat - - and by resigning +- [x] restarting the game + - [x] after defeat + - [x] and by resigning - [ ] time progression - check all areas where time should move, and adjust accordingly - - [ ] defeat due to time expired + - [x] defeat due to time expired - [ ] intro instructions -- [ ] victory +- [x] victory From 7fb940f18ec7d97f394f2d22668c1e41f7537cbd Mon Sep 17 00:00:00 2001 From: Christopher Date: Sat, 4 Mar 2023 09:26:24 +1300 Subject: [PATCH 52/72] started work on photon torpedoes (final system) also moved all prompt text into views submodule --- 84_Super_Star_Trek/rust/src/commands.rs | 24 ++++++++++++++++++------ 84_Super_Star_Trek/rust/src/main.rs | 7 ++++--- 84_Super_Star_Trek/rust/src/model.rs | 8 ++++++-- 84_Super_Star_Trek/rust/src/view.rs | 18 ++++++++++++++++++ 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index c878ae26..98b9e0d8 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -19,7 +19,7 @@ pub fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { } view::energy_available(galaxy.enterprise.total_energy); - let value = input::param_or_prompt_value(&provided, 0, "Number of units to shields", 0, i32::MAX); + let value = input::param_or_prompt_value(&provided, 0, view::prompts::SHIELDS, 0, i32::MAX); if value.is_none() { view::shields_unchanged(); return; @@ -38,7 +38,7 @@ pub fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec) { - let course = input::param_or_prompt_value(&provided, 0, "Course (1-9)?", 1, 9); + let course = input::param_or_prompt_value(&provided, 0, view::prompts::COURSE, 1, 9); if course.is_none() { view::bad_nav(); return; @@ -51,7 +51,7 @@ pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec max_warp = 0.2; } - let speed = input::param_or_prompt_value(&provided, 1, format!("Warp Factor (0-{})?", max_warp).as_str(), 0.0, 8.0); + let speed = input::param_or_prompt_value(&provided, 1, &view::prompts::warp_factor(max_warp), 0.0, 8.0); if speed.is_none() { view::bad_nav(); return; @@ -244,7 +244,7 @@ pub fn run_damage_control(galaxy: &mut Galaxy) { let repair_time = (ship.damaged.len() as f32 * 0.1 + repair_delay).max(0.9); view::repair_estimate(repair_time); - if !input::prompt_yes_no("Will you authorize the repair order") { + if !input::prompt_yes_no(view::prompts::REPAIR) { return; } @@ -273,7 +273,7 @@ pub fn access_computer(galaxy: &Galaxy, provided: Vec) { let operation : i32; loop { - let entered = input::param_or_prompt_value(&provided, 0, "Computer active and waiting command?", 0, 5); + let entered = input::param_or_prompt_value(&provided, 0, view::prompts::COMPUTER, 0, 5); if entered.is_none() { view::computer_options(); } else { @@ -310,7 +310,7 @@ pub fn get_power_and_fire_phasers(galaxy: &mut Galaxy, provided: Vec) { view::phasers_locked(available_energy); let mut power: f32; loop { - let setting = param_or_prompt_value(&provided, 0, "Number of units to fire", 0, available_energy); + let setting = param_or_prompt_value(&provided, 0, view::prompts::PHASERS, 0, available_energy); if setting.is_some() { power = setting.unwrap() as f32; break; @@ -349,4 +349,16 @@ pub fn get_power_and_fire_phasers(galaxy: &mut Galaxy, provided: Vec) { quadrant.klingons.retain(|k| k.energy > 0.0); klingons_fire(galaxy); +} + +pub fn gather_dir_and_launch_torpedo(galaxy: &mut Galaxy, provided: Vec) { + if galaxy.enterprise.damaged.contains_key(systems::TORPEDOES) { + view::inoperable(&systems::name_for(systems::TORPEDOES)); + return; + } + + if galaxy.enterprise.photon_torpedoes == 0 { + view::no_torpedoes_remaining(); + return; + } } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index a7f11d2a..58be1f18 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -18,13 +18,13 @@ fn main() { view::enterprise(); view::intro(&galaxy); - let _ = input::prompt("Press Enter when ready to accept command"); + let _ = input::prompt(view::prompts::WHEN_READY); view::starting_quadrant(&galaxy.enterprise.quadrant); view::short_range_scan(&galaxy); loop { - let command = input::prompt("Command?"); + let command = input::prompt(view::prompts::COMMAND); if command.len() == 0 { continue; } @@ -36,7 +36,8 @@ fn main() { systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&mut galaxy), systems::COMPUTER => commands::access_computer(&galaxy, command[1..].into()), systems::PHASERS => commands::get_power_and_fire_phasers(&mut galaxy, command[1..].into()), - "XXX" => galaxy.enterprise.destroyed = true, + systems::TORPEDOES => commands::gather_dir_and_launch_torpedo(&mut galaxy, command[1..].into()), + systems::RESIGN => galaxy.enterprise.destroyed = true, _ => view::print_command_help() } diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 144a7e93..58251919 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -118,9 +118,12 @@ pub mod systems { pub const LONG_RANGE_SCAN: &str = "LRS"; pub const COMPUTER: &str = "COM"; pub const PHASERS: &str = "PHA"; + pub const TORPEDOES: &str = "TOR"; - pub const KEYS: [&str; 7] = [ - SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL, DAMAGE_CONTROL, LONG_RANGE_SCAN, COMPUTER, PHASERS + pub const RESIGN: &str = "XXX"; + + pub const KEYS: [&str; 8] = [ + SHORT_RANGE_SCAN, WARP_ENGINES, SHIELD_CONTROL, DAMAGE_CONTROL, LONG_RANGE_SCAN, COMPUTER, PHASERS, TORPEDOES ]; pub fn name_for(key: &str) -> String { @@ -132,6 +135,7 @@ pub mod systems { LONG_RANGE_SCAN => "Long Range Scanners".into(), COMPUTER => "Library-Computer".into(), PHASERS => "Phaser Control".into(), + TORPEDOES => "Photon Tubes".into(), _ => "Unknown".into() } } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 73ec39d7..b087a949 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,5 +1,19 @@ use crate::model::{Galaxy, Pos, EndPosition, SectorStatus, Enterprise, systems}; +pub mod prompts { + pub const COURSE: &str = "Course (1-9)?"; + pub const SHIELDS: &str = "Number of units to shields"; + pub const REPAIR: &str = "Will you authorize the repair order"; + pub const COMPUTER: &str = "Computer active and waiting command?"; + pub const PHASERS: &str = "Number of units to fire"; + pub const WHEN_READY: &str = "Press Enter when ready to accept command"; + pub const COMMAND: &str = "Command?"; + + pub fn warp_factor(max_warp: f32) -> String { + format!("Warp Factor (0-{})?", max_warp) + } +} + pub fn full_instructions() { println!( " INSTRUCTIONS FOR 'SUPER STAR TREK' @@ -492,4 +506,8 @@ pub fn replay() { The Federation is in need of a new starship commander for a similar mission -- if there is a volunteer let him step forward and enter 'Aye'") +} + +pub fn no_torpedoes_remaining() { + println!("All photon torpedoes expended") } \ No newline at end of file From 3344649ed4a35f579529f12271a29ee6b05c619d Mon Sep 17 00:00:00 2001 From: Christopher Date: Sat, 4 Mar 2023 11:36:42 +1300 Subject: [PATCH 53/72] changed nav function to calculate a path --- 84_Super_Star_Trek/rust/src/commands.rs | 86 +++++++++++++++++-------- 84_Super_Star_Trek/rust/src/model.rs | 19 +++--- 84_Super_Star_Trek/rust/src/view.rs | 9 +++ 3 files changed, 79 insertions(+), 35 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 98b9e0d8..b3ca531e 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -38,7 +38,7 @@ pub fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec) { pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec) { - let course = input::param_or_prompt_value(&provided, 0, view::prompts::COURSE, 1, 9); + let course = input::param_or_prompt_value(&provided, 0, view::prompts::COURSE, 1.0, 9.0); if course.is_none() { view::bad_nav(); return; @@ -126,28 +126,28 @@ fn repair_or_damage_random_system(enterprise: &mut Enterprise) { view::random_repair_report_for(system_name, true); } -fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { +fn move_enterprise(course: f32, warp_speed: f32, galaxy: &mut Galaxy) { let ship = &mut galaxy.enterprise; // todo account for being blocked - let end = find_end_quadrant_sector(ship.quadrant, ship.sector, course, warp_speed); + let path = find_path(ship.quadrant, ship.sector, course, warp_speed); - if end.energy_cost > ship.total_energy { + if path.energy_cost > ship.total_energy { view::insuffient_warp_energy(warp_speed); return } - if end.hit_edge { - view::hit_edge(&end); + if path.hit_edge { + view::hit_edge(&path); } - if ship.quadrant != end.quadrant { - view::enter_quadrant(&end.quadrant); - galaxy.scanned.insert(end.quadrant); + if ship.quadrant != path.quadrant { + view::enter_quadrant(&path.quadrant); + galaxy.scanned.insert(path.quadrant); - if galaxy.quadrants[end.quadrant.as_index()].klingons.len() > 0 { + if galaxy.quadrants[path.quadrant.as_index()].klingons.len() > 0 { view::condition_red(); if ship.shields <= 200 { view::danger_shields(); @@ -155,16 +155,16 @@ fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { } } - ship.quadrant = end.quadrant; - ship.sector = end.sector; + ship.quadrant = path.quadrant; + ship.sector = path.sector; - let quadrant = &galaxy.quadrants[end.quadrant.as_index()]; + let quadrant = &galaxy.quadrants[path.quadrant.as_index()]; if quadrant.docked_at_starbase(ship.sector) { ship.shields = 0; ship.photon_torpedoes = MAX_PHOTON_TORPEDOES; ship.total_energy = MAX_ENERGY; } else { - ship.total_energy = (ship.total_energy - end.energy_cost).max(0); + ship.total_energy = (ship.total_energy - path.energy_cost).max(0); if ship.shields > ship.total_energy { view::divert_energy_from_shields(); ship.shields = ship.total_energy; @@ -174,26 +174,45 @@ fn move_enterprise(course: u8, warp_speed: f32, galaxy: &mut Galaxy) { view::short_range_scan(&galaxy) } -fn find_end_quadrant_sector(start_quadrant: Pos, start_sector: Pos, course: u8, warp_speed: f32) -> EndPosition { - let (dx, dy): (i8, i8) = COURSES[(course - 1) as usize]; +fn find_path(start_quadrant: Pos, start_sector: Pos, course: f32, warp_speed: f32) -> EndPosition { + + // this course delta stuff is a translation (of a translation, of a translation...) of the original basic calcs + let dir = (course - 1.0) % 8.0; + let (dx1, dy1) = COURSES[dir as usize]; + let (dx2, dy2) = COURSES[(dir + 1.0) as usize]; + let frac = dir - (dir as i32) as f32; + + let dx = dx1 + (dx2 - dx1) * frac; + let dy = dy1 + (dy2 - dy1) * frac; let mut distance = (warp_speed * 8.0) as i8; if distance == 0 { distance = 1; } - let galaxy_pos = start_quadrant * 8u8 + start_sector; + let mut last_sector = start_quadrant * 8 + start_sector; + let mut path = Vec::new(); + let mut hit_edge; - let mut nx = (galaxy_pos.0 as i8) + dx * distance; - let mut ny = (galaxy_pos.1 as i8) + dy * distance; + loop { + let nx = (last_sector.0 as f32 + dx) as i8; + let ny = (last_sector.1 as f32 + dy) as i8; + hit_edge = nx < 0 || ny < 0 || nx >= 64 || ny >= 64; + if hit_edge { + break; + } + last_sector = Pos(nx as u8, ny as u8); + path.push(last_sector); - let hit_edge = nx < 0 || ny < 0 || nx >= 64 || ny >= 64; - nx = nx.min(63).max(0); - ny = ny.min(63).max(0); - - let quadrant = Pos((nx / 8) as u8, (ny / 8) as u8); - let sector = Pos((nx % 8) as u8, (ny % 8) as u8); - let energy_cost = distance as u16 + 10; + distance -= 1; + if distance == 0 { + break; + } + } + + let quadrant = Pos((last_sector.0 / 8) as u8, (last_sector.1 / 8) as u8); + let sector = Pos((last_sector.0 % 8) as u8, (last_sector.1 % 8) as u8); + let energy_cost = path.len() as u16 + 10; EndPosition { quadrant, sector, hit_edge, energy_cost } } @@ -361,4 +380,19 @@ pub fn gather_dir_and_launch_torpedo(galaxy: &mut Galaxy, provided: Vec) view::no_torpedoes_remaining(); return; } + + let course = input::param_or_prompt_value(&provided, 0, view::prompts::TORPEDO_COURSE, 1.0, 9.0); + if course.is_none() { + view::bad_torpedo_course(); + return; + } + + galaxy.enterprise.photon_torpedoes -= 1; + view::torpedo_track(); + + // calculate direction + // step through sectors + // test for hits or final miss + + klingons_fire(galaxy); } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 58251919..a8919b5e 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -183,15 +183,16 @@ impl Display for Pos { } } -pub const COURSES : [(i8, i8); 8] = [ - (1, 0), - (1, -1), - (0, -1), - (-1, -1), - (-1, 0), - (-1, 1), - (0, 1), - (1, 1), +pub const COURSES : [(f32, f32); 9] = [ + (1., 0.), + (1., -1.), + (0., -1.), + (-1., -1.), + (-1., 0.), + (-1., 1.), + (0., 1.), + (1., 1.), + (1., 0.), // course 9 is equal to course 1 ]; #[derive(PartialEq)] diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index b087a949..38e307df 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -2,6 +2,7 @@ use crate::model::{Galaxy, Pos, EndPosition, SectorStatus, Enterprise, systems}; pub mod prompts { pub const COURSE: &str = "Course (1-9)?"; + pub const TORPEDO_COURSE: &str = "Photon torpedo course (1-9)?"; pub const SHIELDS: &str = "Number of units to shields"; pub const REPAIR: &str = "Will you authorize the repair order"; pub const COMPUTER: &str = "Computer active and waiting command?"; @@ -276,6 +277,10 @@ pub fn bad_nav() { println!(" Lt. Sulu reports, 'Incorrect course data, sir!'") } +pub fn bad_torpedo_course() { + println!(" Ensign Chekov reports, 'Incorrect course data, sir!'") +} + pub fn enterprise_hit(hit_strength: &u16, from_sector: &Pos) { println!("{hit_strength} unit hit on Enterprise from sector {from_sector}"); } @@ -510,4 +515,8 @@ let him step forward and enter 'Aye'") pub fn no_torpedoes_remaining() { println!("All photon torpedoes expended") +} + +pub fn torpedo_track() { + println!("Torpedo track:") } \ No newline at end of file From 5c25a83eafe9a8c062c0aed79e30262206cad81a Mon Sep 17 00:00:00 2001 From: Christopher Date: Sat, 4 Mar 2023 11:37:32 +1300 Subject: [PATCH 54/72] bug fix --- 84_Super_Star_Trek/rust/src/view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 38e307df..267fc91b 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -291,7 +291,7 @@ pub fn hit_edge(end: &EndPosition) { 'Permission to attempt crossing of galactic perimeter is hereby *Denied*. Shut down your engines.' Chief Engineer Scott reports, 'Warp engines shut down - at sector {} of quadrant {}.'", end.quadrant, end.sector); + at sector {} of quadrant {}.'", end.sector, end.quadrant); } pub fn condition_red() { From 781d0566f8d351e38ba273854ba0fb1c624df180 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sat, 4 Mar 2023 15:24:05 +1300 Subject: [PATCH 55/72] implemented torpedoes! --- 84_Super_Star_Trek/rust/src/commands.rs | 127 ++++++++++++++++++------ 84_Super_Star_Trek/rust/src/main.rs | 2 +- 84_Super_Star_Trek/rust/src/model.rs | 29 ++++-- 84_Super_Star_Trek/rust/src/view.rs | 39 ++++++-- 84_Super_Star_Trek/rust/tasks.md | 4 +- 5 files changed, 148 insertions(+), 53 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index b3ca531e..cc79dffb 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -132,22 +132,24 @@ fn move_enterprise(course: f32, warp_speed: f32, galaxy: &mut Galaxy) { // todo account for being blocked - let path = find_path(ship.quadrant, ship.sector, course, warp_speed); + let (path, hit_edge) = find_nav_path(ship.quadrant, ship.sector, course, warp_speed); + let energy_cost = path.len() as u16 + 10; - if path.energy_cost > ship.total_energy { + if energy_cost > ship.total_energy { view::insuffient_warp_energy(warp_speed); return } - if path.hit_edge { - view::hit_edge(&path); + let (end_quadrant, end_sector) = path[path.len() - 1].to_local_quadrant_sector(); + if hit_edge { + view::hit_edge(end_quadrant, end_sector); } - if ship.quadrant != path.quadrant { - view::enter_quadrant(&path.quadrant); - galaxy.scanned.insert(path.quadrant); + if ship.quadrant != end_quadrant { + view::enter_quadrant(end_quadrant); + galaxy.scanned.insert(end_quadrant); - if galaxy.quadrants[path.quadrant.as_index()].klingons.len() > 0 { + if galaxy.quadrants[end_quadrant.as_index()].klingons.len() > 0 { view::condition_red(); if ship.shields <= 200 { view::danger_shields(); @@ -155,16 +157,16 @@ fn move_enterprise(course: f32, warp_speed: f32, galaxy: &mut Galaxy) { } } - ship.quadrant = path.quadrant; - ship.sector = path.sector; + ship.quadrant = end_quadrant; + ship.sector = end_sector; - let quadrant = &galaxy.quadrants[path.quadrant.as_index()]; + let quadrant = &galaxy.quadrants[end_quadrant.as_index()]; if quadrant.docked_at_starbase(ship.sector) { ship.shields = 0; ship.photon_torpedoes = MAX_PHOTON_TORPEDOES; ship.total_energy = MAX_ENERGY; } else { - ship.total_energy = (ship.total_energy - path.energy_cost).max(0); + ship.total_energy = ship.total_energy - energy_cost; if ship.shields > ship.total_energy { view::divert_energy_from_shields(); ship.shields = ship.total_energy; @@ -174,23 +176,16 @@ fn move_enterprise(course: f32, warp_speed: f32, galaxy: &mut Galaxy) { view::short_range_scan(&galaxy) } -fn find_path(start_quadrant: Pos, start_sector: Pos, course: f32, warp_speed: f32) -> EndPosition { +fn find_nav_path(start_quadrant: Pos, start_sector: Pos, course: f32, warp_speed: f32) -> (Vec, bool) { - // this course delta stuff is a translation (of a translation, of a translation...) of the original basic calcs - let dir = (course - 1.0) % 8.0; - let (dx1, dy1) = COURSES[dir as usize]; - let (dx2, dy2) = COURSES[(dir + 1.0) as usize]; - let frac = dir - (dir as i32) as f32; - - let dx = dx1 + (dx2 - dx1) * frac; - let dy = dy1 + (dy2 - dy1) * frac; + let (dx, dy) = calculate_delta(course); let mut distance = (warp_speed * 8.0) as i8; if distance == 0 { distance = 1; } - let mut last_sector = start_quadrant * 8 + start_sector; + let mut last_sector = start_sector.as_galactic_sector(start_quadrant); let mut path = Vec::new(); let mut hit_edge; @@ -210,11 +205,20 @@ fn find_path(start_quadrant: Pos, start_sector: Pos, course: f32, warp_speed: f3 } } - let quadrant = Pos((last_sector.0 / 8) as u8, (last_sector.1 / 8) as u8); - let sector = Pos((last_sector.0 % 8) as u8, (last_sector.1 % 8) as u8); - let energy_cost = path.len() as u16 + 10; + (path, hit_edge) +} - EndPosition { quadrant, sector, hit_edge, energy_cost } +fn calculate_delta(course: f32) -> (f32, f32) { + // this course delta stuff is a translation (of a translation, of a translation...) of the original basic calcs + let dir = (course - 1.0) % 8.0; + let (dx1, dy1) = COURSES[dir as usize]; + let (dx2, dy2) = COURSES[(dir + 1.0) as usize]; + let frac = dir - (dir as i32) as f32; + + let dx = dx1 + (dx2 - dx1) * frac; + let dy = dy1 + (dy2 - dy1) * frac; + + (dx, dy) } fn klingons_move(galaxy: &mut Galaxy) { @@ -371,12 +375,15 @@ pub fn get_power_and_fire_phasers(galaxy: &mut Galaxy, provided: Vec) { } pub fn gather_dir_and_launch_torpedo(galaxy: &mut Galaxy, provided: Vec) { - if galaxy.enterprise.damaged.contains_key(systems::TORPEDOES) { + let star_bases = galaxy.remaining_starbases(); + let ship = &mut galaxy.enterprise; + + if ship.damaged.contains_key(systems::TORPEDOES) { view::inoperable(&systems::name_for(systems::TORPEDOES)); return; } - if galaxy.enterprise.photon_torpedoes == 0 { + if ship.photon_torpedoes == 0 { view::no_torpedoes_remaining(); return; } @@ -387,12 +394,68 @@ pub fn gather_dir_and_launch_torpedo(galaxy: &mut Galaxy, provided: Vec) return; } - galaxy.enterprise.photon_torpedoes -= 1; + ship.photon_torpedoes -= 1; view::torpedo_track(); - // calculate direction - // step through sectors - // test for hits or final miss + let path = find_torpedo_path(ship.sector, course.unwrap()); + let quadrant = &mut galaxy.quadrants[ship.quadrant.as_index()]; + let mut hit = false; + for p in path { + view::torpedo_path(p); + match quadrant.sector_status(p) { + SectorStatus::Empty => continue, + SectorStatus::Star => { + hit = true; + view::star_absorbed_torpedo(p); + break; + }, + SectorStatus::Klingon => { + hit = true; + quadrant.get_klingon(p).unwrap().energy = 0.0; + quadrant.klingons.retain(|k| k.energy > 0.0); + view::klingon_destroyed(); + break; + }, + SectorStatus::StarBase => { + hit = true; + quadrant.star_base = None; + let remaining = star_bases - 1; + view::destroyed_starbase(remaining > 0); + if remaining == 0 { + ship.destroyed = true; + } + break; + } + } + } + + if ship.destroyed { // if you wiped out the last starbase, trigger game over + return; + } + + if !hit { + view::torpedo_missed(); + } klingons_fire(galaxy); +} + +fn find_torpedo_path(start_sector: Pos, course: f32) -> Vec { + + let (dx, dy) = calculate_delta(course); + + let mut last_sector = start_sector; + let mut path = Vec::new(); + + loop { + let nx = (last_sector.0 as f32 + dx) as i8; + let ny = (last_sector.1 as f32 + dy) as i8; + if nx < 0 || ny < 0 || nx >= 8 || ny >= 8 { + break; + } + last_sector = Pos(nx as u8, ny as u8); + path.push(last_sector); + } + + path } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 58be1f18..78e59531 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -20,7 +20,7 @@ fn main() { view::intro(&galaxy); let _ = input::prompt(view::prompts::WHEN_READY); - view::starting_quadrant(&galaxy.enterprise.quadrant); + view::starting_quadrant(galaxy.enterprise.quadrant); view::short_range_scan(&galaxy); loop { diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index a8919b5e..9b2f1118 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -60,7 +60,8 @@ impl Enterprise { if self.shields <= hit_strength { view::enterprise_destroyed(); - self.destroyed = true + self.destroyed = true; + return; } self.shields -= hit_strength; @@ -141,13 +142,6 @@ pub mod systems { } } -pub struct EndPosition { - pub quadrant: Pos, - pub sector: Pos, - pub hit_edge: bool, - pub energy_cost: u16, -} - #[derive(PartialEq, Clone, Copy, Debug, Hash, Eq)] pub struct Pos(pub u8, pub u8); @@ -159,6 +153,14 @@ impl Pos { pub fn abs_diff(&self, other: Pos) -> u8 { self.0.abs_diff(other.0) + self.1.abs_diff(other.1) } + + pub fn as_galactic_sector(&self, containing_quadrant: Pos) -> Self { + Pos(containing_quadrant.0 * 8 + self.0, containing_quadrant.1 * 8 + self.1) + } + + pub fn to_local_quadrant_sector(&self) -> (Self, Self) { + (Pos(self.0 / 8, self.1 / 8), Pos(self.0 % 8, self.1 % 8)) + } } impl Mul for Pos { @@ -286,7 +288,7 @@ impl Quadrant { SectorStatus::Star } else if self.is_starbase(sector) { SectorStatus::StarBase - } else if self.has_klingon(§or) { + } else if self.has_klingon(sector) { SectorStatus::Klingon } else { SectorStatus::Empty @@ -300,9 +302,14 @@ impl Quadrant { } } - fn has_klingon(&self, sector: &Pos) -> bool { + fn has_klingon(&self, sector: Pos) -> bool { let klingons = &self.klingons; - klingons.into_iter().find(|k| &k.sector == sector).is_some() + klingons.into_iter().find(|k| k.sector == sector).is_some() + } + + pub fn get_klingon(&mut self, sector: Pos) -> Option<&mut Klingon> { + let klingons = &mut self.klingons; + klingons.into_iter().find(|k| k.sector == sector) } pub fn find_empty_sector(&self) -> Pos { diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 267fc91b..f7bac4db 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,4 +1,4 @@ -use crate::model::{Galaxy, Pos, EndPosition, SectorStatus, Enterprise, systems}; +use crate::model::{Galaxy, Pos, SectorStatus, Enterprise, systems}; pub mod prompts { pub const COURSE: &str = "Course (1-9)?"; @@ -187,19 +187,19 @@ const REGION_NAMES: [&str; 16] = [ const SUB_REGION_NAMES: [&str; 4] = ["I", "II", "III", "IV"]; -fn quadrant_name(quadrant: &Pos) -> String { +fn quadrant_name(quadrant: Pos) -> String { format!("{} {}", REGION_NAMES[((quadrant.1 << 1) + (quadrant.0 >> 2)) as usize], SUB_REGION_NAMES[(quadrant.1 % 4) as usize]) } -pub fn starting_quadrant(quadrant: &Pos) { +pub fn starting_quadrant(quadrant: Pos) { println!( "\nYour mission begins with your starship located in the galactic quadrant, '{}'.\n", quadrant_name(quadrant)) } -pub fn enter_quadrant(quadrant: &Pos) { +pub fn enter_quadrant(quadrant: Pos) { println!("\nNow entering {} quadrant . . .\n", quadrant_name(quadrant)) } @@ -285,13 +285,13 @@ pub fn enterprise_hit(hit_strength: &u16, from_sector: &Pos) { println!("{hit_strength} unit hit on Enterprise from sector {from_sector}"); } -pub fn hit_edge(end: &EndPosition) { +pub fn hit_edge(quadrant: Pos, sector: Pos) { println!( "Lt. Uhura report message from Starfleet Command: 'Permission to attempt crossing of galactic perimeter is hereby *Denied*. Shut down your engines.' Chief Engineer Scott reports, 'Warp engines shut down - at sector {} of quadrant {}.'", end.sector, end.quadrant); + at sector {} of quadrant {}.'", sector, quadrant); } pub fn condition_red() { @@ -494,7 +494,7 @@ pub fn klingon_remaining_energy(energy: f32) { } pub fn klingon_destroyed() { - println!(" Target Destroyed!") // not standard for game but feedback is good. Sorry Mr. Roddenberry + println!("*** Klingon destroyed ***") } pub fn congratulations(efficiency: f32) { @@ -519,4 +519,29 @@ pub fn no_torpedoes_remaining() { pub fn torpedo_track() { println!("Torpedo track:") +} + +pub fn torpedo_path(sector: Pos) { + println!("{:<16}{}", "", sector) +} + +pub fn torpedo_missed() { + println!("Torpedo missed!") +} + +pub fn star_absorbed_torpedo(sector: Pos) { + println!("Star at {sector} absorbed torpedo energy.") +} + +pub fn destroyed_starbase(not_the_last_starbase: bool) { + println!("*** Starbase destroyed ***"); + if not_the_last_starbase { + println!(" +Starfleet Command reviewing your record to consider +court martial!") + } else { + println!(" +That does it, Captain!! You are hereby relieved of command +and sentenced to 99 stardates at hard labor on Cygnus 12!!") + } } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 7a663304..2ddea3df 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -25,9 +25,9 @@ Started after movement and display of stats was finished (no energy management o - [x] proximity detection for docking - [x] repair on damage control - [x] protection from shots -- [ ] weapons +- [x] weapons - [x] phasers - - [ ] torpedoes + - [x] torpedoes - [ ] computer - [x] 0 - output of all short and long range scans (requires tracking if a system has been scanned) - [ ] 1 - klingons, starbases, stardate and damage control From f5bcacb399c8886b09604c03db3bda28eb2c12df Mon Sep 17 00:00:00 2001 From: Christopher Date: Sat, 4 Mar 2023 21:35:00 +1300 Subject: [PATCH 56/72] update to tasks --- 84_Super_Star_Trek/rust/tasks.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 2ddea3df..7d31efd7 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -39,8 +39,9 @@ Started after movement and display of stats was finished (no energy management o - [x] restarting the game - [x] after defeat - [x] and by resigning -- [ ] time progression - - check all areas where time should move, and adjust accordingly +- [x] time progression + - [x] check all areas where time should move, and adjust accordingly + - looks to only be on nav and repair - [x] defeat due to time expired - [ ] intro instructions - [x] victory From 217e76071b11717ac0ad6a8b01c9659678480339 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sat, 4 Mar 2023 21:36:29 +1300 Subject: [PATCH 57/72] added pre-game text blobs --- 84_Super_Star_Trek/rust/src/view.rs | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index f7bac4db..a838922b 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -1,6 +1,7 @@ use crate::model::{Galaxy, Pos, SectorStatus, Enterprise, systems}; pub mod prompts { + pub const INSTRUCTIONS: &str = "Do you need instructions"; pub const COURSE: &str = "Course (1-9)?"; pub const TORPEDO_COURSE: &str = "Photon torpedo course (1-9)?"; pub const SHIELDS: &str = "Number of units to shields"; @@ -15,6 +16,38 @@ pub mod prompts { } } +pub fn title() { + println!(" + + + + + + + + + + + + ************************************* + * * + * * + * * * SUPER STAR TREK * * * + * * + * * + ************************************* + + + + + + + + + + "); +} + pub fn full_instructions() { println!( " INSTRUCTIONS FOR 'SUPER STAR TREK' From 15cf7b31ff26d7dc32da696d85efb5d41fc39678 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 06:33:59 +1300 Subject: [PATCH 58/72] implemented input instructions --- 84_Super_Star_Trek/rust/src/main.rs | 8 +++++++- 84_Super_Star_Trek/rust/src/view.rs | 4 +++- 84_Super_Star_Trek/rust/tasks.md | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index 78e59531..e51b179e 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -1,6 +1,6 @@ use std::process::exit; -use input::prompt; +use input::{prompt, prompt_yes_no}; use model::{Galaxy, systems}; mod input; @@ -12,6 +12,12 @@ fn main() { ctrlc::set_handler(move || { exit(0) }) .expect("Error setting Ctrl-C handler"); + view::title(); + if prompt_yes_no(view::prompts::INSTRUCTIONS) { + view::full_instructions(); + let _ = input::prompt(view::prompts::WHEN_READY); + } + let mut galaxy = Galaxy::generate_new(); let initial_klingons = galaxy.remaining_klingons(); let initial_stardate = galaxy.stardate; diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index a838922b..22f397ef 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -154,7 +154,9 @@ pub fn full_instructions() { direction/distance calculations. Option 5 = Galactic Region Name Map This option prints the names of the sixteen major - galactic regions referred to in the game.") + galactic regions referred to in the game. + +") } pub fn enterprise() { diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 7d31efd7..20f9a5c1 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -43,5 +43,5 @@ Started after movement and display of stats was finished (no energy management o - [x] check all areas where time should move, and adjust accordingly - looks to only be on nav and repair - [x] defeat due to time expired -- [ ] intro instructions +- [x] intro instructions - [x] victory From c4d4f820ac72a42d903d90bc33f3e29b16befd08 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 07:49:25 +1300 Subject: [PATCH 59/72] work on some computer functions --- 84_Super_Star_Trek/rust/src/commands.rs | 16 ++++++++++++++++ 84_Super_Star_Trek/rust/src/view.rs | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index cc79dffb..cf427310 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -307,11 +307,27 @@ pub fn access_computer(galaxy: &Galaxy, provided: Vec) { match operation { 0 => view::galaxy_scanned_map(galaxy), + 3 => show_starbase_data(galaxy), 5 => view::galaxy_region_map(), _ => todo!() // todo implement others } } +fn show_starbase_data(galaxy: &Galaxy) { + let quadrant = &galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; + match &quadrant.star_base { + None => { + view::no_local_starbase(); + return; + }, + Some(s) => { + view::starbase_report(); + let pos = s.sector; + // calulcate direction and distance then print + } + } +} + pub fn get_power_and_fire_phasers(galaxy: &mut Galaxy, provided: Vec) { if galaxy.enterprise.damaged.contains_key(systems::PHASERS) { view::inoperable(&systems::name_for(systems::PHASERS)); diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 22f397ef..75ad1924 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -579,4 +579,12 @@ court martial!") That does it, Captain!! You are hereby relieved of command and sentenced to 99 stardates at hard labor on Cygnus 12!!") } +} + +pub fn no_local_starbase() { + println!("Mr. Spock reports, 'Sensors show no starbases in this quadrant.'") +} + +pub fn starbase_report() { + println!("From Enterprise to Starbase:'") } \ No newline at end of file From 5542e2fe59c7fa4837d65c31c54dd8988acb279b Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 08:11:24 +1300 Subject: [PATCH 60/72] first cut of dir / dist to local objects also bug fix for param reading, where the param wasnt bound by min max --- 84_Super_Star_Trek/rust/src/commands.rs | 5 +++-- 84_Super_Star_Trek/rust/src/input.rs | 11 ++++++---- 84_Super_Star_Trek/rust/src/model.rs | 27 +++++++++++++++++++++++++ 84_Super_Star_Trek/rust/src/view.rs | 7 +++++++ 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index cf427310..60ffcb21 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -322,8 +322,9 @@ fn show_starbase_data(galaxy: &Galaxy) { }, Some(s) => { view::starbase_report(); - let pos = s.sector; - // calulcate direction and distance then print + let origin = galaxy.enterprise.sector; + let target = s.sector; + view::direction_distance(origin.direction(target), origin.dist(target)) } } } diff --git a/84_Super_Star_Trek/rust/src/input.rs b/84_Super_Star_Trek/rust/src/input.rs index 5bd35fb3..68ab7006 100644 --- a/84_Super_Star_Trek/rust/src/input.rs +++ b/84_Super_Star_Trek/rust/src/input.rs @@ -42,12 +42,15 @@ pub fn prompt_value(prompt_text: &str, min: T, max: T) } pub fn param_or_prompt_value(params: &Vec, param_pos: usize, prompt_text: &str, min: T, max: T) -> Option { + let mut res: Option = None; if params.len() > param_pos { match params[param_pos].parse::() { - Ok(n) => Some(n), - _ => None + Ok(n) if (n >= min && n <= max) => res = Some(n), + _ => () } - } else { - return prompt_value::(prompt_text, min, max); } + if res.is_some() { + return res; + } + return prompt_value::(prompt_text, min, max); } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 9b2f1118..dd2b8dd8 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -154,6 +154,33 @@ impl Pos { self.0.abs_diff(other.0) + self.1.abs_diff(other.1) } + pub fn dist(&self, other: Pos) -> f32 { + let dx = other.0 as f32 - self.0 as f32; + let dy = other.1 as f32 - self.1 as f32; + (f32::powi(dx, 2) + f32::powi(dy, 2)).sqrt() + } + + pub fn direction(&self, other: Pos) -> f32 { + // this is a replication of the original BASIC code + let dx = other.0 as f32 - self.0 as f32; + let dy = other.1 as f32 - self.1 as f32; + let dx_dominant = dx.abs() > dy.abs(); + + let frac = if dx_dominant { dy / dx } else { -dx / dy }; + let nearest_cardinal = + if dx_dominant { + if dx > 0. { 7. } else { 3. } + } else { + if dy > 0. { 1. } else { 5. } + }; + + let mut dir = nearest_cardinal + frac; + if dir < 1. { + dir += 8. + } + dir + } + pub fn as_galactic_sector(&self, containing_quadrant: Pos) -> Self { Pos(containing_quadrant.0 * 8 + self.0, containing_quadrant.1 * 8 + self.1) } diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 75ad1924..19cc7a57 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -587,4 +587,11 @@ pub fn no_local_starbase() { pub fn starbase_report() { println!("From Enterprise to Starbase:'") +} + +pub fn direction_distance(dir: f32, dist: f32) { + println!( +"Direction = {dir} +Distance = {dist}" + ) } \ No newline at end of file From 2dba25c4eef4d4ad1563b8aa1192221e53b5a500 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 11:05:43 +1300 Subject: [PATCH 61/72] fixed calculation for direction --- 84_Super_Star_Trek/rust/src/model.rs | 9 +++++---- 84_Super_Star_Trek/rust/src/view.rs | 6 +++--- 84_Super_Star_Trek/rust/tasks.md | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index dd2b8dd8..1bb5ef8e 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -154,16 +154,17 @@ impl Pos { self.0.abs_diff(other.0) + self.1.abs_diff(other.1) } - pub fn dist(&self, other: Pos) -> f32 { + pub fn dist(&self, other: Pos) -> u8 { let dx = other.0 as f32 - self.0 as f32; let dy = other.1 as f32 - self.1 as f32; - (f32::powi(dx, 2) + f32::powi(dy, 2)).sqrt() + (f32::powi(dx, 2) + f32::powi(dy, 2)).sqrt() as u8 } pub fn direction(&self, other: Pos) -> f32 { // this is a replication of the original BASIC code - let dx = other.0 as f32 - self.0 as f32; - let dy = other.1 as f32 - self.1 as f32; + let dy = other.0 as f32 - self.0 as f32; + let dx = other.1 as f32 - self.1 as f32; + // note i actually use x,y, but the calculation assumes y,x so they're flipped above let dx_dominant = dx.abs() > dy.abs(); let frac = if dx_dominant { dy / dx } else { -dx / dy }; diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 19cc7a57..00598b58 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -433,7 +433,7 @@ pub fn long_range_scan(galaxy: &Galaxy) -> Vec { stars = format!("{}", quadrant.stars.len()); } - print!(": {}{}{} ", klingons, stars, star_bases) + print!(": {}{}{} ", klingons, star_bases, stars) } println!(":"); println!("{:-^19}", ""); @@ -482,7 +482,7 @@ pub fn galaxy_scanned_map(galaxy: &Galaxy) { let pos = Pos(x, y); if galaxy.scanned.contains(&pos) { let quadrant = &galaxy.quadrants[pos.as_index()]; - print!(" {}{}{} ", quadrant.klingons.len(), quadrant.stars.len(), quadrant.star_base.as_ref().map_or("0", |_| "1")) + print!(" {}{}{} ", quadrant.klingons.len(), quadrant.star_base.as_ref().map_or("0", |_| "1"), quadrant.stars.len()) } else { print!(" *** "); } @@ -589,7 +589,7 @@ pub fn starbase_report() { println!("From Enterprise to Starbase:'") } -pub fn direction_distance(dir: f32, dist: f32) { +pub fn direction_distance(dir: f32, dist: u8) { println!( "Direction = {dir} Distance = {dist}" diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 20f9a5c1..f3350bd6 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -45,3 +45,4 @@ Started after movement and display of stats was finished (no energy management o - [x] defeat due to time expired - [x] intro instructions - [x] victory +- [ ] switch from x,y to y,x \ No newline at end of file From e593bfd39aa817a921480aa32d9ec35f0c8041a1 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 11:59:16 +1300 Subject: [PATCH 62/72] general status from computer --- 84_Super_Star_Trek/rust/src/commands.rs | 19 ++++++++++++------- 84_Super_Star_Trek/rust/src/main.rs | 5 ++++- 84_Super_Star_Trek/rust/src/view.rs | 16 ++++++++++++++++ 84_Super_Star_Trek/rust/tasks.md | 4 ++-- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 60ffcb21..cfbc77e1 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -248,16 +248,17 @@ fn klingons_fire(galaxy: &mut Galaxy) { } } -pub fn run_damage_control(galaxy: &mut Galaxy) { - - let ship = &mut galaxy.enterprise; - - if ship.damaged.contains_key(systems::DAMAGE_CONTROL) { +pub fn run_damage_control(galaxy: &Galaxy) { + if galaxy.enterprise.damaged.contains_key(systems::DAMAGE_CONTROL) { view::inoperable(&systems::name_for(systems::DAMAGE_CONTROL)); - } else { - view::damage_control(&ship); + return; } + + view::damage_control(&galaxy.enterprise); +} +pub fn try_starbase_ship_repair(galaxy: &mut Galaxy) { + let ship = &mut galaxy.enterprise; let quadrant = &galaxy.quadrants[ship.quadrant.as_index()]; if ship.damaged.len() == 0 || !quadrant.docked_at_starbase(ship.sector) { return; @@ -307,6 +308,10 @@ pub fn access_computer(galaxy: &Galaxy, provided: Vec) { match operation { 0 => view::galaxy_scanned_map(galaxy), + 1 => { + view::status_report(galaxy); + run_damage_control(galaxy); + }, 3 => show_starbase_data(galaxy), 5 => view::galaxy_region_map(), _ => todo!() // todo implement others diff --git a/84_Super_Star_Trek/rust/src/main.rs b/84_Super_Star_Trek/rust/src/main.rs index e51b179e..4c1a277e 100644 --- a/84_Super_Star_Trek/rust/src/main.rs +++ b/84_Super_Star_Trek/rust/src/main.rs @@ -38,7 +38,10 @@ fn main() { systems::SHORT_RANGE_SCAN => commands::perform_short_range_scan(&galaxy), systems::WARP_ENGINES => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()), systems::SHIELD_CONTROL => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()), - systems::DAMAGE_CONTROL => commands::run_damage_control(&mut galaxy), + systems::DAMAGE_CONTROL => { + commands::run_damage_control(&galaxy); + commands::try_starbase_ship_repair(&mut galaxy); + } systems::LONG_RANGE_SCAN => commands::perform_long_range_scan(&mut galaxy), systems::COMPUTER => commands::access_computer(&galaxy, command[1..].into()), systems::PHASERS => commands::get_power_and_fire_phasers(&mut galaxy, command[1..].into()), diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 00598b58..34568bf3 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -594,4 +594,20 @@ pub fn direction_distance(dir: f32, dist: u8) { "Direction = {dir} Distance = {dist}" ) +} + +pub fn status_report(galaxy: &Galaxy) { + let klingon_count = galaxy.remaining_klingons(); + let star_bases = galaxy.remaining_starbases(); + let time_remaining = galaxy.final_stardate - galaxy.stardate; + let mut plural_starbase = ""; + if star_bases > 1 { + plural_starbase = "s"; + } + + println!(" Status report: +Klingons left: {klingon_count} +Mission must be completed in {time_remaining} stardates. +The Federation is maintaining {star_bases} starbase{plural_starbase} in the galaxy. +") } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index f3350bd6..9fcd937d 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -30,9 +30,9 @@ Started after movement and display of stats was finished (no energy management o - [x] torpedoes - [ ] computer - [x] 0 - output of all short and long range scans (requires tracking if a system has been scanned) - - [ ] 1 - klingons, starbases, stardate and damage control + - [x] 1 - klingons, starbases, stardate and damage control - [ ] 2 - photon torpedo data: direction and distance to all local klingons - - [ ] 3 - starbase distance and dir locally + - [x] 3 - starbase distance and dir locally - [ ] 4 - direction/distance calculator (useful for nav actions I guess) - [x] 5 - galactic name map From 50a4ddbcdc382c4c694b52e26128dfc7d2ccd737 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 14:02:39 +1300 Subject: [PATCH 63/72] direction distance calculator --- 84_Super_Star_Trek/rust/src/commands.rs | 21 ++++++++++++++++++++- 84_Super_Star_Trek/rust/src/input.rs | 19 ++++++++++++++++++- 84_Super_Star_Trek/rust/src/view.rs | 10 ++++++++++ 84_Super_Star_Trek/rust/tasks.md | 2 +- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index cfbc77e1..2848b039 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -1,6 +1,6 @@ use rand::Rng; -use crate::{model::*, view, input::{self, param_or_prompt_value}}; +use crate::{model::*, view, input::{self, param_or_prompt_value, prompt_two_values}}; pub fn perform_short_range_scan(galaxy: &Galaxy) { if galaxy.enterprise.damaged.contains_key(systems::SHORT_RANGE_SCAN) { @@ -313,6 +313,7 @@ pub fn access_computer(galaxy: &Galaxy, provided: Vec) { run_damage_control(galaxy); }, 3 => show_starbase_data(galaxy), + 4 => direction_dist_calculator(galaxy), 5 => view::galaxy_region_map(), _ => todo!() // todo implement others } @@ -334,6 +335,24 @@ fn show_starbase_data(galaxy: &Galaxy) { } } +fn direction_dist_calculator(galaxy: &Galaxy) { + view::direction_dist_intro(&galaxy.enterprise); + loop { + let coords1 = prompt_two_values(view::prompts::INITIAL_COORDS, 1, 8).map(|(x, y)| Pos(x, y)); + if coords1.is_none() { + continue; + } + let coords2 = prompt_two_values(view::prompts::TARGET_COORDS, 1, 8).map(|(x, y)| Pos(x, y)); + if coords2.is_none() { + continue; + } + let dir = coords1.unwrap().direction(coords2.unwrap()); + let dist = coords1.unwrap().dist(coords2.unwrap()); + view::direction_distance(dir, dist); + break; + } +} + pub fn get_power_and_fire_phasers(galaxy: &mut Galaxy, provided: Vec) { if galaxy.enterprise.damaged.contains_key(systems::PHASERS) { view::inoperable(&systems::name_for(systems::PHASERS)); diff --git a/84_Super_Star_Trek/rust/src/input.rs b/84_Super_Star_Trek/rust/src/input.rs index 68ab7006..62d4daee 100644 --- a/84_Super_Star_Trek/rust/src/input.rs +++ b/84_Super_Star_Trek/rust/src/input.rs @@ -9,7 +9,7 @@ pub fn prompt(prompt_text: &str) -> Vec { let mut buffer = String::new(); if let Ok(_) = stdin.read_line(&mut buffer) { - return buffer.trim_end().split(" ").map(|s| s.to_string()).collect(); + return buffer.trim_end().split([' ', ',']).map(|s| s.to_string()).collect(); } Vec::new() } @@ -53,4 +53,21 @@ pub fn param_or_prompt_value(params: &Vec, para return res; } return prompt_value::(prompt_text, min, max); +} + +pub fn prompt_two_values(prompt_text: &str, min: T, max: T) -> Option<(T, T)> { + let passed = prompt(prompt_text); + if passed.len() != 2 { + return None + } + match passed[0].parse::() { + Ok(n1) if (n1 >= min && n1 <= max) => { + match passed[1].parse::() { + Ok(n2) if (n2 >= min && n2 <= max) => + Some((n1, n2)), + _ => None + } + } + _ => None + } } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 34568bf3..282e6dc4 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -10,6 +10,8 @@ pub mod prompts { pub const PHASERS: &str = "Number of units to fire"; pub const WHEN_READY: &str = "Press Enter when ready to accept command"; pub const COMMAND: &str = "Command?"; + pub const INITIAL_COORDS: &str = " Initial coordinates (X/Y)"; + pub const TARGET_COORDS: &str = " Final coordinates (X/Y)"; pub fn warp_factor(max_warp: f32) -> String { format!("Warp Factor (0-{})?", max_warp) @@ -610,4 +612,12 @@ Klingons left: {klingon_count} Mission must be completed in {time_remaining} stardates. The Federation is maintaining {star_bases} starbase{plural_starbase} in the galaxy. ") +} + +pub fn direction_dist_intro(enterprise: &Enterprise) { + let quadrant = enterprise.quadrant; + let sector = enterprise.sector; + println!("Direction/distance calculator: +You are at quadrant {quadrant} sector {sector} +Please enter") } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 9fcd937d..1871b317 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -33,7 +33,7 @@ Started after movement and display of stats was finished (no energy management o - [x] 1 - klingons, starbases, stardate and damage control - [ ] 2 - photon torpedo data: direction and distance to all local klingons - [x] 3 - starbase distance and dir locally - - [ ] 4 - direction/distance calculator (useful for nav actions I guess) + - [x] 4 - direction/distance calculator (useful for nav actions I guess) - [x] 5 - galactic name map - [x] restarting the game From d973dec62d26e0688dd548ad32d0feb7c0f57440 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 14:09:28 +1300 Subject: [PATCH 64/72] implemented klongon data, final computer program --- 84_Super_Star_Trek/rust/src/commands.rs | 20 ++++++++++++++++++-- 84_Super_Star_Trek/rust/src/view.rs | 8 ++++++++ 84_Super_Star_Trek/rust/tasks.md | 4 ++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 2848b039..2bc28da8 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -312,14 +312,30 @@ pub fn access_computer(galaxy: &Galaxy, provided: Vec) { view::status_report(galaxy); run_damage_control(galaxy); }, - 3 => show_starbase_data(galaxy), + 2 => show_klingon_direction_data(galaxy), + 3 => show_starbase_direction_data(galaxy), 4 => direction_dist_calculator(galaxy), 5 => view::galaxy_region_map(), _ => todo!() // todo implement others } } -fn show_starbase_data(galaxy: &Galaxy) { +fn show_klingon_direction_data(galaxy: &Galaxy) { + let quadrant = &galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; + if quadrant.klingons.len() == 0 { + view::no_local_enemies(); + return; + } + + view::klingon_report(quadrant.klingons.len() > 1); + let origin = galaxy.enterprise.sector; + for k in &quadrant.klingons { + let target = k.sector; + view::direction_distance(origin.direction(target), origin.dist(target)) + } +} + +fn show_starbase_direction_data(galaxy: &Galaxy) { let quadrant = &galaxy.quadrants[galaxy.enterprise.quadrant.as_index()]; match &quadrant.star_base { None => { diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 282e6dc4..7e8aa399 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -620,4 +620,12 @@ pub fn direction_dist_intro(enterprise: &Enterprise) { println!("Direction/distance calculator: You are at quadrant {quadrant} sector {sector} Please enter") +} + +pub fn klingon_report(more_than_one: bool) { + let mut plural = ""; + if more_than_one { + plural = "s"; + } + println!("From Enterprise to Klingon battle cruiser{}", plural) } \ No newline at end of file diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index 1871b317..c4406208 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -28,10 +28,10 @@ Started after movement and display of stats was finished (no energy management o - [x] weapons - [x] phasers - [x] torpedoes -- [ ] computer +- [x] computer - [x] 0 - output of all short and long range scans (requires tracking if a system has been scanned) - [x] 1 - klingons, starbases, stardate and damage control - - [ ] 2 - photon torpedo data: direction and distance to all local klingons + - [x] 2 - photon torpedo data: direction and distance to all local klingons - [x] 3 - starbase distance and dir locally - [x] 4 - direction/distance calculator (useful for nav actions I guess) - [x] 5 - galactic name map From b9947f69b515d675f7c0f4be65a1f264adeb0688 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 15:05:25 +1300 Subject: [PATCH 65/72] switched from x/y system to y/x (y is horizontal, x is vertical --- 84_Super_Star_Trek/rust/src/model.rs | 19 +++++++++---------- 84_Super_Star_Trek/rust/src/view.rs | 18 +++++++++--------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 1bb5ef8e..1e4359ed 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -162,9 +162,8 @@ impl Pos { pub fn direction(&self, other: Pos) -> f32 { // this is a replication of the original BASIC code - let dy = other.0 as f32 - self.0 as f32; - let dx = other.1 as f32 - self.1 as f32; - // note i actually use x,y, but the calculation assumes y,x so they're flipped above + let dx = other.0 as f32 - self.0 as f32; + let dy = other.1 as f32 - self.1 as f32; let dx_dominant = dx.abs() > dy.abs(); let frac = if dx_dominant { dy / dx } else { -dx / dy }; @@ -214,15 +213,15 @@ impl Display for Pos { } pub const COURSES : [(f32, f32); 9] = [ - (1., 0.), - (1., -1.), - (0., -1.), - (-1., -1.), - (-1., 0.), - (-1., 1.), (0., 1.), + (-1., 1.), + (-1., 0.), + (-1., -1.), + (0., -1.), + (1., -1.), + (1., 0.), (1., 1.), - (1., 0.), // course 9 is equal to course 1 + (0., 1.), // course 9 is equal to course 1 ]; #[derive(PartialEq)] diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 7e8aa399..1cc2d202 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -226,7 +226,7 @@ const SUB_REGION_NAMES: [&str; 4] = ["I", "II", "III", "IV"]; fn quadrant_name(quadrant: Pos) -> String { format!("{} {}", - REGION_NAMES[((quadrant.1 << 1) + (quadrant.0 >> 2)) as usize], + REGION_NAMES[((quadrant.0 << 1) + (quadrant.1 >> 2)) as usize], SUB_REGION_NAMES[(quadrant.1 % 4) as usize]) } @@ -264,8 +264,8 @@ pub fn short_range_scan(model: &Galaxy) { ]; println!("{:-^33}", ""); - for y in 0..=7 { - for x in 0..=7 { + for x in 0..=7 { + for y in 0..=7 { let pos = Pos(x, y); if &pos == &model.enterprise.sector { print!("<*> ") @@ -278,7 +278,7 @@ pub fn short_range_scan(model: &Galaxy) { } } } - println!("{:>9}{}", "", data[y as usize]) + println!("{:>9}{}", "", data[x as usize]) } println!("{:-^33}", ""); } @@ -419,8 +419,8 @@ pub fn long_range_scan(galaxy: &Galaxy) -> Vec { println!("Long range scan for quadrant {}", galaxy.enterprise.quadrant); println!("{:-^19}", ""); - for y in cy - 1..=cy + 1 { - for x in cx - 1..=cx + 1 { + for x in cx - 1..=cx + 1 { + for y in cy - 1..=cy + 1 { let mut klingons = "*".into(); let mut star_bases = "*".into(); let mut stars = "*".into(); @@ -478,9 +478,9 @@ pub fn galaxy_scanned_map(galaxy: &Galaxy) { "Computer record of galaxy for quadrant {} 1 2 3 4 5 6 7 8 ----- ----- ----- ----- ----- ----- ----- -----", galaxy.enterprise.quadrant); - for y in 0..8 { - print!("{} ", y+1); - for x in 0..8 { + for x in 0..8 { + print!("{} ", x+1); + for y in 0..8 { let pos = Pos(x, y); if galaxy.scanned.contains(&pos) { let quadrant = &galaxy.quadrants[pos.as_index()]; From 8c1e7257163ecdcee5512c141bf707be0d6f79c4 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 15:05:49 +1300 Subject: [PATCH 66/72] updated tasks --- 84_Super_Star_Trek/rust/tasks.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md index c4406208..da9e49c9 100644 --- a/84_Super_Star_Trek/rust/tasks.md +++ b/84_Super_Star_Trek/rust/tasks.md @@ -45,4 +45,5 @@ Started after movement and display of stats was finished (no energy management o - [x] defeat due to time expired - [x] intro instructions - [x] victory -- [ ] switch from x,y to y,x \ No newline at end of file +- [x] switch from x,y to y,x +- [ ] uppercase prompts? \ No newline at end of file From 9f4f04582610c50340c35304554ff16c8349b7b9 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 15:30:17 +1300 Subject: [PATCH 67/72] implemented collision detection --- 84_Super_Star_Trek/rust/src/commands.rs | 26 +++++++++++-- 84_Super_Star_Trek/rust/src/model.rs | 2 +- 84_Super_Star_Trek/rust/src/view.rs | 8 +++- 84_Super_Star_Trek/rust/tasks.md | 49 ------------------------- 4 files changed, 29 insertions(+), 56 deletions(-) delete mode 100644 84_Super_Star_Trek/rust/tasks.md diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 2bc28da8..38bc3508 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -40,7 +40,7 @@ pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec let course = input::param_or_prompt_value(&provided, 0, view::prompts::COURSE, 1.0, 9.0); if course.is_none() { - view::bad_nav(); + view::bad_course_data(); return; } @@ -53,7 +53,7 @@ pub fn gather_dir_and_speed_then_move(galaxy: &mut Galaxy, provided: Vec let speed = input::param_or_prompt_value(&provided, 1, &view::prompts::warp_factor(max_warp), 0.0, 8.0); if speed.is_none() { - view::bad_nav(); + view::bad_course_data(); return; } @@ -130,9 +130,27 @@ fn move_enterprise(course: f32, warp_speed: f32, galaxy: &mut Galaxy) { let ship = &mut galaxy.enterprise; - // todo account for being blocked + let (mut path, mut hit_edge) = find_nav_path(ship.quadrant, ship.sector, course, warp_speed); + for i in 0..path.len() { + let (quadrant, sector) = path[i].to_local_quadrant_sector(); + if quadrant != ship.quadrant { + break; // have left current quadrant, so collision checks removed. if there is a collision at the dest... /shrug? + } + let quadrant = &galaxy.quadrants[quadrant.as_index()]; + if quadrant.sector_status(sector) != SectorStatus::Empty { + path = path[..i].into(); + hit_edge = false; + if i > 0 { + let (_, last_sector) = path[path.len() - 1].to_local_quadrant_sector(); + view::bad_nav(last_sector); + } else { + view::bad_nav(ship.sector); + return; + } + break; + } + } - let (path, hit_edge) = find_nav_path(ship.quadrant, ship.sector, course, warp_speed); let energy_cost = path.len() as u16 + 10; if energy_cost > ship.total_energy { diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 1e4359ed..10b97a4d 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -56,7 +56,7 @@ impl Enterprise { return; } - view::enterprise_hit(&hit_strength, §or); + view::enterprise_hit(&hit_strength, sector); if self.shields <= hit_strength { view::enterprise_destroyed(); diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index 1cc2d202..c276dee2 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -310,15 +310,19 @@ pub fn enterprise_destroyed() { println!("The Enterprise has been destroyed. The Federation will be conquered."); } -pub fn bad_nav() { +pub fn bad_course_data() { println!(" Lt. Sulu reports, 'Incorrect course data, sir!'") } +pub fn bad_nav(current_sector: Pos) { + println!("Warp engines shut down at sector {current_sector} dues to bad navigation") +} + pub fn bad_torpedo_course() { println!(" Ensign Chekov reports, 'Incorrect course data, sir!'") } -pub fn enterprise_hit(hit_strength: &u16, from_sector: &Pos) { +pub fn enterprise_hit(hit_strength: &u16, from_sector: Pos) { println!("{hit_strength} unit hit on Enterprise from sector {from_sector}"); } diff --git a/84_Super_Star_Trek/rust/tasks.md b/84_Super_Star_Trek/rust/tasks.md deleted file mode 100644 index da9e49c9..00000000 --- a/84_Super_Star_Trek/rust/tasks.md +++ /dev/null @@ -1,49 +0,0 @@ -# Tasks - -Started after movement and display of stats was finished (no energy management or collision detection or anything). - -- [x] klingon movement -- [x] klingon firing, game over etc -- [x] add intro -- [x] add entering (and starting in) sector headers -- [x] conditions and danger messages -- [x] remove energy on move -- [x] shields - - [x] shield control - - [x] shield hit absorption -- [x] subsystem damage - - [x] and support for reports -- [x] random system damage or repairs on move -- [x] lrs? -- [x] stranded... -- [ ] stop before hitting an object - - when moving across a sector, the enterprise should stop before it runs into something - - the current move is a jump, which makes this problematic. would need to rewrite it - - also, movement courses could be floats, according to the instructions, allowing for more precise movement and aiming -- [x] better command reading - support entering multiple values on a line (e.g. nav 3 0.1) -- [x] starbases - - [x] proximity detection for docking - - [x] repair on damage control - - [x] protection from shots -- [x] weapons - - [x] phasers - - [x] torpedoes -- [x] computer - - [x] 0 - output of all short and long range scans (requires tracking if a system has been scanned) - - [x] 1 - klingons, starbases, stardate and damage control - - [x] 2 - photon torpedo data: direction and distance to all local klingons - - [x] 3 - starbase distance and dir locally - - [x] 4 - direction/distance calculator (useful for nav actions I guess) - - [x] 5 - galactic name map - -- [x] restarting the game - - [x] after defeat - - [x] and by resigning -- [x] time progression - - [x] check all areas where time should move, and adjust accordingly - - looks to only be on nav and repair - - [x] defeat due to time expired -- [x] intro instructions -- [x] victory -- [x] switch from x,y to y,x -- [ ] uppercase prompts? \ No newline at end of file From c59dea8e21c9719bf5dd673765961df22b77bc81 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 15:48:53 +1300 Subject: [PATCH 68/72] removed final todo --- 84_Super_Star_Trek/rust/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index 38bc3508..d2eefc61 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -334,7 +334,7 @@ pub fn access_computer(galaxy: &Galaxy, provided: Vec) { 3 => show_starbase_direction_data(galaxy), 4 => direction_dist_calculator(galaxy), 5 => view::galaxy_region_map(), - _ => todo!() // todo implement others + _ => () // unreachable } } From e6118b4622ad91ad0594403bbd59cdb55d437764 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 15:55:54 +1300 Subject: [PATCH 69/72] added a readme --- 84_Super_Star_Trek/rust/readme.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 84_Super_Star_Trek/rust/readme.md diff --git a/84_Super_Star_Trek/rust/readme.md b/84_Super_Star_Trek/rust/readme.md new file mode 100644 index 00000000..7889ddf3 --- /dev/null +++ b/84_Super_Star_Trek/rust/readme.md @@ -0,0 +1,10 @@ +# Super Star Trek - Rust version + +Explanation of modules: + +- main.rs - creates the galaxy (generation functions are in model.rs as impl methods) then loops listening for commands. after each command checks for victory or defeat condtions. +- model.rs - all the structs and enums that represent the galaxy. key methods in here (as impl methods) are generation functions on galaxy and quadrant, and various comparison methods on the 'Pos' tuple type. +- commands.rs - most of the code that implements instructions given by the player (some code logic is in the model impls, and some in view.rs if its view only). +- view.rs - all text printed to the output, mostly called by command.rs (like view::bad_nav for example). also contains the prompts printed to the user (e.g. view::prompts::COMMAND). +- input.rs - utility methods for getting input from the user, including logic for parsing numbers, repeating prompts until a correct value is provided etc. + From 790e36611fe90e66f7bd6ef949d909a60cbd5015 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 16:02:59 +1300 Subject: [PATCH 70/72] more detail in the readme --- 84_Super_Star_Trek/rust/readme.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/84_Super_Star_Trek/rust/readme.md b/84_Super_Star_Trek/rust/readme.md index 7889ddf3..ae2f58dc 100644 --- a/84_Super_Star_Trek/rust/readme.md +++ b/84_Super_Star_Trek/rust/readme.md @@ -2,9 +2,18 @@ Explanation of modules: -- main.rs - creates the galaxy (generation functions are in model.rs as impl methods) then loops listening for commands. after each command checks for victory or defeat condtions. -- model.rs - all the structs and enums that represent the galaxy. key methods in here (as impl methods) are generation functions on galaxy and quadrant, and various comparison methods on the 'Pos' tuple type. -- commands.rs - most of the code that implements instructions given by the player (some code logic is in the model impls, and some in view.rs if its view only). -- view.rs - all text printed to the output, mostly called by command.rs (like view::bad_nav for example). also contains the prompts printed to the user (e.g. view::prompts::COMMAND). -- input.rs - utility methods for getting input from the user, including logic for parsing numbers, repeating prompts until a correct value is provided etc. +- [main.rs](./src/main.rs) - creates the galaxy (generation functions are in model.rs as impl methods) then loops listening for commands. after each command checks for victory or defeat condtions. +- [model.rs](./src/model.rs) - all the structs and enums that represent the galaxy. key methods in here (as impl methods) are generation functions on galaxy and quadrant, and various comparison methods on the 'Pos' tuple type. +- [commands.rs](./src/commands.rs) - most of the code that implements instructions given by the player (some code logic is in the model impls, and some in view.rs if its view only). +- [view.rs](./src/view.rs) - all text printed to the output, mostly called by command.rs (like view::bad_nav for example). also contains the prompts printed to the user (e.g. view::prompts::COMMAND). +- [input.rs](./src/input.rs) - utility methods for getting input from the user, including logic for parsing numbers, repeating prompts until a correct value is provided etc. +Basically the user is asked for the next command, this runs a function that usually checks if the command system is working, and if so will gather additional input (see next note for a slight change here), then either the model is read and info printed, or its mutated in some way (e.g. firing a torpedo, which reduces the torpedo count on the enterprise and can destroy klingons and star bases; finally the klingons fire back and can destroy the enterprise). Finally the win/lose conditions are checked before the loop repeats. + +## Changes from the original + +I have tried to keep it as close as possible. Notable changes are: + +- commands can be given with parameters in line. e.g. while 'nav' will ask for course and then warp speed in the original, here you can *optionally* also do this as one line, e.g. `nav 1 0.1` to move one sector east. I'm sorry - it was driving me insane in its original form (which is still sorted, as is partial application e.g. nav 1 to preset direction and then provide speed). +- text is mostly not uppercase, as text was in the basic version. this would be easy to change however as all text is in view.rs, but I chose not to. +- the navigation system (plotting direction, paths and collision detection) is as close as I could make it to the basic version (by using other language conversions as specification sources) but I suspect is not perfect. seems to work well enough however. \ No newline at end of file From 371b72fc36733a6881782cf7670788ec3262b4f6 Mon Sep 17 00:00:00 2001 From: Christopher Date: Sun, 5 Mar 2023 16:04:42 +1300 Subject: [PATCH 71/72] small cleanup --- 84_Super_Star_Trek/rust/src/model.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/model.rs b/84_Super_Star_Trek/rust/src/model.rs index 10b97a4d..aa08d734 100644 --- a/84_Super_Star_Trek/rust/src/model.rs +++ b/84_Super_Star_Trek/rust/src/model.rs @@ -257,9 +257,9 @@ impl Galaxy { Galaxy { stardate, final_stardate: stardate + rng.gen_range(25..=35) as f32, - quadrants: quadrants, - scanned: scanned, - enterprise: enterprise + quadrants, + scanned, + enterprise } } From 050765e89f084d2f0e6fb470ebe31a92772403b8 Mon Sep 17 00:00:00 2001 From: Christopher Date: Mon, 6 Mar 2023 09:37:45 +1300 Subject: [PATCH 72/72] minor bug fix for 0 path trying to exit the perimeter --- 84_Super_Star_Trek/rust/src/commands.rs | 7 +++++++ 84_Super_Star_Trek/rust/src/view.rs | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/84_Super_Star_Trek/rust/src/commands.rs b/84_Super_Star_Trek/rust/src/commands.rs index d2eefc61..c1c4bc8d 100644 --- a/84_Super_Star_Trek/rust/src/commands.rs +++ b/84_Super_Star_Trek/rust/src/commands.rs @@ -151,6 +151,13 @@ fn move_enterprise(course: f32, warp_speed: f32, galaxy: &mut Galaxy) { } } + if path.len() == 0 { + if hit_edge { + view::hit_edge(ship.quadrant, ship.sector); + } + return; + } + let energy_cost = path.len() as u16 + 10; if energy_cost > ship.total_energy { diff --git a/84_Super_Star_Trek/rust/src/view.rs b/84_Super_Star_Trek/rust/src/view.rs index c276dee2..caf6b74d 100644 --- a/84_Super_Star_Trek/rust/src/view.rs +++ b/84_Super_Star_Trek/rust/src/view.rs @@ -199,7 +199,7 @@ pub fn intro(model: &Galaxy) { "Your orders are as follows: Destroy the {} Klingon warships which have invaded the galaxy before they can attack federation headquarters - on stardate {}. This gives you {} days. {} in the galaxy for resupplying your ship.\n", + on stardate {:.1}. This gives you {} days. {} in the galaxy for resupplying your ship.\n", model.remaining_klingons(), model.final_stardate, model.final_stardate - model.stardate, star_base_message) } @@ -253,7 +253,7 @@ pub fn short_range_scan(model: &Galaxy) { } let data : [String; 8] = [ - format!("Stardate {}", model.stardate), + format!("Stardate {:.1}", model.stardate), format!("Condition {}", condition), format!("Quadrant {}", model.enterprise.quadrant), format!("Sector {}", model.enterprise.sector), @@ -300,7 +300,7 @@ pub fn print_command_help() { pub fn end_game_failure(galaxy: &Galaxy) { println!( -"Is is stardate {}. +"Is is stardate {:.1}. There were {} Klingon battle cruisers left at the end of your mission. ", galaxy.stardate, galaxy.remaining_klingons()); @@ -519,7 +519,7 @@ pub fn starbase_shields() { pub fn repair_estimate(repair_time: f32) { println!( "Technicians standing by to effect repairs to your ship; -Estimated time to repair: {repair_time} stardates.") +Estimated time to repair: {repair_time:.1} stardates.") } pub fn no_damage(sector: Pos) { @@ -613,7 +613,7 @@ pub fn status_report(galaxy: &Galaxy) { println!(" Status report: Klingons left: {klingon_count} -Mission must be completed in {time_remaining} stardates. +Mission must be completed in {time_remaining:.1} stardates. The Federation is maintaining {star_bases} starbase{plural_starbase} in the galaxy. ") }