use of games.strategy.triplea.delegate.dataObjects.MustMoveWithDetails in project triplea by triplea-game.
the class MovePanel method getTransportsToLoad.
/**
* Allow the user to select what transports to load.
* If null is returned, the move should be canceled.
*/
private Collection<Unit> getTransportsToLoad(final Route route, final Collection<Unit> unitsToLoad, final boolean disablePrompts) {
if (!route.isLoad()) {
return Collections.emptyList();
}
if (unitsToLoad.stream().anyMatch(Matches.unitIsAir())) {
return Collections.emptyList();
}
final Collection<Unit> endOwnedUnits = route.getEnd().getUnits().getUnits();
final PlayerID unitOwner = getUnitOwner(unitsToLoad);
final MustMoveWithDetails endMustMoveWith = MoveValidator.getMustMoveWith(route.getEnd(), endOwnedUnits, dependentUnits, getData(), unitOwner);
int minTransportCost = defaultMinTransportCost;
for (final Unit unit : unitsToLoad) {
minTransportCost = Math.min(minTransportCost, UnitAttachment.get(unit.getType()).getTransportCost());
}
final Predicate<Unit> candidateTransportsMatch = Matches.unitIsTransport().and(Matches.alliedUnit(unitOwner, getGameData()));
final List<Unit> candidateTransports = CollectionUtils.getMatches(endOwnedUnits, candidateTransportsMatch);
// remove transports that don't have enough capacity
final Iterator<Unit> transportIter = candidateTransports.iterator();
while (transportIter.hasNext()) {
final Unit transport = transportIter.next();
final int capacity = TransportTracker.getAvailableCapacity(transport);
if (capacity < minTransportCost) {
transportIter.remove();
}
}
// nothing to choose
if (candidateTransports.isEmpty()) {
return Collections.emptyList();
}
// sort transports in preferred load order
sortTransportsToLoad(candidateTransports, route);
final List<Unit> availableUnits = new ArrayList<>(unitsToLoad);
final IntegerMap<Unit> availableCapacityMap = new IntegerMap<>();
for (final Unit transport : candidateTransports) {
final int capacity = TransportTracker.getAvailableCapacity(transport);
availableCapacityMap.put(transport, capacity);
}
final Set<Unit> defaultSelections = new HashSet<>();
// Algorithm to choose defaultSelections (transports to load)
// We are trying to determine which transports are the best defaults to select for loading,
// and so we need a modified algorithm based strictly on candidateTransports order:
// - owned, capable transports are chosen first; attempt to fill them
// - allied, capable transports are chosen next; attempt to fill them
// - finally, incapable transports are chosen last (will generate errors)
// Note that if any allied transports qualify as defaults, we will always prompt with a
// UnitChooser later on so that it is obvious to the player.
boolean useAlliedTransports = false;
final Collection<Unit> capableTransports = new ArrayList<>(candidateTransports);
// only allow incapable transports for updateUnitsThatCanMoveOnRoute
// so that we can have a nice UI error shown if these transports
// are selected, since it may not be obvious
final Collection<Unit> incapableTransports = CollectionUtils.getMatches(capableTransports, Matches.transportCannotUnload(route.getEnd()));
capableTransports.removeAll(incapableTransports);
final Predicate<Unit> alliedMatch = transport -> !transport.getOwner().equals(unitOwner);
final Collection<Unit> alliedTransports = CollectionUtils.getMatches(capableTransports, alliedMatch);
capableTransports.removeAll(alliedTransports);
// First, load capable transports
final Map<Unit, Unit> unitsToCapableTransports = TransportUtils.mapTransportsToLoadUsingMinTransports(availableUnits, capableTransports);
for (final Unit unit : unitsToCapableTransports.keySet()) {
final Unit transport = unitsToCapableTransports.get(unit);
final int unitCost = UnitAttachment.get(unit.getType()).getTransportCost();
availableCapacityMap.add(transport, (-1 * unitCost));
defaultSelections.add(transport);
}
availableUnits.removeAll(unitsToCapableTransports.keySet());
// Next, load allied transports
final Map<Unit, Unit> unitsToAlliedTransports = TransportUtils.mapTransportsToLoadUsingMinTransports(availableUnits, alliedTransports);
for (final Unit unit : unitsToAlliedTransports.keySet()) {
final Unit transport = unitsToAlliedTransports.get(unit);
final int unitCost = UnitAttachment.get(unit.getType()).getTransportCost();
availableCapacityMap.add(transport, (-1 * unitCost));
defaultSelections.add(transport);
useAlliedTransports = true;
}
availableUnits.removeAll(unitsToAlliedTransports.keySet());
// are selected, since it may not be obvious
if (getSelectedEndpointTerritory() == null) {
final Map<Unit, Unit> unitsToIncapableTransports = TransportUtils.mapTransportsToLoadUsingMinTransports(availableUnits, incapableTransports);
for (final Unit unit : unitsToIncapableTransports.keySet()) {
final Unit transport = unitsToIncapableTransports.get(unit);
final int unitCost = UnitAttachment.get(unit.getType()).getTransportCost();
availableCapacityMap.add(transport, (-1 * unitCost));
defaultSelections.add(transport);
}
availableUnits.removeAll(unitsToIncapableTransports.keySet());
} else {
candidateTransports.removeAll(incapableTransports);
}
// return defaults if we aren't allowed to prompt
if (disablePrompts) {
return defaultSelections;
}
// force UnitChooser to pop up if we are choosing allied transports
if (!useAlliedTransports) {
if (candidateTransports.size() == 1) {
return candidateTransports;
}
// all the same type, dont ask unless we have more than 1 unit type
if (UnitSeperator.categorize(candidateTransports, endMustMoveWith.getMustMoveWith(), true, false).size() == 1 && unitsToLoad.size() == 1) {
return candidateTransports;
}
// Players will need to load incrementally in such cases.
if (defaultSelections.containsAll(candidateTransports)) {
return candidateTransports;
}
}
// the match criteria to ensure that chosen transports will match selected units
final Predicate<Collection<Unit>> transportsToLoadMatch = units -> {
final Collection<Unit> transports = CollectionUtils.getMatches(units, Matches.unitIsTransport());
// prevent too many transports from being selected
return (transports.size() <= Math.min(unitsToLoad.size(), candidateTransports.size()));
};
final UnitChooser chooser = new UnitChooser(candidateTransports, defaultSelections, endMustMoveWith.getMustMoveWith(), /* categorizeMovement */
true, /* categorizeTransportCost */
false, /* allowTwoHit */
false, getMap().getUiContext(), transportsToLoadMatch);
chooser.setTitle("What transports do you want to load");
final int option = JOptionPane.showOptionDialog(getTopLevelAncestor(), chooser, "What transports do you want to load", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
if (option != JOptionPane.OK_OPTION) {
return Collections.emptyList();
}
return chooser.getSelected(false);
}
Aggregations