Search in sources :

Example 1 with MoveValidationResult

use of games.strategy.triplea.delegate.dataObjects.MoveValidationResult in project triplea by triplea-game.

the class MoveDelegate method move.

@Override
public String move(final Collection<Unit> units, final Route route, final Collection<Unit> transportsThatCanBeLoaded, final Map<Unit, Collection<Unit>> newDependents) {
    final GameData data = getData();
    // the reason we use this, is if we are in edit mode, we may have a different unit owner than the current player
    final PlayerID player = getUnitsOwner(units);
    final MoveValidationResult result = MoveValidator.validateMove(units, route, player, transportsThatCanBeLoaded, newDependents, GameStepPropertiesHelper.isNonCombatMove(data, false), movesToUndo, data);
    final StringBuilder errorMsg = new StringBuilder(100);
    final int numProblems = result.getTotalWarningCount() - (result.hasError() ? 0 : 1);
    final String numErrorsMsg = numProblems > 0 ? ("; " + numProblems + " " + MyFormatter.pluralize("error", numProblems) + " not shown") : "";
    if (result.hasError()) {
        return errorMsg.append(result.getError()).append(numErrorsMsg).toString();
    }
    if (result.hasDisallowedUnits()) {
        return errorMsg.append(result.getDisallowedUnitWarning(0)).append(numErrorsMsg).toString();
    }
    boolean isKamikaze = false;
    final boolean getKamikazeAir = Properties.getKamikazeAirplanes(data);
    Collection<Unit> kamikazeUnits = new ArrayList<>();
    // confirm kamikaze moves, and remove them from unresolved units
    if (getKamikazeAir || units.stream().anyMatch(Matches.unitIsKamikaze())) {
        kamikazeUnits = result.getUnresolvedUnits(MoveValidator.NOT_ALL_AIR_UNITS_CAN_LAND);
        if (kamikazeUnits.size() > 0 && getRemotePlayer().confirmMoveKamikaze()) {
            for (final Unit unit : kamikazeUnits) {
                if (getKamikazeAir || Matches.unitIsKamikaze().test(unit)) {
                    result.removeUnresolvedUnit(MoveValidator.NOT_ALL_AIR_UNITS_CAN_LAND, unit);
                    isKamikaze = true;
                }
            }
        }
    }
    if (result.hasUnresolvedUnits()) {
        return errorMsg.append(result.getUnresolvedUnitWarning(0)).append(numErrorsMsg).toString();
    }
    // allow user to cancel move if aa guns will fire
    final AAInMoveUtil aaInMoveUtil = new AAInMoveUtil();
    aaInMoveUtil.initialize(bridge);
    final Collection<Territory> aaFiringTerritores = aaInMoveUtil.getTerritoriesWhereAaWillFire(route, units);
    if (!aaFiringTerritores.isEmpty()) {
        if (!getRemotePlayer().confirmMoveInFaceOfAa(aaFiringTerritores)) {
            return null;
        }
    }
    // do the move
    final UndoableMove currentMove = new UndoableMove(units, route);
    final String transcriptText = MyFormatter.unitsToTextNoOwner(units) + " moved from " + route.getStart().getName() + " to " + route.getEnd().getName();
    bridge.getHistoryWriter().startEvent(transcriptText, currentMove.getDescriptionObject());
    if (isKamikaze) {
        bridge.getHistoryWriter().addChildToEvent("This was a kamikaze move, for at least some of the units", kamikazeUnits);
    }
    tempMovePerformer = new MovePerformer();
    tempMovePerformer.initialize(this);
    tempMovePerformer.moveUnits(units, route, player, transportsThatCanBeLoaded, newDependents, currentMove);
    tempMovePerformer = null;
    return null;
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) GameData(games.strategy.engine.data.GameData) ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) MoveValidationResult(games.strategy.triplea.delegate.dataObjects.MoveValidationResult)

Example 2 with MoveValidationResult

use of games.strategy.triplea.delegate.dataObjects.MoveValidationResult in project triplea by triplea-game.

the class MoveValidator method validateMove.

public static MoveValidationResult validateMove(final Collection<Unit> units, final Route route, final PlayerID player, final Collection<Unit> transportsToLoad, final Map<Unit, Collection<Unit>> newDependents, final boolean isNonCombat, final List<UndoableMove> undoableMoves, final GameData data) {
    final MoveValidationResult result = new MoveValidationResult();
    if (route.hasNoSteps()) {
        return result;
    }
    if (validateFirst(data, units, route, player, result).getError() != null) {
        return result;
    }
    if (isNonCombat) {
        if (validateNonCombat(data, units, route, player, result).getError() != null) {
            return result;
        }
    } else {
        if (validateCombat(data, units, route, player, result).getError() != null) {
            return result;
        }
    }
    if (validateNonEnemyUnitsOnPath(data, units, route, player, result).getError() != null) {
        return result;
    }
    if (validateBasic(data, units, route, player, transportsToLoad, newDependents, result).getError() != null) {
        return result;
    }
    if (AirMovementValidator.validateAirCanLand(data, units, route, player, result).getError() != null) {
        return result;
    }
    if (validateTransport(isNonCombat, data, undoableMoves, units, route, player, transportsToLoad, result).getError() != null) {
        return result;
    }
    if (validateParatroops(isNonCombat, data, units, route, player, result).getError() != null) {
        return result;
    }
    if (validateCanal(data, units, route, player, result).getError() != null) {
        return result;
    }
    if (validateFuel(data, units, route, player, result).getError() != null) {
        return result;
    }
    // Don't let the user move out of a battle zone, the exception is air units and unloading units into a battle zone
    if (AbstractMoveDelegate.getBattleTracker(data).hasPendingBattle(route.getStart(), false) && units.stream().anyMatch(Matches.unitIsNotAir())) {
        // if the units did not move into the territory, then they can move out this will happen if there is a submerged
        // sub in the area, and a different unit moved into the sea zone setting up a battle but the original unit can
        // still remain
        boolean unitsStartedInTerritory = true;
        for (final Unit unit : units) {
            if (AbstractMoveDelegate.getRouteUsedToMoveInto(undoableMoves, unit, route.getEnd()) != null) {
                unitsStartedInTerritory = false;
                break;
            }
        }
        if (!unitsStartedInTerritory) {
            final boolean unload = route.isUnload();
            final PlayerID endOwner = route.getEnd().getOwner();
            final boolean attack = !data.getRelationshipTracker().isAllied(endOwner, player) || AbstractMoveDelegate.getBattleTracker(data).wasConquered(route.getEnd());
            // unless they are unloading into another battle
            if (!(unload && attack)) {
                return result.setErrorReturnResult("Cannot move units out of battle zone");
            }
        }
    }
    return result;
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) MoveValidationResult(games.strategy.triplea.delegate.dataObjects.MoveValidationResult)

Example 3 with MoveValidationResult

use of games.strategy.triplea.delegate.dataObjects.MoveValidationResult in project triplea by triplea-game.

the class MovePanel method updateUnitsThatCanMoveOnRoute.

private void updateUnitsThatCanMoveOnRoute(final Collection<Unit> units, final Route route) {
    if (route == null || route.hasNoSteps()) {
        clearStatusMessage();
        getMap().showMouseCursor();
        currentCursorImage = null;
        unitsThatCanMoveOnRoute = new ArrayList<>(units);
        return;
    }
    getMap().hideMouseCursor();
    // TODO kev check for already loaded airTransports
    Collection<Unit> transportsToLoad = Collections.emptyList();
    if (MoveValidator.isLoad(units, dependentUnits, route, getData(), getCurrentPlayer())) {
        transportsToLoad = route.getEnd().getUnits().getMatches(Matches.unitIsTransport().and(Matches.alliedUnit(getCurrentPlayer(), getData())));
    }
    List<Unit> best = new ArrayList<>(units);
    // only consider the non land units
    if (route.getStart().isWater() && route.getEnd() != null && route.getEnd().isWater() && !route.isLoad()) {
        best = CollectionUtils.getMatches(best, Matches.unitIsLand().negate());
    }
    sortUnitsToMove(best, route);
    Collections.reverse(best);
    List<Unit> bestWithDependents = addMustMoveWith(best);
    MoveValidationResult allResults;
    getData().acquireReadLock();
    try {
        allResults = AbstractMoveDelegate.validateMove(moveType, bestWithDependents, route, getCurrentPlayer(), transportsToLoad, dependentUnits, nonCombat, getUndoableMoves(), getData());
    } finally {
        getData().releaseReadLock();
    }
    MoveValidationResult lastResults = allResults;
    if (!allResults.isMoveValid()) {
        // if the player is invading only consider units that can invade
        if (!nonCombat && route.isUnload() && Matches.isTerritoryEnemy(getCurrentPlayer(), getData()).test(route.getEnd())) {
            best = CollectionUtils.getMatches(best, Matches.unitCanInvade());
            bestWithDependents = addMustMoveWith(best);
            lastResults = AbstractMoveDelegate.validateMove(moveType, bestWithDependents, route, getCurrentPlayer(), transportsToLoad, dependentUnits, nonCombat, getUndoableMoves(), getData());
        }
        while (!best.isEmpty() && !lastResults.isMoveValid()) {
            best = best.subList(1, best.size());
            bestWithDependents = addMustMoveWith(best);
            lastResults = AbstractMoveDelegate.validateMove(moveType, bestWithDependents, route, getCurrentPlayer(), transportsToLoad, dependentUnits, nonCombat, getUndoableMoves(), getData());
        }
    }
    if (allResults.isMoveValid()) {
        // valid move
        if (bestWithDependents.containsAll(selectedUnits)) {
            clearStatusMessage();
            currentCursorImage = null;
        } else {
            setStatusWarningMessage("Not all units can move there");
            currentCursorImage = getMap().getWarningImage().orElse(null);
        }
    } else {
        String message = allResults.getError();
        if (message == null) {
            message = allResults.getDisallowedUnitWarning(0);
        }
        if (message == null) {
            message = allResults.getUnresolvedUnitWarning(0);
        }
        if (!lastResults.isMoveValid()) {
            setStatusErrorMessage(message);
            currentCursorImage = getMap().getErrorImage().orElse(null);
        } else {
            setStatusWarningMessage(message);
            currentCursorImage = getMap().getWarningImage().orElse(null);
        }
    }
    if (unitsThatCanMoveOnRoute.size() != new HashSet<>(unitsThatCanMoveOnRoute).size()) {
        cancelMove();
        return;
    }
    unitsThatCanMoveOnRoute = new ArrayList<>(bestWithDependents);
}
Also used : ArrayList(java.util.ArrayList) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) MoveValidationResult(games.strategy.triplea.delegate.dataObjects.MoveValidationResult) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 4 with MoveValidationResult

use of games.strategy.triplea.delegate.dataObjects.MoveValidationResult in project triplea by triplea-game.

the class WW2V3Year41Test method testParatroopsWalkOnWater.

@Test
public void testParatroopsWalkOnWater() {
    final PlayerID germans = germans(gameData);
    final Territory france = territory("France", gameData);
    TechAttachment.get(germans).setParatroopers("true");
    final Route r = gameData.getMap().getRoute(france, territory("7 Sea Zone", gameData));
    final Collection<Unit> paratroopers = france.getUnits().getMatches(Matches.unitIsAirTransportable());
    assertFalse(paratroopers.isEmpty());
    final MoveValidationResult results = MoveValidator.validateMove(paratroopers, r, germans, Collections.emptyList(), new HashMap<>(), false, null, gameData);
    assertFalse(results.isMoveValid());
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) MoveValidationResult(games.strategy.triplea.delegate.dataObjects.MoveValidationResult) Route(games.strategy.engine.data.Route) Test(org.junit.jupiter.api.Test)

Example 5 with MoveValidationResult

use of games.strategy.triplea.delegate.dataObjects.MoveValidationResult in project triplea by triplea-game.

the class WW2V3Year41Test method testBomberTankOverWater.

@Test
public void testBomberTankOverWater() {
    // can't transport a tank over water using a bomber
    final PlayerID germans = germans(gameData);
    final Territory sz5 = territory("5 Sea Zone", gameData);
    final Territory germany = territory("Germany", gameData);
    final Territory karelia = territory("Karelia S.S.R.", gameData);
    addTo(germany, armour(gameData).create(1, germans));
    final Route r = new Route(germany, sz5, karelia);
    final Collection<Unit> toMove = germany.getUnits().getMatches(Matches.unitCanBlitz());
    toMove.addAll(germany.getUnits().getMatches(Matches.unitIsStrategicBomber()));
    assertEquals(2, toMove.size());
    final MoveValidationResult results = MoveValidator.validateMove(toMove, r, germans, Collections.emptyList(), new HashMap<>(), false, null, gameData);
    assertFalse(results.isMoveValid());
}
Also used : PlayerID(games.strategy.engine.data.PlayerID) Territory(games.strategy.engine.data.Territory) TripleAUnit(games.strategy.triplea.TripleAUnit) Unit(games.strategy.engine.data.Unit) MoveValidationResult(games.strategy.triplea.delegate.dataObjects.MoveValidationResult) Route(games.strategy.engine.data.Route) Test(org.junit.jupiter.api.Test)

Aggregations

MoveValidationResult (games.strategy.triplea.delegate.dataObjects.MoveValidationResult)12 Unit (games.strategy.engine.data.Unit)11 TripleAUnit (games.strategy.triplea.TripleAUnit)11 PlayerID (games.strategy.engine.data.PlayerID)9 Territory (games.strategy.engine.data.Territory)9 Route (games.strategy.engine.data.Route)7 Test (org.junit.jupiter.api.Test)6 GameData (games.strategy.engine.data.GameData)5 TestMapGameData (games.strategy.triplea.xml.TestMapGameData)3 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 Change (games.strategy.engine.data.Change)1 CompositeChange (games.strategy.engine.data.CompositeChange)1 ProBattleResult (games.strategy.triplea.ai.pro.data.ProBattleResult)1 ProPlaceTerritory (games.strategy.triplea.ai.pro.data.ProPlaceTerritory)1 ProPurchaseTerritory (games.strategy.triplea.ai.pro.data.ProPurchaseTerritory)1 ProTerritory (games.strategy.triplea.ai.pro.data.ProTerritory)1 HashSet (java.util.HashSet)1 LinkedHashSet (java.util.LinkedHashSet)1