public Presenter(IActor _player, IActor _computer, INameInput _nameInput, ILogScreen _logScreen, IPlayerScreen _playerScreen, IComputerScreen _computerScreen, IWinLose _winLose) { player = _player; computer = _computer; nameInput = _nameInput; logScreen = _logScreen; playerScreen = _playerScreen; computerScreen = _computerScreen; winLose = _winLose; roundCounter = 1; nameInput.NameSubmitClick += NameInput_NameSubmitClick; playerScreen.AtackHeadClick += PlayerScreen_AtackHeadClick; playerScreen.AtackBodyClick += PlayerScreen_AtackBodyClick; playerScreen.AtackLegsClick += PlayerScreen_AtackLegsClick; playerScreen.BlockHeadClick += PlayerScreen_BlockHeadClick; playerScreen.BlockBodyClick += PlayerScreen_BlockBodyClick; playerScreen.BlockLegsClick += PlayerScreen_BlockLegsClick; playerScreen.SetFirstPlayer += PlayerScreen_SetFirstPlayer; player.Block += Player_Block; player.Wound += Player_Wound; computer.Block += Computer_Block; computer.Wound += Computer_Wound; player.Death += Actor_Death; computer.Death += Actor_Death; }
private void HandleRuntimeError(SprakRuntimeException e, IComputerScreen screen) { // First, consider assertions - the error could be expected, in which case the executor can log // a success and move on. Or it could be a different error to what was expected, so that the // assertion fails. ErrorTest test = null; if (Instructions.HasCurrent) { test = Instructions.CurrentInfo.Tests?.OfType <ErrorTest>().FirstOrDefault(); } if (test != null && _runTestCommands) { if (test.ErrorName == e.Template.Name) { // Success! The error was expected. screen.SetPrintColor(Color.Green); screen.Print($"Assertion passed: error '{test.ErrorName}' occured."); Instructions.Step(); } // This name comparison is a bit awkward, but doesn't seem worth rewriting else if (e.Template.Name != nameof(Messages.AssertionFailed)) { // An error occurred as expected, but it was the wrong one! screen.SetPrintColor(Color.Red); screen.Print("Runtime error: Assertion Failed."); screen.Print($"Expected error: '{test.ErrorName}'. Found error: '{e.Template.Name}'"); screen.Print("Found error details:"); DisplayRuntimeError(e, screen); _breakRequested = true; } else { DisplayRuntimeError(e, screen); _breakRequested = true; } } else { // If there was no error test, then this is a runtime error // to display and pause on. DisplayRuntimeError(e, screen); _breakRequested = true; } screen.SetPrintColor(Color.White); }
private void InvokeTestCommands(bool pre) { if (!Instructions.HasCurrent) { return; } IEnumerable <TestCommand> commands = Instructions.CurrentInfo.Tests; if (commands == null) { return; } IComputerScreen screen = Computer.Screen; foreach (TestCommand command in commands) { if (pre != command.IsPreOp) { continue; } try { command.Invoke(_context); if (screen != null) { screen.SetPrintColor(Color.Green); screen.Print("Assertion passed: " + command.Description); screen.SetPrintColor(Color.White); } } catch (SprakRuntimeException e) { // Since operations can't be reversed as of writing this, failing // an assertion after the operation is complete leaves the execution in // in a state where it cannot try the operation and assertion again. HasUnsafeError = true; // Add a bit of context, and then let the standard runtime error // handling handle things. e.Context = "While executing assertion: " + command.Description; throw; } } }
private void DisplayRuntimeError(SprakRuntimeException e, IComputerScreen screen) { screen.SetPrintColor(Color.Red); screen.Print("Runtime Error: " + e.Template.Title); screen.Print("Detail: " + e.Template.Render(e.Args)); string sourceTrace = GetCurrentTrace(); if (sourceTrace != null) { screen.Print("At: " + sourceTrace); } screen.Print("Execution paused at error location."); screen.SetPrintColor(Color.White); }
private void ExecuteCurrent() { if (Instructions.CurrentInfo.Breakpoint) { if (_skipBreak) { _skipBreak = false; } else { _breakRequested = true; return; } } bool step = Instructions.Current.StepAfterwards; try { if (_runTestCommands) { InvokeTestCommands(pre: true); } Instructions.Current.Execute(_context); if (_runTestCommands) { InvokeTestCommands(pre: false); } if (step) { Instructions.Step(); } } catch (Exception e) { string sourceTrace = null; IComputerScreen screen = Computer.Screen; if (screen != null) { if (e is SprakRuntimeException runtimeException) { HandleRuntimeError(runtimeException, screen); } else { screen.SetPrintColor(Color.Red); screen.Print("Internal error: " + e.GetType().Name); screen.Print(e.Message); screen.Print(e.StackTrace); if (Instructions.HasCurrent) { screen.Print("Op: " + Instructions.Current.ToString()); } if (sourceTrace != null) { screen.Print("Expression: " + sourceTrace); } HasUnsafeError = true; _breakRequested = true; } } else { // Ideally the error would be reported with some sort of log // as well, but there is no logging mechanism at the moment, // so the best that can be done without an output screen is to stop. HasUnsafeError = true; _breakRequested = true; } } }