private final Bullet setFireImpl(double power) {
    if (Double.isNaN(power)) {
      println("SYSTEM: You cannot call fire(NaN)");
      return null;
    }
    if (getGunHeatImpl() > 0 || getEnergyImpl() == 0) {
      return null;
    }

    power = min(getEnergyImpl(), min(max(power, Rules.MIN_BULLET_POWER), Rules.MAX_BULLET_POWER));

    Bullet bullet;
    BulletCommand wrapper;
    Event currentTopEvent = eventManager.getCurrentTopEvent();

    nextBulletId++;

    if (currentTopEvent != null
        && currentTopEvent.getTime() == status.getTime()
        && !statics.isAdvancedRobot()
        && status.getGunHeadingRadians() == status.getRadarHeadingRadians()
        && ScannedRobotEvent.class.isAssignableFrom(currentTopEvent.getClass())) {
      // this is angle assisted bullet
      ScannedRobotEvent e = (ScannedRobotEvent) currentTopEvent;
      double fireAssistAngle =
          Utils.normalAbsoluteAngle(status.getHeadingRadians() + e.getBearingRadians());

      bullet =
          new Bullet(
              fireAssistAngle, getX(), getY(), power, statics.getName(), null, true, nextBulletId);
      wrapper = new BulletCommand(power, true, fireAssistAngle, nextBulletId);
    } else {
      // this is normal bullet
      bullet =
          new Bullet(
              status.getGunHeadingRadians(),
              getX(),
              getY(),
              power,
              statics.getName(),
              null,
              true,
              nextBulletId);
      wrapper = new BulletCommand(power, false, 0, nextBulletId);
    }

    firedEnergy += power;
    firedHeat += Rules.getGunHeat(power);

    commands.getBullets().add(wrapper);

    bullets.put(nextBulletId, bullet);

    return bullet;
  }
 public void enemyPosition(ScannedRobotEvent e, double x, double y) {
   // poll subtargetters for their opinions
   virtualBulletTick++;
   lastEnemyScanTime = owner.getTime();
   // only log it when we actually fire: the enemy may respond to that
   if (owner.shouldFireShot(e)) {
     double bulletPower = e.getDistance() > 500.0 ? 2.0 : 3.0;
     for (int i = 0; i < numVirtualGuns; i++) {
       double angle = targetters[i].target(e, bulletPower);
       VirtualBullet bullet = new VirtualBullet();
       bullet.targetter = i;
       bullet.x = owner.getX();
       bullet.y = owner.getY();
       bullet.velX = Targetting.bulletSpeed(bulletPower) * Math.sin(angle);
       bullet.velY = Targetting.bulletSpeed(bulletPower) * Math.cos(angle);
       bullet.lastUpdateTime = lastEnemyScanTime;
       virtualBullets.add(bullet);
     }
   }
   for (int i = 0; i < numVirtualGuns; i++) {
     targetters[i].enemyPosition(e, x, y);
   }
   enemyX = x;
   enemyY = y;
 }
    public void onScannedRobot(ScannedRobotEvent event) {
      scannedDistance = (int) (event.getDistance() + 0.5);
      scannedEnergy = Math.max(1, (int) (event.getEnergy() + 0.5));
      scannedAngle =
          (int)
              (Math.toDegrees(
                      Utils.normalAbsoluteAngle(peer.getBodyHeading() + event.getBearingRadians()))
                  + 0.5);
      scannedBearing = (int) (event.getBearing() + 0.5);
      scannedHeading = (int) (event.getHeading() + 0.5);
      scannedVelocity = (int) (event.getVelocity() + 0.5);

      JuniorRobot.this.onScannedRobot();
    }