From c35736c5c8cc61f9bf070e65ab776f73fa92b297 Mon Sep 17 00:00:00 2001 From: Christopher Date: Tue, 28 Feb 2023 13:28:08 +1300 Subject: [PATCH] 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