GetString() 공개 메소드

public GetString ( string key ) : string
key string
리턴 string
예제 #1
0
		internal void RunInstruction(Instruction i) {
			switch (i.operation) {
			case ByteCode.Label:
				
				// No-op; used as a destination for JumpTo and Jump.
				break;
			case ByteCode.JumpTo:

				// Jumps to a named label
				state.programCounter = FindInstructionPointForLabel ((string)i.operandA);

				break;
			case ByteCode.RunLine:

				// Looks up a string from the string table and
				// passes it to the client as a line

				var lineText = program.GetString ((int)i.operandA);

				lineHandler (new Dialogue.LineResult (lineText));
				
				break;
			case ByteCode.RunCommand:

				// Passes a string to the client as a custom command
				commandHandler (
					new Dialogue.CommandResult ((string)i.operandA)
				);

				break;
			case ByteCode.PushString:

				// Pushes a string value onto the stack; the operand
				// is an index into the string table, so that's looked up
				// first.
				state.PushValue (program.GetString ((int)i.operandA));

				break;
			case ByteCode.PushNumber:

				// Pushes a number onto the stack.
				state.PushValue (Convert.ToSingle(i.operandA));

				break;
			case ByteCode.PushBool:

				// Pushes a boolean value onto the stack.
				state.PushValue (Convert.ToBoolean(i.operandA));

				break;
			case ByteCode.PushNull:

				// Pushes a null value onto the stack.
				state.PushValue (new Value ());

				break;
			case ByteCode.JumpIfFalse:

				// Jumps to a named label if the value on the top of the stack
				// evaluates to the boolean value 'false'.
				if (state.PeekValue ().AsBool == false) {
					state.programCounter = FindInstructionPointForLabel ((string)i.operandA);
				}
				break;
			
			case ByteCode.Jump:

				// Jumps to a label whose name is on the stack.
				var jumpDestination = state.PeekValue ().AsString;
				state.programCounter = FindInstructionPointForLabel (jumpDestination);

				break;
			
			case ByteCode.Pop:

				// Pops a value from the stack.
				state.PopValue ();
				break;

			case ByteCode.CallFunc:

				// Call a function, whose parameters are expected to
				// be on the stack. Pushes the function's return value,
				// if it returns one.
				var functionName = (string)i.operandA;
				var function = dialogue.library.GetFunction (functionName);
				{

					var paramCount = function.paramCount;

					// If this function takes "-1" parameters, it is variadic.
					// Expect the compiler to have placed the number of parameters
					// actually passed at the top of the stack.
					if (paramCount == -1) {
						paramCount = (int)state.PopValue ().AsNumber;
					}

					// Get the parameters, which were pushed in reverse
					Value[] parameters = new Value[paramCount];
					for (int param = paramCount - 1; param >= 0; param--) {
						parameters [param] = state.PopValue ();
					}

					// Invoke the function
					var result = function.InvokeWithArray (parameters);

					// If the function returns a value, push it
					if (function.returnsValue) {
						state.PushValue (result);
					}
				}

				break;
			case ByteCode.PushVariable:

				// Get the contents of a variable, push that onto the stack.
				var variableName = (string)i.operandA;
				var loadedValue = dialogue.continuity.GetNumber (variableName);
				state.PushValue (loadedValue);

				break;
			case ByteCode.StoreVariable:

				// Store the top value on the stack in a variable.
				var topValue = state.PeekValue ();
				var destinationVariableName = (string)i.operandA;


				// TODO: Handle storing values other than numbers
				dialogue.continuity.SetNumber (destinationVariableName, topValue.AsNumber);

				break;
			case ByteCode.Stop:

				// Immediately stop execution, and report that fact.
				executionState = ExecutionState.Stopped;
				nodeCompleteHandler (new Dialogue.NodeCompleteResult (null));

				break;
			case ByteCode.RunNode:

				string nodeName;

				if (string.IsNullOrEmpty((string) i.operandA)) {
					// Get a string from the stack, and jump to a node with that name.
					 nodeName = state.PeekValue ().AsString;
				} else {
					// jump straight to the node
					nodeName = (string)i.operandA;
				}

				nodeCompleteHandler (new Dialogue.NodeCompleteResult (nodeName));
				SetNode (nodeName);



				break;
			case ByteCode.AddOption:

				// Add an option to the current state.
				state.currentOptions.Add (new KeyValuePair<int, string> ((int)i.operandA, (string)i.operandB));


				break;
			case ByteCode.ShowOptions:

				// If we have no options to show, immediately stop.
				if (state.currentOptions.Count == 0) {
					executionState = ExecutionState.Stopped;
					nodeCompleteHandler (new Dialogue.NodeCompleteResult (null));
					break;
				}

				// If we have a single option, and it has no label, select it immediately and continue
				// execution
				if (state.currentOptions.Count == 1 && state.currentOptions[0].Key == -1) {
					var destinationNode = state.currentOptions[0].Value;
					state.PushValue(destinationNode);
					state.currentOptions.Clear();
					break;
				}

				if (dialogue.continuity.GetNumber(SpecialVariables.ShuffleOptions) != 0.0f) {
					// Shuffle the dialog options if needed
					var r = new Random();
					var n = state.currentOptions.Count;
					for (int opt1 = 0; opt1 < n; opt1++) {
						int opt2 = opt1 + (int)(r.NextDouble () * (n - opt1)); // r.Next(0, state.currentOptions.Count-1);
						var temp = state.currentOptions [opt2];
						state.currentOptions [opt2] = state.currentOptions [opt1];
						state.currentOptions [opt1] = temp;
					}
				}

				// Otherwise, present the list of options to the user and let them pick
				var optionStrings = new List<string> ();
			
				foreach (var option in state.currentOptions) {
					optionStrings.Add (program.GetString (option.Key));
				}



				// We can't continue until our client tell us which option to pick
				executionState = ExecutionState.WaitingOnOptionSelection;

				// Pass the options set to the client, as well as a delegate for them to call when the
				// user has made a selection
				optionsHandler (new Dialogue.OptionSetResult (optionStrings, delegate (int selectedOption) {

					// we now know what number option was selected; push the corresponding node name
					// to the stack
					var destinationNode = state.currentOptions[selectedOption].Value;
					state.PushValue(destinationNode);

					// We no longer need the accumulated list of options; clear it so that it's
					// ready for the next one
					state.currentOptions.Clear();

					// We can now also keep running
					executionState = ExecutionState.Running;

				}));

				break;
			default:

				// Whoa, no idea what bytecode this is. Stop the program
				// and throw an exception.
				executionState = ExecutionState.Stopped;
				throw new ArgumentOutOfRangeException ();
			}
		}
예제 #2
0
        public string ToString(Program p, Library l)
        {
            // Labels are easy: just dump out the name
            if (operation == ByteCode.Label)
            {
                return(operandA + ":");
            }

            // Convert the operands to strings
            var opAString = operandA != null?operandA.ToString() : "";

            var opBString = operandB != null?operandB.ToString() : "";

            // Generate a comment, if the instruction warrants it
            string comment = "";

            // Stack manipulation comments
            var pops   = 0;
            var pushes = 0;

            switch (operation)
            {
            // These operations all push a single value to the stack
            case ByteCode.PushBool:
            case ByteCode.PushNull:
            case ByteCode.PushNumber:
            case ByteCode.PushString:
            case ByteCode.PushVariable:
            case ByteCode.ShowOptions:
                pushes = 1;
                break;

            // Functions pop 0 or more values, and pop 0 or 1
            case ByteCode.CallFunc:
                var function = l.GetFunction((string)operandA);

                pops = function.paramCount;

                if (function.returnsValue)
                {
                    pushes = 1;
                }


                break;

            // Pop always pops a single value
            case ByteCode.Pop:
                pops = 1;
                break;

            // Switching to a different node will always clear the stack
            case ByteCode.RunNode:
                comment += "Clears stack";
                break;
            }

            // If we had any pushes or pops, report them

            if (pops > 0 && pushes > 0)
            {
                comment += string.Format("Pops {0}, Pushes {1}", pops, pushes);
            }
            else if (pops > 0)
            {
                comment += string.Format("Pops {0}", pops);
            }
            else if (pushes > 0)
            {
                comment += string.Format("Pushes {0}", pushes);
            }

            // String lookup comments
            switch (operation)
            {
            case ByteCode.PushString:
            case ByteCode.RunLine:
            case ByteCode.AddOption:

                // Add the string for this option, if it has one
                if ((string)operandA != null)
                {
                    var text = p.GetString((string)operandA);
                    comment += string.Format("\"{0}\"", text);
                }

                break;
            }

            if (comment != "")
            {
                comment = "; " + comment;
            }

            return(string.Format("{0,-15} {1,-10} {2,-10} {3, -10}", operation.ToString(), opAString, opBString, comment));
        }
예제 #3
0
        public string ToString(Program p, Library l)
        {
            // Labels are easy: just dump out the name
            if (operation == ByteCode.Label) {
                return operandA + ":";
            }

            // Convert the operands to strings
            var opAString = operandA != null ? operandA.ToString () : "";
            var opBString = operandB != null ? operandB.ToString () : "";

            // Generate a comment, if the instruction warrants it
            string comment = "";

            // Stack manipulation comments
            var pops = 0;
            var pushes = 0;

            switch (operation) {

            // These operations all push a single value to the stack
            case ByteCode.PushBool:
            case ByteCode.PushNull:
            case ByteCode.PushNumber:
            case ByteCode.PushString:
            case ByteCode.PushVariable:
            case ByteCode.ShowOptions:
                pushes = 1;
                break;

            // Functions pop 0 or more values, and pop 0 or 1
            case ByteCode.CallFunc:
                var function = l.GetFunction ((string)operandA);

                pops = function.paramCount;

                if (function.returnsValue)
                    pushes = 1;

                break;

            // Pop always pops a single value
            case ByteCode.Pop:
                pops = 1;
                break;

            // Switching to a different node will always clear the stack
            case ByteCode.RunNode:
                comment += "Clears stack";
                break;
            }

            // If we had any pushes or pops, report them

            if (pops > 0 && pushes > 0)
                comment += string.Format ("Pops {0}, Pushes {1}", pops, pushes);
            else if (pops > 0)
                comment += string.Format ("Pops {0}", pops);
            else if (pushes > 0)
                comment += string.Format ("Pushes {0}", pushes);

            // String lookup comments
            switch (operation) {
            case ByteCode.PushString:
            case ByteCode.RunLine:
            case ByteCode.AddOption:

                // Add the string for this option, if it has one
                if ((string)operandA != null) {
                    var text = p.GetString((string)operandA);
                    comment += string.Format ("\"{0}\"", text);
                }

                break;

            }

            if (comment != "") {
                comment = "; " + comment;
            }

            return string.Format ("{0,-15} {1,-10} {2,-10} {3, -10}", operation.ToString (), opAString, opBString, comment);
        }
예제 #4
0
        internal void RunInstruction(Instruction i)
        {
            switch (i.operation)
            {
            case ByteCode.Label:
                /// - Label

                /** No-op, used as a destination for JumpTo and Jump.
                 */
                break;

            case ByteCode.JumpTo:
                /// - JumpTo

                /** Jumps to a named label
                 */
                state.programCounter = FindInstructionPointForLabel((string)i.operandA);

                break;

            case ByteCode.RunLine:
                /// - RunLine

                /** Looks up a string from the string table and
                 *  passes it to the client as a line
                 */
                var lineText = program.GetString((string)i.operandA);

                if (lineText == null)
                {
                    dialogue.LogErrorMessage("No loaded string table includes line " + i.operandA);
                    break;
                }

                lineHandler(new Dialogue.LineResult(lineText));

                break;

            case ByteCode.RunCommand:
                /// - RunCommand

                /** Passes a string to the client as a custom command
                 */
                commandHandler(
                    new Dialogue.CommandResult((string)i.operandA)
                    );

                break;

            case ByteCode.PushString:
                /// - PushString

                /** Pushes a string value onto the stack. The operand is an index into
                 *  the string table, so that's looked up first.
                 */
                state.PushValue(program.GetString((string)i.operandA));

                break;

            case ByteCode.PushNumber:
                /// - PushNumber

                /** Pushes a number onto the stack.
                 */
                state.PushValue(Convert.ToSingle(i.operandA));

                break;

            case ByteCode.PushBool:
                /// - PushBool

                /** Pushes a boolean value onto the stack.
                 */
                state.PushValue(Convert.ToBoolean(i.operandA));

                break;

            case ByteCode.PushNull:
                /// - PushNull

                /** Pushes a null value onto the stack.
                 */
                state.PushValue(Value.NULL);

                break;

            case ByteCode.JumpIfFalse:
                /// - JumpIfFalse

                /** Jumps to a named label if the value on the top of the stack
                 *  evaluates to the boolean value 'false'.
                 */
                if (state.PeekValue().AsBool == false)
                {
                    state.programCounter = FindInstructionPointForLabel((string)i.operandA);
                }
                break;

            case ByteCode.Jump:
                /// - Jump

                /** Jumps to a label whose name is on the stack.
                 */
                var jumpDestination = state.PeekValue().AsString;
                state.programCounter = FindInstructionPointForLabel(jumpDestination);

                break;

            case ByteCode.Pop:
                /// - Pop

                /** Pops a value from the stack.
                 */
                state.PopValue();
                break;

            case ByteCode.CallFunc:
                /// - CallFunc

                /** Call a function, whose parameters are expected to
                 *  be on the stack. Pushes the function's return value,
                 *  if it returns one.
                 */
                var functionName = (string)i.operandA;

                var function = dialogue.library.GetFunction(functionName);
                {
                    var paramCount = function.paramCount;

                    // If this function takes "-1" parameters, it is variadic.
                    // Expect the compiler to have placed the number of parameters
                    // actually passed at the top of the stack.
                    if (paramCount == -1)
                    {
                        paramCount = (int)state.PopValue().AsNumber;
                    }

                    Value result;
                    if (paramCount == 0)
                    {
                        result = function.Invoke();
                    }
                    else
                    {
                        // Get the parameters, which were pushed in reverse
                        Value[] parameters = new Value[paramCount];
                        for (int param = paramCount - 1; param >= 0; param--)
                        {
                            parameters [param] = state.PopValue();
                        }

                        // Invoke the function
                        result = function.InvokeWithArray(parameters);
                    }

                    // If the function returns a value, push it
                    if (function.returnsValue)
                    {
                        state.PushValue(result);
                    }
                }

                break;

            case ByteCode.PushVariable:
                /// - PushVariable

                /** Get the contents of a variable, push that onto the stack.
                 */
                var variableName = (string)i.operandA;
                var loadedValue  = dialogue.continuity.GetValue(variableName);
                state.PushValue(loadedValue);

                break;

            case ByteCode.StoreVariable:
                /// - StoreVariable

                /** Store the top value on the stack in a variable.
                 */
                var topValue = state.PeekValue();
                var destinationVariableName = (string)i.operandA;
                dialogue.continuity.SetValue(destinationVariableName, topValue);

                break;

            case ByteCode.Stop:
                /// - Stop

                /** Immediately stop execution, and report that fact.
                 */
                nodeCompleteHandler(new Dialogue.NodeCompleteResult(null));
                executionState = ExecutionState.Stopped;

                break;

            case ByteCode.RunNode:
                /// - RunNode

                /** Run a node
                 */
                string nodeName;

                if (string.IsNullOrEmpty((string)i.operandA))
                {
                    // Get a string from the stack, and jump to a node with that name.
                    nodeName = state.PeekValue().AsString;
                }
                else
                {
                    // jump straight to the node
                    nodeName = (string)i.operandA;
                }

                nodeCompleteHandler(new Dialogue.NodeCompleteResult(nodeName));
                SetNode(nodeName);

                break;

            case ByteCode.AddOption:
                /// - AddOption

                /** Add an option to the current state.
                 */
                state.currentOptions.Add(new KeyValuePair <string, string> ((string)i.operandA, (string)i.operandB));

                break;

            case ByteCode.ShowOptions:
                /// - ShowOptions

                /** If we have no options to show, immediately stop.
                 */
                if (state.currentOptions.Count == 0)
                {
                    nodeCompleteHandler(new Dialogue.NodeCompleteResult(null));
                    executionState = ExecutionState.Stopped;
                    break;
                }

                /** If we have a single option, and it has no label, select it immediately and continue execution
                 */
                if (state.currentOptions.Count == 1 && state.currentOptions[0].Key == null)
                {
                    var destinationNode = state.currentOptions[0].Value;
                    state.PushValue(destinationNode);
                    state.currentOptions.Clear();
                    break;
                }

                if (dialogue.continuity.GetValue(SpecialVariables.ShuffleOptions).AsBool)
                {
                    // Shuffle the dialog options if needed
                    var n = state.currentOptions.Count;
                    for (int opt1 = 0; opt1 < n; opt1++)
                    {
                        int opt2 = opt1 + (int)(random.NextDouble() * (n - opt1));  // r.Next(0, state.currentOptions.Count-1);
                        var temp = state.currentOptions [opt2];
                        state.currentOptions [opt2] = state.currentOptions [opt1];
                        state.currentOptions [opt1] = temp;
                    }
                }

                // Otherwise, present the list of options to the user and let them pick
                var optionStrings = new List <string> ();

                foreach (var option in state.currentOptions)
                {
                    optionStrings.Add(program.GetString(option.Key));
                }

                // We can't continue until our client tell us which option to pick
                executionState = ExecutionState.WaitingOnOptionSelection;

                // Pass the options set to the client, as well as a delegate for them to call when the
                // user has made a selection
                optionsHandler(new Dialogue.OptionSetResult(optionStrings, delegate(int selectedOption) {
                    // we now know what number option was selected; push the corresponding node name
                    // to the stack
                    var destinationNode = state.currentOptions[selectedOption].Value;
                    state.PushValue(destinationNode);

                    // We no longer need the accumulated list of options; clear it so that it's
                    // ready for the next one
                    state.currentOptions.Clear();

                    // We can now also keep running
                    executionState = ExecutionState.Running;
                }));

                break;

            case ByteCode.Concat:
                /// = Concat

                /** Pop two items off the stack, concat them, and push the result onto the stack.
                 */
            {
                var second = state.PopValue();
                var first  = state.PopValue();
                state.PushValue(first.AsString + second.AsString);
            }
            break;

            case ByteCode.RunLineFromStack:
                /// - RunLineFromStack

                /** Pop a string from the stack and pass to client as a line.
                 */
                lineHandler(new Dialogue.LineResult(state.PopValue().AsString));

                break;

            default:
                /// - default

                /** Whoa, no idea what bytecode this is. Stop the program
                 * and throw an exception.
                 */
                executionState = ExecutionState.Stopped;
                throw new ArgumentOutOfRangeException();
            }
        }