Skip to content

Commit

Permalink
Add bot summary.
Browse files Browse the repository at this point in the history
  • Loading branch information
stefank0 committed Jan 28, 2019
1 parent 72d4e14 commit 104dad0
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
# TeamSchildpad

## TODO
- Check lost games and see what goes wrong (check mlomb for timeouts)
## Summary

### Moving/mining
The main steps of our bot are:
a) Create graphs representing the game map and calculate distances.
b) Assign ships to destinations using these distances.
c) Assign commands based on these destinations.

a) The game map is viewed as a graph, with edges connecting adjacent cells. The cost of moving over an edge contains costs accounting for traffic jams/enemy threat/fuel usage and are ship specific*. For these graphs (one graph per ship), distances are computed to all cells (using the Dijkstra algorithm only for a subgraph in order to stay within 2sec computation time).

\* An empty ship experiences less threat from enemy ships. The implementation is such that there is more or less a threshold separating scary from not scary.

b) All cells are scored for each ship: the score of cell x equals the maximum average halite gathered per turn out of a small set scenarios that involve moving to cell x (scenarios: mining up to 5 turns on cell x or moving/mining its best neighbor). Halite carried by enemy ships is also mixed in*, as are turns necessary to return to a dropoff (counted fully if the ship completely fills up to 1000, by ratio if the ship only partially fills). Based on these scores, ships are assigned to destinations, under the constraint that no destination is chosen twice (Hungarian algorithm, matching ships to map cells, maximizing the sum of the scores). If, for a certain ship, the expected total gathered halite in the rest of the game is very low, the ship will go on suicide mission defending our closest dropoff. Ships return to a dropoff when they are nearly full or when the average halite (the score) of the chosen destination is low compared (in some way) to the currently carried halite. Once a ship chooses to return to a dropoff, it is forced to return until it actually reaches a dropoff.

\* Actually the difference in carried halite compared to our ship, under some conditions, such as being in friendly territory. This difference is placed at 3 locations: the location of the enemy ship and the two adjacent locations furthest from our dropoffs, in order to cut off the escape route of the enemy ship and to lure in more than one of our ships to work together.

c) All moves are scored for each ship: the score of move x equals the distance of the shortest path to the destination c given move x (from a to b): score = edge cost from a to b + shortest path cost from b to c. Assign commands, minimizing the sum of these scores, under the constraint of zero self collisions (Hungarian algorithm again, matching ships to map cells). The result: if possible, all ships choose the shortest path, if not, the summed additional distance is minimized.

### Spawning
We tried to make an estimate of the return on investment of building a ship, based on real game data. We spawn if this estimate clearly indicates that spawning is a good idea or when our ship number is behind on the opponent ship numbers (early game: > median, mid game: > minimum, end game: don't spawn).

### Dropoffs
Attempts are made to plan a new dropoff when the ship-to-dropoff ratio reaches a certain point. A search area is determined, consisting of cells that meet certain criteria: close enough such that at least some ships will choose it as dropoff destination, yet not to close to existing dropoffs, high enough halite density and not controlled by the enemy. Basically, the cell with highest halite density is then chosen as spawn location for the new dropoff. If a suitable location is found, just enough halite is kept in reserve (taking into account halite carried by ships reaching a dropoff/shipyard before the new dropoff can be built). From that moment, the dropoff is taken into account as every other dropoff and the first ship getting there actually builds it. The only difference with regular dropoffs is that the planned dropoff can move a single step each turn, so that the dropoff itself can flee (a bit) from the enemy if necessary, and respond to changes in general.

### Python
Using Python to build the bot came with some challenges regarding performance. We needed to rely heavily on NumPy, which was OK. However, straightforward usage of the SciPy implementations of the Hungarian/Dijkstra algorithm resulted in timeouts, and the time was spent inside of the SciPy libraries. Because of that we needed to change the problem a bit / decrease the problem size (perturbing the problem/solution) and to carefully cache/precompute results that could be reused. Despite these performance problems, we would probably still use Python for our next bot, because we like using NumPy, there are enough options we did not explore (Cython, PyCUDA, ..) and in the end it worked out for this one.


## NOT TODO
- Performance improvements (linear_sum_assignment in Cython)(simpler/faster shortest path algorithm)(PyCUDA GPU).
Expand Down

0 comments on commit 104dad0

Please sign in to comment.