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
andants.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
- Check out the forums or IRC (webclient) to discuss more ideas with the other contestants