Ejemplo n.º 1
0
    public static LinkedList<Point> GetWalkingSteps(Point start, BitArray goals, bool walkInWater = false, bool nearbyOk = false)
    {
        Bb.ReadBoard();

        if (!goals.ToPoints().Any())
        {
            return null;
        }
        Point[] starts = { start };
        var passable = Solver.GetPassable(true);
        var aStarPassable = new BitArray(passable);
        aStarPassable.Set(start, true);
        if (nearbyOk)
        {
            aStarPassable.Or(goals);
        }
        Func<Point, Point, int> cost = (c, n) => (Bb.Water.Get(n) && !walkInWater) ? 10 : 1;
        var route = Pather.AStar(starts, p => goals.Get(p), aStarPassable, cost, p => 0);
        if (route == null)
        {
            return null;
        }
        var steps = new LinkedList<Point>(route);
        steps.RemoveFirst();
        if (steps.Count > 0 && !passable.Get(steps.Last.Value))
        {
            steps.RemoveLast();
        }
        return steps;
    }
Ejemplo n.º 2
0
    public static void ReadBoard()
    {
        if (!init)
        {
            throw new Exception("Must call Init(AI ai) before using ReadBoard()");
        }
        Reset();

        tileLookup = BaseAI.tiles.ToDictionary(t => t.ToPoint());

        foreach (Tile tile in BaseAI.tiles)
        {
            int offset = GetOffset(tile.X, tile.Y);
            Point point = new Point(tile.X, tile.Y);

            // IsSpawning
            if (tile.IsSpawning)
            {
                IsSpawning[offset] = true;
            }

            // Glaciers
            if (tile.Depth == 0 && tile.WaterAmount > 0 && tile.Owner == 3)
            {
                Glaciers[offset] = true;
                GlaciersSet.Add(point);
            }

            // Trenches
            if (tile.Depth > 0 && tile.WaterAmount == 0)
            {
                Trenches[offset] = true;
            }

            // Water
            if (tile.Depth > 0 && tile.WaterAmount > 0)
            {
                Water[offset] = true;
            }

            // Our Spawns
            if (tile.Owner == usId && tile.PumpID == -1)
            {
                OurSpawns[offset] = true;
                OurSpawnSet.Add(point);
            }

            // Their Spawns
            if (tile.Owner == themId && tile.PumpID == -1)
            {
                TheirSpawns[offset] = true;
                TheirSpawnSet.Add(point);
            }

            // Our Pumps
            if (tile.Owner == usId && tile.PumpID != -1)
            {
                OurPumps[offset] = true;
            }

            // Their Pumps
            if (tile.Owner == themId && tile.PumpID != -1)
            {
                TheirPumps[offset] = true;
            }

            // Neutral Pumps
            if (tile.Owner == 2 && tile.PumpID != -1)
            {
                NeutralPumps[offset] = true;
            }
        }

        // Units
        foreach (Unit unit in BaseAI.units)
        {
            Point point = new Point(unit.X, unit.Y);
            int offset = GetOffset(point);

            // Our Units
            if (unit.Owner == usId)
            {
                OurUnits[offset] = true;
                OurUnitsSet.Add(unit);
                switch (unit.Type)
                {
                    case 0: OurWorkersSet.Add(unit); break;
                    case 1: OurScoutsSet.Add(unit); break;
                    case 2: OurTanksSet.Add(unit); break;
                }
            }

            // Their Units
            if (unit.Owner == themId)
            {
                TheirUnits[offset] = true;
                TheirUnitsSet.Add(unit);
                switch (unit.Type)
                {
                    case 0: TheirWorkersSet.Add(unit); break;
                    case 1: TheirScoutsSet.Add(unit); break;
                    case 2: TheirTanksSet.Add(unit); break;
                }
            }
        }

        var pumps = new BitArray(OurPumps).Or(TheirPumps).Or(NeutralPumps);
        var pumpLookup = BaseAI.pumpStations.ToDictionary(p => p.Id);
        foreach (var p in pumps.ToPoints())
        {
            var tile = tileLookup[p];
            if (!pumpLookup.ContainsKey(tile.PumpID))
            {
                continue;
            }
            var ps = pumpLookup[tile.PumpID];
            pumpLookup.Remove(ps.Id);

            var pump = new Pump(ps, p);
            if (pump.station.SiegeAmount > 0)
            {
                UnderSiege[GetOffset(pump.SW.x, pump.SW.y)] = true;
                UnderSiege[GetOffset(pump.NW.x, pump.NW.y)] = true;
                UnderSiege[GetOffset(pump.SE.x, pump.SE.y)] = true;
                UnderSiege[GetOffset(pump.NE.x, pump.NE.y)] = true;
            }
            if (tile.Owner == usId)
            {
                OurPumpSet.Add(pump);
            }
            else if (tile.Owner == themId)
            {
                TheirPumpSet.Add(pump);
            }
            else
            {
                NeutralPumpSet.Add(pump);
            }
        }

        pumpPointLookup = OurPumpSet.Union(TheirPumpSet).Union(NeutralPumpSet)
            .SelectMany(pump => pump.GetPoints().Select(point => new { ump = pump, oint = point }))
            .ToDictionary(a => a.oint, a => a.ump);
    }
Ejemplo n.º 3
0
    public static void MoveFarthestAndAttack(Droid attacker, BitArray targets)
    {
        if (attacker.AttacksLeft == 0)
        {
            return;
        }

        var liveTargets = targets.ToPoints().Where(p => Bb.DroidLookup[p].HealthLeft > 0);
        Func<Point, bool> patherPassable = p => IsPassable(p) || p.Equals(attacker.ToPoint());

        var movementSearch = new Pather.Search(new Point[] { attacker.ToPoint() }, patherPassable, p => false, (p1, p2) => 1, attacker.MovementLeft);
        var walkables = movementSearch.GScore.Keys.Where(p => movementSearch.GScore[p] <= attacker.MovementLeft);
        var walkablesWithTargets = walkables.Where(p => liveTargets.Any(t => p.IsInRange(attacker.Range, t)));

        Console.WriteLine("MoveFarthestAndAttack " + attacker.ToPoint());
        Console.WriteLine("Walkables: " + walkables.Count());
        Console.WriteLine("WalkablesWithTargets: " + walkablesWithTargets.Count());

        if (walkablesWithTargets.Any())
        {
            var walkTo = walkablesWithTargets.MaxBy(p => movementSearch.GScore[p]);
            var path = Pather.ConstructPath(movementSearch.CameFrom, walkTo);
            foreach (var step in path.Skip(1))
            {
                Console.WriteLine("Move {0} -> {1}", attacker.ToPoint(), step);
                attacker.move(step.x, step.y);
            }
            var target = liveTargets.First(t => attacker.IsInRange(t));
            attacker.operate(target.x, target.y);
        }
    }
Ejemplo n.º 4
0
    public static void MoveAndAttack(Droid attacker, BitArray targets)
    {
        Bb.ReadBoard();

        if (attacker.AttacksLeft <= 0)
        {
            return;
        }

        BitArray validTargets;
        if ((Unit)attacker.Variant == Unit.HACKER)
        {
            validTargets = targets.ToPoints().Where(t => t.IsHackable()).ToBitArray();
        }
        else if ((Unit)attacker.Variant == Unit.REPAIRER)
        {
            validTargets = targets.ToPoints().Where(t => t.IsRepairable()).ToBitArray();
        }
        else
        {
            validTargets = targets.ToPoints().Where(t => t.IsAttackable()).ToBitArray();
            if (Bb.KillHangerCountDown > 0)
            {
                validTargets = validTargets.ToPoints().Where(t =>
                    {
                        var droid = Bb.DroidLookup[t];
                        return !((Unit)droid.Variant == Unit.HANGAR && droid.HealthLeft <= attacker.Attack);
                    }).ToBitArray();
            }
        }

        Func<Point, bool> patherPassable = p => IsPassable(p) || p.Equals(attacker.ToPoint()) || validTargets.Get(p);

        var path = Pather.AStar(new[] { attacker.ToPoint() }, patherPassable, validTargets.ToFunc());
        if (path == null)
        {
            return;
        }
        if (path.Count() < 2)
        {
            Console.WriteLine("Bad path from attacker " + attacker.Id);
        }

        MoveAndAttack(attacker, path.Skip(1));
    }
Ejemplo n.º 5
0
    public static IEnumerable<Point> Reach(Point start, BitArray targets, BitArray passable)
    {
        var open = new Queue<Point>();
        open.Enqueue(start);

        var closed = new HashSet<Point>();

        var targetSet = new HashSet<Point>(targets.ToPoints());

        var reach = new HashSet<Point>();

        while (open.Count > 0)
        {
            Point current = open.Dequeue();
            closed.Add(current);

            if (targets.Get(current))
            {
                reach.Add(current);
                if (reach.Count == targetSet.Count)
                {
                    break;
                }
            }

            foreach (var n in GetNeighbors(current, passable))
            {
                if (!closed.Contains(n))
                {
                    open.Enqueue(n);
                }
            }
        }

        return reach;
    }