mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-23 07:29:02 -08:00
some reorganisation of code
This commit is contained in:
@@ -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<String>) {
|
||||||
|
|
||||||
|
// 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<String>) {
|
||||||
|
|
||||||
|
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;
|
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 }
|
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()];
|
let quadrant = &mut galaxy.quadrants[galaxy.enterprise.quadrant.as_index()];
|
||||||
for k in 0..quadrant.klingons.len() {
|
for k in 0..quadrant.klingons.len() {
|
||||||
let new_sector = quadrant.find_empty_sector();
|
let new_sector = quadrant.find_empty_sector();
|
||||||
|
|||||||
37
84_Super_Star_Trek/rust/src/input.rs
Normal file
37
84_Super_Star_Trek/rust/src/input.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
use std::{io::{stdin, stdout, Write}, str::FromStr};
|
||||||
|
|
||||||
|
pub fn prompt(prompt_text: &str) -> Vec<String> {
|
||||||
|
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<T: FromStr + PartialOrd>(prompt_text: &str, min: T, max: T) -> Option<T> {
|
||||||
|
let passed = prompt(prompt_text);
|
||||||
|
if passed.len() != 1 {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
match passed[0].parse::<T>() {
|
||||||
|
Ok(n) if (n >= min && n <= max) => Some(n),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn param_or_prompt_value<T: FromStr + PartialOrd>(params: &Vec<String>, param_pos: usize, prompt_text: &str, min: T, max: T) -> Option<T> {
|
||||||
|
if params.len() > param_pos {
|
||||||
|
match params[param_pos].parse::<T>() {
|
||||||
|
Ok(n) => Some(n),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return prompt_value::<T>(prompt_text, min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
use std::{io::{stdin, stdout, Write, Read}, process::exit, str::FromStr};
|
use std::process::exit;
|
||||||
|
|
||||||
use model::Galaxy;
|
use model::Galaxy;
|
||||||
|
|
||||||
|
mod input;
|
||||||
mod model;
|
mod model;
|
||||||
mod commands;
|
mod commands;
|
||||||
mod view;
|
mod view;
|
||||||
@@ -14,104 +15,29 @@ fn main() {
|
|||||||
|
|
||||||
view::enterprise();
|
view::enterprise();
|
||||||
view::intro(&galaxy);
|
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::starting_quadrant(&galaxy.enterprise.quadrant);
|
||||||
view::short_range_scan(&galaxy);
|
view::short_range_scan(&galaxy);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let command = prompt("Command?");
|
let command = input::prompt("Command?");
|
||||||
if command.len() == 0 {
|
if command.len() == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
match command[0].to_uppercase().as_str() {
|
match command[0].to_uppercase().as_str() {
|
||||||
"SRS" => view::short_range_scan(&galaxy),
|
"SRS" => view::short_range_scan(&galaxy),
|
||||||
"NAV" => gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()),
|
"NAV" => commands::gather_dir_and_speed_then_move(&mut galaxy, command[1..].into()),
|
||||||
"SHE" => get_amount_and_set_shields(&mut galaxy, command[1..].into()),
|
"SHE" => commands::get_amount_and_set_shields(&mut galaxy, command[1..].into()),
|
||||||
_ => view::print_command_help()
|
_ => view::print_command_help()
|
||||||
}
|
}
|
||||||
|
|
||||||
if galaxy.enterprise.destroyed { // todo: also check if stranded
|
if galaxy.enterprise.destroyed { // todo: also check if stranded
|
||||||
view::end_game_failure(&galaxy);
|
view::end_game_failure(&galaxy);
|
||||||
|
// todo check if can restart
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// todo check for victory
|
||||||
|
|
||||||
fn get_amount_and_set_shields(galaxy: &mut Galaxy, provided: Vec<String>) {
|
|
||||||
|
|
||||||
// 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<String>) {
|
|
||||||
|
|
||||||
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<String> {
|
|
||||||
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<T: FromStr + PartialOrd>(prompt_text: &str, min: T, max: T) -> Option<T> {
|
|
||||||
let passed = prompt(prompt_text);
|
|
||||||
if passed.len() != 1 {
|
|
||||||
return None
|
|
||||||
}
|
|
||||||
match passed[0].parse::<T>() {
|
|
||||||
Ok(n) if (n >= min && n <= max) => Some(n),
|
|
||||||
_ => None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_or_prompt_value<T: FromStr + PartialOrd>(params: &Vec<String>, param_pos: usize, prompt_text: &str, min: T, max: T) -> Option<T> {
|
|
||||||
if params.len() > param_pos {
|
|
||||||
match params[param_pos].parse::<T>() {
|
|
||||||
Ok(n) => Some(n),
|
|
||||||
_ => None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return prompt_value::<T>(prompt_text, min, max);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user