Beispiel #1
0
  /**
   * Calculates how much of the given goods type this settlement wants and should retain.
   *
   * @param type The <code>GoodsType</code>.
   * @return The amount of goods wanted.
   */
  protected int getWantedGoodsAmount(GoodsType type) {
    if (getUnitCount() <= 0) return 0;

    final Specification spec = getSpecification();
    final UnitType unitType = getFirstUnit().getType();
    final Role militaryRole =
        Role.getAvailableRoles(getOwner(), unitType, spec.getMilitaryRoles()).get(0);

    if (type.isMilitaryGoods()) {
      // Retain enough goods to fully arm.
      int need = 0;
      for (Unit u : ownedUnits) {
        if (u.getRole() == militaryRole) continue;
        List<AbstractGoods> required = u.getGoodsDifference(militaryRole, 1);
        need += AbstractGoods.getCount(type, required);
      }
      return need;
    }

    int consumption = getConsumptionOf(type);
    if (type == spec.getPrimaryFoodType()) {
      // Food is perishable, do not try to retain that much
      return Math.max(40, consumption * 3);
    }
    if (type.isTradeGoods() || type.isNewWorldLuxuryType() || type.isRefined()) {
      // Aim for 10 years supply, resupply is doubtful
      return Math.max(80, consumption * 20);
    }
    // Just keep some around
    return 2 * getUnitCount();
  }
Beispiel #2
0
  /**
   * Gets the amount of gold this <code>IndianSettlment</code> is willing to pay for the given
   * <code>Goods</code>.
   *
   * <p>It is only meaningful to call this method from the server, since the settlement's {@link
   * GoodsContainer} is hidden from the clients. The AI uses it though so it stays here for now.
   * Note that it takes no account of whether the native player actually has the gold.
   *
   * <p>FIXME: this is rancid with magic numbers.
   *
   * @param type The type of <code>Goods</code> to price.
   * @param amount The amount of <code>Goods</code> to price.
   * @return The price.
   */
  public int getPriceToBuy(GoodsType type, int amount) {
    if (amount > GoodsContainer.CARGO_SIZE) {
      throw new IllegalArgumentException("Amount > " + GoodsContainer.CARGO_SIZE);
    }

    int price = 0;
    if (type.isMilitaryGoods()) {
      // Might return zero if a surplus is present
      price = getMilitaryGoodsPriceToBuy(type, amount);
    }
    if (price == 0) {
      price = getNormalGoodsPriceToBuy(type, amount);
    }

    // Apply wanted bonus
    final int wantedBase = 100; // Granularity for wanted bonus
    final int wantedBonus // Premium paid for wanted goods types
        =
        (type == wantedGoods[0])
            ? 150
            : (type == wantedGoods[1]) ? 125 : (type == wantedGoods[2]) ? 110 : 100;
    // Do not simplify with *=, we want the integer truncation.
    price = wantedBonus * price / wantedBase;

    logger.finest("Full price(" + amount + " " + type + ")" + " -> " + price);
    return price;
  }
Beispiel #3
0
 @Override
 public int compare(Goods goods1, Goods goods2) {
   int cmp;
   GoodsType t1 = goods1.getType();
   GoodsType t2 = goods2.getType();
   cmp = (((t2.isNewWorldGoodsType()) ? 1 : 0) - ((t1.isNewWorldGoodsType()) ? 1 : 0));
   if (cmp == 0) {
     int a1 = Math.min(goods2.getAmount(), GoodsContainer.CARGO_SIZE);
     int a2 = Math.min(goods1.getAmount(), GoodsContainer.CARGO_SIZE);
     cmp = getPriceToSell(t2, a2) - getPriceToSell(t1, a1);
     if (cmp == 0) {
       cmp = a2 - a1;
     }
   }
   return cmp;
 }
Beispiel #4
0
  /**
   * Gets the amount of gold this <code>IndianSettlment</code> is willing to sell the given <code>
   * Goods</code> for.
   *
   * <p>It is only meaningful to call this method from the server, since the settlement's {@link
   * GoodsContainer} is hidden from the clients.
   *
   * @param type The type of <code>Goods</code> to price.
   * @param amount The amount of <code>Goods</code> to price.
   * @return The price.
   */
  public int getPriceToSell(GoodsType type, int amount) {
    if (amount > GoodsContainer.CARGO_SIZE) {
      throw new IllegalArgumentException("Amount > " + GoodsContainer.CARGO_SIZE);
    }
    final int full = GOODS_BASE_PRICE + getType().getTradeBonus();

    // Base price is purchase price plus delta.
    // - military goods at double value
    // - trade goods at +50%
    int price = amount + Math.max(0, 11 * getPriceToBuy(type, amount) / 10);
    if (type.isMilitaryGoods()) {
      price = Math.max(price, amount * full * 2);
    } else if (type.isTradeGoods()) {
      price = Math.max(price, 150 * amount * full / 100);
    }
    return price;
  }
Beispiel #5
0
  /** {@inheritDoc} */
  @Override
  public int getImportAmount(GoodsType goodsType, int turns) {
    if (goodsType.limitIgnored()) return Integer.MAX_VALUE;

    int present = Math.max(0, getGoodsCount(goodsType) - turns * getTotalProductionOf(goodsType));
    int capacity = getWarehouseCapacity();
    return capacity - present;
  }
Beispiel #6
0
 /**
  * Updates the goods wanted by this settlement.
  *
  * <p>It is only meaningful to call this method from the server, since the settlement's {@link
  * GoodsContainer} is hidden from the clients.
  */
 public void updateWantedGoods() {
   final Specification spec = getSpecification();
   final java.util.Map<GoodsType, Integer> prices = new HashMap<>();
   for (GoodsType gt : spec.getGoodsTypeList()) {
     // The natives do not trade military or non-storable goods.
     if (gt.isMilitaryGoods() || !gt.isStorable()) continue;
     prices.put(gt, getNormalGoodsPriceToBuy(gt, GoodsContainer.CARGO_SIZE));
   }
   int wantedIndex = 0;
   for (Entry<GoodsType, Integer> e : mapEntriesByValue(prices, descendingIntegerComparator)) {
     GoodsType goodsType = e.getKey();
     if (e.getValue() <= GoodsContainer.CARGO_SIZE * TRADE_MINIMUM_PRICE
         || wantedIndex >= wantedGoods.length) break;
     wantedGoods[wantedIndex] = goodsType;
     wantedIndex++;
   }
   for (; wantedIndex < wantedGoods.length; wantedIndex++) {
     wantedGoods[wantedIndex] = null;
   }
 }
Beispiel #7
0
  /**
   * Price some goods according to the amount present in the settlement.
   *
   * @param type The type of goods for sale.
   * @param amount The amount of goods for sale.
   * @return A price for the goods.
   */
  private int getNormalGoodsPriceToBuy(GoodsType type, int amount) {
    final int tradeGoodsAdd = 20; // Fake additional trade goods present
    final int capacity = getGoodsCapacity();
    int current = getGoodsCount(type);

    // Increase effective stock if its raw material is produced here.
    GoodsType rawType = type.getInputType();
    if (rawType != null) {
      int rawProduction = getMaximumProduction(rawType);
      int add =
          (rawProduction < 5)
              ? 10 * rawProduction
              : (rawProduction < 10)
                  ? 5 * rawProduction + 25
                  : (rawProduction < 20) ? 2 * rawProduction + 55 : 100;
      // Decrease bonus in proportion to current stock, up to capacity.
      add = add * Math.max(0, capacity - current) / capacity;
      current += add;
    } else if (type.isTradeGoods()) {
      // Small artificial increase of the trade goods stored.
      current += tradeGoodsAdd;
    }

    // Only interested in the amount of goods that keeps the
    // total under the threshold.
    int retain = Math.min(getWantedGoodsAmount(type), capacity);
    int valued = (retain <= current) ? 0 : Math.min(amount, retain - current);

    // Unit price then is maximum price plus the bonus for the
    // settlement type, reduced by the proportion of goods present.
    int unitPrice =
        (GOODS_BASE_PRICE + getType().getTradeBonus()) * Math.max(0, capacity - current) / capacity;

    // But farmed goods are always less interesting.
    // and small settlements are not interested in building.
    if (type.isFarmed() || type.isRawBuildingMaterial()) unitPrice /= 2;

    // Only pay for the portion that is valued.
    return (unitPrice < 0) ? 0 : valued * unitPrice;
  }
Beispiel #8
0
  /** {@inheritDoc} */
  @Override
  public int getTotalProductionOf(GoodsType type) {
    if (type.isRefined()) {
      if (type != goodsToMake()) return 0;
      // Pretend 1/3 of the units present make the item with
      // basic production of 3.
      return getUnitCount();
    }

    int potential = 0;
    int tiles = 0;

    for (Tile workTile : getOwnedTiles()) {
      if (workTile != getTile() && !workTile.isOccupied()) {
        // FIXME: make unitType brave
        potential += workTile.getPotentialProduction(type, null);
        tiles++;
      }
    }

    // When a native settlement has more tiles than units, pretend
    // that they produce from their entire area at reduced
    // efficiency.
    if (tiles > getUnitCount()) {
      potential *= (float) getUnitCount() / tiles;
    }

    // Raw production is too generous, apply a fudge factor to reduce it
    // a bit for the non-food cases.
    if (!type.isFoodType()) {
      potential = (int) Math.round(potential * NATIVE_PRODUCTION_EFFICIENCY);
    }

    // But always add full potential of the center tile.
    potential += getTile().getPotentialProduction(type, null);
    return potential;
  }
Beispiel #9
0
 /**
  * Chooses a type of goods for some of the natives in a settlement to manufacture. Simple rule:
  * choose the refined goods that is the greatest shortage for which there is a surplus of the raw
  * material.
  *
  * @return A <code>GoodsType</code> to manufacture, or null if none suitable.
  */
 private GoodsType goodsToMake() {
   GoodsType wantGoods = null;
   int diff, wantAmount = -1;
   for (GoodsType g : getSpecification().getGoodsTypeList()) {
     GoodsType produced;
     if (g.isRawMaterial()
         && (produced = g.getOutputType()) != null
         && !produced.isBreedable()
         && produced.isStorable()
         && getGoodsCount(g) > getWantedGoodsAmount(g)
         && (diff = getWantedGoodsAmount(produced) - getGoodsCount(produced)) > wantAmount) {
       wantGoods = produced;
       wantAmount = diff;
     }
   }
   return wantGoods;
 }
Beispiel #10
0
 /**
  * Will this settlement sell a type of goods. Placeholder until we have a spec-configured
  * blacklist.
  *
  * @param type The <code>GoodsType</code> to consider.
  * @return True if the settlement would sell the goods.
  */
 public boolean willSell(GoodsType type) {
   return !type.isTradeGoods();
 }