use of games.strategy.engine.data.UnitType in project triplea by triplea-game.
the class FinishedBattle method unitsLostInPrecedingBattle.
@Override
public void unitsLostInPrecedingBattle(final IBattle battle, final Collection<Unit> units, final IDelegateBridge bridge, final boolean withdrawn) {
final Collection<Unit> lost = getDependentUnits(units);
lost.addAll(CollectionUtils.intersection(units, m_attackingUnits));
if (lost.size() != 0) {
m_attackingUnits.removeAll(lost);
/*
* TODO: these units are no longer in this territory, most probably. Plus they may have already been removed by
* another "real" battle
* class.
* final String transcriptText = MyFormatter.unitsToText(lost) + " lost in " + m_battleSite.getName();
* bridge.getHistoryWriter().startEvent(transcriptText);
* final Change change = ChangeFactory.removeUnits(m_battleSite, lost);
* bridge.addChange(change);
*/
if (m_attackingUnits.isEmpty()) {
final IntegerMap<UnitType> costs = TuvUtils.getCostsForTuv(m_attacker, m_data);
final int tuvLostAttacker = (withdrawn ? 0 : TuvUtils.getTuv(lost, m_attacker, costs, m_data));
m_attackerLostTUV += tuvLostAttacker;
// scripted?
m_whoWon = WhoWon.DEFENDER;
if (!m_headless) {
m_battleTracker.getBattleRecords().addResultToBattle(m_attacker, m_battleID, m_defender, m_attackerLostTUV, m_defenderLostTUV, BattleRecord.BattleResultDescription.LOST, new BattleResults(this, m_data));
}
m_battleTracker.removeBattle(this);
}
}
}
use of games.strategy.engine.data.UnitType in project triplea by triplea-game.
the class DiceRoll method getSupport.
/**
* Fills a set and map with the support possibly given by these units.
*
* @param supportsAvailable
* an empty set that will be filled with all support rules grouped into lists of non-stacking rules
* @param supportLeft
* an empty map that will be filled with all the support that can be given in the form of counters
* @param supportUnitsLeft
* an empty map that will be filled with all the support that can be given in the form of counters
* @param defence
* are the receiving units defending?
* @param allies
* are the receiving units allied to the giving units?
*/
public static void getSupport(final List<Unit> unitsGivingTheSupport, final Set<List<UnitSupportAttachment>> supportsAvailable, final IntegerMap<UnitSupportAttachment> supportLeft, final Map<UnitSupportAttachment, LinkedIntegerMap<Unit>> supportUnitsLeft, final GameData data, final boolean defence, final boolean allies) {
if (unitsGivingTheSupport == null || unitsGivingTheSupport.isEmpty()) {
return;
}
for (final UnitSupportAttachment rule : UnitSupportAttachment.get(data)) {
if (rule.getPlayers().isEmpty()) {
continue;
}
if (!((defence && rule.getDefence()) || (!defence && rule.getOffence()))) {
continue;
}
if (!((allies && rule.getAllied()) || (!allies && rule.getEnemy()))) {
continue;
}
final Predicate<Unit> canSupport = Matches.unitIsOfType((UnitType) rule.getAttachedTo()).and(Matches.unitOwnedBy(rule.getPlayers()));
final List<Unit> supporters = CollectionUtils.getMatches(unitsGivingTheSupport, canSupport);
int numSupport = supporters.size();
if (numSupport <= 0) {
continue;
}
final List<Unit> impArtTechUnits = new ArrayList<>();
if (rule.getImpArtTech()) {
impArtTechUnits.addAll(CollectionUtils.getMatches(supporters, Matches.unitOwnerHasImprovedArtillerySupportTech()));
}
numSupport += impArtTechUnits.size();
supportLeft.put(rule, numSupport * rule.getNumber());
supportUnitsLeft.put(rule, new LinkedIntegerMap<>(supporters, rule.getNumber()));
supportUnitsLeft.get(rule).addAll(impArtTechUnits, rule.getNumber());
final Iterator<List<UnitSupportAttachment>> iter2 = supportsAvailable.iterator();
List<UnitSupportAttachment> ruleType = null;
boolean found = false;
final String bonusType = rule.getBonusType();
while (iter2.hasNext()) {
ruleType = iter2.next();
if (ruleType.get(0).getBonusType().equals(bonusType)) {
found = true;
break;
}
}
if (!found) {
ruleType = new ArrayList<>();
supportsAvailable.add(ruleType);
}
if (ruleType != null) {
ruleType.add(rule);
}
}
sortSupportRules(supportsAvailable, defence, allies);
}
use of games.strategy.engine.data.UnitType 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.UnitType 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();
}
use of games.strategy.engine.data.UnitType in project triplea by triplea-game.
the class AbstractPlayerRulesAttachment method setProductionPerXTerritories.
private void setProductionPerXTerritories(final String value) throws GameParseException {
final String[] s = value.split(":");
if (s.length <= 0 || s.length > 2) {
throw new GameParseException("productionPerXTerritories cannot be empty or have more than two fields" + thisErrorMsg());
}
final String unitTypeToProduce;
if (s.length == 1) {
unitTypeToProduce = Constants.UNIT_TYPE_INFANTRY;
} else {
unitTypeToProduce = s[1];
}
// validate that this unit exists in the xml
final UnitType ut = getData().getUnitTypeList().getUnitType(unitTypeToProduce);
if (ut == null) {
throw new GameParseException("No unit called: " + unitTypeToProduce + thisErrorMsg());
}
final int n = getInt(s[0]);
if (n <= 0) {
throw new GameParseException("productionPerXTerritories must be a positive integer" + thisErrorMsg());
}
m_productionPerXTerritories.put(ut, n);
}
Aggregations