private Dictionary <TerritoryIDType, PossibleExpandTarget> GetExpansionWeights(HashSet <TerritoryIDType> terrs)
        {
            var bonusPaths = terrs
                             .SelectMany(o => Bot.Map.Territories[o].PartOfBonuses)
                             .Where(o => Bot.BonusValue(o) > 0)
                             .Distinct()
                             .Select(o =>
            {
                if (Bot.PastTime(7))
                {
                    return(null);    //stop trying to expand if we're slow
                }
                return(BonusPath.TryCreate(Bot, o, ts => ts.OwnerPlayerID == Bot.PlayerID));
            })
                             .Where(o => o != null)
                             .ToDictionary(o => o.BonusID, o => o);

            var turnsToTake = bonusPaths.Keys.ToDictionary(o => o, o => TurnsToTake(o, bonusPaths[o]));

            foreach (var cannotTake in turnsToTake.Where(o => o.Value == null).ToList())
            {
                turnsToTake.Remove(cannotTake.Key);
                bonusPaths.Remove(cannotTake.Key);
            }

            var bonusWeights = bonusPaths.Keys.ToDictionary(o => o, o => ExpansionHelper.WeighBonus(Bot, o, ts => ts.OwnerPlayerID == Bot.PlayerID, turnsToTake[o].NumTurns));

            AILog.Log("Expand", "GetExpansionWeights called with " + terrs.Count + " territories.  Weighted " + bonusWeights.Count + " bonuses:");
            foreach (var bw in bonusWeights.OrderByDescending(o => o.Value).Take(10))
            {
                AILog.Log("Expand", " - " + Bot.BonusString(bw.Key) + " Weight=" + bw.Value + " " + turnsToTake[bw.Key] + " TurnsToTakeByDistance=" + bonusPaths[bw.Key].TurnsToTakeByDistance + " CriticalPath=" + bonusPaths[bw.Key].TerritoriesOnCriticalPath.Select(o => Bot.TerrString(o)).JoinStrings(", "));
            }

            var ret = new Dictionary <TerritoryIDType, PossibleExpandTarget>();

            foreach (var terr in terrs)
            {
                ret[terr] = new PossibleExpandTarget(Bot, terr, Bot.Map.Territories[terr].PartOfBonuses.Where(b => bonusPaths.ContainsKey(b)).ToDictionary(b => b, b => new PossibleExpandTargetBonus(bonusWeights[b], bonusPaths[b], turnsToTake[b])));
            }

            AILog.Log("Expand", "Finished weighing " + terrs.Count + " territories:");
            foreach (var terr in ret.OrderByDescending(o => o.Value.Weight).Take(10))
            {
                AILog.Log("Expand", " - " + Bot.TerrString(terr.Key) + " Weight=" + terr.Value);
            }

            return(ret);
        }
Beispiel #2
0
        public override void Go(int remainingUndeployed, bool highlyWeightedOnly)
        {
            //don't search more than 10% of the map. We won't cross the entire map to get a bonus, we're looking for ones near us.  For small maps, never search fewer than 5.
            var maxDistance = highlyWeightedOnly ? 1 : Math.Max(5, (int)(Bot.Map.Territories.Count / 10));

            var armyMult     = ExpansionHelper.ArmyMultiplier(Bot.Settings.DefenseKillRate);
            var bonusWeights = Bot.Map.Bonuses.Keys.Where(o => Bot.BonusValue(o) > 0).ToDictionary(o => o, o => ExpansionHelper.WeighBonus(Bot, o, ts => ts.OwnerPlayerID == Bot.PlayerID, 1)); //assume 1 turn to take for now, which is wrong, but it gives us an even baseline. We'll adjust for turnsToTake in adjustedBonusWeights.

            AILog.Log("ExpandMultiAttack", "remainingUndeployed=" + remainingUndeployed + ". " + bonusWeights.Count + " base weights: ");
            foreach (var bw in bonusWeights.OrderByDescending(o => o.Value).Take(10))
            {
                AILog.Log("ExpandMultiAttack", " - " + Bot.BonusString(bw.Key) + " Weight=" + bw.Value);
            }
            var armiesLeft = remainingUndeployed;

            TryExpand(ref armiesLeft, maxDistance, armyMult, bonusWeights);

            if (!highlyWeightedOnly) //If we have anything left after the second pass, revert to normal expansion.  Do it even if armiesLeft is 0, as it will use normal border armies
            {
                Normal.Go(armiesLeft, highlyWeightedOnly);
            }
        }
        public static void Go(BotMain bot)
        {
            var terrs = bot.Standing.Territories.Values.Where(o => bot.IsTeammateOrUs(o.OwnerPlayerID) && o.NumArmies.NumArmies == bot.Settings.OneArmyMustStandGuardOneOrZero && o.NumArmies.SpecialUnits.Length == 0).Select(o => o.ID).ToHashSet(true);

            foreach (var bonus in bot.Map.Bonuses.Values)
            {
                if (bonus.Territories.All(o => terrs.Contains(o)) && bonus.ControlsBonus(bot.Standing).HasValue == false)
                {
                    //bot bonus is entirely controlled by our team with 1s, but not by a single player. The player with the most territories should take it.
                    var owners = bonus.Territories.GroupBy(o => bot.Standing.Territories[o].OwnerPlayerID).ToList();
                    owners.Sort((f, s) => SharedUtility.CompareInts(s.Count(), f.Count()));

                    Assert.Fatal(owners.Count >= 2);

                    var attacks = bonus.Territories
                                  .Where(o => bot.Standing.Territories[o].OwnerPlayerID != bot.PlayerID)                                                   //Territories in the bonus by our teammate
                                  .Where(o => bot.Map.Territories[o].ConnectedTo.Keys.Any(c => bot.Standing.Territories[c].OwnerPlayerID == bot.PlayerID)) //Where we control an adjacent
                                  .Select(o => new PossibleAttack(bot, bot.Map.Territories[o].ConnectedTo.Keys.First(c => bot.Standing.Territories[c].OwnerPlayerID == bot.PlayerID), o));

                    if (owners[0].Count() == owners[1].Count())
                    {
                        //The top two players have the same number of terrs.  50% chance we should try taking one.
                        if (attacks.Any() && RandomUtility.RandomNumber(2) == 0)
                        {
                            var doAttack1 = bot.UseRandomness ? attacks.Random() : attacks.First();
                            var numArmies = bot.ArmiesToTake(bot.Standing.Territories[doAttack1.To].NumArmies);
                            if (bot.Orders.TryDeploy(doAttack1.From, numArmies))
                            {
                                AILog.Log("ResolveTeamBonuses", "Detected a split bonus " + bot.BonusString(bonus) + ", and we're attempting to break the split by doing a small attack from " + bot.TerrString(doAttack1.From) + " to " + bot.TerrString(doAttack1.To) + " with " + numArmies);
                                bot.Orders.AddAttack(doAttack1.From, doAttack1.To, AttackTransferEnum.Attack, numArmies, true);
                            }
                        }
                    }
                    else if (owners[0].Key == bot.PlayerID)
                    {
                        //We should take the bonus
                        foreach (var doAttack2 in attacks)
                        {
                            var numArmies = bot.ArmiesToTake(bot.Standing.Territories[doAttack2.To].NumArmies);

                            if (bot.Orders.TryDeploy(doAttack2.From, numArmies))
                            {
                                AILog.Log("ResolveTeamBonuses", "Detected we should take bonus " + bot.BonusString(bonus) + ", so we're attacking from " + bot.TerrString(doAttack2.From) + " to " + bot.TerrString(doAttack2.To) + " with " + numArmies);
                                bot.Orders.AddAttack(doAttack2.From, doAttack2.To, AttackTransferEnum.Attack, 2, true);
                            }
                        }
                    }
                }
            }
        }
Beispiel #4
0
 public override string ToString()
 {
     return(Bot.TerrString(ID) + " Weight=" + Weight + ", CriticalPath=" + WeightFromCriticalPath + ", Bonuses: " + Bonuses.Select(o => Bot.BonusString(o.Key) + " " + o.Value).JoinStrings(", "));
 }
        private static float GetExpansionWeight(BotMain bot, TerritoryIDType terrID)
        {
            var td = bot.Map.Territories[terrID];

            var bonusPaths = td.PartOfBonuses
                             .Where(o => bot.BonusValue(o) > 0)
                             .Select(o => BonusPath.TryCreate(bot, o, ts => ts.ID == terrID))
                             .Where(o => o != null)
                             .ToDictionary(o => o.BonusID, o => o);

            var turnsToTake = bonusPaths.Keys.ToDictionary(o => o, o => TurnsToTake(bot, td.ID, o, bonusPaths[o]));

            foreach (var cannotTake in turnsToTake.Where(o => o.Value == null).ToList())
            {
                turnsToTake.Remove(cannotTake.Key);
                bonusPaths.Remove(cannotTake.Key);
            }

            var bonusWeights = bonusPaths.Keys.ToDictionary(o => o, o => ExpansionHelper.WeighBonus(bot, o, ts => ts.ID == terrID, turnsToTake[o].NumTurns));

            var weight = 0.0f;

            weight += ExpansionHelper.WeighMultipleBonuses(td.PartOfBonuses.Where(o => bonusWeights.ContainsKey(o)).ToDictionary(o => o, o => bonusWeights[o]));

            AILog.Log("PickTerritories", "Expansion weight for terr " + bot.TerrString(terrID) + " is " + weight + ". " + td.PartOfBonuses.Select(b => "Bonus " + bot.BonusString(b) + " Weight=" + (bonusWeights.ContainsKey(b) ? bonusWeights[b] : 0) + " TurnsToTake=" + (turnsToTake.ContainsKey(b) ? turnsToTake[b].ToString() : "") + " Path=" + (bonusPaths.ContainsKey(b) ? bonusPaths[b].ToString() : "")).JoinStrings(", "));

            return(weight);
        }