use crate::constants::{
BATS_IN_CAVE, INITIAL_ARROWS, MAX_LINKS_IN_ROOM, MAX_ROOMS_IN_CAVE, MIN_LINKS_IN_ROOM,
MIN_ROOMS_IN_CAVE, PITS_IN_CAVE,
};
use crate::instructions::instructions;
use crate::play::game_loop;
use clap::{ColorChoice, Parser};
use std::process::exit;
use std::sync::OnceLock;
mod constants;
mod error;
mod instructions;
mod interaction;
mod map;
mod play;
#[derive(Debug, Parser)]
#[command(author, version, about, color = ColorChoice::Never)]
struct Args {
#[arg(short, long, default_value_t = INITIAL_ARROWS)]
arrows: u32,
#[arg(short, long, default_value_t = BATS_IN_CAVE)]
bats: u32,
#[arg(short, long)]
debug: bool,
#[arg(short, long, default_value_t = PITS_IN_CAVE)]
pits: u32,
#[arg(skip = 20_u32)] rooms: u32,
#[arg(skip = 3_u32)] tunnels: u32,
#[arg(short = 'H', long)]
hard: bool,
}
static DEBUG: OnceLock<bool> = OnceLock::new();
fn main() {
let args = Args::parse();
DEBUG
.set(args.debug)
.expect("OnceCell \"DEBUG\" was already set.");
if let Some(amusing_error) = validate_arguments(&args) {
eprintln!("{amusing_error}");
exit(-1);
}
instructions();
println!(
"\nYou're in a cave with {} rooms and {} tunnels leading from each room.",
args.rooms, args.tunnels
);
println!(
"There are {} bat{} and {} pit{} scattered throughout the cave, and your",
args.bats,
interaction::plural(args.bats),
args.pits,
interaction::plural(args.pits)
);
println!(
"quiver holds {} custom super anti-evil Wumpus arrows. Good luck.",
args.arrows
);
game_loop(&args).unwrap();
}
fn validate_arguments(args: &Args) -> Option<&'static str> {
if args.rooms < MIN_ROOMS_IN_CAVE {
Some("No self-respecting wumpus would live in such a small cave!\n")
} else if args.rooms > MAX_ROOMS_IN_CAVE {
Some("Even wumpii can't furnish caves that large!\n")
} else if args.tunnels < MIN_LINKS_IN_ROOM {
Some("Wumpii like extra doors in their caves!\n")
} else if args.tunnels > MAX_LINKS_IN_ROOM || args.tunnels > args.rooms - (args.rooms / 4) {
Some("Too many tunnels! The cave collapsed!\n(Fortunately, the wumpus escaped!)\n")
} else if args.bats > args.rooms / 2 {
Some("The wumpus refused to enter the cave, claiming it was too crowded!\n")
} else if args.pits > args.rooms / 2 {
Some("The wumpus refused to enter the cave, claiming it was too dangerous!\n")
} else {
None
}
}