using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TheSlimesJourney { public static class ScriptHandler { private static Character definingEnemy; private static List definingEnemyList; private static List evaluationStack = new List(); private static int scopeDepth = 0; private static UI ui; public static void SetUI(UI newUI) { ui = newUI; } public static void HandleScript(string[] script, Item source = null) { evaluationStack.Clear(); scopeDepth = 0; for (int i = 0; i < script.Length; i++) { string currentLine = script[i]; string[] split = currentLine.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (split.Length > 0) { string baseCommand = split[0]; string argument = Utils.RBQ(currentLine); switch (baseCommand) { case "addenemy": definingEnemy = new Character(); ParseEnemy(script, i); definingEnemyList.Add(definingEnemy); break; case "additem": Game.itemsToBeHandled.Add(new Item(argument)); break; case "addstrength": Game.player.strength += Convert.ToInt32(argument); break; case "adddefense": Game.player.defense += Convert.ToInt32(argument); break; case "addhealth": Game.player.health += Convert.ToInt32(argument); Game.player.maxHealth += Convert.ToInt32(argument); break; case "ambushed": Game.ambushed = true; break; case "call": ScriptHandler.HandleScript(new Event(argument).script); break; case "clearenemies": definingEnemyList = new List(); break; case "combat": Game.EnterCombat(definingEnemyList); break; case "damage": Game.player.health -= Convert.ToInt32(argument); break; case "deathcheck": if (Game.DeathCheck()) return; break; case "destroy": if (Game.player.inventory.Contains(source)) Game.player.inventory.Remove(source); break; case "equip": if (source.equipped) { ui.Print("You unequip the #purple#" + source.name + "."); ui.Pause(); HandleScript(source.unequipScript, source); source.equipped = false; } else { ui.Print("You equip the #purple#" + source.GetName() + "."); ui.Pause(); HandleScript(source.equipScript, source); source.equipped = true; } break; case "gainexp": Game.player.experience += Convert.ToInt32(argument); break; case "heal": int amount = Game.player.Heal(Convert.ToInt32(argument)); ui.Print("#green#You heal " + amount + " health!"); break; case "losestrength": Game.player.strength -= Convert.ToInt32(argument); break; case "losedefense": Game.player.defense -= Convert.ToInt32(argument); break; case "losehealth": Game.player.health -= Convert.ToInt32(argument); Game.player.maxHealth -= Convert.ToInt32(argument); break; case "move": Game.ChangeLocation(argument); break; case "pause": ui.Pause(); break; case "recoverhp": Game.player.FullHeal(); break; case "return": Game.Return(); break; case "shuffle": Game.ShuffleDeck(); break; case "text": ui.Print(argument); break; case "victoryevent": Game.victoryEvent = argument; break; case "wingame": Game.WinGame(); break; case "}": scopeDepth--; break; //Conditions case "hasequipment": case "hasflag": case "hasskill": case "notskill": if (!Evaluate(baseCommand, argument)) i += SkipScope(script, i); else scopeDepth++; break; //Else case "else": if (Evaluate(baseCommand, argument)) i += SkipScope(script, i); else scopeDepth++; break; //Choice case "choice": string[] choiceLines = ReadScope(script, i); i += choiceLines.Length + 2; //{ and } not included Game.eventChoiceDescriptions = new List(); Game.eventChoiceResults = new List(); for (int ii = 0; ii < choiceLines.Length; ii++) { string[] choiceSplit = choiceLines[ii].Split(new string[] { "->" }, StringSplitOptions.None); if (choiceSplit.Length > 1) { Game.eventChoiceDescriptions.Add(Utils.RBQ(choiceSplit[0])); Game.eventChoiceResults.Add(Utils.RBQ(choiceSplit[1])); } } ui.DisplayEventChoices(Game.eventChoiceDescriptions); Game.gameState = Game.GameState.EventChoice; break; } } } } public static bool Evaluate(string baseCommand, string argument, bool addToStack = true) { bool result = false; if (baseCommand != "else" && scopeDepth == 0) evaluationStack.Clear(); switch (baseCommand) { case "hasequipment": for (int i = 0; i < Game.player.inventory.Count; i++) { if (Game.player.inventory[i].name == argument) { if (Game.player.inventory[i].equipped) result = true; } } break; case "hasflag": result = Game.GetFlag(argument); break; case "hasskill": result = Game.player.mutations.ContainsKey(argument); break; case "notflag": result = !(Game.GetFlag(argument)); break; case "notskill": result = !(Game.player.mutations.ContainsKey(argument)); break; case "else": result = GetLatestEvaluation(); break; } if (addToStack) evaluationStack.Add(result); return result; } private static bool GetLatestEvaluation() { if (evaluationStack.Count < 1) return false; return evaluationStack[scopeDepth]; } private static int SkipScope(string[] script, int startingPosition) { int internalScopeDepth = 0; string currentLine = ""; int linesSkipped = 2; //Skip initial statement and { while (currentLine != "}") { currentLine = script[startingPosition + linesSkipped]; if (currentLine == "{") internalScopeDepth++; if (currentLine == "}" && internalScopeDepth > 0) { internalScopeDepth--; currentLine = ""; } linesSkipped++; } return linesSkipped - 1; } //Used only for choices private static string[] ReadScope(string[] script, int startingPosition) { List scope = new List(); string currentLine = ""; int linesSkipped = 2; //Skip initial declaration and { while (currentLine != "}") { currentLine = script[startingPosition + linesSkipped]; if (currentLine != "}") scope.Add(currentLine); linesSkipped++; } return scope.ToArray(); } private static int ParseEnemy(string[] script, int startingPosition) { bool done = false; int counter = 0; while (!done) { string currentLine = script[startingPosition + counter]; string[] split = currentLine.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (split.Length > 0) { string baseCommand = split[0]; string argument = Utils.RBQ(currentLine); switch (baseCommand) { case "}": done = true; break; case "defense": definingEnemy.defense = Convert.ToInt32(argument); break; case "dodgechance": definingEnemy.dodgeChance = Convert.ToInt32(argument); break; case "experience": definingEnemy.experience = Convert.ToInt32(argument); break; case "health": definingEnemy.health = Convert.ToInt32(argument); break; case "maxhealth": definingEnemy.maxHealth = Convert.ToInt32(argument); break; case "name": definingEnemy.name = argument; break; case "strength": definingEnemy.strength = Convert.ToInt32(argument); break; case "attacks": definingEnemy.attacks = new List(); counter++; //Skip 'attacks' string attackName = ""; while (!attackName.Contains("}")) { counter++; //Skip the initial {, then iterate over lines attackName = script[startingPosition + counter]; if (attackName != "}") definingEnemy.attacks.Add(attackName); } break; case "inventory": definingEnemy.inventory = new List(); counter++; //Skip 'inventory' string itemName = ""; while (!itemName.Contains("}")) { counter++; //Skip the initial {, then iterate over lines itemName = script[startingPosition + counter]; if (itemName != "}") definingEnemy.inventory.Add(new Item(itemName)); } break; } } counter++; } return counter; } } }