From: Brett L. <wak...@us...> - 2011-12-23 13:13:26
|
.classpath | 3 LocalisedText.properties | 6 build.xml | 3 buildRails.xml | 2 data/1856/Game.xml | 12 + data/GamesList.xml | 3 data/Properties.xml | 8 + lib/JLayer1.0.1/jl1.0.1.jar |binary manifest | 4 rails/game/Game.java | 9 + rails/game/GameManager.java | 1 rails/game/OperatingRound.java | 3 rails/game/Phase.java | 4 rails/game/StockRound.java | 3 rails/game/specific/_1856/CGRFormationRound.java | 3 rails/sound/BackgroundMusicManager.java | 174 +++++++++++++++++++++++ 16 files changed, 232 insertions(+), 6 deletions(-) New commits: commit cef11684f468baebb8631b0b09b900fc0d1d446e Author: frederickweld <fre...@gm...> Date: Sun Dec 18 20:36:05 2011 +0100 Fix: Music can now be disabled/enabled during the game (config window). diff --git a/rails/sound/BackgroundMusicManager.java b/rails/sound/BackgroundMusicManager.java index de4b411..751d7b0 100644 --- a/rails/sound/BackgroundMusicManager.java +++ b/rails/sound/BackgroundMusicManager.java @@ -47,7 +47,7 @@ public class BackgroundMusicManager { private static final int ROUND_STOCK = 0; private static final int ROUND_OPERATING = 1; private static final String PHASENAME_DEFAULT = ""; - private static Map<Context,String> contextToMusicFileMapping = new HashMap<Context,String>(); + private static Map<Context,String> contextToMusicFileMapping; private static boolean isDisabled = true; private static boolean isMute = false; private static boolean isPlaying = false; @@ -77,6 +77,7 @@ public class BackgroundMusicManager { String enablement = Config.get("sound.backgroundMusic"); if (enablement != null && enablement.equals("enabled")) { isDisabled = false; + contextToMusicFileMapping = new HashMap<Context,String>(); setContextToMusicFileMapping( Config.get("sound.backgroundMusic.stockRound"), new Context(ROUND_STOCK,PHASENAME_DEFAULT) @@ -87,6 +88,7 @@ public class BackgroundMusicManager { ); playNewMusic(); } else { + stopMusic(); isDisabled = true; } @@ -114,14 +116,12 @@ public class BackgroundMusicManager { stopMusic(); } public static void unMute() { - if (!isDisabled) { isMute = false; playNewMusic(); - } } - + private static void playNewMusic() { - if (!isMute) { + if (!isMute && !isDisabled) { if (isPlaying) stopMusic(); if (contextToMusicFileMapping != null) { String newMusicFileName = (String)contextToMusicFileMapping.get(context); @@ -135,14 +135,16 @@ public class BackgroundMusicManager { // run music playing in new thread to play in background playingThread = new Thread() { Player player; + boolean isKilled = false; public void run() { try { - while (!Thread.interrupted()) { + while (!isKilled) { FileInputStream fis = new FileInputStream(currentMusicFileName); BufferedInputStream bis = new BufferedInputStream(fis); player = new Player(bis); log.info("Now playing: "+currentMusicFileName); player.play(); + player.close(); } } catch (Exception e) { @@ -152,6 +154,7 @@ public class BackgroundMusicManager { } public void interrupt() { super.interrupt(); + isKilled = true; if (player!=null) player.close(); } }; @@ -165,6 +168,7 @@ public class BackgroundMusicManager { if (isPlaying) { playingThread.interrupt(); isPlaying = false; + currentMusicFileName = null; } } } commit 717c70611fd8038222338cda45b77ad853487011 Author: frederickweld <fre...@gm...> Date: Sun Dec 18 17:17:05 2011 +0100 Feature 3454269 (background music) available - Some details on the design/implementation Rails is now capable of playing background music depending on the context (phase, round type). So, as for SimTex's 1830, if a new phase begins (or in case of a OR-SR switch), rails plays a different mp3 in the background. As a result, experiencing/triggering context changes (eg, rusting others' trains) is now much more fun. The end user can configure which mp3 track is used for which context in the configuration window (new tab "Sound"). There, he can also define assignment of mp3 tracks to several contexts (e.g., the same SR music independent of the phase - as it is done in SimTex's 1830). For copyright reasons, no default mp3 tracks are included in rails. During testing, I had configured rails to access SimTex's mp3 files but, as I understand, rails would not be allowed to redistribute them. Therefore, the end user has to provide mp3 files on his own. Note however, that I couldn't commit the change yet due to missing permissions. But Brett has already been contacted for that. ========================================== Some more details about the implementation ========================================== Playing mp3 is based on the lib JLayer which is now added to the rails lib. This should be ok for all of you as: - lib licencse is LGPL - lib size is only 100kb All the logic regarding the background music is found in rails.sound.BackgroundMusicManager. Some comments about the most important design decisions: - Manager is a static class - there may only be one background music at a time. - Manager is notified of context changes by adding notification calls from the context-changing parts of the game: - rails.game.Phase - rails.game.StockRound - rails.game.OperatingRound (I would have loved to subscribe to such kind of information but, since there are no such interfaces available and you apparently aim at refactoring for 2.0, this was not possible.) - Manager is started/configured by calls from rails.game.Game I hope this is ok for all of you. If you find bugs in the new code, don't hesitate to contact me. diff --git a/.classpath b/.classpath index 744d0a0..c705fd7 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry excluding="lib/batik-1.7/|lib/batik-1.7/|lib/batik-1.7/lib/|lib/batik-1.7/lib/|lib/jgraph5/|lib/jgraph5/|lib/jgrapht-0.7.3/|lib/jgrapht-0.7.3/|lib/junit-4.8.2|lib/log4j-1.2/|lib/log4j-1.2/" kind="src" path=""/> + <classpathentry excluding="lib/JLayer1.0.1/|lib/batik-1.7/|lib/batik-1.7/|lib/batik-1.7/lib/|lib/batik-1.7/lib/|lib/jgraph5/|lib/jgraph5/|lib/jgrapht-0.7.3/|lib/jgrapht-0.7.3/|lib/junit-4.8.2|lib/log4j-1.2/|lib/log4j-1.2/" kind="src" path=""/> <classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry exported="true" kind="lib" path="lib/log4j-1.2/log4j-1.2.14.jar"/> <classpathentry exported="true" kind="lib" path="lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar"/> @@ -22,6 +22,7 @@ <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-svg-dom.jar"/> <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-xml.jar"/> <classpathentry kind="lib" path="lib/batik-1.7/lib/js.jar"/> + <classpathentry kind="lib" path="lib/JLayer1.0.1/jl1.0.1.jar"/> <classpathentry kind="lib" path="lib/batik-1.7/lib/xerces_2_5_0.jar"/> <classpathentry kind="lib" path="lib/batik-1.7/lib/xml-apis-ext.jar"/> <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-anim.jar"/> diff --git a/LocalisedText.properties b/LocalisedText.properties index ac33c51..26b182e 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -170,6 +170,8 @@ ComponentManagerNotReconfigured=Cannot reconfigure the ComponentManager. ComponentManagerNotYetConfigured=ComponentManager has not yet been configured. Config.infoText.locale=<html>te_ST shows local text keys. <br> Requires restart.</html> Config.infoText.default_players=Enter player names separated by commas. +Config.infoText.sound.backgroundMusic.stockRound=<html>Enter assignment of music files (mp3) to phases.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax phaseName=complete file path<li>Default music is defined by omitting "phaseName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default music: <br><code>c:\SR-default.mp3</code><li>Set phase-dependent music and a default (for trains above 6): <br><code>2=c:\SR-2.mp3,3=c:\SR-3.mp3,4=c:\SR-4.mp3,5=c:\SR-5.mp3,6=c:\SR-6.mp3,c:\SR-D.mp3</code></ul> </html> +Config.infoText.sound.backgroundMusic.operatingRound=<html>Enter assignment of music files (mp3) to phases.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax phaseName=complete file path<li>Default music is defined by omitting "phaseName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default music: <br><code>c:\OR-default.mp3</code><li>Set phase-dependent music and a default (for trains above 6): <br><code>2=c:\OR-2.mp3,3=c:\OR-3.mp3,4=c:\OR-4.mp3,5=c:\OR-5.mp3,6=c:\OR-6.mp3,c:\OR-D.mp3</code></ul> </html> Config.label.default_game=Default game Config.label.default_players=Default players Config.label.font.ui.name=Font selection @@ -192,6 +194,9 @@ Config.label.route.colour.1=Route color for first train Config.label.route.colour.2=Route color for second train Config.label.route.colour.3=Route color for third train Config.label.route.colour.4=Route color for fourth train +Config.label.sound.backgroundMusic=Background Music +Config.label.sound.backgroundMusic.stockRound=Music files for the Stock Round +Config.label.sound.backgroundMusic.operatingRound=Music files for the Operating Round Config.label.stockchart.window.open=Stockchart open Config.label.save.directory=Save folder Config.label.save.filename.date_time_pattern=Filename date pattern @@ -205,6 +210,7 @@ Config.section.General=General Config.section.Log=Log Config.section.Font=Fonts Config.section.Save=Save +Config.section.Sound=Sound Config.section.UI=Map/Report ConfirmToken=Press Lay Token to confirm token, click another city hex, or press the No Token button. connected=connected diff --git a/build.xml b/build.xml index 45e1e35..f58cc8f 100644 --- a/build.xml +++ b/build.xml @@ -17,6 +17,7 @@ <pathelement location="lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar"/> <pathelement location="lib/jgraph5/jgraph.jar"/> <pathelement location="lib/junit-4.8.2/junit.jar"/> + <pathelement location="lib/JLayer1.0.1/jl1.0.1.jar"/> <pathelement location="lib/batik-1.7/lib/batik-transcoder.jar"/> <pathelement location="lib/batik-1.7/lib/batik-dom.jar"/> <pathelement location="lib/batik-1.7/lib/batik-swing.jar"/> @@ -48,6 +49,7 @@ <exclude name="lib/batik-1.7/"/> <exclude name="lib/batik-1.7/lib/"/> <exclude name="lib/batik-1.7/lib/"/> + <exclude name="lib/JLayer1.0.1"/> <exclude name="lib/jgraph5/"/> <exclude name="lib/jgraph5/"/> <exclude name="lib/jgrapht-0.7.3/"/> @@ -72,6 +74,7 @@ <exclude name="lib/batik-1.7/"/> <exclude name="lib/batik-1.7/lib/"/> <exclude name="lib/batik-1.7/lib/"/> + <exclude name="lib/JLayer1.0.1"/> <exclude name="lib/jgraph5/"/> <exclude name="lib/jgraph5/"/> <exclude name="lib/jgrapht-0.7.3/"/> diff --git a/buildRails.xml b/buildRails.xml index d7dd74f..e656d8a 100644 --- a/buildRails.xml +++ b/buildRails.xml @@ -64,6 +64,7 @@ <include name="jgrapht-0.7.3/jgrapht-jdk1.5.jar" /> <include name="jgraph5/jgraph.jar" /> <include name="junit-4.8.2/junit.jar" /> + <include name="JLayer1.0.1/jl1.0.1.jar"/> <include name="batik-1.7/lib/batik-transcoder.jar" /> <include name="batik-1.7/lib/batik-dom.jar" /> <include name="batik-1.7/lib/batik-swing.jar" /> @@ -108,6 +109,7 @@ ./lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar ./lib/jgraph5/jgraph.jar ./lib/junit-4.8.2/junit.jar + ./lib/JLayer1.0.1/jl1.0.1.jar ./lib/batik-1.7/lib/batik-transcoder.jar ./lib/batik-1.7/lib/batik-dom.jar ./lib/batik-1.7/lib/batik-swing.jar diff --git a/data/Properties.xml b/data/Properties.xml index eb95d4c..231e6e6 100644 --- a/data/Properties.xml +++ b/data/Properties.xml @@ -53,4 +53,12 @@ <Property name="report.filename.date_time_pattern" type="STRING" /> <Property name="report.filename.extension" type="STRING" /> </Section> + <Section name="Sound"> + <Property name="sound.backgroundMusic" type="LIST" values="disabled,enabled" + initClass="rails.sound.BackgroundMusicManager" initMethod="init"/> + <Property name="sound.backgroundMusic.stockRound" type="STRING" + initClass="rails.sound.BackgroundMusicManager" initMethod="init"/> + <Property name="sound.backgroundMusic.operatingRound" type="STRING" + initClass="rails.sound.BackgroundMusicManager" initMethod="init"/> + </Section> </Properties> \ No newline at end of file diff --git a/lib/JLayer1.0.1/jl1.0.1.jar b/lib/JLayer1.0.1/jl1.0.1.jar new file mode 100644 index 0000000..bd5fb8b Binary files /dev/null and b/lib/JLayer1.0.1/jl1.0.1.jar differ diff --git a/manifest b/manifest index aadab34..924042b 100644 --- a/manifest +++ b/manifest @@ -1,3 +1,3 @@ Manifest-Version: 1.0 -Class-Path: ./my.properties ./LocalisedText.properties ./lib/log4j-1.2/log4j-1.2.14.jar ./lib/batik-1.6/lib/batik-transcoder.jar ./lib/batik-1.6/batik.jar ./lib/batik-1.6/lib/batik-util.jar ./lib/batik-1.6/lib/batik-script.jar ./lib/batik-1.6/lib/batik-bridge.jar ./lib/batik-1.6/lib/batik-ext.jar ./lib/batik-1.6/lib/batik-awt-util.jar ./lib/batik-1.6/lib/batik-dom.jar ./lib/batik-1.6/lib/batik-gvt.jar -Main-Class: rails.test.GameTest +Class-Path: ./my.properties ./LocalisedText.properties ./lib/log4j-1.2/log4j-1.2.14.jar ./lib/JLayer1.0.1/jl1.0.1.jar ./lib/batik-1.6/lib/batik-transcoder.jar ./lib/batik-1.6/batik.jar ./lib/batik-1.6/lib/batik-util.jar ./lib/batik-1.6/lib/batik-script.jar ./lib/batik-1.6/lib/batik-bridge.jar ./lib/batik-1.6/lib/batik-ext.jar ./lib/batik-1.6/lib/batik-awt-util.jar ./lib/batik-1.6/lib/batik-dom.jar ./lib/batik-1.6/lib/batik-gvt.jar +Main-Class: rails.util.runGame diff --git a/rails/game/Game.java b/rails/game/Game.java index de85c55..3f7dfa8 100644 --- a/rails/game/Game.java +++ b/rails/game/Game.java @@ -11,6 +11,7 @@ import rails.common.DisplayBuffer; import rails.common.LocalText; import rails.common.parser.*; import rails.game.action.PossibleAction; +import rails.sound.BackgroundMusicManager; import rails.util.GameFileIO; public class Game { @@ -89,6 +90,7 @@ public class Game { log.info("========== Start of rails.game " + name + " =========="); log.info("Rails version "+version); ReportBuffer.add(LocalText.getText("GameIs", name)); + } public String start() { @@ -100,6 +102,7 @@ public class Game { } gameManager.startGame(gameOptions); + return null; } @@ -144,12 +147,16 @@ public class Game { return false; } + BackgroundMusicManager.init(); + return true; } public static Game load(String filepath) { + BackgroundMusicManager.mute(); + // use GameLoader object to load game GameFileIO gameLoader = new GameFileIO(); gameLoader.loadGameData(filepath); @@ -167,6 +174,8 @@ public class Game { DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); } + BackgroundMusicManager.unMute(); + return gameLoader.getGame(); } diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java index 8507931..486b24a 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -17,6 +17,7 @@ import rails.game.move.*; import rails.game.special.SpecialPropertyI; import rails.game.special.SpecialTokenLay; import rails.game.state.*; +import rails.sound.BackgroundMusicManager; import rails.util.GameFileIO; import rails.util.Util; diff --git a/rails/game/OperatingRound.java b/rails/game/OperatingRound.java index d799ad9..c7099a7 100644 --- a/rails/game/OperatingRound.java +++ b/rails/game/OperatingRound.java @@ -11,6 +11,7 @@ import rails.game.correct.OperatingCost; import rails.game.move.*; import rails.game.special.*; import rails.game.state.*; +import rails.sound.BackgroundMusicManager; import rails.util.SequenceUtil; /** @@ -106,6 +107,8 @@ public class OperatingRound extends Round implements Observer { ReportBuffer.add(LocalText.getText("START_OR", thisOrNumber)); + BackgroundMusicManager.notifyOfOperatingRoundStart(); + for (Player player : gameManager.getPlayers()) { player.setWorthAtORStart(); } diff --git a/rails/game/Phase.java b/rails/game/Phase.java index 5b50f25..2e3f7b3 100644 --- a/rails/game/Phase.java +++ b/rails/game/Phase.java @@ -8,6 +8,7 @@ import org.apache.log4j.Logger; import rails.common.LocalText; import rails.common.parser.ConfigurationException; import rails.common.parser.Tag; +import rails.sound.BackgroundMusicManager; import rails.util.Util; public class Phase implements PhaseI { @@ -313,11 +314,14 @@ public class Phase implements PhaseI { } } + BackgroundMusicManager.setPhase(name); + if (actions != null && !actions.isEmpty()) { for (String actionName : actions.keySet()) { gameManager.processPhaseAction (actionName, actions.get(actionName)); } } + } public void setLastTrainBuyer(Portfolio lastTrainBuyer) { diff --git a/rails/game/StockRound.java b/rails/game/StockRound.java index 03bb17a..8728af0 100644 --- a/rails/game/StockRound.java +++ b/rails/game/StockRound.java @@ -8,6 +8,7 @@ import rails.game.action.*; import rails.game.move.*; import rails.game.special.*; import rails.game.state.*; +import rails.sound.BackgroundMusicManager; /** * Implements a basic Stock Round. <p> A new instance must be created for each @@ -86,6 +87,8 @@ public class StockRound extends Round { ReportBuffer.add(LocalText.getText("StartStockRound", getStockRoundNumber())); + BackgroundMusicManager.notifyOfStockRoundStart(); + setCurrentPlayerIndex(gameManager.getPriorityPlayer().getIndex()); startingPlayer = getCurrentPlayer(); // For the Report ReportBuffer.add(LocalText.getText("HasPriority", diff --git a/rails/sound/BackgroundMusicManager.java b/rails/sound/BackgroundMusicManager.java new file mode 100644 index 0000000..de4b411 --- /dev/null +++ b/rails/sound/BackgroundMusicManager.java @@ -0,0 +1,170 @@ +/** + * + */ +package rails.sound; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.util.*; + +import javazoom.jl.player.Player; +import org.apache.log4j.Logger; + +import rails.common.parser.Config; + +/** + * This is a static class as there should never be two + * background musics playing at the same time. + * + * This class is notified of: + * - phase changes (eg., 2-train -> 3-train) + * - round changes (eg., SR -> OR) + * + * Based on this information, the appropriate background music (mp3) is played + * in the background. + */ +public class BackgroundMusicManager { + private static class Context { + public int round; + public String phaseName; + public Context(int round, String phaseName) { + this.round = round; + this.phaseName = phaseName; + } + public boolean equals(Object o) { + if (!(o instanceof Context)) return false; + Context c = (Context)o; + return ((round == c.round) && (phaseName.equals(c.phaseName))); + } + public int hashCode() { + return round+phaseName.hashCode(); + } + public Context clone() { + return new Context(round,phaseName); + } + } + private static final int ROUND_UNDEFINED = -1; + private static final int ROUND_STOCK = 0; + private static final int ROUND_OPERATING = 1; + private static final String PHASENAME_DEFAULT = ""; + private static Map<Context,String> contextToMusicFileMapping = new HashMap<Context,String>(); + private static boolean isDisabled = true; + private static boolean isMute = false; + private static boolean isPlaying = false; + private static String currentMusicFileName; + private static Thread playingThread; + private static Context context = new Context(ROUND_UNDEFINED,PHASENAME_DEFAULT); + private static Logger log = Logger.getLogger(BackgroundMusicManager.class.getPackage().getName()); + + private static void setContextToMusicFileMapping (String config,Context defaultContext) { + if (config == null || config.equals("")) return; + String[] assignments = config.split(","); + for ( int i = 0 ; i < assignments.length ; i++ ) { + String[] assignment = assignments[i].split("="); + Context c = defaultContext.clone(); + if (assignment.length == 1) { + //default assignment (meaning, phase-independent) + contextToMusicFileMapping.put(c, assignment[0]); + } + else if (assignment.length == 2) { + //phase-dependent assignment + c.phaseName = assignment[0]; + contextToMusicFileMapping.put(c, assignment[1]); + } + } + } + public static void init() { + String enablement = Config.get("sound.backgroundMusic"); + if (enablement != null && enablement.equals("enabled")) { + isDisabled = false; + setContextToMusicFileMapping( + Config.get("sound.backgroundMusic.stockRound"), + new Context(ROUND_STOCK,PHASENAME_DEFAULT) + ); + setContextToMusicFileMapping( + Config.get("sound.backgroundMusic.operatingRound"), + new Context(ROUND_OPERATING,PHASENAME_DEFAULT) + ); + playNewMusic(); + } else { + isDisabled = true; + } + + } + public static void setPhase(String name) { + if (!context.phaseName.equals(name)) { + context.phaseName = name; + playNewMusic(); + } + } + public static void notifyOfStockRoundStart() { + if (context.round != ROUND_STOCK) { + context.round = ROUND_STOCK; + playNewMusic(); + } + } + public static void notifyOfOperatingRoundStart() { + if (context.round != ROUND_OPERATING) { + context.round = ROUND_OPERATING; + playNewMusic(); + } + } + public static void mute() { + isMute = true; + stopMusic(); + } + public static void unMute() { + if (!isDisabled) { + isMute = false; + playNewMusic(); + } + } + + private static void playNewMusic() { + if (!isMute) { + if (isPlaying) stopMusic(); + if (contextToMusicFileMapping != null) { + String newMusicFileName = (String)contextToMusicFileMapping.get(context); + if (newMusicFileName == null) { + //try phase-defaulting if nothing was found + newMusicFileName = (String)contextToMusicFileMapping.get(new Context(context.round,PHASENAME_DEFAULT)); + } + //only restart/change the music if a new music file is to be played + if (newMusicFileName != null && !newMusicFileName.equals(currentMusicFileName)) { + currentMusicFileName = newMusicFileName; + // run music playing in new thread to play in background + playingThread = new Thread() { + Player player; + public void run() { + try { + while (!Thread.interrupted()) { + FileInputStream fis = new FileInputStream(currentMusicFileName); + BufferedInputStream bis = new BufferedInputStream(fis); + player = new Player(bis); + log.info("Now playing: "+currentMusicFileName); + player.play(); + } + } + catch (Exception e) { + //if anything goes wrong, don't play anything + log.error(e); + } + } + public void interrupt() { + super.interrupt(); + if (player!=null) player.close(); + } + }; + playingThread.start(); + isPlaying = true; + } + } + } + } + private static void stopMusic() { + if (isPlaying) { + playingThread.interrupt(); + isPlaying = false; + } + } +} commit 0c14f32279f83c1ce5cc5574a5b09570316be8c4 Author: frederickweld <fre...@gm...> Date: Sat Dec 17 15:01:12 2011 +0100 Added option to play 1856 as a 2-player game. The standard rules do not define cert limit & starting cap for this setting. Reasonable values were chosen for these parameters. diff --git a/data/1856/Game.xml b/data/1856/Game.xml index 3a13eb9..330ac4d 100644 --- a/data/1856/Game.xml +++ b/data/1856/Game.xml @@ -8,6 +8,7 @@ <!-- <Option name="NoMapMode" type="toggle" default="no" /> --> <GameOption name="UnlimitedBonusTokens" type="toggle" default="no"/> <GameOption name="LeaveAuctionOnPass" type="toggle" default="no"/> + <GameOption name="TwoPlayersCertLimit70Percent" type="toggle" default="yes"/> <GameOption name="SeparateSalesAtSamePrice" type="toggle" default="yes"/> <GameOption name="1856THBHomeBlocked" type="toggle" default="no" /> <GameParameters> @@ -20,7 +21,15 @@ <EmergencyTrainBuying mustBuyCheapestTrain="yes" mayBuyFromCompany="no"/> </OperatingRound> <ShareSellingRound class="rails.game.specific._1856.ShareSellingRound_1856"/> - <PlayerShareLimit percentage="60"/> + <PlayerShareLimit percentage="60"> + <!-- Option "NumberOfPlayers" is automatically set + by the game engine --> + <IfOption name="NumberOfPlayers" value="2"> + <IfOption name="TwoPlayersCertLimit70Percent" value="yes"> + <Attributes percentage="70"/> + </IfOption> + </IfOption> + </PlayerShareLimit> <BankPoolLimit percentage="50"/> </GameParameters> <GuiClasses> @@ -33,6 +42,7 @@ </EndOfGame> </Component> <Component name="PlayerManager" class="rails.game.PlayerManager"> + <Players number="2" cash="750" certLimit="28"/> <Players number="3" cash="500" certLimit="20"/> <Players number="4" cash="375" certLimit="16"/> <Players number="5" cash="300" certLimit="13"/> diff --git a/data/GamesList.xml b/data/GamesList.xml index 0e0c25e..4286a01 100644 --- a/data/GamesList.xml +++ b/data/GamesList.xml @@ -102,7 +102,8 @@ Limitation: <Option name="LeaveAuctionOnPass" type="toggle" default="no"/> <Option name="SeparateSalesAtSamePrice" type="toggle" default="yes"/> <Option name="1856THBHomeBlocked" type="toggle" default="no" /> - <Players minimum="3" maximum="6"/> + <Option name="TwoPlayersCertLimit70Percent" type="toggle" default="no"/> + <Players minimum="2" maximum="6"/> </Game> <Game name="1889"> diff --git a/rails/game/specific/_1856/CGRFormationRound.java b/rails/game/specific/_1856/CGRFormationRound.java index f7066e7..2df04f8 100644 --- a/rails/game/specific/_1856/CGRFormationRound.java +++ b/rails/game/specific/_1856/CGRFormationRound.java @@ -44,6 +44,7 @@ public class CGRFormationRound extends SwitchableUIRound { public static final int STEP_EXCHANGE_TOKENS = 3; private static int[][] certLimitsTable = { + {14, 19, 21, 26, 29, 31, 36, 40}, {10, 13, 15, 18, 20, 22, 25, 28}, {8, 10, 12, 14, 16, 18, 20, 22}, {7, 8, 10, 11, 13, 15, 16, 18}, @@ -511,7 +512,7 @@ public class CGRFormationRound extends SwitchableUIRound { int numCompanies = Math.min(11, 12-mergingCompanies.size()); int numPlayers = gameManager.getNumberOfPlayers(); // Need some checks here... - int newCertLimit = certLimitsTable[numPlayers-3][numCompanies-4]; + int newCertLimit = certLimitsTable[numPlayers-2][numCompanies-4]; gameManager.setPlayerCertificateLimit(newCertLimit); message = LocalText.getText("CertificateLimit", newCertLimit, |