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 }