Ejemplo n.º 1
0
        protected List <Coord> filterThreats(List <Coord> units, Coord myUnit, float score)
        {
            List <Coord> lowThreat = new List <Coord>();

            foreach (Coord enemy in units)
            {
                AIBattle battle = new AIBattle(battlefield.units[enemy.x, enemy.y], battlefield.units[myUnit.x, myUnit.y], battlefield.map[myUnit.x, myUnit.y].Peek(), myUnit, battlefield);
                if (battle.score >= score)
                {
                    lowThreat.Add(enemy);
                }
            }
            return(lowThreat);
        }
Ejemplo n.º 2
0
        public override async Task <Move> getMove()
        {
            //Get all unit categories
            List <Coord> units   = findAllUnits();
            List <Coord> enemies = filterEnemies(units);
            List <Coord> allies  = filterAllies(units);

            List <Coord> available = filterHasMove(allies);

            // Select a unit based on type
            Coord unitCoord = new Coord(0, 0);
            Unit  curUnit   = null;

            foreach (Coord coord in available)
            {
                Unit unit = battlefield.units[coord.x, coord.y];
                if (unit is HealerUnit)
                {
                    unitCoord = coord;
                    curUnit   = unit;
                    break;
                }
                else if (unit is MeleeUnit)
                {
                    unitCoord = coord;
                    curUnit   = unit;
                }
                else if (!(curUnit is MeleeUnit))
                {
                    unitCoord = coord;
                    curUnit   = unit;
                }
            }


            if (curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield).Count == 0 && curUnit.getTargets(unitCoord.x, unitCoord.y, battlefield, character).Count == 0)
            {
                return(new Move(unitCoord, unitCoord));
            }

            if (VIPs.Contains(curUnit))
            {
                // Debug.Log("VIP");
                // Evade
                HashSet <Coord> dangerZone = enemyAttackZone(enemies);
                HashSet <Coord> safeZone   = safeMoves(unitCoord, dangerZone);
                if (safeZone.Count > 0)
                {
                    int   bestScore = Int32.MaxValue;
                    Coord bestCoord = null;
                    foreach (Coord coord in safeZone)
                    {
                        int distScore = sumDistances(coord, allies);
                        if (distScore < bestScore)
                        {
                            bestScore = distScore;
                            bestCoord = coord;
                        }
                    }
                    return(new Move(unitCoord, bestCoord));
                }
                else
                {
                    int          bestScore = 0;
                    Coord        bestCoord = null;
                    List <Coord> moves     = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield);
                    moves.Add(unitCoord);
                    foreach (Coord coord in moves)
                    {
                        int distScore = sumDistances(coord, enemies);
                        if (distScore > bestScore)
                        {
                            bestScore = distScore;
                            bestCoord = coord;
                        }
                    }
                    return(new Move(unitCoord, bestCoord));
                }
            }

            //Decide action based on type
            if (curUnit is HealerUnit)
            {
                Coord bestTarget = null;
                float bestScore  = 0;
                if (curUnit.hasMovedThisTurn)
                {
                    foreach (Coord target in curUnit.getTargets(unitCoord.x, unitCoord.y, battlefield, character))
                    {
                        Unit  targetUnit = battlefield.units[target.x, target.y];
                        float score      = targetUnit.maxHealth / targetUnit.getHealth();
                        if (score > bestScore)
                        {
                            bestTarget = target;
                            bestScore  = score;
                        }
                    }
                    return(new Move(unitCoord, bestTarget));
                }
                if (curUnit.getHealth() < curUnit.maxHealth * -0.4)
                {
                    // TODO
                    // Flee
                }
                else
                {
                    List <Coord> injured = filterInjured(allies, 0.6f);
                    if (injured.Count > 0)
                    {
                        HashSet <Coord> attackZone = curUnit.getTotalAttackZone(unitCoord.x, unitCoord.y, battlefield, character);
                        attackZone.IntersectWith(injured);
                        List <Coord> targets = new List <Coord>(attackZone);
                        if (targets.Count > 0)
                        {
                            bestTarget = null;
                            bestScore  = 0;
                            foreach (Coord target in targets)
                            {
                                Unit  targetUnit = battlefield.units[target.x, target.y];
                                float score      = targetUnit.maxHealth / targetUnit.getHealth();
                                if (score > bestScore)
                                {
                                    bestTarget = target;
                                    bestScore  = score;
                                }
                            }
                            // If unit has already moved heal best target
                            if (curUnit.hasMovedThisTurn)
                            {
                                return(new Move(unitCoord, bestTarget));
                            }
                            // Else choose best tile to move to
                            HashSet <Coord> adjacentTiles = new HashSet <Coord>();
                            adjacentTiles.Add(new Coord(bestTarget.x + 1, bestTarget.y));
                            adjacentTiles.Add(new Coord(bestTarget.x - 1, bestTarget.y));
                            adjacentTiles.Add(new Coord(bestTarget.x, bestTarget.y + 1));
                            adjacentTiles.Add(new Coord(bestTarget.x, bestTarget.y - 1));
                            adjacentTiles.IntersectWith(curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield));

                            // Hardcoded hack for time efficiency
                            if (manhattanDistance(unitCoord, bestTarget) == 1)
                            {
                                adjacentTiles.Add(unitCoord);
                            }
                            Coord bestCoord = null;
                            int   tileDef   = Int32.MinValue;
                            foreach (Coord coord in adjacentTiles)
                            {
                                if (tileDef < ConstantTables.TileDefense[(int)battlefield.map[coord.x, coord.y].Peek().tileType])
                                {
                                    tileDef   = ConstantTables.TileDefense[(int)battlefield.map[coord.x, coord.y].Peek().tileType];
                                    bestCoord = coord;
                                }
                            }
                            if (unitCoord.Equals(bestCoord))
                            {
                                return(new Move(unitCoord, bestTarget));
                            }
                            return(new Move(unitCoord, bestCoord));
                        }
                        else
                        {
                            // Find nearest injured and move to them
                            bestTarget = nearestCoord(unitCoord, injured);
                            Coord bestCoord = nearestCoord(bestTarget, curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield));
                            return(new Move(unitCoord, bestCoord));
                        }
                    }
                    else
                    {
                        // Evade around the capture point
                        HashSet <Coord> dangerZone = enemyAttackZone(enemies);
                        HashSet <Coord> safeZone   = safeMoves(unitCoord, dangerZone);
                        if (safeZone.Count > 0)
                        {
                            bestScore = Int32.MaxValue;
                            Coord bestCoord = null;
                            foreach (Coord coord in safeZone)
                            {
                                int distScore = manhattanDistance(capturePoint, coord);
                                if (distScore < bestScore)
                                {
                                    bestScore = distScore;
                                    bestCoord = coord;
                                }
                            }
                            return(new Move(unitCoord, bestCoord));
                        }
                        else
                        {
                            bestScore = 0;
                            Coord        bestCoord = null;
                            List <Coord> moves     = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield);
                            moves.Add(unitCoord);
                            foreach (Coord coord in moves)
                            {
                                int distScore = manhattanDistance(capturePoint, coord);
                                if (distScore > bestScore)
                                {
                                    bestScore = distScore;
                                    bestCoord = coord;
                                }
                            }
                            return(new Move(unitCoord, bestCoord));
                        }
                    }
                }
            }
            else if (curUnit is MeleeUnit)
            {
                if (curUnit.getHealth() < curUnit.maxHealth * -0.4)
                {
                    // TODO
                    // Flee
                }
                else
                {
                    // Seek an enemy to attack if health is high
                    HashSet <Coord> attackZone = curUnit.getTotalAttackZone(unitCoord.x, unitCoord.y, battlefield, character);
                    attackZone.IntersectWith(enemies);
                    List <Coord> targets    = new List <Coord>(attackZone);
                    float        bestScore  = 0;
                    Coord        bestTarget = null;
                    if (targets.Count > 0)
                    {
                        // If targets are in range find best
                        foreach (Coord target in targets)
                        {
                            Tile     enemyTile = battlefield.map[target.x, target.y].Peek();
                            Unit     enemy     = battlefield.units[target.x, target.y];
                            AIBattle battle    = new AIBattle(curUnit, enemy, enemyTile, target, battlefield);
                            if (battle.score > bestScore)
                            {
                                bestScore  = battle.score;
                                bestTarget = target;
                            }
                        }
                        // If unit has already moved attack best target
                        if (curUnit.hasMovedThisTurn)
                        {
                            return(new Move(unitCoord, bestTarget));
                        }
                        // Else choose best tile to move to
                        HashSet <Coord> adjacentTiles = new HashSet <Coord>();
                        adjacentTiles.Add(new Coord(bestTarget.x + 1, bestTarget.y));
                        adjacentTiles.Add(new Coord(bestTarget.x - 1, bestTarget.y));
                        adjacentTiles.Add(new Coord(bestTarget.x, bestTarget.y + 1));
                        adjacentTiles.Add(new Coord(bestTarget.x, bestTarget.y - 1));
                        adjacentTiles.IntersectWith(curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield));

                        // Hardcoded hack for time efficiency
                        if (manhattanDistance(unitCoord, bestTarget) == 1)
                        {
                            adjacentTiles.Add(unitCoord);
                        }
                        Coord bestCoord = null;
                        int   tileDef   = Int32.MinValue;
                        foreach (Coord coord in adjacentTiles)
                        {
                            if (tileDef < ConstantTables.TileDefense[(int)battlefield.map[coord.x, coord.y].Peek().tileType])
                            {
                                tileDef   = ConstantTables.TileDefense[(int)battlefield.map[coord.x, coord.y].Peek().tileType];
                                bestCoord = coord;
                            }
                        }
                        if (unitCoord.Equals(bestCoord))
                        {
                            return(new Move(unitCoord, bestTarget));
                        }
                        return(new Move(unitCoord, bestCoord));
                    }
                    else
                    {
                        // Move towards defence point
                        List <Coord> moves = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield);
                        moves.Add(unitCoord);
                        Coord bestCoord = nearestCoord(capturePoint, moves);
                        return(new Move(unitCoord, bestCoord));
                    }
                }
            }
            else if (curUnit is RangedUnit)
            {
                if (curUnit.getHealth() < curUnit.maxHealth * -0.4)
                {
                    // TODO
                    // Flee
                }
                else
                {
                    // Seek an enemy to attack if health is high
                    HashSet <Coord> attackZone = curUnit.getTotalAttackZone(unitCoord.x, unitCoord.y, battlefield, character);
                    attackZone.IntersectWith(enemies);
                    List <Coord> targets    = new List <Coord>(attackZone);
                    float        bestScore  = 0;
                    Coord        bestTarget = null;
                    if (targets.Count > 0)
                    {
                        // If targets are in range find best
                        foreach (Coord target in targets)
                        {
                            Tile     enemyTile = battlefield.map[target.x, target.y].Peek();
                            Unit     enemy     = battlefield.units[target.x, target.y];
                            AIBattle battle    = new AIBattle(curUnit, enemy, enemyTile, target, battlefield);
                            if (battle.score > bestScore)
                            {
                                bestScore  = battle.score;
                                bestTarget = target;
                            }
                        }
                        return(new Move(unitCoord, bestTarget));
                    }
                    else
                    {
                        // Move towards defence point
                        List <Coord> moves = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield);
                        moves.Add(unitCoord);
                        Coord bestCoord = nearestCoord(capturePoint, moves);
                        return(new Move(unitCoord, bestCoord));
                    }
                }
            }
            else if (curUnit is StatusUnit)
            {
                if (curUnit.getHealth() < curUnit.maxHealth * -0.4)
                {
                    // TODO
                    // Flee
                }
                else
                {
                    // Seek an enemy to attack if health is high
                    HashSet <Coord> attackZone = curUnit.getTotalAttackZone(unitCoord.x, unitCoord.y, battlefield, character);
                    attackZone.IntersectWith(enemies);
                    List <Coord> targets    = new List <Coord>(attackZone);
                    float        bestScore  = 0;
                    Coord        bestTarget = null;
                    if (targets.Count > 0)
                    {
                        // If targets are in range find best
                        foreach (Coord target in targets)
                        {
                            Tile     enemyTile = battlefield.map[target.x, target.y].Peek();
                            Unit     enemy     = battlefield.units[target.x, target.y];
                            AIBattle battle    = new AIBattle(curUnit, enemy, enemyTile, target, battlefield);
                            if (battle.score > bestScore)
                            {
                                bestScore  = battle.score;
                                bestTarget = target;
                            }
                        }
                        return(new Move(unitCoord, bestTarget));
                    }
                    else
                    {
                        // Move towards defence point
                        List <Coord> moves = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield);
                        moves.Add(unitCoord);
                        Coord bestCoord = nearestCoord(capturePoint, moves);
                        return(new Move(unitCoord, bestCoord));
                    }
                }
            }

            //Just so the player can keep track of what's happening
            await Task.Delay(300);

            return(new Move());
        }