Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Rails-18xx/Rails
Browse files Browse the repository at this point in the history
  • Loading branch information
neutronc committed Feb 7, 2021
2 parents a751fef + 6f3fdde commit 26eca3d
Show file tree
Hide file tree
Showing 120 changed files with 15,547 additions and 3,614 deletions.
33 changes: 18 additions & 15 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
# Rails-18xx 2.3 Release
# Rails-18xx 2.4 Release
This release is meant to show the current state of the Rails-18xx implementation.

Due to different reasons Rails-18xx 2.0 and 2.1 have not been release as production releases. We hope that the audience
finds the release usefull. As usual we welcome bug reports and save games that show the affected states of the game.

We would like to **thank** the various bug reporters and the developers who have contributed over the years for one
feature or ground breaking work.
Please take note that to run Rails-18xx as a JAR directly you need to install a JDK with Java V11 as minimum. The game comes with its own JRE compiled in.

Please dont use the .bat from earlier versions.

## New Features
**Using the installer on Windows and the same directory as previous installations, will overwrite everything in that directory.**

* Notification of Moves via Slack
* Notification of Moves via Discord
* Autoloading and Autopolling for near time gaming allowing you to reload the save game that has changed during turns
* Direct Revenue Allocation for various Contracts possible
* State of Direct Revenue Allocation is static towards company operations budget (no Half pay) - Workaround you half the allocation and add the rest to normal revenue distribution
* Installers for Windows, Mac OS, Linux (Redhat)
We would like to **thank** the varios bug reporters and the developers who have contributed over the years for one feature or ground breaking work.

## New games

* 18Scan
* Steam over Holland
* Steam over Holland implemented by Erik Vos.

## Status of Games

* Implementation of 18Chesapeake started, needs playtesting, bug reports welcome
* Implementation of 1837 - Have a look but be prepared that it might break...
* Open Topics in 1837 Implementation:
* Coal Minors merging round implementation not always working as intended..

## Bug Fixes

* 1856 : Various Bugs
* 1835 : Berlin to Berlin not counts for revenue anymore
* 1880 : Fix for tile #235, Fix for Investor display, broken in 2.2.2

* Various svg-Tiles werent configured correctly which lead to graphic error while resizing or moving the map. Issue reported for 18NL/18TN by Lou Jerkich; Fixes done for 1837 1880 and 18Chesapeake

## Issues fixed:
* #342
* #338
* #329
* #326
* #320
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ plugins {
// https://openjfx.io/openjfx-docs/#gradle
id 'org.openjfx.javafxplugin' version '0.0.9'
// https://docs.sonarqube.org/latest/analysis/scan/sonarscanner-for-gradle/
id 'org.sonarqube' version '3.0'
id 'org.sonarqube' version '3.1.1'
// used by SonarQube for code coverage
id 'jacoco'
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/net/sf/rails/algorithms/NetworkVertex.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import net.sf.rails.game.*;
import net.sf.rails.ui.swing.hexmap.*;

import net.sf.rails.util.Util;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -94,8 +95,7 @@ private NetworkVertex(VertexType type, String name) {
/** factory method for virtual vertex
*/
public static NetworkVertex getVirtualVertex(VertexType type, String name) {
NetworkVertex vertex = new NetworkVertex(type, name);
return vertex;
return new NetworkVertex(type, name);
}

void addToRevenueCalculator(RevenueCalculator rc, int vertexId) {
Expand Down
29 changes: 24 additions & 5 deletions src/main/java/net/sf/rails/algorithms/RevenueAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
* RevenueAdapter links the revenue algorithm to Rails.
*/
public final class RevenueAdapter implements Runnable {

int specialRevenue;

private static final Logger log = LoggerFactory.getLogger(RevenueAdapter.class);

// define VertexVisitSet
Expand Down Expand Up @@ -589,14 +592,22 @@ private List<RevenueTrainRun> convertRcRun(int[][] rcRun) {

public int calculateRevenue() {
// allows (one) dynamic modifiers to have their own revenue calculation method
// TODO: Still to be added
// TODO: Still to be added - beware: it is used differently in 1837
// (see RunToCoalMineModifier).
// if (hasDynamicCalculator) {
// return revenueManager.revenueFromDynamicCalculator(this);
// For 1837 we need to do both!
specialRevenue = revenueManager.revenueFromDynamicCalculator(this);
// } else { // otherwise standard calculation
return calculateRevenue(0, trains.size() - 1);
return calculateRevenue(0, trains.size() - 1);
// }
}

// Another way to get the special revenue
public void setSpecialRevenue (int value) {
specialRevenue = value;
}

public int calculateRevenue(int startTrain, int finalTrain) {
if (startTrain < 0 || finalTrain >= trains.size() || startTrain > finalTrain) {
return 0;
Expand All @@ -606,10 +617,15 @@ public int calculateRevenue(int startTrain, int finalTrain) {
rc.initRuns(startTrain, finalTrain);
rc.executePredictions(startTrain, finalTrain);
int value = rc.calculateRevenue(startTrain, finalTrain);

return value;
}

public List<RevenueTrainRun> getOptimalRun() {
public int getSpecialRevenue() {
return specialRevenue;
}

public List<RevenueTrainRun> getOptimalRun() {
if (optimalRun == null) {
optimalRun = convertRcRun(rc.getOptimalRun());
if (hasDynamicModifiers) {
Expand All @@ -630,6 +646,7 @@ int dynamicEvaluation() {
int value = 0;
if (hasDynamicModifiers) {
value = revenueManager.evaluationValue(this.getCurrentRun(), false);
specialRevenue = revenueManager.getSpecialRevenue();
}
return value;
}
Expand All @@ -649,14 +666,16 @@ public void addRevenueListener(RevenueListener listener) {
this.revenueListener = listener;
}

void notifyRevenueListener(final int revenue, final boolean finalResult) {
void notifyRevenueListener(final int revenue, final int specialRevenue, final boolean finalResult) {
if (revenueListener == null) return;

EventQueue.invokeLater(
new Runnable() {
public void run() {
//listener could have deregistered himself in the meantime
if (revenueListener != null) revenueListener.revenueUpdate(revenue, finalResult);
if (revenueListener != null) {
revenueListener.revenueUpdate(revenue, specialRevenue, finalResult);
}
}
});
}
Expand Down
16 changes: 11 additions & 5 deletions src/main/java/net/sf/rails/algorithms/RevenueCalculator.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ abstract class RevenueCalculator {
protected final int [] trainStartEdge;
protected final int[] trainDistance; // keeps track of distance travelled (for H-trains)

int specialRevenue;

// static bonus data
protected final int [] bonusValue;
protected final boolean [][] bonusActiveForTrain; // dimensions: bonus x train
Expand Down Expand Up @@ -264,14 +266,14 @@ final String getStatistics() {
return statistics.toString();
}

private void notifyRevenueAdapter(final int revenue, final boolean finalResult) {
private void notifyRevenueAdapter(final int revenue, final int specialRevenue, final boolean finalResult) {
String modifier;
if (finalResult)
modifier = "final";
else
modifier = "new best";
log.debug("Report {} result of {} after {}", modifier, revenue, getStatistics());
revenueAdapter.notifyRevenueListener(revenue, finalResult);
revenueAdapter.notifyRevenueListener(revenue, specialRevenue, finalResult);
}

private int[] bestRevenues(final int[] values, final int length) {
Expand Down Expand Up @@ -399,7 +401,7 @@ final int calculateRevenue(final int startTrain, final int finalTrain) {
runTrain(startTrain);

// inform revenue listener via adapter
notifyRevenueAdapter(currentBestValue, true);
notifyRevenueAdapter(currentBestValue, specialRevenue, true);

return currentBestValue;
}
Expand Down Expand Up @@ -526,7 +528,10 @@ protected final void evaluateResults() {
// }
}

if (callDynamicModifiers) totalValue += revenueAdapter.dynamicEvaluation();
if (callDynamicModifiers) {
totalValue += revenueAdapter.dynamicEvaluation();
specialRevenue = revenueAdapter.getSpecialRevenue();
}

nbEvaluations++;
log.debug("RC: current total value {}", totalValue);
Expand All @@ -547,7 +552,8 @@ protected final void evaluateResults() {
}
log.debug("RC: Found better run with {}", totalValue);
// inform revenue listener via adapter
notifyRevenueAdapter(currentBestValue, false);
// special revenue only to be reported with the final result
notifyRevenueAdapter(currentBestValue, specialRevenue, false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ public interface RevenueCalculatorModifier {
* If several dynamic modifier have their own method, their prediction values are added up.
* @return optimal value
*/
public int calculateRevenue(RevenueAdapter revenueAdpater);
public int calculateRevenue(RevenueAdapter revenueAdapter);


public int getSpecialRevenue();

}
2 changes: 1 addition & 1 deletion src/main/java/net/sf/rails/algorithms/RevenueListener.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package net.sf.rails.algorithms;

public interface RevenueListener {
public void revenueUpdate(int revenue, boolean finalResult);
public void revenueUpdate(int revenue, int specialRevenue, boolean finalResult);
}
11 changes: 11 additions & 0 deletions src/main/java/net/sf/rails/algorithms/RevenueManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
*/
public final class RevenueManager extends RailsManager implements Configurable {

private int specialRevenue;

private static final Logger log = LoggerFactory.getLogger(RevenueManager.class);

// Modifiers that are configurable
Expand Down Expand Up @@ -200,6 +202,8 @@ boolean initDynamicModifiers(RevenueAdapter revenueAdapter) {
* @return revenue from active calculator
*/
// FIXME: This does not fully cover all cases that needs the revenue from the calculator
// EV: indeed, it used in a different way in 1837, so beware!
// See RunToCoalMineModifier.
int revenueFromDynamicCalculator(RevenueAdapter revenueAdapter) {
return calculatorModifier.calculateRevenue(revenueAdapter);

Expand Down Expand Up @@ -229,9 +233,16 @@ int evaluationValue(List<RevenueTrainRun> run, boolean optimal) {
for (RevenueDynamicModifier modifier : activeDynamicModifiers) {
value += modifier.evaluationValue(run, optimal);
}
if (calculatorModifier != null) {
specialRevenue = calculatorModifier.getSpecialRevenue();
}
return value;
}

public int getSpecialRevenue () {
return specialRevenue;
}

/**
* @return total prediction value of dynamic modifiers
*/
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/sf/rails/common/GuiDef.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public enum Parm {
NO_MAP_MODE,
REVENUE_SUGGEST,
ROUTE_HIGHLIGHT,
PLAYER_ORDER_VARIES, HAS_SPECIAL_COMPANY_INCOME
PLAYER_ORDER_VARIES,
HAS_SPECIAL_COMPANY_INCOME
}

/**
Expand Down
30 changes: 18 additions & 12 deletions src/main/java/net/sf/rails/common/parser/Tag.java
Original file line number Diff line number Diff line change
Expand Up @@ -276,18 +276,24 @@ private void parseSubTags(Element element) throws ConfigurationException {
value = attribute.getNodeValue();
attributes.put(name, value);
}
} else if ( "IfOption".equalsIgnoreCase(childTagName)) {
Node nameAttr = nnp.getNamedItem("name");
if (nameAttr == null)
throw new ConfigurationException(
"IfOption has no optionName attribute");
name = nameAttr.getNodeValue();

Node parmAttr = nnp.getNamedItem("parm");
if (parmAttr != null) {
value = parmAttr.getNodeValue();
Iterable<String> parameters = Splitter.on(XMLTags.VALUES_DELIM).split(value);
name = GameOption.constructParameterisedName(name, ImmutableList.copyOf(parameters));
} else if ("IfOption".equalsIgnoreCase(childTagName)
|| "IfVariant".equalsIgnoreCase(childTagName)) {

if ("IfOption".equalsIgnoreCase(childTagName)) {
Node nameAttr = nnp.getNamedItem("name");
if (nameAttr == null)
throw new ConfigurationException(
"IfOption has no optionName attribute");
name = nameAttr.getNodeValue();

Node parmAttr = nnp.getNamedItem("parm");
if (parmAttr != null) {
value = parmAttr.getNodeValue();
Iterable<String> parameters = Splitter.on(XMLTags.VALUES_DELIM).split(value);
name = GameOption.constructParameterisedName(name, ImmutableList.copyOf(parameters));
}
} else { // IfVariant
name = "Variant";
}

Node valueAttr = nnp.getNamedItem("value");
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/net/sf/rails/game/GameManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ protected void beginStartRound() {

protected void createStartRound(StartPacket startPacket) {
String startRoundClassName = startPacket.getRoundClassName();
startRoundNumber.add(1);
StartRound startRound = createRound(startRoundClassName,
"startRound_" + startRoundNumber.value());
startRoundNumber.add(1);
startRound.start();
}

Expand Down
Loading

0 comments on commit 26eca3d

Please sign in to comment.