use std::io::{ Write, stdin, stdout, }; /// As a dare to myself, I won't use any error-handling crates. #[derive (Debug)] enum GameError { IoError, } impl From for GameError { fn from (_: std::io::Error) -> Self { Self::IoError } } type Result = std::result::Result ; /// Prints a string, naively wrapping at 80-character boundaries /// This means a period might be wrapped separate from the sentence it ends /// , and frankly I think that's part of the charm. fn print (mut s: &str) { const COLS: usize = 80; while s.len () > COLS { println! ("{}", &s [0..80]); s = &s [80..]; } println! ("{}", s); } fn read_input () -> Result { { let mut stdout = stdout (); stdout.write_all (b"> ")?; stdout.flush ()?; } let mut buffer = String::new (); stdin ().read_line (&mut buffer)?; // I don't know why I need the type annotation here, but I do. let x: &[_] = &['\r', '\n']; let buffer = buffer.trim_end_matches (x).to_string (); Ok (buffer) } #[derive (Debug, PartialEq)] enum PlayerAction { Nonsense, } fn parse_input (_s: &str) -> PlayerAction { PlayerAction::Nonsense } fn main () -> Result <()> { print ("Welcome to SEROTONIN DEPOSITORY, the only adventure game ever made."); print (""); print ("You have been consensually kidnapped by a diabolical ADVENTURE GAME ENTHUSIAST and encouraged to solve PUZZLES for their sick PLEASURE. The only winning move is to solve all the PUZZLES."); print (""); print ("Press ENTER if you dare to begin."); let input = read_input ()?; if ! input.is_empty () { print ("That was more than just ENTER but OKAY, overachiever."); } print (""); print ("You are in a small room. In one corner is a TABLE. The door behind you is locked. Obvious exits are a DOOR locked by a KEYPAD, and an EMERGENCY EXIT."); let input = read_input ()?; let _action = parse_input (&input); Ok (()) } #[cfg (test)] mod test { #[test] fn parse_input () { use super::PlayerAction::*; for (input, expected) in [ ("", Nonsense), ].into_iter () { let actual = super::parse_input (input); assert_eq! (actual, expected); } } }