package games.strategy.triplea.attachments;
import games.strategy.engine.data.Attachable;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.GameParseException;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.UnitType;
import games.strategy.engine.data.annotations.GameProperty;
import games.strategy.triplea.Constants;
import games.strategy.util.IntegerMap;
/**
* The purpose of this class is to separate the Rules Attachment variables and methods that affect Players,
* from the Rules Attachment things that are part of conditions and national objectives. <br>
* In other words, things like m_placementAnyTerritory (allows placing in any territory without need of a factory),
* or m_movementRestrictionTerritories (restricts movement to certain territories), would go in This class.
* While things like m_alliedOwnershipTerritories (a conditions for testing ownership of territories,
* or m_objectiveValue (the money given if the condition is true), would NOT go in This class. <br>
* Please do not add new things to this class. Any new Player-Rules type of stuff should go in "PlayerAttachment".
*/
public abstract class AbstractPlayerRulesAttachment extends AbstractRulesAttachment {
private static final long serialVersionUID = 7224407193725789143L;
// Please do not add new things to this class. Any new Player-Rules type of stuff should go in "PlayerAttachment".
// These variables are related to a "rulesAttachment" that changes certain rules for the attached player. They are
// not related to
// conditions at all.
protected String m_movementRestrictionType = null;
protected String[] m_movementRestrictionTerritories = null;
// allows placing units in any owned land
protected boolean m_placementAnyTerritory = false;
// allows placing units in any sea by owned land
protected boolean m_placementAnySeaZone = false;
// allows placing units in a captured territory
protected boolean m_placementCapturedTerritory = false;
// turns of the warning to the player when they produce more than they can place
protected boolean m_unlimitedProduction = false;
// can only place units in the capital
protected boolean m_placementInCapitalRestricted = false;
// enemy units will defend at 1
protected boolean m_dominatingFirstRoundAttack = false;
// negates m_dominatingFirstRoundAttack
protected boolean m_negateDominatingFirstRoundAttack = false;
// automatically produces 1 unit of a certain
protected IntegerMap<UnitType> m_productionPerXTerritories = new IntegerMap<>();
// type per every X territories owned
// stops the user from placing units in any territory that already contains more than this
protected int m_placementPerTerritory = -1;
// number of owned units
// maximum number of units that can be placed in each territory.
protected int m_maxPlacePerTerritory = -1;
// It would wreck most map xmls to move the rulesAttachment's to another class, so don't move them out of here
// please!
// However, any new rules attachments that are not conditions, should be put into the "PlayerAttachment" class.
public AbstractPlayerRulesAttachment(final String name, final Attachable attachable, final GameData gameData) {
super(name, attachable, gameData);
}
/**
* Convenience method, will not return objectives and conditions, only the RulesAttachment (like what China in ww2v3
* has).
* These attachments returned are not conditions to be tested, they are special rules affecting a player
* (for example: being able to produce without factories, or not being able to move out of specific territories).
*
* @param player
* PlayerID
* @return new rule attachment
*/
public static RulesAttachment get(final PlayerID player) {
final RulesAttachment rVal = player.getRulesAttachment();
if (rVal == null) {
throw new IllegalStateException("Rules & Conditions: No rule attachment for:" + player.getName());
}
return rVal;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setMovementRestrictionTerritories(final String value) {
if (value == null) {
m_movementRestrictionTerritories = null;
return;
}
m_movementRestrictionTerritories = value.split(":");
validateNames(m_movementRestrictionTerritories);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setMovementRestrictionTerritories(final String[] value) {
m_movementRestrictionTerritories = value;
}
public String[] getMovementRestrictionTerritories() {
return m_movementRestrictionTerritories;
}
public void resetMovementRestrictionTerritories() {
m_movementRestrictionTerritories = null;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setMovementRestrictionType(final String value) throws GameParseException {
if (value == null) {
m_movementRestrictionType = null;
return;
}
if (!(value.equals("disallowed") || value.equals("allowed"))) {
throw new GameParseException("movementRestrictionType must be allowed or disallowed" + thisErrorMsg());
}
m_movementRestrictionType = value;
}
public String getMovementRestrictionType() {
return m_movementRestrictionType;
}
public void resetMovementRestrictionType() {
m_movementRestrictionType = null;
}
/**
* Adds to, not sets. Anything that adds to instead of setting needs a clear function as well.
*/
@GameProperty(xmlProperty = true, gameProperty = true, adds = true)
public void setProductionPerXTerritories(final String value) throws GameParseException {
final String[] s = value.split(":");
if (s.length <= 0 || s.length > 2) {
throw new GameParseException(
"productionPerXTerritories cannot be empty or have more than two fields" + thisErrorMsg());
}
String unitTypeToProduce;
if (s.length == 1) {
unitTypeToProduce = Constants.UNIT_TYPE_INFANTRY;
} else {
unitTypeToProduce = s[1];
}
// validate that this unit exists in the xml
final UnitType ut = getData().getUnitTypeList().getUnitType(unitTypeToProduce);
if (ut == null) {
throw new GameParseException("No unit called: " + unitTypeToProduce + thisErrorMsg());
}
final int n = getInt(s[0]);
if (n <= 0) {
throw new GameParseException("productionPerXTerritories must be a positive integer" + thisErrorMsg());
}
m_productionPerXTerritories.put(ut, n);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setProductionPerXTerritories(final IntegerMap<UnitType> value) {
m_productionPerXTerritories = value;
}
public IntegerMap<UnitType> getProductionPerXTerritories() {
return m_productionPerXTerritories;
}
public void clearProductionPerXTerritories() {
m_productionPerXTerritories.clear();
}
public void resetProductionPerXTerritories() {
m_productionPerXTerritories = new IntegerMap<>();
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementPerTerritory(final String value) {
m_placementPerTerritory = getInt(value);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementPerTerritory(final Integer value) {
m_placementPerTerritory = value;
}
public int getPlacementPerTerritory() {
return m_placementPerTerritory;
}
public void resetPlacementPerTerritory() {
m_placementPerTerritory = -1;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setMaxPlacePerTerritory(final String value) {
m_maxPlacePerTerritory = getInt(value);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setMaxPlacePerTerritory(final Integer value) {
m_maxPlacePerTerritory = value;
}
public int getMaxPlacePerTerritory() {
return m_maxPlacePerTerritory;
}
public void resetMaxPlacePerTerritory() {
m_maxPlacePerTerritory = -1;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementAnyTerritory(final String value) {
m_placementAnyTerritory = getBool(value);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementAnyTerritory(final Boolean value) {
m_placementAnyTerritory = value;
}
public boolean getPlacementAnyTerritory() {
return m_placementAnyTerritory;
}
public void resetPlacementAnyTerritory() {
m_placementAnyTerritory = false;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementAnySeaZone(final String value) {
m_placementAnySeaZone = getBool(value);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementAnySeaZone(final Boolean value) {
m_placementAnySeaZone = value;
}
public boolean getPlacementAnySeaZone() {
return m_placementAnySeaZone;
}
public void resetPlacementAnySeaZone() {
m_placementAnySeaZone = false;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementCapturedTerritory(final String value) {
m_placementCapturedTerritory = getBool(value);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementCapturedTerritory(final Boolean value) {
m_placementCapturedTerritory = value;
}
public boolean getPlacementCapturedTerritory() {
return m_placementCapturedTerritory;
}
public void resetPlacementCapturedTerritory() {
m_placementCapturedTerritory = false;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementInCapitalRestricted(final String value) {
m_placementInCapitalRestricted = getBool(value);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setPlacementInCapitalRestricted(final Boolean value) {
m_placementInCapitalRestricted = value;
}
public boolean getPlacementInCapitalRestricted() {
return m_placementInCapitalRestricted;
}
public void resetPlacementInCapitalRestricted() {
m_placementInCapitalRestricted = false;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setUnlimitedProduction(final String value) {
m_unlimitedProduction = getBool(value);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setUnlimitedProduction(final Boolean value) {
m_unlimitedProduction = value;
}
public boolean getUnlimitedProduction() {
return m_unlimitedProduction;
}
public void resetUnlimitedProduction() {
m_unlimitedProduction = false;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setDominatingFirstRoundAttack(final String value) {
m_dominatingFirstRoundAttack = getBool(value);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setDominatingFirstRoundAttack(final Boolean value) {
m_dominatingFirstRoundAttack = value;
}
public boolean getDominatingFirstRoundAttack() {
return m_dominatingFirstRoundAttack;
}
public void resetDominatingFirstRoundAttack() {
m_dominatingFirstRoundAttack = false;
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setNegateDominatingFirstRoundAttack(final String value) {
m_negateDominatingFirstRoundAttack = getBool(value);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setNegateDominatingFirstRoundAttack(final Boolean value) {
m_negateDominatingFirstRoundAttack = value;
}
public boolean getNegateDominatingFirstRoundAttack() {
return m_negateDominatingFirstRoundAttack;
}
public void resetNegateDominatingFirstRoundAttack() {
m_negateDominatingFirstRoundAttack = false;
}
@Override
public void validate(final GameData data) throws GameParseException {
super.validate(data);
validateNames(m_movementRestrictionTerritories);
}
}