public void GetIntegerReturnsTheNextIntegerInTheScriptData()
        {
            SetUpScriptData(bw =>
            {
                bw.Write(65);
                bw.Write(3);
                bw.Write(14);
            });

            _programCounter.GetInteger().Should().Be(65);
            _programCounter.GetInteger().Should().Be(3);
            _programCounter.GetInteger().Should().Be(14);
        }
        void MoveScriptPointerIfStackValueIsZero(IProgramCounter programCounter)
        {
            var distance = programCounter.GetInteger();

            if (_stack.PopValue() == 0)
            {
                programCounter.MoveScriptPointer(distance);
            }
        }
        void ProcessFnRoutine(IProgramCounter programCounter, IVariableManager localVariables)
        {
            var parameterCount = programCounter.GetInteger();
            var fnRoutineName  = programCounter.GetNullTerminatedString();

            var parameters = GetStackParametersIfRequired(parameterCount);

            var result = _fnRoutinesCaller.CallFnRoutine(localVariables, fnRoutineName, parameters);

            _stack.PushValue(result);
        }
        bool ProcessDropSkipPauseNotZero(IProgramCounter programCounter)
        {
            var distance = programCounter.GetInteger();
            var value    = _stack.PopValue();

            switch (value)
            {
            case (int)ScriptReturn.Continue:
                return(true);

            case (int)ScriptReturn.PauseRepeat:
                programCounter.MoveScriptPointer(distance - 4);
                return(false);

            case (int)ScriptReturn.Pause:
                return(false);
            }

            return(true);
        }
        bool RunScriptCommand(IProgramCounter programCounter, IVariableManager localVariables)
        {
            if (programCounter.Eof)
            {
                throw new Exception($"Unexpected end of script found in '{programCounter.GetScriptName()}'");
            }

            var command = programCounter.GetCommand();

            switch ((ScriptToken)command)
            {
            case ScriptToken.PushIntValue:
                _stack.PushValue(programCounter.GetInteger());
                break;

            case ScriptToken.PushStringValue:
                _stack.PushValue(programCounter.GetNullTerminatedString());
                break;

            case ScriptToken.PushGlobalVariable:     //  4
                PushGlobalVariableOnToTheStack(programCounter);
                break;

            case ScriptToken.PopGlobalVariable:     //  5
                SetGlobalVariableToBottomValueOfStack(programCounter);
                break;

            case ScriptToken.Jfalse:     //  6
                MoveScriptPointerIfStackValueIsZero(programCounter);
                break;

            case ScriptToken.Jtrue:     //  7
                MoveScriptPointerIfStackValueIsNotZero(programCounter);
                break;

            case ScriptToken.Jall:     //  8
                MoveScriptPointerAlways(programCounter);
                break;

            case ScriptToken.Add:     //  9
                _stack.Add();
                break;

            case ScriptToken.Subtract:     //  10
                _stack.Subtract();
                break;

            case ScriptToken.Multiply:     //  11
                _stack.Multiply();
                break;

            case ScriptToken.Divide:     //  12
                _stack.Divide();
                break;

            case ScriptToken.Negate:     //  13
                _stack.Negate();
                break;

            case ScriptToken.LogicalNot:     //  14
                _stack.LogicalNot();
                break;

            case ScriptToken.Lt:     //  15
                _stack.Lt();
                break;

            case ScriptToken.Gt:     //  16
                _stack.Gt();
                break;

            case ScriptToken.Lte:     //  17
                _stack.Lte();
                break;

            case ScriptToken.Gte:     //  18
                _stack.Gte();
                break;

            case ScriptToken.VariableEquals:     //  19
                _stack.VariableEquals();
                break;

            case ScriptToken.LogicalAnd:     //  20
                _stack.LogicalAnd();
                break;

            case ScriptToken.LogicalOr:     //  21
                _stack.LogicalOr();
                break;

            case ScriptToken.CallFnRoutine:     //  22
                ProcessFnRoutine(programCounter, localVariables);
                break;

            case ScriptToken.DropStackValue:     //  23
                return(_stack.PopValue() == 0);

            case ScriptToken.EndScript:     //  24
                return(false);

            case ScriptToken.DropSkipPauseNotZero:     //  25
                return(ProcessDropSkipPauseNotZero(programCounter));

            case ScriptToken.PauseScript:     // 26
                return(false);

            case ScriptToken.PushLocalVariable:     //  27
                PushLocalVariableOnToTheStack(programCounter, localVariables);
                break;

            case ScriptToken.PopLocalVariable:     //  28
                SetLocalVariableToBottomValueOfStack(programCounter, localVariables);
                break;

            default:
                throw new InvalidOperationException($"Invalid Script Command {command}");
            }

            return(true);
        }
        void MoveScriptPointerAlways(IProgramCounter programCounter)
        {
            var distance = programCounter.GetInteger();

            programCounter.MoveScriptPointer(distance);
        }