use of games.strategy.engine.data.ProductionRule in project triplea by triplea-game.
the class InitializationDelegate method initDestroyerArtillery.
private static void initDestroyerArtillery(final IDelegateBridge bridge) {
final GameData data = bridge.getData();
final boolean addArtilleryAndDestroyers = Properties.getUseDestroyersAndArtillery(data);
if (!isWW2V2(data) && addArtilleryAndDestroyers) {
final CompositeChange change = new CompositeChange();
final ProductionRule artillery = data.getProductionRuleList().getProductionRule("buyArtillery");
final ProductionRule destroyer = data.getProductionRuleList().getProductionRule("buyDestroyer");
final ProductionFrontier frontier = data.getProductionFrontierList().getProductionFrontier("production");
if (artillery != null && !frontier.getRules().contains(artillery)) {
change.add(ChangeFactory.addProductionRule(artillery, frontier));
}
if (destroyer != null && !frontier.getRules().contains(destroyer)) {
change.add(ChangeFactory.addProductionRule(destroyer, frontier));
}
final ProductionRule artilleryIndustrialTechnology = data.getProductionRuleList().getProductionRule("buyArtilleryIndustrialTechnology");
final ProductionRule destroyerIndustrialTechnology = data.getProductionRuleList().getProductionRule("buyDestroyerIndustrialTechnology");
final ProductionFrontier frontierIndustrialTechnology = data.getProductionFrontierList().getProductionFrontier("productionIndustrialTechnology");
if (artilleryIndustrialTechnology != null && !frontierIndustrialTechnology.getRules().contains(artilleryIndustrialTechnology)) {
change.add(ChangeFactory.addProductionRule(artilleryIndustrialTechnology, frontierIndustrialTechnology));
}
if (destroyerIndustrialTechnology != null && !frontierIndustrialTechnology.getRules().contains(destroyerIndustrialTechnology)) {
change.add(ChangeFactory.addProductionRule(destroyerIndustrialTechnology, frontierIndustrialTechnology));
}
if (!change.isEmpty()) {
bridge.getHistoryWriter().startEvent("Adding destroyers and artillery production rules");
bridge.addChange(change);
}
}
}
use of games.strategy.engine.data.ProductionRule in project triplea by triplea-game.
the class InitializationDelegate method initShipyards.
private static void initShipyards(final IDelegateBridge bridge) {
final GameData data = bridge.getData();
final boolean useShipyards = Properties.getUseShipyards(data);
if (useShipyards) {
final CompositeChange change = new CompositeChange();
final ProductionFrontier frontierShipyards = data.getProductionFrontierList().getProductionFrontier("productionShipyards");
/*
* Find the productionRules, if the unit is NOT a sea unit, add it to the ShipYards prod rule.
*/
final ProductionFrontier frontierNonShipyards = data.getProductionFrontierList().getProductionFrontier("production");
final Collection<ProductionRule> rules = frontierNonShipyards.getRules();
for (final ProductionRule rule : rules) {
final String ruleName = rule.getName();
final IntegerMap<NamedAttachable> ruleResults = rule.getResults();
final NamedAttachable named = ruleResults.keySet().iterator().next();
if (!(named instanceof UnitType)) {
continue;
}
final UnitType unit = data.getUnitTypeList().getUnitType(named.getName());
final boolean isSea = UnitAttachment.get(unit).getIsSea();
if (!isSea) {
final ProductionRule prodRule = data.getProductionRuleList().getProductionRule(ruleName);
change.add(ChangeFactory.addProductionRule(prodRule, frontierShipyards));
}
}
bridge.getHistoryWriter().startEvent("Adding shipyard production rules - land/air units");
bridge.addChange(change);
}
}
use of games.strategy.engine.data.ProductionRule in project triplea by triplea-game.
the class GameDataExporter method productionFrontiers.
private void productionFrontiers(final GameData data) {
for (final String frontierName : data.getProductionFrontierList().getProductionFrontierNames()) {
final ProductionFrontier frontier = data.getProductionFrontierList().getProductionFrontier(frontierName);
xmlfile.append("\n");
xmlfile.append(" <productionFrontier name=\"").append(frontier.getName()).append("\">\n");
for (final ProductionRule rule : frontier.getRules()) {
xmlfile.append(" <frontierRules name=\"").append(rule.getName()).append("\"/>\n");
}
xmlfile.append(" </productionFrontier>\n");
}
xmlfile.append("\n");
}
use of games.strategy.engine.data.ProductionRule in project triplea by triplea-game.
the class GameDataExporter method productionRules.
private void productionRules(final GameData data) {
for (final ProductionRule pr : data.getProductionRuleList().getProductionRules()) {
xmlfile.append(" <productionRule name=\"").append(pr.getName()).append("\">\n");
for (final Resource cost : pr.getCosts().keySet()) {
xmlfile.append(" <cost resource=\"").append(cost.getName()).append("\" quantity=\"").append(pr.getCosts().getInt(cost)).append("\"/>\n");
}
for (final NamedAttachable result : pr.getResults().keySet()) {
xmlfile.append(" <result resourceOrUnit=\"").append(result.getName()).append("\" quantity=\"").append(pr.getResults().getInt(result)).append("\"/>\n");
}
xmlfile.append(" </productionRule>\n");
}
}
use of games.strategy.engine.data.ProductionRule in project triplea by triplea-game.
the class WeakAi method purchase.
@Override
public void purchase(final boolean purchaseForBid, final int pusToSpend, final IPurchaseDelegate purchaseDelegate, final GameData data, final PlayerID player) {
if (purchaseForBid) {
// bid will only buy land units, due to weak ai placement for bid not being able to handle sea units
final Resource pus = data.getResourceList().getResource(Constants.PUS);
int leftToSpend = pusToSpend;
final List<ProductionRule> rules = player.getProductionFrontier().getRules();
final IntegerMap<ProductionRule> purchase = new IntegerMap<>();
int minCost = Integer.MAX_VALUE;
int i = 0;
while ((minCost == Integer.MAX_VALUE || leftToSpend >= minCost) && i < 100000) {
i++;
for (final ProductionRule rule : rules) {
final NamedAttachable resourceOrUnit = rule.getResults().keySet().iterator().next();
if (!(resourceOrUnit instanceof UnitType)) {
continue;
}
final UnitType results = (UnitType) resourceOrUnit;
if (Matches.unitTypeIsSea().test(results) || Matches.unitTypeIsAir().test(results) || Matches.unitTypeIsInfrastructure().test(results) || Matches.unitTypeIsAaForAnything().test(results) || Matches.unitTypeHasMaxBuildRestrictions().test(results) || Matches.unitTypeConsumesUnitsOnCreation().test(results) || Matches.unitTypeIsStatic(player).test(results)) {
continue;
}
final int cost = rule.getCosts().getInt(pus);
if (cost < 1) {
continue;
}
if (minCost == Integer.MAX_VALUE) {
minCost = cost;
}
if (minCost > cost) {
minCost = cost;
}
// give a preference to cheap units
if (Math.random() * cost < 2) {
if (cost <= leftToSpend) {
leftToSpend -= cost;
purchase.add(rule, 1);
}
}
}
}
purchaseDelegate.purchase(purchase);
pause();
return;
}
final boolean isAmphib = isAmphibAttack(player, data);
final Route amphibRoute = getAmphibRoute(player, data);
final int transportCount = countTransports(data, player);
final int landUnitCount = countLandUnits(data, player);
int defUnitsAtAmpibRoute = 0;
if (isAmphib && amphibRoute != null) {
defUnitsAtAmpibRoute = amphibRoute.getEnd().getUnits().getUnitCount();
}
final Resource pus = data.getResourceList().getResource(Constants.PUS);
final int totalPu = player.getResources().getQuantity(pus);
int leftToSpend = totalPu;
final Territory capitol = TerritoryAttachment.getFirstOwnedCapitalOrFirstUnownedCapital(player, data);
final List<ProductionRule> rules = player.getProductionFrontier().getRules();
final IntegerMap<ProductionRule> purchase = new IntegerMap<>();
final List<RepairRule> repairRules;
final Predicate<Unit> ourFactories = Matches.unitIsOwnedBy(player).and(Matches.unitCanProduceUnits());
final List<Territory> repairFactories = CollectionUtils.getMatches(Utils.findUnitTerr(data, ourFactories), Matches.isTerritoryOwnedBy(player));
// figure out if anything needs to be repaired
if (player.getRepairFrontier() != null && Properties.getDamageFromBombingDoneToUnitsInsteadOfTerritories(data)) {
repairRules = player.getRepairFrontier().getRules();
final IntegerMap<RepairRule> repairMap = new IntegerMap<>();
final HashMap<Unit, IntegerMap<RepairRule>> repair = new HashMap<>();
final Map<Unit, Territory> unitsThatCanProduceNeedingRepair = new HashMap<>();
final int minimumUnitPrice = 3;
int diff;
int capProduction = 0;
Unit capUnit = null;
Territory capUnitTerritory = null;
int currentProduction = 0;
// we should sort this
Collections.shuffle(repairFactories);
for (final Territory fixTerr : repairFactories) {
if (!Matches.territoryIsOwnedAndHasOwnedUnitMatching(player, Matches.unitCanProduceUnitsAndCanBeDamaged()).test(fixTerr)) {
continue;
}
final Unit possibleFactoryNeedingRepair = TripleAUnit.getBiggestProducer(CollectionUtils.getMatches(fixTerr.getUnits().getUnits(), ourFactories), fixTerr, player, data, false);
if (Matches.unitHasTakenSomeBombingUnitDamage().test(possibleFactoryNeedingRepair)) {
unitsThatCanProduceNeedingRepair.put(possibleFactoryNeedingRepair, fixTerr);
}
if (fixTerr == capitol) {
capProduction = TripleAUnit.getHowMuchCanUnitProduce(possibleFactoryNeedingRepair, fixTerr, player, data, true, true);
capUnit = possibleFactoryNeedingRepair;
capUnitTerritory = fixTerr;
}
currentProduction += TripleAUnit.getHowMuchCanUnitProduce(possibleFactoryNeedingRepair, fixTerr, player, data, true, true);
}
repairFactories.remove(capitol);
unitsThatCanProduceNeedingRepair.remove(capUnit);
// assume minimum unit price is 3, and that we are buying only that... if we over repair, oh well, that is better
// than under-repairing
// goal is to be able to produce all our units, and at least half of that production in the capitol
//
// if capitol is super safe, we don't have to do this. and if capitol is under siege, we should repair enough to
// place all our units here
int maxUnits = (totalPu - 1) / minimumUnitPrice;
if ((capProduction <= maxUnits / 2 || repairFactories.isEmpty()) && capUnit != null) {
for (final RepairRule rrule : repairRules) {
if (!capUnit.getType().equals(rrule.getResults().keySet().iterator().next())) {
continue;
}
if (!Matches.territoryIsOwnedAndHasOwnedUnitMatching(player, Matches.unitCanProduceUnitsAndCanBeDamaged()).test(capitol)) {
continue;
}
final TripleAUnit taUnit = (TripleAUnit) capUnit;
diff = taUnit.getUnitDamage();
final int unitProductionAllowNegative = TripleAUnit.getHowMuchCanUnitProduce(capUnit, capUnitTerritory, player, data, false, true) - diff;
if (!repairFactories.isEmpty()) {
diff = Math.min(diff, (maxUnits / 2 - unitProductionAllowNegative) + 1);
} else {
diff = Math.min(diff, (maxUnits - unitProductionAllowNegative));
}
diff = Math.min(diff, leftToSpend - minimumUnitPrice);
if (diff > 0) {
if (unitProductionAllowNegative >= 0) {
currentProduction += diff;
} else {
currentProduction += diff + unitProductionAllowNegative;
}
repairMap.add(rrule, diff);
repair.put(capUnit, repairMap);
leftToSpend -= diff;
purchaseDelegate.purchaseRepair(repair);
repair.clear();
repairMap.clear();
// ideally we would adjust this after each single PU spent, then re-evaluate
// everything.
maxUnits = (leftToSpend - 1) / minimumUnitPrice;
}
}
}
int i = 0;
while (currentProduction < maxUnits && i < 2) {
for (final RepairRule rrule : repairRules) {
for (final Unit fixUnit : unitsThatCanProduceNeedingRepair.keySet()) {
if (fixUnit == null || !fixUnit.getType().equals(rrule.getResults().keySet().iterator().next())) {
continue;
}
if (!Matches.territoryIsOwnedAndHasOwnedUnitMatching(player, Matches.unitCanProduceUnitsAndCanBeDamaged()).test(unitsThatCanProduceNeedingRepair.get(fixUnit))) {
continue;
}
// territories
if (currentProduction >= maxUnits) {
continue;
}
final TripleAUnit taUnit = (TripleAUnit) fixUnit;
diff = taUnit.getUnitDamage();
final int unitProductionAllowNegative = TripleAUnit.getHowMuchCanUnitProduce(fixUnit, unitsThatCanProduceNeedingRepair.get(fixUnit), player, data, false, true) - diff;
if (i == 0) {
if (unitProductionAllowNegative < 0) {
diff = Math.min(diff, (maxUnits - currentProduction) - unitProductionAllowNegative);
} else {
diff = Math.min(diff, (maxUnits - currentProduction));
}
}
diff = Math.min(diff, leftToSpend - minimumUnitPrice);
if (diff > 0) {
if (unitProductionAllowNegative >= 0) {
currentProduction += diff;
} else {
currentProduction += diff + unitProductionAllowNegative;
}
repairMap.add(rrule, diff);
repair.put(fixUnit, repairMap);
leftToSpend -= diff;
purchaseDelegate.purchaseRepair(repair);
repair.clear();
repairMap.clear();
// ideally we would adjust this after each single PU spent, then re-evaluate
// everything.
maxUnits = (leftToSpend - 1) / minimumUnitPrice;
}
}
}
repairFactories.add(capitol);
if (capUnit != null) {
unitsThatCanProduceNeedingRepair.put(capUnit, capUnitTerritory);
}
i++;
}
}
int minCost = Integer.MAX_VALUE;
int i = 0;
while ((minCost == Integer.MAX_VALUE || leftToSpend >= minCost) && i < 100000) {
i++;
for (final ProductionRule rule : rules) {
final NamedAttachable resourceOrUnit = rule.getResults().keySet().iterator().next();
if (!(resourceOrUnit instanceof UnitType)) {
continue;
}
final UnitType results = (UnitType) resourceOrUnit;
if (Matches.unitTypeIsAir().test(results) || Matches.unitTypeIsInfrastructure().test(results) || Matches.unitTypeIsAaForAnything().test(results) || Matches.unitTypeHasMaxBuildRestrictions().test(results) || Matches.unitTypeConsumesUnitsOnCreation().test(results) || Matches.unitTypeIsStatic(player).test(results)) {
continue;
}
final int transportCapacity = UnitAttachment.get(results).getTransportCapacity();
// buy transports if we can be amphibious
if (Matches.unitTypeIsSea().test(results)) {
if (!isAmphib || transportCapacity <= 0) {
continue;
}
}
final int cost = rule.getCosts().getInt(pus);
if (cost < 1) {
continue;
}
if (minCost == Integer.MAX_VALUE) {
minCost = cost;
}
if (minCost > cost) {
minCost = cost;
}
// give a preferene to cheap units, and to transports
// but dont go overboard with buying transports
int goodNumberOfTransports = 0;
final boolean isTransport = transportCapacity > 0;
if (amphibRoute != null) {
// 25% transports - can be more if frontier is far away
goodNumberOfTransports = (landUnitCount / 4);
// boost for transport production
if (isTransport && defUnitsAtAmpibRoute > goodNumberOfTransports && landUnitCount > defUnitsAtAmpibRoute && defUnitsAtAmpibRoute > transportCount) {
final int transports = (leftToSpend / cost);
leftToSpend -= cost * transports;
purchase.add(rule, transports);
continue;
}
}
final boolean buyBecauseTransport = (Math.random() < 0.7 && transportCount < goodNumberOfTransports) || Math.random() < 0.10;
final boolean dontBuyBecauseTooManyTransports = transportCount > 2 * goodNumberOfTransports;
if ((!isTransport && Math.random() * cost < 2) || (isTransport && buyBecauseTransport && !dontBuyBecauseTooManyTransports)) {
if (cost <= leftToSpend) {
leftToSpend -= cost;
purchase.add(rule, 1);
}
}
}
}
purchaseDelegate.purchase(purchase);
pause();
}
Aggregations