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;
}
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;
}
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);
}
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());
}
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());
}
Aggregations