package games.strategy.triplea.attachments; import games.strategy.engine.data.Attachable; import games.strategy.engine.data.DefaultAttachment; import games.strategy.engine.data.GameData; import games.strategy.engine.data.GameParseException; import games.strategy.engine.data.RelationshipType; import games.strategy.engine.data.annotations.GameProperty; import games.strategy.triplea.Constants; import games.strategy.triplea.MapSupport; @MapSupport public class RelationshipTypeAttachment extends DefaultAttachment { private static final long serialVersionUID = -4367286684249791984L; public static final String ARCHETYPE_NEUTRAL = Constants.RELATIONSHIP_ARCHETYPE_NEUTRAL; public static final String ARCHETYPE_WAR = Constants.RELATIONSHIP_ARCHETYPE_WAR; public static final String ARCHETYPE_ALLIED = Constants.RELATIONSHIP_ARCHETYPE_ALLIED; public static final String UPKEEP_FLAT = "flat"; public static final String UPKEEP_PERCENTAGE = "percentage"; public static final String PROPERTY_DEFAULT = Constants.RELATIONSHIP_PROPERTY_DEFAULT; public static final String PROPERTY_TRUE = Constants.RELATIONSHIP_PROPERTY_TRUE; public static final String PROPERTY_FALSE = Constants.RELATIONSHIP_PROPERTY_FALSE; private String m_archeType = ARCHETYPE_WAR; // private final String m_helpsDefendAtSea = PROPERTY_DEFAULT; private String m_canMoveLandUnitsOverOwnedLand = PROPERTY_DEFAULT; private String m_canMoveAirUnitsOverOwnedLand = PROPERTY_DEFAULT; private String m_alliancesCanChainTogether = PROPERTY_DEFAULT; private String m_isDefaultWarPosition = PROPERTY_DEFAULT; private String m_upkeepCost = PROPERTY_DEFAULT; private String m_canLandAirUnitsOnOwnedLand = PROPERTY_DEFAULT; private String m_canTakeOverOwnedTerritory = PROPERTY_DEFAULT; private String m_givesBackOriginalTerritories = PROPERTY_DEFAULT; private String m_canMoveIntoDuringCombatMove = PROPERTY_DEFAULT; private String m_canMoveThroughCanals = PROPERTY_DEFAULT; private String m_rocketsCanFlyOver = PROPERTY_DEFAULT; /** * Creates new RelationshipTypeAttachment. */ public RelationshipTypeAttachment(final String name, final Attachable attachable, final GameData gameData) { super(name, attachable, gameData); } /** * Convenience method. * * @return RelationshipTypeAttachment belonging to the RelationshipType pr */ public static RelationshipTypeAttachment get(final RelationshipType pr) { final RelationshipTypeAttachment rVal = (RelationshipTypeAttachment) pr.getAttachment(Constants.RELATIONSHIPTYPE_ATTACHMENT_NAME); if (rVal == null) { throw new IllegalStateException("No relationshipType attachment for:" + pr.getName()); } return rVal; } public static RelationshipTypeAttachment get(final RelationshipType pr, final String nameOfAttachment) { final RelationshipTypeAttachment rVal = (RelationshipTypeAttachment) pr.getAttachment(nameOfAttachment); if (rVal == null) { throw new IllegalStateException("No relationshipType attachment for:" + pr.getName()); } return rVal; } /** * This sets a ArcheType for this relationshipType, there are 3 different archeTypes: War, Allied and Neutral * These archeTypes can be accessed by using the constants: WAR_ARCHETYPE, ALLIED_ARCHETYPE, NEUTRAL_ARCHETYPE * These archeTypes determine the behavior of isAllied, isWar and isNeutral * These archeTyps determine the default behavior of the engine unless you override some option in this attachment; * for example the RelationshipType ColdWar could be based on the WAR_ARCHETYPE but overrides options like "canInvade" * "canAttackHomeTerritory" * to not allow all-out invasion to mimic a not-all-out-war. * Or you could base it on NEUTRAL_ARCHETYPE but override the options like "canAttackAtSea" and "canFireAA" to mimic a * uneasy peace. * * @param archeType * the template used to base this relationType on, can be war, allied or neutral, default archeType = * WAR_ARCHETYPE * @throws GameParseException * if archeType isn't set to war, allied or neutral */ @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setArcheType(final String archeType) throws GameParseException { if (archeType.toLowerCase().equals(ARCHETYPE_WAR)) { m_archeType = ARCHETYPE_WAR; } else if (archeType.toLowerCase().equals(ARCHETYPE_ALLIED)) { m_archeType = ARCHETYPE_ALLIED; } else if (archeType.toLowerCase().equals(ARCHETYPE_NEUTRAL)) { m_archeType = ARCHETYPE_NEUTRAL; } else { throw new GameParseException("archeType must be " + ARCHETYPE_WAR + "," + ARCHETYPE_ALLIED + " or " + ARCHETYPE_NEUTRAL + " for " + thisErrorMsg()); } } /** * @return The ArcheType of this relationshipType, this really shouldn't be called, typically you should call * isNeutral, isAllied or * isWar(). */ public String getArcheType() { return m_archeType; } public void resetArcheType() { m_archeType = ARCHETYPE_WAR; } /** * <strong> EXAMPLE</strong> method on how you could do finegrained authorizations instead of looking at isNeutral, * isAllied or isWar(); * Just for future reference, doesn't do anything right now. * * @param canFlyOver * should be "true", "false" or "default" */ @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setCanMoveAirUnitsOverOwnedLand(final String canFlyOver) { m_canMoveAirUnitsOverOwnedLand = canFlyOver; } /** * <strong> EXAMPLE</strong> method on how you could do finegrained authorizations instead of looking at isNeutral, * isAllied or isWar(); * Just for future reference, doesn't do anything right now. * * @return whether in this relationshipType you can fly over other territories */ public boolean getCanMoveAirUnitsOverOwnedLand() { // War: true, Allied: True, Neutral: false if (m_canMoveAirUnitsOverOwnedLand.equals(PROPERTY_DEFAULT)) { return isWar() || isAllied(); } return m_canMoveAirUnitsOverOwnedLand.equals(PROPERTY_TRUE); } public void resetCanMoveAirUnitsOverOwnedLand() { m_canMoveAirUnitsOverOwnedLand = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setCanMoveLandUnitsOverOwnedLand(final String canFlyOver) { m_canMoveLandUnitsOverOwnedLand = canFlyOver; } public boolean getCanMoveLandUnitsOverOwnedLand() { // War: true, Allied: True, Neutral: false if (m_canMoveLandUnitsOverOwnedLand.equals(PROPERTY_DEFAULT)) { return isWar() || isAllied(); } return m_canMoveLandUnitsOverOwnedLand.equals(PROPERTY_TRUE); } public void resetCanMoveLandUnitsOverOwnedLand() { m_canMoveLandUnitsOverOwnedLand = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setCanLandAirUnitsOnOwnedLand(final String canLandAir) { m_canLandAirUnitsOnOwnedLand = canLandAir; } public boolean getCanLandAirUnitsOnOwnedLand() { // War: false, Allied: true, Neutral: false if (m_canLandAirUnitsOnOwnedLand.equals(PROPERTY_DEFAULT)) { return isAllied(); } return m_canLandAirUnitsOnOwnedLand.equals(PROPERTY_TRUE); } public void resetCanLandAirUnitsOnOwnedLand() { m_canLandAirUnitsOnOwnedLand = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setCanTakeOverOwnedTerritory(final String canTakeOver) { m_canTakeOverOwnedTerritory = canTakeOver; } public boolean getCanTakeOverOwnedTerritory() { // War: true, Allied: false, Neutral: false if (m_canTakeOverOwnedTerritory.equals(PROPERTY_DEFAULT)) { return isWar(); } return m_canTakeOverOwnedTerritory.equals(PROPERTY_TRUE); } public void resetCanTakeOverOwnedTerritory() { m_canTakeOverOwnedTerritory = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setUpkeepCost(final String integerCost) throws GameParseException { if (integerCost.equals(PROPERTY_DEFAULT)) { m_upkeepCost = PROPERTY_DEFAULT; } else { final String[] s = integerCost.split(":"); if (s.length < 1 || s.length > 2) { throw new GameParseException("upkeepCost must have either 1 or 2 fields" + thisErrorMsg()); } final int cost = getInt(s[0]); if (s.length == 2) { if (s[1].equals(UPKEEP_FLAT)) { // do nothing } else if (s[1].equals(UPKEEP_PERCENTAGE)) { if (cost > 100) { throw new GameParseException("upkeepCost may not have a percentage greater than 100" + thisErrorMsg()); } } else { throw new GameParseException( "upkeepCost must have either: " + UPKEEP_FLAT + " or " + UPKEEP_PERCENTAGE + thisErrorMsg()); } } m_upkeepCost = integerCost; } } public String getUpkeepCost() { if (m_upkeepCost.equals(PROPERTY_DEFAULT)) { return String.valueOf(0); } return m_upkeepCost; } public void resetUpkeepCost() { m_upkeepCost = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setAlliancesCanChainTogether(final String value) throws GameParseException { if (!(value.equals(PROPERTY_DEFAULT) || value.equals(PROPERTY_FALSE) || value.equals(PROPERTY_TRUE))) { throw new GameParseException("alliancesCanChainTogether must be either " + PROPERTY_DEFAULT + " or " + PROPERTY_FALSE + " or " + PROPERTY_TRUE + thisErrorMsg()); } m_alliancesCanChainTogether = value; } public boolean getAlliancesCanChainTogether() { if (m_alliancesCanChainTogether.equals(PROPERTY_DEFAULT) || isWar() || isNeutral()) { return false; } return m_alliancesCanChainTogether.equals(PROPERTY_TRUE); } public void resetAlliancesCanChainTogether() { m_alliancesCanChainTogether = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setIsDefaultWarPosition(final String value) throws GameParseException { if (!(value.equals(PROPERTY_DEFAULT) || value.equals(PROPERTY_FALSE) || value.equals(PROPERTY_TRUE))) { throw new GameParseException("isDefaultWarPosition must be either " + PROPERTY_DEFAULT + " or " + PROPERTY_FALSE + " or " + PROPERTY_TRUE + thisErrorMsg()); } m_isDefaultWarPosition = value; } public boolean getIsDefaultWarPosition() { if (m_isDefaultWarPosition.equals(PROPERTY_DEFAULT) || isAllied() || isNeutral()) { return false; } return m_isDefaultWarPosition.equals(PROPERTY_TRUE); } public void resetIsDefaultWarPosition() { m_isDefaultWarPosition = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setGivesBackOriginalTerritories(final String value) throws GameParseException { if (!(value.equals(PROPERTY_DEFAULT) || value.equals(PROPERTY_FALSE) || value.equals(PROPERTY_TRUE))) { throw new GameParseException("givesBackOriginalTerritories must be either " + PROPERTY_DEFAULT + " or " + PROPERTY_FALSE + " or " + PROPERTY_TRUE + thisErrorMsg()); } m_givesBackOriginalTerritories = value; } public boolean getGivesBackOriginalTerritories() { if (m_givesBackOriginalTerritories.equals(PROPERTY_DEFAULT)) { return false; } return m_givesBackOriginalTerritories.equals(PROPERTY_TRUE); } public void resetGivesBackOriginalTerritories() { m_givesBackOriginalTerritories = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setCanMoveIntoDuringCombatMove(final String value) throws GameParseException { if (!(value.equals(PROPERTY_DEFAULT) || value.equals(PROPERTY_FALSE) || value.equals(PROPERTY_TRUE))) { throw new GameParseException("canMoveIntoDuringCombatMove must be either " + PROPERTY_DEFAULT + " or " + PROPERTY_FALSE + " or " + PROPERTY_TRUE + thisErrorMsg()); } m_canMoveIntoDuringCombatMove = value; } public boolean getCanMoveIntoDuringCombatMove() { // this property is not affected by any archetype. if (m_canMoveIntoDuringCombatMove.equals(PROPERTY_DEFAULT)) { return true; } return m_canMoveIntoDuringCombatMove.equals(PROPERTY_TRUE); } public void resetCanMoveIntoDuringCombatMove() { m_canMoveIntoDuringCombatMove = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setCanMoveThroughCanals(final String value) throws GameParseException { if (!(value.equals(PROPERTY_DEFAULT) || value.equals(PROPERTY_FALSE) || value.equals(PROPERTY_TRUE))) { throw new GameParseException("canMoveIntoDuringCombatMove must be either " + PROPERTY_DEFAULT + " or " + PROPERTY_FALSE + " or " + PROPERTY_TRUE + thisErrorMsg()); } m_canMoveThroughCanals = value; } public boolean getCanMoveThroughCanals() { // only allied can move through canals normally if (m_canMoveThroughCanals.equals(PROPERTY_DEFAULT)) { return isAllied(); } return m_canMoveThroughCanals.equals(PROPERTY_TRUE); } public void resetCanMoveThroughCanals() { m_canMoveThroughCanals = PROPERTY_DEFAULT; } @GameProperty(xmlProperty = true, gameProperty = true, adds = false) public void setRocketsCanFlyOver(final String value) throws GameParseException { if (!(value.equals(PROPERTY_DEFAULT) || value.equals(PROPERTY_FALSE) || value.equals(PROPERTY_TRUE))) { throw new GameParseException("canMoveIntoDuringCombatMove must be either " + PROPERTY_DEFAULT + " or " + PROPERTY_FALSE + " or " + PROPERTY_TRUE + thisErrorMsg()); } m_rocketsCanFlyOver = value; } public boolean getRocketsCanFlyOver() { // rockets can normally fly over everyone. if (m_rocketsCanFlyOver.equals(PROPERTY_DEFAULT)) { return true; } return m_rocketsCanFlyOver.equals(PROPERTY_TRUE); } public void resetRocketsCanFlyOver() { m_rocketsCanFlyOver = PROPERTY_DEFAULT; } /** * @return whether this relationship is based on the WAR_ARCHETYPE. */ public boolean isWar() { return m_archeType.equals(RelationshipTypeAttachment.ARCHETYPE_WAR); } /** * @return whether this relationship is based on the ALLIED_ARCHETYPE. */ public boolean isAllied() { return m_archeType.equals(RelationshipTypeAttachment.ARCHETYPE_ALLIED); } /** * @return whether this relationship is based on the NEUTRAL_ARCHETYPE. */ public boolean isNeutral() { return m_archeType.equals(RelationshipTypeAttachment.ARCHETYPE_NEUTRAL); } @Override public void validate(final GameData data) throws GameParseException {} }