Пример #1
0
  private static void archonMicro(RobotController rc, RobotInfo enemyArchon)
      throws GameActionException {
    if (rc.isCoreReady()) {
      int dist = myLoc.distanceSquaredTo(enemyArchon.location);
      // When not adjacent to the archon, walk/mine through to him.
      if (dist > 2) {
        Direction desired = myLoc.directionTo(enemyArchon.location);
        Direction dir = Movement.getBestMoveableDirection(desired, rc, 2);
        if (dir != Direction.NONE) {
          rc.move(dir);
        } else if (shouldMine(rc, desired)) {
          rc.clearRubble(desired);
        } else if (shouldMine(rc, desired.rotateLeft())) {
          rc.clearRubble(desired.rotateLeft());
        } else if (shouldMine(rc, desired.rotateRight())) {
          rc.clearRubble(desired.rotateRight());
        }
      }
      // When adjacent to archon, rotate to the left/right when possible.
      else {
        Direction dir = myLoc.directionTo(enemyArchon.location);
        if (rc.canMove(dir.rotateLeft())) {
          rc.move(dir.rotateLeft());
        } else if (rc.canMove(dir.rotateRight())) {
          rc.move(dir.rotateRight());
        }
      }
    }

    if (rc.isWeaponReady()) {
      if (rc.canAttackLocation(enemyArchon.location)) {
        rc.attackLocation(enemyArchon.location);
      }
    }
  }
Пример #2
0
 private static void shootRandomly() throws GameActionException {
   if (rc.getRoundNum() > 500) {
     Direction trueAway = alpha.directionTo(here);
     Direction away = trueAway;
     MapLocation enemyLocation = here;
     int count = 0;
     while (count < 4 || rc.canAttackLocation(enemyLocation.add(away))) {
       enemyLocation = enemyLocation.add(away);
       away =
           (new Direction[] {
                 trueAway,
                 trueAway.rotateLeft(),
                 trueAway.rotateRight(),
                 trueAway.rotateLeft().rotateLeft(),
                 trueAway.rotateRight().rotateRight()
               })
               [rand.nextInt(5)];
       count++;
       if (rc.canSenseLocation(enemyLocation) && !rc.onTheMap(enemyLocation)) {
         return;
       }
     }
     if (rc.canAttackLocation(enemyLocation)) {
       rc.attackLocation(enemyLocation);
       return;
     }
   }
 }
Пример #3
0
  private MapLocation traceNext(MapLocation currentLoc, Direction faceDir, boolean cw) {

    // Put isTraversable first so that the second while loop will rotate the
    // direction to walkable position
    // Try code reuse in the future

    int step = 0;

    if (cw) {
      while (isTraversable(currentLoc.add(faceDir)) && step < 8) {
        faceDir = faceDir.rotateRight();
        step++;
      }
      step = 0;
      while (!isTraversable(currentLoc.add(faceDir)) && step < 8) {
        faceDir = faceDir.rotateLeft();
        step++;
      }
    } else {
      while (isTraversable(currentLoc.add(faceDir)) && step < 8) {
        faceDir = faceDir.rotateLeft();
        step++;
      }
      step = 0;
      while (!isTraversable(currentLoc.add(faceDir)) && step < 8) {
        faceDir = faceDir.rotateRight();
        step++;
      }
    }

    return currentLoc.add(faceDir);
  }
Пример #4
0
  public static void enemyMicro(RobotController rc, RobotInfo bestEnemy)
      throws GameActionException {
    // Prioritize movement
    Direction d = myLoc.directionTo(bestEnemy.location);
    if (rc.isCoreReady()) {
      if (rc.getHealth() > (numEnemySoldiers + 1) * RobotType.SOLDIER.attackPower) {
        // If the enemy can be killed but we're not in range, move forward
        if (!rc.canAttackLocation(bestEnemy.location)
            && bestEnemy.health <= RobotType.SOLDIER.attackPower) {
          if (rc.canMove(d)) {
            rc.move(d);
          } else if (rc.canMove(d.rotateLeft())) {
            rc.move(d.rotateLeft());
          } else if (rc.canMove(d.rotateRight())) {
            rc.move(d.rotateRight());
          }
          // If not in range, see if we should move in by comparing soldier health
        } else {
          double totalOurSoldierHealth = 0;
          RobotInfo[] allies = rc.senseNearbyRobots(bestEnemy.location, 18, rc.getTeam());
          for (RobotInfo ally : allies) {
            if (ally.type == RobotType.SOLDIER) {
              if (ally.health > numEnemySoldiers * RobotType.SOLDIER.attackPower) {
                totalOurSoldierHealth += ally.health;
              }
            }
          }
          // If we feel that we are strong enough, rush in.
          if (totalOurSoldierHealth > totalEnemySoldierHealth) {
            if (!rc.canAttackLocation(bestEnemy.location)) {
              if (rc.canMove(d)) {
                rc.move(d);
              } else if (rc.canMove(d.rotateLeft())) {
                rc.move(d.rotateLeft());
              } else if (rc.canMove(d.rotateRight())) {
                rc.move(d.rotateRight());
              }
            }
          } else if (4 * totalOurSoldierHealth < 3 * totalEnemySoldierHealth) {
            if (rc.canMove(d.opposite())) {
              rc.move(d.opposite());
            } else if (rc.canMove(d.opposite().rotateLeft())) {
              rc.move(d.opposite().rotateLeft());
            } else if (rc.canMove(d.opposite().rotateRight())) {
              rc.move(d.opposite().rotateRight());
            }
          }
        }
      }
    }

    // Attack whenever you can
    if (rc.isWeaponReady()) {
      if (rc.canAttackLocation(bestEnemy.location)) {
        broadcastingAttack(rc, bestEnemy);
      }
    }
  }
Пример #5
0
 public static Direction[] bestDir(Direction dir) {
   Direction[] bestDir = {
     dir,
     dir.rotateLeft(),
     dir.rotateRight(),
     dir.rotateLeft().rotateLeft(),
     dir.rotateRight().rotateRight()
   };
   return bestDir;
 }
Пример #6
0
  private static void runMissile() {
    int lastTurn = Clock.getRoundNum() + GameConstants.MISSILE_LIFESPAN;
    int[] damageRange = {0, 8, 15, 24, 35, 48};
    MapLocation target = null;
    boolean targetMoves = true;

    while (true) {
      myLoc = rc.getLocation();
      int turns = lastTurn - Clock.getRoundNum();

      if (targetMoves) { // Re-acquire the target's location
        RobotInfo[] inRange = rc.senseNearbyRobots(damageRange[turns], enemyTeam);
        if (inRange.length > 0) { // No units to target
          target = inRange[0].location;
          targetMoves = inRange[0].type.canMove();
          rc.setIndicatorString(0, "Missile targetting " + inRange[0].type + "@" + target);
        } else {
          targetMoves = false; // Pick a tower or the HQ
          MapLocation[] enemyTowers = rc.senseEnemyTowerLocations();
          for (MapLocation t : enemyTowers) {
            if (myLoc.distanceSquaredTo(t) <= damageRange[turns]) {
              target = t;
              rc.setIndicatorString(0, "Missile targetting Tower @" + target);
              break;
            }
          }
          if (target == null) {
            target = rc.senseEnemyHQLocation();
            rc.setIndicatorString(0, "Missile targetting HQ @" + target);
          }
        }
      }

      try {
        if (target != null) {
          if (myLoc.distanceSquaredTo(target) <= GameConstants.MISSILE_RADIUS_SQUARED) rc.explode();
          else {
            Direction d = myLoc.directionTo(target);
            if (rc.canMove(d)) rc.move(d);
            else if (rc.canMove(d.rotateLeft())) rc.move(d.rotateLeft());
            else if (rc.canMove(d.rotateRight())) rc.move(d.rotateRight());
          }
        }
      } catch (GameActionException e) {
        System.out.println("Missile exception");
        // e.printStackTrace();
      }
      rc.yield();
    }
  }
Пример #7
0
  // In this function the HQ spawns a soldier ideally toward the enemy base but in any direction
  // otherwise
  public static void SpawnSoldiers(RobotController rc) {
    try {
      if (rc.isActive() && rc.getType() == RobotType.HQ) {
        Direction toEnemy = rc.getLocation().directionTo(rc.senseEnemyHQLocation());
        if (rc.senseObjectAtLocation(rc.getLocation().add(toEnemy)) == null) {
        } else {
          for (int i = 0; i < 7; i++) {
            toEnemy = toEnemy.rotateLeft();

            if (rc.senseObjectAtLocation(rc.getLocation().add(toEnemy)) == null) {
              i = 47;
            } else if (i == 6) {
              toEnemy = Direction.NONE;
            }
          }
        }

        if (toEnemy != Direction.NONE) {
          if (rc.isActive()) {
            if (rc.getType() == RobotType.HQ) {
              rc.spawn(toEnemy);
            }
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
      System.out.println("Utility Exception");
    }
  }
Пример #8
0
  private void cautiouslyApproachVisibleEnemySoldier(MapLocation enemySoldier, int maxEnemyExposure)
      throws GameActionException {
    int[] numEnemiesAttackingDirs = countNumEnemiesAttackingMoveDirs();

    Direction toEnemy = here.directionTo(enemySoldier);
    Direction[] tryDirs = new Direction[] {toEnemy, toEnemy.rotateLeft(), toEnemy.rotateRight()};
    for (int i = 0; i < tryDirs.length; i++) {
      Direction tryDir = tryDirs[i];
      if (!rc.canMove(tryDir)) continue;
      if (numEnemiesAttackingDirs[tryDir.ordinal()] > maxEnemyExposure) continue;
      if (Util.inHQAttackRange(here.add(tryDir), theirHQ)) continue;
      Debug.indicate(
          "micro",
          1,
          String.format(
              "cautiously approaching enemy soldier; direction %d; attackers = %d %d %d %d %d %d %d %d",
              tryDir.ordinal(),
              numEnemiesAttackingDirs[0],
              numEnemiesAttackingDirs[1],
              numEnemiesAttackingDirs[2],
              numEnemiesAttackingDirs[3],
              numEnemiesAttackingDirs[4],
              numEnemiesAttackingDirs[5],
              numEnemiesAttackingDirs[6],
              numEnemiesAttackingDirs[7]));
      rc.move(tryDir);
      return;
    }
    Debug.indicate("micro", 1, "can't safely approach enemy soldier");
  }
Пример #9
0
  private boolean spawn() throws GameActionException {

    Direction dir = rc.getLocation().directionTo(rc.senseEnemyHQLocation());

    // Need to do this first so the termination check works
    if (rc.canMove(dir)) {
      rc.spawn(dir);
      return true;
    }
    // Spawn as close to the desired direction as possible
    Direction dirLeft = dir;
    Direction dirRight = dir;

    do {
      dirLeft = dirLeft.rotateLeft();
      if (rc.canMove(dirLeft)) {
        rc.spawn(dirLeft);
        return true;
      }

      dirRight = dirRight.rotateRight();
      if (rc.canMove(dirRight)) {
        rc.spawn(dirRight);
        return true;
      }

    } while (dirRight != dirLeft);

    return false;
  }
Пример #10
0
  private boolean isOpen(
      MapLocation currentLoc,
      Direction currentDir,
      Direction nextDir,
      Direction desDir,
      boolean cw) {
    if (desDir == Direction.OMNI) {
      return true;
    }

    if (!isTraversable(currentLoc.add(currentDir))) return false;

    if (cw) {
      while (currentDir != nextDir) {
        if (currentDir == desDir) return true;
        currentDir = currentDir.rotateRight();
      }
    } else {
      while (currentDir != nextDir) {
        if (currentDir == desDir) return true;
        currentDir = currentDir.rotateLeft();
      }
    }
    return (nextDir == desDir);
  }
Пример #11
0
 protected Direction directionTo(MapLocation source, MapLocation target)
     throws GameActionException {
   Direction dir = source.directionTo(target);
   if (rc.senseTerrainTile(source.add(dir)).ordinal() < 2) return dir;
   else {
     Direction candidateDir = dir.rotateLeft();
     if (isGood(source.add(candidateDir))) {
       return candidateDir;
     }
     candidateDir = dir.rotateLeft();
     if (isGood(source.add(candidateDir))) {
       return candidateDir;
     }
     return null;
   }
 }
Пример #12
0
  /*
   * 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();
      }
    }
  }
Пример #13
0
  public Direction Bug(MapLocation s, MapLocation t, int tolerance) {

    // arrive the destination
    if (s.distanceSquaredTo(t) <= tolerance) {
      reset();
      return Direction.OMNI;
    }

    Direction nextDir;
    Direction faceDir = controllers.myRC.getDirection();

    // if target is not traversable, back-tracing the destination
    while (!isTraversable(t)) {
      nextDir = s.directionTo(t);
      t = t.subtract(nextDir);

      // beside the source
      if (s.distanceSquaredTo(t) <= tolerance) {
        reset();
        return Direction.OMNI;
      }
    }

    modifiedDes = t;

    Direction desDir = s.directionTo(t);
    MapLocation nextLoc;

    if (isTracing) {

      Direction startTracingDir =
          isCW ? faceDir.rotateRight().rotateRight() : faceDir.rotateLeft().rotateLeft();
      nextLoc = traceNext(s, startTracingDir, isCW);
      nextDir = s.directionTo(nextLoc);

      // The way is open
      if (isOpen(s, faceDir, nextDir, desDir, isCW) && isTraversable(s.add(desDir))) {
        isTracing = false;
        return desDir;
      }

      return nextDir;

    } else {
      if (isTraversable(s.add(desDir))) {
        return desDir;
      } else {
        isTracing = true;
        isCW = betterTracingWay(s, t);
        nextLoc = traceNext(s, desDir, isCW);

        return s.directionTo(nextLoc);
      }
    }
  }
Пример #14
0
  protected boolean trySafeMove(
      Direction direction, RobotInfo[] nearbyEnemies, RobotInfo[] nearbyZombies)
      throws GameActionException {
    MapLocation currentLocation = rc.getLocation();
    MapLocation next = currentLocation.add(direction);
    if (canMoveSafely(direction, next, nearbyEnemies, nearbyZombies)) {
      rc.move(direction);
      return true;
    }

    Direction left = direction.rotateLeft();
    next = currentLocation.add(left);
    if (canMoveSafely(left, next, nearbyEnemies, nearbyZombies)) {
      rc.move(left);
      return true;
    }

    Direction right = direction.rotateRight();
    next = currentLocation.add(right);
    if (canMoveSafely(right, next, nearbyEnemies, nearbyZombies)) {
      rc.move(right);
      return true;
    }

    for (int i = 0; i < 2; i++) {
      left = left.rotateLeft();
      next = currentLocation.add(left);
      if (canMoveSafely(left, next, nearbyEnemies, nearbyZombies)) {
        rc.move(left);
        return true;
      }

      right = right.rotateRight();
      next = currentLocation.add(right);
      if (canMoveSafely(right, next, nearbyEnemies, nearbyZombies)) {
        rc.move(right);
        return true;
      }
    }

    return false;
  }
Пример #15
0
  private Direction detour(Direction faceDir, boolean cw) {

    if (cw) {
      while (controllers.motor.canMove(faceDir)) {
        faceDir = faceDir.rotateRight();
      }
      while (!controllers.motor.canMove(faceDir)) {
        faceDir = faceDir.rotateLeft();
      }
    } else {
      while (controllers.motor.canMove(faceDir)) {
        faceDir = faceDir.rotateLeft();
      }
      while (!controllers.motor.canMove(faceDir)) {
        faceDir = faceDir.rotateRight();
      }
    }

    return faceDir;
  }
Пример #16
0
  public static boolean turnNuke(RobotController rc) {
    boolean nuke = false;

    GameObject[] nearByEnemies =
        rc.senseNearbyGameObjects(Robot.class, 35, rc.getTeam().opponent());
    GameObject[] nearByFriends;

    if (nearByEnemies.length == 0) {

    } else {
      MapLocation[] nearBySpots = new MapLocation[8];

      Direction dir = rc.getLocation().directionTo(rc.senseHQLocation());

      for (int i = 0; i < nearBySpots.length; i++) {
        nearBySpots[i] = rc.getLocation().add(dir);
        dir.rotateLeft();
      }

      int[] damage = new int[8];

      for (int i = 0; i < damage.length; i++) {
        nearByEnemies =
            rc.senseNearbyGameObjects(Robot.class, nearBySpots[i], 2, rc.getTeam().opponent());
        nearByFriends = rc.senseNearbyGameObjects(Robot.class, nearBySpots[i], 2, rc.getTeam());

        int total = nearByEnemies.length - nearByFriends.length;
        damage[i] = total;
      }

      int largest = damage[0];
      int index = 0;

      for (int k = 1; k < damage.length; k++) {
        if (largest < damage[k]) {
          largest = damage[k];
          index = k;
        }
      }

      if (largest > 1) {
        // Nuke nuker = new Nuke(rc, nearBySpots[index]);
        // nuker.run();
        return true;
      } else {
        return false;
      }
    }
    return nuke;
  }
Пример #17
0
  /**
   * Try to move.
   *
   * @param sneak:
   * @return
   */
  public void execute(int sneak) {
    // int bc = Clock.getBytecodesLeft();
    // RC.setIndicatorString(1, "my x = " + Integer.toString(RC.getLocation().x) + ", my y = " +
    // Integer.toString(RC.getLocation().y)
    // + "x = " + Integer.toString(dest.x) + ", y = " + Integer.toString(dest.y));
    // RC.setIndicatorString(2, Clock.getRoundNum() + " | dest = " + dest + ", navtype = " +
    // navType);

    if (arrived()) return;

    if (RC.isActive()) {
      Direction d;
      d = navAlg.getNextDir();
      if (d != null && d != Direction.NONE && d != Direction.OMNI) {
        if (RC.canMove(d)) {
          try {
            switch (sneak) {
              case SNEAK:
                // RC.setIndicatorString(2, dest.x + ", " + dest.y + ": sneak");
                RC.sneak(d);
                break;
              case RUN:
                // RC.setIndicatorString(2, dest.x + ", " + dest.y + ": run");
                RC.move(d);
                break;
              case PUSH_HOME:
                // RC.setIndicatorString(2, dest.x + ", " + dest.y + ": push_home");
                Direction awayFromHome = currentLocation.directionTo(ALLY_HQ).opposite();
                if (d == awayFromHome
                    || d == awayFromHome.rotateLeft()
                    || d == awayFromHome.rotateRight()) {
                  RC.sneak(d);
                } else {
                  RC.move(d);
                }
                break;
              default:
                break;
            }
          } catch (GameActionException e) {
            e.printStackTrace();
          }
        } else if (currentLocation.distanceSquaredTo(dest) <= 2) {
          setTarget(currentLocation);
        }
      }
    }
    // System.out.println("Bytecodes used by Mover.execute() = " +
    // Integer.toString(bc-Clock.getBytecodesLeft()));
  }
Пример #18
0
  /**
   * Checks if rc can move in direction dir (runs isCoreReady and canMove). If so, moves. If not,
   * moves rc in any of the four directions nearest dir, if possible.
   *
   * @param rc
   * @param dir
   * @return true if rc moves else false
   * @throws GameActionException
   */
  private static void moveTowards(RobotController rc, Direction dir) throws GameActionException {
    if (rc.isCoreReady() && !dir.equals(Direction.OMNI) && !dir.equals(Direction.NONE)) {
      Direction[] moveRight = {
        dir,
        dir.rotateRight(),
        dir.rotateLeft(),
        dir.rotateRight().rotateRight(),
        dir.rotateLeft().rotateLeft()
      };
      Direction[] moveLeft = {
        dir,
        dir.rotateLeft(),
        dir.rotateRight(),
        dir.rotateLeft().rotateLeft(),
        dir.rotateRight().rotateRight()
      };
      Direction[] nearDirections =
          Math.random() >= .5
              ? moveRight
              : moveLeft; // 50% chance robot tries to move to right first

      for (Direction nearDir : nearDirections) {
        if (rc.canMove(nearDir) && rc.isCoreReady()) {
          rc.move(nearDir);
        }
      }
      if (rc.getType() != RobotType.TTM
          && rc.getType() != RobotType.TTM) // these types can't clear rubble
      {
        if (rc.isCoreReady()
            && rc.onTheMap(rc.getLocation().add(dir))
            && rc.senseRubble(rc.getLocation().add(dir)) > RUBBLE_LOWER_CLEAR_THRESHOLD) {
          clearRubble(rc);
        }
      }
    }
  }
Пример #19
0
 /**
  * @param desiredDir
  * @param otherDir
  * @return Integer.MAX_VALUE if otherDir can't be rotated to desiredDir or... TODO
  */
 private static double distanceFromDirection(Direction desiredDir, Direction otherDir) {
   double[] weights = {0, 3, 8, 15, 25};
   //		double[] weights = {0.75, 0.8, .85, .9, .95};
   //		double[] weights = {1, 1.0001, 1.0002, 1.0003, 1.0004};
   Direction leftRotation = otherDir;
   Direction rightRotation = otherDir;
   for (int i = 0; i <= 4; i++) {
     if (desiredDir.equals(leftRotation) || desiredDir.equals(rightRotation)) {
       return weights[i];
     }
     leftRotation = leftRotation.rotateLeft();
     rightRotation = rightRotation.rotateRight();
   }
   return Integer.MAX_VALUE;
 }
Пример #20
0
  protected void tryMove(Direction direction) throws GameActionException {
    if (rc.canMove(direction)) {
      rc.move(direction);
      return;
    }

    Direction left = direction.rotateLeft();
    if (rc.canMove(left)) {
      rc.move(left);
      return;
    }

    Direction right = direction.rotateRight();
    if (rc.canMove(right)) {
      rc.move(right);
      return;
    }

    for (int i = 0; i < 2; i++) {
      left = left.rotateLeft();
      if (rc.canMove(left)) {
        rc.move(left);
        return;
      }

      right = right.rotateRight();
      if (rc.canMove(right)) {
        rc.move(right);
        return;
      }
    }

    if (rc.getType() != RobotType.TTM) {
      tryClearRubble(direction);
    }
  }
Пример #21
0
 private static boolean isBlockingSomeone(RobotController rc, MapLocation target)
     throws GameActionException {
   Direction dir = myLoc.directionTo(target);
   MapLocation behind = myLoc.add(dir.opposite());
   MapLocation left = behind.add(dir.rotateLeft());
   MapLocation right = behind.add(dir.rotateRight());
   // There is someone behind us
   if (rc.senseRobotAtLocation(behind) != null) {
     // If there is stuff blocking on both sides, then blocking
     if (!rc.canMove(myLoc.directionTo(left)) && !rc.canMove(myLoc.directionTo(right))) {
       return true;
     }
   }
   return false;
 }
Пример #22
0
 /**
  * @param rc
  * @param dirToCorner
  * @return the location of the corner in the given direction or LOCATION_NONE if it is not a
  *     corner
  * @throws GameActionException
  */
 private static MapLocation checkForCorner(RobotController rc, Direction dirToCorner)
     throws GameActionException {
   int senseRadiusMinusOneSquared =
       (int) Math.pow(Math.sqrt(rc.getType().sensorRadiusSquared) - 1, 2);
   // so that when you add one below to check for a corner, you can still sense the +1 location
   MapLocation[] nearby =
       MapLocation.getAllMapLocationsWithinRadiusSq(rc.getLocation(), senseRadiusMinusOneSquared);
   boolean isCorner = true;
   MapLocation corner = getFurthestInDirection(rc, nearby, dirToCorner);
   Direction[] nearDirections = {dirToCorner, dirToCorner.rotateLeft(), dirToCorner.rotateRight()};
   for (Direction dir : nearDirections) {
     if (rc.onTheMap(corner.add(dir))) {
       isCorner = false;
     }
   }
   return isCorner ? corner : LOCATION_NONE;
 }
Пример #23
0
  protected void goTo(Direction direction) throws GameActionException {
    Direction destinationDirection = direction;
    Direction currentDirection = destinationDirection;

    while (!myRC.canMove(currentDirection)
        && !currentDirection.equals(destinationDirection.rotateLeft())) {
      currentDirection = currentDirection.rotateRight();
    }

    if (myRC.canMove(currentDirection)) {
      if (!myRC.getDirection().equals(currentDirection)) {
        myRC.setDirection(currentDirection);
      } else {
        myRC.moveForward();
      }
    }
  }
Пример #24
0
 /**
  * If robotType is null, compute where to move. Else compute where to build.
  *
  * @param rc
  * @param dir
  * @param robotType
  * @return Direction to move/build in
  */
 static Direction findPathDirection(RobotController rc, Direction dir, RobotType robotType) {
   final int maxRotations = 8;
   int diff = rand.nextInt(2);
   for (int i = 0; i <= maxRotations; ++i) {
     if (i == maxRotations) return Direction.NONE;
     if ((i + diff) % 2 == 0) {
       for (int j = 0; j < i; ++j) dir = dir.rotateLeft();
     } else {
       for (int j = 0; j < i; ++j) dir = dir.rotateRight();
     }
     if (robotType == null) {
       if (rc.canMove(dir)) break;
     } else {
       if (rc.canBuild(dir, robotType)) break;
     }
   }
   return dir;
 }
Пример #25
0
 private static MapLocation getFurthestInDirection(
     RobotController rc, MapLocation[] locs, Direction dir) throws GameActionException {
   final MapLocation myLocation = rc.getLocation();
   MapLocation furthest = myLocation.add(dir);
   int furthestDist = myLocation.distanceSquaredTo(furthest);
   List<Direction> directionsTowards = Arrays.asList(dir, dir.rotateLeft(), dir.rotateRight());
   for (MapLocation loc : locs) {
     if (directionsTowards.contains(myLocation.directionTo(loc))) {
       if (rc.onTheMap(loc)) {
         int dist = myLocation.distanceSquaredTo(loc);
         if (dist > furthestDist) {
           furthestDist = dist;
           furthest = loc;
         }
       }
     }
   }
   return furthest;
 }
Пример #26
0
  public Direction getNextDir(int tolerance) {

    if (controllers.myRC.getLocation().equals(previousRobLoc)) {
      if (controllers.motor.canMove(previousDir)) {
        //				controllers.myRC.setIndicatorString(1, "precomputed");
        return previousDir;
      }
      //			else if (!controllers.motor.isActive() &&
      // controllers.motor.canMove(previousDir.rotateRight())) {
      //				isTracing = false;
      //				previousDir = previousDir.rotateRight();
      //				controllers.myRC.setIndicatorString(1, "yield");
      //				return previousDir;
      //			}
      else {
        //				controllers.myRC.setIndicatorString(1, "detour " + isCW);
        if (!isTracing) {
          previousDir = detour(controllers.myRC.getDirection(), isCW);
        } else {
          Direction faceDir = controllers.myRC.getDirection();
          Direction startTracingDir =
              isCW ? faceDir.rotateRight().rotateRight() : faceDir.rotateLeft().rotateLeft();
          previousDir = detour(startTracingDir, isCW);
        }
      }
      return previousDir;

    } else {
      //			controllers.myRC.setIndicatorString(1, "bugging");
      previousRobLoc = controllers.myRC.getLocation();

      if (destination == null) {
        reset();
        previousDir = Direction.OMNI;
        return Direction.OMNI;
      } else {
        previousDir = Bug(controllers.myRC.getLocation(), modifiedDes, tolerance);
        return previousDir;
      }
    }
  }
Пример #27
0
  /*
   * 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();
    }
  }
Пример #28
0
 private static void moveToLocFartherThanAlphaIfPossible() throws GameActionException {
   Direction dir = here.directionTo(center);
   boolean shouldMove = false;
   Direction bestDir = dir;
   int bestScore = 0;
   int distanceToAlpha = here.distanceSquaredTo(alpha);
   boolean startedAsTTM = isTTM;
   RobotInfo[] enemyRobots =
       rc.senseHostileRobots(rc.getLocation(), RobotType.TURRET.sensorRadiusSquared);
   NavSafetyPolicy theSafety = new SafetyPolicyAvoidAllUnits(enemyRobots);
   for (int i = 0; i < 8; i++) {
     MapLocation newLoc = here.add(dir);
     if (rc.onTheMap(newLoc)
         && !rc.isLocationOccupied(newLoc)
         && rc.senseRubble(newLoc) < GameConstants.RUBBLE_OBSTRUCTION_THRESH) {
       int newDistanceToAlpha = newLoc.distanceSquaredTo(alpha);
       if (newDistanceToAlpha > distanceToAlpha
           && newDistanceToAlpha <= range
           && theSafety.isSafeToMoveTo(newLoc)) {
         if (newDistanceToAlpha > bestScore) bestDir = dir;
         bestScore = newDistanceToAlpha;
         shouldMove = true;
       }
     }
     dir = dir.rotateLeft();
   }
   if (shouldMove) {
     if (!isTTM) {
       rc.pack();
       isTTM = true;
     } else {
       rc.move(bestDir);
     }
   } else if (startedAsTTM) {
     rc.unpack();
     isTTM = false;
   }
 }
Пример #29
0
  public static void run(RobotController rc) {
    Random rand = new Random(rc.getID());
    Team myTeam = rc.getTeam();
    Team enemyTeam = myTeam.opponent();
    int numFriendly = 0;
    RobotInfo[] adjNeutralRobots = rc.senseNearbyRobots(2, Team.NEUTRAL);
    // if useTurrets = true, then use turret strategy
    boolean useTurrets = false;

    try {
      // Any code here gets executed exactly once at the beginning of the game.
      RobotInfo[] nearbyArchons =
          rc.senseNearbyRobots(RobotType.ARCHON.sensorRadiusSquared, rc.getTeam());
      if (nearbyArchons.length >= 2) {
        useTurrets = true;
      }
      // rc.setIndicatorString(1, "newString");
    } catch (Exception e) {
      // Throwing an uncaught exception makes the robot die, so we need to catch exceptions.
      // Caught exceptions will result in a bytecode penalty.
      System.out.println(e.getMessage());
      e.printStackTrace();
    }

    while (true) {
      // This is a loop to prevent the run() method from returning. Because of the Clock.yield()
      // at the end of it, the loop will iterate once per game round.
      try {
        if (useTurrets) {
          boolean escape = false;
          //					if (rc.isCoreReady()) {
          //						int numAdjTurrets = 0;
          //						for (RobotInfo f : friendlyAdjacent) {
          //							if (f.type == RobotType.TURRET) {
          //								numAdjTurrets++;
          //							}
          //						}
          //						if (numAdjTurrets < 3) {
          //							escape = Movement.moveAwayFromEnemy(rc);
          //						}
          //					}
          //					if (rc.isCoreReady()) {
          //						escape = Movement.moveAwayFromEnemy(rc);
          //					}
          if (!escape) {
            if (adjNeutralRobots.length > 0) {
              // if there is a neutral robot adjacent, activate it or wait until there's no core
              // delay
              if (rc.isCoreReady()) {
                rc.activate(adjNeutralRobots[0].location);
              }
            }
            // careful- moving to parts might get into enemy turret range
            if (Movement.getToAdjParts(rc)) {
            } else {
              boolean toheal = false;
              // repair a nearby friendly robot
              if (rc.isWeaponReady()) {
                RobotInfo[] friendlyWithinRange = rc.senseNearbyRobots(24, myTeam);
                numFriendly = friendlyWithinRange.length;
                if (friendlyWithinRange.length > 0) {
                  RobotInfo toRepair = friendlyWithinRange[0];
                  for (RobotInfo r : friendlyWithinRange) {
                    if ((r.health < toRepair.health)
                        && (r.type != RobotType.ARCHON)
                        && (r.maxHealth - r.health > 1)) {
                      toRepair = r;
                    }
                  }
                  if ((toRepair.maxHealth - toRepair.health > 1)
                      && (toRepair.type != RobotType.ARCHON)) {
                    toheal = true;
                    rc.repair(toRepair.location);
                  }
                }
              }
              if (toheal == false && rc.isCoreReady()) {
                // did not heal any robots

                // sense all the hostile robots within the archon's radius
                MapLocation myLoc = rc.getLocation();
                RobotInfo[] hostileWithinRange =
                    rc.senseHostileRobots(myLoc, RobotType.ARCHON.sensorRadiusSquared);
                RobotInfo closestRobot = null;
                int closestDistance = 0;
                // get the furthest robot from the scout
                for (RobotInfo r : hostileWithinRange) {
                  if (r.location.distanceSquaredTo(myLoc) > closestDistance) {
                    closestRobot = r;
                    closestDistance = r.location.distanceSquaredTo(myLoc);
                  }
                }
                // if there is such an enemy, signal it to range 8
                if (closestRobot != null) {
                  try {
                    // this signaling is only effective against non turret enemies
                    rc.broadcastMessageSignal(closestRobot.location.x, closestRobot.location.y, 8);
                  } catch (GameActionException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                  }
                }

                int turnNum = rc.getRoundNum();
                int numVeryCloseScouts = 0;
                int numNearbyTurrets = 0;
                RobotInfo[] friendlyNearby =
                    rc.senseNearbyRobots(RobotType.ARCHON.sensorRadiusSquared, myTeam);
                for (RobotInfo f : friendlyNearby) {
                  if (f.type == RobotType.TURRET) {
                    numNearbyTurrets++;
                  }
                }
                // for sensing if there are guards within range 24
                RobotInfo[] friendlyClose = rc.senseNearbyRobots(24, myTeam);
                int numNearbyGuards = 0;
                for (RobotInfo f : friendlyClose) {
                  if (f.type == RobotType.GUARD) {
                    numNearbyGuards++;
                  }
                }
                // check for scouts; how close should they be????
                RobotInfo[] friendlyVeryClose = rc.senseNearbyRobots(15, myTeam);
                for (RobotInfo f : friendlyClose) {
                  if (f.type == RobotType.SCOUT) {
                    numVeryCloseScouts++;
                  }
                }
                if (rc.hasBuildRequirements(RobotType.GUARD)
                    && rc.isCoreReady()
                    && numNearbyGuards < 1) {
                  Direction dirToBuild = RobotPlayer.directions[rand.nextInt(8)];
                  for (int i = 0; i < 8; i++) {
                    // If possible, build in this direction
                    if (rc.canBuild(dirToBuild, RobotType.GUARD)) {
                      rc.build(dirToBuild, RobotType.GUARD);
                      break;
                    } else {
                      // Rotate the direction to try
                      dirToBuild = dirToBuild.rotateLeft();
                    }
                  }
                }
                // if there are <1 turrets next to archon, build asap
                if (rc.hasBuildRequirements(RobotType.TURRET)
                    && rc.isCoreReady()
                    && numNearbyTurrets < 1) {
                  Direction dirToBuild = RobotPlayer.directions[rand.nextInt(4) * 2];
                  for (int i = 0; i < 4; i++) {
                    // If possible, build in this direction
                    if (rc.canBuild(dirToBuild, RobotType.TURRET)) {
                      rc.build(dirToBuild, RobotType.TURRET);
                      turretCount++;
                      break;
                    } else {
                      // Rotate the direction to try
                      dirToBuild = dirToBuild.rotateLeft();
                      dirToBuild = dirToBuild.rotateLeft();
                    }
                  }
                }
                // if there are <1 scout next to archon and 1 turret, build scout asap
                if (rc.hasBuildRequirements(RobotType.SCOUT)
                    && rc.isCoreReady()
                    && numNearbyTurrets > 0
                    && numVeryCloseScouts == 0
                    && turnNum < 400) {
                  Direction dirToBuild = RobotPlayer.directions[rand.nextInt(8)];
                  for (int i = 0; i < 8; i++) {
                    // If possible, build in this direction
                    if (rc.canBuild(dirToBuild, RobotType.SCOUT)) {
                      rc.build(dirToBuild, RobotType.SCOUT);
                      scoutCount++;
                      break;
                    } else {
                      // Rotate the direction to try
                      dirToBuild = dirToBuild.rotateLeft();
                    }
                  }
                }
                // build turret every 100 turns until turn 400
                //								if (turnNum > 1 && turnNum < 400) {
                //									if (turnNum % 100 == 85 && rc.isCoreReady()) {
                //										Direction dirToBuild = RobotPlayer.directions[rand.nextInt(4)*2];
                //										for (int i = 0; i < 4; i++) {
                //											// If possible, build in this direction
                //											if (rc.canBuild(dirToBuild, RobotType.TURRET)) {
                //												rc.build(dirToBuild, RobotType.TURRET);
                //												turretCount++;
                //												break;
                //											} else {
                //												// Rotate the direction to try
                //												dirToBuild = dirToBuild.rotateLeft();
                //												dirToBuild = dirToBuild.rotateLeft();
                //											}
                //										}
                //									}
                //								}
                else {
                  // Check if this ARCHON's core is ready
                  if (rc.isCoreReady()) {
                    boolean built = false;
                    RobotType typeToBuild = RobotType.TURRET;
                    if (scoutCount < turretCount / 5) {
                      typeToBuild = RobotType.SCOUT;
                    }
                    // never build scouts after a certain turn
                    if (turnNum < 1500) {
                      typeToBuild = RobotType.TURRET;
                    }
                    // Check for sufficient parts
                    if (rc.hasBuildRequirements(typeToBuild)) {
                      // Choose a random direction to try to build in; NESW for turrets; all 8 for
                      // scouts
                      if (typeToBuild.equals(RobotType.TURRET)) {
                        Direction dirToBuild = RobotPlayer.directions[rand.nextInt(4) * 2];
                        for (int i = 0; i < 4; i++) {
                          // If possible, build in this direction
                          if (rc.canBuild(dirToBuild, RobotType.TURRET)) {
                            rc.build(dirToBuild, RobotType.TURRET);
                            turretCount++;
                            break;
                          } else {
                            // Rotate the direction to try
                            dirToBuild = dirToBuild.rotateLeft();
                            dirToBuild = dirToBuild.rotateLeft();
                          }
                        }
                      } else {
                        Direction dirToBuild = RobotPlayer.directions[rand.nextInt(8)];
                        for (int i = 0; i < 8; i++) {
                          // If possible, build in this direction
                          if (rc.canBuild(dirToBuild, RobotType.SCOUT)) {
                            rc.build(dirToBuild, RobotType.SCOUT);
                            scoutCount++;
                            break;
                          } else {
                            // Rotate the direction to try
                            dirToBuild = dirToBuild.rotateLeft();
                          }
                        }
                      }
                    }
                    // only move around if there are resources
                    if ((!built)
                        && rc.hasBuildRequirements(RobotType.TURRET)
                        && (rc.isCoreReady())) {
                      // don't move into enemy turret range if scout sends signal about it
                      Set<Direction> dangerousDirs = new HashSet<>();
                      Signal currentSignal = rc.readSignal();
                      while (currentSignal != null) {
                        int messageX = currentSignal.getMessage()[0];
                        int messageY = currentSignal.getMessage()[1];
                        // if signal message > 80000, then the message is signaling a turret
                        // location
                        if (messageX > 80000) {
                          messageX = messageX - 100000;
                          messageY = messageY - 100000;
                          MapLocation enemyTurretLoc = new MapLocation(messageX, messageY);
                          Direction dirToEnemyTurret = myLoc.directionTo(enemyTurretLoc);
                          Direction dirToEnemyTurretL =
                              myLoc.directionTo(enemyTurretLoc).rotateLeft();
                          Direction dirToEnemyTurretR =
                              myLoc.directionTo(enemyTurretLoc).rotateRight();
                          if (myLoc.add(dirToEnemyTurret).distanceSquaredTo(enemyTurretLoc) <= 48) {
                            dangerousDirs.add(dirToEnemyTurret);
                          }
                          if (myLoc.add(dirToEnemyTurretL).distanceSquaredTo(enemyTurretLoc)
                              <= 48) {
                            dangerousDirs.add(dirToEnemyTurretL);
                          }
                          if (myLoc.add(dirToEnemyTurretR).distanceSquaredTo(enemyTurretLoc)
                              <= 48) {
                            dangerousDirs.add(dirToEnemyTurretR);
                          }
                        }
                        currentSignal = rc.readSignal();
                      }

                      Direction dirToMove = RobotPlayer.directions[(rand.nextInt(4) * 2) + 1];
                      for (int i = 0; i < 4; i++) {
                        if (rc.canMove(dirToMove) && !dangerousDirs.contains(dirToMove)) {
                          rc.move(dirToMove);
                          break;
                        } else {
                          dirToMove = dirToMove.rotateLeft();
                          dirToMove = dirToMove.rotateLeft();
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        } else { // use soldiers
          boolean escape = false;
          if (rc.isCoreReady()) {
            escape = Movement.moveAwayFromEnemy(rc);
          }
          if (!escape) {
            if (adjNeutralRobots.length > 0) {
              // if there is a neutral robot adjacent, activate it or wait until there's no core
              // delay
              if (rc.isCoreReady()) {
                rc.activate(adjNeutralRobots[0].location);
              }
            }
            if (Movement.getToAdjParts(rc)) {
            } else {
              boolean toheal = false;
              // repair a nearby friendly robot
              if (rc.isWeaponReady()) {
                RobotInfo[] friendlyWithinRange = rc.senseNearbyRobots(24, myTeam);
                numFriendly = friendlyWithinRange.length;
                if (friendlyWithinRange.length > 0) {
                  RobotInfo toRepair = friendlyWithinRange[0];
                  for (RobotInfo r : friendlyWithinRange) {
                    if ((r.health < toRepair.health)
                        && (r.type != RobotType.ARCHON)
                        && (r.maxHealth - r.health > 1)) {
                      toRepair = r;
                    }
                  }
                  if ((toRepair.maxHealth - toRepair.health > 1)
                      && (toRepair.type != RobotType.ARCHON)) {
                    toheal = true;
                    rc.repair(toRepair.location);
                  }
                }
              }
              if (toheal == false) {
                // for sensing if there are guards within range 24
                RobotInfo[] friendlyClose = rc.senseNearbyRobots(24, myTeam);
                int numNearbyGuards = 0;
                for (RobotInfo f : friendlyClose) {
                  if (f.type == RobotType.GUARD) {
                    numNearbyGuards++;
                  }
                }

                boolean built = false;
                int turnNum = rc.getRoundNum();
                if (rc.hasBuildRequirements(RobotType.SCOUT)
                    && rc.isCoreReady()
                    && turnNum > 1
                    && turnNum % 150 >= 0
                    && turnNum % 150 <= 19
                    && turnNum < 900) {
                  Direction dirToBuild = RobotPlayer.directions[rand.nextInt(8)];
                  for (int i = 0; i < 8; i++) {
                    // If possible, build in this direction
                    if (rc.canBuild(dirToBuild, RobotType.SCOUT)) {
                      rc.build(dirToBuild, RobotType.SCOUT);
                      built = true;
                      break;
                    } else {
                      // Rotate the direction to try
                      dirToBuild = dirToBuild.rotateLeft();
                    }
                  }
                }
                if (rc.hasBuildRequirements(RobotType.GUARD)
                    && rc.isCoreReady()
                    && !built
                    && numNearbyGuards < 1) {
                  Direction dirToBuild = RobotPlayer.directions[rand.nextInt(8)];
                  for (int i = 0; i < 8; i++) {
                    // If possible, build in this direction
                    if (rc.canBuild(dirToBuild, RobotType.GUARD)) {
                      rc.build(dirToBuild, RobotType.GUARD);
                      built = true;
                      break;
                    } else {
                      // Rotate the direction to try
                      dirToBuild = dirToBuild.rotateLeft();
                    }
                  }
                }
                if (rc.hasBuildRequirements(RobotType.SOLDIER) && rc.isCoreReady() && !built) {
                  Direction dirToBuild = RobotPlayer.directions[rand.nextInt(8)];
                  for (int i = 0; i < 8; i++) {
                    // If possible, build in this direction
                    if (rc.canBuild(dirToBuild, RobotType.SOLDIER)) {
                      rc.build(dirToBuild, RobotType.SOLDIER);
                      built = true;
                      break;
                    } else {
                      // Rotate the direction to try
                      dirToBuild = dirToBuild.rotateLeft();
                    }
                  }
                }
                // if archon has nothing to do, tell soldiers to come to it's location
                /*if (rc.getRoundNum() > 500 && rc.isCoreReady() && rc.isWeaponReady()) {
                	rc.broadcastMessageSignal(-100, 0, 70 * 70);
                }*/
              }
            }
          }
        }
        Clock.yield();
      } catch (Exception e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
      }
    }
  }
Пример #30
0
  public SearchNode bugSearch(MapLocation start, MapLocation target) throws GameActionException {
    MapLocation s = start, t = target;
    int closest = s.distanceSquaredTo(t);
    int closestL = closest, closestR = closest;
    SearchNode current = new SearchNode(start, 1, null, true),
        currentL = new SearchNode(start, 1, null, true),
        currentR = new SearchNode(start, 1, null, true);
    boolean isTracingL = false, isTracingR = false;
    Direction curDir = current.loc.directionTo(t);
    Direction curDirL = curDir, curDirR = curDir;

    if (debug) System.out.println("Source: " + s + "; Target: " + t);
    while (!(current.loc.x == t.x && current.loc.y == t.y)
        && !(currentL.loc.x == t.x && currentL.loc.y == t.y)
        && !(currentR.loc.x == t.x && currentR.loc.y == t.y)) {
      if (debug)
        System.out.println(
            "Current: " + current.loc + ";Right " + currentR.loc + ";Left " + currentL.loc);

      if (!isTracingL || !isTracingR) {
        // we're done tracing
        if (isTracingL) {
          // the right bug finished first
          isTracingL = false;
          current = currentR;
          closest = closestR;
        } else if (isTracingR) {
          // the left bug finished first
          isTracingR = false;
          current = currentL;
          closest = closestL;
        }
        curDir = directionTo(current.loc, t);
        if (curDir != null) {
          current = current.update(curDir);
        } else {
          current.isPivot = true;
          closest = current.loc.distanceSquaredTo(t);
          closestL = closest;
          closestR = closest;
          isTracingL = true;
          isTracingR = true;
          curDir = current.loc.directionTo(t);
          curDirL = curDir;
          curDirR = curDir;

          while (!isGood(current.loc.add(curDirL))) {
            curDirL = curDirL.rotateRight();
          }
          while (!isGood(current.loc.add(curDirR))) {
            curDirR = curDirR.rotateLeft();
          }
          currentL = current.update(curDirL);
          currentR = current.update(curDirR);
          if (currentL.loc.distanceSquaredTo(t) < closestL)
            closestL = currentL.loc.distanceSquaredTo(t);
          if (currentR.loc.distanceSquaredTo(t) < closestR)
            closestR = currentR.loc.distanceSquaredTo(t);
        }
      } else { // we're tracing
        if (currentL.loc.distanceSquaredTo(t) < currentR.loc.distanceSquaredTo(t)) {
          if (debug) System.out.println("LEFT TRACE");
          // the left trace is closer
          curDirL = directionTo(currentL.loc, t);
          if (curDirL != null && currentL.loc.add(curDirL).distanceSquaredTo(t) < closestL) {
            if (debug) System.out.print("FINISH LEFT TRACE. GOING " + curDirL);
            isTracingL = false;
            currentL.isPivot = true;
            if (debug) System.out.println("LEFT PIVOT");
            currentL = currentL.update(curDirL);
            if (currentL.loc.distanceSquaredTo(t) < closestL)
              closestL = currentL.loc.distanceSquaredTo(t);
          } else {
            curDirL = currentL.loc.directionTo(currentL.prevLoc.loc).rotateRight().rotateRight();
            int i = 2;
            while (!isGood(currentL.loc.add(curDirL))) {
              curDirL = curDirL.rotateRight();
              i++;
            }
            if (i < 4
                || curDirL != Direction.EAST
                    && curDirL != Direction.WEST
                    && curDirL != Direction.NORTH
                    && curDirL != Direction.SOUTH) {
              currentL.isPivot = true;
              if (debug) System.out.println("LEFT PIVOT");
            }
            if (curDirL != directionTo(currentL.prevLoc.loc, currentL.loc)) {
              currentL.isPivot = true;
              if (debug) System.out.println("LEFT PIVOT");
            }
            currentL = currentL.update(curDirL);
            if (currentL.loc.distanceSquaredTo(t) < closestL)
              closestL = currentL.loc.distanceSquaredTo(t);
          }
        } else {
          // the right trace is closer
          if (debug) System.out.println("RIGHT TRACE");
          curDirR = directionTo(currentR.loc, t);
          if (curDirR != null && currentR.loc.add(curDirR).distanceSquaredTo(t) < closestR) {
            if (debug) System.out.println("FINISH RIGHT TRACE. GOING " + curDirR);
            isTracingR = false;
            currentR.isPivot = true;
            if (debug) System.out.println("RIGHT PIVOT");
            currentR = currentR.update(curDirR);
            if (currentR.loc.distanceSquaredTo(t) < closestR)
              closestR = currentR.loc.distanceSquaredTo(t);
          } else {
            curDirR = currentR.loc.directionTo(currentR.prevLoc.loc).rotateLeft().rotateLeft();
            int i = 2;
            while (!isGood(currentR.loc.add(curDirR))) {
              curDirR = curDirR.rotateLeft();
              i++;
            }
            if (i < 4
                || curDirR != Direction.EAST
                    && curDirR != Direction.WEST
                    && curDirR != Direction.NORTH
                    && curDirR != Direction.SOUTH) {
              currentR.isPivot = true;
              if (debug) System.out.println("RIGHT PIVOT");
            }
            if (curDirR != directionTo(currentR.prevLoc.loc, currentR.loc)) {
              currentR.isPivot = true;
              if (debug) System.out.println("RIGHT PIVOT");
            }
            currentR = currentR.update(curDirR);
            if (currentR.loc.distanceSquaredTo(t) < closestR)
              closestR = currentR.loc.distanceSquaredTo(t);
          }
        }
      }
    }

    current.isPivot = true;
    currentL.isPivot = true;
    currentR.isPivot = true;
    if (current.loc.equals(t)) {
      return current;
    }
    if (currentL.loc.equals(t)) {
      return currentL;
    }
    if (currentR.loc.equals(t)) {
      return currentR;
    }
    throw new GameActionException(null, "Unable to find a path from " + s + " to " + t);
  }