public bool RunPlanner() { GOAPAction currentAction = FindNextAction(); // we can't find any valid actions, exit completely (in a real game we would 'idle'). if (currentAction == null) { return(false); } // execute task foreach (var v in currentAction.GetEffects()) { if (v.GetAgent() == null) { v.SetAgent(this); } // run the effect on the owner v.Evaluate(); } mEnergy -= currentAction.mCost; return(true); }
public void AddAction(GOAPAction a) { if (a.mAgent == null) { a.mAgent = this; } // for all preconditions and effects, set agent to this one mActions.Add(a); Console.WriteLine("[AddAction] \"{0}\"", a); }
List <GOAPAction> mActions = new List <GOAPAction>(); // should be prio queue public GOAPAction FindNextAction() { if (mActions.Count() == 0) { return(null); } // get lowest energy, valid task GOAPAction currentAction = mActions[0]; GOAPAction replenish = mActions[0]; foreach (GOAPAction a in mActions) { if (a.AreAllPrerequisitesSatisfied() && a.mCost < currentAction.mCost) { if (a.mCost > 0) { currentAction = a; } else { replenish = a; } } } if (currentAction == null) { Console.WriteLine("[Agent] [RunPlanner] Info=\"No available tasks\""); return(null); } Console.WriteLine("[Agent] [RunPlanner] ActionSelected={0}", currentAction); // if no energy try to find a task that replenishes energy if ((mEnergy - currentAction.mCost) < 0) { Console.WriteLine( "[Agent] [RunPlanner] Info=\"No energy for selected task. Running replenish task\" CurrentEnergy={0} RequiredEnergy={1} ReplenishEnergy={2}", mEnergy, currentAction.mCost, replenish.mCost); currentAction = replenish; } return(currentAction); }
static void GoapMain(string[] args) { // setup objects WorldObject woWood = new WorldObject("wood"); WorldObject woAxe = new WorldObject("axe"); WorldObject woBed = new WorldObject("bed"); Agent woWoodDeposit = new Agent("wood deposit"); Agent Alice = new Agent("Alice"); // set up actions // chop wood requires an axe, no wood GOAPAction ChopWood = new GOAPAction("Chop wood", 3); var reqAxe = new GOAPState <WorldObject>("requires Axe", woAxe, (WorldObject wo, Agent a1) => { return(a1.HasWorldObject(wo)); }); var reqNoWood = new GOAPState <WorldObject>("requires no Wood", woWood, (WorldObject wo, Agent a1) => { return(!a1.HasWorldObject(wo)); }); ChopWood.AddPrerequisite(reqAxe); ChopWood.AddPrerequisite(reqNoWood); var giveWood = new GOAPState <WorldObject>("give wood to agent", woWood, (WorldObject wo, Agent a1) => { a1.AddObjectToInventory(wo); return(true); }); ChopWood.AddEffect(giveWood); // done with chop wood // deposit wood GOAPAction DepositWood = new GOAPAction("Deposit wood", 2); var reqWood = new GOAPState <WorldObject>("requires Wood", woWood, (WorldObject wo, Agent a1) => { return(a1.HasWorldObject(wo)); }); DepositWood.AddPrerequisite(reqWood); var depWood = new GOAPState <WorldObject, Agent>("give wood to depo", woWood, woWoodDeposit, (WorldObject wo, Agent a1, Agent a2) => { a2.RemoveObjectFromInventory(wo); a1.AddObjectToInventory(wo); return(true); }); DepositWood.AddEffect(depWood); // done with deposit wood GOAPAction Sleep = new GOAPAction("Sleep", -20); var reqSleep = new GOAPState("requires sleep", (Agent a1) => { return(a1.mEnergy < 3); }); var replenishEnergy = new GOAPState <WorldObject>("sleep", woBed, (WorldObject wo, Agent a1) => { /*a1.mEnergy += 20; */ return(true); }); Sleep.AddPrerequisite(reqSleep); Sleep.AddEffect(replenishEnergy); // rest // done with rest Alice.AddAction(ChopWood); Alice.AddAction(DepositWood); Alice.AddAction(Sleep); Console.WriteLine("\n=== Simulation running ===\n"); // run simulation while (Alice.RunPlanner()) { Console.WriteLine("{0}", Alice.ToString()); Alice.PrintInventory(); Console.WriteLine(); } Console.ReadLine(); }