Beispiel #1
0
	/// <summary>
	/// Plans through a StoryArc up to level "planningUpTo". The returned StoryArc keeps all the previous Events in it and is globally consistent. If that's not possible, an Error is thrown.
	/// </summary>
	public StoryArc planGlobalUpTo(int planningUpTo, StoryArc arc, IEnumerable<SmartObject> reducedObjectSpace, PlanSpace option, ref bool success)
	{
		Debug.Log ("Start Planning Global"); 
		StoryArc newArc = new StoryArc (arc);

		//Stacks are used to save: The arcs we planned, from where we started, Beatlevel we plan to. So we can go back if something went wrong
		Stack<StoryArc> arcStack = new Stack<StoryArc> ();
		Stack<int> fromStack = new Stack<int> ();
		Stack<int> ToStack = new Stack<int> ();
		Stack<List<EventID>> IdListStack = new Stack<List<EventID>>();
		Stack<List<BeatPopulation>> BeatPopulationSetStack = new Stack<List<BeatPopulation>> ();
		Stack<int> xthTryStack = new Stack<int> ();

		List<StoryBeat> newBeats = new List<StoryBeat>();
		List<Transition> upgoing = new List<Transition> ();
		Transition cur;
		int maxFails = (planningUpTo * (planningUpTo - 1)) / 2;
		int maxTrys = 1;
		int nrFails = 0;
		int curPlanningFrom = 0;
		int curPlanningUpTo = planningUpTo;
		int curTry = 0;

		arcStack.Push (newArc);
		fromStack.Push (curPlanningFrom);
		ToStack.Push (curPlanningUpTo);
		
		xthTryStack.Push (curTry);

		domains.Add (new EventDomain (stateSpaceManager));
		EventDomain domain = (EventDomain)domains [0];

		if(PlanSpace.Reduced == option)
			stateSpaceManager.setListReduced (reducedObjectSpace.ToArray ());
		stateSpaceManager.option = option;
		BeatPopulationSetStack.Push (getBestPopulations(curPlanningFrom, arc, maxTrys));
		List<Transition> bestChoice = new List<Transition>();

		// while "from" isn't the last Beat yet we continue planning
		while(ToStack.Peek() != fromStack.Peek())
		{
			arc = arcStack.Peek();
			curPlanningFrom = fromStack.Peek();
			curPlanningUpTo = ToStack.Peek ();
			//--------------------------------
			//PLANNING WITH PARAMETERFILLING
			curTry = xthTryStack.Peek();
			StoryBeat BeatWithNewPop = BeatPopulationSetStack.Peek().ElementAt(curTry).ToStoryBeat();
			StoryBeat[] remainingBeats = arc.Beats;
			remainingBeats[curPlanningFrom] = BeatWithNewPop;
			arc = new StoryArc(remainingBeats);
			//--------------------------------

			//Convert the EndEvents from Events to Transitions
			endEvents = arc.Beats[curPlanningFrom].Events;
			endTransitions = new Transition[endEvents.Length];
			for (int i=0;i<endEvents.Length;i++)
				endTransitions[i] = new Transition(endEvents[i]);
			if(curTry==0)
				bestChoice = endTransitions.ToList();
			//Adding the relevant states of the end-Transitions, so heuristic only depending on these states can be used to compute plan
			domain.relevanceMasks = stateSpaceManager.createRelevanceMasks(endTransitions);
			planner.init (ref domains, MAXNODES);

			stateSpaceManager.resetGlobalState ();
			SimulateUpTo (stateSpaceManager, curPlanningFrom, arc);
			//Set start state to the state after the Beat we are planning from
			DefaultState startState = new DefaultState (stateSpaceManager.globalState);

			//end state is set to the state after the startEvents and the necessary preconditions changed
			DefaultState endState = new DefaultState (startState);
			List<RelevanceMask> relev = domain.relevanceMasks.ToList();

			//end state is changed according to the upgoing conditions for global consistency
			foreach(Transition t in upgoing)
			{
				endState = stateSpaceManager.getGlobalStateBeforeEvent(endState,t);
				foreach(RelevanceMask mask in stateSpaceManager.createRelevanceMasks(t))
						relev.Add(mask);
			}
			domain.relevanceMasks = relev.ToArray();

			//conditions from upgoing are overwritten if they conflict with preconditions for current beat
			foreach(Transition t in endTransitions)
			{
				endState = stateSpaceManager.getGlobalStateBeforeEvent(endState,t);
			}

			stateSpaceManager.endTransitions = endTransitions.ToList();
			foreach(Transition t in upgoing)
			{
				stateSpaceManager.endTransitions.Add(t);
			}

			plan.Clear();
			success = planner.computePlan (ref startState, ref endState, ref plan, TIMEOUT);

			//---------------------------------------------------------------
			if (success)
			{
				plan.Pop (); 		//pop start event
				upgoing.Clear();
				int oldNrBeats = arc.Beats.Count();
				int newNrEvents = plan.Count;
				//add Beats up to the starting level of planning
				for(int i=0; i<curPlanningFrom; i++)
				{
					newBeats.Add(arc.Beats[i]);
				}
				//add planned beats
				List<EventID> IdList = new List<EventID>();
				while(plan.Count>0)
				{
					cur = ((Transition)plan.Pop());
					newBeats.Add(new StoryBeat(cur.ToStoryEvent()));
					IdList.Add(newBeats.Last().Events.First().ID);
				}
				//add Beats after the planning
				for(int i=curPlanningFrom; i<oldNrBeats; i++)
				{
					newBeats.Add(arc.Beats[i]);
				}
				newArc = new StoryArc(newBeats.ToArray());
				IdListStack.Push(IdList);
				arcStack.Push(newArc);
				fromStack.Push(curPlanningFrom + 1 + newNrEvents);
				ToStack.Push (curPlanningUpTo + newNrEvents);
				if(fromStack.Peek() != ToStack.Peek())
					BeatPopulationSetStack.Push (getBestPopulations(fromStack.Peek(), newArc, maxTrys));
				xthTryStack.Push(0);
				newBeats.Clear();
				upgoing.Clear();
			}
			else
			{
				if(curTry + 1>=maxTrys || curTry >= BeatPopulationSetStack.Peek().Count-1)
				{
					nrFails++;
					//Propagate the Transitions we need to consider upwards if planning fails
					if (upgoing.Count == 0)
						foreach(Transition t in bestChoice)
							upgoing.Add (t);

					if(fromStack.Peek() > 0)
					{
						IdListStack.Pop ();
						fromStack.Pop ();
						arcStack.Pop();
						ToStack.Pop ();
						BeatPopulationSetStack.Pop();
						xthTryStack.Pop();
					}
					if(fromStack.Peek()==0 || nrFails>maxFails)
					{
						return arc;
					}
				}
				else {
					int temp = xthTryStack.Peek();
					temp++;
					xthTryStack.Pop();
					xthTryStack.Push (temp);
				}
			}
		}
		List<EventID> IDsFromOneLevel;
		while(IdListStack.Count > 0)
		{
			IDsFromOneLevel = IdListStack.Pop ();
			foreach(EventID i in IDsFromOneLevel)
				IDs.Add(i);
		}
		return arcStack.Peek();
	}
Beispiel #2
0
	/// <summary>
	/// Plans through a whole StoryArc. The returned StoryArc keeps all the previous Events in it and is globally consistent. If that's not possible, an Error is thrown.
	/// </summary>
	public StoryArc planGlobal(StoryArc arc, IEnumerable<SmartObject> reducedObjectSpace, PlanSpace option, ref bool success)
	{
		return planGlobalUpTo (arc.Beats.Count (), arc, reducedObjectSpace, option, ref success);
	}