/ benchmark / RuleBot.java
RuleBot.java
  1  import hlt.*;
  2  import pep.TextLogger;
  3  
  4  import java.util.*;
  5  
  6  /**
  7   * This benchmark bot has basic navigation optimizations (ships don't collide with spawns or deadlock)
  8   * Ships harvest from the best adjacent cell, and deposit when approximately full
  9   */
 10  public class RuleBot {
 11  
 12      private static Random rng;
 13      private static Game game;
 14      private static Player me;
 15      private static GameMap gameMap;
 16      private static Map<EntityId, Status> statuses = new HashMap<>();
 17      private static String avgInitial;
 18  
 19      private enum Status {
 20          EXPLORING, RETURNING
 21      }
 22  
 23      public static void main(final String[] args) {
 24          rng = new Random(System.nanoTime());
 25          game = new Game();
 26          game.ready("RuleBot");
 27  
 28          Log.log("Successfully created bot! My Player ID is " + game.myId);
 29  
 30          for (;;) {
 31              game.updateFrame();
 32              me = game.me;
 33              gameMap = game.gameMap;
 34              Map<EntityId, Command> commands = new HashMap<>();
 35  
 36              updateStatuses();
 37              addSpawns(commands);
 38              addMoves(getTargets(), commands);
 39              // logCommands(commands);
 40              writePerfomance();
 41              game.endTurn(commands.values());
 42          }
 43      }
 44  
 45      private static void logCommands(Map<EntityId, Command> commands){
 46          for (Command cmd : commands.values()) {
 47              Log.log(cmd.command);
 48          }
 49      }
 50  
 51      private static void writePerfomance(){
 52          if (game.turnNumber == 1){
 53                  int avgHalite = gameMap.getTotalHalite() / (gameMap.width * gameMap.width);
 54                  avgInitial = Integer.toString(avgHalite);
 55          }
 56          if (game.turnNumber == Constants.MAX_TURNS - 1){
 57              String bankHalite = Integer.toString(me.halite  - 4000);
 58              TextLogger.writeLine("rule.txt", avgInitial + ", " + bankHalite);
 59          }
 60      }
 61  
 62      /**
 63       * Update the status of each ship
 64       */
 65      private static void updateStatuses() {
 66          for (final Ship ship : me.ships.values()) {
 67              if (!statuses.containsKey(ship.id)){
 68                  statuses.put(ship.id, Status.EXPLORING);
 69              } else if (statuses.get(ship.id) == Status.EXPLORING && ship.getHalite() > 0.9 * Constants.MAX_HALITE){
 70                  statuses.put(ship.id, Status.RETURNING);
 71              } else if (statuses.get(ship.id) == Status.RETURNING && ship.position.equals(me.shipyard.position)){
 72                  statuses.put(ship.id, Status.EXPLORING);
 73              } else if (game.turnNumber > 0.9 * Constants.MAX_TURNS && ship.getHalite() > 0.3 * Constants.MAX_HALITE){
 74                  statuses.put(ship.id, Status.RETURNING);
 75              }
 76          }
 77      }
 78  
 79      /**
 80       * @return A map specifying the target position of each ship
 81       */
 82      private static Map<EntityId, Position> getTargets() {
 83          Map<EntityId, Position> targets = new HashMap<>();
 84  
 85          for (final Ship ship : me.ships.values()) {
 86              Position target = ship.position;
 87  
 88              if (statuses.get(ship.id) == Status.RETURNING) {
 89                  target = me.shipyard.position;
 90              } else if (statuses.get(ship.id) == Status.EXPLORING && gameMap.at(ship.position).halite < Constants.MAX_HALITE / 10) {
 91                  final Direction randomDirection = Direction.ALL_CARDINALS.get(rng.nextInt(4));
 92                  target = ship.position.directionalOffset(randomDirection);
 93                  for (Position pos : ship.position.adjacentPositions()) {
 94                      if (gameMap.at(pos).halite > 1.3 * gameMap.at(target).halite) {
 95                          target = pos;
 96                      }
 97                  }
 98              }
 99              targets.put(ship.id, target);
100          }
101          return targets;
102      }
103  
104      /**
105       * Adds moves to the command queue based on target positions
106       */
107      private static void addMoves(Map<EntityId, Position> targets, Map<EntityId, Command> commands){
108          // add moves for ships
109          for (Map.Entry<EntityId, Position> entry : targets.entrySet()){
110              Ship ship = me.ships.get(entry.getKey());
111              Position target = entry.getValue();
112              if (ship.position.equals(target) || !gameMap.canMove(ship)){
113                  commands.put(ship.id, ship.stayStill());
114              } else {
115                  Direction dir = gameMap.naiveNavigate(ship, target, false);
116                  commands.put(ship.id, ship.move(dir));
117                  gameMap.at(ship.position).markSafe();
118              }
119          }
120      }
121  
122      private static void addSpawns(Map<EntityId, Command> commands){
123          if (me.ships.size() == 0) {
124              commands.put(me.shipyard.id, Command.spawnShip());
125          }
126      }
127  }