From: Stefan F. <ste...@us...> - 2011-08-11 09:56:22
|
LocalisedText.properties | 1 data/18TN/Game.xml | 3 rails/algorithms/NetworkGraphBuilder.java | 2 rails/algorithms/NetworkTrain.java | 43 +++++ rails/algorithms/RevenueAdapter.java | 62 +++----- rails/algorithms/RevenueManager.java | 114 +++++++++++++-- rails/algorithms/RevenueStaticModifier.java | 13 + rails/game/Bonus.java | 13 + rails/game/special/SpecialRight.java | 17 +- rails/game/specific/_1825/ScoreTileOnlyOnceModifier.java | 12 + rails/game/specific/_1851/OffBoardRevenueModifier.java | 9 + rails/game/specific/_1856/PublicCompany_CGR.java | 11 + rails/game/specific/_18AL/NamedTrainRevenueModifier.java | 19 +- rails/game/specific/_18EU/OffBoardRevenueModifier.java | 12 + rails/game/specific/_18Kaas/RuhrRevenueModifier.java | 11 + rails/game/specific/_18TN/PublicCompany_18TN.java | 38 ++++- 16 files changed, 309 insertions(+), 71 deletions(-) New commits: commit 4ba69a2f5672264290b00102a18afa06fe53187f Author: Stefan Frey <ste...@we...> Date: Thu Aug 11 11:57:16 2011 +0200 Refactoring of the revenue modifiers: Moving a lot of functionality from revenue adapter to the revenue manager. Allow static modifier to display pretty print as well. diff --git a/LocalisedText.properties b/LocalisedText.properties index f5b4b38..b0750ce 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -129,6 +129,7 @@ CantSell={0} cannot sell {1} share(s) of {2}: {3} CantStart={0} cannot start company {1} for {2}: {3} CertificateLimit=The certificate limit is now {0} ({1} players, {2} companies) CityHasNoEmptySlots=City has not empty slots +CivilWarActive=Civil War is active. ClassCannotBeInstantiated=Class {0} cannot be instantiated ClickForSell=Click to select for selling ClickToSelectForBuying=Click to select for buying diff --git a/rails/algorithms/NetworkGraphBuilder.java b/rails/algorithms/NetworkGraphBuilder.java index ec34efb..1488cc9 100644 --- a/rails/algorithms/NetworkGraphBuilder.java +++ b/rails/algorithms/NetworkGraphBuilder.java @@ -153,7 +153,7 @@ public final class NetworkGraphBuilder implements Iterable<NetworkVertex> { // add graph modifiers if (revenueManager != null) { - revenueManager.callGraphModifiers(this); + revenueManager.initGraphModifiers(this); } } diff --git a/rails/algorithms/RevenueAdapter.java b/rails/algorithms/RevenueAdapter.java index 080b585..9df031a 100644 --- a/rails/algorithms/RevenueAdapter.java +++ b/rails/algorithms/RevenueAdapter.java @@ -60,6 +60,7 @@ public final class RevenueAdapter implements Runnable { // basic links, to be defined at creation private final GameManagerI gameManager; + private final RevenueManager revenueManager; private final NetworkGraphBuilder graphBuilder; private final NetworkCompanyGraph companyGraph; private final PublicCompanyI company; @@ -81,7 +82,8 @@ public final class RevenueAdapter implements Runnable { private List<NetworkVertex> rcVertices; private List<NetworkEdge> rcEdges; private List<RevenueTrainRun> optimalRun; - private List<RevenueDynamicModifier> dynamicModifiers; + private boolean hasDynamicModifiers; + private boolean hasDynamicCalculator; // revenue listener to communicate results private RevenueListener revenueListener; @@ -89,6 +91,7 @@ public final class RevenueAdapter implements Runnable { public RevenueAdapter(GameManagerI gameManager, NetworkGraphBuilder graphBuilder, NetworkCompanyGraph companyGraph, PublicCompanyI company, PhaseI phase){ this.gameManager = gameManager; + this.revenueManager = gameManager.getRevenueManager(); this.graphBuilder = graphBuilder; this.companyGraph = companyGraph; this.company = company; @@ -231,8 +234,8 @@ public final class RevenueAdapter implements Runnable { } // add all static modifiers - if (gameManager.getRevenueManager() != null) { - gameManager.getRevenueManager().callStaticModifiers(this); + if (revenueManager != null) { + revenueManager.initStaticModifiers(this); } } @@ -302,11 +305,10 @@ public final class RevenueAdapter implements Runnable { this.useMultiGraph = useMultiGraph; - // add all dynamic modifiers - if (gameManager.getRevenueManager() != null) { - dynamicModifiers = gameManager.getRevenueManager().callDynamicModifiers(this); - } else { - dynamicModifiers = new ArrayList<RevenueDynamicModifier>(); + // check for dynamic modifiers (including an own calculator + if (revenueManager != null) { + hasDynamicModifiers = revenueManager.initDynamicModifiers(this); + hasDynamicCalculator = revenueManager.hasDynamicCalculator(); } // define optimized graph @@ -524,7 +526,7 @@ public final class RevenueAdapter implements Runnable { // activate dynamic modifiers - rc.setDynamicModifiers(!dynamicModifiers.isEmpty()); + rc.setDynamicModifiers(hasDynamicModifiers); } public int getVertexValue(NetworkVertex vertex, NetworkTrain train, PhaseI phase) { @@ -583,19 +585,10 @@ public final class RevenueAdapter implements Runnable { } public int calculateRevenue() { - // allow dynamic modifiers to have their own revenue calculation method - boolean isModified = false; - int value = 0; - for (RevenueDynamicModifier modifier:dynamicModifiers) { - if (modifier.providesOwnCalculateRevenue()) { - isModified = true; - value += modifier.calculateRevenue(this); - } - } - // if no modifier was used, standard method is to evaluate all trains - if (isModified) { - return value; - } else { + // allows (one) dynamic modifiers to have their own revenue calculation method + if (hasDynamicCalculator) { + return revenueManager.revenueFromDynamicCalculator(this); + } else { // otherwise standard calculation return calculateRevenue(0, trains.size() - 1); } } @@ -615,9 +608,8 @@ public final class RevenueAdapter implements Runnable { public List<RevenueTrainRun> getOptimalRun() { if (optimalRun == null) { optimalRun = convertRcRun(rc.getOptimalRun()); - // allow dynamic modifiers to change the optimal run - for (RevenueDynamicModifier modifier:dynamicModifiers) { - modifier.adjustOptimalRun(optimalRun); + if (hasDynamicModifiers) { + revenueManager.adjustOptimalRun(optimalRun); } } return optimalRun; @@ -632,9 +624,8 @@ public final class RevenueAdapter implements Runnable { */ int dynamicEvaluation() { int value = 0; - List<RevenueTrainRun> run = this.getCurrentRun(); - for (RevenueDynamicModifier modifier:dynamicModifiers) { - value += modifier.evaluationValue(run, false); + if (hasDynamicModifiers) { + value = revenueManager.evaluationValue(this.getCurrentRun(), false); } return value; } @@ -644,8 +635,8 @@ public final class RevenueAdapter implements Runnable { */ int dynamicPrediction() { int value = 0; - for (RevenueDynamicModifier modifier:dynamicModifiers) { - value += modifier.predictionValue(); + if (hasDynamicModifiers) { + value = revenueManager.predictionValue(); } return value; } @@ -687,16 +678,13 @@ public final class RevenueAdapter implements Runnable { } } if (includeDetails) { - for (RevenueDynamicModifier modifier:dynamicModifiers) { - String modifierText = modifier.prettyPrint(this); - if (modifierText != null) { - runPrettyPrint.append(modifierText); - } + if (revenueManager != null) { + runPrettyPrint.append(revenueManager.prettyPrint(this)); } } else { int dynamicBonuses = 0; - for (RevenueDynamicModifier modifier:dynamicModifiers) { - dynamicBonuses += modifier.evaluationValue(this.getOptimalRun(), true); + if (hasDynamicModifiers) { + dynamicBonuses = revenueManager.evaluationValue(this.getOptimalRun(), true); } if (dynamicBonuses != 0) { runPrettyPrint.append("; " + diff --git a/rails/algorithms/RevenueManager.java b/rails/algorithms/RevenueManager.java index 5f4210d..d8b11e2 100644 --- a/rails/algorithms/RevenueManager.java +++ b/rails/algorithms/RevenueManager.java @@ -29,17 +29,24 @@ public final class RevenueManager implements ConfigurableComponentI { protected static Logger log = Logger.getLogger(RevenueManager.class.getPackage().getName()); + private final HashSet<ConfigurableComponentI> configurableModifiers; private final ArrayListState<NetworkGraphModifier> graphModifiers; private final ArrayListState<RevenueStaticModifier> staticModifiers; private final ArrayListState<RevenueDynamicModifier> dynamicModifiers; - private final HashSet<ConfigurableComponentI> configurableModifiers; + + private final ArrayList<RevenueStaticModifier> activeStaticModifiers; + private final ArrayList<RevenueDynamicModifier> activeDynamicModifiers; + private RevenueDynamicModifier activeCalculator; public RevenueManager() { graphModifiers = new ArrayListState<NetworkGraphModifier>("NetworkGraphModifiers"); staticModifiers = new ArrayListState<RevenueStaticModifier>("RevenueStaticModifiers"); dynamicModifiers = new ArrayListState<RevenueDynamicModifier>("RevenueDynamicModifiers"); configurableModifiers = new HashSet<ConfigurableComponentI>(); + + activeStaticModifiers = new ArrayList<RevenueStaticModifier>(); + activeDynamicModifiers = new ArrayList<RevenueDynamicModifier>(); } public void configureFromXML(Tag tag) throws ConfigurationException { @@ -144,25 +151,116 @@ public final class RevenueManager implements ConfigurableComponentI { return result; } - void callGraphModifiers(NetworkGraphBuilder graphBuilder) { + void initGraphModifiers(NetworkGraphBuilder graphBuilder) { for (NetworkGraphModifier modifier:graphModifiers.viewList()) { modifier.modifyGraph(graphBuilder); } } - void callStaticModifiers(RevenueAdapter revenueAdapter) { + void initStaticModifiers(RevenueAdapter revenueAdapter) { + activeStaticModifiers.clear(); for (RevenueStaticModifier modifier:staticModifiers.viewList()) { - modifier.modifyCalculator(revenueAdapter); + if (modifier.modifyCalculator(revenueAdapter)) { + activeStaticModifiers.add(modifier); + } } } - List<RevenueDynamicModifier> callDynamicModifiers(RevenueAdapter revenueAdapter) { - List<RevenueDynamicModifier> activeModifiers = new ArrayList<RevenueDynamicModifier>(); + /** + * @param revenueAdapter + * @return true if there are active dynamic modifiers + */ + boolean initDynamicModifiers(RevenueAdapter revenueAdapter) { + activeDynamicModifiers.clear(); for (RevenueDynamicModifier modifier:dynamicModifiers.viewList()) { if (modifier.prepareModifier(revenueAdapter)) - activeModifiers.add(modifier); + activeDynamicModifiers.add(modifier); + } + return !activeDynamicModifiers.isEmpty(); + } + + /** + * @return true if one of the dynamic modifiers is an calculator of its own + */ + boolean hasDynamicCalculator() { + for (RevenueDynamicModifier modifier:activeDynamicModifiers) { + if (modifier.providesOwnCalculateRevenue()) { + activeCalculator = modifier; + return true; + } } - return activeModifiers; + return false; + } + + /** + * @param revenueAdapter + * @return revenue from active calculator + */ + int revenueFromDynamicCalculator(RevenueAdapter revenueAdapter) { + return activeCalculator.calculateRevenue(revenueAdapter); + } + /** + * Allows dynamic modifiers to adjust the optimal run + * @param optimalRun + */ + void adjustOptimalRun(List<RevenueTrainRun> optimalRun) { + // allow dynamic modifiers to change the optimal run + for (RevenueDynamicModifier modifier:activeDynamicModifiers) { + modifier.adjustOptimalRun(optimalRun); + } + } + + /** + * @param run the current run + * @param optimal flag if this is the found optimal run + * @return total value of dynamic modifiers + */ + int evaluationValue(List<RevenueTrainRun> run, boolean optimal) { + // allow dynamic modifiers to change the optimal run + int value = 0; + for (RevenueDynamicModifier modifier:activeDynamicModifiers) { + value += modifier.evaluationValue(run, optimal); + } + return value; + } + + /** + * @return total prediction value of dynamic modifiers + */ + int predictionValue() { + int value = 0; + for (RevenueDynamicModifier modifier:activeDynamicModifiers) { + value += modifier.predictionValue(); + } + return value; + } + + /** + * + * @param revenueAdapter + * @return pretty print output from all modifiers (both static and dynamic) + */ + String prettyPrint(RevenueAdapter revenueAdapter) { + StringBuffer prettyPrint = new StringBuffer(); + + for (RevenueStaticModifier modifier:activeStaticModifiers) { + String modifierText = modifier.prettyPrint(revenueAdapter); + if (modifierText != null) { + prettyPrint.append(modifierText + "\n"); + } + } + + for (RevenueDynamicModifier modifier:activeDynamicModifiers) { + String modifierText = modifier.prettyPrint(revenueAdapter); + if (modifierText != null) { + prettyPrint.append(modifierText + "\n"); + } + } + + return prettyPrint.toString(); + } + + } diff --git a/rails/algorithms/RevenueStaticModifier.java b/rails/algorithms/RevenueStaticModifier.java index 501aa21..27e68cd 100644 --- a/rails/algorithms/RevenueStaticModifier.java +++ b/rails/algorithms/RevenueStaticModifier.java @@ -13,6 +13,17 @@ package rails.algorithms; public interface RevenueStaticModifier{ - public void modifyCalculator(RevenueAdapter revenueAdapter); + /** method called after the setup of the revenueAdapter, but before the actual calculation + * Allows to call methods of the revenue adapter to change the content + * @param revenueAdapter + * @return if true a pretty print text is required + */ + public boolean modifyCalculator(RevenueAdapter revenueAdapter); + + /** + * Allows to append additional text + * Only called if modifyCalculator returned true + * @return String output for display in Rails */ + public String prettyPrint(RevenueAdapter revenueAdapter); } diff --git a/rails/game/Bonus.java b/rails/game/Bonus.java index 9cde020..1256b65 100644 --- a/rails/game/Bonus.java +++ b/rails/game/Bonus.java @@ -104,17 +104,26 @@ public class Bonus implements Closeable, RevenueStaticModifier { /** * Add bonus value to revenue calculator */ - public void modifyCalculator(RevenueAdapter revenueAdapter) { + public boolean modifyCalculator(RevenueAdapter revenueAdapter) { // 1. check operating company - if (owner != revenueAdapter.getCompany()) return; + if (owner != revenueAdapter.getCompany()) return false; // 2. find vertices to hex + boolean found = false; Set<NetworkVertex> bonusVertices = NetworkVertex.getVerticesByHexes(revenueAdapter.getVertices(), locations); for (NetworkVertex bonusVertex:bonusVertices) { if (!bonusVertex.isStation()) continue; RevenueBonus bonus = new RevenueBonus(value, name); bonus.addVertex(bonusVertex); revenueAdapter.addRevenueBonus(bonus); + found = true; } + return found; } + + public String prettyPrint(RevenueAdapter revenueAdapter) { + if (name == null) return null; + return "Bonus active = " + name; + } + } diff --git a/rails/game/special/SpecialRight.java b/rails/game/special/SpecialRight.java index 65f0611..0b9647b 100644 --- a/rails/game/special/SpecialRight.java +++ b/rails/game/special/SpecialRight.java @@ -122,15 +122,22 @@ public class SpecialRight extends SpecialProperty implements RevenueStaticModifi /** * modify revenue calculation of the - * TODO: rights is missing a location field, currently hardcoded for 1830 coalfields + * TODO: if owner would be known or only one rights object pretty print would be possible */ - public void modifyCalculator(RevenueAdapter revenueAdapter) { + public boolean modifyCalculator(RevenueAdapter revenueAdapter) { // 1. check operating company if it has the right then it is excluded from the removal - if (revenueAdapter.getCompany().hasRight(rightName)) return; + if (revenueAdapter.getCompany().hasRight(rightName)) return false; // 2. find vertices to hex and remove those - MapHex hex = GameManager.getInstance().getMapManager().getHex("L10"); - Set<NetworkVertex> verticesToRemove = NetworkVertex.getVerticesByHex(revenueAdapter.getVertices(), hex); + Set<NetworkVertex> verticesToRemove = NetworkVertex.getVerticesByHexes(revenueAdapter.getVertices(), locations); revenueAdapter.getGraph().removeAllVertices(verticesToRemove); + + // nothing to print, as the owner is unknown + return false; + } + + public String prettyPrint(RevenueAdapter revenueAdapter) { + // nothing to print + return null; } } diff --git a/rails/game/specific/_1825/ScoreTileOnlyOnceModifier.java b/rails/game/specific/_1825/ScoreTileOnlyOnceModifier.java index baa2eb7..66c4285 100644 --- a/rails/game/specific/_1825/ScoreTileOnlyOnceModifier.java +++ b/rails/game/specific/_1825/ScoreTileOnlyOnceModifier.java @@ -15,7 +15,8 @@ import rails.game.MapHex; public class ScoreTileOnlyOnceModifier implements RevenueStaticModifier { - public void modifyCalculator(RevenueAdapter revenueAdapter) { + public boolean modifyCalculator(RevenueAdapter revenueAdapter) { + // 1. define for each hex a list of stations HashMap<MapHex, List<NetworkVertex>> hexStations = new HashMap<MapHex, List<NetworkVertex>>(); for (NetworkVertex v:revenueAdapter.getVertices()) { @@ -27,13 +28,20 @@ public class ScoreTileOnlyOnceModifier implements RevenueStaticModifier { hexStations.get(v.getHex()).add(v); } } + // 2. convert those with more than one station to a vertex visit set for (MapHex hex:hexStations.keySet()) { if (hexStations.get(hex).size() >= 2) { revenueAdapter.addVertexVisitSet(revenueAdapter.new VertexVisit(hexStations.get(hex))); } } - + // nothing to print + return false; } + public String prettyPrint(RevenueAdapter revenueAdapter) { + // nothing to print + return null; + } + } diff --git a/rails/game/specific/_1851/OffBoardRevenueModifier.java b/rails/game/specific/_1851/OffBoardRevenueModifier.java index 4fc7e0a..6956f3c 100644 --- a/rails/game/specific/_1851/OffBoardRevenueModifier.java +++ b/rails/game/specific/_1851/OffBoardRevenueModifier.java @@ -13,7 +13,7 @@ public class OffBoardRevenueModifier implements RevenueStaticModifier { private static final int BONUS_VALUE = 10; - public void modifyCalculator(RevenueAdapter revenueAdapter) { + public boolean modifyCalculator(RevenueAdapter revenueAdapter) { // 1. get all off-board type stations and all other stations Set<NetworkVertex> offBoard = new HashSet<NetworkVertex>(); Set<NetworkVertex> otherStations = new HashSet<NetworkVertex>(); @@ -43,5 +43,12 @@ public class OffBoardRevenueModifier implements RevenueStaticModifier { } } } + // no additional text required + return false; + } + + public String prettyPrint(RevenueAdapter revenueAdapter) { + // nothing to print + return null; } } diff --git a/rails/game/specific/_1856/PublicCompany_CGR.java b/rails/game/specific/_1856/PublicCompany_CGR.java index e39a88a..113edd2 100644 --- a/rails/game/specific/_1856/PublicCompany_CGR.java +++ b/rails/game/specific/_1856/PublicCompany_CGR.java @@ -162,13 +162,20 @@ public class PublicCompany_CGR extends PublicCompany implements RevenueStaticMod return (hasTemporaryPresident() ? "T" : ""); } - public void modifyCalculator(RevenueAdapter revenueAdapter) { + public boolean modifyCalculator(RevenueAdapter revenueAdapter) { // check if the running company is the cgr - if (revenueAdapter.getCompany() != this) return; + if (revenueAdapter.getCompany() != this) return false; // add the diesel train if (runsWithBorrowedTrain()) { revenueAdapter.addTrainByString("D"); + return true; } + return false; + } + + public String prettyPrint(RevenueAdapter revenueAdapter) { + + return null; } } diff --git a/rails/game/specific/_18AL/NamedTrainRevenueModifier.java b/rails/game/specific/_18AL/NamedTrainRevenueModifier.java index 4777915..43893b9 100644 --- a/rails/game/specific/_18AL/NamedTrainRevenueModifier.java +++ b/rails/game/specific/_18AL/NamedTrainRevenueModifier.java @@ -57,9 +57,9 @@ public class NamedTrainRevenueModifier implements RevenueStaticModifier, Revenue } - public void modifyCalculator(RevenueAdapter revenueAdapter) { + public boolean modifyCalculator(RevenueAdapter revenueAdapter) { // static modifier - if (dynamic) return; + if (dynamic) return false; // 1. check all Trains for name Tokens for (NetworkTrain networkTrain:revenueAdapter.getTrains()) { @@ -73,6 +73,8 @@ public class NamedTrainRevenueModifier implements RevenueStaticModifier, Revenue bonus.addTrain(train); revenueAdapter.addRevenueBonus(bonus); } + // no additional text required + return false; } public boolean prepareModifier(RevenueAdapter revenueAdapter) { @@ -129,19 +131,24 @@ public class NamedTrainRevenueModifier implements RevenueStaticModifier, Revenue } public String prettyPrint(RevenueAdapter revenueAdapter) { + List<RevenueTrainRun> runs = revenueAdapter.getOptimalRun(); StringBuffer prettyPrint = new StringBuffer(); + + boolean first = true; for (RevenueBonus bonus:bonuses) { for (RevenueTrainRun run:runs) { if (run.getUniqueVertices().containsAll(bonus.getVertices())) { - prettyPrint.append(bonus.getName() + " = " + bonus.getValue() + "\n"); + if (!first) { + prettyPrint.append("\n"); // add line break, except for the first + } else { + first = false; + } + prettyPrint.append(bonus.getName() + " = " + bonus.getValue()); continue; // each bonus can only be scored once } } } return prettyPrint.toString(); } - - - } diff --git a/rails/game/specific/_18EU/OffBoardRevenueModifier.java b/rails/game/specific/_18EU/OffBoardRevenueModifier.java index 656f917..ce0d0ae 100644 --- a/rails/game/specific/_18EU/OffBoardRevenueModifier.java +++ b/rails/game/specific/_18EU/OffBoardRevenueModifier.java @@ -20,7 +20,7 @@ public class OffBoardRevenueModifier implements RevenueStaticModifier { Logger.getLogger(OffBoardRevenueModifier.class.getPackage().getName()); - public void modifyCalculator(RevenueAdapter revenueAdapter) { + public boolean modifyCalculator(RevenueAdapter revenueAdapter) { // 1. define value PhaseI phase = revenueAdapter.getPhase(); @@ -32,7 +32,7 @@ public class OffBoardRevenueModifier implements RevenueStaticModifier { } else if (phase.isTileColourAllowed(Tile.GREEN_COLOUR_NAME)) { bonusValue = 10; } else { - return; + return false; } log.info("OffBoardRevenueModifier: bonusValue = " + bonusValue); @@ -79,5 +79,13 @@ public class OffBoardRevenueModifier implements RevenueStaticModifier { } } } + // no additional text required + return false; + } + + + public String prettyPrint(RevenueAdapter revenueAdapter) { + // nothing to do + return null; } } diff --git a/rails/game/specific/_18Kaas/RuhrRevenueModifier.java b/rails/game/specific/_18Kaas/RuhrRevenueModifier.java index 99555e2..840fab5 100644 --- a/rails/game/specific/_18Kaas/RuhrRevenueModifier.java +++ b/rails/game/specific/_18Kaas/RuhrRevenueModifier.java @@ -32,7 +32,7 @@ public class RuhrRevenueModifier implements RevenueStaticModifier, ConfigurableC } // creates revenueBonuses that double the value of each station/value vertex - public void modifyCalculator(RevenueAdapter revenueAdapter) { + public boolean modifyCalculator(RevenueAdapter revenueAdapter) { Set<NetworkVertex> ruhrGebied = new HashSet<NetworkVertex>(); for (NetworkVertex vertex:revenueAdapter.getVertices()) { @@ -41,6 +41,7 @@ public class RuhrRevenueModifier implements RevenueStaticModifier, ConfigurableC ruhrGebied.add(vertex); } } + // 2. add revenue bonuses for stations for (NetworkVertex vertex:revenueAdapter.getVertices()) { if (!ruhrGebied.contains(vertex) && vertex.isStation() && (vertex.isMajor() || !doublesOnlyMajors)) { @@ -52,5 +53,13 @@ public class RuhrRevenueModifier implements RevenueStaticModifier, ConfigurableC } } } + + // nothing to print + return false; + } + + public String prettyPrint(RevenueAdapter revenueAdapter) { + // nothing to print + return null; } } diff --git a/rails/game/specific/_18TN/PublicCompany_18TN.java b/rails/game/specific/_18TN/PublicCompany_18TN.java index 53c550f..b6fe19d 100644 --- a/rails/game/specific/_18TN/PublicCompany_18TN.java +++ b/rails/game/specific/_18TN/PublicCompany_18TN.java @@ -6,6 +6,7 @@ import java.util.List; import rails.algorithms.NetworkTrain; import rails.algorithms.RevenueAdapter; import rails.algorithms.RevenueStaticModifier; +import rails.common.LocalText; import rails.common.parser.ConfigurationException; import rails.game.GameManagerI; import rails.game.PublicCompany; @@ -16,7 +17,6 @@ public class PublicCompany_18TN extends PublicCompany implements RevenueStaticMo private BooleanState civilWar; - public ModelObject getCivilWar() { return civilWar; } @@ -52,20 +52,28 @@ public class PublicCompany_18TN extends PublicCompany implements RevenueStaticMo /** * Modify the revenue calculation for the civil war by removing the shortest train */ - public void modifyCalculator(RevenueAdapter revenueAdapter) { + public boolean modifyCalculator(RevenueAdapter revenueAdapter) { // check if it is civil war, otherwise no effect - if (!isCivilWar()) return; + if (!isCivilWar()) return false; List<NetworkTrain> trains = revenueAdapter.getTrains(); - if (trains.size() == 0) return; // no train, no effect + if (trains.size() == 0) return false; // no train, no effect // sort trains in ascending order (by domination which is equal to length for TN) Collections.sort(trains); // and remove the first train (shortest) trains.remove(0); + + return true; + } + + public String prettyPrint(RevenueAdapter revenueAdapter) { + return LocalText.getText("CivilWarActive"); } + + } commit 92911e549ee5d25bf7d3fb7808cc7d344e8bdd35 Author: Stefan Frey <ste...@we...> Date: Wed Aug 10 12:38:59 2011 +0200 Added train domination comparator to NetworkTrains Civil war effects on Revenue Calculation diff --git a/data/18TN/Game.xml b/data/18TN/Game.xml index 8e971cd..837b8e9 100644 --- a/data/18TN/Game.xml +++ b/data/18TN/Game.xml @@ -121,5 +121,8 @@ </Phase> <Phase name="8"> </Phase> + </Component> + <Component name="RevenueManager" class="rails.algorithms.RevenueManager"> + <!-- Required for TN civil war '--> </Component> </ComponentManager> \ No newline at end of file diff --git a/rails/algorithms/NetworkTrain.java b/rails/algorithms/NetworkTrain.java index 2232c36..b532bda 100644 --- a/rails/algorithms/NetworkTrain.java +++ b/rails/algorithms/NetworkTrain.java @@ -1,11 +1,12 @@ package rails.algorithms; + import org.apache.log4j.Logger; import rails.game.TrainI; import rails.game.TrainType; -public final class NetworkTrain { +public final class NetworkTrain implements Comparable<NetworkTrain>{ protected static Logger log = Logger.getLogger(NetworkTrain.class.getPackage().getName()); @@ -164,4 +165,44 @@ public final class NetworkTrain { return trainName; } + + /** + * Comperator on trains as defined by train domination + * + * A train dominates: + * it has to be longer in either majors and minors + * and at least equally long in both + * + * Furthermore the dominating train has at least the same multiples as the shorter + */ + + public int compareTo(NetworkTrain other) { + + // Check if A is the longer train first + boolean longerA = this.majors > other.majors && this.minors >= other.minors || this.majors == other.majors && this.minors > other.minors; + + if (longerA) { + // then check the multiples + if (this.multiplyMajors >= other.multiplyMajors && this.multiplyMinors >= other.multiplyMinors) { + return 1; + } else { + return 0; + } + } else { + // otherwise B might B longer + boolean longerB = this.majors < other.majors && this.minors <= other.minors || this.majors == other.majors && this.minors < other.minors; + if (longerB) { + // then check the multiples + if (this.multiplyMajors <= other.multiplyMajors && this.multiplyMinors <= other.multiplyMinors) { + return -1; + } else { + return 0; + } + } else { + // none is longer + return 0; + } + } + } + } diff --git a/rails/game/specific/_18TN/PublicCompany_18TN.java b/rails/game/specific/_18TN/PublicCompany_18TN.java index 738200c..53c550f 100644 --- a/rails/game/specific/_18TN/PublicCompany_18TN.java +++ b/rails/game/specific/_18TN/PublicCompany_18TN.java @@ -1,12 +1,18 @@ package rails.game.specific._18TN; +import java.util.Collections; +import java.util.List; + +import rails.algorithms.NetworkTrain; +import rails.algorithms.RevenueAdapter; +import rails.algorithms.RevenueStaticModifier; import rails.common.parser.ConfigurationException; import rails.game.GameManagerI; import rails.game.PublicCompany; import rails.game.model.ModelObject; import rails.game.state.BooleanState; -public class PublicCompany_18TN extends PublicCompany { +public class PublicCompany_18TN extends PublicCompany implements RevenueStaticModifier { private BooleanState civilWar; @@ -22,6 +28,8 @@ public class PublicCompany_18TN extends PublicCompany { super.finishConfiguration(gameManager); civilWar = new BooleanState (name+"_CivilWar", false); + + gameManager.getRevenueManager().addStaticModifier(this); } public boolean isCivilWar() { @@ -41,5 +49,23 @@ public class PublicCompany_18TN extends PublicCompany { stockMarket.withhold(this); } + /** + * Modify the revenue calculation for the civil war by removing the shortest train + */ + public void modifyCalculator(RevenueAdapter revenueAdapter) { + + // check if it is civil war, otherwise no effect + if (!isCivilWar()) return; + + List<NetworkTrain> trains = revenueAdapter.getTrains(); + if (trains.size() == 0) return; // no train, no effect + + // sort trains in ascending order (by domination which is equal to length for TN) + Collections.sort(trains); + + // and remove the first train (shortest) + trains.remove(0); + } + } |