/** * 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(); }
/** * 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; }
/** * 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; }
/** * 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; } }