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;
}
}
}