Ejemplo n.º 1
0
    public static float EvaluateAOEAttackState(GameState gameState, HexTileController htc)
    {
        //Data is going into a MinQ, smaller number is better
        float          aiHealthLost = 0;
        float          playerLost   = 0;
        List <HexTile> attackRange  = htc.FindRadius(gameState.selfTile, gameState.selfChar.stats.aoeRange);

        attackRange.Add(gameState.selfTile);
        foreach (HexTile hex in attackRange)
        {
            foreach (Character c in gameState.aiChars)
            {
                if (hex.Equals(htc.FindHex(c.gameCharacter.position)))
                {
                    aiHealthLost += gameState.selfChar.stats.attackdmg;
                }
            }
            foreach (Character c in gameState.playerChars)
            {
                if (hex.Equals(htc.FindHex(c.gameCharacter.position)))
                {
                    playerLost += gameState.selfChar.stats.attackdmg;
                }
            }
        }


        return(aiHealthLost - playerLost);
    }
Ejemplo n.º 2
0
    public List <Character> GetAllInAOERange(HexTile tile, int tiles)
    {
        List <Character> inrange = new List <Character>();
        int radius = tiles;

        GameObject[] tmp = Array.ConvertAll <HexTile, GameObject>(htc.FindRadius(tile, radius).ToArray(), t => t.HoldingObject);
        for (int i = 0; i < tmp.Length; i++)
        {
            if (tmp[i] == null)
            {
                continue;
            }
            Agent agent = tmp[i].GetComponent <Agent>();
            if (agent != null)
            {
                inrange.Add(agent.character);
            }
        }

        return(inrange);
    }
Ejemplo n.º 3
0
    public static MiniAction DecideAction(GameState gameState, HexTileController htc)
    {
        MoveDebug md           = GameObject.FindGameObjectWithTag("MoveDebug").GetComponent <MoveDebug>();
        int       attackRadius = gameState.selfChar.stats.range;

        // **** Spencer Notes ******

        /*  If you can attack, do
         *  Else evaluate all the locations you could possible move to,
         *  then take the largest and move to it
         */
        //If this character is the hacker, find best possible place to put the attack
        if (gameState.selfChar.characterclass == CharacterClass.HACKER)
        {
            List <HexTile> attackRange  = htc.FindRadius(gameState.selfTile, attackRadius);
            PriorityQueue  attackFringe = new PriorityQueue();
            md.ClearAll();
            foreach (HexTile hex in attackRange)
            {
                GameState gs    = new GameState(gameState.aiChars, gameState.playerChars, hex, gameState.selfChar);
                float     value = EvaluateAOEAttackState(gs, htc);
                md.SetText(hex, value);
                //If this attack will do more damage to yourself, don't add it to the list
                if (value < -1)
                {
                    attackFringe.Push((hex, null), value);
                }
            }
            //If there is nothing in the list (No good attacks) Move intead
            if (attackFringe.HasNext())
            {
                ((HexTile attackHex, List <int> a), float value) = attackFringe.PopWithVal();
                //If this attack only did damage to 1 character (or 1 more than your own chars)

                /* *** Come back if you have more time ****
                 * if (value <= gameState.selfChar.stats.attackdmg)
                 * {
                 *  //Find see if there is a better place to attack and move to that spot
                 *
                 * }*/
                return(new MiniAttack()
                {
                    type = "AOEAttack", attackLocation = attackHex.Position
                });
            }
        }
        else if (gameState.selfChar.characterclass == CharacterClass.PSYONIC)
        {
            Character needestChar     = null;
            Character cantReachChar   = null;
            float     cantReachHealth = 1;
            float     leastHealth     = 1;
            foreach (Character character in gameState.aiChars)
            {
                if (character.CompareTo(gameState.selfChar) != 0)
                {
                    int   distance = htc.FindHexDistance(gameState.selfChar.gameCharacter.position, character.gameCharacter.position);
                    float health   = character.stats.health / character.stats.maxHealth;
                    //If you can heal the character, and the health is less than 1
                    if (health < leastHealth)
                    {
                        if (distance <= attackRadius)
                        {
                            leastHealth = health;
                            needestChar = character;
                        }
                        else
                        {
                            cantReachHealth = health;
                            cantReachChar   = character;
                        }
                    }
                }
            }
            if (leastHealth < 1)
            {
                return(new MiniAttack()
                {
                    type = "Attack", toAttack = needestChar
                });
            }
            else if (cantReachHealth < 1)
            {
                //If there is a character in need that you can't reach, move towards it
                Debug.Log("Healer Moving towards " + cantReachChar.name);
                HexTile toMovTo = MoveTowards(cantReachChar, gameState, htc, true);
                return(new MiniMove()
                {
                    type = "Move", Dest = toMovTo
                });
            }
            else
            {
                //Can't heal yourself*******
                //Move towards the Ranger
                Character target = GetCharacter(gameState.aiChars, CharacterClass.RANGED);
                if (target != null)
                {
                    HexTile toMovTo = MoveTowards(target, gameState, htc, true);
                    return(new MiniMove()
                    {
                        type = "Move", Dest = toMovTo
                    });
                }
                target = GetCharacter(gameState.aiChars, CharacterClass.HACKER);
                if (target != null)
                {
                    HexTile toMovTo = MoveTowards(target, gameState, htc, true);
                    return(new MiniMove()
                    {
                        type = "Move", Dest = toMovTo
                    });
                }
                target = GetCharacter(gameState.aiChars, CharacterClass.MELEE);
                if (target != null)
                {
                    HexTile toMovTo = MoveTowards(target, gameState, htc, true);
                    return(new MiniMove()
                    {
                        type = "Move", Dest = toMovTo
                    });
                }
                //No other characters but you exist, await the sweet release of death
                return(new MiniMove()
                {
                    type = "Move", Dest = gameState.selfTile
                });
            }
        }
        else
        {
            Character weakestChar = null;
            Character deadChar    = null;
            float     leastHealth = int.MaxValue;
            foreach (Character character in gameState.playerChars)
            {
                int distance = htc.FindHexDistance(gameState.selfChar.gameCharacter.position, character.gameCharacter.position);

                if (distance <= attackRadius)
                {
                    //If your attack would kill this character, target this one above all else
                    if ((Mathf.Max(0, character.stats.health - gameState.selfChar.stats.attackdmg) / character.stats.maxHealth) <= 0)
                    {
                        deadChar = character;
                    }
                    if ((character.stats.health / character.stats.maxHealth) < leastHealth)
                    {
                        leastHealth = (character.stats.health / character.stats.maxHealth);
                        weakestChar = character;
                    }
                }
            }
            //Attack the soon to be dead character if it can
            if (deadChar != null)
            {
                return(new MiniAttack()
                {
                    type = "Attack", toAttack = deadChar
                });
            }
            if (weakestChar != null)
            {
                return(new MiniAttack()
                {
                    type = "Attack", toAttack = weakestChar
                });
            }
        }

        // **** Spencer Notes ******

        /* Could not find anything to attack so move to the best possible location
         */

        List <HexTile>               possibleMoves  = htc.FindRadius(gameState.selfTile, gameState.selfChar.stats.speed);
        List <Character>             allChars       = gameState.aiChars.Concat(gameState.playerChars).ToList();
        List <(HexTile, List <int>)> possibleMoves2 = ValidateRadius(gameState.selfTile, possibleMoves, gameState.selfChar.stats.speed, allChars, htc);

        //possibleMoves = ValidateRadius(gameState.selfTile, possibleMoves, gameState.selfChar.stats.speed, allChars, htc);
        possibleMoves = new List <HexTile>();
        foreach ((HexTile hex, List <int> path) in possibleMoves2)
        {
            possibleMoves.Add(hex);
        }
        PriorityQueue fringe = new PriorityQueue();

        foreach (HexTile hex in possibleMoves)
        {
            GameState gs = new GameState(gameState.aiChars, gameState.playerChars, hex, gameState.selfChar);
            fringe.Push((hex, null), EvaluateState(gs, htc));
        }

        if (!fringe.HasNext())
        {
            //No avialable moves, move to self
            return(new MiniMove()
            {
                type = "Move", Dest = gameState.selfTile
            });
        }
        (HexTile state, List <int> actions) = fringe.Pop();
        return(new MiniMove()
        {
            type = "Move", Dest = state
        });
    }
Ejemplo n.º 4
0
    public static HexTile MoveTowards(Character target, GameState gameState, HexTileController htc, bool runFromEnemy = false)
    {
        //choose the tile you want to move to, either the character directly, or a tile next to the character that is away from the enemy
        HexTile targetTile = htc.FindHex(target.gameCharacter.position);

        if (runFromEnemy)
        {
            List <HexTile> tilesAroundTarget = htc.FindRadius(targetTile, 1);
            int            farthest          = 0;
            foreach (HexTile hexTile in tilesAroundTarget)
            {
                if (!hexTile.IsObstacle && hexTile.HoldingObject == null)
                {
                    //Find distance to all player characters
                    int newDist = 0;
                    foreach (Character c in gameState.playerChars)
                    {
                        newDist += htc.FindHexDistance(hexTile.Position, c.gameCharacter.position);
                    }
                    //You want the distance to the player to be largest
                    if (newDist > farthest)
                    {
                        farthest   = newDist;
                        targetTile = hexTile;
                    }
                }
            }
        }
        List <int> moves = GreedySearch(gameState.selfTile, targetTile, htc);

        //If run from enemy is false, your target in ON a character, so remove that last step
        if (!runFromEnemy)
        {
            //Remove the last step (the one on the distination character)
            if (moves.Count > 0)
            {
                moves.RemoveAt(moves.Count - 1);
            }
        }

        Debug.Log("Psyonic wants to move ...");
        foreach (int i in moves)
        {
            Debug.Log(i);
        }
        Debug.Log("To get to " + target.name);

        //If you were already right next to the target, don't go anywhere
        if (moves.Count == 0)
        {
            return(gameState.selfTile);
        }
        //Only keep the number of steps that you are allowed to move
        //Starting hex is your own
        HexTile hex = gameState.selfTile;

        //Repet until you hit your step count, or you run out of moves
        for (int i = 0; i < Mathf.Min(gameState.selfChar.stats.speed, moves.Count); i++)
        {
            //Get the neighbor that the path tells you too
            hex = hex.nexts[moves[i]];
        }
        return(hex);
    }