use of games.strategy.triplea.util.UnitCategory in project triplea by triplea-game.
the class BattleDisplay method updateKilledUnits.
/**
* updates the panel content according to killed units for the player.
*
* @param killedUnits
* list of units killed
* @param playerId
* player kills belongs to
*/
private Collection<Unit> updateKilledUnits(final Collection<Unit> killedUnits, final PlayerID playerId) {
final JPanel casualtyPanel;
if (playerId.equals(defender)) {
casualtyPanel = casualtiesInstantPanelDefender;
} else {
casualtyPanel = casualtiesInstantPanelAttacker;
}
Map<Unit, Collection<Unit>> dependentsMap;
gameData.acquireReadLock();
try {
dependentsMap = BattleCalculator.getDependents(killedUnits);
} finally {
gameData.releaseReadLock();
}
final Collection<Unit> dependentUnitsReturned = new ArrayList<>();
for (Collection<Unit> dependentCollection : dependentsMap.values()) {
dependentUnitsReturned.addAll(dependentCollection);
}
for (final UnitCategory category : UnitSeperator.categorize(killedUnits, dependentsMap, false, false)) {
final JPanel panel = new JPanel();
JLabel unit = uiContext.createUnitImageJLabel(category.getType(), category.getOwner());
panel.add(unit);
panel.add(new JLabel("x " + category.getUnits().size()));
for (final UnitOwner owner : category.getDependents()) {
unit = uiContext.createUnitImageJLabel(owner.getType(), owner.getOwner());
panel.add(unit);
// TODO this size is of the transport collection size, not the transportED collection size.
panel.add(new JLabel("x " + category.getUnits().size()));
}
casualtyPanel.add(panel);
}
return dependentUnitsReturned;
}
use of games.strategy.triplea.util.UnitCategory in project triplea by triplea-game.
the class MovePanel method getUnitsToUnload.
/**
* Return the units that are to be unloaded for this route.
* If needed will ask the user what transports to unload.
* This is needed because the user needs to be able to select what transports to unload
* in the case where some transports have different movement, different
* units etc
*/
private Collection<Unit> getUnitsToUnload(final Route route, final Collection<Unit> unitsToUnload) {
final Collection<Unit> allUnits = getFirstSelectedTerritory().getUnits().getUnits();
final List<Unit> candidateUnits = CollectionUtils.getMatches(allUnits, getUnloadableMatch(route, unitsToUnload));
if (unitsToUnload.size() == candidateUnits.size()) {
return unitsToUnload;
}
final List<Unit> candidateTransports = CollectionUtils.getMatches(allUnits, Matches.unitIsTransportingSomeCategories(candidateUnits));
// Remove all incapable transports
final Collection<Unit> incapableTransports = CollectionUtils.getMatches(candidateTransports, Matches.transportCannotUnload(route.getEnd()));
candidateTransports.removeAll(incapableTransports);
if (candidateTransports.size() == 0) {
return Collections.emptyList();
}
// Just one transport, don't bother to ask
if (candidateTransports.size() == 1) {
return unitsToUnload;
}
// Are the transports all of the same type and if they are, then don't ask
final Collection<UnitCategory> categories = UnitSeperator.categorize(candidateTransports, mustMoveWithDetails.getMustMoveWith(), true, false);
if (categories.size() == 1) {
return unitsToUnload;
}
sortTransportsToUnload(candidateTransports, route);
// unitsToUnload are actually dependents, but need to select transports
final Set<Unit> defaultSelections = TransportUtils.findMinTransportsToUnload(unitsToUnload, candidateTransports);
// Match criteria to ensure that chosen transports will match selected units
final Predicate<Collection<Unit>> transportsToUnloadMatch = units -> {
final List<Unit> sortedTransports = CollectionUtils.getMatches(units, Matches.unitIsTransport());
final Collection<Unit> availableUnits = new ArrayList<>(unitsToUnload);
// track the changing capacities of the transports as we assign units
final IntegerMap<Unit> capacityMap = new IntegerMap<>();
for (final Unit transport : sortedTransports) {
final Collection<Unit> transporting = TripleAUnit.get(transport).getTransporting();
capacityMap.add(transport, TransportUtils.getTransportCost(transporting));
}
boolean hasChanged = false;
final Comparator<Unit> increasingCapacityComparator = UnitComparator.getIncreasingCapacityComparator(sortedTransports);
// the selected units amongst the current selection of chosen transports.
do {
hasChanged = false;
// Sort transports by increasing capacity
sortedTransports.sort(increasingCapacityComparator);
// Try to remove one unit from each transport, in succession
final Iterator<Unit> transportIter = sortedTransports.iterator();
while (transportIter.hasNext()) {
final Unit transport = transportIter.next();
final Collection<Unit> transporting = TripleAUnit.get(transport).getTransporting();
if (transporting == null) {
continue;
}
final Collection<UnitCategory> transCategories = UnitSeperator.categorize(transporting);
final Iterator<Unit> unitIter = availableUnits.iterator();
while (unitIter.hasNext()) {
final Unit unit = unitIter.next();
final Collection<UnitCategory> unitCategory = UnitSeperator.categorize(Collections.singleton(unit));
// Is one of the transported units of the same type we want to unload?
if (CollectionUtils.someIntersect(transCategories, unitCategory)) {
// Unload the unit, remove the transport from our list, and continue
hasChanged = true;
unitIter.remove();
transportIter.remove();
break;
}
}
}
// Repeat until there are no units left or no changes occur
} while (availableUnits.size() > 0 && hasChanged);
// If we haven't seen all of the transports (and removed them) then there are extra transports that don't fit
return (sortedTransports.size() == 0);
};
// Choosing what transports to unload
final UnitChooser chooser = new UnitChooser(candidateTransports, defaultSelections, mustMoveWithDetails.getMustMoveWith(), /* categorizeMovement */
true, /* categorizeTransportCost */
false, /* allowTwoHit */
false, getMap().getUiContext(), transportsToUnloadMatch);
chooser.setTitle("What transports do you want to unload");
final int option = JOptionPane.showOptionDialog(getTopLevelAncestor(), chooser, "What transports do you want to unload", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
if (option != JOptionPane.OK_OPTION) {
return Collections.emptyList();
}
final Collection<Unit> chosenTransports = CollectionUtils.getMatches(chooser.getSelected(), Matches.unitIsTransport());
final List<Unit> allUnitsInSelectedTransports = new ArrayList<>();
for (final Unit transport : chosenTransports) {
final Collection<Unit> transporting = TripleAUnit.get(transport).getTransporting();
if (transporting != null) {
allUnitsInSelectedTransports.addAll(transporting);
}
}
allUnitsInSelectedTransports.retainAll(candidateUnits);
sortUnitsToMove(allUnitsInSelectedTransports, route);
final List<Unit> selectedUnitsToUnload = new ArrayList<>();
final List<Unit> sortedTransports = new ArrayList<>(chosenTransports);
sortedTransports.sort(UnitComparator.getIncreasingCapacityComparator(sortedTransports));
final Collection<Unit> selectedUnits = new ArrayList<>(unitsToUnload);
// First pass: choose one unit from each selected transport
for (final Unit transport : sortedTransports) {
boolean hasChanged = false;
final Iterator<Unit> selectedIter = selectedUnits.iterator();
while (selectedIter.hasNext()) {
final Unit selected = selectedIter.next();
final Collection<Unit> transporting = TripleAUnit.get(transport).getTransporting();
for (final Unit candidate : transporting) {
if (selected.getType().equals(candidate.getType()) && selected.getOwner().equals(candidate.getOwner()) && selected.getHits() == candidate.getHits()) {
hasChanged = true;
selectedUnitsToUnload.add(candidate);
allUnitsInSelectedTransports.remove(candidate);
selectedIter.remove();
break;
}
}
if (hasChanged) {
break;
}
}
}
// Now fill remaining slots in preferred unit order
for (final Unit selected : selectedUnits) {
final Iterator<Unit> candidateIter = allUnitsInSelectedTransports.iterator();
while (candidateIter.hasNext()) {
final Unit candidate = candidateIter.next();
if (selected.getType().equals(candidate.getType()) && selected.getOwner().equals(candidate.getOwner()) && selected.getHits() == candidate.getHits()) {
selectedUnitsToUnload.add(candidate);
candidateIter.remove();
break;
}
}
}
return selectedUnitsToUnload;
}
use of games.strategy.triplea.util.UnitCategory in project triplea by triplea-game.
the class MovePanel method allowSpecificUnitSelection.
/**
* Allow the user to select specific units, if for example some units
* have different movement
* Units are sorted in preferred order, so units represents the default selections.
*/
private boolean allowSpecificUnitSelection(final Collection<Unit> units, final Route route, boolean mustQueryUser, final Predicate<Collection<Unit>> matchCriteria) {
final List<Unit> candidateUnits = getFirstSelectedTerritory().getUnits().getMatches(getMovableMatch(route, units));
if (!mustQueryUser) {
final Set<UnitCategory> categories = UnitSeperator.categorize(candidateUnits, mustMoveWithDetails.getMustMoveWith(), true, false);
for (final UnitCategory category1 : categories) {
// we cant move these, dont bother to check
if (category1.getMovement() == 0) {
continue;
}
for (final UnitCategory category2 : categories) {
// we cant move these, dont bother to check
if (category2.getMovement() == 0) {
continue;
}
// then the user has to refine his selection
if (category1 != category2 && category1.getType() == category2.getType() && !category1.equals(category2)) {
// if we are moving all the units from both categories, then nothing to choose
if (units.containsAll(category1.getUnits()) && units.containsAll(category2.getUnits())) {
continue;
}
// if we are moving some of the units from either category, then we need to stop
if (!CollectionUtils.intersection(category1.getUnits(), units).isEmpty() || !CollectionUtils.intersection(category2.getUnits(), units).isEmpty()) {
mustQueryUser = true;
}
}
}
}
}
if (mustQueryUser) {
final List<Unit> defaultSelections = new ArrayList<>(units.size());
if (route.isLoad()) {
final Collection<Unit> transportsToLoad = new ArrayList<>(getTransportsToLoad(route, units, false));
defaultSelections.addAll(TransportUtils.mapTransports(route, units, transportsToLoad).keySet());
} else {
defaultSelections.addAll(units);
}
// sort candidateUnits in preferred order
sortUnitsToMove(candidateUnits, route);
final UnitChooser chooser = new UnitChooser(candidateUnits, defaultSelections, mustMoveWithDetails.getMustMoveWith(), true, false, false, getMap().getUiContext(), matchCriteria);
final String text = "Select units to move from " + getFirstSelectedTerritory() + ".";
final int option = JOptionPane.showOptionDialog(getTopLevelAncestor(), chooser, text, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
if (option != JOptionPane.OK_OPTION) {
units.clear();
return false;
}
units.clear();
units.addAll(chooser.getSelected(false));
}
// add the dependent units
final List<Unit> unitsCopy = new ArrayList<>(units);
for (final Unit unit : unitsCopy) {
final Collection<Unit> forced = mustMoveWithDetails.getMustMoveWith().get(unit);
if (forced != null) {
// add dependent if necessary
for (final Unit dependent : forced) {
if (unitsCopy.indexOf(dependent) == -1) {
units.add(dependent);
}
}
}
}
return true;
}
use of games.strategy.triplea.util.UnitCategory in project triplea by triplea-game.
the class MapPanel method setMouseShadowUnits.
void setMouseShadowUnits(final Collection<Unit> units) {
if (units == null || units.isEmpty()) {
movementLeftForCurrentUnits = "";
mouseShadowImage = null;
SwingUtilities.invokeLater(this::repaint);
return;
}
final Tuple<Integer, Integer> movementLeft = TripleAUnit.getMinAndMaxMovementLeft(CollectionUtils.getMatches(units, Matches.unitIsBeingTransported().negate()));
movementLeftForCurrentUnits = movementLeft.getFirst() + (movementLeft.getSecond() > movementLeft.getFirst() ? "+" : "");
gameData.acquireReadLock();
try {
movementFuelCost = Route.getMovementFuelCostCharge(units, routeDescription.getRoute(), units.iterator().next().getOwner(), gameData);
} finally {
gameData.releaseReadLock();
}
final Set<UnitCategory> categories = UnitSeperator.categorize(units);
final int iconWidth = uiContext.getUnitImageFactory().getUnitImageWidth();
final int horizontalSpace = 5;
final BufferedImage img = Util.createImage(categories.size() * (horizontalSpace + iconWidth), uiContext.getUnitImageFactory().getUnitImageHeight(), true);
final Graphics2D g = img.createGraphics();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f));
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
final Rectangle bounds = new Rectangle(0, 0, 0, 0);
getData().acquireReadLock();
try {
int i = 0;
for (final UnitCategory category : categories) {
final Point place = new Point(i * (iconWidth + horizontalSpace), 0);
final UnitsDrawer drawer = new UnitsDrawer(category.getUnits().size(), category.getType().getName(), category.getOwner().getName(), place, category.getDamaged(), category.getBombingDamage(), category.getDisabled(), false, "", uiContext);
drawer.draw(bounds, gameData, g, uiContext.getMapData(), null, null);
i++;
}
} finally {
getData().releaseReadLock();
}
mouseShadowImage = img;
SwingUtilities.invokeLater(this::repaint);
g.dispose();
}
use of games.strategy.triplea.util.UnitCategory in project triplea by triplea-game.
the class AbstractUndoableMovesPanel method createComponentForMove.
private JComponent createComponentForMove(final AbstractUndoableMove move) {
final Box unitsBox = new Box(BoxLayout.X_AXIS);
unitsBox.add(new JLabel((move.getIndex() + 1) + ") "));
final Collection<UnitCategory> unitCategories = UnitSeperator.categorize(move.getUnits());
final Dimension buttonSize = new Dimension(80, 22);
for (final UnitCategory category : unitCategories) {
final Optional<ImageIcon> icon = movePanel.getMap().getUiContext().getUnitImageFactory().getIcon(category.getType(), category.getOwner(), category.hasDamageOrBombingUnitDamage(), category.getDisabled());
if (icon.isPresent()) {
final JLabel label = new JLabel("x" + category.getUnits().size() + " ", icon.get(), SwingConstants.LEFT);
unitsBox.add(label);
}
}
unitsBox.add(Box.createHorizontalGlue());
final JLabel text = new JLabel(move.getMoveLabel());
final Box textBox = new Box(BoxLayout.X_AXIS);
textBox.add(text);
textBox.add(Box.createHorizontalGlue());
final JButton cancelButton = new JButton(new UndoMoveActionListener(move.getIndex()));
setSize(buttonSize, cancelButton);
final JButton viewbutton = new JButton(new ViewAction(move));
setSize(buttonSize, viewbutton);
final Box buttonsBox = new Box(BoxLayout.X_AXIS);
buttonsBox.add(viewbutton);
buttonsBox.add(cancelButton);
buttonsBox.add(Box.createHorizontalGlue());
final Box containerBox = new Box(BoxLayout.Y_AXIS);
containerBox.add(unitsBox);
containerBox.add(textBox);
containerBox.add(buttonsBox);
containerBox.add(new JLabel(" "));
return containerBox;
}
Aggregations