Move UnitTypeChange to FCSOT.

This commit is contained in:
Michael Pope 2016-07-11 15:43:21 +09:30 committed by Mike Pope
parent dcee469617
commit 6da2682541
7 changed files with 106 additions and 150 deletions

View File

@ -20,7 +20,7 @@
In case of incompatible changes, please update version number and
XSD schema for validation.
-->
<freecol-specification id="classic" version="0.104">
<freecol-specification id="classic" version="0.107">
<!-- Modifiers that are not attached to other game object
types. They may be modified, but MUST NOT be removed. -->
@ -1437,41 +1437,63 @@
<required-goods id="model.goods.food"
value="200"/>
<downgrade unit="model.unit.freeColonist" delete="true" />
<upgrade unit="model.unit.expertFarmer" turns-to-learn="4"
<upgrade unit="model.unit.expertFarmer"
learn-in-school="100" turns-to-learn="4"
learn-from-natives="100" learn-from-experience="4"/>
<upgrade unit="model.unit.expertFisherman" turns-to-learn="4"
<upgrade unit="model.unit.expertFisherman"
learn-in-school="100" turns-to-learn="4"
learn-from-natives="100" learn-from-experience="4"/>
<upgrade unit="model.unit.expertFurTrapper" turns-to-learn="4"
<upgrade unit="model.unit.expertFurTrapper"
learn-in-school="100" turns-to-learn="4"
learn-from-natives="100" learn-from-experience="4"/>
<upgrade unit="model.unit.expertSilverMiner" turns-to-learn="4"
<upgrade unit="model.unit.expertSilverMiner"
learn-in-school="100" turns-to-learn="4"
learn-from-natives="100" learn-from-experience="4"/>
<upgrade unit="model.unit.expertLumberJack" turns-to-learn="4"
<upgrade unit="model.unit.expertLumberJack"
learn-in-school="100" turns-to-learn="4"
learn-from-natives="100" learn-from-experience="4"/>
<upgrade unit="model.unit.expertOreMiner" turns-to-learn="4"
<upgrade unit="model.unit.expertOreMiner"
learn-in-school="100" turns-to-learn="4"
learn-from-natives="100" learn-from-experience="4"/>
<upgrade unit="model.unit.masterSugarPlanter" turns-to-learn="6"
<upgrade unit="model.unit.masterSugarPlanter"
learn-in-school="100" turns-to-learn="6"
learn-from-natives="100" learn-from-experience="4"/>
<upgrade unit="model.unit.masterCottonPlanter" turns-to-learn="6"
<upgrade unit="model.unit.masterCottonPlanter"
learn-in-school="100" turns-to-learn="6"
learn-from-natives="100" learn-from-experience="4"/>
<upgrade unit="model.unit.masterTobaccoPlanter" turns-to-learn="6"
<upgrade unit="model.unit.masterTobaccoPlanter"
learn-in-school="100" turns-to-learn="6"
learn-from-natives="100" learn-from-experience="4"/>
<upgrade unit="model.unit.firebrandPreacher" turns-to-learn="8"/>
<upgrade unit="model.unit.elderStatesman" turns-to-learn="8"/>
<upgrade unit="model.unit.masterCarpenter" turns-to-learn="4"/>
<upgrade unit="model.unit.masterDistiller" turns-to-learn="6"/>
<upgrade unit="model.unit.masterWeaver" turns-to-learn="6"
<upgrade unit="model.unit.firebrandPreacher"
learn-in-school="100" turns-to-learn="8"/>
<upgrade unit="model.unit.elderStatesman"
learn-in-school="100" turns-to-learn="8"/>
<upgrade unit="model.unit.masterCarpenter"
learn-in-school="100" turns-to-learn="4"/>
<upgrade unit="model.unit.masterDistiller"
learn-in-school="100" turns-to-learn="6"/>
<upgrade unit="model.unit.masterWeaver"
learn-in-school="100" turns-to-learn="6"
learn-from-natives="100"/>
<upgrade unit="model.unit.masterTobacconist" turns-to-learn="6"/>
<upgrade unit="model.unit.masterFurTrader" turns-to-learn="6"
<upgrade unit="model.unit.masterTobacconist"
learn-in-school="100" turns-to-learn="6"/>
<upgrade unit="model.unit.masterFurTrader"
learn-in-school="100" turns-to-learn="6"
learn-from-natives="100"/>
<upgrade unit="model.unit.masterBlacksmith" turns-to-learn="6"/>
<upgrade unit="model.unit.masterGunsmith" turns-to-learn="6"/>
<upgrade unit="model.unit.seasonedScout" turns-to-learn="4"
<upgrade unit="model.unit.masterBlacksmith"
learn-in-school="100" turns-to-learn="6"/>
<upgrade unit="model.unit.masterGunsmith"
learn-in-school="100" turns-to-learn="6"/>
<upgrade unit="model.unit.seasonedScout"
learn-in-school="100" turns-to-learn="4"
learn-from-natives="100" learn-in-lost-city="100"/>
<upgrade unit="model.unit.hardyPioneer" turns-to-learn="4"/>
<upgrade unit="model.unit.veteranSoldier" turns-to-learn="6"
<upgrade unit="model.unit.hardyPioneer"
learn-in-school="100" turns-to-learn="4"/>
<upgrade unit="model.unit.veteranSoldier"
learn-in-school="100" turns-to-learn="6"
promotion="100"/>
<upgrade unit="model.unit.jesuitMissionary" turns-to-learn="8"/>
<upgrade unit="model.unit.jesuitMissionary"
learn-in-school="100" turns-to-learn="8"/>
</unit-type>
<unit-type id="model.unit.expertFarmer" extends="colonist"
price="1100" skill="1" expert-production="model.goods.grain"
@ -1633,7 +1655,8 @@
skill="-1" recruit-probability="20" score-value="2">
<downgrade unit="model.unit.freeColonist" delete="true"/>
<upgrade unit="model.unit.freeColonist"
turns-to-learn="4" promotion="100"/>
learn-in-school="100" turns-to-learn="4"
promotion="100"/>
<upgrade unit="model.unit.expertFarmer"
learn-from-natives="100" learn-in-school="0"/>
<upgrade unit="model.unit.expertFisherman"

View File

@ -20,7 +20,7 @@
In case of incompatible changes, please update version number and
XSD schema for validation.
-->
<freecol-specification id="freecol" version="0.104" extends="classic">
<freecol-specification id="freecol" version="0.107" extends="classic">
<goods-types>
<goods-type id="model.goods.horses" is-farmed="false"

View File

@ -1005,7 +1005,16 @@
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="scope"/>
</xs:sequence>
<xs:attribute name="unit" use="required" type="xs:string"/>
<xs:attribute name="turns-to-learn" use="optional"
type="xs:nonNegativeInteger"/>
<!-- TODO: delete is mutually exclusive with any of the following. -->
<xs:attribute name="delete" type="xs:boolean"/>
<!-- We need a rule to insist there is at least one of these. -->
<xs:attribute name="conversion" type="PercentageType"/>
<xs:attribute name="creation" type="PercentageType"/>
<xs:attribute name="enter-colony" type="PercentageType"/>
@ -1015,8 +1024,6 @@
<xs:attribute name="learn-in-lost-city" type="PercentageType"/>
<xs:attribute name="learn-in-school" type="PercentageType"/>
<xs:attribute name="promotion" type="PercentageType"/>
<xs:attribute name="turns-to-learn" type="xs:nonNegativeInteger"/>
<xs:attribute name="unit" use="optional" type="xs:string"/>
<!-- TODO: these are downgrades, but serialization can not
handle non-static XML Element tag names! We need to combine
upgrade and downgrade into a typechange. -->
@ -1041,12 +1048,15 @@
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="scope"/>
</xs:sequence>
<xs:attribute name="unit" use="optional" type="xs:string"/>
<xs:attribute name="delete" type="xs:boolean"/>
<xs:attribute name="capture" type="xs:string"/>
<xs:attribute name="clear-skill" type="xs:string"/>
<xs:attribute name="demotion" type="xs:string"/>
<xs:attribute name="undead" type="xs:string"/>
<xs:attribute name="unit" use="optional" type="xs:string"/>
<!-- @compat 0.11.3 -->
<xs:attribute name="clearSkill" type="PercentageType"/>
<!-- end @compat 0.11.3 -->

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- XSD for specification version 0.89
<!-- XSD for specification version 0.107
CHANGELOG:
0.26: add capture-equipment
0.27: add limits
@ -83,6 +83,7 @@
0.104: Fix capitalization in Scope.
0.105: Fix capitalization in Operand.
0.106: Add priority to unit-type.
0.107: Improve unit changes.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:annotation>
@ -1025,8 +1026,16 @@
<xs:sequence>
<xs:element ref="scope" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="unit" use="required" type="xs:string"/>
<xs:attribute name="turns-to-learn" use="optional"
type="xs:nonNegativeInteger"/>
<!-- TODO: delete is mutually exclusive with any of the following. -->
<xs:attribute name="delete" type="xs:boolean"/>
<!-- We need a rule to insist there is at least one of these. -->
<xs:attribute name="conversion" type="PercentageType"/>
<xs:attribute name="creation" type="PercentageType"/>
<xs:attribute name="enter-colony" type="PercentageType"/>
@ -1036,8 +1045,6 @@
<xs:attribute name="learn-in-lost-city" type="PercentageType"/>
<xs:attribute name="learn-in-school" type="PercentageType"/>
<xs:attribute name="promotion" type="PercentageType"/>
<xs:attribute name="turns-to-learn" type="xs:nonNegativeInteger"/>
<xs:attribute name="unit" use="optional" type="xs:string"/>
<!-- TODO: these are downgrades, but serialization can not
handle non-static XML Element tag names! We need to combine
upgrade and downgrade into a type change. -->
@ -1062,13 +1069,15 @@
<xs:sequence>
<xs:element ref="scope" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="unit" use="required" type="xs:string"/>
<xs:attribute name="delete" type="xs:boolean"/>
<xs:attribute name="capture" type="PercentageType"/>
<xs:attribute name="clear-skill" type="PercentageType"/>
<xs:attribute name="demotion" type="PercentageType"/>
<xs:attribute name="undead" type="PercentageType"/>
<xs:attribute name="unit" use="optional" type="xs:string"/>
<!-- @compat 0.11.3 -->
<xs:attribute name="clearSkill" type="PercentageType"/>
<!-- end @compat 0.11.3 -->

View File

@ -158,23 +158,13 @@ public abstract class FreeColSpecObjectType extends FreeColSpecObject
this.scopes.add(scope);
}
/**
* Does at least one of this effect's scopes apply to an object type.
*
* @param objectType The <code>FreeColSpecObjectType</code> to check.
* @return True if this effect applies.
*/
public boolean appliesTo(final FreeColSpecObjectType objectType) {
return appliesTo((FreeColObject)objectType);
}
/**
* Does at least one of this effect's scopes apply to an object.
*
* @param object The <code>FreeColObject</code> to check.
* @return True if this effect applies.
*/
protected boolean appliesTo(FreeColObject object) {
public boolean appliesTo(FreeColObject object) {
return (this.scopes == null || this.scopes.isEmpty()) ? true
: any(this.scopes, s -> s.appliesTo(object));
}

View File

@ -35,7 +35,7 @@ import static net.sf.freecol.common.util.CollectionUtils.*;
/**
* The possible changes of a unit type.
*/
public class UnitTypeChange extends FreeColSpecObject {
public class UnitTypeChange extends FreeColSpecObjectType {
public static enum ChangeType {
EDUCATION,
@ -91,9 +91,6 @@ public class UnitTypeChange extends FreeColSpecObject {
protected final Map<ChangeType, Integer> changeTypes
= new EnumMap<>(ChangeType.class);
/** A list of Scopes limiting the applicability of this Feature. */
private List<Scope> scopes = null;
/**
* Deliberately trivial constructor.
@ -198,48 +195,6 @@ public class UnitTypeChange extends FreeColSpecObject {
return asResultOf(ChangeType.EDUCATION) && turnsToLearn > 0;
}
/**
* Gets the scopes associated with this type change.
*
* @return The list of scopes.
*/
public List<Scope> getScopes() {
return (scopes == null) ? Collections.<Scope>emptyList()
: scopes;
}
/**
* Sets the scopes associated with this type change.
* Public for the test suite.
*
* @param scopes The new list of <code>Scope</code>s.
*/
public void setScopes(List<Scope> scopes) {
this.scopes = scopes;
}
/**
* Add a scope.
*
* @param scope The <code>Scope</code> to add.
*/
private void addScope(Scope scope) {
if (scopes == null) scopes = new ArrayList<>();
scopes.add(scope);
}
/**
* Does this change type apply to a given player?
*
* @param player The <code>Player</code> to test.
* @return True if this change is applicable.
*/
public boolean appliesTo(Player player) {
List<Scope> scopeList = getScopes();
return (scopeList.isEmpty()) ? true
: any(scopeList, s -> s.appliesTo(player));
}
// Serialization
@ -272,16 +227,6 @@ public class UnitTypeChange extends FreeColSpecObject {
}
}
/**
* {@inheritDoc}
*/
@Override
protected void writeChildren(FreeColXMLWriter xw) throws XMLStreamException {
super.writeChildren(xw);
for (Scope scope : getScopes()) scope.toXML(xw);
}
/**
* {@inheritDoc}
*/
@ -289,62 +234,40 @@ public class UnitTypeChange extends FreeColSpecObject {
protected void readAttributes(FreeColXMLReader xr) throws XMLStreamException {
// UnitTypeChange do not have ids, no super.readAttributes().
// However, they might in future.
final Specification spec = getSpecification();
if (xr.hasAttribute(UNIT_TAG)) {
newUnitType = xr.getType(spec, UNIT_TAG,
UnitType.class, (UnitType)null);
// @compat 0.11.6
// unit tag became required for 0.11.7
// end @compat 0.11.6
newUnitType = xr.getType(spec, UNIT_TAG,
UnitType.class, (UnitType)null);
// @compat 0.11.3
if (xr.hasAttribute(OLD_TURNS_TO_LEARN_TAG)) {
turnsToLearn = xr.getAttribute(OLD_TURNS_TO_LEARN_TAG, UNDEFINED);
} else
// end @compat 0.11.3
turnsToLearn = xr.getAttribute(TURNS_TO_LEARN_TAG, UNDEFINED);
for (ChangeType type : ChangeType.values()) {
int value = xr.getAttribute(tags.get(type), -1);
// @compat 0.11.3
if (xr.hasAttribute(OLD_TURNS_TO_LEARN_TAG)) {
turnsToLearn = xr.getAttribute(OLD_TURNS_TO_LEARN_TAG, UNDEFINED);
} else
if (value < 0) {
String x = compatTags.get(type);
if (x != null) value = xr.getAttribute(x, -1);
}
// end @compat 0.11.3
turnsToLearn = xr.getAttribute(TURNS_TO_LEARN_TAG, UNDEFINED);
if (turnsToLearn > 0) {
changeTypes.put(ChangeType.EDUCATION, 100);
}
for (ChangeType type : ChangeType.values()) {
int value = xr.getAttribute(tags.get(type), -1);
// @compat 0.11.3
if (value < 0) {
String x = compatTags.get(type);
if (x != null) value = xr.getAttribute(x, -1);
}
// end @compat 0.11.3
if (value >= 0) {
changeTypes.put(type, Math.min(100, value));
}
if (value >= 0) {
changeTypes.put(type, Math.min(100, value));
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void readChildren(FreeColXMLReader xr) throws XMLStreamException {
// Clear containers.
scopes = null;
super.readChildren(xr);
}
/**
* {@inheritDoc}
*/
@Override
protected void readChild(FreeColXMLReader xr) throws XMLStreamException {
final String tag = xr.getLocalName();
if (Scope.getTagName().equals(tag)) {
addScope(new Scope(xr));
} else {
super.readChild(xr);
}
// @compat 0.11.6
// Prior to 0.11.7 education upgrades were specified only by the
// "turns-to-learn" attribute, but now "learn-in-school" is always
// present if education is allowed.
if (turnsToLearn > 0) changeTypes.put(ChangeType.EDUCATION, 100);
// end @compat 0.11.6
}
/**

View File

@ -25,6 +25,7 @@ import java.util.List;
import net.sf.freecol.common.model.UnitType;
import net.sf.freecol.server.model.ServerUnit;
import net.sf.freecol.util.test.FreeColTestCase;
import static net.sf.freecol.common.util.CollectionUtils.*;
public class UnitTypeChangeTest extends FreeColTestCase {
@ -36,8 +37,8 @@ public class UnitTypeChangeTest extends FreeColTestCase {
public void testEmptyScope() {
UnitTypeChange change = new UnitTypeChange(spec());
assertTrue("A new change has empty scopes",
change.getScopes().isEmpty());
assertEquals("A new change has no scopes", 0,
count(change.getScopes()));
// empty scope applies to all players
for (Player player : getStandardGame().getPlayerList()) {
@ -60,7 +61,7 @@ public class UnitTypeChangeTest extends FreeColTestCase {
UnitTypeChange change = new UnitTypeChange(game.getSpecification());
change.setNewUnitType(farmer);
change.getChangeTypes().put(education, 100);
List<Scope> scopes = new ArrayList<>(change.getScopes());
List<Scope> scopes = toList(change.getScopes());
scopes.add(scope);
change.setScopes(scopes);