public List<DeployArmies> AttackHard(BotState state, int armiesLeft) { string myName = state.MyPlayerName; string opponentName = state.OpponentPlayerName; List<DeployArmies> deployArmies = new List<DeployArmies>(); // pick the target with most strategic value (position and stack advantage) foreach (Region rr in state.EnemyBorders) { rr.tempSortValue = 0; // give higher count if positioned in top ranked expansion if (rr.SuperRegion.ArmiesReward == 2) rr.tempSortValue += 2; // give higher count if we have stack advantage int maxarmies = 0; foreach (Region rn in rr.Neighbors) { if (rn.OwnedByPlayer(myName)) { if (rn.Armies > maxarmies) maxarmies = rn.Armies; } } rr.tempSortValue += maxarmies - rr.Armies; } var lst = state.EnemyBorders.OrderByDescending(p => p.tempSortValue).ToList(); Region target = state.FullMap.GetRegion(lst[0].Id); // pick the neighbour (our territory) with the highest army count foreach (Region rn in target.Neighbors) { int ac = 0; if (rn.OwnedByPlayer(myName)) { ac += rn.Armies; } rn.tempSortValue = ac; } lst = target.Neighbors.OrderByDescending(p => p.tempSortValue).ToList(); Region attacker = lst[0]; // validate if (target.OwnedByPlayer(opponentName) && attacker.OwnedByPlayer(myName)) { deployArmies.Add(new DeployArmies(myName, attacker, armiesLeft)); state.ScheduleAttack(attacker, target, armiesLeft, attacker.Armies - 1 + armiesLeft); //state.scheduledAttack.Add(new Tuple<int, int, int>(attacker.Id, target.Id, attacker.Armies - 1 + armiesLeft)); armiesLeft = 0; } return deployArmies; }
// is only called when no enemy is in sight public List<DeployArmies> ExpandTowardsEnemyWithFullStack(BotState state, int armiesLeft) { string myName = state.MyPlayerName; //string opponentName = state.OpponentPlayerName; List<DeployArmies> deployArmies = new List<DeployArmies>(); // determine the best region the opponent is most likely in if (state.OpponentStartRegions.Count > 0) { // find next step on shortest path to get there // and schedule an attack in that direction int nextstep = state.FullMap.FindNextStep(state.OpponentStartRegions[0].Id); if (nextstep != -1) { Region region = state.FullMap.GetRegion(nextstep); // find our neighbour with highest available armies foreach (Region a in region.Neighbors) { int aArmies = a.Armies + a.PledgedArmies - a.ReservedArmies; if (aArmies < 0) aArmies = 0; 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)) { deployArmies.Add(new DeployArmies(myName, neigh, armiesLeft)); int armiesCount = neigh.Armies + neigh.PledgedArmies - neigh.ReservedArmies + armiesLeft - 1; state.ScheduleAttack(neigh, region, armiesLeft, armiesCount ); } } } return deployArmies; }
public List<DeployArmies> GetDeployArmiesMoves(BotState state, long timeOut) { string myName = state.MyPlayerName; string opponentName = state.OpponentPlayerName; bool enemySighted = state.EnemySighted; List<DeployArmies> deployArmies = new List<DeployArmies>(); int armiesLeft = state.StartingArmies; // figure out if the best listed superregion is finishable on this turn bool finishableSuperRegion = FinishableSuperRegion(state); if (enemySighted) { // on first rounds, attack any enemies on sight, unless we can finish a super region or have already attacked neutrals if ((state.RoundNumber < 5) && !finishableSuperRegion && !state.AttackedOneNeutral) { // if we have atleast 2 enemy sightings, pick one and hit it hard List<DeployArmies> deploy = AttackHard(state, armiesLeft); foreach (DeployArmies da in deploy) { deployArmies.Add(da); armiesLeft -= da.Armies; } } // if we are SABased, northafrica is ours, enemy is in africa, NA is not finished and enemy is not in NA, Region northafrica = state.FullMap.GetRegion(21); SuperRegion africa = state.FullMap.GetSuperRegion(northafrica.SuperRegion.Id); SuperRegion na = state.FullMap.GetSuperRegion(1); if (state.SABased && northafrica.OwnedByPlayer(myName) && africa.HasPlayer(state.FullMap, opponentName) && !na.HasPlayer(state.FullMap, opponentName) && (na.OwnedByPlayer(state.FullMap) != myName) && state.ExpansionTargets.Count > 0) { // do minimum expansion (should be NA or australia) List<DeployArmies> deploy = ExpandMinimum(state, armiesLeft); foreach (DeployArmies da in deploy) { deployArmies.Add(da); armiesLeft -= da.Armies; } // deploy all else on northafrica deployArmies.Add(new DeployArmies(myName, northafrica, armiesLeft)); armiesLeft = 0; } // if game is stuck with high stacks expand to get more income if (armiesLeft > 0) { bool bigstack = false; foreach (Region reg in state.VisibleMap.Regions) { if (reg.OwnedByPlayer(myName)) { if (reg.Armies > 180) { bigstack = true; } } } if (bigstack) { List<DeployArmies> expand = ExpandGameStalled(state, armiesLeft); foreach (DeployArmies da in expand) { deployArmies.Add(da); armiesLeft -= da.Armies; } } } if (finishableSuperRegion) { List<DeployArmies> deploy = FinishSuperRegion(state, armiesLeft); foreach (DeployArmies da in deploy) { deployArmies.Add(da); armiesLeft -= da.Armies; } } else { // used to have full attack against spotted enemy super region here, but it's now being taken care of during the next phase // minimum expansion if ((armiesLeft > 0) && (state.ExpansionTargets.Count > 0)) { // do minimum expansion, but only on expansiontargets that are close to being finished // or we know the game has been stalled for a while (stacks bigger then, lets say 60) // or we have no superregion at all, so we really need one //todo: and we are fairly certain the target sr is not already being bordered by enemy // check how many territories of the expansion target we already own int count = 0; foreach (Region reg in state.ExpansionTargets[0].SubRegions) { Region rn = state.FullMap.GetRegion(reg.Id); if (rn.OwnedByPlayer(myName)) count++; } bool issafe = true; // check if there are any estimated opponentstartingregions in or bordering this superregion // only check for south america, australia and africa, rest can be considered safe by default if (state.ExpansionTargets[0].ArmiesReward <= 3) { foreach (Region border in state.OpponentStartRegions) { foreach (Region n in border.Neighbors) { Region b = state.FullMap.GetRegion(n.Id); if (b.SuperRegion.Id == state.ExpansionTargets[0].Id) issafe = false; } } } // check if the game is starting to have big stacks bool bigstack = false; foreach (Region reg in state.VisibleMap.Regions) { if (reg.OwnedByPlayer(myName)) { if (reg.Armies > 60) { bigstack = true; // todo: refactor code below to find best path without region hardcoded logic // check if we are building a bigstack in middle of africa without having eyes on SA and northafrica doesnt belong to the enemy //Region northafrica = state.FullMap.GetRegion(21); if ((reg.SuperRegion.Id == 4) && state.FullMap.GetRegion(12).OwnedByPlayer("unknown") && !northafrica.OwnedByPlayer(opponentName)) { int nextstep = -1; if (northafrica.OwnedByPlayer("neutral")) nextstep = 21; if (northafrica.OwnedByPlayer("unknown")) { // go through east africa nextstep = 23; Region ea = state.FullMap.GetRegion(23); // if ea is taken by enemy, rethink if (ea.OwnedByPlayer(opponentName)) { // if congo is neutral, go through congo if (state.FullMap.GetRegion(24).OwnedByPlayer("neutral")) { nextstep = 24; } // if congo is unknown then i guess we're stuck in madagascar and have to flank through south africa if (state.FullMap.GetRegion(24).OwnedByPlayer("unknown")) { nextstep = 25; } } } if (nextstep != -1) { Region region = state.FullMap.GetRegion(nextstep); // find our neighbour with highest available armies foreach (Region a in region.Neighbors) { int aArmies = a.Armies + a.PledgedArmies - a.ReservedArmies; if (aArmies < 0) aArmies = 0; 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)) { deployArmies.Add(new DeployArmies(myName, neigh, armiesLeft)); state.ScheduleAttack(neigh, region, armiesLeft, neigh.Armies + armiesLeft - 1); armiesLeft = 0; } } } } } } // do minimum expansion only when we have a big stack and have safe superregions if ((armiesLeft > 0) && issafe) { if ((count > state.ExpansionTargets[0].SubRegions.Count * 0.5) || (bigstack) || (state.StartingArmies == 5)) { List<DeployArmies> deploy = ExpandMinimum(state, armiesLeft); foreach (DeployArmies da in deploy) { deployArmies.Add(da); armiesLeft -= da.Armies; } } } } } // deploy rest of your income bordering the enemy List<DeployArmies> placings = DeployBorderingEnemy(state, armiesLeft); foreach (DeployArmies da in placings) { deployArmies.Add(da); armiesLeft -= da.Armies; } } else { // no enemy in sight, expand normally / strategically if (finishableSuperRegion) { List<DeployArmies> deploy = FinishSuperRegion(state, armiesLeft); foreach (DeployArmies da in deploy) { deployArmies.Add(da); armiesLeft -= da.Armies; } } else { if (state.OZBased) { // if we are based in australia and have no territory in africa, europe or south america // we should be making our way into africa bool thereyet = false; foreach (Region reg in state.VisibleMap.Regions) { if ((reg.SuperRegion.Id == 2) || //SA (reg.SuperRegion.Id == 3) || //europe (reg.SuperRegion.Id == 4)) //africa { thereyet = true; } } if (!thereyet) { // we dont have egypt (22) but have middle east (36) if (!state.FullMap.GetRegion(22).OwnedByPlayer(myName) && state.FullMap.GetRegion(36).OwnedByPlayer(myName)) { deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(36), armiesLeft)); state.ScheduleAttack(state.FullMap.GetRegion(36), state.FullMap.GetRegion(22), armiesLeft, state.FullMap.GetRegion(36).Armies - 1 + armiesLeft); //state.scheduledAttack.Add(new Tuple<int, int, int>(36, 22, state.FullMap.GetRegion(36).Armies - 1 + armiesLeft)); armiesLeft = 0; } else // we dont have middle east (36) but have india (37) if (!state.FullMap.GetRegion(36).OwnedByPlayer(myName) && state.FullMap.GetRegion(37).OwnedByPlayer(myName)) { deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(37), armiesLeft)); state.ScheduleAttack(state.FullMap.GetRegion(37), state.FullMap.GetRegion(36), armiesLeft, state.FullMap.GetRegion(37).Armies - 1 + armiesLeft); //state.scheduledAttack.Add(new Tuple<int, int, int>(37, 36, state.FullMap.GetRegion(37).Armies - 1 + armiesLeft)); armiesLeft = 0; } else // we dont have india (37) but have siam (38) if (!state.FullMap.GetRegion(37).OwnedByPlayer(myName) && state.FullMap.GetRegion(38).OwnedByPlayer(myName)) { deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(38), armiesLeft)); state.ScheduleAttack(state.FullMap.GetRegion(38), state.FullMap.GetRegion(37), armiesLeft, state.FullMap.GetRegion(38).Armies - 1 + armiesLeft); //state.scheduledAttack.Add(new Tuple<int, int, int>(38, 37, state.FullMap.GetRegion(38).Armies - 1 + armiesLeft)); armiesLeft = 0; } else // we dont have siam (38) but have indonesia (39) if (!state.FullMap.GetRegion(38).OwnedByPlayer(myName) && state.FullMap.GetRegion(39).OwnedByPlayer(myName)) { deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(39), armiesLeft)); state.ScheduleAttack(state.FullMap.GetRegion(39), state.FullMap.GetRegion(38), armiesLeft, state.FullMap.GetRegion(39).Armies - 1 + armiesLeft); //state.scheduledAttack.Add(new Tuple<int, int, int>(39, 38, state.FullMap.GetRegion(39).Armies - 1 + armiesLeft)); armiesLeft = 0; } else { Console.Error.WriteLine("ozbased turn without any action?! (round " + state.RoundNumber + ")"); } } else { // lets go check north africa Region northafrica = state.FullMap.GetRegion(21); if (northafrica.OwnedByPlayer("unknown") || northafrica.OwnedByPlayer("neutral")) { int nextstep = state.FullMap.FindNextStep(12); if (nextstep != -1) { Region region = state.FullMap.GetRegion(nextstep); // find our neighbour with highest available armies foreach (Region a in region.Neighbors) { int aArmies = a.Armies + a.PledgedArmies - a.ReservedArmies; if (aArmies < 0) aArmies = 0; 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)) { deployArmies.Add(new DeployArmies(myName, neigh, armiesLeft)); state.ScheduleAttack(neigh, region, armiesLeft, neigh.Armies + armiesLeft - 1); armiesLeft = 0; } } } //todo: we have foot in africa/europe/south america but enemy could be expanding safely on north america... //todo: how can we be sure we are not wasting armies going to alaska? need to track historic of enemy deployments... } } if (state.AfricaBased) { // if africaBased and not saBased, go hard into brazil if (!state.SABased) { Region rnn = state.FullMap.GetRegion(21); // deploy all on north africa Region r = state.FullMap.GetRegion(12); // attack brazil state.ScheduleFullAttack(rnn, r, armiesLeft); deployArmies.Add(new DeployArmies(myName, rnn, armiesLeft)); armiesLeft = 0; } else if (state.FullMap.GetRegion(12).OwnedByPlayer(myName)) { // we have brazil and no enemy bordering, so we can predict enemy is coming at us from oz // so go hard into middle east Region rnn = state.FullMap.GetRegion(22); // deploy all on egypt Region r = state.FullMap.GetRegion(36); // attack middle east if (!r.OwnedByPlayer(myName)) { state.ScheduleFullAttack(rnn, r, armiesLeft); deployArmies.Add(new DeployArmies(myName, rnn, armiesLeft)); armiesLeft = 0; } } } // if saBased and no enemy on north africa, go hard into north africa from brazil if (state.SABased && !state.FullMap.GetRegion(21).OwnedByPlayer(opponentName)) { Region rnn = state.FullMap.GetRegion(12); // deploy all on brazil Region r = state.FullMap.GetRegion(21); // attack north africa if (!r.OwnedByPlayer(myName)) { state.ScheduleFullAttack(rnn, r, armiesLeft); deployArmies.Add(new DeployArmies(myName, rnn, armiesLeft)); armiesLeft = 0; } } if (state.SABased && state.FullMap.GetRegion(21).OwnedByPlayer(myName) && !state.NABased) { // do minimum expansion into north america // expansion target 0 should already be pointing at it if (armiesLeft > 0) { List<DeployArmies> deploy = ExpandMinimum(state, armiesLeft); foreach (DeployArmies da in deploy) { deployArmies.Add(da); armiesLeft -= da.Armies; } } // deploy rest on North Africa if (armiesLeft > 0) { deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(21), armiesLeft)); armiesLeft = 0; } } } // if no priority predictions occurs if (armiesLeft > 0) { List<DeployArmies> expand = ExpandTowardsEnemyWithFullStack(state, armiesLeft); foreach (DeployArmies da in expand) { deployArmies.Add(da); armiesLeft -= da.Armies; } } } return deployArmies; }