/**
   * Assign a carrier for this treasure.
   *
   * @param lb A <code>LogBuilder</code> to log to.
   * @return A suitable carrier <code>AIUnit</code>, to which this unit has been queued for
   *     transport.
   */
  private AIUnit assignCarrier(LogBuilder lb) {
    final AIUnit aiUnit = getAIUnit();
    final Unit unit = getUnit();
    final Player player = unit.getOwner();
    final Europe europe = player.getEurope();

    List<Unit> carriers = player.getCarriersForUnit(unit);
    if (carriers.isEmpty()) return null;

    // Pick the closest carrier and queue this unit.
    final Location here = unit.getLocation();
    int turns = INFINITY;
    Unit closest = null;
    for (Unit c : carriers) {
      int t = c.getTurnsToReach(here);
      if (turns > t) {
        turns = t;
        closest = c;
      }
    }
    final AIMain aiMain = getAIMain();
    TransportMission tm;
    AIUnit aiCarrier;
    if (closest != null
        && (aiCarrier = aiMain.getAIUnit(closest)) != null
        && (tm = aiCarrier.getMission(TransportMission.class)) != null) {
      setTarget(europe);
      aiUnit.changeTransport(aiCarrier);
      if (tm.forceCollection(aiUnit, lb)) {
        lb.add(" forced collection on ", aiCarrier.getUnit());
        return aiCarrier;
      }
    }
    return null;
  }
  /** {@inheritDoc} */
  @Override
  public Mission doMission(LogBuilder lb) {
    lb.add(tag);
    String reason = invalidReason();
    if (isTargetReason(reason)) {
      return retargetMission(reason, lb);
    } else if (reason != null) {
      return lbFail(lb, false, reason);
    }

    for (; ; ) {
      // Go to the target.
      final Unit unit = getUnit();
      Unit.MoveType mt =
          travelToTarget(getTarget(), CostDeciders.avoidSettlementsAndBlockingUnits(), lb);
      switch (mt) {
        case MOVE: // Arrived
          break;

        case MOVE_HIGH_SEAS:
        case MOVE_NO_MOVES:
        case MOVE_NO_REPAIR:
        case MOVE_ILLEGAL:
          return lbWait(lb);

        case MOVE_NO_ACCESS_EMBARK:
        case MOVE_NO_TILE:
          return this;

        default:
          return lbMove(lb, mt);
      }

      // Cash in now if:
      // - already in Europe
      // - or can never get there
      // - it is free to transport the treasure
      // - or there is no potential carrier to get the treasure to there
      // Otherwise, it is better to send to Europe.
      lbAt(lb);
      final AIUnit aiUnit = getAIUnit();
      final Europe europe = getUnit().getOwner().getEurope();
      if (unit.canCashInTreasureTrain()) {
        AIUnit aiCarrier = null;
        boolean cashin = unit.isInEurope() || europe == null || unit.getTransportFee() == 0;
        if (!cashin && aiUnit.getTransport() == null) {
          cashin = assignCarrier(lb) == null;
        }
        if (cashin)
          return (AIMessage.askCashInTreasureTrain(aiUnit))
              ? lbDone(lb, false, "cashed in")
              : lbFail(lb, false, "cashin");
      }
      return retargetMission("transport expected", lb);
    }
  }
Example #3
0
 /**
  * Loads all valid mods from a specified directory.
  *
  * @param directory The directory to load from.
  */
 private static void loadModDirectory(File directory) {
   if (directory != null && directory.isDirectory()) {
     LogBuilder lb = new LogBuilder(64);
     lb.add("In ", directory.getPath(), " found mod:");
     lb.mark();
     for (File f : directory.listFiles(MOD_FILTER)) {
       try {
         FreeColModFile fcmf = new FreeColModFile(f);
         allMods.put(fcmf.getId(), fcmf);
         lb.add(" ", fcmf.getId());
       } catch (IOException e) {
         logger.log(Level.WARNING, "Bad mod in " + f.getPath(), e);
       }
     }
     if (lb.grew()) lb.log(logger, Level.INFO);
   }
 }
  /** {@inheritDoc} */
  @Override
  public Mission doMission(LogBuilder lb) {
    lb.add(tag);
    String reason = invalidReason();
    if (reason != null) return lbFail(lb, false, reason);

    final AIUnit aiUnit = getAIUnit();
    final Unit unit = getUnit();
    final IndianSettlement is = unit.getHomeIndianSettlement();
    Direction d;

    while (!this.demanded) {
      Unit.MoveType mt = travelToTarget(getTarget(), null, lb);
      switch (mt) {
        case MOVE_HIGH_SEAS:
        case MOVE_NO_MOVES:
        case MOVE_ILLEGAL:
          return lbWait(lb);

        case MOVE_NO_REPAIR:
          return lbFail(lb, false, AIUNITDIED);

        case MOVE_NO_TILE:
          return this;

        case ATTACK_SETTLEMENT: // Arrived?
          d = unit.getTile().getDirection(getTarget().getTile());
          if (d != null) break; // Yes, arrived at target
          // Fall through
        case ATTACK_UNIT: // Something is blocking our path
          Location blocker = resolveBlockage(aiUnit, getTarget());
          if (blocker == null) {
            moveRandomly(tag, null);
            continue;
          }
          d = unit.getTile().getDirection(blocker.getTile());
          if (AIMessage.askAttack(aiUnit, d)) {
            return lbAttack(lb, blocker);
          }
          continue;

        default:
          return lbMove(lb, mt);
      }

      // Load the goods.
      lbAt(lb);
      Colony colony = (Colony) getTarget();
      Player enemy = colony.getOwner();
      Goods goods = selectGoods(colony);
      GoodsType type = (goods == null) ? null : goods.getType();
      int amount = (goods == null) ? 0 : goods.getAmount();
      if (goods == null) {
        if (!enemy.checkGold(1)) {
          return lbDone(lb, false, "empty handed");
        }
        amount = enemy.getGold() / 20;
        if (amount == 0) amount = enemy.getGold();
      }
      this.demanded = AIMessage.askIndianDemand(aiUnit, colony, type, amount);
      if (this.demanded && (goods == null || hasTribute())) {
        if (goods == null) {
          return lbDone(lb, false, "accepted tribute ", amount, " gold");
        }
        lb.add(", accepted tribute ", goods);
        return lbRetarget(lb);
      }

      // Consider attacking if not content.
      int unitTension = (is == null) ? 0 : is.getAlarm(enemy).getValue();
      int tension = Math.max(unitTension, unit.getOwner().getTension(enemy).getValue());
      d = unit.getTile().getDirection(colony.getTile());
      if (tension >= Tension.Level.CONTENT.getLimit() && d != null) {
        if (AIMessage.askAttack(aiUnit, d)) lbAttack(lb, colony);
      }
      return lbDone(lb, false, "refused at ", colony);
    }

    // Take the goods home
    for (; ; ) {
      Unit.MoveType mt =
          travelToTarget(getTarget(), CostDeciders.avoidSettlementsAndBlockingUnits(), lb);
      switch (mt) {
        case MOVE: // Arrived
          break;

        case MOVE_HIGH_SEAS:
        case MOVE_NO_MOVES:
        case MOVE_ILLEGAL:
          return lbWait(lb);

        case MOVE_NO_REPAIR:
          return lbFail(lb, false, AIUNITDIED);

        case MOVE_NO_TILE:
          return this;

        default:
          return lbMove(lb, mt);
      }

      // Unload the goods
      lbAt(lb);
      GoodsContainer container = unit.getGoodsContainer();
      for (Goods goods : container.getCompactGoods()) {
        Goods tribute = container.removeGoods(goods.getType());
        is.addGoods(tribute);
      }
      return lbDone(lb, false, "unloaded tribute");
    }
  }