private void InsertPlan(Plan newPlan, PlanImportance importance) //work has a set schedule and should already have been calculated { ResetTick(); planning.Sort(); List <Plan> interventions; //if priority if (importance != PlanImportance.Normal) { interventions = CheckIfPlanIntervines(newPlan); foreach (Plan other in interventions) { interventions.Remove(other); } } else { //keep checking in between plans int duration = newPlan.Duration; int otherDuration; for (int i = 0; i < planning.Count; i++) { if (i == planning.Count - 1) { newPlan.start = planning[i].End; break; } otherDuration = planning[i + 1].start - planning[i].End; if (otherDuration > duration) { newPlan.start = planning[i].End; break; } } } newPlan.importance = importance; planning.Add(newPlan); }
private IEnumerator GOAP_Planning(List <Action.State> wanted, PlanImportance importance) // only gives one option { if (wanted.Count == 0) { wanted.Add(new Action.State(concedeTag, 100)); } List <ActionPath> succeeded = new List <ActionPath>(); List <ActionPath> aps = new List <ActionPath>(); ActionPath ap; List <ActionPath> newActions = new List <ActionPath>(); List <ActionsBranchable> actionsByWant; ActionsBranchable branchable; List <BranchTemporaryEntry> possible = new List <BranchTemporaryEntry>(); ActionsBranchable actionBranch; int calc = 0, old; bool fit, symbiont; int wantedChosen = -1; foreach (Action.State want in wanted) { wantedChosen++; aps.Clear(); actionsByWant = GetBranchableActions(new List <Action.State> { want }); //its certain that its only one right now actionBranch = actionsByWant[0]; foreach (Action action in actionBranch.actions) { aps.Add(new ActionPath(action, null)); } while (aps.Count > 0) { calc++; if (calc > intelligence.calcsPerSecond) { calc = 0; yield return(null); } ap = aps[0]; aps.RemoveAt(0); //check if able to execute #region Execute Check fit = true; symbiont = false; foreach (Action action in ap.actions) { if (action.requirements.Count == 0) { symbiont = true; } foreach (Action.State requirement in action.requirements) { symbiont = false; foreach (AState aState in states) { if (requirement.state == aState.state) { symbiont = true; if (requirement.amount > aState.amount) { fit = false; break; } } } if (!fit || !symbiont) { break; } } if (!fit) { break; } } if (fit && symbiont) { succeeded.Add(ap); continue; } #endregion //foreach action get branches newActions.Clear(); fit = true; foreach (Action oldAction in ap.actions) { actionsByWant = GetBranchableActions(oldAction.requirements); if (actionsByWant.Count == 0) { continue; } possible.Clear(); foreach (Action a in actionsByWant[0].actions) { possible.Add(new BranchTemporaryEntry(null, a)); } for (int i = 1; i < actionsByWant.Count; i++) { branchable = actionsByWant[i]; old = possible.Count - 1; //multiply all excisting with each of this list for (int _old = old; _old > -1; _old--) { foreach (Action a in branchable.actions) { possible.Add(new BranchTemporaryEntry(possible[_old], a)); } } //remove all the old ones for (int _i = old; _i > 0; _i--) { possible.RemoveAt(_i); } } for (int p = possible.Count - 1; p > -1; p--) { if (possible[p].actions.Count < actionsByWant.Count) { possible.RemoveAt(p); } } if (possible.Count == 0) { fit = false; break; } //add actions to temp list foreach (BranchTemporaryEntry bte in possible) { //remove functions that are executed multiple times for (int i = bte.actions.Count - 1; i > -1; i--) { for (int _i = bte.actions.Count - 1; _i > -1; _i--) { if (i == _i) { continue; } if (bte.actions[i] == bte.actions[_i]) { bte.actions.RemoveAt(i); } } } newActions.Add(new ActionPath(bte.actions, ap)); } } if (!fit) { continue; } foreach (ActionPath aP in newActions) { aps.Add(aP); } } //if it continues the loop, the current one has not been solved if (succeeded.Count == 0) { continue; } succeeded.Sort(); int choice = Mathf.RoundToInt(Mathf.Lerp(0, succeeded.Count - 1, (float)intelligence.value / 100)); #region Debug /* * //temporary debug * foreach (ActionPath e in succeeded) * { * string s = ""; * ActionPath _e = e; * while (true) * { * foreach (Action a in _e.actions) * s += a.name + " "; * if (!(_e.parent != null)) * break; * _e = _e.parent; * } * * print(s); * } */ #endregion //convert action path into a planning Plan newPlan = new Plan(); newPlan.goal = wanted[wantedChosen].state; ActionPath current = succeeded[choice]; while (true) { foreach (Action action in current.actions) { newPlan.parts.Add(action); } if (!(current.parent != null)) { break; } current = current.parent; } InsertPlan(newPlan, importance); StartPlan(); yield break; } //a man without a plan }
//check planning > if time left try fill //if none create plan //list of most wanted to least = stabilizing ? fill hunger / health needs | maintaining ? keep filling but dont prioritize | inproving ? //if not able to execute try next //if nothing, plan relax #region Goap //idle = at the start of lifecycle, at the end of plan public void Idle() { State myState = GetState(); //most to least important List <Action.State> needs = new List <Action.State>(); PlanImportance importance = PlanImportance.Normal; bool planned; switch (myState) { case State.Stabilizing: foreach (AState aS in states) { if (aS.rootStat) { if (aS.amount <= stats.pointCritical) { needs.Add(aS); } } } importance = PlanImportance.Priority; break; //check planning //when making a plan you automatically make sure you get enough base needs for the job case State.Improving: foreach (Action.State s in improvementState) { needs.Add(s); } foreach (Action a in intelligence.actions) { foreach (Action.State improvement in a.improvements) { int current = 0; foreach (Action.State aState in currentState) { if (aState.state == improvement.state) { current = aState.amount; break; } } if (improvement.amount > current) { planned = false; foreach (Plan plan in planning) { if (plan.goal == improvement.state) { planned = true; break; } } if (!planned) { needs.Add(improvement); } } } } foreach (AState aS in states) { if (aS.rootStat) { needs.Add(aS); } } break; default: break; } if (needs.Count == 0) { needs.Add(new Action.State(rewardTag, 100 - GetHappiness())); } needs.Sort(); if (goap != null) { StopCoroutine(goap); } goap = StartCoroutine(GOAP_Planning(needs, importance)); }