Search in sources :

Example 11 with UnitAttachment

use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.

the class MoveValidator method getCanCarry.

private static Collection<Unit> getCanCarry(final Unit carrier, final Collection<Unit> selectFrom, final PlayerID playerWhoIsDoingTheMovement, final GameData data) {
    final UnitAttachment ua = UnitAttachment.get(carrier.getType());
    final Collection<Unit> canCarry = new ArrayList<>();
    int available = ua.getCarrierCapacity();
    final TripleAUnit taCarrier = (TripleAUnit) carrier;
    for (final Unit plane : selectFrom) {
        final TripleAUnit taPlane = (TripleAUnit) plane;
        final UnitAttachment planeAttachment = UnitAttachment.get(plane.getType());
        final int cost = planeAttachment.getCarrierCost();
        if (available >= cost) {
            // this is to test if they started in the same sea zone or not, and its not a very good way of testing it.
            if ((taCarrier.getAlreadyMoved() == taPlane.getAlreadyMoved()) || (Matches.unitHasNotMoved().test(plane) && Matches.unitHasNotMoved().test(carrier)) || (Matches.unitIsOwnedBy(playerWhoIsDoingTheMovement).negate().test(plane) && Matches.alliedUnit(playerWhoIsDoingTheMovement, data).test(plane))) {
                available -= cost;
                canCarry.add(plane);
            }
        }
        if (available == 0) {
            break;
        }
    }
    return canCarry;
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) TripleAUnit(games.strategy.triplea.TripleAUnit)

Example 12 with UnitAttachment

use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.

the class MoveValidator method validateTransport.

private static MoveValidationResult validateTransport(final boolean isNonCombat, final GameData data, final List<UndoableMove> undoableMoves, final Collection<Unit> units, final Route route, final PlayerID player, final Collection<Unit> transportsToLoad, final MoveValidationResult result) {
    final boolean isEditMode = getEditMode(data);
    if (!units.isEmpty() && units.stream().allMatch(Matches.unitIsAir())) {
        return result;
    }
    if (!route.hasWater()) {
        return result;
    }
    // If there are non-sea transports return
    final boolean seaOrNoTransportsPresent = transportsToLoad.isEmpty() || transportsToLoad.stream().anyMatch(Matches.unitIsSea().and(Matches.unitCanTransport()));
    if (!seaOrNoTransportsPresent) {
        return result;
    }
    final Territory routeEnd = route.getEnd();
    final Territory routeStart = route.getStart();
    // if unloading make sure length of route is only 1
    if (!isEditMode && route.isUnload()) {
        if (route.hasMoreThenOneStep()) {
            return result.setErrorReturnResult("Unloading units must stop where they are unloaded");
        }
        for (final Unit unit : TransportTracker.getUnitsLoadedOnAlliedTransportsThisTurn(units)) {
            result.addDisallowedUnit(CANNOT_LOAD_AND_UNLOAD_AN_ALLIED_TRANSPORT_IN_THE_SAME_ROUND, unit);
        }
        final Collection<Unit> transports = TransportUtils.mapTransports(route, units, null).values();
        final boolean isScramblingOrKamikazeAttacksEnabled = Properties.getScrambleRulesInEffect(data) || Properties.getUseKamikazeSuicideAttacks(data);
        final boolean submarinesPreventUnescortedAmphibAssaults = Properties.getSubmarinesPreventUnescortedAmphibiousAssaults(data);
        final Predicate<Unit> enemySubmarineMatch = Matches.unitIsEnemyOf(data, player).and(Matches.unitIsSub());
        final Predicate<Unit> ownedSeaNonTransportMatch = Matches.unitIsOwnedBy(player).and(Matches.unitIsSea()).and(Matches.unitIsNotTransportButCouldBeCombatTransport());
        for (final Unit transport : transports) {
            if (!isNonCombat && route.numberOfStepsIncludingStart() == 2) {
                if (Matches.territoryHasEnemyUnits(player, data).test(routeEnd) || Matches.isTerritoryEnemyAndNotUnownedWater(player, data).test(routeEnd)) {
                    // this is an amphibious assault
                    if (submarinesPreventUnescortedAmphibAssaults && !Matches.territoryHasUnitsThatMatch(ownedSeaNonTransportMatch).test(routeStart) && Matches.territoryHasUnitsThatMatch(enemySubmarineMatch).test(routeStart)) {
                        // stops our unloading for amphibious assault
                        for (final Unit unit : TransportTracker.transporting(transport)) {
                            result.addDisallowedUnit(ENEMY_SUBMARINE_PREVENTING_UNESCORTED_AMPHIBIOUS_ASSAULT_LANDING, unit);
                        }
                    }
                } else if (!AbstractMoveDelegate.getBattleTracker(data).wasConquered(routeEnd)) {
                    // this is an unload to a friendly territory
                    if (isScramblingOrKamikazeAttacksEnabled || !Matches.territoryIsEmptyOfCombatUnits(data, player).test(routeStart)) {
                        // TODO: should we use the battle tracker for this instead?
                        for (final Unit unit : TransportTracker.transporting(transport)) {
                            result.addDisallowedUnit(TRANSPORT_MAY_NOT_UNLOAD_TO_FRIENDLY_TERRITORIES_UNTIL_AFTER_COMBAT_IS_RESOLVED, unit);
                        }
                    }
                }
            }
            // in which they perform their actions. check whether transport has already unloaded
            if (TransportTracker.hasTransportUnloadedInPreviousPhase(transport)) {
                for (final Unit unit : TransportTracker.transporting(transport)) {
                    result.addDisallowedUnit(TRANSPORT_HAS_ALREADY_UNLOADED_UNITS_IN_A_PREVIOUS_PHASE, unit);
                }
            // check whether transport is restricted to another territory
            } else if (TransportTracker.isTransportUnloadRestrictedToAnotherTerritory(transport, route.getEnd())) {
                final Territory alreadyUnloadedTo = getTerritoryTransportHasUnloadedTo(undoableMoves, transport);
                for (final Unit unit : TransportTracker.transporting(transport)) {
                    result.addDisallowedUnit(TRANSPORT_HAS_ALREADY_UNLOADED_UNITS_TO + alreadyUnloadedTo.getName(), unit);
                }
            // Check if the transport has already loaded after being in combat
            } else if (TransportTracker.isTransportUnloadRestrictedInNonCombat(transport)) {
                for (final Unit unit : TransportTracker.transporting(transport)) {
                    result.addDisallowedUnit(TRANSPORT_CANNOT_LOAD_AND_UNLOAD_AFTER_COMBAT, unit);
                }
            }
        }
    }
    // if we are land make sure no water in route except for transport situations
    final Collection<Unit> land = CollectionUtils.getMatches(units, Matches.unitIsLand());
    final Collection<Unit> landAndAir = CollectionUtils.getMatches(units, Matches.unitIsLand().or(Matches.unitIsAir()));
    // make sure we can be transported
    final Predicate<Unit> cantBeTransported = Matches.unitCanBeTransported().negate();
    for (final Unit unit : CollectionUtils.getMatches(land, cantBeTransported)) {
        result.addDisallowedUnit("Not all units can be transported", unit);
    }
    // make sure that the only the first or last territory is land don't want situation where they go sea land sea
    if (!isEditMode && route.hasLand() && !(route.getStart().isWater() || route.getEnd().isWater())) {
        // carried by the air and that the air has enough capacity
        if (nonParatroopersPresent(player, landAndAir)) {
            return result.setErrorReturnResult("Invalid move, only start or end can be land when route has water.");
        }
    }
    // TODO handle this
    if (!isEditMode && !route.getEnd().isWater() && !route.getStart().isWater() && nonParatroopersPresent(player, landAndAir)) {
        return result.setErrorReturnResult("Must stop units at a transport on route");
    }
    if (route.getEnd().isWater() && route.getStart().isWater()) {
        // make sure units and transports stick together
        for (final Unit unit : units) {
            final UnitAttachment ua = UnitAttachment.get(unit.getType());
            // make sure transports dont leave their units behind
            if (ua.getTransportCapacity() != -1) {
                final Collection<Unit> holding = TransportTracker.transporting(unit);
                if (!units.containsAll(holding)) {
                    result.addDisallowedUnit("Transports cannot leave their units", unit);
                }
            }
            // make sure units dont leave their transports behind
            if (ua.getTransportCost() != -1) {
                final Unit transport = TransportTracker.transportedBy(unit);
                if (transport != null && !units.contains(transport)) {
                    result.addDisallowedUnit("Unit must stay with its transport while moving", unit);
                }
            }
        }
    }
    if (route.isLoad()) {
        if (!isEditMode && !route.hasExactlyOneStep() && nonParatroopersPresent(player, landAndAir)) {
            return result.setErrorReturnResult("Units cannot move before loading onto transports");
        }
        final Predicate<Unit> enemyNonSubmerged = Matches.enemyUnit(player, data).and(Matches.unitIsSubmerged().negate());
        if (!Properties.getUnitsCanLoadInHostileSeaZones(data) && route.getEnd().getUnits().anyMatch(enemyNonSubmerged) && nonParatroopersPresent(player, landAndAir) && !onlyIgnoredUnitsOnPath(route, player, data, false) && !AbstractMoveDelegate.getBattleTracker(data).didAllThesePlayersJustGoToWarThisTurn(player, route.getEnd().getUnits().getUnits(), data)) {
            return result.setErrorReturnResult("Cannot load when enemy sea units are present");
        }
        final Map<Unit, Unit> unitsToTransports = TransportUtils.mapTransports(route, land, transportsToLoad);
        if (!isEditMode) {
            for (final Unit baseUnit : land) {
                final TripleAUnit unit = (TripleAUnit) baseUnit;
                if (Matches.unitHasMoved().test(unit)) {
                    result.addDisallowedUnit("Units cannot move before loading onto transports", unit);
                }
                final Unit transport = unitsToTransports.get(unit);
                if (transport == null) {
                    continue;
                }
                if (TransportTracker.hasTransportUnloadedInPreviousPhase(transport)) {
                    result.addDisallowedUnit(TRANSPORT_HAS_ALREADY_UNLOADED_UNITS_IN_A_PREVIOUS_PHASE, unit);
                } else if (TransportTracker.isTransportUnloadRestrictedToAnotherTerritory(transport, route.getEnd())) {
                    Territory alreadyUnloadedTo = getTerritoryTransportHasUnloadedTo(undoableMoves, transport);
                    for (final Unit transportToLoad : transportsToLoad) {
                        final TripleAUnit trn = (TripleAUnit) transportToLoad;
                        if (!TransportTracker.isTransportUnloadRestrictedToAnotherTerritory(trn, route.getEnd())) {
                            final UnitAttachment ua = UnitAttachment.get(unit.getType());
                            if (TransportTracker.getAvailableCapacity(trn) >= ua.getTransportCost()) {
                                alreadyUnloadedTo = null;
                                break;
                            }
                        }
                    }
                    if (alreadyUnloadedTo != null) {
                        result.addDisallowedUnit(TRANSPORT_HAS_ALREADY_UNLOADED_UNITS_TO + alreadyUnloadedTo.getName(), unit);
                    }
                }
            }
        }
        if (!unitsToTransports.keySet().containsAll(land)) {
            // some units didn't get mapped to a transport
            final Collection<UnitCategory> unitsToLoadCategories = UnitSeperator.categorize(land);
            if (unitsToTransports.size() == 0 || unitsToLoadCategories.size() == 1) {
                // set all unmapped units as disallowed if there are no transports or only one unit category
                for (final Unit unit : land) {
                    if (unitsToTransports.containsKey(unit)) {
                        continue;
                    }
                    final UnitAttachment ua = UnitAttachment.get(unit.getType());
                    if (ua.getTransportCost() != -1) {
                        result.addDisallowedUnit("Not enough transports", unit);
                    }
                }
            } else {
                // set all units as unresolved if there is at least one transport and mixed unit categories
                for (final Unit unit : land) {
                    final UnitAttachment ua = UnitAttachment.get(unit.getType());
                    if (ua.getTransportCost() != -1) {
                        result.addUnresolvedUnit("Not enough transports", unit);
                    }
                }
            }
        }
    }
    return result;
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) Territory(games.strategy.engine.data.Territory) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) TripleAUnit(games.strategy.triplea.TripleAUnit) UnitCategory(games.strategy.triplea.util.UnitCategory)

Example 13 with UnitAttachment

use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.

the class MustFightBattle method sortAmphib.

/**
 * In an amphibious assault, sort on who is unloading from transports first as this will allow the marines with higher
 * scores to get killed last.
 */
private void sortAmphib(final List<Unit> units) {
    final Comparator<Unit> decreasingMovement = UnitComparator.getLowestToHighestMovementComparator();
    units.sort(Comparator.comparing(Unit::getType, Comparator.comparing(UnitType::getName)).thenComparing((u1, u2) -> {
        final UnitAttachment ua = UnitAttachment.get(u1.getType());
        final UnitAttachment ua2 = UnitAttachment.get(u2.getType());
        if (ua.getIsMarine() != 0 && ua2.getIsMarine() != 0) {
            return compareAccordingToAmphibious(u1, u2);
        }
        return 0;
    }).thenComparing(decreasingMovement));
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) UnitType(games.strategy.engine.data.UnitType) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit)

Example 14 with UnitAttachment

use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.

the class EndTurnDelegate method createUnits.

private String createUnits(final IDelegateBridge bridge) {
    final StringBuilder endTurnReport = new StringBuilder();
    final GameData data = getData();
    final PlayerID player = data.getSequence().getStep().getPlayerId();
    final Predicate<Unit> myCreatorsMatch = Matches.unitIsOwnedBy(player).and(Matches.unitCreatesUnits());
    final CompositeChange change = new CompositeChange();
    for (final Territory t : data.getMap().getTerritories()) {
        final Collection<Unit> myCreators = CollectionUtils.getMatches(t.getUnits().getUnits(), myCreatorsMatch);
        if (myCreators != null && !myCreators.isEmpty()) {
            final Collection<Unit> toAdd = new ArrayList<>();
            final Collection<Unit> toAddSea = new ArrayList<>();
            final Collection<Unit> toAddLand = new ArrayList<>();
            for (final Unit u : myCreators) {
                final UnitAttachment ua = UnitAttachment.get(u.getType());
                final IntegerMap<UnitType> createsUnitsMap = ua.getCreatesUnitsList();
                final Collection<UnitType> willBeCreated = createsUnitsMap.keySet();
                for (final UnitType ut : willBeCreated) {
                    if (UnitAttachment.get(ut).getIsSea() && Matches.territoryIsLand().test(t)) {
                        toAddSea.addAll(ut.create(createsUnitsMap.getInt(ut), player));
                    } else if (!UnitAttachment.get(ut).getIsSea() && !UnitAttachment.get(ut).getIsAir() && Matches.territoryIsWater().test(t)) {
                        toAddLand.addAll(ut.create(createsUnitsMap.getInt(ut), player));
                    } else {
                        toAdd.addAll(ut.create(createsUnitsMap.getInt(ut), player));
                    }
                }
            }
            if (!toAdd.isEmpty()) {
                final String transcriptText = player.getName() + " creates " + MyFormatter.unitsToTextNoOwner(toAdd) + " in " + t.getName();
                bridge.getHistoryWriter().startEvent(transcriptText, toAdd);
                endTurnReport.append(transcriptText).append("<br />");
                final Change place = ChangeFactory.addUnits(t, toAdd);
                change.add(place);
            }
            if (!toAddSea.isEmpty()) {
                final Predicate<Territory> myTerrs = Matches.territoryIsWater();
                final Collection<Territory> waterNeighbors = data.getMap().getNeighbors(t, myTerrs);
                if (waterNeighbors != null && !waterNeighbors.isEmpty()) {
                    final Territory tw = getRandomTerritory(waterNeighbors, bridge);
                    final String transcriptText = player.getName() + " creates " + MyFormatter.unitsToTextNoOwner(toAddSea) + " in " + tw.getName();
                    bridge.getHistoryWriter().startEvent(transcriptText, toAddSea);
                    endTurnReport.append(transcriptText).append("<br />");
                    final Change place = ChangeFactory.addUnits(tw, toAddSea);
                    change.add(place);
                }
            }
            if (!toAddLand.isEmpty()) {
                final Predicate<Territory> myTerrs = Matches.isTerritoryOwnedBy(player).and(Matches.territoryIsLand());
                final Collection<Territory> landNeighbors = data.getMap().getNeighbors(t, myTerrs);
                if (landNeighbors != null && !landNeighbors.isEmpty()) {
                    final Territory tl = getRandomTerritory(landNeighbors, bridge);
                    final String transcriptText = player.getName() + " creates " + MyFormatter.unitsToTextNoOwner(toAddLand) + " in " + tl.getName();
                    bridge.getHistoryWriter().startEvent(transcriptText, toAddLand);
                    endTurnReport.append(transcriptText).append("<br />");
                    final Change place = ChangeFactory.addUnits(tl, toAddLand);
                    change.add(place);
                }
            }
        }
    }
    if (!change.isEmpty()) {
        bridge.addChange(change);
    }
    return endTurnReport.toString();
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) GameData(games.strategy.engine.data.GameData) ArrayList(java.util.ArrayList) CompositeChange(games.strategy.engine.data.CompositeChange) Change(games.strategy.engine.data.Change) Unit(games.strategy.engine.data.Unit) UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) UnitType(games.strategy.engine.data.UnitType) CompositeChange(games.strategy.engine.data.CompositeChange)

Example 15 with UnitAttachment

use of games.strategy.triplea.attachments.UnitAttachment in project triplea by triplea-game.

the class DiceRoll method getTotalAAattacks.

static int getTotalAAattacks(final Collection<Unit> defendingEnemyAa, final Collection<Unit> validAttackingUnitsForThisRoll) {
    if (defendingEnemyAa.isEmpty() || validAttackingUnitsForThisRoll.isEmpty()) {
        return 0;
    }
    int totalAAattacksNormal = 0;
    int totalAAattacksSurplus = 0;
    for (final Unit aa : defendingEnemyAa) {
        final UnitAttachment ua = UnitAttachment.get(aa.getType());
        if (ua.getMaxAaAttacks() == -1) {
            totalAAattacksNormal = validAttackingUnitsForThisRoll.size();
        } else {
            if (ua.getMayOverStackAa()) {
                totalAAattacksSurplus += ua.getMaxAaAttacks();
            } else {
                totalAAattacksNormal += ua.getMaxAaAttacks();
            }
        }
    }
    totalAAattacksNormal = Math.min(totalAAattacksNormal, validAttackingUnitsForThisRoll.size());
    return totalAAattacksNormal + totalAAattacksSurplus;
}
Also used : UnitAttachment(games.strategy.triplea.attachments.UnitAttachment) Unit(games.strategy.engine.data.Unit)

Aggregations

UnitAttachment (games.strategy.triplea.attachments.UnitAttachment)60 Unit (games.strategy.engine.data.Unit)45 ArrayList (java.util.ArrayList)25 TripleAUnit (games.strategy.triplea.TripleAUnit)23 UnitType (games.strategy.engine.data.UnitType)20 GameData (games.strategy.engine.data.GameData)19 Territory (games.strategy.engine.data.Territory)19 PlayerID (games.strategy.engine.data.PlayerID)12 CompositeChange (games.strategy.engine.data.CompositeChange)8 TerritoryAttachment (games.strategy.triplea.attachments.TerritoryAttachment)7 IntegerMap (games.strategy.util.IntegerMap)6 Collection (java.util.Collection)6 Set (java.util.Set)6 Change (games.strategy.engine.data.Change)5 Resource (games.strategy.engine.data.Resource)5 Tuple (games.strategy.util.Tuple)5 HashSet (java.util.HashSet)5 ITestDelegateBridge (games.strategy.engine.data.ITestDelegateBridge)4 Route (games.strategy.engine.data.Route)4 List (java.util.List)4