|
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.
|