private static void doMinerMove() { // If there is an available adjacent tile with twice as much ore we are better off moving Direction startDir = directions[rand.nextInt(directions.length)]; Direction d = startDir; Direction best = Direction.NONE; double mostOre = rc.senseOre(myLoc) * 2; // Only move if there is twice as much ore boolean done = false; while (!done) { if (rc.canMove(d)) { MapLocation adj = rc.getLocation().add(d); double ore = rc.senseOre(adj); if ((ore > mostOre || (ore == mostOre && ore > 0 && adj.distanceSquaredTo(myHQ) > myLoc.distanceSquaredTo(myHQ))) && !threats.isThreatened(adj)) { mostOre = rc.senseOre(adj); best = d; } } d = d.rotateRight(); done = (d == startDir); } if (best != Direction.NONE) { rc.setIndicatorString(2, "Mining - better ore " + d); try { rc.move(best); } catch (GameActionException e) { System.out.println("Miner move exception"); // e.printStackTrace(); } } }
// All combat units (Soldiers, Bashers, Tanks, Drones, Launchers, Commander) private static void runCombat() { while (true) { threats.update(); myLoc = rc.getLocation(); // Move if we can and want to if (rc.isCoreReady()) { boolean ignoreThreat = overwhelms(); if (!ignoreThreat && shouldRetreat()) { if (rc.isWeaponReady() && myType.loadingDelay == 0) attackWeakest(); doRetreatMove(); // Pull back if in range of the enemy guns } else { boolean engaged = false; if (rc.isCoreReady() && inCombat(4)) engaged = doCloseWithEnemyMove(ignoreThreat); if (rc.isCoreReady() && !engaged) // Close with enemy might not do a move if the enemy is a drone out of // reach doAdvanceMove(); } } // Attack if there is an enemy in sight if (myType == RobotType.LAUNCHER) doLaunch(); else if (rc.isWeaponReady()) attackWeakest(); doTransfer(); rc.yield(); } }
private static void flashTowards(MapLocation m, boolean ignoreThreat) { // We want to pick a safe tile that is within flash range (10) and nearest to the destination // If we are allowed to ignore threat store the nearest threatened tile in case there are no // safe ones // We don't bother with moves to adjacent tiles! MapLocation[] inRange = MapLocation.getAllMapLocationsWithinRadiusSq(myLoc, GameConstants.FLASH_RANGE_SQUARED); MapLocation bestSafe = myLoc; MapLocation best = myLoc; // The closest regardless of threat try { for (MapLocation target : inRange) { if (!target.equals(myLoc) && rc.isPathable(myType, target) && !rc.isLocationOccupied(target) && target.distanceSquaredTo(myLoc) > 1) { if (target.distanceSquaredTo(m) < bestSafe.distanceSquaredTo(m) && !threats.isThreatened(target)) bestSafe = target; if (target.distanceSquaredTo(m) < best.distanceSquaredTo(m)) best = target; } } if (!bestSafe.equals(myLoc)) rc.castFlash(bestSafe); else if (ignoreThreat && !best.equals(myLoc)) rc.castFlash(best); } catch (GameActionException e) { System.out.println("Flash exception"); // e.printStackTrace(); } }
// Drones private static void runDrone() { moveDir = Direction.NORTH; droneMoveCurrent = 1; droneMoveMax = 2; patrolClockwise = true; droneCentred = false; // We haven't made it to the centre of our spiral yet while (true) { threats.update(); myLoc = rc.getLocation(); // Attack if there is an enemy in sight if (rc.isWeaponReady()) attackWeakest(); // Move if we can and want to if (rc.isCoreReady()) { if (shouldRetreat()) { doRetreatMove(); // Pull back if in range of the enemy guns } else if (Clock.getRoundNum() < 600) { doPatrol(); } else { doSupply(); } } doTransfer(); rc.yield(); } }
/* * Head towards the nearest tile that we haven't sensed before * If there is a tie, pick the one nearest to the hq */ private static void doPatrol() { if (!droneCentred) { // start point for the spiral is 2/5 of the way from our HQ to their HQ MapLocation centre = new MapLocation( (3 * myHQ.x + 2 * threats.enemyHQ.x) / 5, (3 * myHQ.y + 2 * threats.enemyHQ.y) / 5); if (threats.isThreatened(centre) || myLoc.distanceSquaredTo(centre) <= 2) droneCentred = true; else { moveDir = myLoc.directionTo(centre); } } if (droneCentred && --droneMoveCurrent <= 0) { if (patrolClockwise) moveDir = moveDir.rotateRight(); else moveDir = moveDir.rotateLeft(); if (!moveDir.isDiagonal()) droneMoveMax++; droneMoveCurrent = droneMoveMax; } while (true) { try { if (rc.canMove(moveDir) && !threats.isThreatened(myLoc.add(moveDir))) { rc.move(moveDir); break; } else if (rc.canMove(moveDir.rotateLeft()) && !threats.isThreatened(myLoc.add(moveDir.rotateLeft()))) { rc.move(moveDir.rotateLeft()); break; } else if (rc.canMove(moveDir.rotateRight()) && !threats.isThreatened(myLoc.add(moveDir.rotateRight()))) { rc.move(moveDir.rotateRight()); break; } else if (droneCentred) { moveDir = moveDir.opposite(); patrolClockwise = !patrolClockwise; if (!moveDir.isDiagonal()) droneMoveMax++; droneMoveCurrent = droneMoveMax; } else { break; } } catch (GameActionException e) { System.out.println("Drone patrol exception"); // e.printStackTrace(); } } }
private static void runTower() { while (true) { threats.update(); // Attack if there is an enemy in sight if (rc.isWeaponReady()) attackWeakest(); rc.yield(); } }
// Factories and supply depots private static void runBuilding() { // Most builds spawn units if (myType.canSpawn()) strategy = new BuildStrategy(rc); while (true) { if (rc.isCoreReady() && myType.canSpawn()) { threats.update(); RobotType build = strategy.getBuildOrder(); if (build != null) trySpawn(rc.getLocation().directionTo(threats.enemyHQ), build); } doTransfer(); rc.yield(); } }
// Beavers private static void runBeaver() { strategy = new BuildStrategy(rc); rand = new Random(rc.getID()); while (true) { threats.update(); myLoc = rc.getLocation(); if (rc.isCoreReady()) { RobotType build = strategy.getBuildOrder(); if (build != null) tryBuild(rc.getLocation().directionTo(threats.enemyHQ), build); } // Attack if there is an enemy in sight if (rc.isWeaponReady()) attackWeakest(); double ore = rc.senseOre(rc.getLocation()); // Move if we can and want to if (rc.isCoreReady()) { boolean ignoreThreat = overwhelms(); if (!ignoreThreat && shouldRetreat()) { doRetreatMove(); // Pull back if in range of the enemy guns } else { doMinerMove(); if (ore == 0 && rc.isCoreReady()) { // We didn't find ore nearby doSearchMove(); } } } // Mine if possible if (rc.isCoreReady() && ore > 0) { try { rc.mine(); } catch (GameActionException e) { System.out.println("Mining Exception"); // e.printStackTrace(); } } doTransfer(); rc.yield(); } }
/* * Beavers and miners without ore do this */ private static void doSearchMove() { // We keep moving in the direction we were going // When blocked we turn left or right depending on our unique ID rc.setIndicatorString(2, "Mining: No ore - searching"); if (lastMove == null || rand.nextInt(10) == 1) lastMove = directions[rand.nextInt(directions.length)]; Direction startDir = lastMove; while (!rc.canMove(lastMove) || threats.isThreatened(myLoc.add(lastMove))) { if (rc.getID() % 2 == 0) lastMove = lastMove.rotateLeft(); else lastMove = lastMove.rotateRight(); if (lastMove == startDir) // We are trapped return; } try { rc.move(lastMove); } catch (GameActionException e) { System.out.println("Move exception"); // e.printStackTrace(); } }
// Computers private static void runOther() { int numTowers = -1; while (true) { threats.update(); myLoc = rc.getLocation(); // Move if we can and want to if (rc.isCoreReady() && myType.canMove()) { if (shouldRetreat()) doRetreatMove(); // Pull back if in range of the enemy guns else doAdvanceMove(); // Move towards our HQ } doTransfer(); // Perform a background breadth first search to the enemy HQ if (myType == RobotType.COMPUTER && Clock.getBytecodesLeft() > 1000) { bfs.work(threats.enemyHQ, Bfs.PRIORITY_HIGH, 1000, numTowers != threats.enemyTowers.length); } numTowers = threats.enemyTowers.length; rc.yield(); } }
// This method will attempt to build in the given direction (or as close to it as possible) static boolean tryBuild(Direction d, RobotType type) { int offsetIndex = 0; int[] offsets = {0, 1, -1, 2, -2, 3, -3, 4}; int dirint = directionToInt(d); while (offsetIndex < 8) { int i = (dirint + offsets[offsetIndex] + 8) % 8; Direction build = directions[i]; MapLocation m = myLoc.add(build); if (rc.canBuild(build, type) && !wouldBlock(build) && !threats.isThreatened(m)) { try { rc.build(directions[i], type); strategy.addUnit(type); } catch (GameActionException e) { System.out.println("Build exception"); // e.printStackTrace(); } return true; } offsetIndex++; } return false; }
// HQ is responsible for collating unit counts and broadcasting them each turn // It also needs to pass on its supply each turn and fire if there are enemies in range private static void runHQ() { // double lastOre = 500; strategy = new BuildStrategy(rc); while (true) { threats.update(); strategy.broadcast(); // double oreIncome = rc.getTeamOre() - lastOre + strategy.oreSpent(); // System.out.println("Ore income " + oreIncome + " per miner = " + (oreIncome-5) / // (strategy.units(RobotType.MINER) + strategy.units(RobotType.BEAVER))); // See if we need to spawn a beaver if (rc.isCoreReady()) { RobotType build = strategy.getBuildOrder(); if (build != null) { trySpawn(rc.getLocation().directionTo(threats.enemyHQ), build); } } // Attack if there is an enemy in sight if (rc.isWeaponReady()) { int senseRange = RobotType.HQ.attackRadiusSquared; MapLocation[] myTowers = rc.senseTowerLocations(); if (myTowers.length >= 5) { senseRange = 52; // This is slightly larger than the real range but does include all possible // enemies that can be hit with splash attackRange = GameConstants.HQ_BUFFED_ATTACK_RADIUS_SQUARED; } else if (myTowers.length >= 2) { attackRange = GameConstants.HQ_BUFFED_ATTACK_RADIUS_SQUARED; } else { attackRange = senseRange; } RobotInfo[] enemies = rc.senseNearbyRobots(senseRange, enemyTeam); // Pick the first valid target MapLocation best = null; for (RobotInfo e : enemies) { int range = e.location.distanceSquaredTo(myLoc); if (range <= attackRange) { best = e.location; break; } if (myTowers.length >= 5) { // Check for tiles adjacent to the enemy as they might be in splash range Direction d = e.location.directionTo(myLoc); if (e.location.add(d).distanceSquaredTo(myLoc) <= attackRange) { best = e.location.add(d); break; } if (e.location.add(d.rotateLeft()).distanceSquaredTo(myLoc) <= attackRange) { best = e.location.add(d.rotateLeft()); break; } if (e.location.add(d.rotateRight()).distanceSquaredTo(myLoc) <= attackRange) { best = e.location.add(d.rotateRight()); break; } } } if (best != null) { try { rc.attackLocation(best); } catch (GameActionException e) { System.out.println("HQ attack exception"); // e.printStackTrace(); } } } doTransfer(); // lastOre = rc.getTeamOre(); rc.yield(); } }
private static void tryMove(Direction preferred, boolean ignoreThreat) { Direction[] options = null; int turn = Clock.getRoundNum(); if ((turn / 50) % 3 == 0) { // 1/3 of the time we prefer to move left Direction[] allMovesLeft = { preferred, preferred.rotateLeft(), preferred.rotateRight(), preferred.rotateLeft().rotateLeft(), preferred.rotateRight().rotateRight(), Direction.NONE, preferred.opposite().rotateRight(), preferred.opposite().rotateLeft(), preferred.opposite() }; options = allMovesLeft; } else if ((turn / 50) % 3 == 1) { // 1/3 of the time we prefer to move right Direction[] allMovesRight = { preferred, preferred.rotateRight(), preferred.rotateLeft(), preferred.rotateRight().rotateRight(), preferred.rotateLeft().rotateLeft(), Direction.NONE, preferred.opposite().rotateLeft(), preferred.opposite().rotateRight(), preferred.opposite() }; options = allMovesRight; } else { // 1/3 of the time we prefer to stay still if we can't move forward Direction[] allMovesForward = { preferred, preferred.rotateLeft(), preferred.rotateRight(), Direction.NONE, preferred.rotateLeft().rotateLeft(), preferred.rotateRight().rotateRight(), preferred.opposite().rotateRight(), preferred.opposite().rotateLeft(), preferred.opposite() }; options = allMovesForward; } // Scan through possible moves // If we find a valid move but it is a threatened tile we store it and continue // If we don't find a better move we use the stored one Direction retreat = null; for (Direction d : options) { boolean valid = (d == Direction.NONE || rc.canMove(d)); MapLocation dest = myLoc.add(d); if (valid) { // This is a valid move - check to see if it is safe if (ignoreThreat || !threats.isThreatened(dest)) { // Do this move if (d != Direction.NONE) try { // System.out.println("tryMove: preferred " + preferred + " got " + d); rc.move(d); } catch (GameActionException e) { System.out.println("Movement exception"); // e.printStackTrace(); } return; } else if (retreat == null) retreat = d; } } if (retreat != null && retreat != Direction.NONE) { try { rc.move(retreat); } catch (GameActionException e) { System.out.println("Movement exception"); // e.printStackTrace(); } } }
private static boolean inCombat(int multiplier) { return rc.senseNearbyRobots(senseRange * multiplier, enemyTeam).length > 0 || threats.isThreatened(myLoc); }
// If our tile is threatened we should retreat unless the enemy is quicker than us // If the enemy can advance and fire before we can move away we might as well stand and fight private static boolean shouldRetreat() { if (myType == RobotType.LAUNCHER && rc.getMissileCount() == 0) return true; return threats.isThreatened(myLoc) || threats.inMissileRange(); }