public bool IsComboBonus(BotBonus bonus, BotMap map) { if (bonus.Amount > 4 || IsInefficientBonus(bonus) || IsWastelandedBonus(bonus)) { return(false); } ComboBonuses temp = new ComboBonuses(bonus, map); return(temp.isCombo); }
/// <summary> /// Prioritizes combos or FTBs that contain less picks adjacent to the bonus. Also places Sub Combos at bottom of list with exception of counterable combos /// </summary> /// <param name="list"></param> private void ReorderCombosByNumberOfTerritories(ref List <ComboBonuses> list) { List <TerritoryIDType> seenPickIDs = new List <TerritoryIDType>(); for (int i = 0; i < list.Count; i++) { if (seenPickIDs.Contains(list[i].mainPick.ID)) { continue; } else { seenPickIDs.Add(list[i].mainPick.ID); if (list[i].adjacentPickTerritories.Count < 3 && list[i].isEfficient) { ComboBonuses temp = list[i]; list.Remove(temp); list.Insert(0, temp); } } } if (list.Count > 0 && !list[0].isFTB) { List <TerritoryIDType> hasSeen = new List <TerritoryIDType>(); for (int i = 0; i < list.Count; i++) { if (!hasSeen.Contains(list[i].mainPick.Details.ID) && (list[i].mainBonus.Amount == 3 || GetSmallestBonus(list[i].isFTB ? list[i].supportFTBPick : list[i].supportComboPick) == 5)) { ComboBonuses temp = list[i]; list.RemoveAt(i); list.Add(temp); hasSeen.Add(list[i].mainPick.Details.ID); } } hasSeen = new List <TerritoryIDType>(); for (int i = 0; i < list.Count; i++) { if (!hasSeen.Contains(list[i].mainPick.Details.ID) && list[i].adjacentPickTerritories.Count > 2) { ComboBonuses temp = list[i]; list.RemoveAt(i); list.Add(temp); hasSeen.Add(list[i].mainPick.Details.ID); } } } }
/// <summary> /// Obtains the picks that will be used for the game. Will determine an initial score that will be used to order to picks initially, followed by finding FTBs and combos /// that will be interspersed based on cases outlined in tree diagram /// </summary> /// <returns>List of territory IDs of the final picks to be sent</returns> public List <TerritoryIDType> GetPicks() { if (BotState.Map.IsScenarioDistribution(BotState.Settings.DistributionModeID)) { var us = BotState.Map.GetTerritoriesForScenario(BotState.Settings.DistributionModeID, BotState.Me.ScenarioID); us.RandomizeOrder(); return(us); } int maxPicks = BotState.Settings.LimitDistributionTerritories == 0 ? BotState.Map.Territories.Count : (BotState.Settings.LimitDistributionTerritories * BotState.Players.Count(o => o.Value.State == GamePlayerState.Playing)); var pickableTerritories = BotState.DistributionStanding.Territories.Values.Where(o => o.OwnerPlayerID == TerritoryStanding.AvailableForDistribution).Select(o => o.ID).ToList(); bool isAntWastelanded = false; TerritoryIDType ausID = (TerritoryIDType)0; var map = BotMap.FromStanding(BotState, BotState.DistributionStanding); var weights = pickableTerritories.ToDictionary(o => o, terrID => { // Check if Ant is wastelanded for Aus score modifier map.Territories[terrID].OwnerPlayerID = BotState.Me.ID; if (map.Territories[terrID].Bonuses[0].Details.Name.Equals("Antarctica") && BotState.BonusPickValueCalculator.IsWastelandedBonus(map.Territories[terrID].Bonuses[0])) { isAntWastelanded = true; } else if (map.Territories[terrID].Bonuses[0].Details.Name.Equals("Australia")) { ausID = terrID; } // Only find value if bonus has significiant amount if (map.Territories[terrID].Bonuses.Count > 0) { BotBonus bonus = map.Territories[terrID].Bonuses[0]; bonus.SetMyPickValueHeuristic(); double r = bonus.ExpansionValue; return(r); } else { return(0); } }); // Check for if pick is in Aus if (!isAntWastelanded && weights.ContainsKey(ausID)) { weights[ausID] -= 25; } foreach (TerritoryIDType terrID in weights.Keys) { AILog.Log("Pick Values", map.Territories[terrID].Bonuses[0] + ": " + weights[terrID]); } // Check for FTBs and assign value for Aus based on Ant Wasteland boolean List <ComboBonuses> firstTurnBonusList = new List <ComboBonuses>(); List <ComboBonuses> comboList = new List <ComboBonuses>(); foreach (KeyValuePair <TerritoryIDType, double> pick in weights) { // Checks for FTB and combos if (BotState.BonusPickValueCalculator.IsFirstTurnBonus(map.Territories[pick.Key].Bonuses[0])) { ComboBonuses newCombo = new ComboBonuses(map.Territories[pick.Key].Bonuses[0], map); firstTurnBonusList.Add(newCombo); } else if (BotState.BonusPickValueCalculator.IsComboBonus(map.Territories[pick.Key].Bonuses[0], map)) { ComboBonuses newCombo = new ComboBonuses(map.Territories[pick.Key].Bonuses[0], map); comboList.Add(newCombo); } } ReorderCombosByNumberOfTerritories(ref firstTurnBonusList); ReorderCombosByNumberOfTerritories(ref comboList); AILog.Log("Picks", "Number of FTBs: " + firstTurnBonusList.Count); AILog.Log("Picks", "Number of Combos: " + comboList.Count); AILog.Log("Picks", "FTBs found:"); foreach (ComboBonuses ftb in firstTurnBonusList) { AILog.Log("Picks", "\tBonus: " + ftb.mainBonus.Details.Name); AILog.Log("Picks", "\t\t" + ftb.mainPick.Details.Name); for (int i = 0; i < ftb.adjacentPickTerritories.Count; i++) { if (ftb.adjacentPickTerritories[i].Details.Name.Equals(ftb.mainPick.Details.Name)) { continue; } AILog.Log("Picks", "\t\t\t" + ftb.adjacentPickTerritories[i].Details.Name); } } AILog.Log("Picks", "End of FTB list"); AILog.Log("Picks", "Combos found:"); foreach (ComboBonuses combo in comboList) { AILog.Log("Picks", "\tBonus: " + combo.mainBonus.Details.Name); AILog.Log("Picks", "\t\t" + combo.mainPick.Details.Name); for (int i = 0; i < combo.adjacentPickTerritories.Count; i++) { if (combo.adjacentPickTerritories[i].Details.Name.Equals(combo.mainPick.Details.Name)) { continue; } AILog.Log("Picks", "\t\t\t" + (combo.adjacentPickTerritories[i].Details.Name.Equals(combo.mainPick.Details.Name) ? combo.adjacentPickTerritories[++i].Details.Name : combo.adjacentPickTerritories[i].Details.Name)); } } AILog.Log("Picks", "End of combo list"); List <TerritoryIDType> picks = weights.OrderByDescending(o => o.Value).Take(maxPicks).Select(o => o.Key).Distinct().ToList(); //StatefulFogRemover.PickedTerritories = picks; AILog.Log("Picks", "Before final reshuffle:"); foreach (var terr in picks) { AILog.Log("Picks", "\t" + map.Territories[terr].Bonuses[0].Details.Name + ", " + map.Territories[terr].Details.Name); } ReorderPicksByCombos(firstTurnBonusList, comboList, ref picks); AILog.Log("Picks", "After final reshuffle:"); foreach (var terr in picks) { AILog.Log("Picks", "\t" + map.Territories[terr].Bonuses[0].Details.Name + ", " + map.Territories[terr].Details.Name); } Memory.PickTracker.SetPickList(picks); BotMap storedMap = BotState.VisibleMap.GetMapCopy(); Memory.PickTracker.pickMap = storedMap; return(picks); }
private Boolean IsManyTurnBonus(BotBonus bonus, ComboBonuses optionalCombo = null) { IDictionary <BotTerritory, bool> seenTerritories = new Dictionary <BotTerritory, bool>(); BotTerritory pick = null; foreach (BotTerritory terr in bonus.Territories) { if (terr.Armies.NumArmies == 0) { seenTerritories[terr] = true; pick = terr; } } if (pick == null) { return(true); } foreach (BotTerritory adjTerr in pick.Neighbors) { if (!ContainsTerritory(bonus, adjTerr)) { continue; } seenTerritories[adjTerr] = true; foreach (BotTerritory adjSecondTerr in adjTerr.Neighbors) { if (!ContainsTerritory(bonus, adjSecondTerr)) { continue; } seenTerritories[adjSecondTerr] = true; } } if (seenTerritories.Count == bonus.Territories.Count) { return(false); } else if (optionalCombo != null) { List <BotTerritory> unseenTerritories = Except(bonus, seenTerritories.Keys.ToList <BotTerritory>()); foreach (BotTerritory terr in optionalCombo.adjacentPickTerritories) { if (terr.Bonuses[0] == bonus) { continue; } foreach (BotTerritory adjTerr in terr.Neighbors) { if (unseenTerritories.Contains(adjTerr)) { unseenTerritories.Remove(adjTerr); if (unseenTerritories.Count == 0) { return(false); } } foreach (BotTerritory adjSecondTerr in adjTerr.Neighbors) { if (unseenTerritories.Contains(adjSecondTerr)) { unseenTerritories.Remove(adjSecondTerr); if (unseenTerritories.Count == 0) { return(false); } } } } } } return(true); }