use of games.strategy.engine.data.RelationshipTracker in project triplea by triplea-game.
the class BattleTracker method undoBattle.
void undoBattle(final Route route, final Collection<Unit> units, final PlayerID player, final IDelegateBridge bridge) {
for (final IBattle battle : new ArrayList<>(m_pendingBattles)) {
if (battle.getTerritory().equals(route.getEnd())) {
battle.removeAttack(route, units);
if (battle.isEmpty()) {
removeBattleForUndo(player, battle);
}
}
}
final RelationshipTracker relationshipTracker = bridge.getData().getRelationshipTracker();
// because we could have conquered the end territory if there are no units there
for (final Territory current : route.getAllTerritories()) {
if (!relationshipTracker.isAllied(current.getOwner(), player) && m_conquered.contains(current)) {
m_conquered.remove(current);
m_blitzed.remove(current);
}
}
// say they weren't in combat
final CompositeChange change = new CompositeChange();
for (final Unit unit : units) {
change.add(ChangeFactory.unitPropertyChange(unit, false, TripleAUnit.WAS_IN_COMBAT));
}
bridge.addChange(change);
}
use of games.strategy.engine.data.RelationshipTracker in project triplea by triplea-game.
the class GameDataExporter method relationshipInitialize.
private void relationshipInitialize(final GameData data) {
if (data.getRelationshipTypeList().getAllRelationshipTypes().size() <= 4) {
return;
}
final RelationshipTracker rt = data.getRelationshipTracker();
xmlfile.append(" <relationshipInitialize>\n");
final Collection<PlayerID> players = data.getPlayerList().getPlayers();
final Collection<PlayerID> playersAlreadyDone = new HashSet<>();
for (final PlayerID p1 : players) {
for (final PlayerID p2 : players) {
if (p1.equals(p2) || playersAlreadyDone.contains(p2)) {
continue;
}
final RelationshipType type = rt.getRelationshipType(p1, p2);
final int roundValue = rt.getRoundRelationshipWasCreated(p1, p2);
xmlfile.append(" <relationship type=\"").append(type.getName()).append("\" player1=\"").append(p1.getName()).append("\" player2=\"").append(p2.getName()).append("\" roundValue=\"").append(roundValue).append("\"/>\n");
}
playersAlreadyDone.add(p1);
}
xmlfile.append(" </relationshipInitialize>\n");
}
use of games.strategy.engine.data.RelationshipTracker in project triplea by triplea-game.
the class MovePerformer method markMovementChange.
private Change markMovementChange(final Collection<Unit> units, final Route route, final PlayerID id) {
final GameData data = bridge.getData();
final CompositeChange change = new CompositeChange();
final Territory routeStart = route.getStart();
final TerritoryAttachment taRouteStart = TerritoryAttachment.get(routeStart);
final Territory routeEnd = route.getEnd();
TerritoryAttachment taRouteEnd = null;
if (routeEnd != null) {
taRouteEnd = TerritoryAttachment.get(routeEnd);
}
// only units owned by us need to be marked
final RelationshipTracker relationshipTracker = data.getRelationshipTracker();
for (final Unit baseUnit : CollectionUtils.getMatches(units, Matches.unitIsOwnedBy(id))) {
final TripleAUnit unit = (TripleAUnit) baseUnit;
int moved = route.getMovementCost(unit);
final UnitAttachment ua = UnitAttachment.get(unit.getType());
if (ua.getIsAir()) {
if (taRouteStart != null && taRouteStart.getAirBase() && relationshipTracker.isAllied(route.getStart().getOwner(), unit.getOwner())) {
moved--;
}
if (taRouteEnd != null && taRouteEnd.getAirBase() && relationshipTracker.isAllied(route.getEnd().getOwner(), unit.getOwner())) {
moved--;
}
}
change.add(ChangeFactory.unitPropertyChange(unit, moved + unit.getAlreadyMoved(), TripleAUnit.ALREADY_MOVED));
}
// if entered a non blitzed conquered territory, mark with 0 movement
if (GameStepPropertiesHelper.isCombatMove(data) && (MoveDelegate.getEmptyNeutral(route).size() != 0 || hasConqueredNonBlitzed(route))) {
for (final Unit unit : CollectionUtils.getMatches(units, Matches.unitIsLand())) {
change.add(ChangeFactory.markNoMovementChange(Collections.singleton(unit)));
}
}
if (routeEnd != null && Properties.getSubsCanEndNonCombatMoveWithEnemies(data) && GameStepPropertiesHelper.isNonCombatMove(data, false) && routeEnd.getUnits().anyMatch(Matches.unitIsEnemyOf(data, id).and(Matches.unitIsDestroyer()))) {
// if there is an enemy destroyer there
for (final Unit unit : CollectionUtils.getMatches(units, Matches.unitIsSub().and(Matches.unitIsAir().negate()))) {
change.add(ChangeFactory.markNoMovementChange(Collections.singleton(unit)));
}
}
return change;
}
use of games.strategy.engine.data.RelationshipTracker in project triplea by triplea-game.
the class BattleTracker method takeOver.
public void takeOver(final Territory territory, final PlayerID id, final IDelegateBridge bridge, final UndoableMove changeTracker, final Collection<Unit> arrivingUnits) {
// This could be NULL if unowned water
final TerritoryAttachment ta = TerritoryAttachment.get(territory);
if (ta == null) {
// TODO: allow capture/destroy of infrastructure on unowned water
return;
}
final GameData data = bridge.getData();
final Collection<Unit> arrivedUnits = (arrivingUnits == null ? null : new ArrayList<>(arrivingUnits));
final RelationshipTracker relationshipTracker = data.getRelationshipTracker();
final boolean isTerritoryOwnerAnEnemy = relationshipTracker.canTakeOverOwnedTerritory(id, territory.getOwner());
// check to make sure attackers have more than just transports. If they don't, exit here.
if (territory.isWater() && arrivedUnits != null) {
// Total Attacking Sea units = all units - land units - air units - submerged subs
// Also subtract transports & subs (if they can't control sea zones)
int totalMatches = arrivedUnits.size() - CollectionUtils.countMatches(arrivedUnits, Matches.unitIsLand()) - CollectionUtils.countMatches(arrivedUnits, Matches.unitIsAir()) - CollectionUtils.countMatches(arrivedUnits, Matches.unitIsSubmerged());
// If transports are restricted from controlling sea zones, subtract them
final Predicate<Unit> transportsCanNotControl = Matches.unitIsTransportAndNotDestroyer().and(Matches.unitIsTransportButNotCombatTransport());
if (!Properties.getTransportControlSeaZone(data)) {
totalMatches -= CollectionUtils.countMatches(arrivedUnits, transportsCanNotControl);
}
// If subs are restricted from controlling sea zones, subtract them
if (Properties.getSubControlSeaZoneRestricted(data)) {
totalMatches -= CollectionUtils.countMatches(arrivedUnits, Matches.unitIsSub());
}
if (totalMatches == 0) {
return;
}
}
// If it was a Convoy Route- check ownership of the associated neighboring territory and set message
if (ta.getConvoyRoute()) {
// we could be part of a convoy route for another territory
final Collection<Territory> attachedConvoyTo = TerritoryAttachment.getWhatTerritoriesThisIsUsedInConvoysFor(territory, data);
for (final Territory convoy : attachedConvoyTo) {
final TerritoryAttachment cta = TerritoryAttachment.get(convoy);
if (!cta.getConvoyRoute()) {
continue;
}
final PlayerID convoyOwner = convoy.getOwner();
if (relationshipTracker.isAllied(id, convoyOwner)) {
if (CollectionUtils.getMatches(cta.getConvoyAttached(), Matches.isTerritoryAllied(convoyOwner, data)).size() <= 0) {
bridge.getHistoryWriter().addChildToEvent(convoyOwner.getName() + " gains " + cta.getProduction() + " production in " + convoy.getName() + " for the liberation the convoy route in " + territory.getName());
}
} else if (relationshipTracker.isAtWar(id, convoyOwner)) {
if (CollectionUtils.getMatches(cta.getConvoyAttached(), Matches.isTerritoryAllied(convoyOwner, data)).size() == 1) {
bridge.getHistoryWriter().addChildToEvent(convoyOwner.getName() + " loses " + cta.getProduction() + " production in " + convoy.getName() + " due to the capture of the convoy route in " + territory.getName());
}
}
}
}
// if neutral, we may charge money to enter
if (territory.getOwner().isNull() && !territory.isWater() && Properties.getNeutralCharge(data) >= 0) {
final Resource pus = data.getResourceList().getResource(Constants.PUS);
final int puChargeIdeal = -Properties.getNeutralCharge(data);
final int puChargeReal = Math.min(0, Math.max(puChargeIdeal, -id.getResources().getQuantity(pus)));
final Change neutralFee = ChangeFactory.changeResourcesChange(id, pus, puChargeReal);
bridge.addChange(neutralFee);
if (changeTracker != null) {
changeTracker.addChange(neutralFee);
}
if (puChargeIdeal == puChargeReal) {
bridge.getHistoryWriter().addChildToEvent(id.getName() + " loses " + -puChargeReal + " " + MyFormatter.pluralize("PU", -puChargeReal) + " for violating " + territory.getName() + "s neutrality.");
} else {
System.out.println("Player, " + id.getName() + " attacks a Neutral territory, and should have had to pay " + puChargeIdeal + ", but did not have enough PUs to pay! This is a bug.");
bridge.getHistoryWriter().addChildToEvent(id.getName() + " loses " + -puChargeReal + " " + MyFormatter.pluralize("PU", -puChargeReal) + " for violating " + territory.getName() + "s neutrality. Correct amount to charge is: " + puChargeIdeal + ". Player should not have been able to make this attack!");
}
}
// instead it is relying on the fact that the capital should be owned by the person it is attached to
if (isTerritoryOwnerAnEnemy && ta.getCapital() != null) {
// if the capital is owned by the capitols player take the money
final PlayerID whoseCapital = data.getPlayerList().getPlayerId(ta.getCapital());
final PlayerAttachment pa = PlayerAttachment.get(id);
final PlayerAttachment paWhoseCapital = PlayerAttachment.get(whoseCapital);
final List<Territory> capitalsList = new ArrayList<>(TerritoryAttachment.getAllCurrentlyOwnedCapitals(whoseCapital, data));
// we are losing one right now, so it is < not <=
if (paWhoseCapital != null && paWhoseCapital.getRetainCapitalNumber() < capitalsList.size()) {
// do nothing, we keep our money since we still control enough capitals
bridge.getHistoryWriter().addChildToEvent(id.getName() + " captures one of " + whoseCapital.getName() + " capitals");
} else if (whoseCapital.equals(territory.getOwner())) {
final Resource pus = data.getResourceList().getResource(Constants.PUS);
final int capturedPuCount = whoseCapital.getResources().getQuantity(pus);
if (pa != null) {
if (isPacificTheater(data)) {
final Change changeVp = ChangeFactory.attachmentPropertyChange(pa, (capturedPuCount + pa.getCaptureVps()), "captureVps");
bridge.addChange(changeVp);
if (changeTracker != null) {
changeTracker.addChange(changeVp);
}
}
}
final Change remove = ChangeFactory.changeResourcesChange(whoseCapital, pus, -capturedPuCount);
bridge.addChange(remove);
if (paWhoseCapital != null && paWhoseCapital.getDestroysPUs()) {
bridge.getHistoryWriter().addChildToEvent(id.getName() + " destroys " + capturedPuCount + MyFormatter.pluralize("PU", capturedPuCount) + " while taking " + whoseCapital.getName() + " capital");
if (changeTracker != null) {
changeTracker.addChange(remove);
}
} else {
bridge.getHistoryWriter().addChildToEvent(id.getName() + " captures " + capturedPuCount + MyFormatter.pluralize("PU", capturedPuCount) + " while taking " + whoseCapital.getName() + " capital");
if (changeTracker != null) {
changeTracker.addChange(remove);
}
final Change add = ChangeFactory.changeResourcesChange(id, pus, capturedPuCount);
bridge.addChange(add);
if (changeTracker != null) {
changeTracker.addChange(add);
}
}
// remove all the tokens of the captured player
final Resource tokens = data.getResourceList().getResource(Constants.TECH_TOKENS);
if (tokens != null) {
final int currTokens = whoseCapital.getResources().getQuantity(Constants.TECH_TOKENS);
final Change removeTokens = ChangeFactory.changeResourcesChange(whoseCapital, tokens, -currTokens);
bridge.addChange(removeTokens);
if (changeTracker != null) {
changeTracker.addChange(removeTokens);
}
}
}
}
// is this an allied territory, revert to original owner if it is, unless they dont own there captital
final PlayerID terrOrigOwner = OriginalOwnerTracker.getOriginalOwner(territory);
PlayerID newOwner = id;
// then we do not worry about this.
if (isTerritoryOwnerAnEnemy && terrOrigOwner != null && relationshipTracker.isAllied(terrOrigOwner, id) && !terrOrigOwner.equals(territory.getOwner())) {
final List<Territory> capitalsListOwned = new ArrayList<>(TerritoryAttachment.getAllCurrentlyOwnedCapitals(terrOrigOwner, data));
if (!capitalsListOwned.isEmpty()) {
newOwner = terrOrigOwner;
} else {
newOwner = id;
final List<Territory> capitalsListOriginal = new ArrayList<>(TerritoryAttachment.getAllCapitals(terrOrigOwner, data));
for (final Territory current : capitalsListOriginal) {
if (territory.equals(current) || current.getOwner().equals(PlayerID.NULL_PLAYERID)) {
// if a neutral controls our capital, our territories get liberated (ie: china in ww2v3)
newOwner = terrOrigOwner;
}
}
}
}
// then we set that here (except we don't set it if we are liberating allied owned territory)
if (isTerritoryOwnerAnEnemy && newOwner.equals(id) && Matches.territoryHasWhenCapturedByGoesTo().test(territory)) {
for (final String value : ta.getWhenCapturedByGoesTo()) {
final String[] s = value.split(":");
final PlayerID capturingPlayer = data.getPlayerList().getPlayerId(s[0]);
final PlayerID goesToPlayer = data.getPlayerList().getPlayerId(s[1]);
if (capturingPlayer.equals(goesToPlayer)) {
continue;
}
if (capturingPlayer.equals(id)) {
newOwner = goesToPlayer;
break;
}
}
}
if (isTerritoryOwnerAnEnemy) {
final Change takeOver = ChangeFactory.changeOwner(territory, newOwner);
bridge.getHistoryWriter().addChildToEvent(takeOver.toString());
bridge.addChange(takeOver);
if (changeTracker != null) {
changeTracker.addChange(takeOver);
changeTracker.addToConquered(territory);
}
// play a sound
if (territory.isWater()) {
// should probably see if there is something actually happening for water
bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_TERRITORY_CAPTURE_SEA, id);
} else if (ta.getCapital() != null) {
bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_TERRITORY_CAPTURE_CAPITAL, id);
} else if (m_blitzed.contains(territory) && arrivedUnits.stream().anyMatch(Matches.unitCanBlitz())) {
bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_TERRITORY_CAPTURE_BLITZ, id);
} else {
bridge.getSoundChannelBroadcaster().playSoundForAll(SoundPath.CLIP_TERRITORY_CAPTURE_LAND, id);
}
}
// TODO: see if necessary
if (territory.getUnits().anyMatch(Matches.unitIsEnemyOf(data, id).and(Matches.unitCanBeDamaged()))) {
final IBattle bombingBattle = getPendingBattle(territory, true, null);
if (bombingBattle != null) {
final BattleResults results = new BattleResults(bombingBattle, WhoWon.DRAW, data);
getBattleRecords().addResultToBattle(id, bombingBattle.getBattleId(), null, 0, 0, BattleRecord.BattleResultDescription.NO_BATTLE, results);
bombingBattle.cancelBattle(bridge);
removeBattle(bombingBattle);
throw new IllegalStateException("Bombing Raids should be dealt with first! Be sure the battle has dependencies set correctly!");
}
}
captureOrDestroyUnits(territory, id, newOwner, bridge, changeTracker);
// Also check to make sure playerAttachment even HAS a capital to fix abend
if (isTerritoryOwnerAnEnemy && terrOrigOwner != null && ta.getCapital() != null && TerritoryAttachment.getAllCapitals(terrOrigOwner, data).contains(territory) && relationshipTracker.isAllied(terrOrigOwner, id)) {
// if it is give it back to the original owner
final Collection<Territory> originallyOwned = OriginalOwnerTracker.getOriginallyOwned(data, terrOrigOwner);
final List<Territory> friendlyTerritories = CollectionUtils.getMatches(originallyOwned, Matches.isTerritoryAllied(terrOrigOwner, data));
// give back the factories as well.
for (final Territory item : friendlyTerritories) {
if (item.getOwner() == terrOrigOwner) {
continue;
}
final Change takeOverFriendlyTerritories = ChangeFactory.changeOwner(item, terrOrigOwner);
bridge.addChange(takeOverFriendlyTerritories);
bridge.getHistoryWriter().addChildToEvent(takeOverFriendlyTerritories.toString());
if (changeTracker != null) {
changeTracker.addChange(takeOverFriendlyTerritories);
}
final Collection<Unit> units = CollectionUtils.getMatches(item.getUnits().getUnits(), Matches.unitIsInfrastructure());
if (!units.isEmpty()) {
final Change takeOverNonComUnits = ChangeFactory.changeOwner(units, terrOrigOwner, territory);
bridge.addChange(takeOverNonComUnits);
if (changeTracker != null) {
changeTracker.addChange(takeOverNonComUnits);
}
}
}
}
// (they may want to unload from the transport and attack)
if (Matches.territoryIsWater().test(territory) && arrivedUnits != null) {
arrivedUnits.removeAll(CollectionUtils.getMatches(arrivedUnits, Matches.unitIsLand()));
}
markWasInCombat(arrivedUnits, bridge, changeTracker);
}
use of games.strategy.engine.data.RelationshipTracker in project triplea by triplea-game.
the class ProUtils method isFfa.
/**
* Returns whether the game is a FFA based on whether any of the player's enemies
* are enemies of each other.
*/
public static boolean isFfa(final GameData data, final PlayerID player) {
final RelationshipTracker relationshipTracker = data.getRelationshipTracker();
final Set<PlayerID> enemies = relationshipTracker.getEnemies(player);
for (final PlayerID enemy : enemies) {
if (relationshipTracker.isAtWarWithAnyOfThesePlayers(enemy, enemies)) {
return true;
}
}
return false;
}
Aggregations