using STVrogue.GameLogic; using STVrogue.TestInfrastructure; using STVrogue.Utils; namespace STVrogue { /// /// This class implements the STVRogue's game main loop. It maintains a game-state, /// represented by an instance of the class . /// The latter also provides a method /// that contains the logic of a single turn update. /// /// This class is not finished. You have to finish it. /// public class GameRunner : GamePlay { /// /// The entire game-state is kept here. /// Game game; public GameRunner(Game game) { this.game = game; } /// /// To run the game. /// public void Run() { Run(null); } /// /// To run the game. The method implements a game loop where at every iteration /// it prints the game status to the Console, and waits for the user's input. /// The input is the translated to some action, and the method goes to the next /// iteration in the game loop. /// /// /// NOTE: for the 1st-phase of the project, ignore phi. /// /// A temporal property to check as the game runs. This is for /// Part-2 of the project. For Part-1 you can just pass null as phi. /// /// A judgement. Only relevant for the 2-nd phase of the project. /// If temporal property phi is not null, and the run satisfies /// phi, this method returns a Valid judgement. If the run violates phi, Invalid is /// returned. If Valid or Invalid cannot be decided, the method returns Inconclusive. /// public Judgement Run(TemporalProperty phi) { // Don't write directly to system-console. Use methods from game.GameConsole: game.GameConsole.WriteLines(" _______ _________ _______ _______ _______ _______ ", "( ____ \\\\__ __/|\\ /| ( ____ )( ___ )( ____ \\|\\ /|( ____ \\", "| ( \\/ ) ( | ) ( | | ( )|| ( ) || ( \\/| ) ( || ( \\/", "| (_____ | | | | | | | (____)|| | | || | | | | || (__ ", "(_____ ) | | ( ( ) ) | __)| | | || | ____ | | | || __) ", " ) | | | \\ \\_/ / | (\\ ( | | | || | \\_ )| | | || ( ", "/\\____) | | | \\ / | ) \\ \\__| (___) || (___) || (___) || (____/\\", "\\_______) )_( \\_/ |/ \\__/(_______)(_______)(_______)(_______/", "Welcome stranger..."); // ignore this judgement for the 1st Phase of the project if (phi != null) phi.Reset(); Judgement phiJudgement = Check(phi); // The game loop. Repeat until gameover or user quit: bool quit = false; while (!game.Gameover && !quit) { game.GameConsole.WriteLines("", $"TURN {game.TurnNumber}", "You are in a room. It is dark, and it feels dangerous...", "You are " + (game.Player.Alive ? "alive" : "DEAD"), $"Your health: {game.Player.Hp}, kill-counts: {game.Player.Kp}", "In your bag: nothing/nada/zero :(", "Your action: Move(m) | Pick-items(p) | Do-nothing(SPACE) | Quit(q)", " Attack(a) | Flee(f) | Use-item(u) "); // determine what the user action is, and covert it to an instance of Command: var c = game.GameConsole.ReadKey(); Command command = null; switch (c) { case 'm': command = new Command(CommandType.MOVE, "") ; break; case 'a': command = new Command(CommandType.ATTACK, ""); break; case 'u': command = new Command(CommandType.USE, "") ; break; case 'f': command = new Command(CommandType.FLEE, ""); break; case 'p': command = new Command(CommandType.PICKUP, ""); break; case ' ': command = new Command(CommandType.DoNOTHING, ""); break; case 'q': quit = true; break; } if (command == null) { continue; } // now the command is known, invoke a single-turn update: game.Update(command); // ignore this judgement for the 1st Phase of the project phiJudgement = Check(phi); } game.GameConsole.WriteLines("** Aaaw you QUIT! Score:" + game.Player.Kp + ". Go ahead and brag it out."); return phiJudgement; } Judgement Check(TemporalProperty phi) { if (phi == null) return Judgement.Inconclusive; Judgement j = phi.EvaluateNextState(game); if (j == Judgement.Invalid) { STVLogger.Log($"##### {ReplayId()} VIOLATES the given temporal property!"); } return j; } /// /// Reset the state of this runner to prepare it for a Replay-run. /// This is for Part-2 of Project. /// public void ResetReplayState() { STVLogger.Log("## Resetting the state of this game for replay."); // resetting the replay-console: var replayConsole = game.GameConsole as ReplayGameConsole; replayConsole.Reset(); // creating a fresh instance of Game, with the same config. This also resets the // random seed: game = new Game(game.Config); game.GameConsole = replayConsole; } /// /// The name/id of the game-play to replay. This is for Part-2 of the Project.. /// public string ReplayId() { var replayConsole = game.GameConsole as ReplayGameConsole; return replayConsole.Name; } /// /// Do a reply-run, and check the given temporal property. /// This is for part-2 of the Project. /// public Judgement Satisfies(TemporalProperty phi) { this.ResetReplayState(); Judgement j = this.Run(phi); return j; } } }