private MultiMoves GetBreakBonusMoves(BonusIDType opponentBonus, MultiMoves presentMoves) { var bonusTerritories = GameState.Map.Bonuses[opponentBonus].Territories; var distances = MapInformer.GetDistancesFromTerritories(bonusTerritories); var ownedBorderTerritories = MapInformer.GetOwnedBorderTerritories(presentMoves.GetTerritoryStandingsAfterAllMoves(), GameState.MyPlayerId); int minDistance = ownedBorderTerritories.Min(o => distances[o.ID]); var bestStartTerritory = ownedBorderTerritories.Where(o => distances[o.ID] == minDistance).First(); int currentDistance = minDistance; var currentTerritoryInAttackPath = bestStartTerritory.ID; List <TerritoryIDType> territoriesToTake = new List <TerritoryIDType>(); while (currentDistance != 0) { var neighbors = MapInformer.GetNeighborTerritories(currentTerritoryInAttackPath); var possibleAttackNeighbors = neighbors.Where(n => distances[n] == currentDistance - 1).ToList(); var bestNeighborToAttack = GetBestNeighborToAttack(possibleAttackNeighbors); territoriesToTake.Add(bestNeighborToAttack); currentTerritoryInAttackPath = bestNeighborToAttack; currentDistance--; } TakeTerritoriesTask takeTerritoriesTask = new TakeTerritoriesTask(REASON); MultiMoves resultMoves = takeTerritoriesTask.CalculateTakeTerritoriesMoves(territoriesToTake, presentMoves); return(resultMoves); }
private MultiAttackPathToBonus(BotMain bot, TerritoryIDType startFrom, BonusIDType bonusID, int jumpsToGetToBonus, int armiesNeededToCapture, int armiesNeedToKillToGetThere, List <TerritoryIDType> pathToGetThere) { this.Bot = bot; this.StartFrom = startFrom; this.BonusID = bonusID; this.JumpsToGetToBonus = jumpsToGetToBonus; this.EstArmiesNeededToCapture = armiesNeededToCapture; this.ArmiesNeedToKillToGetThere = armiesNeedToKillToGetThere; this.PathToGetThere = pathToGetThere; }
public int BonusValue(BonusIDType bonusID) { if (Settings.OverriddenBonuses.ContainsKey(bonusID)) { return(Settings.OverriddenBonuses[bonusID]); } else { return(Map.Bonuses[bonusID].Amount); } }
/// <summary> /// Estimate how many turns it would take us to complete the bonus, assuming full deployment and usage of armies in or next to it. /// </summary> /// <param name="bonusID"></param> /// <param name="bonusPath"></param> /// <returns></returns> private CaptureTerritories TurnsToTake(BonusIDType bonusID, BonusPath path) { var bonus = Bot.Map.Bonuses[bonusID]; var terrsToTake = bonus.Territories.Where(o => Bot.Standing.Territories[o].OwnerPlayerID != Bot.PlayerID).ToHashSet(true); var terrsWeOwnInOrAroundBonus = bonus.Territories.Concat(bonus.Territories.SelectMany(o => Bot.Map.Territories[o].ConnectedTo.Keys)).Where(o => Bot.Standing.Territories[o].OwnerPlayerID == Bot.PlayerID).ToHashSet(false); var armiesWeHaveInOrAroundBonus = terrsWeOwnInOrAroundBonus.Sum(o => Bot.MakeOrders.GetArmiesAvailable(o)); var armiesPerTurn = Bot.BaseIncome.FreeArmies; return(CaptureTerritories.TryFindTurnsToTake(Bot, path, armiesWeHaveInOrAroundBonus, armiesPerTurn, terrsToTake, o => o.NumArmies.Fogged ? ExpansionHelper.GuessNumberOfArmies(Bot, o.ID).DefensePower : o.NumArmies.DefensePower)); }
public float BonusFuzz(BonusIDType bonusID) { if (!UseRandomness) { return(0); } if (_bonusFuzz == null) { _bonusFuzz = new Dictionary <BonusIDType, float>(); } if (!_bonusFuzz.ContainsKey(bonusID)) { _bonusFuzz.Add(bonusID, (float)RandomUtility.BellRandom(-2, 2)); } return(_bonusFuzz[bonusID]); }
public static float WeighBonus(BotMain bot, BonusIDType bonusID, Func <TerritoryStanding, bool> weOwn, int turnsToTake) { var bonus = bot.Map.Bonuses[bonusID]; int bonusValue = bot.BonusValue(bonusID); if (bonusValue <= 0) { throw new Exception("Considered zero or negative bonuses"); //we should not even be considering zero or negative bonuses, ensure they're filtered out before we get here. } var weight = BaseBonusWeight; //When randomness is enabled, modify the bonus by a fixed amount for this bonus. weight += bot.BonusFuzz(bonusID); weight += bonusValue * (bot.IsFFA ? 7 : 4); //Subtract value for each additional turn it takes to take over one weight -= bonusValue * (turnsToTake - 1); weight -= bonus.Territories.Count * bot.Settings.OneArmyMustStandGuardOneOrZero; float armyMult = ArmyMultiplier(bot.Settings.DefenseKillRate); //How many territories do we need to take to get it? Subtract one weight for each army standing in our way foreach (var terrInBonus in bonus.Territories) { var ts = bot.Standing.Territories[terrInBonus]; if (weOwn(ts)) { weight += ts.NumArmies.AttackPower * armyMult; //Already own it } else if (ts.OwnerPlayerID == TerritoryStanding.FogPlayerID) { weight -= GuessNumberOfArmies(bot, ts.ID).DefensePower *armyMult; } else if (bot.IsTeammate(ts.OwnerPlayerID)) { weight -= bot.Players[ts.OwnerPlayerID].IsAIOrHumanTurnedIntoAI ? 0 : ts.NumArmies.DefensePower * 4 * armyMult; //Human teammate in it. We'll defer to them since humans know best. } else if (ts.OwnerPlayerID == TerritoryStanding.AvailableForDistribution) { weight -= Math.Max(bot.Settings.InitialNeutralsInDistribution, bot.Settings.InitialPlayerArmiesPerTerritory) * armyMult; //assume another player could start there } else if (ts.IsNeutral) { //Neutral in it if (ts.NumArmies.Fogged == false) { weight -= ts.NumArmies.DefensePower * armyMult; } else { weight -= GuessNumberOfArmies(bot, ts.ID).DefensePower *armyMult; } } else { //Opponent in it - expansion less likely if (ts.NumArmies.Fogged == false) { weight -= ts.NumArmies.DefensePower * 3 * armyMult; } else { weight -= GuessNumberOfArmies(bot, ts.ID).DefensePower *armyMult; } } } return(weight); }
public BotBonus(BotMap parent, BonusIDType id) { this.Parent = parent; this.ID = id; }
public string BonusString(BonusIDType bonusID) { return(BonusString(Map.Bonuses[bonusID])); }
/// <summary> /// Returns null if we can't find a way to take the bonus or if we already own it /// </summary> /// <param name="bot"></param> /// <param name="bonusID"></param> /// <returns></returns> public static MultiAttackPathToBonus TryCreate(BotMain bot, TerritoryIDType startFrom, BonusIDType bonusID, GameStanding standing, int maxDistance) { var bonus = bot.Map.Bonuses[bonusID]; var allUnownedTerrsInBonus = bonus.Territories.Where(o => standing.Territories[o].OwnerPlayerID != bot.PlayerID).ToHashSet(true); if (allUnownedTerrsInBonus.Count == 0) { return(null); //already own it } HashSet <TerritoryIDType> terrsWeEnterBonus; int jumpsToGetToBonus = DistanceToTerrs(bot, startFrom, bonus.Territories.ToHashSet(true), standing, maxDistance, out terrsWeEnterBonus); if (jumpsToGetToBonus == int.MaxValue) { return(null); //can't take it within a reasonable searching distance } if (jumpsToGetToBonus == 0) { //We're already in it var armiesNeededToCapture = bot.ArmiesToTakeMultiAttack(allUnownedTerrsInBonus.Select(o => ExpansionHelper.GuessNumberOfArmies(bot, o, standing, MultiAttackExpand.GuessOpponentNumberOfArmiesInFog))); return(new MultiAttackPathToBonus(bot, startFrom, bonusID, 0, armiesNeededToCapture, 0, new List <TerritoryIDType>())); } else { var pathToGetThere = FindPath.TryFindShortestPath(bot, startFrom, t => terrsWeEnterBonus.Contains(t), visit => visit == startFrom || bot.IsTeammateOrUs(standing.Territories[visit].OwnerPlayerID) == false); if (pathToGetThere == null) { return(null); } var getThere = pathToGetThere.ExceptOne(pathToGetThere.Last()); var armiesNeededToCapture = bot.ArmiesToTakeMultiAttack(getThere.Concat(allUnownedTerrsInBonus).Select(o => ExpansionHelper.GuessNumberOfArmies(bot, o, standing, MultiAttackExpand.GuessOpponentNumberOfArmiesInFog))); return(new MultiAttackPathToBonus(bot, startFrom, bonusID, jumpsToGetToBonus, armiesNeededToCapture, getThere.Sum(o => ExpansionHelper.GuessNumberOfArmies(bot, o, standing).DefensePower), pathToGetThere)); } }
public static BonusPath TryCreate(BotMain bot, BonusIDType bonusID, Func <TerritoryStanding, bool> weOwn) { var bonus = bot.Map.Bonuses[bonusID]; var allUnownedTerrsInBonus = bonus.Territories.Where(o => !weOwn(bot.Standing.Territories[o])).ToHashSet(true); if (allUnownedTerrsInBonus.Count == 0) { return(new BonusPath(bonusID, 0, new HashSet <TerritoryIDType>())); //Already own the bonus. We'll only get here with one-territory bonuses during distribution } var terrsToTake = allUnownedTerrsInBonus.ToHashSet(true); var ownedTerritoriesTraverse = bot.Standing.Territories.Values.Where(o => weOwn(o)).Select(o => o.ID).ToHashSet(true); HashSet <TerritoryIDType> finalTerritoriesCaptured = null; var turns = 1; while (true) { var takeThisTurn = terrsToTake.Where(o => bot.Map.Territories[o].ConnectedTo.Keys.Any(z => ownedTerritoriesTraverse.Contains(z))).ToHashSet(true); if (takeThisTurn.Count == 0) { //We can't take it without leaving the bonus. AILog.Log("BonusPath", " Could not find a way to take bonus " + bot.BonusString(bonus) + " without leaving it"); return(null); } if (takeThisTurn.Count == terrsToTake.Count) { //We captured the bonus finalTerritoriesCaptured = takeThisTurn; break; } //Keep expanding! turns++; ownedTerritoriesTraverse.AddRange(takeThisTurn); terrsToTake.RemoveAll(takeThisTurn); } var terrsWeOwnInOrAroundBonus = bonus.Territories.Concat(bonus.Territories.SelectMany(o => bot.Map.Territories[o].ConnectedTo.Keys)).Where(o => weOwn(bot.Standing.Territories[o])).ToHashSet(false); var traverse = allUnownedTerrsInBonus.Concat(terrsWeOwnInOrAroundBonus).ToHashSet(false); var criticalPath = new HashSet <TerritoryIDType>(); foreach (var final in finalTerritoriesCaptured) { var path = FindPath.TryFindShortestPathReversed(bot, o => weOwn(bot.Standing.Territories[o]), final, o => traverse.Contains(o)); if (path != null) { //AILog.Log("BonusPath", " Critical path to " + bot.TerrString(final) + " goes " + path.Select(o => bot.TerrString(o)).JoinStrings(" -> ")); criticalPath.AddRange(path); } else { AILog.Log("BonusPath", " Could not find a path to " + bot.TerrString(final)); } } //AILog.Log("BonusPath", "With infinite armies, we can take bonus " + bot.BonusString(bonus) + " in " + TurnsToTake + " turns. " + /*" Final territories=" + finalTerritoriesCaptured.Select(o => bot.TerrString(o)).JoinStrings(", ") +*/ " Critical path=" + TerritoriesOnCriticalPath.Select(o => bot.TerrString(o)).JoinStrings(", ")); return(new BonusPath(bonusID, turns, criticalPath)); }
public int TurnsToTakeByDistance; //how long to take the bonus, assuming we have infinite armies public BonusPath(BonusIDType bonusID, int turnsToTakeByDistance, HashSet <TerritoryIDType> terrsOnCriticalPath) { this.BonusID = bonusID; this.TurnsToTakeByDistance = turnsToTakeByDistance; this.TerritoriesOnCriticalPath = terrsOnCriticalPath; }
/// <param name="id">: a Bonus id number</param> /// <returns>: the matching Bonus object</returns> public BotBonus GetBonus(BonusIDType id) { return(Bonuses[id]); }
public BotBonus(CowzowBot bot, BonusIDType id) { this.Bot = bot; this.ID = id; this.ArmiesReward = bot.Settings.OverriddenBonuses.ContainsKey(id) ? bot.Settings.OverriddenBonuses[id] : Details.Amount; }
/// <summary> /// Estimate how many turns it would take us to complete the bonus, assuming we start in the passed territory and can use full deployment every turn /// </summary> /// <param name="bonusID"></param> /// <param name="bonusPath"></param> /// <returns></returns> private static CaptureTerritories TurnsToTake(BotMain bot, TerritoryIDType terrID, BonusIDType bonusID, BonusPath path) { var bonus = bot.Map.Bonuses[bonusID]; var terrsToTake = bonus.Territories.ExceptOne(terrID).ToHashSet(true); return(CaptureTerritories.TryFindTurnsToTake(bot, path, bot.Settings.InitialPlayerArmiesPerTerritory, bot.Settings.MinimumArmyBonus, terrsToTake, o => o.OwnerPlayerID == TerritoryStanding.AvailableForDistribution ? bot.Settings.InitialNeutralsInDistribution : o.NumArmies.DefensePower)); }