/// <summary>
    /// Attempts to do whatever action this enemy does.
    /// Called after the character finishes moving.
    /// If the enemy is within range of an ally, it will push them.
    /// </summary>
    protected override void AttemptAction()
    {
        Node currentNode = MAContRef.GetNodeByWorldPosition(this.transform.position);
        // Get the nodes it can push
        List <Node> adjNodes = MAContRef.GetNodesDistFromNode(currentNode, 1);
        // Try to find an ally to push at any of these nodes
        Node nodeToAttack = null;

        foreach (Node curNode in adjNodes)
        {
            // If we found a node containing an ally
            if (curNode.Occupying == CharacterType.Ally)
            {
                nodeToAttack = curNode;
                break;
            }
        }

        // If we found an ally to push, push it
        if (nodeToAttack != null)
        {
            MARef.StartAttack(nodeToAttack.Position);
        }
        // Otherwise, just end the attack
        else
        {
            MARef.EndAttack();
        }
    }
    /// <summary>
    /// Attempts to do whatever action this enemy does.
    /// Called after the character finishes moving.
    /// Uses the character's skill on an enemy in range.
    /// </summary>
    override protected void AttemptAction()
    {
        // Recalculate the enemy's move and attack tiles.
        // We really only want their attack tiles, but those are based on the move tiles
        // Which are currently out of place since they are what the
        MARef.CalculateAllTiles();
        Vector2Int nodeToAttack = new Vector2Int(int.MaxValue, int.MaxValue);

        // Try to find an ally in range
        //Debug.Log("These are " + this.name + " at " + this.transform.position + " potential attack tiles: ");
        foreach (Node atkNode in MARef.AttackTiles)
        {
            //Debug.Log(atkNode.Position);
            MoveAttack potAlly = MAContRef.GetCharacterMAByNode(atkNode);
            // If we found an ally at that tile
            if (potAlly != null && potAlly.WhatAmI == CharacterType.Ally)
            {
                //Debug.Log("Attacking ^ That tile");
                nodeToAttack = atkNode.Position;
                break;
            }
        }
        // If there is no node to attack, just end the attack
        if (nodeToAttack.x == int.MaxValue && nodeToAttack.y == int.MaxValue)
        {
            MARef.EndAttack();
        }
        // If there is a node being attacked, start the attack
        else
        {
            MARef.StartAttack(nodeToAttack);
        }
    }
    /// <summary>
    /// Finds and returns the tile this enemy should move to.
    /// Specified in the overrides.
    /// </summary>
    /// <returns>Node that this enemy should move to</returns>
    protected override Node FindTileToMoveTo()
    {
        // 1) Find the closest ally
        Node closestAllyNode = null;
        int  closestAllyF    = int.MaxValue;

        // Iterate over each ally to find the closest
        foreach (Transform charTrans in GetAllyParent())
        {
            // Get the node that character is on
            Node charNode = MAContRef.GetNodeByWorldPosition(charTrans.position);
            // Path to that ally
            MAContRef.Pathing(StandingNode, charNode, CharacterType.Enemy, false);

            // If it is closer than the currently closest ally
            if (closestAllyF > charNode.F)
            {
                closestAllyNode = charNode;
                closestAllyF    = charNode.F;
            }
        }
        // If there is no closest ally node, we return the node the enemy is currently on
        if (closestAllyNode == null)
        {
            //Debug.Log("There was no closest Ally");
            return(StandingNode);
        }

        // 2) Find the path from that ally to the exit
        // Find the exit
        GameObject stairsObj  = GameObject.Find(ProceduralGenerationController.STAIRS_NAME);
        Node       stairsNode = MAContRef.GetNodeByWorldPosition(stairsObj.transform.position);
        // Initialize the list of nodes in the ally's path
        // This path is the one the ally would take if they did not care about enemies in their path
        List <Node> allyStraightPathToExit = new List <Node>();

        // Path from that ally to the exit
        // We say we don't care in the case that there is an enemy covering the exit
        if (MAContRef.Pathing(closestAllyNode, stairsNode, CharacterType.Enemy, false))
        {
            // Store this path
            Node curNode = closestAllyNode;
            while (curNode.WhereToGo != curNode)
            {
                curNode = curNode.WhereToGo;
                allyStraightPathToExit.Add(curNode);
            }
        }
        // Iterate over this straight path to get the actual path the ally would have to take
        List <Node> allyActualPathToExit = new List <Node>();

        for (int i = 0; i < allyStraightPathToExit.Count; ++i)
        {
            Node curNode = allyStraightPathToExit[i];
            // If the ally could actually go here, add the node to the allyActualPath
            if (curNode.Occupying == CharacterType.None ||
                curNode.Occupying == CharacterType.Ally)
            {
                allyActualPathToExit.Add(curNode);
            }
            // If the ally could not actually go here, find the next unoccupied node and
            // try to path from the previous node to the next unoccupied ndoe
            else
            {
                // Get the previous node
                Node prevNode = null;
                if (allyActualPathToExit.Count > 0)
                {
                    prevNode = allyActualPathToExit[allyActualPathToExit.Count - 1];
                }
                else
                {
                    prevNode = closestAllyNode;
                }
                // Find next unoccupied node
                // If there are no more unoccupied nodes, then we just have the unoccupied node be the last node
                Node unoccNode = allyStraightPathToExit[allyStraightPathToExit.Count - 1];
                for (int k = i + 1; k < allyStraightPathToExit.Count; ++k)
                {
                    Node curTestNode = allyStraightPathToExit[k];
                    // If we found the unoccupied node
                    if (curTestNode.Occupying == CharacterType.None ||
                        curTestNode.Occupying == CharacterType.Ally)
                    {
                        unoccNode = curTestNode;
                        break;
                    }
                }

                // Path from the previous node to the unoccupied node (we don't care if we can
                // actually make it there in case there was no unoccupied node)
                if (MAContRef.Pathing(prevNode, unoccNode, CharacterType.Ally, false))
                {
                    // Add this path to the actual path (we don't add the first or last node)
                    Node subPathNode = prevNode.WhereToGo;
                    while (subPathNode.WhereToGo != subPathNode)
                    {
                        allyActualPathToExit.Add(subPathNode);
                        subPathNode = subPathNode.WhereToGo;
                    }
                }
                // If the pathing fails, we have made the full path the enemy can take right now
                else
                {
                    break;
                }
            }
        }

        // 3) Find the closest node in this path to the enemy
        // We start by pathing to the first one and iterating. If the distance to a node
        // ever increases, that node is farther away, and the rest will be too, so we stop there
        Node targetNode = null;
        // The settle node is the node we will get close to if we can't reach any of the nodes in the path
        Node settleNode = StandingNode;
        int  settleF    = int.MaxValue;

        foreach (Node curNode in allyActualPathToExit)
        {
            // If we are already there or could actually move to there right now, we found our node
            if (curNode == StandingNode || MARef.MoveTiles.Contains(curNode))
            {
                targetNode = curNode;
                break;
            }
            // If we cannot instantly reach this tile, see how far it is away from this enemy
            // If we succesfully pathed there, compare the distance
            if (MAContRef.Pathing(StandingNode, curNode, CharacterType.Enemy))
            {
                // If the current node's F is smaller than the settleF, this node is closer
                if (settleF > curNode.F)
                {
                    settleNode = curNode;
                    settleF    = curNode.F;
                }
                // If it is farther away, all other ones will be farther away too, so dont keep testing
                else
                {
                    break;
                }
            }
        }

        // If we found a target node we can move to immediately, return it
        if (targetNode != null)
        {
            return(targetNode);
        }
        // If we did not find a target node, find node closest to the settle node that we can reach
        else
        {
            Node closestNode = StandingNode;
            int  closestF    = int.MaxValue;
            // Iterate over the possible tiles to move to
            foreach (Node moveTile in MARef.MoveTiles)
            {
                // Path from that move tile to the settle node
                // If successful, check if its closer than the current closestNode
                if (MAContRef.Pathing(moveTile, settleNode, CharacterType.Enemy))
                {
                    // It its closer, its the new closestNode
                    if (closestF > settleNode.F)
                    {
                        closestNode = moveTile;
                        closestF    = settleNode.F;
                    }
                }
            }

            return(closestNode);
        }
    }
    /// <summary>
    /// Finds and returns the tile this enemy should move to.
    /// Find the closest tile they can attack an enemy from.
    /// </summary>
    /// <returns>Node that this enemy should move to</returns>
    override protected Node FindTileToMoveTo()
    {
        //Debug.Log("------------------------------------------");
        //Debug.Log("Start Node " + StandingNode.Position);
        // 1) Get closest ally node with an attackable node
        Node closestAllyNode   = null;
        int  closestAllyF      = int.MaxValue;
        Node closestAttackNode = null;
        int  closestAttackF    = int.MaxValue;

        // Iterate over each ally to find the closest
        foreach (Transform charTrans in GetAllyParent())
        {
            // Get the node that character is on
            Node charNode = MAContRef.GetNodeByWorldPosition(charTrans.position);
            // Path to that ally
            MAContRef.Pathing(StandingNode, charNode, CharacterType.Enemy, false);

            // FOR TESTING
            //Vector2Int printPos = new Vector2Int(int.MaxValue, int.MaxValue);
            //if (closestAllyNode != null)
            //    printPos = closestAllyNode.Position;
            //Debug.Log(charNode.Position + " with " + charNode.F + " is being compared with " + printPos + " with " + closestAllyF);

            // If it is closer than the currently closest ally
            if (closestAllyF > charNode.F)
            {
                int charFVal = charNode.F;
                //Debug.Log("It was closer in distance");

                // 2) Get the closest node this enemy could attack that ally from
                // We know that is enemy is closer in walking distance, but we don't know if they have any openings to attack
                // So we test to see if we can find any openings to attack
                // Get the potential nodes to attack from
                List <Node> potAttackNodes = MAContRef.GetNodesDistFromNode(charNode, MARef.AttackRange);
                // Figure out which is closest to the standing positions
                //Debug.Log("The attack nodes are at ");
                foreach (Node curAdjNode in potAttackNodes)
                {
                    //Debug.Log(curAdjNode.Position);
                    // If the node is not occupied by someone other than this enemy
                    // since if this enemy is standing next to an ally, obvious that ally is the closest
                    MoveAttack curAdjEnemyMARef = MAContRef.GetCharacterMAByNode(curAdjNode);
                    if (curAdjNode.Occupying == CharacterType.None || curAdjEnemyMARef == MARef)
                    {
                        // Path there, if succesful, then see if it is closer than the current attackfrom node
                        // We say we don't care if we can get there (shouldCare=false) because we have already
                        // checked if someone was there and if there is someone there, it would be this enemy
                        if (MAContRef.Pathing(StandingNode, curAdjNode, CharacterType.Enemy, false))
                        {
                            // If it is closer than the closest attack from node
                            if (closestAttackF > curAdjNode.F)
                            {
                                //Debug.Log("It was closer and could be attacked");
                                // It is the new closest enemy node
                                closestAllyNode = charNode;
                                closestAllyF    = charFVal;

                                // It is the new closest attack node
                                closestAttackNode = curAdjNode;
                                closestAttackF    = curAdjNode.F;
                            }
                        }
                    }
                }
            }
        }
        // If there is no closest attack from node, return the current Node
        if (closestAttackNode == null)
        {
            //Debug.Log("There was no closest Ally with an opening to attack");
            return(StandingNode);
        }
        //Debug.Log("The closest ally is at " + closestAllyNode.Position);


        // This short find a tile to move to replaced the other way, which was faster, but much more complex

        // Short cut. If the closest attack node is one of the moveTiles, just return it
        // Iterate over the possible tiles to move to
        foreach (Node moveTile in MARef.MoveTiles)
        {
            // If its a part of the movetiles
            if (moveTile == closestAttackNode)
            {
                return(closestAttackNode);
            }
        }


        // If the shortcut didn't work do it the long way
        Node closestNode = StandingNode;
        int  closestF    = int.MaxValue;

        // Iterate over the possible tiles to move to
        foreach (Node moveTile in MARef.MoveTiles)
        {
            // Path from that move tile to the closest attack node
            // If successful, check if its closer than the closestNode
            if (MAContRef.Pathing(moveTile, closestAttackNode, CharacterType.Enemy))
            {
                // It its closer, its the new closestNode
                if (closestF > closestAttackNode.F)
                {
                    closestNode = moveTile;
                    closestF    = closestAttackNode.F;
                }
            }
        }

        // Its the endtile
        return(closestNode);
    }
    /// <summary>
    /// Finds and returns the tile this enemy should move to.
    /// Find the closest tile they can heal an enemy from
    /// </summary>
    /// <returns>Node that this enemy should move to</returns>
    override protected Node FindTileToMoveTo()
    {
        //Debug.Log("------------------------------------------");
        //Debug.Log("Start Node " + StandingNode.Position);
        // 1) Get closest enemy node that can be healed
        Node closestEnemyNode = null;
        int  closestEnemyF    = int.MaxValue;
        Node closestHealNode  = null;
        int  closestHealF     = int.MaxValue;

        // Iterate over each enemy to find the closest
        foreach (Transform charTrans in GetEnemyParent())
        {
            // Only if the enemy is active and not this character
            if (charTrans.gameObject.activeInHierarchy && charTrans != this.transform)
            {
                // We only want to try moving there is the enemy is damaged
                Health charHealth = charTrans.GetComponent <Health>();
                if (charHealth.CurHP < charHealth.MaxHP)
                {
                    Node charNode = MAContRef.GetNodeByWorldPosition(charTrans.position);
                    // Path to that enemy
                    MAContRef.Pathing(StandingNode, charNode, CharacterType.Enemy, false);

                    // FOR TESTING
                    //Vector2Int printPos = new Vector2Int(int.MaxValue, int.MaxValue);
                    //if (closestAllyNode != null)
                    //    printPos = closestAllyNode.Position;
                    //Debug.Log(charNode.Position + " with " + charNode.F + " is being compared with " + printPos + " with " + closestAllyF);

                    // If it is closer than the currently closest enemy
                    if (closestEnemyF > charNode.F)
                    {
                        int charFVal = charNode.F;
                        //Debug.Log("It was closer in distance");

                        // 2) Get the closest node this enemy could heal that enemy from
                        // We know that is enemy is closer in walking distance, but we don't know if they have any openings to heal
                        // So we test to see if we can find any openings to heal
                        // Get the potential nodes to heal from
                        List <Node> potHealNodes = MAContRef.GetNodesDistFromNode(charNode, MARef.AttackRange);
                        // Figure out which is closest to the standing positions
                        //Debug.Log("The attack nodes are at ");
                        foreach (Node curAdjNode in potHealNodes)
                        {
                            //Debug.Log(curAdjNode.Position);
                            // If the node is not occupied by someone other than this enemy
                            // since if this enemy is standing next to an ally, obvious that ally is the closest
                            MoveAttack curAdjEnemyMARef = MAContRef.GetCharacterMAByNode(curAdjNode);
                            if (curAdjNode.Occupying == CharacterType.None || curAdjEnemyMARef == MARef)
                            {
                                // Path there, if succesful, then see if it is closer than the current attackfrom node
                                // We say we don't care if we can get there (shouldCare=false) because we have already
                                // checked if someone was there and if there is someone there, it would be this enemy
                                if (MAContRef.Pathing(StandingNode, curAdjNode, CharacterType.Enemy, false))
                                {
                                    // If it is closer than the closest attack from node
                                    if (closestHealF > curAdjNode.F)
                                    {
                                        //Debug.Log("It was closer and could be attacked");
                                        // It is the new closest enemy node
                                        closestEnemyNode = charNode;
                                        closestEnemyF    = charFVal;

                                        // It is the new closest heal node
                                        closestHealNode = curAdjNode;
                                        closestHealF    = curAdjNode.F;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        // If there is no closest heal from node, make the enemy run away
        if (closestHealNode == null)
        {
            // Get the allies nodes before (we only want the allies who are close enough
            // that they could attack us on their next turn)
            List <Node> allyNodes = new List <Node>();
            foreach (Transform allyTrans in GetAllyParent())
            {
                Node curAllyNode = MAContRef.GetNodeByWorldPosition(allyTrans.position);
                // Calculate the distance between the ally's node and this enemy's node
                Vector2Int distVect = curAllyNode.Position - StandingNode.Position;
                int        dist     = Mathf.Abs(distVect.x + distVect.y);
                // Only add the ally if the enemy is within their attack range
                MoveAttack curAllyMA = MAContRef.GetCharacterMAByNode(curAllyNode);
                curAllyMA.ResetMyTurn();
                //Debug.Log("Dist from " + curAllyMA.name + ": " + dist + ". " + curAllyNode.Position + "->" + StandingNode.Position);
                if (dist <= curAllyMA.AttackRange + curAllyMA.MoveRange)
                {
                    //Debug.Log(curAllyMA.name + " is close enough to " + this.name);
                    allyNodes.Add(curAllyNode);
                }
            }
            // Set a reference to the node that is the farthest from all allies
            Node furthestNode = StandingNode;
            int  furthestF    = 0;
            // Get the move tiles of this enemy plus the node they are standing on
            List <Node> testNodes = new List <Node>(MARef.MoveTiles);
            testNodes.Add(StandingNode);
            // Iterate over this enemy's move tiles
            foreach (Node moveTile in testNodes)
            {
                int curAddedF = 0;
                // Path from each ally to the current tile
                foreach (Node curAllyNode in allyNodes)
                {
                    MAContRef.Pathing(curAllyNode, moveTile, CharacterType.Enemy, false);
                    curAddedF += moveTile.F;
                }
                // If the distance from each ally is greater than the last distance, it is the new furthest
                if (curAddedF > furthestF)
                {
                    furthestNode = moveTile;
                    furthestF    = curAddedF;
                }
            }

            // Return the furthest node
            return(furthestNode);
        }
        //Debug.Log("The closest ally is at " + closestAllyNode.Position);


        // Short cut. If the closest attack node is one of the moveTiles, just return it
        // Iterate over the possible tiles to move to
        if (MARef.MoveTiles != null)
        {
            foreach (Node moveTile in MARef.MoveTiles)
            {
                // If its a part of the movetiles
                if (moveTile == closestHealNode)
                {
                    return(closestHealNode);
                }
            }
        }
        else
        {
            Debug.LogError("MoveTiles is null");
        }


        // If the shortcut didn't work do it the long way
        Node closestNode = StandingNode;
        int  closestF    = int.MaxValue;

        if (MARef.MoveTiles != null)
        {
            // Iterate over the possible tiles to move to
            foreach (Node moveTile in MARef.MoveTiles)
            {
                // Path from that move tile to the closest attack node
                // If successful, check if its closer than the closestNode
                if (MAContRef.Pathing(moveTile, closestHealNode, CharacterType.Enemy))
                {
                    // It its closer, its the new closestNode
                    if (closestF > closestHealNode.F)
                    {
                        closestNode = moveTile;
                        closestF    = closestHealNode.F;
                    }
                }
            }
        }
        else
        {
            Debug.LogError("MoveTiles is null");
        }
        // Its the endtile
        return(closestNode);
    }