public void Retreat(GameState state, int[,] EnemyDist, Ant ant) { var best = Ants.Aim.Keys.Select(dir => new { dir, loc = state.GetDestination(ant, dir) }) .Where(x => !state.OccupiedNextRound.At(x.loc)) .Where(x => state.GetIsPassable(x.loc)) .OrderBy(x => EnemyDist.At(x.loc)) .LastOrDefault(); if (best == null) { return; } if (EnemyDist.At(best.loc) >= EnemyDist.At(ant)) { Bot.IssueOrder(state, ant, best.dir, "Retreat" + battleId); } //foreach (Direction direction in Ants.Aim.Keys) //{ // Location newLoc = state.GetDestination(ant, direction); // //Todo sort best result; // if (state.GetIsPassable(newLoc) && !state.OccupiedNextRound.At(newLoc) && EnemyDist.At(newLoc) > EnemyDist.At(ant)) // { // Bot.IssueOrder(state, ant, direction); // break; // } //} }
public void Attack(GameState state, int[,] EnemyDist, Ant ant) { var best = Ants.Aim.Keys.Select(dir => new { dir, loc = state.GetDestination(ant, dir) }) .Where(x => !state.OccupiedNextRound.At(x.loc)) .Where(x => state.GetIsPassable(x.loc)) .OrderByDescending(x => EnemyDist.At(x.loc)) //.ThenBy(state.GetBestDirection(x.loc, loc) //Prioritize by direction, need to have a goal... .LastOrDefault(); if (best == null) { return;//TODO wals around obstacle here?? } if (EnemyDist.At(best.loc) <= EnemyDist.At(ant)) { Bot.IssueOrder(state, ant, best.dir, "Attack" + battleId); } //foreach (Direction direction in Ants.Aim.Keys) //{ // Location newLoc = state.GetDestination(ant, direction); // //Todo sort best result; // if (state.GetIsPassable(newLoc) && !state.OccupiedNextRound.At(newLoc) && EnemyDist.At(newLoc) > EnemyDist.At(ant)) // { // Bot.IssueOrder(state, ant, direction); // break; // } //} }
public static void IssueOrder(GameState state, Location loc, Direction direction, string action) { System.Console.Out.WriteLine("o {0} {1} {2}", loc.Row, loc.Col, direction.ToChar()); Logger.Log.Trace("Ant Moved : {0} => {1} ({2}) ", loc, direction, action); if (state.OccupiedNextRound.At(loc) != true) { Logger.Log.Error("Source Location was not occupied (ant moved)... ANT {0} {1}", loc, new System.Diagnostics.StackTrace(1, true)); } if (state.OccupiedNextRound.At(state.GetDestination(loc, direction)) == true) { Logger.Log.Error("Dest Location is occupied... ANT {0} {1}", loc, new System.Diagnostics.StackTrace(1, true)); } state.OccupiedNextRound.Set(loc, false); state.OccupiedNextRound.Set(state.GetDestination(loc, direction), true); }
public static TargetWithDir <T> FindClosest <T>(GameState state, Location startingPoint, Func <Location, T> test, int MaxDistance = 10) where T : class { Dictionary <Location, int> distance = new Dictionary <Location, int>(); var queue = new Queue <Location>(); distance[startingPoint] = 0; queue.Enqueue(startingPoint); while (queue.Count > 0) { var item = queue.Dequeue(); foreach (Direction direction in Ants.Aim.Keys) { Location newLoc = state.GetDestination(item, direction); if (distance.ContainsKey(newLoc)) { continue;//Already tested } if (!state.GetIsPassable(newLoc)) { continue;//Cant go there } T result = test(newLoc); if (result != null) { return(new TargetWithDir <T>(result, direction, distance[item] + 1, startingPoint)); } if (distance[item] + 1 >= MaxDistance) { continue; } distance[newLoc] = distance[item] + 1; queue.Enqueue(newLoc); } } return(null); }
private bool goToFront(GameState state, int[,] visibility, Ant ant) { int value = visibility.At(ant); Direction dir = Direction.North; foreach (Direction direction in Ants.Aim.Keys) { Location newLoc = state.GetDestination(ant, direction); if (state.GetIsPassable(newLoc) && !state.OccupiedNextRound.At(newLoc) && value > visibility.At(newLoc)) { value = visibility.At(newLoc); dir = direction; } } if (value != visibility.At(ant)) { IssueOrder(state, ant, dir, "Go To Front"); return(true); } return(false); }
private bool getFood(GameState state, int[,] FoodProximity, Ant ant) { if (FoodProximity.At(ant) < FoodRadius) { int value = 999; Direction dir = Direction.North; foreach (Direction direction in Ants.Aim.Keys) { Location newLoc = state.GetDestination(ant, direction); if (state.GetIsPassable(newLoc) && !state.OccupiedNextRound.At(newLoc) && value > FoodProximity.At(newLoc)) { value = FoodProximity.At(newLoc); dir = direction; } } IssueOrder(state, ant, dir, "GetFoodOld"); return(true); } return(false); }
private bool explore(GameState state, int[,] visibility, Ant ant) { ////find the nearest undiscovered spot and go in that direction // TODO if two direction are in the way of the "unknown", select the one with the most spread with the other ants { int value = visibility.At(ant); if (value < unknownExplorationDistance) { Direction dir = Direction.North; foreach (Direction direction in Ants.Aim.Keys) { Location newLoc = state.GetDestination(ant, direction); if (state.GetIsPassable(newLoc) && !state.OccupiedNextRound.At(newLoc) && value > visibility.At(newLoc)) { value = visibility.At(newLoc); dir = direction; } } if (value != visibility.At(ant)) { IssueOrder(state, ant, dir, "Explore"); return(true); } } } //try distanciate other ants //var AllyProximity = calculateAllyProximity(state, ant); //if (AllyProximity.At(ant) < 20) //{ // int value = AllyProximity.At(ant); // Direction dir = Direction.North; // foreach (Direction direction in Ants.Aim.Keys) // { // Location newLoc = state.GetDestination(ant, direction); // if (state.GetIsPassable(newLoc) && !state.OccupiedNextRound.At(newLoc) && value < AllyProximity.At(newLoc)) // { // value = AllyProximity.At(newLoc); // dir = direction; // } // } // if (value != AllyProximity.At(ant)) // { // IssueOrder(state, ant, dir); // return true; // } //} ////try all the directions //foreach (Direction direction in Ants.Aim.Keys) //{ // // GetDestination will wrap around the map properly // // and give us a new location // Location newLoc = state.GetDestination(ant, direction); // // GetIsPassable returns true if the location is land // if (state.GetIsPassable(newLoc)) // { // IssueOrder(ant, direction); // // stop now, don't give 1 and multiple orders // return true; // } //} return(false); }
public override void DoTurn(GameState state) { try { Log.Debug("Starting Turn " + turn++);// state.TimeRemaining //FoodRadius = (int)Math.Sqrt(state.ViewRadius2); //Calculate proximity //var FoodProximity = calculateFoodProximity(state); var visibility = calculateVisibilityProximity(state); var enemyProximity = CalculateProximity(state, state.EnemyHills.Union <TeamLocation>(state.EnemyAnts).ToList(), 200); var antMoved = new List <Ant>(); var ennemyConsidered = new List <Ant>(); //Attack/defend foreach (Ant enemy in state.EnemyAnts) { if (ennemyConsidered.Contains(enemy)) { continue; } if (Math.Sqrt(state.ViewRadius2) - visibility.At(enemy) < BattleRadius) { var battle = new Battle(); battle.StartBattle(state, state.MyAnts.Except(antMoved).OrderBy(a => state.GetDistance(enemy, a)).First(), enemy, enemyProximity); ennemyConsidered.AddRange(battle.EnemyPlatoon); antMoved.AddRange(battle.AllyPlatoon); } } { //Food.getAnt var antLookingForFood = state.MyAnts.Except(antMoved).ToList(); var antGatheringFood = new Dictionary <Ant, TargetWithDir <Ant> >(); var foodqueue = new Queue <Location>(state.FoodTiles.Union(state.EnemyHills)); while (foodqueue.Count > 0) { var food = foodqueue.Dequeue(); var result = FindClosest(state, food, x => antLookingForFood.Select(ant => (x.Row == ant.Row && x.Col == ant.Col) ? ant : null).Where(y => y != null).FirstOrDefault()); Log.Trace("Food.GetAnt : Food{0} => Ant {1}", food, result?.Target); if (result != null) { if (antGatheringFood.ContainsKey(result.Target)) { Log.Trace("Food.GetAnt : ANT already selected at Food{0} => Ant {1}", antGatheringFood[result.Target].Source, result.Target); if (antGatheringFood[result.Target].Dist > result.Dist) { foodqueue.Enqueue(antGatheringFood[result.Target].Source); } else { continue; } } var dir = result.Dir.Opposite(); Location newLoc = state.GetDestination(result.Target, dir); antGatheringFood.Add(result.Target, result); antLookingForFood.Remove(result.Target); } } foreach (var item in antGatheringFood) { var result = item.Value; var dir = result.Dir.Opposite(); Location newLoc = state.GetDestination(result.Target, dir); if (!state.OccupiedNextRound.At(newLoc)) { IssueOrder(state, result.Target, dir, "GetFood"); } } antMoved.AddRange(antGatheringFood.Keys); } var antToMove = state.MyAnts.Except(antMoved).ToList(); foreach (Ant ant in antToMove) { // check if we have time left to calculate more orders if (state.TimeRemaining < 10) { break; } // General game signals // Defend hill -> converge + sacrifice self //continue if move done //if (getFood(state, FoodProximity, ant)) //Replace par food.getAnt() above // continue; if (explore(state, visibility, ant)) { continue; } goToFront(state, enemyProximity, ant); } } catch (Exception e) { Log.Debug(e.ToString()); } //For debugging //while (state.TimeRemaining > 10) continue; }
// DoTurn is run once per turn public override void DoTurn(GameState state) { state.expectedLocation.Clear(); //attack until our number of ants falls below 250 from 300 if (!attackMode && state.MyAnts.Count > 300) attackMode = true; if (attackMode && state.MyAnts.Count < 250) attackMode = false; this.diffuseOne(state); this.diffuseTwo(state); // loop through all my ants and try to give them orders foreach (Ant ant in state.MyAnts) { Location up = state.GetDestination(ant, Direction.North); Location right = state.GetDestination(ant, Direction.East); Location left = state.GetDestination(ant, Direction.West); Location down = state.GetDestination(ant, Direction.South); List<Tup4> adjacentTiles = new List<Tup4>(); //use diffusion layer 1 this layer prefers to harvest food and grow the ant colony if (!attackMode) { Tup4 n1 = new Tup4(state.diffusionOne[up.Row, up.Col], Direction.North, up.Row, up.Col); Tup4 e1 = new Tup4(state.diffusionOne[right.Row, right.Col], Direction.East, right.Row, right.Col); Tup4 w1 = new Tup4(state.diffusionOne[left.Row, left.Col], Direction.West, left.Row, left.Col); Tup4 s1 = new Tup4(state.diffusionOne[down.Row, down.Col], Direction.South, down.Row, down.Col); adjacentTiles.Add(n1); adjacentTiles.Add(e1); adjacentTiles.Add(s1); adjacentTiles.Add(w1); } else { Tup4 n2 = new Tup4(state.diffusionTwo[up.Row, up.Col], Direction.North, up.Row, up.Col); Tup4 e2 = new Tup4(state.diffusionTwo[right.Row, right.Col], Direction.East, right.Row, right.Col); Tup4 w2 = new Tup4(state.diffusionTwo[left.Row, left.Col], Direction.West, left.Row, left.Col); Tup4 s2 = new Tup4(state.diffusionTwo[down.Row, down.Col], Direction.South, down.Row, down.Col); //use diffusion layer 2, this layer prefers to be aggressive adjacentTiles.Add(n2); adjacentTiles.Add(s2); adjacentTiles.Add(e2); adjacentTiles.Add(w2); } double maxDiffusion = 0; //assume the ant can't move Direction direction = Direction.East; int ct = 0; int row = 0; int col = 0; //check the four adjacent tiles to move while (ct < 4) { //check if this tile has a higher diffusion score and that it is not occupied already by a friendly ant if (adjacentTiles[ct].Item1 > maxDiffusion && state.diffusionOne[adjacentTiles[ct].Item3, adjacentTiles[ct].Item4] > 0 && state.GetIsUnoccupied(new Location(adjacentTiles[ct].Item3, adjacentTiles[ct].Item4))) { maxDiffusion = adjacentTiles[ct].Item1; direction = adjacentTiles[ct].Item2; row = adjacentTiles[ct].Item3; col = adjacentTiles[ct].Item4; } ct += 1; } //ants will only move onto tiles with a diffusion score > 0 if (maxDiffusion > 0) { IssueOrder(ant, direction); state.diffusionOne[row, col] = 0; state.expectedLocation[state.GetDestination(ant, direction)] = ant; } else { //ant could not move expected location is the same state.expectedLocation[new Location(ant.Row, ant.Col)] = ant; } // check if we have time left to calculate more orders if (state.TimeRemaining < 10) { //exit the loop immediately to prevent the bot from timing out break; } } }
/// <summary> /// Calculate the current diffusion scores for layer 2. /// </summary> /// <param name="state">The state.</param> public void diffuseTwo(GameState state) { for (int row = 0; row < state.Height; row++) { for (int col = 0; col < state.Width; col++) { if (state.map[row, col] == Tile.Water) state.diffusionTwo[row, col] = WATER_SCORE; else if (state.map[row, col] == Tile.Ant && state.ants.ContainsKey(new Location(row, col)) && state.ants[new Location(row, col)].Team != 0) { state.diffusionTwo[row, col] = ENEMY_ANT_SCORE_D2; } else if (state.map[row, col] == Tile.Unseen) { state.diffusionTwo[row, col] = UNSEEN_SCORE_D2; } else if (state.isEnemyHill(row, col)) { state.diffusionTwo[row, col] = ENEMYHILL_SCORE_D2; } else if (state.isMyHill(row, col)) { state.diffusionTwo[row, col] = MYHILL_SCORE; } else { double u = state.diffusionTwo[row, col]; Location location = new Location(row, col); Location up = state.GetDestination(location, Direction.North); Location right = state.GetDestination(location, Direction.East); Location left = state.GetDestination(location, Direction.West); Location down = state.GetDestination(location, Direction.South); state.diffusionTwo[row, col] = u + D2_COEFFICIENT * (1 + state.diffusionTwo[up.Row, up.Col] + state.diffusionTwo[down.Row, down.Col] + state.diffusionTwo[left.Row, left.Col] + state.diffusionTwo[right.Row, right.Col] - u * 4); } } } }
/// <summary> /// Calculate the current diffusion scores for layer 1. /// </summary> /// <param name="state">The state.</param> public void diffuseOne(GameState state) { for (int row = 0; row < state.Height; row++) { for (int col = 0; col < state.Width; col++) { if (state.map[row, col] == Tile.Water) { state.diffusionOne[row, col] = WATER_SCORE; } else if (state.map[row, col] == Tile.Ant) { state.diffusionOne[row, col] = MY_ANT_SCORE_D1; Location location = new Location(row, col); if (state.ants.ContainsKey(location)) { Ant ant = state.ants[location]; if (ant.Team != 0) { List<AntHill> myHills = state.MyHills; foreach (AntHill myHill in myHills) { if (state.GetDistance(myHill, ant) <= 12) { state.diffusionOne[row, col] = HILL_IN_DANGER; break; } } } } } else if (state.map[row, col] == Tile.Food) { state.diffusionOne[row, col] = FOOD_SCORE_D1; } else if (state.map[row, col] == Tile.Unseen) { state.diffusionOne[row, col] = UNSEEN_SCORE_D1; } else if (state.isEnemyHill(row, col)) { state.diffusionOne[row, col] = ENEMYHILL_SCORE_D1; } else if (state.isMyHill(row, col)) { state.diffusionOne[row, col] = MYHILL_SCORE; } else { double u = state.diffusionOne[row, col]; Location L = new Location(row, col); Location up = state.GetDestination(L, Direction.North); Location right = state.GetDestination(L, Direction.East); Location left = state.GetDestination(L, Direction.West); Location down = state.GetDestination(L, Direction.South); state.diffusionOne[row, col] = u + D1_COEFFICIENT * (1 + state.diffusionOne[up.Row, up.Col] + state.diffusionOne[down.Row, down.Col] + state.diffusionOne[left.Row, left.Col] + state.diffusionOne[right.Row, right.Col] - u * 4); } } } }