From: <ste...@us...> - 2011-07-16 06:23:26
|
Revision: 1614 http://rails.svn.sourceforge.net/rails/?rev=1614&view=rev Author: stefanfrey Date: 2011-07-16 06:23:19 +0000 (Sat, 16 Jul 2011) Log Message: ----------- Added TGVmodifier revenue for 1826 support. Updated dynamic modifier and include more doc and text. Modified Paths: -------------- trunk/18xx/LocalisedText.properties trunk/18xx/data/1870/Game.xml trunk/18xx/rails/algorithms/NetworkTrain.java trunk/18xx/rails/algorithms/RevenueAdapter.java trunk/18xx/rails/algorithms/RevenueCalculator.java trunk/18xx/rails/algorithms/RevenueDynamicModifier.java trunk/18xx/rails/game/specific/_1825/DoubleHeadingModifier.java trunk/18xx/rails/game/specific/_1825/TerminateAtMajorModifier.java trunk/18xx/rails/game/specific/_18AL/NamedTrainRevenueModifier.java trunk/18xx/rails/game/specific/_18EU/PullmanRevenueModifier.java Added Paths: ----------- trunk/18xx/rails/game/specific/_1826/ trunk/18xx/rails/game/specific/_1826/TGVModifier.java Modified: trunk/18xx/LocalisedText.properties =================================================================== --- trunk/18xx/LocalisedText.properties 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/LocalisedText.properties 2011-07-16 06:23:19 UTC (rev 1614) @@ -236,6 +236,7 @@ DoesNotForm={0} does not form DoesNotHaveTheShares=Does not have the shares Done=Done +DoubleHeadingModifier1825={0} are two {1}-trains running as a {2}-train (double heading). ShortORExecuted=A short OR has been held, in which only the sold privates have paid out. DuplicateTileID=Duplicate tile {0} in Tiles.xml DuplicateTilesetID=Duplicate tile {0} in TileSet.xml @@ -620,6 +621,7 @@ TRAINS=Trains TakeLoanPrompt=Will {0} take a loan of {1}? TakeLoans=Take loan(s) +TGVModifier=TGV trains run on separate tracks. ThisItemIsAuctionedNow=This item is auctioned now TileAlreadyHasToken=Tile {0} already has a base token of company {1} TileColorMissing=Missing color in tile {0} Modified: trunk/18xx/data/1870/Game.xml =================================================================== --- trunk/18xx/data/1870/Game.xml 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/data/1870/Game.xml 2011-07-16 06:23:19 UTC (rev 1614) @@ -88,5 +88,9 @@ <Tiles colour="yellow,green,brown,grey"/> <OffBoardRevenue step="3"/> </Phase> + </Component> + <Component name="RevenueManager" class="rails.algorithms.RevenueManager"> + <Modifier class="rails.game.specific._1826.TGVModifier" /> </Component> + </ComponentManager> \ No newline at end of file Modified: trunk/18xx/rails/algorithms/NetworkTrain.java =================================================================== --- trunk/18xx/rails/algorithms/NetworkTrain.java 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/rails/algorithms/NetworkTrain.java 2011-07-16 06:23:19 UTC (rev 1614) @@ -15,11 +15,11 @@ private final boolean ignoreMinors; private final int multiplyMajors; private final int multiplyMinors; - private final String trainName; + private String trainName; private final TrainI railsTrain; - public NetworkTrain(int majors, int minors, boolean ignoreMinors, + private NetworkTrain(int majors, int minors, boolean ignoreMinors, int multiplyMajors, int multiplyMinors, String trainName, TrainI train) { this.majors = majors; this.minors = minors; @@ -49,12 +49,18 @@ trainName, railsTrain); } - static NetworkTrain createFromString(String trainString) { + public static NetworkTrain createFromString(String trainString) { String t = trainString.trim(); int cities = 0; int towns = 0; boolean ignoreTowns = false; int multiplyCities = 1; int multiplyTowns = 1; if (t.equals("D")) { log.info("RA: found Diesel train"); cities = 99; + } else if (t.equals("TGV")) { + log.info("RA: found TGV train"); + cities = 3; + ignoreTowns = true; + multiplyCities = 2; + multiplyTowns = 0; } else if (t.contains("+")) { log.info("RA: found Plus train"); cities = Integer.parseInt(t.split("\\+")[0]); // + train @@ -110,6 +116,10 @@ return ignoreMinors; } + public void setTrainName(String name) { + trainName = name; + } + public String getTrainName() { return trainName; } Modified: trunk/18xx/rails/algorithms/RevenueAdapter.java =================================================================== --- trunk/18xx/rails/algorithms/RevenueAdapter.java 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/rails/algorithms/RevenueAdapter.java 2011-07-16 06:23:19 UTC (rev 1614) @@ -560,15 +560,31 @@ } public int calculateRevenue() { - return calculateRevenue(0, trains.size() - 1); + // 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 { + return calculateRevenue(0, trains.size() - 1); + } } public int calculateRevenue(int startTrain, int finalTrain) { - optimalRun = null; if (startTrain < 0 || finalTrain >= trains.size() || startTrain > finalTrain) { return 0; } - rc.initialPredictionRuns(startTrain, finalTrain); + // the optimal run might change + optimalRun = null; + rc.initRuns(startTrain, finalTrain); + rc.executePredictions(startTrain, finalTrain); int value = rc.calculateRevenue(startTrain, finalTrain); return value; } Modified: trunk/18xx/rails/algorithms/RevenueCalculator.java =================================================================== --- trunk/18xx/rails/algorithms/RevenueCalculator.java 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/rails/algorithms/RevenueCalculator.java 2011-07-16 06:23:19 UTC (rev 1614) @@ -142,6 +142,7 @@ trainStackPos = new int[nbTrains]; trainBottomActive = new boolean[nbTrains]; trainStartEdge = new int[nbTrains]; + maxCumulatedTrainRevenues = new int[nbTrains]; bonusValue = new int[nbBonuses]; bonusRequiresVertices = new int[nbBonuses]; @@ -324,21 +325,31 @@ log.info("maxCumulatedTrainRevenues = " + Arrays.toString(maxCumulatedTrainRevenues)); } - final void initialPredictionRuns(final int startTrain, final int finalTrain) { - + final void initRuns(final int startTrain, final int finalTrain) { + log.info("RC: init runs from " + startTrain + " to " + finalTrain); if (startTrain > finalTrain) return; this.startTrainSet = startTrain; this.finalTrainSet = finalTrain; - useRevenuePrediction = true; - this.maxCumulatedTrainRevenues = new int[nbTrains]; - for (int i=0; i < nbTrains; i++) { + + // initialize all trains and currentValues + for (int i = startTrain; i < finalTrain; i++) { currentBestRun[i][0] = -1; } + currentBestValue = 0; + + } + final void executePredictions(final int startTrain, final int finalTrain) { + useRevenuePrediction = true; + + if (startTrain > finalTrain) return; + initRevenueValues(startTrain, finalTrain); - if (startTrain == finalTrain) return; + if (startTrain == finalTrain) { + return; + } // start prediction runs nbEvaluations = 0; nbPredictions = 0; nbEdgesTravelled = 0; @@ -380,17 +391,8 @@ final int calculateRevenue(final int startTrain, final int finalTrain) { log.info("RC: calculateRevenue trains from " + startTrain + " to " + finalTrain); - if (!useRevenuePrediction) { - for (int i=0; i < nbTrains; i++) { - currentBestRun[i][0] = -1; - } - } - - this.startTrainSet = startTrain; - this.finalTrainSet = finalTrain; - this.startTrain = startTrain; - this.finalTrainSet = finalTrain; + this.finalTrain = finalTrain; runTrain(startTrain); Modified: trunk/18xx/rails/algorithms/RevenueDynamicModifier.java =================================================================== --- trunk/18xx/rails/algorithms/RevenueDynamicModifier.java 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/rails/algorithms/RevenueDynamicModifier.java 2011-07-16 06:23:19 UTC (rev 1614) @@ -3,30 +3,64 @@ import java.util.List; /** - * Classes that change properties of the revenue calculation - * after the actual calculation started implement the dynamic modifier. + * A dynamic modifier allows to change revenue calculation + * during the revenue calculation + * + * For any modfication that only change the setup (e.g. adding bonuses, change train attributes) + * the simpler {@link RevenueStaticModifier} is preferred. * * They have to register themselves to the RevenueManager via the GameManager instance. + * + * Caveats: + * Usually only one instance of a dynamic modifier is needed. + * The interaction between several dynamic modifiers can be complicated. + * + * * @author freystef - * */ public interface RevenueDynamicModifier { - /** after the setup of the revenueAdapter, but before the actual calculation - * if return is false => deactivate */ + /** method called after the setup of the revenueAdapter, but before the actual calculation + * @return true => active, false => deactivate */ public boolean prepareModifier(RevenueAdapter revenueAdapter); - /** returns the value used for prediction */ + /** + * Allows to change the value for the prediction + * If several dynamic modifiers are active simultaneously, their prediction values are added up. + * @return value used to change the prediction + */ public int predictionValue(); - /** returns the value used for evaluation (at the runs supplied) */ + /** + * Allows to change the value for the supplied runs from the revenue calculator + * @param runs Current run of the revenue calculator + * @param optimalRuns true => after optimization, false => during optimization + * @return value used to change the run results + */ public int evaluationValue(List<RevenueTrainRun> runs, boolean optimalRuns); - /** allows to adjust the run list of the optimal train run output */ + /** + * Allows to adjust the run list of the optimal train run output + * @param optimalRuns Optimized run from the revenue calculator + * */ public void adjustOptimalRun(List<RevenueTrainRun> optimalRuns); + + /** + * If the modifier uses its own method for revenue calculation + */ + public boolean providesOwnCalculateRevenue(); + + /** + * Allows to replace the usual calculation process (evaluate all trains simultaneously) + * If several dynamic modifier have their own method, their prediction values are added up. + * @return optimal value + */ + public int calculateRevenue(RevenueAdapter revenueAdpater); - /** returns the results as pretty prints */ - public String prettyPrint(RevenueAdapter adapter); + /** + * Allows to append additional text + * @return String output for display in Rails */ + public String prettyPrint(RevenueAdapter revenueAdapter); } Modified: trunk/18xx/rails/game/specific/_1825/DoubleHeadingModifier.java =================================================================== --- trunk/18xx/rails/game/specific/_1825/DoubleHeadingModifier.java 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/rails/game/specific/_1825/DoubleHeadingModifier.java 2011-07-16 06:23:19 UTC (rev 1614) @@ -8,21 +8,23 @@ import rails.algorithms.RevenueAdapter; import rails.algorithms.RevenueDynamicModifier; import rails.algorithms.RevenueTrainRun; +import rails.common.LocalText; +import rails.game.TrainManager; /** - * 1825 modifiers: - * Trains have to start and end in a major station - * Allows two 2-trains to run as a 3-train (double heading) + * Double heading modifier + * Allows two trains to run as a longer train (double heading) */ public class DoubleHeadingModifier implements RevenueDynamicModifier { - private final static String TRAIN_2_NAME = "2"; - private final static String DUALHEAD_NAME = "2&2"; + private final static String TRAIN_SINGLE = "2"; + private final static String DOUBLEHEAD_NAME = "2&2"; + private final static String TRAIN_DOUBLE = "3"; public boolean prepareModifier(RevenueAdapter revenueAdapter) { int nbTrain2 = 0; for (NetworkTrain train:revenueAdapter.getTrains()) { - // checks name of traintype - if (train.getRailsTrainType().getName().equals(TRAIN_2_NAME)) { + // checks name of train + if (train.getTrainName().equals(TRAIN_SINGLE)) { nbTrain2 ++; } } @@ -30,7 +32,8 @@ // add dualhead 3 train for each of a pair of 2-trains boolean hasDualHead = false; while (nbTrain2 >= 2) { - NetworkTrain dualHead = new NetworkTrain(3, 0, false, 1, 1, DUALHEAD_NAME, null); + NetworkTrain dualHead = NetworkTrain.createFromString(TRAIN_DOUBLE); + dualHead.setTrainName(DOUBLEHEAD_NAME); revenueAdapter.addTrain(dualHead); hasDualHead = true; nbTrain2 -= 2; @@ -53,7 +56,7 @@ // find and sort the train2Revenues List<RevenueTrainRun> train2Runs = new ArrayList<RevenueTrainRun>(); for (RevenueTrainRun run:runs) { - if (run.getTrain().getTrainName().equals(TRAIN_2_NAME)) { + if (run.getTrain().getTrainName().equals(TRAIN_SINGLE)) { train2Runs.add(run); } } @@ -64,7 +67,7 @@ // find DualHeads and remove two 2-train revenues for (RevenueTrainRun run:runs) { // only if train has non zero value - if (run.getTrain().getTrainName().equals(DUALHEAD_NAME) && run.getRunValue() !=0) { + if (run.getTrain().getTrainName().equals(DOUBLEHEAD_NAME) && run.getRunValue() !=0) { // two trains get removed index2Runs += 2; } @@ -97,16 +100,25 @@ // remove double heading trains that do not generate value List<RevenueTrainRun> removeDoubleHeading = new ArrayList<RevenueTrainRun>(); for (RevenueTrainRun run:optimalRuns) { - if (run.getTrain().getTrainName().equals(DUALHEAD_NAME) && run.getRunValue() == 0) { + if (run.getTrain().getTrainName().equals(DOUBLEHEAD_NAME) && run.getRunValue() == 0) { removeDoubleHeading.add(run); } } optimalRuns.removeAll(removeDoubleHeading); } + public boolean providesOwnCalculateRevenue() { + // does not + return false; + } + + public int calculateRevenue(RevenueAdapter revenueAdpater) { + // zero does no change + return 0; + } + public String prettyPrint(RevenueAdapter adapter) { - // nothing to print - return null; + return LocalText.getText("DoubleHeadingModifier1825", DOUBLEHEAD_NAME, TRAIN_SINGLE, TRAIN_DOUBLE); } } Modified: trunk/18xx/rails/game/specific/_1825/TerminateAtMajorModifier.java =================================================================== --- trunk/18xx/rails/game/specific/_1825/TerminateAtMajorModifier.java 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/rails/game/specific/_1825/TerminateAtMajorModifier.java 2011-07-16 06:23:19 UTC (rev 1614) @@ -48,7 +48,16 @@ run.getRunVertices().clear(); } } + public boolean providesOwnCalculateRevenue() { + // does not + return false; + } + public int calculateRevenue(RevenueAdapter revenueAdpater) { + // zero does no change + return 0; + } + public String prettyPrint(RevenueAdapter adapter) { // nothing to do return null; Added: trunk/18xx/rails/game/specific/_1826/TGVModifier.java =================================================================== --- trunk/18xx/rails/game/specific/_1826/TGVModifier.java (rev 0) +++ trunk/18xx/rails/game/specific/_1826/TGVModifier.java 2011-07-16 06:23:19 UTC (rev 1614) @@ -0,0 +1,82 @@ +package rails.game.specific._1826; + +import java.util.ArrayList; +import java.util.List; + +import rails.algorithms.NetworkTrain; +import rails.algorithms.RevenueAdapter; +import rails.algorithms.RevenueDynamicModifier; +import rails.algorithms.RevenueTrainRun; +import rails.common.LocalText; + +/** + * TGV is a train that runs on independent track (defined in Game 1826) + * implementation allows several tgv trains + * @author freystef + */ +public class TGVModifier implements RevenueDynamicModifier { + + final private String TGV_NAME = "TGV"; + + private int nbTGV = 0; // store the number of tgv + + public boolean prepareModifier(RevenueAdapter revenueAdapter) { + + // separate trains into tgv and others + List<NetworkTrain> allTrains = revenueAdapter.getTrains(); + List<NetworkTrain> tgvTrains = new ArrayList<NetworkTrain>(); + List<NetworkTrain> otherTrains = new ArrayList<NetworkTrain>(); + for (NetworkTrain train:allTrains) { + // checks name of train + if (train.getTrainName().equals(TGV_NAME)) { + tgvTrains.add(train); + } else { + otherTrains.add(train); + } + } + + // change list that tgv trains are the first ones, if there are tgvs ... + nbTGV = tgvTrains.size(); + if (nbTGV != 0) { + allTrains.clear(); + allTrains.addAll(tgvTrains); + allTrains.addAll(otherTrains); + return true; + } else { // ... otherwise deactivate modifier + return false; + } + } + + public int predictionValue() { + // nothing to do here + return 0; + } + + public int evaluationValue(List<RevenueTrainRun> runs, boolean optimalRuns) { + // nothing to do here + return 0; + } + + public void adjustOptimalRun(List<RevenueTrainRun> optimalRuns) { + // nothing to do + } + + public boolean providesOwnCalculateRevenue() { + return true; + } + + public int calculateRevenue(RevenueAdapter revenueAdapter) { + // tgv run separately (see prepare modifier above) + int value = 0; + value = revenueAdapter.calculateRevenue(0, nbTGV-1); + // add the other trains + value += revenueAdapter.calculateRevenue(nbTGV, revenueAdapter.getTrains().size()-1); + return value; + } + + public String prettyPrint(RevenueAdapter adapter) { + return LocalText.getText("TGVModifier"); + } + + +} Property changes on: trunk/18xx/rails/game/specific/_1826/TGVModifier.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: trunk/18xx/rails/game/specific/_18AL/NamedTrainRevenueModifier.java =================================================================== --- trunk/18xx/rails/game/specific/_18AL/NamedTrainRevenueModifier.java 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/rails/game/specific/_18AL/NamedTrainRevenueModifier.java 2011-07-16 06:23:19 UTC (rev 1614) @@ -118,6 +118,16 @@ // do nothing here (all is done by changing the evaluation value) } + public boolean providesOwnCalculateRevenue() { + // does not + return false; + } + + public int calculateRevenue(RevenueAdapter revenueAdpater) { + // zero does no change + return 0; + } + public String prettyPrint(RevenueAdapter revenueAdapter) { List<RevenueTrainRun> runs = revenueAdapter.getOptimalRun(); StringBuffer prettyPrint = new StringBuffer(); Modified: trunk/18xx/rails/game/specific/_18EU/PullmanRevenueModifier.java =================================================================== --- trunk/18xx/rails/game/specific/_18EU/PullmanRevenueModifier.java 2011-07-09 12:07:23 UTC (rev 1613) +++ trunk/18xx/rails/game/specific/_18EU/PullmanRevenueModifier.java 2011-07-16 06:23:19 UTC (rev 1614) @@ -49,6 +49,15 @@ return maxValue; } + public boolean providesOwnCalculateRevenue() { + // does not + return false; + } + + public int calculateRevenue(RevenueAdapter revenueAdpater) { + // zero does no change + return 0; + } public void adjustOptimalRun(List<RevenueTrainRun> optimalRuns) { // do nothing here (all is done by changing the evaluation value) } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |