public List<DeployArmies> ExpandMinimum(BotState state, int armiesLeft) { string myName = state.MyPlayerName; string opponentName = state.OpponentPlayerName; List<DeployArmies> deployArmies = new List<DeployArmies>(); if (state.ExpansionTargets.Count == 0) return deployArmies; // check if opponent might be there (or neighboring) // map has 12 starting spots, 3 of them are ours, 3 estimated for opponent // each gets removed as they are seen for the first time // so we can estimate decently the // so only apply this filter between 9 and 6 if ( state.OpponentStartRegions.Count > 6 ) { for (int i = 0; i < 2; i++) { foreach (Region reg in state.OpponentStartRegions[i].Neighbors) { Region neigh = state.FullMap.GetRegion(reg.Id); if (neigh.SuperRegion.Id == state.ExpansionTargets[0].Id) { // don't do minimum expansion here if (state.ExpansionTargets.Count == 0) return deployArmies; } } } } // check if we can do minimum expansion on our best found expansion target bool doMinimumExpansion = true; foreach (Region reg in state.ExpansionTargets[0].SubRegions) { Region a = state.FullMap.GetRegion(reg.Id); // only try to expand if enemy is not on it if (a.OwnedByPlayer(opponentName)) doMinimumExpansion = false; // find best subregion to expand into int count = 0; // must be a neutral if (!a.OwnedByPlayer("neutral")) { reg.tempSortValue = -1; continue; } foreach (Region neig in a.Neighbors) { Region neigh = state.FullMap.GetRegion(neig.Id); // if neighbor is the enemy, we shouldnt be thinking of expansion, we want to keep our stack close to the enemy if (neigh.OwnedByPlayer(opponentName)) { count -= 5; } // the more neighbours belong to me the better if (neigh.OwnedByPlayer(myName)) { count += 5; } // if it has neutrals on the target superregion its good if (neigh.OwnedByPlayer("neutral") && (neigh.SuperRegion.Id == a.SuperRegion.Id)) count++; // if it has unknowns on the target superregion its even better (means we will be able to finish it faster) if (neigh.OwnedByPlayer("unknown") && (neigh.SuperRegion.Id == a.SuperRegion.Id)) count += 1; // if it has only has 1 army it costs less to take, so its better if (neigh.Armies == 1) count++; // boost if this territory can take this neighbour without deploying, at all int armyCount = a.Armies + a.PledgedArmies - a.ReservedArmies - neigh.Armies * 2; // the more armies we'll have left the better if (armyCount > 0) count += armyCount; } reg.tempSortValue = count; } if (doMinimumExpansion) { var lst = state.ExpansionTargets[0].SubRegions.OrderByDescending(p => p.tempSortValue).ToList(); Region target = state.FullMap.GetRegion(lst[0].Id); if (target.OwnedByPlayer("neutral")) { // find best region to attack from, must be my territory foreach (Region an in lst[0].Neighbors) { Region a = state.FullMap.GetRegion(an.Id); // if it's not our territory, don't bother if (!a.OwnedByPlayer(myName)) { an.tempSortValue = -1; continue; } // best attacker is the one with more armies available int armyCount = a.Armies + a.PledgedArmies - a.ReservedArmies; if (armyCount < 0) armyCount = 0; an.tempSortValue = armyCount; } var atk = lst[0].Neighbors.OrderByDescending(p => p.tempSortValue).ToList(); Region attacker = state.FullMap.GetRegion(atk[0].Id); if (attacker.OwnedByPlayer(myName)) { int deployed = state.ScheduleNeutralAttack(attacker, target, armiesLeft); deployArmies.Add(new DeployArmies(myName, attacker, deployed)); armiesLeft -= deployed; } else { Console.Error.WriteLine("something went wrong with minimum expansion, tried to attack from a territory which wasnt mine"); } } else { Console.Error.WriteLine("something went wrong with minimum expansion on round " + state.RoundNumber + " maybe because all options are bad?"); } } else { //todo: deploy all on biggest stack of main area and attack if predicting to win //todo: later: find a better expansiontarget (without enemy), or risk finishing this one } return deployArmies; }
public List<DeployArmies> FinishSuperRegion(BotState state, int armiesLeft) { string myName = state.MyPlayerName; //string opponentName = state.OpponentPlayerName; List<DeployArmies> deployArmies = new List<DeployArmies>(); if (state.ExpansionTargets.Count == 0) return deployArmies; //todo: later: calculate if we should be attacking a particular region more strongly (in case there is chance of counter or defensive positioning) // if you have enough income to finish an area this turn, deploy for it foreach (Region reg in state.ExpansionTargets[0].SubRegions) { Region region = state.FullMap.GetRegion(reg.Id); // skip if you already own this region if (region.OwnedByPlayer(myName)) continue; if (!region.OwnedByPlayer("neutral")) { Console.Error.WriteLine("trying to finish a FTB with " + region.PlayerName + " on it is a bit silly"); break; } // find neighbour with highest available armies (will be the attacker) foreach (Region an in region.Neighbors) { Region a = state.FullMap.GetRegion(an.Id); if (!a.OwnedByPlayer(myName)) { an.tempSortValue = -1; } else { // more armies available the better int aArmies = a.Armies + a.PledgedArmies - a.ReservedArmies; an.tempSortValue = aArmies; // if that attacker has only one neutral of this superregion in sight, give it a little bonus // this will help determine that this is the territory attacking when there are others with same armies available int neutralcnt = 0; foreach (Region un in a.Neighbors) { Region u = state.FullMap.GetRegion(un.Id); if (u.OwnedByPlayer("neutral") && (u.SuperRegion.Id == reg.Id)) neutralcnt++; } if (neutralcnt == 1) an.tempSortValue++; } } var neigh = region.Neighbors.OrderByDescending(p => p.tempSortValue).ToList(); // make sure the attacking neighbour is owned by us, so we can deploy on it if (neigh[0].OwnedByPlayer(myName)) { int deployed = state.ScheduleNeutralAttack(neigh[0], region, armiesLeft); if (deployed > 0) { deployArmies.Add(new DeployArmies(myName, neigh[0], deployed)); armiesLeft -= deployed; } } else { Console.Error.WriteLine("trying to attack out of a territory owned by " + neigh[0].PlayerName + " on round " + state.RoundNumber + "! guess we ran out of available armies :("); } } if (armiesLeft < 0) Console.Error.WriteLine("exceeded army deployment on turn " + state.RoundNumber); // deploy the rest of our armies if (armiesLeft > 0) { if (state.EnemySighted) { List<DeployArmies> placings = DeployBorderingEnemy(state, armiesLeft); foreach (DeployArmies pl in placings) { deployArmies.Add(pl); } } } return deployArmies; }
// more aggressive expansion, used only when game is stalled to help move things along for minimal expansion and finishregion to complete it public List<DeployArmies> ExpandGameStalled(BotState state, int armiesLeft) { string myName = state.MyPlayerName; //string opponentName = state.OpponentPlayerName; List<DeployArmies> deployArmies = new List<DeployArmies>(); if (state.ExpansionTargets.Count == 0) return deployArmies; // expand on the main expansion target SuperRegion expansionTarget = state.FullMap.GetSuperRegion(state.ExpansionTargets[0].Id); foreach (Region reg in expansionTarget.SubRegions) { Region region = state.FullMap.GetRegion(reg.Id); // skip if you already own this region if (region.OwnedByPlayer(myName)) continue; // find our neighbour with highest available armies foreach (Region a in region.Neighbors) { int aArmies = a.Armies + a.PledgedArmies - a.ReservedArmies; if (!a.OwnedByPlayer(myName)) aArmies = -1; a.tempSortValue = aArmies; } var lst = region.Neighbors.OrderByDescending(p => p.tempSortValue).ToList(); Region neigh = state.FullMap.GetRegion(lst[0].Id); if (neigh.OwnedByPlayer(myName)) { int deployed = state.ScheduleNeutralAttack(neigh, region, armiesLeft); if (armiesLeft >= deployed) { deployArmies.Add(new DeployArmies(myName, neigh, deployed)); //neigh.PledgedArmies += deployed; armiesLeft -= deployed; } } // only do the expansion for the first neutral region found //break; } return deployArmies; }