// Creates and reads a plan into an object. public static Plan Plan(Planner planner, Domain domain, Problem problem) { if (planner.Equals(Planner.FastDownward)) { return(FastDownward.Plan(domain, problem)); } else if (planner.Equals(Planner.FDMulti)) { return(FDMulti.Plan(domain, problem)); } else if (planner.Equals(Planner.Glaive)) { return(Glaive.Plan(domain, problem)); } return(null); }
// Creates a child node. private static StateSpaceNode CreateChild(Planner planner, Domain domain, Problem problem, Plan plan, State state, StateSpaceEdge edge) { // Create a new problem object. Problem newProblem = new Problem(); // Create a new domain object. Domain newDomain = domain; // Create a new plan object. Plan newPlan = new Plan(); // Store actions the system takes. List <IOperator> systemActions = new List <IOperator>(); // If the outgoing action is an exceptional step... if (edge.ActionType == ActionType.Exceptional) { // Count the exceptional edge. Exceptional++; // Create a new problem object. newProblem = NewProblem(newDomain, problem, state, edge.Action); // Find a new plan. if (planner.Equals(Planner.FastDownward)) { newPlan = FastDownward.Plan(newDomain, newProblem); } else if (planner.Equals(Planner.Glaive)) { newPlan = Glaive.Plan(newDomain, newProblem); } // If the action was accommodated and the first step of the new plan isn't taken by the player... if (newPlan.Steps.Count > 0) { // Add the action to the system action list. systemActions = GetSystemActions(newPlan, new List <string> { problem.Player }, new List <IOperator>()); // Update the problem object with the system's next move. newProblem = NewProblem(newDomain, newProblem, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First()), systemActions); // Update the plan with the system's next move. newPlan = newPlan.GetPlanUpdate(newProblem, systemActions); } else if (CEDeletion) { // Try to find a domain revision alibi. Tuple <Domain, Operator> alibi = ReviseDomain(planner, newDomain, problem, state, edge.Action as Operator); // If domain revision worked. if (alibi != null) { // Remember the new domain. newDomain = alibi.First; // Push the modified action to the edge object. edge.Action = alibi.Second; // Create a new problem object. newProblem = NewProblem(newDomain, problem, state, edge.Action); // Find a new plan. if (planner.Equals(Planner.FastDownward)) { newPlan = FastDownward.Plan(newDomain, newProblem); } else if (planner.Equals(Planner.Glaive)) { newPlan = Glaive.Plan(newDomain, newProblem); } // Add the action to the system action list. systemActions = GetSystemActions(newPlan, new List <string> { problem.Player }, new List <IOperator>()); // Update the problem object with the system's next move. newProblem = NewProblem(newDomain, newProblem, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First()), systemActions); // Update the plan with the system's next move. newPlan = newPlan.GetPlanUpdate(newProblem, systemActions); } } } // Otherwise, if the action is a consistent step... else if (edge.ActionType == ActionType.Consistent) { // Count the consistent edge. Consistent++; // Create a new problem object. newProblem = NewProblem(newDomain, problem, state, edge.Action); // Add the action to the system action list. systemActions = GetSystemActions(plan, new List <string> { problem.Player }, new List <IOperator>()); // Create a new state. State newState = new State(newProblem.Initial, state.nextStep, (Operator)plan.Steps.First()); // Create a new problem object. newProblem = NewProblem(newDomain, newProblem, newState, systemActions); // Create a new plan. newPlan = plan.GetPlanUpdate(newProblem, systemActions); } // Otherwise, the action is a constituent step... else { // Count the constituent edge. Constituent++; // If there are effects of the constituent action... if (edge.Action.Effects.Count > 0) { // Create a new problem object. newProblem = NewProblem(newDomain, problem, state, edge.Action); // Create a new plan. newPlan = plan.GetPlanUpdate(newProblem, edge.Action as Operator); } // Otherwise, initialize to the old problem and plan... else { newProblem = problem; newPlan = plan.Clone() as Plan; } // If there are still plan actions... if (newPlan.Steps.Count > 0) { // Add the action to the system action list. systemActions = GetSystemActions(newPlan, new List <string> { problem.Player }, new List <IOperator>()); // Update the problem object with the system's next move. newProblem = NewProblem(newDomain, newProblem, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First()), systemActions); // Update the plan with the system's next move. newPlan = newPlan.GetPlanUpdate(newProblem, systemActions); } } // Add the system actions to the current edge. edge.SystemActions = systemActions; // Create an empty child node. StateSpaceNode child = null; // If there are remaining plan steps... if (newPlan.Steps.Count > 0) { // Build a new tree using the first step of the plan as the next step. child = StateSpaceSearchTools.CreateNode(planner, newDomain, newProblem, newPlan, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First())); } else { // Terminate the tree by adding a goal node. child = StateSpaceSearchTools.CreateNode(planner, newDomain, newProblem, newPlan, new State(newProblem.Initial, newPlan.InitialStep, newPlan.GoalStep)); } // Store the system actions. child.systemActions = systemActions; // Record the action that triggered the node's generation. child.incoming = edge; return(child); }
// Rewrites history to remove harmful conditional effects. public static StateSpaceNode RemoveConditionalEffects(Planner planner, Domain domain, Problem problem, Plan plan, State state, StateSpaceEdge edge, int depth) { // Store the incoming action. Operator incoming = edge.Action as Operator; // Create a new plan object. Plan newPlan = new Plan(); // Examine each exceptional effect. foreach (Predicate effect in incoming.ExceptionalEffects) { // Create a new domain object. Domain newDomain = new Domain(); // Save the domain's name. newDomain.Name = domain.Name; newDomain.staticStart = domain.staticStart; // If the current effect is conditional... if (incoming.IsConditional(effect)) { // If the conditional effect has not been observed by the player. // Remove the conditional effect from the domain. // Copy the current operator templates into a list. List <IOperator> templates = new List <IOperator>(); foreach (IOperator templ in domain.Operators) { templates.Add(templ.Clone() as IOperator); } // Create a clone of the incoming action's unbound operator template. IOperator temp = incoming.Template() as Operator; // Find the incoming action template in the domain list. Operator template = templates.Find(t => t.Equals(temp)) as Operator; // Remove the incoming action template from the domain list. templates.Remove(template); // Create a clone of the incoming action. Operator clone = incoming.Clone() as Operator; // Create a list of conditional effects to remove from the template. List <IAxiom> remove = new List <IAxiom>(); foreach (IAxiom conditional in clone.Conditionals) { if (conditional.Effects.Contains(effect)) { remove.Add(conditional); } } // Remove each conditional effect from the template. foreach (IAxiom rem in remove) { template.Conditionals.Remove(rem.Template() as IAxiom); } // Add the modified template to the domain list. templates.Add(template); // Push the modified list to the new domain object. newDomain.Operators = templates; // Write new problem and domain files. Writer.ProblemToPDDL(Parser.GetTopDirectory() + @"Benchmarks/" + domain.Name.ToLower() + @"/probrob.pddl", newDomain, problem, state.Predicates); Writer.DomainToPDDL(Parser.GetTopDirectory() + @"Benchmarks/" + domain.Name.ToLower() + @"/domrob.pddl", newDomain); // Find a new plan. if (planner.Equals(Planner.FastDownward)) { newPlan = FastDownward.Plan(newDomain, problem); } else if (planner.Equals(Planner.Glaive)) { newPlan = Glaive.Plan(newDomain, problem); } // If the modified domain can accommodate the player's action... if (newPlan.Steps.Count > 0) { // Clone the modified incoming action template. Operator newAction = template.Clone() as Operator; // Bind the cloned action with the incoming action's bindings. newAction.Bindings = incoming.Bindings; // Push the modified action to the edge object. edge.Action = newAction; // Expand the tree using the new domain. return(ExpandTree(planner, newDomain, problem, plan, state, edge, depth)); } } } return(null); }
/// <summary> /// An online text-based command line game that is a traversal of mediation space. /// </summary> /// <param name="domainName">The game domain.</param> /// <param name="debug">Whether or not debug mode is enabled.</param> public static void Play() { Console.Clear(); string domainName = ""; // Make sure the file exists. while (!File.Exists(Parser.GetTopDirectory() + @"Benchmarks\" + domainName + @"\domain.pddl") || !File.Exists(Parser.GetTopDirectory() + @"Benchmarks\" + domainName + @"\prob01.pddl")) { // Prompt the user for game name. Console.WriteLine("What would you like to play?"); Console.WriteLine(" Type 'exit' to end program."); Console.WriteLine(" Type 'path' to modify the directory."); Console.WriteLine(" Type 'planner' to choose the planner."); Console.WriteLine(" Type 'help' to print game titles."); Console.Write(" Type 'debug' to turn debug mode "); if (debug) { Console.WriteLine("off."); } else { Console.WriteLine("on."); } Console.WriteLine(); Console.Write(">"); // Read in the game to load. domainName = Console.ReadLine().ToLower(); // Print domains if prompted. if (domainName.Equals("help")) { Console.WriteLine(); if (System.IO.Directory.Exists(Parser.GetTopDirectory() + @"Benchmarks\")) { foreach (string file in Directory.GetFileSystemEntries(Parser.GetTopDirectory() + @"Benchmarks\")) { Console.WriteLine(Path.GetFileName(file)); } Console.WriteLine(); Console.Write(">"); // Read in the game to load. domainName = Console.ReadLine().ToLower(); } else { Console.WriteLine(Parser.GetTopDirectory() + @"Benchmarks\ does not exist!"); Console.ReadKey(); domainName = "482990adkdlllifkdlkfjlaoow"; } } // Rewrite directory if prompted. if (domainName.Equals("path")) { Console.WriteLine(); Console.WriteLine("Your current game directory is: " + Parser.GetTopDirectory()); Console.WriteLine("Enter new path."); Console.WriteLine(); Console.Write(">"); string newPath = Console.ReadLine(); Console.WriteLine(); if (Directory.Exists(newPath + @"Benchmarks\")) { Parser.path = newPath; } else { Console.WriteLine("Sorry, " + newPath + @"Benchmarks\" + " does not exist."); Console.ReadKey(); } } // Change the planner if prompted. if (domainName.Equals("planner")) { Console.WriteLine(); Console.WriteLine("Your current planner is: " + planner); Console.WriteLine("Enter new planner."); Console.WriteLine(); Console.Write(">"); string newPlanner = Console.ReadLine(); Console.WriteLine(); if (Enum.IsDefined(typeof(Planner), newPlanner)) { planner = (Planner)Enum.Parse(typeof(Planner), newPlanner, true); Console.WriteLine("Your planner is now " + planner); Console.ReadKey(); } else { Console.WriteLine("Sorry, " + newPlanner + " does not exist."); Console.ReadKey(); } } // Exit if prompted. if (domainName.Equals("exit")) { Environment.Exit(0); } // Toggle debug if prompted if (domainName.Equals("debug")) { debug = !debug; } if ((!File.Exists(Parser.GetTopDirectory() + @"Benchmarks\" + domainName + @"\domain.pddl") || !File.Exists(Parser.GetTopDirectory() + @"Benchmarks\" + domainName + @"\prob01.pddl")) && !domainName.Equals("debug") && !domainName.Equals("path") && !domainName.Equals("planner") && !domainName.Equals("482990adkdlllifkdlkfjlaoow")) { // Prompt that the game doesn't exist. Console.WriteLine(); Console.WriteLine("I'm sorry, but I can't find " + domainName.ToUpper()); Console.WriteLine(); Console.ReadKey(); } // Clear the console screen. Console.Clear(); } // Parse the domain file. domain = Parser.GetDomain(Parser.GetTopDirectory() + @"Benchmarks\" + domainName + @"\domain.pddl", PlanType.StateSpace); // Parse the problem file. problem = Parser.GetProblemWithTypes(Parser.GetTopDirectory() + @"Benchmarks\" + domainName + @"\prob01.pddl", domain); // Find the initial plan. if (planner.Equals(Planner.FastDownward)) { plan = FastDownward.Plan(domain, problem); } else if (planner.Equals(Planner.Glaive)) { plan = Glaive.Plan(domain, problem); } // Welcome the player to the game. Console.WriteLine("Welcome to " + domain.Name); // Find the first state. state = plan.GetFirstState(); // Create the initial node of mediation space. root = StateSpaceMediator.BuildTree(planner, domain, problem, plan, state, 0); // Initialize a stopwatch for debugging. Stopwatch watch = new Stopwatch(); // Present information about the player. command = "look"; arguments = new List <string> { "me" }; Look(); Console.WriteLine(); // Present the initial state. command = ""; Look(); // Loop while this is false. bool exit = false; while (!exit) { // Initialize the frontier. frontier = new Hashtable(); // Expand the frontier in a new thread. frontierThread = new Thread(ExpandFrontier); // Start the thread. frontierThread.Start(); // Ask for input. Console.WriteLine(); Console.Write(">"); input = Console.ReadLine(); // If in debug mode, start the stop watch. if (debug) { watch.Reset(); watch.Start(); } // Parse the command and its arguments. command = ParseCommand(input).ToLower(); arguments = ParseArguments(input); // Interpret the command. switch (command) { case "exit": exit = true; break; case "clear": Console.Clear(); break; case "cls": Console.Clear(); break; case "look": Look(); break; case "help": Help(); break; case "wait": Console.Clear(); Wait(); break; default: OneArg(); break; } // If debugging, write the current plan and the elapsed time. if (debug && plan.Steps.Count > 0 && !command.Equals("clear") && !command.Equals("cls")) { Console.Out.WriteLine(); Console.WriteLine("Narrative Trajectory:"); int longestName = 0; foreach (Operator step in plan.Steps) { if (step.TermAt(0).Length > longestName) { longestName = step.TermAt(0).Length; } } string lastName = ""; foreach (Operator step in plan.Steps) { if (!step.TermAt(0).Equals(lastName)) { lastName = step.TermAt(0); Console.Out.Write("".PadLeft(5) + UppercaseFirst(step.TermAt(0)) + "".PadLeft(longestName - step.TermAt(0).Length + 1)); } else { Console.Out.Write("".PadLeft(5) + "".PadLeft(longestName + 1)); } string[] splitName = step.Name.Split('-'); Console.Out.Write(splitName[0] + "s "); for (int i = 1; i < step.Name.Count(x => x == '-') + 1; i++) { Console.Out.Write(UppercaseFirst(step.TermAt(i)) + " "); } Console.Out.WriteLine(); } Console.Out.WriteLine(); Console.Write("Elapsed time: "); Console.Out.Write(watch.ElapsedMilliseconds); Console.WriteLine("ms"); } // Check for goal state. if (root.Goal) { Console.WriteLine("GOAL STATE"); Console.ReadKey(); exit = true; } // Check for incompatible state. else if (root.Incompatible) { Console.WriteLine("UNWINNABLE STATE"); Console.ReadKey(); exit = true; } if (exit) { Console.Clear(); } // Kill the frontier thread (this should be okay). frontierThread.Abort(); } Game.Play(); }