use std::io::{self, Write}; use std::process; pub struct Game { encounter: Option, zone: Zone, adventurer: Adventurer, scarers: Vec, } impl Game { pub fn new() -> Game { Game { encounter: None, zone: Zone { width: 4, depth: 4 }, adventurer: Adventurer { name: String::from("adv"), h: Humors { health: 1000, attack: 1, critical_pct: 10, }, l: Location { x: 0, y: 0 }, }, scarers: vec![Scarer { name: String::from("Blue Minotaur"), description: String::from("Towering half bull with flaming nostrils"), h: Humors { health: 4000, attack: 4, critical_pct: 2, }, l: Location { x: 2, y: 2 }, }], } } pub fn play(&mut self) { loop { self.step(); } } fn on(&mut self, event: Event) { match event { Event::ApproachEdge => { println!("// you stand at the edge of the zone"); } Event::Encounter(s) => { println!("// !! you encounter an {}", s.name); } Event::Unencounter(s, o) => { println!("// !! you unencountered an {} with outcome {:?}", s.name, o); } Event::Fall => { println!("// you fall out of the zone"); process::exit(0); } Event::Step(d) => { println!("// you step {:?}", d); } Event::Miss => { println!("// you brace yourself for the next step"); } } } pub fn step(&mut self) { { let al = &self.adventurer.l; if al.x == 0 || al.y == 0 || al.x as u8 == self.zone.width || al.y as u8 == self.zone.depth { self.on(Event::ApproachEdge); } } let adventurer_loc = Location { x: self.adventurer.l.x, y: self.adventurer.l.y, }; let evt: Event = Event::Miss; for s in self.scarers.iter() { if adventurer_loc == s.l { evt = Event::Encounter(*s); } } self.on(evt); print!("> "); io::stdout().flush().expect("failed to flush stdout"); let mut line = String::new(); io::stdin() .read_line(&mut line) .expect("failed to read line of input"); line = line.trim().to_string(); match &mut self.encounter { None => { mut self.wandering_step(&line) }, Some(e) => { mut self.encounter_step(&line, e) }, } } fn encounter_step(&self, line: &str, enc: &mut Encounter) { eprintln!( "// this is not an encounter {:?} from line {:?} OK", enc, line ); } fn wandering_step(&mut self, line: &str) { let v: Vec<&str> = line.split(' ').collect(); match v.get(0) { Some(cmd) => { match *cmd { "help" => { println!("// maybe try 'loc'"); } "loc" => { println!( "// you stand at ({}, {})", self.adventurer.l.x, self.adventurer.l.y ); } "step" => { let (mv, dir) = match v.get(1) { Some(direction) => { let direction = direction.trim().to_lowercase(); match direction.as_str() { "forward" => ((1i8, 0i8), Direction::Forward), "back" => ((-1i8, 0i8), Direction::Back), "left" => ((0i8, 1i8), Direction::Left), "right" => ((0i8, -1i8), Direction::Right), _ => { println!("unknown direction {}", direction); ((0i8, 0i8), Direction::Forward) } } } None => ((1i8, 0i8), Direction::Forward), }; let loc = &mut self.adventurer.l; loc.x += mv.0; loc.y += mv.1; println!("// you step {:?}", dir); } _ => { println!("// what is this {}?", cmd); } }; } None => println!("// ..."), } } } #[derive(Debug)] enum Direction { Forward, Back, Left, Right, } #[derive(Debug)] enum EncounterOutcome { Victory, Defeat, } enum Event { Fall, ApproachEdge, Step(Direction), Encounter(Scarer), Unencounter(Scarer, EncounterOutcome), Miss, } #[derive(Debug)] struct Encounter { scarer: Scarer, } #[derive(Debug)] struct Humors { health: u16, attack: u8, critical_pct: u8, } #[derive(Debug)] struct Location { x: i8, y: i8, } impl PartialEq for Location { fn eq(&self, other: &Self) -> bool { self.x == other.x && self.y == other.y } } struct Adventurer { name: String, h: Humors, l: Location, } #[derive(Debug)] struct Scarer { name: String, description: String, h: Humors, l: Location, } struct Zone { width: u8, depth: u8, }