use of games.strategy.engine.data.NamedAttachable in project triplea by triplea-game.
the class TuvUtils method getResourceCostsForTuvForAllPlayersMergedAndAveraged.
/**
* Return a map where key are unit types and values are the AVERAGED for all players.
* Any production rule that produces multiple units
* (like artillery in NWO, costs 7 but makes 2 artillery, meaning effective price is 3.5 each)
* will have their costs rounded up on a per unit basis.
* Therefore, this map should NOT be used for Purchasing information!
*/
private static Map<UnitType, ResourceCollection> getResourceCostsForTuvForAllPlayersMergedAndAveraged(final GameData data) {
final Map<UnitType, ResourceCollection> average = new HashMap<>();
final Resource pus;
data.acquireReadLock();
try {
pus = data.getResourceList().getResource(Constants.PUS);
} finally {
data.releaseReadLock();
}
final IntegerMap<Resource> defaultMap = new IntegerMap<>();
defaultMap.put(pus, 1);
final ResourceCollection defaultResources = new ResourceCollection(data, defaultMap);
final Map<UnitType, List<ResourceCollection>> backups = new HashMap<>();
final Map<UnitType, ResourceCollection> backupAveraged = new HashMap<>();
for (final ProductionRule rule : data.getProductionRuleList().getProductionRules()) {
if (rule == null || rule.getResults() == null || rule.getResults().isEmpty() || rule.getCosts() == null || rule.getCosts().isEmpty()) {
continue;
}
final IntegerMap<NamedAttachable> unitMap = rule.getResults();
final ResourceCollection costPerGroup = new ResourceCollection(data, rule.getCosts());
final Set<UnitType> units = new HashSet<>();
for (final NamedAttachable resourceOrUnit : unitMap.keySet()) {
if (!(resourceOrUnit instanceof UnitType)) {
continue;
}
units.add((UnitType) resourceOrUnit);
}
if (units.isEmpty()) {
continue;
}
final int totalProduced = unitMap.totalValues();
if (totalProduced == 1) {
final UnitType ut = units.iterator().next();
final List<ResourceCollection> current = backups.computeIfAbsent(ut, k -> new ArrayList<>());
current.add(costPerGroup);
} else if (totalProduced > 1) {
costPerGroup.discount((double) 1 / (double) totalProduced);
for (final UnitType ut : units) {
final List<ResourceCollection> current = backups.computeIfAbsent(ut, k -> new ArrayList<>());
current.add(costPerGroup);
}
}
}
for (final Entry<UnitType, List<ResourceCollection>> entry : backups.entrySet()) {
final ResourceCollection avgCost = new ResourceCollection(entry.getValue().toArray(new ResourceCollection[0]), data);
if (entry.getValue().size() > 1) {
avgCost.discount((double) 1 / (double) entry.getValue().size());
}
backupAveraged.put(entry.getKey(), avgCost);
}
final Map<PlayerID, Map<UnitType, ResourceCollection>> allPlayersCurrent = getResourceCostsForTuv(data, false);
allPlayersCurrent.remove(null);
for (final UnitType ut : data.getUnitTypeList().getAllUnitTypes()) {
final List<ResourceCollection> costs = new ArrayList<>();
for (final Map<UnitType, ResourceCollection> entry : allPlayersCurrent.values()) {
if (entry.get(ut) != null) {
costs.add(entry.get(ut));
}
}
if (costs.isEmpty()) {
final ResourceCollection backup = backupAveraged.get(ut);
if (backup != null) {
costs.add(backup);
} else {
costs.add(defaultResources);
}
}
final ResourceCollection avgCost = new ResourceCollection(costs.toArray(new ResourceCollection[0]), data);
if (costs.size() > 1) {
avgCost.discount((double) 1 / (double) costs.size());
}
average.put(ut, avgCost);
}
return average;
}
use of games.strategy.engine.data.NamedAttachable in project triplea by triplea-game.
the class TuvUtils method getResourceCostsForTuv.
/**
* Return map where keys are unit types and values are resource costs of that unit type, based on a player.
* Any production rule that produces multiple units
* (like artillery in NWO, costs 7 but makes 2 artillery, meaning effective price is 3.5 each)
* will have their costs rounded up on a per unit basis.
* Therefore, this map should NOT be used for Purchasing information!
*/
public static Map<PlayerID, Map<UnitType, ResourceCollection>> getResourceCostsForTuv(final GameData data, final boolean includeAverageForMissingUnits) {
final HashMap<PlayerID, Map<UnitType, ResourceCollection>> result = new LinkedHashMap<>();
final Map<UnitType, ResourceCollection> average = includeAverageForMissingUnits ? TuvUtils.getResourceCostsForTuvForAllPlayersMergedAndAveraged(data) : new HashMap<>();
final List<PlayerID> players = data.getPlayerList().getPlayers();
players.add(PlayerID.NULL_PLAYERID);
for (final PlayerID p : players) {
final ProductionFrontier frontier = p.getProductionFrontier();
// any one will do then
if (frontier == null) {
result.put(p, average);
continue;
}
final Map<UnitType, ResourceCollection> current = result.computeIfAbsent(p, k -> new LinkedHashMap<>());
for (final ProductionRule rule : frontier.getRules()) {
if (rule == null || rule.getResults() == null || rule.getResults().isEmpty() || rule.getCosts() == null || rule.getCosts().isEmpty()) {
continue;
}
final IntegerMap<NamedAttachable> unitMap = rule.getResults();
final ResourceCollection costPerGroup = new ResourceCollection(data, rule.getCosts());
final Set<UnitType> units = new HashSet<>();
for (final NamedAttachable resourceOrUnit : unitMap.keySet()) {
if (!(resourceOrUnit instanceof UnitType)) {
continue;
}
units.add((UnitType) resourceOrUnit);
}
if (units.isEmpty()) {
continue;
}
final int totalProduced = unitMap.totalValues();
if (totalProduced == 1) {
current.put(units.iterator().next(), costPerGroup);
} else if (totalProduced > 1) {
costPerGroup.discount((double) 1 / (double) totalProduced);
for (final UnitType ut : units) {
current.put(ut, costPerGroup);
}
}
}
// we will add any unit types not in our list, based on the list for everyone
for (final UnitType ut : average.keySet()) {
if (!current.keySet().contains(ut)) {
current.put(ut, average.get(ut));
}
}
}
result.put(null, average);
return result;
}
use of games.strategy.engine.data.NamedAttachable in project triplea by triplea-game.
the class GameDataExporter method printAttachments.
private void printAttachments(final Tuple<IAttachment, ArrayList<Tuple<String, String>>> attachmentPlusValues) {
final IAttachment attachment = attachmentPlusValues.getFirst();
try {
// TODO: none of the attachment exporter classes have been updated since TripleA version 1.3.2.2
final String attachmentOptions;
attachmentOptions = printAttachmentOptionsBasedOnOriginalXml(attachmentPlusValues.getSecond(), attachment);
final NamedAttachable attachTo = (NamedAttachable) attachment.getAttachedTo();
// TODO: keep this list updated
String type = "";
if (attachTo.getClass().equals(PlayerID.class)) {
type = "player";
}
if (attachTo.getClass().equals(UnitType.class)) {
type = "unitType";
}
if (attachTo.getClass().equals(Territory.class)) {
type = "territory";
}
if (attachTo.getClass().equals(TerritoryEffect.class)) {
type = "territoryEffect";
}
if (attachTo.getClass().equals(Resource.class)) {
type = "resource";
}
if (attachTo.getClass().equals(RelationshipType.class)) {
type = "relationship";
}
if (TechAdvance.class.isAssignableFrom(attachTo.getClass())) {
type = "technology";
}
if (type.isEmpty()) {
throw new AttachmentExportException("no attachmentType known for " + attachTo.getClass().getCanonicalName());
}
if (attachmentOptions.length() > 0) {
xmlfile.append(" <attachment name=\"").append(attachment.getName()).append("\" attachTo=\"").append(attachTo.getName()).append("\" javaClass=\"").append(attachment.getClass().getCanonicalName()).append("\" type=\"").append(type).append("\">\n");
xmlfile.append(attachmentOptions);
xmlfile.append(" </attachment>\n");
}
} catch (final Exception e) {
ClientLogger.logError("An Error occured whilst trying to print the Attachment \"" + attachment.getName() + "\"", e);
}
}
use of games.strategy.engine.data.NamedAttachable in project triplea by triplea-game.
the class PurchaseDelegate method purchase.
@Override
public String purchase(final IntegerMap<ProductionRule> productionRules) {
final IntegerMap<Resource> costs = getCosts(productionRules);
final IntegerMap<NamedAttachable> results = getResults(productionRules);
if (!(canAfford(costs, player))) {
return NOT_ENOUGH_RESOURCES;
}
// check to see if player has too many of any building with a building limit
for (final NamedAttachable next : results.keySet()) {
if (!(next instanceof Resource)) {
final UnitType type = (UnitType) next;
final int quantity = results.getInt(type);
final UnitAttachment ua = UnitAttachment.get(type);
final int maxBuilt = ua.getMaxBuiltPerPlayer();
if (maxBuilt == 0) {
return "May not build any of this unit right now: " + type.getName();
} else if (maxBuilt > 0) {
// count how many units are yet to be placed or are in the field
int currentlyBuilt = player.getUnits().countMatches(Matches.unitIsOfType(type));
final Predicate<Unit> unitTypeOwnedBy = Matches.unitIsOfType(type).and(Matches.unitIsOwnedBy(player));
final Collection<Territory> allTerrs = getData().getMap().getTerritories();
for (final Territory t : allTerrs) {
currentlyBuilt += t.getUnits().countMatches(unitTypeOwnedBy);
}
final int allowedBuild = maxBuilt - currentlyBuilt;
if (allowedBuild - quantity < 0) {
return "May only build " + allowedBuild + " of " + type.getName() + " this turn, may only build " + maxBuilt + " total";
}
}
}
}
// remove first, since add logs PUs remaining
final Collection<Unit> totalUnits = new ArrayList<>();
final Collection<UnitType> totalUnitTypes = new ArrayList<>();
final Collection<Resource> totalResources = new ArrayList<>();
final CompositeChange changes = new CompositeChange();
// and find all added units
for (final NamedAttachable next : results.keySet()) {
if (next instanceof Resource) {
final Resource resource = (Resource) next;
final int quantity = results.getInt(resource);
final Change change = ChangeFactory.changeResourcesChange(player, resource, quantity);
changes.add(change);
for (int i = 0; i < quantity; i++) {
totalResources.add(resource);
}
} else {
final UnitType type = (UnitType) next;
final int quantity = results.getInt(type);
final Collection<Unit> units = type.create(quantity, player);
totalUnits.addAll(units);
for (int i = 0; i < quantity; i++) {
totalUnitTypes.add(type);
}
}
}
final Collection<NamedAttachable> totalAll = new ArrayList<>();
totalAll.addAll(totalUnitTypes);
totalAll.addAll(totalResources);
// add changes for added units
if (!totalUnits.isEmpty()) {
final Change change = ChangeFactory.addUnits(player, totalUnits);
changes.add(change);
}
// add changes for spent resources
final String remaining = removeFromPlayer(costs, changes);
// add history event
final String transcriptText;
if (!totalUnits.isEmpty()) {
transcriptText = player.getName() + " buy " + MyFormatter.defaultNamedToTextList(totalAll, ", ", true) + "; " + remaining;
} else {
transcriptText = player.getName() + " buy nothing; " + remaining;
}
bridge.getHistoryWriter().startEvent(transcriptText, totalUnits);
// commit changes
bridge.addChange(changes);
return null;
}
use of games.strategy.engine.data.NamedAttachable in project triplea by triplea-game.
the class PlayerUnitsPanel method getUnitTypes.
/**
* Return all the unit types available for the given player. A unit type is
* available if the unit can be purchased or if a player has one on the map.
*/
private Collection<UnitType> getUnitTypes(final PlayerID player) {
Collection<UnitType> unitTypes = new LinkedHashSet<>();
final ProductionFrontier frontier = player.getProductionFrontier();
if (frontier != null) {
for (final ProductionRule rule : frontier) {
for (final NamedAttachable type : rule.getResults().keySet()) {
if (type instanceof UnitType) {
unitTypes.add((UnitType) type);
}
}
}
}
for (final Territory t : data.getMap()) {
for (final Unit u : t.getUnits()) {
if (u.getOwner().equals(player)) {
unitTypes.add(u.getType());
}
}
}
// Filter out anything like factories, or units that have no combat ability AND cannot be taken casualty
unitTypes = CollectionUtils.getMatches(unitTypes, Matches.unitTypeCanBeInBattle(!defender, isLand, player, 1, false, false, false));
return unitTypes;
}
Aggregations