use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class UnitInformation method saveToFile.
void saveToFile(final PrintGenerationData printData, final Map<UnitType, UnitAttachment> unitInfoMap) {
data = printData.getData();
printData.getOutDir().mkdir();
final File outFile = new File(printData.getOutDir(), "General Information.csv");
try (Writer unitInformation = Files.newBufferedWriter(outFile.toPath(), StandardCharsets.UTF_8)) {
for (int i = 0; i < 8; i++) {
unitInformation.write(",");
}
unitInformation.write("Unit Information");
for (int i = 10; i < 20; i++) {
unitInformation.write(",");
}
unitInformation.write("\r\n");
unitInformation.write("Unit,Cost,Movement,Attack,Defense,CanBlitz,Artillery?,ArtillerySupportable?" + ",Can Produce Units?,Marine?,Transport Cost,AA Gun?,Air Unit?,Strategic Bomber?,Carrier Cost," + "Sea Unit?,Hit Points?,Transport Capacity,Carrier Capacity,Submarine?,Destroyer?");
unitInformation.write("\r\n");
for (final Entry<UnitType, UnitAttachment> entry : unitInfoMap.entrySet()) {
final UnitType currentType = entry.getKey();
final UnitAttachment currentAttachment = entry.getValue();
if (currentType.getName().equals(Constants.UNIT_TYPE_AAGUN)) {
unitInformation.write(currentType.getName() + ",");
} else {
unitInformation.write(capitalizeFirst(currentType.getName()) + ",");
}
unitInformation.write(getCostInformation(currentType) + ",");
unitInformation.write(currentAttachment.getMovement(PlayerID.NULL_PLAYERID) + "," + currentAttachment.getAttack(PlayerID.NULL_PLAYERID) + "," + currentAttachment.getDefense(PlayerID.NULL_PLAYERID) + "," + (!currentAttachment.getCanBlitz(PlayerID.NULL_PLAYERID) ? "-" : "true") + "," + (!currentAttachment.getArtillery() ? "-" : "true") + "," + (!currentAttachment.getArtillerySupportable() ? "-" : "true") + "," + (!currentAttachment.getCanProduceUnits() ? "-" : "true") + "," + (currentAttachment.getIsMarine() == 0 ? "-" : currentAttachment.getIsMarine()) + "," + (currentAttachment.getTransportCost() == -1 ? "-" : currentAttachment.getTransportCost()) + "," + (!Matches.unitTypeIsAaForAnything().test(currentType) ? "-" : "true") + "," + (!currentAttachment.getIsAir() ? "-" : "true") + "," + (!currentAttachment.getIsStrategicBomber() ? "-" : "true") + "," + (currentAttachment.getCarrierCost() == -1 ? "-" : currentAttachment.getCarrierCost()) + "," + (!currentAttachment.getIsSea() ? "-" : "true") + "," + (currentAttachment.getHitPoints()) + "," + (currentAttachment.getTransportCapacity() == -1 ? "-" : currentAttachment.getTransportCapacity()) + "," + (currentAttachment.getCarrierCapacity() == -1 ? "-" : currentAttachment.getCarrierCapacity()) + "," + (!currentAttachment.getIsSub() ? "-" : "true") + "," + (!currentAttachment.getIsDestroyer() ? "-" : "true"));
unitInformation.write("\r\n");
}
unitInformation.write("\r\n");
} catch (final IOException e) {
ClientLogger.logError("There was an error while trying to save File " + outFile.toString(), e);
}
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class ExportMenu method createAndSaveStats.
private void createAndSaveStats(final boolean showPhaseStats) {
final ExtendedStats statPanel = new ExtendedStats(gameData, uiContext);
final JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
final File rootDir = new File(SystemProperties.getUserDir());
final int currentRound = gameData.getCurrentRound();
String defaultFileName = "stats_" + dateTimeFormatter.format(LocalDateTime.now()) + "_" + gameData.getGameName() + "_round_" + currentRound + (showPhaseStats ? "_full" : "_short");
defaultFileName = FileNameUtils.removeIllegalCharacters(defaultFileName);
defaultFileName = defaultFileName + ".csv";
chooser.setSelectedFile(new File(rootDir, defaultFileName));
if (chooser.showSaveDialog(frame) != JOptionPane.OK_OPTION) {
return;
}
final StringBuilder text = new StringBuilder(1000);
try {
gameData.acquireReadLock();
final GameData clone = GameDataUtils.cloneGameData(gameData);
final IStat[] stats = statPanel.getStats();
// extended stats covers stuff that doesn't show up in the game stats menu bar, like custom resources or tech
// tokens or # techs, etc.
final IStat[] statsExtended = statPanel.getStatsExtended(gameData);
final String[] alliances = statPanel.getAlliances().toArray(new String[0]);
final PlayerID[] players = statPanel.getPlayers().toArray(new PlayerID[0]);
// its important here to translate the player objects into our game data
// the players for the stat panel are only relevant with respect to
// the game data they belong to
Arrays.setAll(players, i -> clone.getPlayerList().getPlayerId(players[i].getName()));
text.append(defaultFileName).append(",");
text.append("\n");
text.append("TripleA Engine Version: ,");
text.append(ClientContext.engineVersion()).append(",");
text.append("\n");
text.append("Game Name: ,");
text.append(gameData.getGameName()).append(",");
text.append("\n");
text.append("Game Version: ,");
text.append(gameData.getGameVersion()).append(",");
text.append("\n");
text.append("\n");
text.append("Current Round: ,");
text.append(currentRound).append(",");
text.append("\n");
text.append("Number of Players: ,");
text.append(statPanel.getPlayers().size()).append(",");
text.append("\n");
text.append("Number of Alliances: ,");
text.append(statPanel.getAlliances().size()).append(",");
text.append("\n");
text.append("\n");
text.append("Turn Order: ,");
text.append("\n");
final List<PlayerID> playerOrderList = new ArrayList<>(gameData.getPlayerList().getPlayers());
playerOrderList.sort(new PlayerOrderComparator(gameData));
final Set<PlayerID> playerOrderSetNoDuplicates = new LinkedHashSet<>(playerOrderList);
for (final PlayerID currentPlayerId : playerOrderSetNoDuplicates) {
text.append(currentPlayerId.getName()).append(",");
final Collection<String> allianceNames = gameData.getAllianceTracker().getAlliancesPlayerIsIn(currentPlayerId);
for (final String allianceName : allianceNames) {
text.append(allianceName).append(",");
}
text.append("\n");
}
text.append("\n");
text.append("Winners: ,");
final EndRoundDelegate delegateEndRound = (EndRoundDelegate) gameData.getDelegateList().getDelegate("endRound");
if (delegateEndRound != null && delegateEndRound.getWinners() != null) {
for (final PlayerID p : delegateEndRound.getWinners()) {
text.append(p.getName()).append(",");
}
} else {
text.append("none yet; game not over,");
}
text.append("\n");
text.append("\n");
text.append("Resource Chart: ,");
text.append("\n");
for (final Resource resource : gameData.getResourceList().getResources()) {
text.append(resource.getName()).append(",");
text.append("\n");
}
// if short, we won't both showing production and unit info
if (showPhaseStats) {
text.append("\n");
text.append("Production Rules: ,");
text.append("\n");
text.append("Name,Result,Quantity,Cost,Resource,\n");
final Collection<ProductionRule> purchaseOptions = gameData.getProductionRuleList().getProductionRules();
for (final ProductionRule pr : purchaseOptions) {
String costString = pr.toStringCosts().replaceAll("; ", ",");
costString = costString.replaceAll(" ", ",");
text.append(pr.getName()).append(",").append(pr.getResults().keySet().iterator().next().getName()).append(",").append(pr.getResults().getInt(pr.getResults().keySet().iterator().next())).append(",").append(costString).append(",");
text.append("\n");
}
text.append("\n");
text.append("Unit Types: ,");
text.append("\n");
text.append("Name,Listed Abilities\n");
for (final UnitType unitType : gameData.getUnitTypeList()) {
final UnitAttachment ua = UnitAttachment.get(unitType);
if (ua == null) {
continue;
}
String toModify = ua.allUnitStatsForExporter();
toModify = toModify.replaceFirst("UnitType called ", "").replaceFirst(" with:", "").replaceAll("games.strategy.engine.data.", "").replaceAll("\n", ";").replaceAll(",", ";");
toModify = toModify.replaceAll(" ", ",");
toModify = toModify.replaceAll(", ", ",").replaceAll(" ,", ",");
text.append(toModify);
text.append("\n");
}
}
text.append("\n");
text.append((showPhaseStats ? "Full Stats (includes each phase that had activity)," : "Short Stats (only shows first phase with activity per player per round),"));
text.append("\n");
text.append("Turn Stats: ,");
text.append("\n");
text.append("Round,Player Turn,Phase Name,");
for (final IStat stat : stats) {
for (final PlayerID player : players) {
text.append(stat.getName()).append(" ");
text.append(player.getName());
text.append(",");
}
for (final String alliance : alliances) {
text.append(stat.getName()).append(" ");
text.append(alliance);
text.append(",");
}
}
for (final IStat element : statsExtended) {
for (final PlayerID player : players) {
text.append(element.getName()).append(" ");
text.append(player.getName());
text.append(",");
}
for (final String alliance : alliances) {
text.append(element.getName()).append(" ");
text.append(alliance);
text.append(",");
}
}
text.append("\n");
clone.getHistory().gotoNode(clone.getHistory().getLastNode());
@SuppressWarnings("unchecked") final Enumeration<TreeNode> nodes = ((DefaultMutableTreeNode) clone.getHistory().getRoot()).preorderEnumeration();
PlayerID currentPlayer = null;
int round = 0;
while (nodes.hasMoreElements()) {
// we want to export on change of turn
final HistoryNode element = (HistoryNode) nodes.nextElement();
if (element instanceof Round) {
round++;
}
if (!(element instanceof Step)) {
continue;
}
final Step step = (Step) element;
if (step.getPlayerId() == null || step.getPlayerId().isNull()) {
continue;
}
// this is to stop from having multiple entries for each players turn.
if (!showPhaseStats) {
if (step.getPlayerId() == currentPlayer) {
continue;
}
}
currentPlayer = step.getPlayerId();
clone.getHistory().gotoNode(element);
final String playerName = step.getPlayerId() == null ? "" : step.getPlayerId().getName() + ": ";
String stepName = step.getStepName();
// copied directly from TripleAPlayer, will probably have to be updated in the future if more delegates are made
if (stepName.endsWith("Bid")) {
stepName = "Bid";
} else if (stepName.endsWith("Tech")) {
stepName = "Tech";
} else if (stepName.endsWith("TechActivation")) {
stepName = "TechActivation";
} else if (stepName.endsWith("Purchase")) {
stepName = "Purchase";
} else if (stepName.endsWith("NonCombatMove")) {
stepName = "NonCombatMove";
} else if (stepName.endsWith("Move")) {
stepName = "Move";
} else if (stepName.endsWith("Battle")) {
stepName = "Battle";
} else if (stepName.endsWith("BidPlace")) {
stepName = "BidPlace";
} else if (stepName.endsWith("Place")) {
stepName = "Place";
} else if (stepName.endsWith("Politics")) {
stepName = "Politics";
} else if (stepName.endsWith("EndTurn")) {
stepName = "EndTurn";
} else {
stepName = "";
}
text.append(round).append(",").append(playerName).append(",").append(stepName).append(",");
for (final IStat stat : stats) {
for (final PlayerID player : players) {
text.append(stat.getFormatter().format(stat.getValue(player, clone)));
text.append(",");
}
for (final String alliance : alliances) {
text.append(stat.getFormatter().format(stat.getValue(alliance, clone)));
text.append(",");
}
}
for (final IStat element2 : statsExtended) {
for (final PlayerID player : players) {
text.append(element2.getFormatter().format(element2.getValue(player, clone)));
text.append(",");
}
for (final String alliance : alliances) {
text.append(element2.getFormatter().format(element2.getValue(alliance, clone)));
text.append(",");
}
}
text.append("\n");
}
} finally {
gameData.releaseReadLock();
}
try (Writer writer = Files.newBufferedWriter(chooser.getSelectedFile().toPath(), StandardCharsets.UTF_8)) {
writer.write(text.toString());
} catch (final IOException e1) {
ClientLogger.logQuietly("Failed to write stats: " + chooser.getSelectedFile().getAbsolutePath(), e1);
}
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class MovePerformer method markMovementChange.
private Change markMovementChange(final Collection<Unit> units, final Route route, final PlayerID id) {
final GameData data = bridge.getData();
final CompositeChange change = new CompositeChange();
final Territory routeStart = route.getStart();
final TerritoryAttachment taRouteStart = TerritoryAttachment.get(routeStart);
final Territory routeEnd = route.getEnd();
TerritoryAttachment taRouteEnd = null;
if (routeEnd != null) {
taRouteEnd = TerritoryAttachment.get(routeEnd);
}
// only units owned by us need to be marked
final RelationshipTracker relationshipTracker = data.getRelationshipTracker();
for (final Unit baseUnit : CollectionUtils.getMatches(units, Matches.unitIsOwnedBy(id))) {
final TripleAUnit unit = (TripleAUnit) baseUnit;
int moved = route.getMovementCost(unit);
final UnitAttachment ua = UnitAttachment.get(unit.getType());
if (ua.getIsAir()) {
if (taRouteStart != null && taRouteStart.getAirBase() && relationshipTracker.isAllied(route.getStart().getOwner(), unit.getOwner())) {
moved--;
}
if (taRouteEnd != null && taRouteEnd.getAirBase() && relationshipTracker.isAllied(route.getEnd().getOwner(), unit.getOwner())) {
moved--;
}
}
change.add(ChangeFactory.unitPropertyChange(unit, moved + unit.getAlreadyMoved(), TripleAUnit.ALREADY_MOVED));
}
// if entered a non blitzed conquered territory, mark with 0 movement
if (GameStepPropertiesHelper.isCombatMove(data) && (MoveDelegate.getEmptyNeutral(route).size() != 0 || hasConqueredNonBlitzed(route))) {
for (final Unit unit : CollectionUtils.getMatches(units, Matches.unitIsLand())) {
change.add(ChangeFactory.markNoMovementChange(Collections.singleton(unit)));
}
}
if (routeEnd != null && Properties.getSubsCanEndNonCombatMoveWithEnemies(data) && GameStepPropertiesHelper.isNonCombatMove(data, false) && routeEnd.getUnits().anyMatch(Matches.unitIsEnemyOf(data, id).and(Matches.unitIsDestroyer()))) {
// if there is an enemy destroyer there
for (final Unit unit : CollectionUtils.getMatches(units, Matches.unitIsSub().and(Matches.unitIsAir().negate()))) {
change.add(ChangeFactory.markNoMovementChange(Collections.singleton(unit)));
}
}
return change;
}
use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.
the class MustFightBattle method addAttackChange.
@Override
public Change addAttackChange(final Route route, final Collection<Unit> units, final HashMap<Unit, HashSet<Unit>> targets) {
final CompositeChange change = new CompositeChange();
// Filter out allied units if WW2V2
final Predicate<Unit> ownedBy = Matches.unitIsOwnedBy(m_attacker);
final Collection<Unit> attackingUnits = isWW2V2() ? CollectionUtils.getMatches(units, ownedBy) : units;
final Territory attackingFrom = route.getTerritoryBeforeEnd();
m_attackingFrom.add(attackingFrom);
m_attackingUnits.addAll(attackingUnits);
m_attackingFromMap.computeIfAbsent(attackingFrom, k -> new ArrayList<>());
final Collection<Unit> attackingFromMapUnits = m_attackingFromMap.get(attackingFrom);
attackingFromMapUnits.addAll(attackingUnits);
// are we amphibious
if (route.getStart().isWater() && route.getEnd() != null && !route.getEnd().isWater() && attackingUnits.stream().anyMatch(Matches.unitIsLand())) {
getAmphibiousAttackTerritories().add(route.getTerritoryBeforeEnd());
m_amphibiousLandAttackers.addAll(CollectionUtils.getMatches(attackingUnits, Matches.unitIsLand()));
m_isAmphibious = true;
}
final Map<Unit, Collection<Unit>> dependencies = TransportTracker.transporting(units);
if (!isAlliedAirIndependent()) {
dependencies.putAll(MoveValidator.carrierMustMoveWith(units, units, m_data, m_attacker));
for (final Unit carrier : dependencies.keySet()) {
final UnitAttachment ua = UnitAttachment.get(carrier.getType());
if (ua.getCarrierCapacity() == -1) {
continue;
}
final Collection<Unit> fighters = dependencies.get(carrier);
// Dependencies count both land and air units. Land units could be allied or owned, while air is just allied
// since owned already launched at beginning of turn
fighters.retainAll(CollectionUtils.getMatches(fighters, Matches.unitIsAir()));
for (final Unit fighter : fighters) {
// Set transportedBy for fighter
change.add(ChangeFactory.unitPropertyChange(fighter, carrier, TripleAUnit.TRANSPORTED_BY));
}
// remove transported fighters from battle display
m_attackingUnits.removeAll(fighters);
}
}
addDependentUnits(dependencies);
// mark units with no movement for all but air
Collection<Unit> nonAir = CollectionUtils.getMatches(attackingUnits, Matches.unitIsNotAir());
// so restrict non air to remove land units
if (m_battleSite.isWater()) {
nonAir = CollectionUtils.getMatches(nonAir, Matches.unitIsNotLand());
}
// If attacker stops in an occupied territory, movement stops (battle is optional)
if (MoveValidator.onlyIgnoredUnitsOnPath(route, m_attacker, m_data, false)) {
return change;
}
change.add(ChangeFactory.markNoMovementChange(nonAir));
return change;
}
use of games.strategy.triplea.attachments.UnitAttachment 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;
}
Aggregations