public int ShouldUseItem()
        {
            //print("ShouldUseItem()");

            // TODO: foreach item in inventory,
            //       if any item would give the player any value
            //           set itemToUseIndex to be the item that offers the greatest value and return success
            //       else if none of the items give any value at this moment (ex: no targets, etc...)
            //           return failure

            int missileIndex  = Inventory.GetItemIndex("Rocket");
            int boostIndex    = Inventory.GetItemIndex("Boost");
            int shieldIndex   = Inventory.GetItemIndex("Shield");
            int oilSpillIndex = Inventory.GetItemIndex("Oil Spill");

            if (boostIndex != -1)
            {
                itemToUseIndex = boostIndex;
            }
            else if (missileIndex != -1)
            {
                // check if other players are in sight for missile target
                foreach (AbstractPlayer p in GameplayManager.Instance.Players)
                {
                    RaycastHit[] hits = Physics.RaycastAll(transform.position + (Vector3.up * 0.5f), p.transform.position - transform.position);
                    foreach (RaycastHit hit in hits)
                    {
                        // we are colliding with ourself
                        if (hit.transform == transform)
                        {
                            continue;
                        }

                        if (hit.collider.tag.Equals("HumanPlayer") || hit.collider.tag.Equals("AIPlayer"))
                        {
                            AbstractPlayer potentialTarget = hit.collider.GetComponent <AbstractPlayer>();

                            // check if potentialTarget is in equal or higher place standing. If not, then do not waste the missile on them.
                            if (potentialTarget.checkpoints.Count <= checkpoints.Count)
                            {
                                playerAttackTarget = potentialTarget;
                                itemToUseIndex     = missileIndex;
                            }

                            break;
                        }
                    }
                }
            }
            else if (shieldIndex != -1)
            {
                // check if player is in sight for foreign missiles
                foreach (AbstractPlayer p in GameplayManager.Instance.Players)
                {
                    if (p.Inventory.GetItemIndex("Rocket") != -1)
                    {
                        RaycastHit[] hits = Physics.RaycastAll(p.transform.position + (Vector3.up * 0.5f), transform.position - p.transform.position);
                        Debug.DrawRay(p.transform.position, transform.position - p.transform.position, Color.red, 10000);
                        foreach (RaycastHit hit in hits)
                        {
                            // the ray has hit us
                            if (hit.transform == transform)
                            {
                                itemToUseIndex = shieldIndex;
                            }
                        }

                        // itemToUseIndex = shieldIndex;
                    }
                }
            }
            else if (oilSpillIndex != -1)
            {
                // we can only place oil spills on neighbor nodes around us
                IWeightedDiGraph <GameObject, float> graph = PositionNode.mbGraph.graph;
                List <GameObject> potentialOilTargets      = new List <GameObject>();
                foreach (GraphNode <GameObject> graphNode in graph.Neighbors(PositionNode.nodeId))
                {
                    // CalculatePathToGoal() and if this node is on that path then do not add it to the list (otherwise we'd be hindering ourselves)
                    potentialOilTargets.Add(graphNode.Data);
                }

                Checkpoint  checkpointTarget = GetClosestCheckpoint();
                MBGraphNode checkpointNode   = checkpointTarget == null ? null : checkpointTarget.node;

                GraphNode <GameObject> optimalGraphNode = reachableNodeIds.Count > 0 ? GameplayManager.Instance.gridGraph.graph[reachableNodeIds[0]] : null;
                float dist = Mathf.Infinity;
                foreach (string nodeId in reachableNodeIds)
                {
                    GraphNode <GameObject> gNode = GameplayManager.Instance.gridGraph.graph[nodeId];
                    float tempDist = (gNode.Data.transform.position - checkpointNode.transform.position).magnitude;
                    if (tempDist < dist)
                    {
                        optimalGraphNode = gNode;
                        dist             = tempDist;
                    }
                }

                if (optimalGraphNode != null)
                {
                    List <GraphNode <GameObject> > path = pathFinding.FindPath(PositionNode.nodeId, optimalGraphNode.Id, MovementHeuristic, checkpoints.Count <= 1);

                    if (path.Count > 0)
                    {
                        path.RemoveAt(0);
                    }
                    if (path.Count == 0)
                    {
                        return((int)BTNode.EState.Failure);
                    }


                    // If there 1 or less nodes that don't have an oil spill on them then don't place the oil spill or else we would be trapping ourselves
                    if (potentialOilTargets.Count > 1)
                    {
                        // select the first potential oil target
                        nodeToSpillOn = potentialOilTargets[0];
                        foreach (GameObject ot in potentialOilTargets)
                        {
                            if (!path.Contains(GameplayManager.Instance.gridGraph.graph[ot.GetComponent <MBGraphNode>().nodeId]))
                            {
                                nodeToSpillOn  = ot;
                                itemToUseIndex = oilSpillIndex;
                                break;
                            }
                        }
                    }
                }
            }

            return(itemToUseIndex >= 0 ? (int)BTNode.EState.Success : (int)BTNode.EState.Failure);
        }
        public int ShouldTakeCover()
        {
            //print("ShouldTakeCover()");

            // foreach player in the game, check if they have ranged/attack items
            //       if they do, then get the item with the longest range and check if they can reach this player
            //       if they can reach us
            //           set shouldTakeCover to true
            //           add players who are a threat to playerAttackThreats list
            //           return Success
            //       else if no one can reach us with an attack
            //           return failure

            if (shieldObject.activeSelf)
            {
                return((int)BTNode.EState.Failure);
            }

            bool shouldTakeCover = false;

            foreach (AbstractPlayer p in GameplayManager.Instance.Players)
            {
                int pOilSpillIndex = p.Inventory.GetItemIndex("Oil Spill");
                int pMissileIndex  = p.Inventory.GetItemIndex("Rocket");

                if (pMissileIndex != -1)
                {
                    RaycastHit[] hits = Physics.RaycastAll(p.transform.position + (Vector3.up * 0.5f), transform.position - p.transform.position);
                    foreach (RaycastHit hit in hits)
                    {
                        // the ray has hit us
                        if (hit.transform == transform)
                        {
                            playerAttackThreats.Add(p);
                            shouldTakeCover = true;
                        }
                    }
                }
                else if (pOilSpillIndex != -1)
                {
                    IWeightedDiGraph <GameObject, float> graph = PositionNode.mbGraph.graph;
                    foreach (GraphNode <GameObject> graphNode in graph.Neighbors(PositionNode.nodeId))
                    {
                        if (graphNode.Data.transform == PositionNode.transform)
                        {
                            // we can be hit by this player's oil spill directly
                            playerAttackThreats.Add(p);
                            shouldTakeCover = true;
                        }
                    }
                }
            }

            if (shouldTakeCover)
            {
                return((int)BTNode.EState.Success);
            }
            else
            {
                return((int)BTNode.EState.Failure);
            }
        }
Exemple #3
0
        public List <GraphNode <GameObject> > FindPath(string startId, string goalId, Heuristic heuristic = null, bool blockedOffNodesAreAllowed = false, bool isAdmissible = true)
        {
            if (mbGraph == null)
            {
                return(new List <GraphNode <GameObject> >());
            }

            IWeightedDiGraph <GameObject, float> graph = mbGraph.graph;

            if (heuristic == null)
            {
                heuristic = (Transform s, Transform e) => 0;
            }

            List <GraphNode <GameObject> > path = null;
            bool solutionFound = false;

            Dictionary <string, float> gnDict = new Dictionary <string, float>();

            gnDict.Add(startId, default);

            Dictionary <string, float> fnDict = new Dictionary <string, float>();

            fnDict.Add(startId, heuristic(graph[startId].Data.transform, graph[goalId].Data.transform) + gnDict[startId]);

            Dictionary <string, string> pathDict = new Dictionary <string, string>();

            pathDict.Add(startId, null);

            PriorityQueue <float, string> openPQ = new PriorityQueue <float, string>();

            openPQ.Push(fnDict[startId], startId, fnDict[startId]);

            OrderedDictionary closedODict = new OrderedDictionary();

            while (!openPQ.Empty)
            {
                string currentId = openPQ.Pop().Value;
                closedODict[currentId] = true;

                if (currentId == goalId && isAdmissible)
                {
                    solutionFound = true;
                    break;
                }
                else if (closedODict.Contains(goalId))
                {
                    float gGoal             = gnDict[goalId];
                    bool  pathIsTheShortest = true;
                    foreach (PQEntry <float, string> entry in openPQ)
                    {
                        if (gGoal > gnDict[entry.Value])
                        {
                            pathIsTheShortest = false;
                            break;
                        }
                    }

                    if (pathIsTheShortest)
                    {
                        break;
                    }
                }

                List <GraphNode <GameObject> > neighbors = graph.Neighbors(currentId);
                foreach (GraphNode <GameObject> n in neighbors)
                {
                    float cost = graph.GetEdge(currentId, n.Id).Weight;

                    if (closedODict.Contains(n.Id))
                    {
                        continue;
                    }

                    if (GameplayManager.Instance.blockedOffNodes.Contains(n.Data.GetComponent <MBGraphNode>()) && !blockedOffNodesAreAllowed)
                    {
                        continue;
                    }

                    if (graph[n.Id].Data.GetComponentInChildren <OilSpillManager>() != null)
                    {
                        cost += 4; // hard coded oil spill cost
                    }
                    float gNeighbor = gnDict[currentId] + cost;
                    if (!gnDict.ContainsKey(n.Id) || gNeighbor < gnDict[n.Id])
                    {
                        pathDict[n.Id] = currentId;
                        gnDict[n.Id]   = gNeighbor;
                        float hNeighbor = heuristic(n.Data.transform, graph[goalId].Data.transform);
                        fnDict[n.Id] = gNeighbor + hNeighbor;

                        openPQ.Push(fnDict[n.Id], n.Id, hNeighbor);

                        if (openPQ.Top.Key > fnDict[n.Id])
                        {
                            closedODict[currentId] = true;
                        }
                    }
                }
            }

            if (!solutionFound && closedODict.Contains(goalId))
            {
                solutionFound = true;
            }

            if (solutionFound)
            {
                path = new List <GraphNode <GameObject> >();

                string key = goalId;
                while (key != null && pathDict.ContainsKey(key))
                {
                    path.Add(graph[key]);
                    key = pathDict[key];
                }

                path.Reverse();
            }

            return(path);
        }