Beispiel #1
0
        public static bool MoveOff(Beaver beaver)
        {
            if (!beaver.CanMove())
            {
                return(false);
            }

            var target = beaver.Tile.GetNeighbors().FirstOrDefault(n => n.IsPathable() && beaver.Moves >= GetMoveCost(beaver.Tile, n));

            return(target != null && beaver.Move(target));
        }
Beispiel #2
0
        /// <summary>Gets off the lodge if it's on one</summary>
        private bool GetOffLodge(Beaver b)
        {
            if (b.Tile.LodgeOwner == null)
            {
                return(false);
            }

            Tile target = this.GetNeighborWhere(b.Tile, t => t.LodgeOwner == null && b.Moves < b.MoveCost(t));

            return(target != null && b.Move(target));
        }
Beispiel #3
0
        /// <summary>Harvests resource</summary>
        private bool Harvest(Beaver b, string resource)
        {
            // Don't bother harvesting if it can't hold anymore stuff
            if (b.Branches + b.Food >= b.Job.CarryLimit)
            {
                return(false);
            }

            bool keepGoing = false;

            // Function for finding movement targets
            Func <Tile, bool> isTarget = t => t.Spawner != null && t.Spawner.Type == resource && !t.Spawner.HasBeenHarvested && t.Spawner.Health > 3;

            // Find nearest resource, skipping current node
            IEnumerable <Tile> basePath = this.FindPathCustom(b.Tile,
                                                              (t, parent) => {
                double cost = this.GetCost(t, parent, b);
                if (cost < 0)
                {
                    return(cost);
                }
                return(this.IsNextTo(t, isTarget) ? 0 : cost);
            })
                                          .Skip(1);

            // Traverse path
            LinkedList <Tile> path = new LinkedList <Tile>(basePath);

            while (path.Any())
            {
                // If can't move anymore
                if (b.Moves < b.MoveCost(path.First()) || !b.Move(path.First()))
                {
                    break;
                }
                path.RemoveFirst();
                keepGoing = true;
            }

            // Try to harvest if next to the target spawner
            Tile target = this.GetNeighborWhere(b.Tile, isTarget);

            if (target != null && b.Actions > 0)
            {
                if (AI.Verbose)
                {
                    Console.WriteLine("Harvesting resource");
                }
                b.Harvest(target.Spawner);
                keepGoing = true;
            }

            return(keepGoing);
        }
Beispiel #4
0
        public static void MoveAlong(Beaver beaver, IEnumerable <Point> steps, bool dontStopInDanger = false)
        {
            if (!steps.Any())
            {
                return;
            }

            IEnumerable <Point> dontStops = new Point[0];

            if (dontStopInDanger)
            {
                var fears = AI._Player.Opponent.Beavers
                            .Where(b => b.CanBeAttacked())
                            .Where(b => b.Job == AI.Basic || b.Job == AI.Fighter || b.Job == AI.Bulky || b.Job == AI.HotLady)
                            .Where(b => !b.Tile.GetNeighbors().Any(n => n.Beaver != null && n.Beaver.Owner == AI._Player));
                if (fears.Any())
                {
                    dontStops = AI._Game.Tiles.Where(t => fears.Select(b => b.ToPoint().ManhattanDistance(t.ToPoint())).Min() == 2)
                                .ToPoints()
                                .ToHashSet();
                }
            }

            AI.GoalLocations[beaver.Id] = steps.Last();
            if (!beaver.CanMove())
            {
                return;
            }

            var queue = steps.SkipWhile(p => p.Equals(beaver.ToPoint())).ToQueue();

            while (queue.Count > 0 && queue.Peek().ToTile().IsPathable() && GetMoveCost(beaver.Tile, queue.Peek().ToTile()) <= beaver.Moves && !dontStops.Contains(queue.Peek()))
            {
                beaver.Move(queue.Dequeue().ToTile());
            }
        }
Beispiel #5
0
        /// <summary>Attacks enemy beavers</summary>
        private bool Attack(Beaver b)
        {
            if (b.Actions <= 0)
            {
                return(false);
            }

            bool retValue = false;

            // Find suitable building spot
            Func <Tile, bool> isTarget = t => t.Beaver != null && t.Beaver.Owner != this.Player && t.Beaver.Recruited;

            IEnumerable <Tile> pfResult;

            if (this.NextLodge == null)
            {
                // Look for a spot two spaces away from an unclaimed food spot
                pfResult = this.FindPathCustom(b.Tile,
                                               (t, parent) => {
                    double cost = this.GetCost(t, parent, b);
                    if (cost < 0)
                    {
                        return(cost);
                    }
                    return(this.IsNextTo(t, isTarget) ? 0 : cost);
                })
                           .Skip(1);

                // Look for a spot two spaces away from any unclaimed resource
                if (!pfResult.Any())
                {
                    pfResult = this.FindPathCustom(b.Tile,
                                                   (t, parent) => {
                        double cost = this.GetCost(t, parent, b);
                        if (cost < 0)
                        {
                            return(cost);
                        }
                        if (isTarget(t))
                        {
                            return(0);
                        }
                        return(cost);
                    })
                               .Skip(1);
                }

                // Set this as the next lodge spot
                if (pfResult.Any())
                {
                    this.NextLodge = pfResult.Last();
                }
            }
            else
            {
                pfResult = this.FindPathCustom(b.Tile, this.NextLodge).Skip(1);
            }

            // Traverse path
            LinkedList <Tile> path = new LinkedList <Tile>(pfResult);

            while (path.Any())
            {
                // If can't move
                if (b.Moves < b.MoveCost(path.First()) || !b.Move(path.First()))
                {
                    break;
                }
                path.RemoveFirst();
                retValue = true;
            }

            // Try to attack a beaver
            Tile target = this.GetNeighborWhere(b.Tile, isTarget);

            if (target != null)
            {
                while (b.Actions > 0 && b.Health > target.Beaver.Job.Damage)
                {
                    b.Attack(target.Beaver);
                }
            }

            return(retValue);
        }
Beispiel #6
0
        /// <summary>Builds lodges</summary>
        private bool Build(Beaver b)
        {
            // Check if it can even build a lodge
            if (b.Branches <= 0)
            {
                return(false);
            }

            bool retValue = false;

            // Find suitable building spot
            bool foodOnly = true;

            // ReSharper disable once AccessToModifiedClosure
            Func <Tile, bool> isTarget = t => t.LodgeOwner == null && t.Spawner == null && t.FlowDirection == null && this.IsNextTo(t, n1 => this.IsNextTo(n1, n2 => n2.Spawner != null && (!foodOnly || n2.Spawner.Type == "food") && !this.ClaimedResources.Contains(n2.Id)));

            IEnumerable <Tile> basePath;

            if (this.NextLodge == null)
            {
                // Look for a spot two spaces away from an unclaimed food spot
                basePath = this.FindPathCustom(b.Tile,
                                               (t, parent) => {
                    double cost = this.GetCost(t, parent, b);
                    if (cost < 0)
                    {
                        return(cost);
                    }
                    return(isTarget(t) ? 0 : cost);
                })
                           .Skip(1);

                // Look for a spot two spaces away from any unclaimed resource
                if (!basePath.Any())
                {
                    foodOnly = false;
                    basePath = this.FindPathCustom(b.Tile,
                                                   (t, parent) => {
                        double cost = this.GetCost(t, parent, b);
                        if (cost < 0)
                        {
                            return(cost);
                        }
                        return(isTarget(t) ? 0 : cost);
                    })
                               .Skip(1);
                }

                // Set this as the next lodge spot
                if (basePath.Any())
                {
                    this.NextLodge = basePath.Last();
                }
            }
            else
            {
                basePath = this.FindPathCustom(b.Tile, this.NextLodge).Skip(1);
            }

            // Traverse path
            LinkedList <Tile> path = new LinkedList <Tile>(basePath);

            while (path.Any())
            {
                // If can't move
                if (b.Moves < b.MoveCost(path.First()) || !b.Move(path.First()))
                {
                    break;
                }
                path.RemoveFirst();
                retValue = true;
            }

            // Try to build a lodge
            Tile target = b.Tile;

            if (isTarget(b.Tile))
            {
                if (b.Actions > 0 && target.Branches >= this.Player.BranchesToBuildLodge)
                {
                    if (AI.Verbose)
                    {
                        Console.WriteLine("Building lodge");
                    }
                    b.BuildLodge();
                    this.NextLodge = null;
                    retValue       = true;

                    // Set nearby food source as "claimed"
                    // TODO: If the lodge is destroyed, unclaim those sources

                    IEnumerable <Tile> sources = from n1 in new[] { target.TileNorth, target.TileEast, target.TileSouth, target.TileWest }
                    where n1 != null
                    from n2 in new[] { n1.TileNorth, n1.TileEast, n1.TileSouth, n1.TileWest }
                    where n2?.Spawner != null
                    select n2;
                    foreach (Tile source in sources)
                    {
                        this.ClaimedResources.Add(source.Id);
                    }
                }
                else if (b.Actions > 0 && b.Branches > 0)
                {
                    if (AI.Verbose)
                    {
                        Console.WriteLine("Dropping branches for lodge");
                    }
                    b.Drop(target, nameof(b)); // branches
                    retValue = true;
                }
            }

            return(retValue);
        }
Beispiel #7
0
        /// <summary>Picks up resource from owned lodges</summary>
        private bool Pickup(Beaver b, string resource)
        {
            if (b.Branches + b.Food >= b.Job.CarryLimit)
            {
                return(false);
            }

            bool keepGoing = false;

            // Go to nearest lodge with the given resource
            Func <Tile, bool> isTarget = t => t.LodgeOwner == this.Player && resource == "branches" ? t.Branches > 0 : t.Food > 0;

            // Find nearest resource, skipping current node
            IEnumerable <Tile> basePath = this.FindPathCustom(b.Tile,
                                                              (t, parent) => {
                double cost = this.GetCost(t, parent, b);
                if (cost < 0)
                {
                    return(cost);
                }
                if (this.IsNextTo(t, isTarget))
                {
                    return(0);
                }
                return(cost);
            })
                                          .Skip(1);

            // Traverse path
            LinkedList <Tile> path = new LinkedList <Tile>(basePath);

            while (path.Any())
            {
                // If can't move anymore
                if (b.Moves < b.MoveCost(path.First()) || !b.Move(path.First()))
                {
                    break;
                }
                path.RemoveFirst();
                keepGoing = true;
            }

            // Try to pick up resources if next to the target lodge
            Tile target = this.GetNeighborWhere(b.Tile, isTarget);

            if (target != null && b.Actions > 0)
            {
                int amount = resource == "food" ? target.Food : target.Branches;
                if (target.LodgeOwner == this.Player)
                {
                    amount--;
                }
                amount = Math.Min(amount, b.Job.CarryLimit - b.Branches - b.Food);
                if (amount > 0)
                {
                    if (AI.Verbose)
                    {
                        Console.WriteLine("Picking up resource");
                    }
                    b.Pickup(target, resource, amount);
                    keepGoing = true;
                }
            }

            return(keepGoing);
        }
Beispiel #8
0
        /// <summary>Stores carried resources in lodges</summary>
        private bool Store(Beaver b)
        {
            // Don't bother storing if it doesn't have a full inventory
            if (b.Branches + b.Food < b.Job.CarryLimit)
            {
                return(false);
            }

            bool retValue = false;

            // Function for finding movement targets
            Func <Tile, bool> isTarget = t => t.LodgeOwner == this.Player;

            // Find nearest lodge, skipping current node
            IEnumerable <Tile> basePath = this.FindPathCustom(b.Tile,
                                                              (t, parent) => {
                double cost = this.GetCost(t, parent, b);
                if (cost < 0)
                {
                    return(cost);
                }
                return(this.IsNextTo(t, isTarget) ? 0 : cost);
            })
                                          .Skip(1);

            // Traverse path
            LinkedList <Tile> path = new LinkedList <Tile>(basePath);

            while (path.Any())
            {
                // If can't move anymore
                if (b.Moves < b.MoveCost(path.First()) || !b.Move(path.First()))
                {
                    break;
                }
                path.RemoveFirst();
                retValue = true;
            }

            // Drop off resources at lodge
            Tile target = this.GetNeighborWhere(b.Tile, isTarget);

            if (target != null && b.Actions > 0)
            {
                if (AI.Verbose)
                {
                    Console.WriteLine("Dropping resources on lodge");
                }
                if (b.Branches > 0)
                {
                    b.Drop(target, "b"); // branches
                }
                if (b.Food > 0)
                {
                    b.Drop(target, "f"); // food
                }
                retValue = true;
            }

            return(retValue);
        }