Created
June 14, 2013 01:09
-
-
Save Bocom/5778721 to your computer and use it in GitHub Desktop.
Horrible code made through throwing stuff at the wall
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.IO; | |
| namespace NewSceneManager.Dialogue | |
| { | |
| public class DialogueEngine | |
| { | |
| Dictionary<string, DialogueBlock> labels; | |
| List<DialogueCharacter> characters; | |
| public DialogueEngine() | |
| { | |
| labels = new Dictionary<string, DialogueBlock>(); | |
| characters = new List<DialogueCharacter>(); | |
| } | |
| void ParseLabel(string labelName, List<string> labelNode) | |
| { | |
| labels.Add(labelName, DialogueBlock.ParseLabel(this, labelNode)); | |
| } | |
| public void ParseScript(string filename) | |
| { | |
| var rawFile = File.OpenText(Path.GetFullPath(filename)); | |
| bool readingLabel = false; | |
| Dictionary<string, List<string>> rawLabels = new Dictionary<string, List<string>>(); | |
| List<string> labelLines = new List<string>(); | |
| string labelName = ""; | |
| while (!rawFile.EndOfStream) | |
| { | |
| string line = rawFile.ReadLine(); | |
| if (readingLabel) | |
| { | |
| labelLines.Add(line.Trim()); | |
| if (line == "}") | |
| { | |
| readingLabel = false; | |
| rawLabels.Add(Path.GetFileNameWithoutExtension(filename)+"."+labelName, labelLines); | |
| labelName = ""; | |
| labelLines = new List<string>(); | |
| } | |
| } | |
| else | |
| { | |
| string[] parts = line.Split(' '); | |
| if (parts[0] == "label") | |
| { | |
| labelLines.Add(line.Trim()); | |
| labelName = parts[1]; | |
| readingLabel = true; | |
| } | |
| } | |
| } | |
| foreach (var label in rawLabels) | |
| { | |
| ParseLabel(label.Key, label.Value); | |
| } | |
| } | |
| internal void Run() | |
| { | |
| foreach (var label in labels) | |
| { | |
| Console.WriteLine("Running label \"" + label.Key + "\""); | |
| label.Value.RunBlock(); | |
| Console.WriteLine(); | |
| } | |
| } | |
| } | |
| class DialogueCharacter | |
| { | |
| } | |
| struct DialogueChoiceEntry | |
| { | |
| public string Text; | |
| public DialogueBlock Block; | |
| public DialogueChoiceEntry(string text, DialogueBlock block) | |
| { | |
| Text = text; | |
| Block = block; | |
| } | |
| } | |
| class DialogueChoiceBlock | |
| { | |
| public List<DialogueChoiceEntry> Choices; | |
| public DialogueChoiceBlock() | |
| { | |
| Choices = new List<DialogueChoiceEntry>(); | |
| } | |
| public static DialogueChoiceBlock Parse(DialogueEngine de, List<string> lines) | |
| { | |
| DialogueChoiceBlock dcb = new DialogueChoiceBlock(); | |
| char[] splitSpc = new char[] { ' ' }; | |
| List<string> blockLines = new List<string>(); | |
| bool inBlock = false; | |
| string text = ""; | |
| foreach (var line in lines) | |
| { | |
| string[] op = line.Split(splitSpc, 2); | |
| if (inBlock) | |
| { | |
| if (line.Contains("}")) | |
| { | |
| inBlock = false; | |
| var db = new DialogueBlock(de); | |
| db.Parse(blockLines.ToArray()); | |
| dcb.Choices.Add(new DialogueChoiceEntry(text, db)); | |
| text = ""; | |
| blockLines = new List<string>(); | |
| } | |
| else | |
| blockLines.Add(line); | |
| } | |
| if (op[0] == "choice") | |
| { | |
| int len = op[1].Length; | |
| int lidx = op[1].LastIndexOf(" "); | |
| text = op[1].Substring(0, lidx); | |
| inBlock = true; | |
| } | |
| } | |
| return dcb; | |
| } | |
| } | |
| class DialogueBlock | |
| { | |
| List<Operation> ops; | |
| List<DialogueChoiceBlock> choiceBlocks; | |
| int pc; | |
| DialogueEngine de; | |
| Operation Op { get { return ops[pc]; } } | |
| public int Length { get { return ops.Count; } } | |
| public DialogueBlock(DialogueEngine de) | |
| { | |
| this.de = de; | |
| ops = new List<Operation>(); | |
| choiceBlocks = new List<DialogueChoiceBlock>(); | |
| pc = 0; | |
| } | |
| public void RunBlock() | |
| { | |
| while (pc < ops.Count) | |
| { | |
| ops[pc].Code(); | |
| pc++; | |
| } | |
| } | |
| public void OpSay() | |
| { | |
| Console.WriteLine((Op.Args[0] == null ? "Narrator" : Op.Args[0]) + " says {0}", Op.Args[1]); | |
| } | |
| public void OpShowPortrait() | |
| { | |
| Console.WriteLine("Showing {1} {0}", Op.Args[0], Op.Args[1]); | |
| } | |
| public void OpHidePortrait() | |
| { | |
| Console.WriteLine("Hiding {0}", Op.Args[0]); | |
| } | |
| public void OpClearPortraits() | |
| { | |
| Console.WriteLine("Clearing portraits"); | |
| } | |
| public void OpGotoLabel() | |
| { | |
| Console.WriteLine("Going to label {0}", Op.Args[0]); | |
| } | |
| public void OpRunChoiceBlock() | |
| { | |
| var dcb = choiceBlocks[(int)Op.Args[0]]; | |
| Console.WriteLine("Choice block:"); | |
| dcb.Choices.ForEach((x) => { Console.WriteLine("\t" + x.Text); x.Block.RunBlock(); }); | |
| } | |
| public void OpSelection() | |
| { | |
| Console.WriteLine("Came upon a selection"); | |
| Conditional cond = (Conditional)Op.Args[0]; | |
| bool hasElse = (bool)Op.Args[2]; | |
| bool res = cond.Run(); | |
| if (res) | |
| { | |
| Console.WriteLine("The selection returned true!"); | |
| ((DialogueBlock)Op.Args[1]).RunBlock(); | |
| if (hasElse) | |
| pc++; | |
| } | |
| else | |
| { | |
| Console.WriteLine("The selection returned false!"); | |
| } | |
| } | |
| public void OpRunBlock() | |
| { | |
| Console.WriteLine("Running a block"); | |
| ((DialogueBlock)Op.Args[0]).RunBlock(); | |
| } | |
| public static DialogueBlock Parse(DialogueEngine de, string[] blockLines) | |
| { | |
| DialogueBlock ret = new DialogueBlock(de); | |
| ret.Parse(blockLines); | |
| return ret; | |
| } | |
| public void Parse(string[] blockLines) | |
| { | |
| int parentBlockDepth = 0; | |
| int blockDepth = 0; | |
| bool parsingChoiceBlock = false; | |
| bool parsingSelectionBlock = false; | |
| bool readingIf = false; | |
| bool readingElse = false; | |
| bool hasElse = false; | |
| List<string> choiceLines = new List<string>(); | |
| List<string> selectionLines = new List<string>(); | |
| string condLine = ""; | |
| char[] splitSpc = new char[] { ' ' }; | |
| int choiceIndex = 0; | |
| //Console.WriteLine(labelNode[0]); | |
| //foreach (var node in blockLines) | |
| for (int i = 0; i < blockLines.Length; i++) | |
| { | |
| string node = blockLines[i]; | |
| if (node.Contains("}")) | |
| blockDepth--; | |
| if (node.Contains("{")) | |
| blockDepth++; | |
| if (parsingSelectionBlock) | |
| { | |
| if (blockDepth > parentBlockDepth) | |
| selectionLines.Add(node); | |
| else if (blockDepth <= parentBlockDepth) | |
| { | |
| parentBlockDepth = 0; | |
| var dcb = DialogueBlock.Parse(de, selectionLines.ToArray()); | |
| selectionLines.Clear(); | |
| if (readingIf) | |
| { | |
| //parsingSelectionBlock = false; | |
| readingIf = false; | |
| var next = blockLines[i + 1].Split(' ')[0]; | |
| if (next == "else") | |
| { | |
| hasElse = true; | |
| } | |
| Conditional cond = Conditional.Build(condLine); | |
| ops.Add(new Operation(OpSelection, cond, dcb, hasElse)); | |
| } | |
| else if (readingElse) | |
| { | |
| readingElse = false; | |
| ops.Add(new Operation(OpRunBlock, dcb)); | |
| } | |
| parsingSelectionBlock = false; | |
| } | |
| continue; | |
| } | |
| if (parsingChoiceBlock) | |
| { | |
| if (blockDepth > parentBlockDepth) | |
| { | |
| choiceLines.Add(node); | |
| } | |
| else if (blockDepth <= parentBlockDepth) | |
| { | |
| parsingChoiceBlock = false; | |
| parentBlockDepth = 0; | |
| var dcb = DialogueChoiceBlock.Parse(de, choiceLines); | |
| choiceBlocks.Add(dcb); | |
| ops.Add(new Operation(OpRunChoiceBlock, choiceIndex)); | |
| choiceLines.Clear(); | |
| choiceIndex++; | |
| } | |
| continue; | |
| } | |
| string[] op = node.Split(splitSpc, 2); | |
| if (op[0] == "say") | |
| { | |
| // Shows a line of dialogue as either character dialogue or narration | |
| if (op[1][0] != '"') | |
| { | |
| // Character defined | |
| string[] args = op[1].Split(splitSpc, 2); | |
| ops.Add(new Operation(OpSay, args)); | |
| } | |
| else | |
| { | |
| // Narration | |
| ops.Add(new Operation(OpSay, null, op[1])); | |
| } | |
| } | |
| else if (op[0] == "show") | |
| { | |
| // Show a character portrait. | |
| // Replace a character's portrait. | |
| string[] args = op[1].Split(splitSpc); | |
| // Here we need a check to see if a character is already shown. | |
| if (args.Length > 1) | |
| { | |
| // State included | |
| ops.Add(new Operation(OpShowPortrait, args)); | |
| } | |
| else | |
| { | |
| // Show default | |
| ops.Add(new Operation(OpShowPortrait, args[0], "Default")); | |
| } | |
| } | |
| else if (op[0] == "hide") | |
| { | |
| // Hide op[1] | |
| ops.Add(new Operation(OpHidePortrait, op[1])); | |
| } | |
| else if (op[0] == "goto") | |
| { | |
| // Go to another label | |
| // TODO: Specialize this probably | |
| ops.Add(new Operation(OpGotoLabel, op[1])); | |
| } | |
| else if (op[0] == "clear") | |
| { | |
| // Clear existing portraits | |
| ops.Add(new Operation(OpClearPortraits)); | |
| } | |
| else if (op[0] == "execute") | |
| { | |
| // Execute a script file | |
| Console.WriteLine("execute is not handled."); | |
| } | |
| else if (op[0] == "choices") | |
| { | |
| // Defines a choices block | |
| parentBlockDepth = blockDepth - 1; | |
| parsingChoiceBlock = true; | |
| } | |
| else if (op[0] == "sets") | |
| { | |
| // Change a switch's value | |
| Console.WriteLine("sets is not handled."); | |
| } | |
| else if (op[0] == "setv") | |
| { | |
| // Change a variable's value | |
| Console.WriteLine("setv is not handled."); | |
| } | |
| else if (op[0] == "if" || op[0] == "elif") | |
| { | |
| // Selection | |
| parentBlockDepth = blockDepth - 1; | |
| var si = node.IndexOf("(") + 1; | |
| var ei = node.LastIndexOf(")") - si; | |
| condLine = node.Substring(si, ei); | |
| parsingSelectionBlock = true; | |
| readingIf = true; | |
| } | |
| //else if (op[0] == "elif") | |
| //{ | |
| // // Extra selection | |
| // Console.WriteLine("elif is not handled."); | |
| // // Oh shit! | |
| //} | |
| else if (op[0] == "else") | |
| { | |
| // Even more selection | |
| parentBlockDepth = blockDepth - 1; | |
| parsingSelectionBlock = true; | |
| readingElse = true; | |
| } | |
| } | |
| //Console.WriteLine(labelNode[labelNode.Count - 1]); | |
| if (blockDepth != 0) | |
| throw new Exception("blockDepth"); | |
| } | |
| public static DialogueBlock ParseLabel(DialogueEngine de, List<string> labelLines) | |
| { | |
| DialogueBlock dl = new DialogueBlock(de); | |
| string[] labelContents = labelLines.GetRange(1, labelLines.Count - 2).ToArray(); | |
| dl.Parse(labelContents); | |
| return dl; | |
| } | |
| } | |
| class CondFuncs | |
| { | |
| public static bool Equals(object[] args) | |
| { | |
| return args[0].Equals(args[1]); | |
| } | |
| public static bool NotEquals(object[] args) | |
| { | |
| return !args[0].Equals(args[1]); | |
| } | |
| public static bool Greater(object[] args) | |
| { | |
| return (int)args[0] > (int)args[1]; | |
| } | |
| public static bool GreaterEquals(object[] args) | |
| { | |
| return (int)args[0] >= (int)args[1]; | |
| } | |
| public static bool Lesser(object[] args) | |
| { | |
| return (int)args[0] < (int)args[1]; | |
| } | |
| public static bool LesserEquals(object[] args) | |
| { | |
| return (int)args[0] <= (int)args[1]; | |
| } | |
| public static bool And(object[] args) | |
| { | |
| return And((Conditional)args[0], (Conditional)args[1]); | |
| } | |
| public static bool And(Conditional arg1, Conditional arg2) | |
| { | |
| var a1 = arg1.Run(); | |
| if (!a1) | |
| return false; | |
| return a1 && arg2.Run(); | |
| } | |
| public static bool Or(object[] args) | |
| { | |
| return Or((Conditional)args[0], (Conditional)args[1]); | |
| } | |
| public static bool Or(Conditional arg1, Conditional arg2) | |
| { | |
| return arg1.Run() || arg2.Run(); | |
| } | |
| public static bool HasItem(object[] args) | |
| { | |
| return HasItem(args[0]); | |
| } | |
| // TODO: Make HasItem return actual value. | |
| public static bool HasItem(object arg) | |
| { | |
| return true; | |
| } | |
| public static bool GetSwitch(object[] args) | |
| { | |
| return GetSwitch(args[0]); | |
| } | |
| // TODO: Make GetSwitch return actual value. | |
| public static bool GetSwitch(object arg) | |
| { | |
| return false; | |
| } | |
| public static object GetVar(object[] args) | |
| { | |
| return GetVar(args[0]); | |
| } | |
| // TODO: Make GetVar return actual value. | |
| public static object GetVar(object arg) | |
| { | |
| return 1; | |
| } | |
| } | |
| struct Conditional | |
| { | |
| public Func<object[], bool> Func; | |
| public object[] Args; | |
| public Conditional(Func<object[], bool> func, params object[] args) | |
| { | |
| Func = func; | |
| Args = args; | |
| } | |
| public void SetArguments(params object[] args) | |
| { | |
| Args = args; | |
| } | |
| public static Conditional Build(string inp) | |
| { | |
| // TODO: Temporary | |
| Conditional cond = new Conditional(); | |
| Conditional nested = new Conditional(); | |
| if (inp.Contains("(")) | |
| { | |
| var si = inp.IndexOf("(") + 1; | |
| var ei = inp.LastIndexOf(")") - si; | |
| var condLine = inp.Substring(si, ei); | |
| // FIXME: needs a check for parenthesis that are on the left side too. | |
| inp = inp.Substring(0, si - 1) + "(nested)"; | |
| nested = Conditional.Build(condLine); | |
| } | |
| List<Conditional> conds = new List<Conditional>(); | |
| var aksjd = inp.Split(' '); | |
| bool andor1 = false; | |
| bool andor2 = false; | |
| Conditional andorCond = new Conditional(); | |
| for (int i = 0; i < aksjd.Length; i++) | |
| { | |
| var item = aksjd[i]; | |
| var c = new Conditional(); | |
| if (andor1) | |
| andor2 = true; | |
| if (item == "has_item") | |
| { | |
| c.Func = CondFuncs.HasItem; | |
| var itemName = aksjd[++i]; | |
| c.SetArguments(itemName); | |
| } | |
| else if (item == "switch") | |
| { | |
| c.Func = CondFuncs.GetSwitch; | |
| var switchName = aksjd[++i]; | |
| c.SetArguments(switchName); | |
| } | |
| else if (item == "var") | |
| { | |
| var varName = aksjd[++i]; | |
| var op = aksjd[++i]; | |
| var val = aksjd[++i]; | |
| switch (op) | |
| { | |
| case ">": | |
| c.Func = CondFuncs.Greater; | |
| break; | |
| case "<": | |
| c.Func = CondFuncs.Lesser; | |
| break; | |
| case ">=": | |
| c.Func = CondFuncs.GreaterEquals; | |
| break; | |
| case "<=": | |
| c.Func = CondFuncs.LesserEquals; | |
| break; | |
| default: | |
| case "==": | |
| c.Func = CondFuncs.Equals; | |
| break; | |
| case "!=": | |
| c.Func = CondFuncs.NotEquals; | |
| break; | |
| } | |
| // TODO: THIS IS WRONG | |
| c.SetArguments( | |
| (int)CondFuncs.GetVar(varName), | |
| int.Parse(val)); | |
| } | |
| else if (item == "and") | |
| { | |
| c.Func = CondFuncs.And; | |
| var c1 = conds[conds.Count - 1]; | |
| conds.RemoveAt(conds.Count - 1); | |
| c.SetArguments(c1, null); | |
| andorCond = c; | |
| andor1 = true; | |
| } | |
| else if (item == "or") | |
| { | |
| c.Func = CondFuncs.Or; | |
| var c1 = conds[conds.Count - 1]; | |
| conds.RemoveAt(conds.Count - 1); | |
| c.SetArguments(c1, null); | |
| andorCond = c; | |
| andor1 = true; | |
| } | |
| else if (item == "(nested)") | |
| { | |
| c = nested; | |
| } | |
| if (andor2) | |
| { | |
| andor2 = false; | |
| andorCond.Args[1] = c; | |
| conds.Add(andorCond); | |
| andorCond = new Conditional(); | |
| } | |
| else if (!andor1) | |
| { | |
| conds.Add(c); | |
| } | |
| } | |
| cond = conds[0]; | |
| return cond; | |
| } | |
| public bool Run() | |
| { | |
| return Func(Args); | |
| } | |
| } | |
| struct Operation | |
| { | |
| public Action Code; | |
| public object[] Args; | |
| public Operation(Action code, params object[] args) | |
| { | |
| Code = code; | |
| Args = args; | |
| } | |
| public override string ToString() | |
| { | |
| return "Op("+Code.ToString()+", "+Args.ToString()+")"; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment