public virtual float Heuristic(AIGoal goal) { //float r = 0; //foreach (var keys in goal.PostConditions) //{ // object Output; // if (PostConditions.TryGetValue(keys.Key, out Output)) // { // r++; // if (Convert.ToBoolean(Output) != Convert.ToBoolean(keys.Value)) // { // } // else // { // r--; // } // } // else // { // } //} //return r; return(0); }
public List <AIAction> TryAndPlan(AIGoal corGoal) { List <AIAction> plan = new List <AIAction>(); List <AIAction> validActions = new List <AIAction>(); bool valid = true; foreach (var action in Actions) { action.mAgent = this; valid = true; foreach (var keys in action.PostConditions) { object Output; if (corGoal.PostConditions.TryGetValue(keys.Key, out Output)) { if (Convert.ToBoolean(Output) != Convert.ToBoolean(keys.Value)) { valid = false; } } else { valid = false; } } if (valid) { if (action.CheckProceduralPreCondition()) { validActions.Add(action); } } } validActions.Sort((x, y) => x.GetCost().CompareTo(y.GetCost())); if (validActions.Count() == 0) { return(plan); } List <AIAction> path = new List <AIAction>(); //clear tiles prev stuff foreach (var t in Actions) { t.g = 0; } var lastCheckedNode = validActions[0]; List <AIAction> openSet = new List <AIAction>(); // openSet starts with beginning node only openSet.Add(lastCheckedNode); List <AIAction> closedSet = new List <AIAction>(); //This function returns a measure of aesthetic preference for //use when ordering the openSet. It is used to prioritise //between equal standard heuristic scores. It can therefore //be anything you like without affecting the ability to find //a minimum cost path. //Run one finding step. //returns 0 if search ongoing //returns 1 if goal reached //returns -1 if no solution var end = corGoal; bool searching = true; while (searching == true) { if (openSet.Count() > 0) { // Best next option var winner = 0; for (var i = 1; i < openSet.Count(); i++) { if (openSet[i].GetF(end) < openSet[winner].GetF(end)) { winner = i; } //if we have a tie according to the standard heuristic if (openSet[i].GetF(end) == openSet[winner].GetF(end)) { //Prefer to explore options with longer known paths (closer to goal) if (openSet[i].g > openSet[winner].g) { winner = i; } } } var current = openSet[winner]; lastCheckedNode = current; // Did I finish? if (current.IsCompatibleWithCurWorldState(WorldState)) { path.Add(current); AIAction cur = current; while (cur.Parent != null) { path.Add(cur.Parent); cur = cur.Parent; } path.Reverse(); return(path); } // Best option moves from openSet to closedSet openSet.Remove(current); closedSet.Add(current); // Check all the neighbors var neighbors = current.GetActionNeighbours(this); neighbors = neighbors.Where(o => o.CheckProceduralPreCondition()).ToList(); for (var i = 0; i < neighbors.Count(); i++) { var neighbor = neighbors[i]; // Valid next spot? if (!closedSet.Contains(neighbor)) { // Is this a better path than before? var tempG = current.g + 0 + current.GetCost();; // Is this a better path than before? if (!openSet.Contains(neighbor)) { openSet.Add(neighbor); } else if (tempG >= neighbor.g) { // No, it's not a better path continue; } neighbor.g = tempG; neighbor.Parent = current; } } } else { searching = false; return(path); } // Uh oh, no solution } return(path); }
public virtual float GetF(AIGoal goal) { return(Heuristic(goal) + g); }