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); }
public void Weight(Dictionary <PlayerIDType, int> weightedNeighbors) { var opponentID = Bot.Standing.Territories[this.To].OwnerPlayerID; Assert.Fatal(opponentID != TerritoryStanding.NeutralPlayerID); Assert.Fatal(!Bot.IsTeammateOrUs(opponentID)); //Seed the border weight with a lessened neighbor weight this.DefenseImportance = !weightedNeighbors.ContainsKey(opponentID) ? 0 : (weightedNeighbors[opponentID] / 10.0); this.OffenseImportance = this.DefenseImportance; //Are we defending a bonus we control? foreach (var defendingBonus in Bot.Map.Territories[this.From].PartOfBonuses .Select(b => Bot.Map.Bonuses[b]) .Where(b => Bot.PlayerControlsBonus(b) && Bot.Map.Territories[this.To].PartOfBonuses .Select(b2 => Bot.Map.Bonuses[b2]) .Any(b2 => !Bot.PlayerControlsBonus(b2)))) { //Defend importance is bonus value * 10 this.DefenseImportance += Bot.BonusValue(defendingBonus.ID) * 10.0; } //Would attacking break an opponents bonus? foreach (var attackingBonus in Bot.Map.Territories[this.To].PartOfBonuses .Select(b => Bot.Map.Bonuses[b]) .Where(b => Bot.OpponentMightControlBonus(b))) { this.OffenseImportance += Bot.BonusValue(attackingBonus.ID) * (Bot.IsFFA ? 4.0 : 10); //be conservative in FFAs, but aggressive in heads up. } var toTs = Bot.Standing.Territories[this.To]; //How is our current ratio var ourArmies = Bot.Standing.Territories[this.From].NumArmies.NumArmies; var theirArmies = !toTs.NumArmies.Fogged ? toTs.NumArmies.DefensePower : Bot.UseRandomness ? RandomUtility.RandomNumber(ourArmies * 2) : (int)(ourArmies / 2); var ratio = (double)theirArmies / (double)ourArmies; if (ourArmies + theirArmies < 10) { ratio = 1; //Small numbers change so rapidly anyway that we just consider it equal. } this.OffenseImportance *= ratio; this.DefenseImportance *= ratio; //AILog.Log("Returning " + possibleAttack.OffenseImportance + "," + possibleAttack.DefenseImportance); }
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); } }
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); }