Step 5: Attacking the Enemy Hills

The Plan

If we see a hill, we need to do something about it. Hills are very important, it's the only way you can get points to win the game (besides killing all the other ants and hoping no one else got the hills first.)

  • If we see a hill, send all available ants to attack it.

The Implementation

If you see a hill, chances are you have sent a scouting ant to the enemy base, and chances are he's going to die, because that's where the enemy ants spawn. This means if you lose vision of the hill, you don't want to forget that it's there. We'll create another class level variable to help us remember where it is. If we see more than one hill, each ant will attack the closest one, just like the food gathering code.

The Code

Put this code in the do_setup method:

    def do_setup(self, ants):
        self.hills = []

This will be the list of all hills we have found.

Put the following code after the food gathering section and before the map exploration section.

        # attack hills
        for hill_loc, hill_owner in ants.enemy_hills():
            if hill_loc not in self.hills:
                self.hills.append(hill_loc)        
        ant_dist = []
        for hill_loc in self.hills:
            for ant_loc in ants.my_ants():
                if ant_loc not in orders.values():
                    dist = ants.distance(ant_loc, hill_loc)
                    ant_dist.append((dist, ant_loc, hill_loc))
        ant_dist.sort()
        for dist, ant_loc, hill_loc in ant_dist:
            do_move_location(ant_loc, hill_loc)

In the first part, we loop through all enemy hills, and if we haven't seen it before, we add it to the list.

In the second part, we create a list of all distances from ants to hills, just like we did for gathering food.

Last, we sort the list by closest distance first, then send each ant in to attack. We aren't checking to see if a target was already chosen, because we want to send in all ants to attack.

Put this class level variable declaration with the others:

    private Set<Tile> enemyHills = new HashSet<Tile>();

This will be the list of all enemy hills we have found.

Add the following code below the food gathering code, and above the exploring code:

        // add new hills to set
        for (Tile enemyHill : ants.getEnemyHills()) {
            if (!enemyHills.contains(enemyHill)) {
                enemyHills.add(enemyHill);
            }
        }
        // attack hills
        List<Route> hillRoutes = new ArrayList<Route>();
        for (Tile hillLoc : enemyHills) {
            for (Tile antLoc : sortedAnts) {
                if (!orders.containsValue(antLoc)) {
                    int distance = ants.getDistance(antLoc, hillLoc);
                    Route route = new Route(antLoc, hillLoc, distance);
                    hillRoutes.add(route);
                }
            }
        }
        Collections.sort(hillRoutes);
        for (Route route : hillRoutes) {
            doMoveLocation(route.getStart(), route.getEnd());
        }

In the first part, we loop through all enemy hills, and if we haven't seen it before, we add it to the list.

In the second part, we create a list of all distances from ants to hills, just like we did for gathering food.

Last, we loop through the sorted list by closest distance first, then send each ant in to attack. We aren't checking to see if a target was already chosen, because we want to send in all ants to attack. (Note: we never remove an enemy hill once we have added it. )

The Results

Let's run the bot again and see how we do.

C:\aichallenge>tutorial.cmd
running for 60 turns
                  ant_count c_turns climb? cutoff food r_turn ranking_bots s_alive s_hills score  w_turn winning
turn    0 stats:   [1,1,0]     0    [1,1]    -     18    0        None      [1,1]   [1,1]  [1,1]   0     None
turn    1 stats:   [1,1,0]     0    [1,1]    -     16    1       [0,0]      [1,1]   [1,1]  [1,1]   1     [0,1]
turn    2 stats:   [2,1,0]     0    [1,1]    -     16    1       [0,0]      [1,1]   [1,1]  [1,1]   1     [0,1]
...
turn   43 stats:   [7,3,0]     0    [0,0]    -     2     43      [0,1]      [1,1]   [1,0]  [3,0]   43     [0]
score 3 0
status survived survived
playerturns 43 43

Here is the replay:

# [ { "embedded": true, "game": "5 - Attacking Enemy Hills" }, 600, 600, { "speedFactor": 0, "speedFastest": 2, "speedSlowest": 2, "zoom": 1 }, "example_games/tutorial.5.replay" ]

There we go; A successful kill! This concludes the tutorial.

There's probably a lot more that can be done. Here are a few ideas:

  • The ants.distance and ants.direction functions work using a manhatten distance, which means they assume you can walk on water and they will get you stuck in corners. Our tutorial map was very open, so it didn't hurt us much. You'll need to implement some path finding and replace these functions to give more accurate results and help you find your way out of a maze.
  • We didn't talk about fighting other ants. The attack rules are such that you can kill an enemy ant without taking losses. Maybe some logic to find an enemy, send some reinforcements and then move in for the kill would help.
  • Food will constantly spawn during the game, and it could spawn anywhere. Keeping your ants spread out to cover the whole map will help you spot new food and gather before the opponent does. This means our exploring code only works once, not continuously.
  • You'll lose a point if you don't defend your hill. It may be good to keep a couple of ants around just in case you get attacked.
  • Deciding whether to attack a hill or gather food first may change during the game. You may want to attack a hill first if you have plenty of ants and are trying to be faster than the next closest enemy. You may want to gather more ants if you are trying to defend you hill.
  • The data structures using in the tutorial are just to get you started, but may not be the best choice. Try and balance memory usage with CPU performance to make the best bot.
  • Watch the games of the top bots, and try figure out what they do. Then implement those ideas.

Next