You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(3) |
Nov
(46) |
Dec
(57) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(51) |
Feb
(10) |
Mar
|
Apr
|
May
(14) |
Jun
|
Jul
(13) |
Aug
(30) |
Sep
(83) |
Oct
(56) |
Nov
(148) |
Dec
(107) |
2010 |
Jan
(260) |
Feb
(164) |
Mar
(183) |
Apr
(99) |
May
(160) |
Jun
(40) |
Jul
(33) |
Aug
(48) |
Sep
(22) |
Oct
(24) |
Nov
(1) |
Dec
(12) |
2011 |
Jan
(6) |
Feb
(15) |
Mar
(13) |
Apr
(37) |
May
(27) |
Jun
(29) |
Jul
(33) |
Aug
(20) |
Sep
(17) |
Oct
(20) |
Nov
(33) |
Dec
(17) |
2012 |
Jan
(39) |
Feb
(38) |
Mar
(20) |
Apr
(21) |
May
(17) |
Jun
(22) |
Jul
(16) |
Aug
(3) |
Sep
(9) |
Oct
(10) |
Nov
|
Dec
|
From: Frederick W. <fre...@us...> - 2012-02-04 15:58:30
|
.classpath | 4 LocalisedText.properties | 10 + build.xml | 4 buildRails.xml | 4 data/Properties.xml | 4 lib/df_1.1.0/dockingFramesCommon.jar |binary lib/df_1.1.0/dockingFramesCore.jar |binary manifest | 2 rails/sound/SoundConfig.java | 3 rails/sound/SoundEventInterpreter.java | 9 + rails/ui/swing/GameUIManager.java | 1 rails/ui/swing/ORPanel.java | 85 ++++++++++++++-- rails/ui/swing/ORWindow.java | 170 +++++++++++++++++++++++++++++---- rails/ui/swing/UpgradesPanel.java | 18 +++ 14 files changed, 278 insertions(+), 36 deletions(-) New commits: commit 08f42f7eecaf26eca424b1f5012ecbd2e831fc21 Author: Frederick Weld <fre...@gm...> Date: Sat Feb 4 16:47:17 2012 +0100 Added saving/restoring dockable panel layout on a per-game basis Layout files (xml) are persisted into a dedicated subfolder of the save game folder. Each game has a specific layout associated to it. diff --git a/rails/ui/swing/GameUIManager.java b/rails/ui/swing/GameUIManager.java index 72a3aa7..f281034 100644 --- a/rails/ui/swing/GameUIManager.java +++ b/rails/ui/swing/GameUIManager.java @@ -126,6 +126,7 @@ public class GameUIManager implements DialogOwner { public void terminate () { getWindowSettings ().save(); + if (orWindow != null) orWindow.saveDockableLayout(); System.exit(0); } diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java index 7e28b47..5f75ad9 100644 --- a/rails/ui/swing/ORWindow.java +++ b/rails/ui/swing/ORWindow.java @@ -4,6 +4,7 @@ package rails.ui.swing; import java.awt.BorderLayout; import java.awt.Rectangle; import java.awt.event.*; +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -46,6 +47,11 @@ public class ORWindow extends JFrame implements ActionPerformer { List<LayTile> allowedTileLays = new ArrayList<LayTile>(); List<LayToken> allowedTokenLays = new ArrayList<LayToken>(); + CControl orWindowControl = null; + + private static final String layoutFolderName = "DockableLayout"; + private static final String layoutFileSuffix = "_layout.rails_ini"; + protected static Logger log = Logger.getLogger(ORWindow.class.getPackage().getName()); @@ -82,7 +88,7 @@ public class ORWindow extends JFrame implements ActionPerformer { //DOCKABLE LAYOUT //build the docking layout - CControl orWindowControl = new CControl( this ); + orWindowControl = new CControl( this ); orWindowControl.setTheme( ThemeMap.KEY_SMOOTH_THEME ); add( orWindowControl.getContentArea() ); CGrid orWindowLayout = new CGrid( orWindowControl ); @@ -164,6 +170,7 @@ public class ORWindow extends JFrame implements ActionPerformer { addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { + saveDockableLayout(); StatusWindow.uncheckMenuItemBox(StatusWindow.MAP_CMD); frame.dispose(); } @@ -191,6 +198,9 @@ public class ORWindow extends JFrame implements ActionPerformer { ws.set(frame); gameUIManager.reportWindow.updateLog(); + + //dockable panes: restore former layout (depending on game variant) + loadDockableLayout(); } public ORUIManager getORUIManager() { @@ -295,4 +305,51 @@ public class ORWindow extends JFrame implements ActionPerformer { public boolean isDockablePanelsEnabled() { return "yes".equals(Config.get("or.window.dockablePanels")); } + + + private String getLayoutName() { + return getClass().getSimpleName() + "_" + + gameUIManager.getGameManager().getGameName() ; + } + + private File getLayoutFile() { + try { + //get layout folder (and ensure that it is available) + File layoutFolder = new File(Config.get("save.directory"),layoutFolderName); + if (!layoutFolder.isDirectory()) { + layoutFolder.mkdirs(); + } + File layoutFile = new File(layoutFolder, + getLayoutName() + layoutFileSuffix ); + return layoutFile; + } catch (Exception e) { + //return no valid file if anything goes wrong + return null; + } + } + + public void saveDockableLayout() { + if (!isDockablePanelsEnabled()) return; + + File layoutFile = getLayoutFile(); + if (layoutFile != null) { + try { + orWindowControl.save(getLayoutName()); + orWindowControl.writeXML(layoutFile); + } catch (Exception e) {} //skip in case of issue + } + } + + private void loadDockableLayout() { + if (!isDockablePanelsEnabled()) return; + + File layoutFile = getLayoutFile(); + if (layoutFile != null) { + try { + orWindowControl.readXML(layoutFile); + orWindowControl.load(getLayoutName()); + } catch (Exception e) {} //skip if layout not found + } + } + } commit e1cada7237772dca0022a66e90f0bff0cb592c44 Author: Frederick Weld <fre...@gm...> Date: Sat Feb 4 07:25:35 2012 +0100 Rendered button panel as dockable pane (detachable from OR panel) Change only applies if config option for dockable or window panels is set. Button panel's sizing is also adjusted in order to allow for both vertical / horizontal / grid layouts of the buttons. As a pre-condition, the buttons are all given the same size. Added localized texts for the dock titles. diff --git a/LocalisedText.properties b/LocalisedText.properties index 86bdea9..071d381 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -288,6 +288,11 @@ DiscardsBaseToken={0} discards a {1} base token on {2} DoesNotExist=Item does not exist DoesNotForm={0} does not form DoesNotHaveTheShares=Does not have the shares +DockableTitle.orWindow.messagePanel = Messages +DockableTitle.orWindow.upgradePanel = Upgrades +DockableTitle.orWindow.mapPanel = Map +DockableTitle.orWindow.orPanel = Companies +DockableTitle.orWindow.buttonPanel = Commands 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. diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java index cdaad11..453db01 100644 --- a/rails/ui/swing/ORPanel.java +++ b/rails/ui/swing/ORPanel.java @@ -4,6 +4,7 @@ package rails.ui.swing; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javax.swing.*; @@ -160,7 +161,11 @@ implements ActionListener, KeyListener, RevenueListener { setLayout(new BorderLayout()); add(statusPanel, BorderLayout.CENTER); - add(buttonPanel, BorderLayout.SOUTH); + + //only add button panel directly for conventional layout + if (!parent.isDockablePanelsEnabled()) { + add(buttonPanel, BorderLayout.SOUTH); + } menuBar = new JMenuBar(); @@ -268,8 +273,7 @@ implements ActionListener, KeyListener, RevenueListener { } private void initButtonPanel() { - buttonPanel = new JPanel(); - + // sfy: operatingcosts button buttonOC = new ActionButton(LocalText.getText("OCButtonLabel")); buttonOC.setActionCommand(OPERATING_COST_CMD); @@ -277,14 +281,12 @@ implements ActionListener, KeyListener, RevenueListener { buttonOC.addActionListener(this); buttonOC.setEnabled(false); buttonOC.setVisible(false); - buttonPanel.add(buttonOC); button1 = new ActionButton(LocalText.getText("LayTile")); button1.setActionCommand(LAY_TILE_CMD); button1.setMnemonic(KeyEvent.VK_T); button1.addActionListener(this); - button1.setEnabled(true); - buttonPanel.add(button1); + button1.setEnabled(false); button2 = new ActionButton(LocalText.getText("BUY_PRIVATE")); button2.setActionCommand(BUY_PRIVATE_CMD); @@ -292,30 +294,88 @@ implements ActionListener, KeyListener, RevenueListener { button2.addActionListener(this); button2.setEnabled(false); button2.setVisible(false); - buttonPanel.add(button2); button3 = new ActionButton(LocalText.getText("Done")); button3.setActionCommand(DONE_CMD); button3.setMnemonic(KeyEvent.VK_D); button3.addActionListener(this); - button3.setEnabled(true); - buttonPanel.add(button3); + button3.setEnabled(false); undoButton = new ActionButton(LocalText.getText("UNDO")); undoButton.setActionCommand(UNDO_CMD); undoButton.setMnemonic(KeyEvent.VK_U); undoButton.addActionListener(this); undoButton.setEnabled(false); - buttonPanel.add(undoButton); redoButton = new ActionButton(LocalText.getText("REDO")); redoButton.setActionCommand(REDO_CMD); redoButton.setMnemonic(KeyEvent.VK_R); redoButton.addActionListener(this); redoButton.setEnabled(false); + + //choose button panel layout depending on whether panel becomes a dockable + if (orWindow.isDockablePanelsEnabled()) { + + //customized panel for dockable layout + //the minimal size is defined by the size of one button + //(aim here: user can choose whether buttons are laid out + // vertically or horizontally or in a grid, since + // the minimal size's restriction is minimal indeed.) + buttonPanel = new JPanel() { + private static final long serialVersionUID = 1L; + @Override + public Dimension getMinimumSize() { + int width = 0; + int height = 0; + if (getComponents().length != 0) { + //getting the first component is sufficient as their + //size is all the same + width = getComponents()[0].getPreferredSize().width; + height = getComponents()[0].getPreferredSize().height; + } + //add a margin + width += 10; + height += 10; + return new Dimension(width,height); + } + public Dimension getPreferredSize() { + return getMinimumSize(); + } + }; + + } else { + //plain panel for conventional layout + buttonPanel = new JPanel(); + } + + buttonPanel.add(buttonOC); + buttonPanel.add(button1); + buttonPanel.add(button2); + buttonPanel.add(button3); + buttonPanel.add(undoButton); buttonPanel.add(redoButton); + //for dockable button panel, ensure that all buttons have the same size + //(necessary, otherwise vertical/box layout will look ugly) + if (orWindow.isDockablePanelsEnabled()) { + + //get maximum size + Dimension maxSize = new Dimension(); + for (Component c : Arrays.asList( buttonPanel.getComponents() )) { + if (c.getPreferredSize().width > maxSize.width) + maxSize.width = c.getPreferredSize().width; + if (c.getPreferredSize().height > maxSize.height) + maxSize.height = c.getPreferredSize().height; + } + //apply maximum size to all buttons + for (Component c : Arrays.asList( buttonPanel.getComponents() )) { + c.setPreferredSize(maxSize); + } + + } + buttonPanel.setOpaque(true); + } public MouseListener getCompanyCaptionMouseClickListener() { @@ -1288,6 +1348,9 @@ implements ActionListener, KeyListener, RevenueListener { public PublicCompanyI[] getOperatingCompanies() { return companies; } - + + public JPanel getButtonPanel() { + return buttonPanel; + } } \ No newline at end of file diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java index 10480c5..7e28b47 100644 --- a/rails/ui/swing/ORWindow.java +++ b/rails/ui/swing/ORWindow.java @@ -95,33 +95,40 @@ public class ORWindow extends JFrame implements ActionPerformer { } //add message panel - DefaultSingleCDockable singleDockable = new DefaultSingleCDockable( - "MessagePanel", "MessagePanel" ); + String dockableName = LocalText.getText("DockableTitle.orWindow.messagePanel"); + DefaultSingleCDockable singleDockable = new DefaultSingleCDockable( dockableName, dockableName ); singleDockable.add( slider, BorderLayout.CENTER ); singleDockable.setCloseable( false ); orWindowLayout.add( 0, 0, 100, 10, singleDockable ); //add upgrade panel - singleDockable = new DefaultSingleCDockable( - "UpgradePanel", "UpgradePanel" ); + dockableName = LocalText.getText("DockableTitle.orWindow.upgradePanel"); + singleDockable = new DefaultSingleCDockable( dockableName, dockableName ); singleDockable.add( upgradePanel, BorderLayout.CENTER ); singleDockable.setCloseable( false ); orWindowLayout.add( 0, 10, 20, 70, singleDockable ); //add map panel - singleDockable = new DefaultSingleCDockable( - "MapPanel", "MapPanel" ); + dockableName = LocalText.getText("DockableTitle.orWindow.mapPanel"); + singleDockable = new DefaultSingleCDockable( dockableName, dockableName ); singleDockable.add( mapPanel, BorderLayout.CENTER ); singleDockable.setCloseable( false ); orWindowLayout.add( 20, 10, 80, 70, singleDockable ); //add or panel - singleDockable = new DefaultSingleCDockable( - "ORPanel", "ORPanel" ); + dockableName = LocalText.getText("DockableTitle.orWindow.orPanel"); + singleDockable = new DefaultSingleCDockable( dockableName, dockableName ); singleDockable.add( orPanel, BorderLayout.CENTER ); singleDockable.setCloseable( false ); - orWindowLayout.add( 0, 80, 100, 20, singleDockable ); + orWindowLayout.add( 0, 80, 100, 15, singleDockable ); + //add button panel of or panel + dockableName = LocalText.getText("DockableTitle.orWindow.buttonPanel"); + singleDockable = new DefaultSingleCDockable( dockableName, dockableName ); + singleDockable.add( orPanel.getButtonPanel(), BorderLayout.CENTER ); + singleDockable.setCloseable( false ); + orWindowLayout.add( 0, 95, 100, 5, singleDockable ); + orWindowControl.getContentArea().deploy( orWindowLayout ); } else { commit c6880f1e074772b3ae60437e0239351b2e8745a0 Author: Frederick Weld <fre...@gm...> Date: Sat Feb 4 07:13:01 2012 +0100 Added sfx option for lay tile to distinguish between city / track upgrades diff --git a/LocalisedText.properties b/LocalisedText.properties index 5025b59..86bdea9 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -226,7 +226,8 @@ Config.label.sound.sfx.or.buyTrain=Buy Train (several files) Config.label.sound.sfx.or.decision.payout=Payout Revenue Config.label.sound.sfx.or.decision.split=Split Revenue Config.label.sound.sfx.or.decision.withhold=Withhold Revenue -Config.label.sound.sfx.or.layTile=Lay Tile +Config.label.sound.sfx.or.layTile.city=Lay Tile (city) +Config.label.sound.sfx.or.layTile.track=Lay Tile (track, town) Config.label.sound.sfx.or.layToken=Lay Token Config.label.sound.sfx.or.rotateTile=Rotate Tile Config.label.sound.sfx.or.setRevenue=Set Revenue diff --git a/data/Properties.xml b/data/Properties.xml index 972596e..4802f74 100644 --- a/data/Properties.xml +++ b/data/Properties.xml @@ -87,7 +87,8 @@ <Property name="sound.sfx.sr.sellShare.nonPresident" type="FILE" /> <Property name="sound.sfx.sr.companyFloats" type="FILE" /> <Property name="sound.sfx.or.rotateTile" type="FILE" /> - <Property name="sound.sfx.or.layTile" type="FILE" /> + <Property name="sound.sfx.or.layTile.track" type="FILE" /> + <Property name="sound.sfx.or.layTile.city" type="FILE" /> <Property name="sound.sfx.or.layToken" type="FILE" /> <Property name="sound.sfx.or.setRevenue" type="FILE" /> <Property name="sound.sfx.or.decision.payout" type="FILE" /> diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index 4e86877..6867ddf 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -37,7 +37,8 @@ public class SoundConfig { public static final String KEY_SFX_SR_SellShare_NonPresident = "sound.sfx.sr.sellShare.nonPresident"; public static final String KEY_SFX_SR_CompanyFloats = "sound.sfx.sr.companyFloats"; public static final String KEY_SFX_OR_RotateTile = "sound.sfx.or.rotateTile"; - public static final String KEY_SFX_OR_LayTile = "sound.sfx.or.layTile"; + public static final String KEY_SFX_OR_LayTile_track = "sound.sfx.or.layTile.track"; + public static final String KEY_SFX_OR_LayTile_city = "sound.sfx.or.layTile.city"; public static final String KEY_SFX_OR_LayToken = "sound.sfx.or.layToken"; public static final String KEY_SFX_OR_SetRevenue = "sound.sfx.or.setRevenue"; public static final String KEY_SFX_OR_Decision_Payout = "sound.sfx.or.decision.payout"; diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java index ac6e640..48a8df2 100644 --- a/rails/sound/SoundEventInterpreter.java +++ b/rails/sound/SoundEventInterpreter.java @@ -102,7 +102,14 @@ public class SoundEventInterpreter { //OR actions else if (action instanceof LayTile) { - player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile); + LayTile lt = (LayTile)action; + if (lt.getLaidTile().getNumStations() == 0) { + //track upgrade + player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_track); + } else { + //city upgrade + player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_city); + } } else if (action instanceof LayToken) { player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayToken); commit 31fbe3a41c5f5c3e6331e23cb3a0f37c66840336 Author: Frederick Weld <fre...@gm...> Date: Fri Feb 3 16:36:05 2012 +0100 Aligned upgrade tile zoomstep with the hex map (dockable or panes only) Now, upgrade panel tiles are displayed in the same zoom step as the tiles of the map. This wasn't possible before as the upgrade panel's width couldn't be adjusted manually. diff --git a/rails/ui/swing/UpgradesPanel.java b/rails/ui/swing/UpgradesPanel.java index 1ac2332..02556b6 100644 --- a/rails/ui/swing/UpgradesPanel.java +++ b/rails/ui/swing/UpgradesPanel.java @@ -235,7 +235,7 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener if (tempGUITile != null) { //tile has been rotated to valid orientation //get unscaled image for this orientation - hexImage = tempGUITile.getTileImage(UPGRADE_TILE_ZOOM_STEP); + hexImage = tempGUITile.getTileImage(getZoomStep()); } } @@ -399,7 +399,21 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener } private BufferedImage getHexImage(int tileId) { - return GameUIManager.getImageLoader().getTile(tileId, UPGRADE_TILE_ZOOM_STEP); + return GameUIManager.getImageLoader().getTile(tileId, getZoomStep()); + } + + /** + * @return Default zoom step for conventional panes or, for dockable panes, + * the zoom step used in the map. + * Map zoom step can only be used for dockable panes as user-based pane sizing + * could be necessary when displaying tiles of an arbitrary size + */ + private int getZoomStep() { + if (orUIManager.getORWindow().isDockablePanelsEnabled()) { + return hexMap.getZoomStep(); + } else { + return UPGRADE_TILE_ZOOM_STEP; + } } @Override commit c16e31e8b9cf0014dfcc78c3833f5917e5b469ca Author: Frederick Weld <fre...@gm...> Date: Fri Feb 3 16:24:15 2012 +0100 Added option for dockable panels of OR window (disabled by default) The conventional layout has been reincluded into OR window ==> both conventional / docking mode are supported. Furthermore, fixed an issue with transferring rails default locale to the docking framework (if it was en_us). diff --git a/LocalisedText.properties b/LocalisedText.properties index b8ff06d..5025b59 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -173,6 +173,7 @@ Config.infoText.default_players=Enter player names separated by commas. Config.infoText.gridPanel.tableBorders=Grid layouts are used for the Status Window and the panel of the Operating Round Window. Config.infoText.map.displayCurrentRoutes=If enabled, optimal train routes are displayed for the company which is currently taking its turn. Config.infoText.map.highlightHexes=<html>If enabled, parts of the map are highlighted depending on the position of the mouse pointer:<ul><li><b>Private companies:</b> Point to the name of a private company in order to highlight the locations associated with it (e.g., its reserved hex).<ul><li>If you point to a set of private companies (in the player or company holding), the locations of all contained private companies are highlighted</ul><li><b>Minor & Public Companies:</b> Point to the name of the company in order to highlight the locations associated with it (home and destination).</ul></html> +Config.infoText.or.window.dockablePanels=<html>This alters the window of the Operating Round. If enabled, allows for the following:<ul><li>Manually resize panels.<li>Manually adjust the layout of the panels within the window.<li>Detach / retach panel from / to window.</ul></html> Config.infoText.sound.backgroundMusic=The only music file type supported is mp3. Config.infoText.sound.backgroundMusic.stockRound=<html>Enter assignment of music files 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 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> @@ -197,6 +198,7 @@ Config.label.map.highlightHexes=Highlight company locations Config.label.map.zoomstep=Map zoomstep Config.label.money_format=Money format Config.label.or.number_format=OR number format +Config.label.or.window.dockablePanels=Flexible panels for operating round Config.label.report.directory=Report directory Config.label.report.filename.date_time_pattern=Report filename date pattern Config.label.report.filename.extension=Report filename extension diff --git a/data/Properties.xml b/data/Properties.xml index a5b1e51..972596e 100644 --- a/data/Properties.xml +++ b/data/Properties.xml @@ -40,6 +40,7 @@ <Property name="report.window.open" type="BOOLEAN" /> <Property name="report.window.editable" type="BOOLEAN" /> <Property name="stockchart.window.open" type="BOOLEAN" /> + <Property name="or.window.dockablePanels" type="BOOLEAN" /> </Section> <Section name="Format"> <Property name="money_format" type="STRING" /> diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java index 7fcb336..10480c5 100644 --- a/rails/ui/swing/ORWindow.java +++ b/rails/ui/swing/ORWindow.java @@ -6,6 +6,7 @@ import java.awt.Rectangle; import java.awt.event.*; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import javax.swing.JFrame; import javax.swing.JOptionPane; @@ -20,6 +21,7 @@ import bibliothek.gui.dock.common.theme.ThemeMap; import rails.common.GuiDef; import rails.common.LocalText; +import rails.common.parser.Config; import rails.game.GameManager; import rails.game.OperatingRound; import rails.game.action.*; @@ -75,41 +77,63 @@ public class ORWindow extends JFrame implements ActionPerformer { orPanel = new ORPanel(this, orUIManager); - //build the docking layout - CControl orWindowControl = new CControl( this ); - orWindowControl.setTheme( ThemeMap.KEY_SMOOTH_THEME ); - add( orWindowControl.getContentArea() ); - CGrid orWindowLayout = new CGrid( orWindowControl ); - - //add message panel - DefaultSingleCDockable singleDockable = new DefaultSingleCDockable( - "MessagePanel", "MessagePanel" ); - singleDockable.add( slider, BorderLayout.CENTER ); - singleDockable.setCloseable( false ); - orWindowLayout.add( 0, 0, 100, 10, singleDockable ); - - //add upgrade panel - singleDockable = new DefaultSingleCDockable( - "UpgradePanel", "UpgradePanel" ); - singleDockable.add( upgradePanel, BorderLayout.CENTER ); - singleDockable.setCloseable( false ); - orWindowLayout.add( 0, 10, 20, 70, singleDockable ); - - //add map panel - singleDockable = new DefaultSingleCDockable( - "MapPanel", "MapPanel" ); - singleDockable.add( mapPanel, BorderLayout.CENTER ); - singleDockable.setCloseable( false ); - orWindowLayout.add( 20, 10, 80, 70, singleDockable ); - - //add or panel - singleDockable = new DefaultSingleCDockable( - "ORPanel", "ORPanel" ); - singleDockable.add( orPanel, BorderLayout.CENTER ); - singleDockable.setCloseable( false ); - orWindowLayout.add( 0, 80, 100, 20, singleDockable ); - - orWindowControl.getContentArea().deploy( orWindowLayout ); + //create docking / conventional layout depending config + if (isDockablePanelsEnabled()) { + //DOCKABLE LAYOUT + + //build the docking layout + CControl orWindowControl = new CControl( this ); + orWindowControl.setTheme( ThemeMap.KEY_SMOOTH_THEME ); + add( orWindowControl.getContentArea() ); + CGrid orWindowLayout = new CGrid( orWindowControl ); + + //set docks tooltip language + if ("en_us".equalsIgnoreCase(Config.get("locale"))) { + //hard setting to default in case of US as this is DockingFrames default language + //don't use Locale constant as it is en_US (case sensitive) + orWindowControl.setLanguage(new Locale("")); + } + + //add message panel + DefaultSingleCDockable singleDockable = new DefaultSingleCDockable( + "MessagePanel", "MessagePanel" ); + singleDockable.add( slider, BorderLayout.CENTER ); + singleDockable.setCloseable( false ); + orWindowLayout.add( 0, 0, 100, 10, singleDockable ); + + //add upgrade panel + singleDockable = new DefaultSingleCDockable( + "UpgradePanel", "UpgradePanel" ); + singleDockable.add( upgradePanel, BorderLayout.CENTER ); + singleDockable.setCloseable( false ); + orWindowLayout.add( 0, 10, 20, 70, singleDockable ); + + //add map panel + singleDockable = new DefaultSingleCDockable( + "MapPanel", "MapPanel" ); + singleDockable.add( mapPanel, BorderLayout.CENTER ); + singleDockable.setCloseable( false ); + orWindowLayout.add( 20, 10, 80, 70, singleDockable ); + + //add or panel + singleDockable = new DefaultSingleCDockable( + "ORPanel", "ORPanel" ); + singleDockable.add( orPanel, BorderLayout.CENTER ); + singleDockable.setCloseable( false ); + orWindowLayout.add( 0, 80, 100, 20, singleDockable ); + + orWindowControl.getContentArea().deploy( orWindowLayout ); + + } else { + // CONVENTIONAL LAYOUT + + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(slider, BorderLayout.NORTH); + getContentPane().add(mapPanel, BorderLayout.CENTER); + getContentPane().add(upgradePanel, BorderLayout.WEST); + getContentPane().add(orPanel, BorderLayout.SOUTH); + + } orUIManager.init(this); @@ -148,7 +172,10 @@ public class ORWindow extends JFrame implements ActionPerformer { } }); - //pack(); + //rearrange layout only if no docking framework active + if (!isDockablePanelsEnabled()) { + pack(); + } WindowSettings ws = gameUIManager.getWindowSettings(); Rectangle bounds = ws.getBounds(this); @@ -207,7 +234,10 @@ public class ORWindow extends JFrame implements ActionPerformer { } public void repaintORPanel() { - //orPanel.revalidate(); + //rearrange layout only if no docking framework active + if (!isDockablePanelsEnabled()) { + orPanel.revalidate(); + } } public void activate(OperatingRound or) { @@ -219,14 +249,17 @@ public class ORWindow extends JFrame implements ActionPerformer { gameManager.getORId(), String.valueOf(gameManager.getRelativeORNumber()), numORs )); - /* - pack(); - if (lastBounds != null) { - Rectangle newBounds = getBounds(); - lastBounds.width = newBounds.width; - setBounds (lastBounds); + + //rearrange layout only if no docking framework active + if (!isDockablePanelsEnabled()) { + pack(); + if (lastBounds != null) { + Rectangle newBounds = getBounds(); + lastBounds.width = newBounds.width; + setBounds (lastBounds); + } } - */ + setVisible(true); requestFocus(); } @@ -251,4 +284,8 @@ public class ORWindow extends JFrame implements ActionPerformer { messagePanel.setMessage(""); setTitle(LocalText.getText("MapWindowTitle")); } + + public boolean isDockablePanelsEnabled() { + return "yes".equals(Config.get("or.window.dockablePanels")); + } } commit 2608a348b7b6dfe37b77fc3de3543905e9cf1a5f Author: Frederick Weld <fre...@gm...> Date: Thu Feb 2 13:35:06 2012 +0100 Put ORWindow on docking framework (panels stay as they were before) diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java index 5c6f5bb..7fcb336 100644 --- a/rails/ui/swing/ORWindow.java +++ b/rails/ui/swing/ORWindow.java @@ -13,6 +13,11 @@ import javax.swing.JScrollPane; import org.apache.log4j.Logger; +import bibliothek.gui.dock.common.CControl; +import bibliothek.gui.dock.common.CGrid; +import bibliothek.gui.dock.common.DefaultSingleCDockable; +import bibliothek.gui.dock.common.theme.ThemeMap; + import rails.common.GuiDef; import rails.common.LocalText; import rails.game.GameManager; @@ -59,24 +64,52 @@ public class ORWindow extends JFrame implements ActionPerformer { gameUIManager.setORUIManager(orUIManager); orUIManager.setGameUIManager(gameUIManager); - getContentPane().setLayout(new BorderLayout()); - messagePanel = new MessagePanel(); JScrollPane slider = new JScrollPane(messagePanel); messagePanel.setParentSlider(slider); - getContentPane().add(slider, BorderLayout.NORTH); - - mapPanel = new MapPanel(gameUIManager); - getContentPane().add(mapPanel, BorderLayout.CENTER); - - upgradePanel = new UpgradesPanel(orUIManager); - getContentPane().add(upgradePanel, BorderLayout.WEST); addMouseListener(upgradePanel); + mapPanel = new MapPanel(gameUIManager); + orPanel = new ORPanel(this, orUIManager); - getContentPane().add(orPanel, BorderLayout.SOUTH); + + //build the docking layout + CControl orWindowControl = new CControl( this ); + orWindowControl.setTheme( ThemeMap.KEY_SMOOTH_THEME ); + add( orWindowControl.getContentArea() ); + CGrid orWindowLayout = new CGrid( orWindowControl ); + + //add message panel + DefaultSingleCDockable singleDockable = new DefaultSingleCDockable( + "MessagePanel", "MessagePanel" ); + singleDockable.add( slider, BorderLayout.CENTER ); + singleDockable.setCloseable( false ); + orWindowLayout.add( 0, 0, 100, 10, singleDockable ); + + //add upgrade panel + singleDockable = new DefaultSingleCDockable( + "UpgradePanel", "UpgradePanel" ); + singleDockable.add( upgradePanel, BorderLayout.CENTER ); + singleDockable.setCloseable( false ); + orWindowLayout.add( 0, 10, 20, 70, singleDockable ); + + //add map panel + singleDockable = new DefaultSingleCDockable( + "MapPanel", "MapPanel" ); + singleDockable.add( mapPanel, BorderLayout.CENTER ); + singleDockable.setCloseable( false ); + orWindowLayout.add( 20, 10, 80, 70, singleDockable ); + + //add or panel + singleDockable = new DefaultSingleCDockable( + "ORPanel", "ORPanel" ); + singleDockable.add( orPanel, BorderLayout.CENTER ); + singleDockable.setCloseable( false ); + orWindowLayout.add( 0, 80, 100, 20, singleDockable ); + + orWindowControl.getContentArea().deploy( orWindowLayout ); orUIManager.init(this); @@ -115,7 +148,7 @@ public class ORWindow extends JFrame implements ActionPerformer { } }); - pack(); + //pack(); WindowSettings ws = gameUIManager.getWindowSettings(); Rectangle bounds = ws.getBounds(this); @@ -174,7 +207,7 @@ public class ORWindow extends JFrame implements ActionPerformer { } public void repaintORPanel() { - orPanel.revalidate(); + //orPanel.revalidate(); } public void activate(OperatingRound or) { @@ -186,12 +219,14 @@ public class ORWindow extends JFrame implements ActionPerformer { gameManager.getORId(), String.valueOf(gameManager.getRelativeORNumber()), numORs )); + /* pack(); if (lastBounds != null) { Rectangle newBounds = getBounds(); lastBounds.width = newBounds.width; setBounds (lastBounds); } + */ setVisible(true); requestFocus(); } commit 06e5c945cc5c977af10f383edb704c23325d319e Author: Frederick Weld <fre...@gm...> Date: Thu Feb 2 12:13:54 2012 +0100 Added DockingFrames library (LGPL licenced) diff --git a/.classpath b/.classpath index c705fd7..4dd2569 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <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 excluding="lib/JLayer1.0.1/|lib/df_1.1.0/|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"/> @@ -27,5 +27,7 @@ <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"/> <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-codec.jar"/> + <classpathentry kind="lib" path="lib/df_1.1.0/dockingFramesCommon.jar"/> + <classpathentry kind="lib" path="lib/df_1.1.0/dockingFramesCore.jar"/> <classpathentry kind="output" path="classes"/> </classpath> diff --git a/build.xml b/build.xml index f58cc8f..c098278 100644 --- a/build.xml +++ b/build.xml @@ -18,6 +18,8 @@ <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/df_1.1.0/dockingFramesCommon.jar"/> + <pathelement location="lib/df_1.1.0/dockingFramesCore.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"/> @@ -50,6 +52,7 @@ <exclude name="lib/batik-1.7/lib/"/> <exclude name="lib/batik-1.7/lib/"/> <exclude name="lib/JLayer1.0.1"/> + <exclude name="lib/df_1.1.0"/> <exclude name="lib/jgraph5/"/> <exclude name="lib/jgraph5/"/> <exclude name="lib/jgrapht-0.7.3/"/> @@ -75,6 +78,7 @@ <exclude name="lib/batik-1.7/lib/"/> <exclude name="lib/batik-1.7/lib/"/> <exclude name="lib/JLayer1.0.1"/> + <exclude name="lib/df_1.1.0"/> <exclude name="lib/jgraph5/"/> <exclude name="lib/jgraph5/"/> <exclude name="lib/jgrapht-0.7.3/"/> diff --git a/buildRails.xml b/buildRails.xml index e656d8a..07b6d96 100644 --- a/buildRails.xml +++ b/buildRails.xml @@ -65,6 +65,8 @@ <include name="jgraph5/jgraph.jar" /> <include name="junit-4.8.2/junit.jar" /> <include name="JLayer1.0.1/jl1.0.1.jar"/> + <include name="lib/df_1.1.0/dockingFramesCommon.jar"/> + <include name="lib/df_1.1.0/dockingFramesCore.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" /> @@ -110,6 +112,8 @@ ./lib/jgraph5/jgraph.jar ./lib/junit-4.8.2/junit.jar ./lib/JLayer1.0.1/jl1.0.1.jar + ./lib/df_1.1.0/dockingFramesCommon.jar + ./lib/df_1.1.0/dockingFramesCore.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/lib/df_1.1.0/dockingFramesCommon.jar b/lib/df_1.1.0/dockingFramesCommon.jar new file mode 100644 index 0000000..e07f52e Binary files /dev/null and b/lib/df_1.1.0/dockingFramesCommon.jar differ diff --git a/lib/df_1.1.0/dockingFramesCore.jar b/lib/df_1.1.0/dockingFramesCore.jar new file mode 100644 index 0000000..0ef9fe9 Binary files /dev/null and b/lib/df_1.1.0/dockingFramesCore.jar differ diff --git a/manifest b/manifest index 924042b..2c8d7aa 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/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 +Class-Path: ./my.properties ./LocalisedText.properties ./lib/log4j-1.2/log4j-1.2.14.jar ./lib/df_1.1.0/dockingFramesCommon.jar ./lib/df_1.1.0/dockingFramesCore.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 |
From: Erik V. <ev...@us...> - 2012-02-03 20:12:36
|
rails/game/specific/_18EU/StartCompany_18EU.java | 20 - rails/ui/swing/GameStatus.java | 2 rails/ui/swing/GameUIManager.java | 77 +++--- rails/ui/swing/ORUIManager.java | 32 +- rails/ui/swing/StartRoundWindow.java | 5 rails/ui/swing/elements/CheckBoxDialog.java | 11 rails/ui/swing/elements/ConfirmationDialog.java | 111 +-------- rails/ui/swing/elements/MessageDialog.java | 6 rails/ui/swing/elements/NonModalDialog.java | 73 +++--- rails/ui/swing/elements/RadioButtonDialog.java | 6 rails/ui/swing/gamespecific/_1835/GameUIManager_1835.java | 46 ++-- rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java | 12 - rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java | 13 - rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java | 3 rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java | 161 +++++++------- 15 files changed, 256 insertions(+), 322 deletions(-) New commits: commit c734b75e2823f0be6ede03d5d58b57e66e300b3f Author: Erik Vos <eri...@xs...> Date: Fri Feb 3 21:06:37 2012 +0100 Refactored nonmodal dialog classes II Added MessageDialog. Refactored most non-modal dialog processing to take advantage of the new dialog-key concept. The Type and Usage enums (introduced in the previous commit) have been dropped. diff --git a/rails/game/specific/_18EU/StartCompany_18EU.java b/rails/game/specific/_18EU/StartCompany_18EU.java index f8333f1..0c44e69 100644 --- a/rails/game/specific/_18EU/StartCompany_18EU.java +++ b/rails/game/specific/_18EU/StartCompany_18EU.java @@ -86,7 +86,7 @@ public class StartCompany_18EU extends StartCompany { MapHex hex = mapManager.getHex(parts[0]); selectedHomeStation = hex.getStop(Integer.parseInt(parts[1])); } - + return selectedHomeStation; } @@ -97,25 +97,23 @@ public class StartCompany_18EU extends StartCompany { @Override public String toString() { - StringBuffer text = new StringBuffer(super.toString()); - if (minorsToMergeNames != null) { - text.append(" minors=").append(minorsToMergeNames); - } + StringBuilder text = new StringBuilder(super.toString()); if (chosenMinorName != null) { - text.append(" merged minor=" + chosenMinorName); - } - if (availableHomeStationNames != null) { - text.append(" stations=" + availableHomeStationNames); + text.append(" minor=" + chosenMinorName); + } else if (minorsToMergeNames != null) { + text.append(" minors=").append(minorsToMergeNames); } if (selectedHomeStationName != null) { - text.append(" home station=" + selectedHomeStationName); + text.append(" home=" + selectedHomeStationName); + } else if (availableHomeStationNames != null) { + text.append(" homes=" + availableHomeStationNames); } return text.toString(); } /** Deserialize */ private void readObject(ObjectInputStream in) throws IOException, - ClassNotFoundException { + ClassNotFoundException { in.defaultReadObject(); diff --git a/rails/ui/swing/GameStatus.java b/rails/ui/swing/GameStatus.java index dd8e00e..a10dd80 100644 --- a/rails/ui/swing/GameStatus.java +++ b/rails/ui/swing/GameStatus.java @@ -768,7 +768,7 @@ public class GameStatus extends GridPanel implements ActionListener { if (options.size() > 1) { if (startCompany) { RadioButtonDialog dialog = new RadioButtonDialog ( - NonModalDialog.Usage.COMPANY_START_PRICE, + GameUIManager.COMPANY_START_PRICE_DIALOG, gameUIManager, parent, LocalText.getText("PleaseSelect"), diff --git a/rails/ui/swing/GameUIManager.java b/rails/ui/swing/GameUIManager.java index b081250..72a3aa7 100644 --- a/rails/ui/swing/GameUIManager.java +++ b/rails/ui/swing/GameUIManager.java @@ -89,6 +89,12 @@ public class GameUIManager implements DialogOwner { protected boolean previousResult; + /* Keys of dialogs owned by this class */ + public static final String COMPANY_START_PRICE_DIALOG = "CompanyStartPrice"; + public static final String SELECT_COMPANY_DIALOG = "SelectCompany"; + public static final String REPAY_LOANS_DIALOG = "RepayLoans"; + public static final String EXCHANGE_TOKENS_DIALOG = "ExchangeTokens"; + protected static Logger log = Logger.getLogger(GameUIManager.class.getPackage().getName()); @@ -221,7 +227,7 @@ public class GameUIManager implements DialogOwner { // define configWindow configWindow = new ConfigWindow(true); configWindow.init(); - + // notify sound manager of game initialization SoundManager.notifyOfGameInit(gameManager); } @@ -256,7 +262,7 @@ public class GameUIManager implements DialogOwner { // resulting sfx are played in the correct order (first the action // related sfx and then model-change related sfx) SoundManager.notifyOfActionProcessing(gameManager, action); - + // Process the action on the server result = previousResult = processOnServer (action); @@ -272,7 +278,7 @@ public class GameUIManager implements DialogOwner { log.info ("Relinquishing turn to "+newPlayer.getName()); } else if (!wasMyTurn && isMyTurn) { autoLoadPoller.setActive(false); - setCurrentDialog(new MessageDialog(this, + setCurrentDialog(new MessageDialog(null, this, (JFrame) activeWindow, LocalText.getText("Message"), LocalText.getText("YourTurn", localPlayerName)), @@ -341,7 +347,7 @@ public class GameUIManager implements DialogOwner { public boolean displayServerMessage() { String[] message = DisplayBuffer.get(); if (message != null) { - setCurrentDialog(new MessageDialog(this, + setCurrentDialog(new MessageDialog(null, this, (JFrame) activeWindow, LocalText.getText("Message"), "<html>" + Util.joinWithDelimiter(message, "<br>")), @@ -631,7 +637,7 @@ public class GameUIManager implements DialogOwner { orWindow.setVisible(true); orWindow.toFront(); - CheckBoxDialog dialog = new CheckBoxDialog(NonModalDialog.Usage.EXCHANGE_TOKENS, + CheckBoxDialog dialog = new CheckBoxDialog(EXCHANGE_TOKENS_DIALOG, this, orWindow, LocalText.getText("ExchangeTokens"), @@ -650,10 +656,27 @@ public class GameUIManager implements DialogOwner { if (!ready) { - if (checkGameSpecificDialogAction()) { - ; - } else if (currentDialog instanceof RadioButtonDialog - && currentDialogAction instanceof StartCompany) { + String key = ""; + if (currentDialog instanceof NonModalDialog) key = ((NonModalDialog)currentDialog).getKey(); + + if (currentDialog instanceof AutoSaveLoadDialog) { + // Not yet a NonModalDialog subclass + autoSaveLoadGame2 ((AutoSaveLoadDialog)currentDialog); + + } else if (!(currentDialog instanceof NonModalDialog)) { + + log.warn("Unknown dialog action: dialog=["+currentDialog+"] action=["+currentDialogAction+"]"); + currentDialogAction = null; + + } else if (currentDialog instanceof MessageDialog) { + // Nothing to do. + currentDialogAction = null; + // This cancels the currently incomplete user action. + // WARNING: always do this if dialog processing terminates in a context + // where an action is aborted and the UI must return to its previous state. + // This will normally be the case after a CANCEL (but not after a NO). + + } else if (COMPANY_START_PRICE_DIALOG.equals(key)) { RadioButtonDialog dialog = (RadioButtonDialog) currentDialog; StartCompany action = (StartCompany) currentDialogAction; @@ -665,12 +688,10 @@ public class GameUIManager implements DialogOwner { action.setNumberBought(action.getSharesPerCertificate()); } else { // No selection done - no action - return; + currentDialogAction = null; } - - } else if (currentDialog instanceof CheckBoxDialog - && currentDialogAction instanceof ExchangeTokens) { + } else if (EXCHANGE_TOKENS_DIALOG.equals(key)) { CheckBoxDialog dialog = (CheckBoxDialog) currentDialog; ExchangeTokens action = (ExchangeTokens) currentDialogAction; @@ -704,28 +725,20 @@ public class GameUIManager implements DialogOwner { action.getTokensToExchange().get(index).setSelected(true); } } - } else if (currentDialog instanceof RadioButtonDialog - && currentDialogAction instanceof RepayLoans) { + } else if (REPAY_LOANS_DIALOG.equals(key)) { RadioButtonDialog dialog = (RadioButtonDialog) currentDialog; RepayLoans action = (RepayLoans) currentDialogAction; int selected = dialog.getSelectedOption(); action.setNumberTaken(action.getMinNumber() + selected); - } else if (currentDialog instanceof MessageDialog) { - // Nothing to do - currentDialogAction = null; // Should already be null - - } else if (currentDialog instanceof AutoSaveLoadDialog) { - - autoSaveLoadGame2 ((AutoSaveLoadDialog)currentDialog); - } else { - return; + log.warn("Unknown NonModal dialog action: dialog=["+currentDialog+"] action=["+currentDialogAction+"]"); + currentDialogAction = null; } } - /*if (currentDialogAction != null)*/ processAction(currentDialogAction); + processAction(currentDialogAction); } @@ -988,16 +1001,6 @@ public class GameUIManager implements DialogOwner { } - /* - public boolean isMyTurn() { - return myTurn; - } - - public void setMyTurn(boolean myTurn) { - this.myTurn = myTurn; - } - */ - public void setSaveDirectory(String saveDirectory) { this.saveDirectory = saveDirectory; } @@ -1042,10 +1045,6 @@ public class GameUIManager implements DialogOwner { return gameManager.getPlayers(); } - //public List<String> getPlayerNames() { - // return gameManager.getPlayerNames(); - //} - public Player getCurrentPlayer() { return gameManager.getCurrentPlayer(); } diff --git a/rails/ui/swing/ORUIManager.java b/rails/ui/swing/ORUIManager.java index 226a8b5..ea2d561 100644 --- a/rails/ui/swing/ORUIManager.java +++ b/rails/ui/swing/ORUIManager.java @@ -90,6 +90,10 @@ public class ORUIManager implements DialogOwner { "ConfirmToken", "SetRevenue", "SelectPayout", "CorrectMap" }; + /* Keys of dialogs owned by this class */ + public static final String SELECT_DESTINATION_COMPANIES_DIALOG = "SelectDestinationCompanies"; + public static final String REPAY_LOANS_DIALOG = "RepayLoans"; + protected static Logger log = Logger.getLogger(ORUIManager.class.getPackage().getName()); @@ -494,7 +498,7 @@ public class ORUIManager implements DialogOwner { orPanel.stopRevenueUpdate(); log.debug("Set revenue amount is " + amount); action.setActualRevenue(amount); - + // notify sound manager of set revenue amount as soon as // set revenue is pressed (not waiting for the completion // of the set dividend action) @@ -554,7 +558,7 @@ public class ORUIManager implements DialogOwner { orWindow.setVisible(true); orWindow.toFront(); - CheckBoxDialog dialog = new CheckBoxDialog(NonModalDialog.Usage.SELECT_DESTINATION_COMPANIES, + CheckBoxDialog dialog = new CheckBoxDialog(SELECT_DESTINATION_COMPANIES_DIALOG, this, orWindow, LocalText.getText("DestinationsReached"), @@ -614,7 +618,7 @@ public class ORUIManager implements DialogOwner { public boolean hexClicked(GUIHex clickedHex, GUIHex selectedHex) { boolean triggerORPanelRepaint = false; - + if (mapCorrectionEnabled) { triggerORPanelRepaint = true; boolean checkClickedHex = false; @@ -696,7 +700,7 @@ public class ORUIManager implements DialogOwner { } if (triggerORPanelRepaint) orWindow.repaintORPanel(); - + return triggerORPanelRepaint; } @@ -730,7 +734,7 @@ public class ORUIManager implements DialogOwner { upgradePanel.showUpgrades(); } } - + /** * @return True if the indicated tile must be connected to some other track if * placed on indicated hex. @@ -738,26 +742,26 @@ public class ORUIManager implements DialogOwner { public boolean getMustConnectRequirement (GUIHex hex,TileI tile) { if (tile == null || hex == null) return false; return tile.getColourName().equalsIgnoreCase(Tile.YELLOW_COLOUR_NAME) - // Does not apply to the current company's home hex(es) - && !hex.getHexModel().isHomeFor(orComp) - // Does not apply to special tile lays - && !isUnconnectedTileLayTarget(hex.getHexModel()); + // Does not apply to the current company's home hex(es) + && !hex.getHexModel().isHomeFor(orComp) + // Does not apply to special tile lays + && !isUnconnectedTileLayTarget(hex.getHexModel()); } - + public void addTileUpgradeIfValid(GUIHex hex, int tileId) { addTileUpgradeIfValid (hex, gameUIManager.getGameManager().getTileManager().getTile(tileId)); } - + public void addTileUpgradeIfValid(GUIHex hex, TileI tile) { if (!tileUpgrades.contains(tile) && isTileUpgradeValid(hex,tile)) { tileUpgrades.add(tile); } } - + public boolean isTileUpgradeValid(GUIHex hex, TileI tile) { // Check if the new tile must be connected to some other track - return hex.isTileUpgradeValid(tile.getId(), + return hex.isTileUpgradeValid(tile.getId(), getMustConnectRequirement(hex,tile)); } @@ -1477,7 +1481,7 @@ public class ORUIManager implements DialogOwner { Bank.format(i * loanAmount)); } } - RadioButtonDialog currentDialog = new RadioButtonDialog (NonModalDialog.Usage.REPAY_LOANS, + RadioButtonDialog currentDialog = new RadioButtonDialog (REPAY_LOANS_DIALOG, gameUIManager, orWindow, LocalText.getText("Select"), diff --git a/rails/ui/swing/StartRoundWindow.java b/rails/ui/swing/StartRoundWindow.java index 47f0a9a..1ff36cd 100644 --- a/rails/ui/swing/StartRoundWindow.java +++ b/rails/ui/swing/StartRoundWindow.java @@ -112,6 +112,9 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { private boolean includeBidding; private boolean showBasePrices; + /* Keys of dialogs owned by this class */ + public static final String COMPANY_START_PRICE_DIALOG = "CompanyStartPrice"; + protected static Logger log = Logger.getLogger(StartRoundWindow.class.getPackage().getName()); @@ -653,7 +656,7 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { } RadioButtonDialog dialog = new RadioButtonDialog( - NonModalDialog.Usage.COMPANY_START_PRICE, + COMPANY_START_PRICE_DIALOG, this, this, LocalText.getText("PleaseSelect"), diff --git a/rails/ui/swing/elements/CheckBoxDialog.java b/rails/ui/swing/elements/CheckBoxDialog.java index 0a56e91..d2fd91a 100644 --- a/rails/ui/swing/elements/CheckBoxDialog.java +++ b/rails/ui/swing/elements/CheckBoxDialog.java @@ -24,15 +24,16 @@ public class CheckBoxDialog extends NonModalDialog { int chosenOption = -1; boolean hasCancelButton = false; - public CheckBoxDialog(Usage usage, DialogOwner owner, JFrame window, String title, String message, + public CheckBoxDialog(String key, DialogOwner owner, JFrame window, String title, String message, String[] options) { - this (usage, owner, window, title, message, options, null, false); + this (key, owner, window, title, message, options, null, false); } - public CheckBoxDialog(Usage usage, DialogOwner owner, JFrame window, String title, String message, + public CheckBoxDialog(String key, DialogOwner owner, JFrame window, String title, String message, String[] options, boolean[] selectedOptions, boolean addCancelButton) { - super (Type.CHECKBOX, usage, owner, window, title, message, addCancelButton); + super (key, owner, window, title, message); + this.hasCancelButton = addCancelButton; this.options = options; this.numOptions = options.length; @@ -42,7 +43,7 @@ public class CheckBoxDialog extends NonModalDialog { this.selectedOptions = new boolean[numOptions]; } - initialize(); + initialize(hasCancelButton); } @Override diff --git a/rails/ui/swing/elements/ConfirmationDialog.java b/rails/ui/swing/elements/ConfirmationDialog.java index c3269b9..cbcdf6b 100644 --- a/rails/ui/swing/elements/ConfirmationDialog.java +++ b/rails/ui/swing/elements/ConfirmationDialog.java @@ -1,118 +1,35 @@ /* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/ui/swing/elements/ConfirmationDialog.java,v 1.1 2010/02/28 21:38:06 evos Exp $*/ package rails.ui.swing.elements; -import java.awt.*; -import java.awt.event.*; +import java.awt.event.ActionEvent; -import javax.swing.*; - -import org.apache.log4j.Logger; - -import rails.common.LocalText; +import javax.swing.JFrame; /** - * A generic YES/NO dialog + * A generic YES/NO dialog */ -public class ConfirmationDialog extends JDialog implements ActionListener { +public class ConfirmationDialog extends NonModalDialog { private static final long serialVersionUID = 1L; - GridBagConstraints gc; - JPanel messagePane, buttonPane; - JButton okButton, cancelButton; - Dimension size, optSize; - DialogOwner owner; - String message; boolean answer = false; - protected static Logger log = - Logger.getLogger(ConfirmationDialog.class.getPackage().getName()); - - public ConfirmationDialog(DialogOwner owner, String title, String message, - String okText, String cancelText) { - super((Frame) null, title, false); // Non-modal - this.owner = owner; - this.message = message; - - initialize(okText, cancelText); - pack(); + public ConfirmationDialog(String key, DialogOwner owner, JFrame window, String title, String message, + String okTextKey, String cancelTextKey) { - // Center on owner - /* - int x = - (int) owner.getLocationOnScreen().getX() - + (owner.getWidth() - getWidth()) / 2; - int y = - (int) owner.getLocationOnScreen().getY() - + (owner.getHeight() - getHeight()) / 2; - */ - int x = 400; - int y = 400; - setLocation(x, y); + super (key, owner, window, title, message); - setVisible(true); - setAlwaysOnTop(true); + initialize(okTextKey, cancelTextKey); } - private void initialize(String okText, String cancelText) { - - gc = new GridBagConstraints(); - - getContentPane().setLayout(new GridBagLayout()); - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - - messagePane = new JPanel(); - - messagePane.add(new JLabel(message)); - - buttonPane = new JPanel(); - - okButton = new JButton(LocalText.getText(okText)); - // We only expect Yes/No or OK/Cancel - if (okText.startsWith("O")) - okButton.setMnemonic(KeyEvent.VK_O); - else if (okText.startsWith("Y")) - okButton.setMnemonic(KeyEvent.VK_Y); - okButton.addActionListener(this); - buttonPane.add(okButton); - - cancelButton = new JButton(LocalText.getText(cancelText)); - // We only expect Yes/No or OK/Cancel - if (cancelText.startsWith("C")) - cancelButton.setMnemonic(KeyEvent.VK_C); - else if (cancelText.startsWith("N")) - cancelButton.setMnemonic(KeyEvent.VK_N); - cancelButton.addActionListener(this); - buttonPane.add(cancelButton); - - getContentPane().add(messagePane, constraints(0, 0, 0, 0, 0, 0)); - getContentPane().add(buttonPane, constraints(0, 1, 0, 0, 0, 0)); - } - - private GridBagConstraints constraints(int gridx, int gridy, int leftinset, - int topinset, int rightinset, int bottominset) { - if (gridx >= 0) gc.gridx = gridx; - if (gridy >= 0) gc.gridy = gridy; - gc.fill = GridBagConstraints.BOTH; - gc.weightx = 0.5; - gc.weighty = 0.5; - if (leftinset >= 0) gc.insets.left = leftinset; - if (topinset >= 0) gc.insets.top = topinset; - if (rightinset >= 0) gc.insets.right = rightinset; - if (bottominset >= 0) gc.insets.bottom = bottominset; - - return gc; + @Override + protected void processOK (ActionEvent actionEvent) { + answer = true; } - public void actionPerformed(ActionEvent arg0) { - if (arg0.getSource().equals(okButton)) { - answer = true; - } else if (arg0.getSource().equals(cancelButton)) { - answer = false; - } - this.setVisible(false); - this.dispose(); - owner.dialogActionPerformed(); + @Override + protected void processCancel (ActionEvent actionEvent) { + answer = false; } public synchronized boolean getAnswer() { diff --git a/rails/ui/swing/elements/MessageDialog.java b/rails/ui/swing/elements/MessageDialog.java index e4bfe66..9a6dad3 100644 --- a/rails/ui/swing/elements/MessageDialog.java +++ b/rails/ui/swing/elements/MessageDialog.java @@ -10,11 +10,11 @@ public class MessageDialog extends NonModalDialog { private static final long serialVersionUID = 1L; - public MessageDialog(DialogOwner owner, JFrame window, String title, String message) { + public MessageDialog(String key, DialogOwner owner, JFrame window, String title, String message) { - super (Type.MESSAGE, null, owner, window, title, message, false); + super (key, owner, window, title, message); - initialize(); + initialize(false); } diff --git a/rails/ui/swing/elements/NonModalDialog.java b/rails/ui/swing/elements/NonModalDialog.java index 0fe730c..72718d2 100644 --- a/rails/ui/swing/elements/NonModalDialog.java +++ b/rails/ui/swing/elements/NonModalDialog.java @@ -8,55 +8,47 @@ import javax.swing.*; import org.apache.log4j.Logger; import rails.common.LocalText; +import rails.util.Util; public abstract class NonModalDialog extends JDialog implements ActionListener { private static final long serialVersionUID = 1L; - protected Type type; - protected Usage usage; + protected String key; protected DialogOwner owner = null; protected JFrame window = null; protected String message; - protected boolean hasCancelButton = false; + protected boolean hasCancelButton = true; GridBagConstraints gc; JPanel optionsPane, buttonPane; JButton okButton, cancelButton; - - public static enum Usage { - REPAY_LOANS, - DESTINATION_REACHED, - BUY_WHICH_TRAIN, - COMPANY_START_PRICE, - EXCHANGE_TOKENS, - SELECT_FOLDING_COMPANIES, - SELECT_DESTINATION_COMPANIES, - SELECT_COMPANY, - SELECT_HOME_STATION - } - - public static enum Type { - CHECKBOX, - RADIO, - MESSAGE, - MIXED - } + String okTextKey = "OK"; + String cancelTextKey = "Cancel"; protected static Logger log = Logger.getLogger(NonModalDialog.class.getPackage().getName()); - public NonModalDialog(Type type, Usage usage, - DialogOwner owner, JFrame window, String title, String message, - boolean addCancelButton) { + public NonModalDialog(String key, + DialogOwner owner, JFrame window, String title, String message) { super((Frame) null, title, false); // Non-modal - this.type = type; - this.usage = usage; + this.key = key; this.owner = owner; this.window = window; this.message = message; - hasCancelButton = addCancelButton; + } + + protected final void initialize (String okTextKey, String cancelTextKey) { + this.okTextKey = okTextKey; + this.cancelTextKey = cancelTextKey; + this.hasCancelButton = Util.hasValue(cancelTextKey); + initialize(); + } + + protected final void initialize (boolean hasCancelButton) { + this.hasCancelButton = hasCancelButton; + initialize(); } protected final void initialize() { @@ -66,14 +58,14 @@ public abstract class NonModalDialog extends JDialog implements ActionListener { optionsPane = new JPanel(); buttonPane = new JPanel(); - okButton = new JButton(LocalText.getText("OK")); - okButton.setMnemonic(KeyEvent.VK_O); + okButton = new JButton(LocalText.getText(okTextKey)); + okButton.setMnemonic(okTextKey.startsWith("Y") ? KeyEvent.VK_Y : KeyEvent.VK_O); okButton.addActionListener(this); buttonPane.add(okButton); if (hasCancelButton) { - cancelButton = new JButton(LocalText.getText("Cancel")); - cancelButton.setMnemonic(KeyEvent.VK_C); + cancelButton = new JButton(LocalText.getText(cancelTextKey)); + cancelButton.setMnemonic(cancelTextKey.startsWith("N") ? KeyEvent.VK_N : KeyEvent.VK_C); cancelButton.addActionListener(this); buttonPane.add(cancelButton); } @@ -102,8 +94,7 @@ public abstract class NonModalDialog extends JDialog implements ActionListener { setAlwaysOnTop(true); } - protected void initializeInput() { - } + protected void initializeInput() {} protected GridBagConstraints constraints(int gridx, int gridy, int leftinset, int topinset, int rightinset, int bottominset) { @@ -126,12 +117,22 @@ public abstract class NonModalDialog extends JDialog implements ActionListener { } else if (actionEvent.getSource().equals(cancelButton)) { processCancel (actionEvent); } + log.debug("Processed: dialog="+getClass().getSimpleName()+" key="+key); setVisible(false); dispose(); owner.dialogActionPerformed (); } - protected void processOK (ActionEvent actionEvent) {}; + protected void processOK (ActionEvent actionEvent) {} + + protected void processCancel (ActionEvent actionEvent) {} - protected void processCancel (ActionEvent actionEvent) {}; + public String getKey() { + return key; + } + + @Override + public String toString() { + return "Dialog type="+getClass().getSimpleName()+" key="+key; + } } diff --git a/rails/ui/swing/elements/RadioButtonDialog.java b/rails/ui/swing/elements/RadioButtonDialog.java index 1d7cc59..cbd4306 100644 --- a/rails/ui/swing/elements/RadioButtonDialog.java +++ b/rails/ui/swing/elements/RadioButtonDialog.java @@ -22,16 +22,16 @@ public class RadioButtonDialog extends NonModalDialog { int selectedOption; int chosenOption = -1; - public RadioButtonDialog(Usage usage, DialogOwner owner, JFrame window, String title, String message, + public RadioButtonDialog(String key, DialogOwner owner, JFrame window, String title, String message, String[] options, int selectedOption) { - super (Type.RADIO, usage, owner, window, title, message, selectedOption < 0); + super (key, owner, window, title, message); this.options = options; this.numOptions = options.length; this.selectedOption = selectedOption; - initialize(); + initialize(selectedOption < 0); } @Override diff --git a/rails/ui/swing/gamespecific/_1835/GameUIManager_1835.java b/rails/ui/swing/gamespecific/_1835/GameUIManager_1835.java index 22654a6..192bd50 100644 --- a/rails/ui/swing/gamespecific/_1835/GameUIManager_1835.java +++ b/rails/ui/swing/gamespecific/_1835/GameUIManager_1835.java @@ -6,45 +6,51 @@ import java.util.List; import rails.game.CompanyI; import rails.game.specific._1835.FoldIntoPrussian; import rails.ui.swing.GameUIManager; -import rails.ui.swing.elements.CheckBoxDialog; -import rails.ui.swing.elements.ConfirmationDialog; +import rails.ui.swing.elements.*; public class GameUIManager_1835 extends GameUIManager { - protected boolean checkGameSpecificDialogAction() { - - if (currentDialog instanceof ConfirmationDialog - && currentDialogAction instanceof FoldIntoPrussian) { - + // Keys of dialogs owned by this class. + public static final String START_PRUSSIAN_DIALOG = "StartPrussian"; + public static final String MERGE_INTO_PRUSSIAN_DIALOG = "MergeIntoPrussian"; + + @Override + public void dialogActionPerformed() { + + String key = ""; + if (currentDialog instanceof NonModalDialog) key = ((NonModalDialog)currentDialog).getKey(); + + // Check for the dialogs that are postprocessed in this class. + if (START_PRUSSIAN_DIALOG.equals(key)) { + ConfirmationDialog dialog = (ConfirmationDialog) currentDialog; FoldIntoPrussian action = (FoldIntoPrussian) currentDialogAction; if (dialog.getAnswer()) { action.setFoldedCompanies(action.getFoldableCompanies()); } - - return true; - - } else if (currentDialog instanceof CheckBoxDialog - && currentDialogAction instanceof FoldIntoPrussian) { - + + } else if (MERGE_INTO_PRUSSIAN_DIALOG.equals(key)) { + CheckBoxDialog dialog = (CheckBoxDialog) currentDialog; FoldIntoPrussian action = (FoldIntoPrussian) currentDialogAction; boolean[] exchanged = dialog.getSelectedOptions(); String[] options = dialog.getOptions(); - + List<CompanyI> foldedCompanies = new ArrayList<CompanyI>(); for (int index=0; index < options.length; index++) { if (exchanged[index]) { foldedCompanies.add(action.getFoldableCompanies().get(index)); - } + } } action.setFoldedCompanies(foldedCompanies); - - return true; - + } else { - return false; + // Current dialog not found yet, try the superclass. + super.dialogActionPerformed(false); + return; } - } + // Dialog action found and processed, let the superclass initiate processing. + super.dialogActionPerformed(true); + } } diff --git a/rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java b/rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java index aed46cc..75924af 100644 --- a/rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java +++ b/rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java @@ -2,8 +2,6 @@ package rails.ui.swing.gamespecific._1835; import java.util.List; -import javax.swing.JDialog; - import rails.common.LocalText; import rails.game.*; import rails.game.action.DiscardTrain; @@ -63,17 +61,19 @@ public class StatusWindow_1835 extends StatusWindow { protected void fold (FoldIntoPrussian action) { List<CompanyI> foldables = action.getFoldableCompanies(); - JDialog currentDialog; + NonModalDialog currentDialog; if (foldables.get(0).getName().equals("M2")) { // Ask if the Prussian should be started - currentDialog = new ConfirmationDialog (gameUIManager, + currentDialog = new ConfirmationDialog (GameUIManager_1835.START_PRUSSIAN_DIALOG, + gameUIManager, this, LocalText.getText("Select"), LocalText.getText("MergeMinorConfirm", getCurrentPlayer().getName(), GameManager_1835.M2_ID, GameManager_1835.PR_ID), "Yes", - "No"); + "No" + ); } else { // Ask if any other prePrussians should be folded String[] options = new String[foldables.size()]; @@ -87,7 +87,7 @@ public class StatusWindow_1835 extends StatusWindow { ((ExchangeForShare)(company.getSpecialProperties().get(0))).getShare() ); } - currentDialog = new CheckBoxDialog (NonModalDialog.Usage.SELECT_FOLDING_COMPANIES, + currentDialog = new CheckBoxDialog (GameUIManager_1835.MERGE_INTO_PRUSSIAN_DIALOG, gameUIManager, this, LocalText.getText("Select"), diff --git a/rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java b/rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java index b48d117..4a4b7e7 100644 --- a/rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java +++ b/rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java @@ -8,8 +8,8 @@ import rails.game.Bank; import rails.game.RoundI; import rails.game.action.*; import rails.game.specific._1856.CGRFormationRound; +import rails.ui.swing.GameUIManager; import rails.ui.swing.StatusWindow; -import rails.ui.swing.elements.NonModalDialog; import rails.ui.swing.elements.RadioButtonDialog; import rails.util.Util; @@ -52,15 +52,6 @@ public class StatusWindow_1856 extends StatusWindow { repayLoans (nextAction); return true; - /* Moved up - } else if (immediateAction instanceof DiscardTrain) { - // Make a local copy and discard the original, - // so that it's not going to loop. - DiscardTrain nextAction = (DiscardTrain) immediateAction; - immediateAction = null; - gameUIManager.discardTrains (nextAction); - return true; - */ } else if (immediateAction instanceof ExchangeTokens) { // Make a local copy and discard the original, // so that it's not going to loop. @@ -100,7 +91,7 @@ public class StatusWindow_1856 extends StatusWindow { + "<br>" + message; } - RadioButtonDialog currentDialog = new RadioButtonDialog (NonModalDialog.Usage.REPAY_LOANS, + RadioButtonDialog currentDialog = new RadioButtonDialog (GameUIManager.REPAY_LOANS_DIALOG, gameUIManager, this, LocalText.getText("1856MergerDialog", action.getCompanyName()), diff --git a/rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java b/rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java index 81e816d..f3378b3 100644 --- a/rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java +++ b/rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java @@ -8,7 +8,6 @@ import rails.game.PublicCompanyI; import rails.game.action.MergeCompanies; import rails.game.action.PossibleAction; import rails.ui.swing.GameStatus; -import rails.ui.swing.elements.NonModalDialog; import rails.ui.swing.elements.RadioButtonDialog; /** @@ -71,7 +70,7 @@ public class GameStatus_18EU extends GameStatus { } RadioButtonDialog dialog = new RadioButtonDialog ( - NonModalDialog.Usage.SELECT_COMPANY, + GameUIManager_18EU.SELECT_MERGING_MAJOR, gameUIManager, parent, LocalText.getText("PleaseSelect"), diff --git a/rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java b/rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java index 5c17748..0c6cc86 100644 --- a/rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java +++ b/rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java @@ -15,123 +15,138 @@ import rails.ui.swing.elements.RadioButtonDialog; public class GameUIManager_18EU extends GameUIManager { + // Keys of dialogs owned by this class. + public static final String SELECT_CONVERTING_MINOR = "SelectConvertingMinor"; + public static final String SELECT_MERGING_MAJOR = "SelectMergingMajor"; + public static final String SELECT_HOME_STATION_DIALOG = "SelectHomeStation"; + @Override public void dialogActionPerformed () { - if (currentDialog instanceof RadioButtonDialog - && currentDialogAction instanceof MergeCompanies) { + String key = ""; + if (currentDialog instanceof NonModalDialog) key = ((NonModalDialog)currentDialog).getKey(); + + // Check for the dialogs that are postprocessed in this class. + if (SELECT_MERGING_MAJOR.equals(key)) { + // A major company has been selected (or not) to merge a minor into. RadioButtonDialog dialog = (RadioButtonDialog) currentDialog; MergeCompanies action = (MergeCompanies) currentDialogAction; PublicCompanyI minor = action.getMergingCompany(); - if (action.getSelectedTargetCompany() == null) { - // Step 1: selection of the major company to merge into - int choice = dialog.getSelectedOption(); - if (choice < 0) return; + int choice = dialog.getSelectedOption(); + if (choice < 0) return; - PublicCompanyI major = action.getTargetCompanies().get(choice); - action.setSelectedTargetCompany(major); + PublicCompanyI major = action.getTargetCompanies().get(choice); + action.setSelectedTargetCompany(major); - if (major != null && action.canReplaceToken(choice)) { + if (major != null && action.canReplaceToken(choice)) { - boolean replaceToken = - JOptionPane.showConfirmDialog(statusWindow, LocalText.getText( - "WantToReplaceToken", - minor.getName(), - major.getName() ), - LocalText.getText("PleaseSelect"), - JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION; - action.setReplaceToken(replaceToken); - } + boolean replaceToken = + JOptionPane.showConfirmDialog(statusWindow, LocalText.getText( + "WantToReplaceToken", + minor.getName(), + major.getName() ), + LocalText.getText("PleaseSelect"), + JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION; + action.setReplaceToken(replaceToken); + } + + } else if (SELECT_CONVERTING_MINOR.equals(key)) { + + // A minor has been selected (or not) to merge into a starting company before phase 6. + RadioButtonDialog dialog = (RadioButtonDialog) currentDialog; + StartCompany_18EU action = (StartCompany_18EU) currentDialogAction; + int choice = dialog.getSelectedOption(); + if (choice < 0) { + currentDialogAction = null; } else { - // To be added later when ReplaceToken dialog is modeless + PublicCompanyI minor = action.getMinorsToMerge().get(choice); + action.setChosenMinor(minor); } - } else if (currentDialog instanceof RadioButtonDialog + } else if (COMPANY_START_PRICE_DIALOG.equals(key) && currentDialogAction instanceof StartCompany_18EU) { + // A start price has been selected (or not) for a stating major company. RadioButtonDialog dialog = (RadioButtonDialog) currentDialog; StartCompany_18EU action = (StartCompany_18EU) currentDialogAction; - if (action.getPrice() == 0) { + int index = dialog.getSelectedOption(); + if (index < 0) { + currentDialogAction = null; + return; + } + action.setStartPrice(action.getStartPrices()[index]); + + // Set up another dialog for the next step + List<PublicCompanyI> minors = action.getMinorsToMerge(); + + if (minors != null && !minors.isEmpty()) { + // Up to phase 6, a minor must be exchanged + String[] options = new String[minors.size()]; + int i = 0; + for (PublicCompanyI minor : minors) { + options[i++] = + "Minor " + minor.getName() + " " + + minor.getLongName(); + } + dialog = new RadioButtonDialog (SELECT_CONVERTING_MINOR, + this, + statusWindow, + LocalText.getText("PleaseSelect"), + LocalText.getText( + "SelectMinorToMerge", + action.getCompanyName()), + options, -1); + setCurrentDialog(dialog, action); + statusWindow.disableButtons(); + return; + } else { - // The price will be set first - int index = dialog.getSelectedOption(); - if (index < 0) return; - action.setStartPrice(action.getStartPrices()[index]); - - // Set up another dialog for the next step - List<PublicCompanyI> minors = action.getMinorsToMerge(); - - if (minors != null && !minors.isEmpty()) { - // Up to phase 6, a minor must be exchanged - String[] options = new String[minors.size()]; - int i = 0; - for (PublicCompanyI minor : minors) { - options[i++] = - "Minor " + minor.getName() + " " - + minor.getLongName(); + // From phase 6, no minors are involved, but a home station must be chosen + List<Stop> cities = action.getAvailableHomeStations(); + if (cities != null && !cities.isEmpty()) { + String[] options = new String[cities.size()]; + for (int i = 0; i < options.length; i++) { + options[i] = cities.get(i).toString(); } - dialog = new RadioButtonDialog (NonModalDialog.Usage.SELECT_FOLDING_COMPANIES, + dialog = new RadioButtonDialog (SELECT_HOME_STATION_DIALOG, this, statusWindow, LocalText.getText("PleaseSelect"), LocalText.getText( - "SelectMinorToMerge", + "SelectHomeStation", action.getCompanyName()), options, -1); setCurrentDialog(dialog, action); statusWindow.disableButtons(); return; - } else { - - // From phase 6, no minors are involved, but a home station must be chosen - List<Stop> cities = action.getAvailableHomeStations(); - if (cities != null && !cities.isEmpty()) { - String[] options = new String[cities.size()]; - for (int i = 0; i < options.length; i++) { - options[i] = cities.get(i).toString(); - } - dialog = new RadioButtonDialog (NonModalDialog.Usage.SELECT_HOME_STATION, - this, - statusWindow, - LocalText.getText("PleaseSelect"), - LocalText.getText( - "SelectHomeStation", - action.getCompanyName()), - options, -1); - setCurrentDialog(dialog, action); - statusWindow.disableButtons(); - return; - - } - } - } else if (action.getMinorsToMerge() != null) { - // Up to phase 5: a minor to merge has been selected (or not) - int choice = dialog.getSelectedOption(); - if (choice < 0) { - // Also reset price - action.setStartPrice(0); - return; } - action.setChosenMinor(action.getMinorsToMerge().get(choice)); + } + + } else if (SELECT_HOME_STATION_DIALOG.equals(key)) { + + RadioButtonDialog dialog = (RadioButtonDialog) currentDialog; + StartCompany_18EU action = (StartCompany_18EU) currentDialogAction; - } else if (action.getAvailableHomeStations() != null) { + if (action.getAvailableHomeStations() != null) { // From phase 6: a home station has been selected (or not) int index = dialog.getSelectedOption(); if (index < 0) { - // Also reset price - action.setStartPrice(0); + currentDialogAction = null; return; } action.setHomeStation(action.getAvailableHomeStations().get(index)); } } else { + // Current dialog not found yet, try the superclass. super.dialogActionPerformed(false); + return; } + // Dialog action found and processed, let the superclass initiate processing. super.dialogActionPerformed(true); } |
From: Stefan F. <ste...@us...> - 2012-02-01 18:26:36
|
Tag 'v1.6.2' created by Stefan Frey <ste...@we...> at 2012-02-01 18:26 +0000 version 1.6.2 Changes since v1.6.1-3: --- 0 files changed --- |
From: Frederick W. <fre...@us...> - 2012-02-01 17:59:52
|
rails/ui/swing/ORUIManager.java | 6 + rails/ui/swing/UpgradesPanel.java | 30 ++++++++- rails/ui/swing/hexmap/GUIHex.java | 7 +- rails/ui/swing/hexmap/GUITile.java | 120 ++++++++++++++++++++++++++++++------- 4 files changed, 136 insertions(+), 27 deletions(-) New commits: commit f69750118d746100e0f16eb7b1b2ebe3813810dd Author: Frederick Weld <fre...@gm...> Date: Wed Feb 1 18:54:15 2012 +0100 Rotate upgrade panel tiles to the first valid orientation The existing logic of determining validity of orientations was re-used (required some refactoring). This means that, once this logic is further improved, the upgrade panel's tile orientations will also get more accurate. The other source of complexity is that svg tile images are not centered and that image rotation by AOP result in additional borders on the bottom/right. Code that is able to handle that complexity is put to GUITile, as the former tile paint code is also there. diff --git a/rails/ui/swing/ORUIManager.java b/rails/ui/swing/ORUIManager.java index 6f7f8c6..226a8b5 100644 --- a/rails/ui/swing/ORUIManager.java +++ b/rails/ui/swing/ORUIManager.java @@ -731,7 +731,11 @@ public class ORUIManager implements DialogOwner { } } - private boolean getMustConnectRequirement (GUIHex hex,TileI tile) { + /** + * @return True if the indicated tile must be connected to some other track if + * placed on indicated hex. + */ + public boolean getMustConnectRequirement (GUIHex hex,TileI tile) { if (tile == null || hex == null) return false; return tile.getColourName().equalsIgnoreCase(Tile.YELLOW_COLOUR_NAME) // Does not apply to the current company's home hex(es) diff --git a/rails/ui/swing/UpgradesPanel.java b/rails/ui/swing/UpgradesPanel.java index 16486b5..1ac2332 100644 --- a/rails/ui/swing/UpgradesPanel.java +++ b/rails/ui/swing/UpgradesPanel.java @@ -19,11 +19,14 @@ import rails.game.action.*; import rails.game.correct.MapCorrectionAction; import rails.ui.swing.elements.ActionLabel; import rails.ui.swing.hexmap.GUIHex; +import rails.ui.swing.hexmap.GUITile; import rails.ui.swing.hexmap.HexHighlightMouseListener; import rails.ui.swing.hexmap.HexMap; public class UpgradesPanel extends Box implements MouseListener, ActionListener { private static final long serialVersionUID = 1L; + + private static final int UPGRADE_TILE_ZOOM_STEP = 10; private ORUIManager orUIManager; private List<ActionLabel> tokenLabels; @@ -61,7 +64,7 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener this.orUIManager = orUIManager; - preferredSize = new Dimension((int)Math.round(100 * (2 + Scale.getFontScale())/3), 200); + preferredSize = new Dimension((int)Math.round(110 * (2 + Scale.getFontScale())/3), 200); setSize(preferredSize); setVisible(true); @@ -220,7 +223,28 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener } private HexLabel createHexLabel(TileI tile,String toolTipHeaderLine) { - BufferedImage hexImage = getHexImage(tile.getPictureId()); + BufferedImage hexImage = null; + + //get a buffered image of the tile in the first valid orientation + GUIHex selectedGUIHex = hexMap.getSelectedHex(); + if (selectedGUIHex != null) { + GUITile tempGUITile = selectedGUIHex.createUpgradeTileIfValid ( + tile.getId(), + orUIManager.getMustConnectRequirement(selectedGUIHex, tile)); + + if (tempGUITile != null) { + //tile has been rotated to valid orientation + //get unscaled image for this orientation + hexImage = tempGUITile.getTileImage(UPGRADE_TILE_ZOOM_STEP); + } + } + + //fallback if no valid orientation exists: + //get the image in the standard orientation + if (hexImage == null) { + hexImage = getHexImage(tile.getPictureId()); + } + ImageIcon hexIcon = new ImageIcon(hexImage); // Cheap n' Easy rescaling. @@ -375,7 +399,7 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener } private BufferedImage getHexImage(int tileId) { - return GameUIManager.getImageLoader().getTile(tileId, 10); + return GameUIManager.getImageLoader().getTile(tileId, UPGRADE_TILE_ZOOM_STEP); } @Override diff --git a/rails/ui/swing/hexmap/GUIHex.java b/rails/ui/swing/hexmap/GUIHex.java index f67de31..af052cb 100644 --- a/rails/ui/swing/hexmap/GUIHex.java +++ b/rails/ui/swing/hexmap/GUIHex.java @@ -889,7 +889,12 @@ public class GUIHex implements ViewObject { return (provisionalGUITile != null); } - private GUITile createUpgradeTileIfValid (int tileId, boolean upgradeMustConnect) { + /** + * Creates an upgrade tile onto this hex without dropping it on the hex. + * This means that this hex won't consider the returned tile being part of it + * (even not on a temporary base). + */ + public GUITile createUpgradeTileIfValid (int tileId, boolean upgradeMustConnect) { GUITile t = new GUITile(tileId, this); /* Check if we can find a valid orientation of this tile */ return ( t.rotate(0, currentGUITile, upgradeMustConnect) ? t : null); diff --git a/rails/ui/swing/hexmap/GUITile.java b/rails/ui/swing/hexmap/GUITile.java index 9adfa4c..becbe56 100644 --- a/rails/ui/swing/hexmap/GUITile.java +++ b/rails/ui/swing/hexmap/GUITile.java @@ -25,7 +25,6 @@ public class GUITile { protected String tileType = null; protected int picId; - protected BufferedImage tileImage = null; protected int rotation = 0; @@ -38,7 +37,7 @@ public class GUITile { protected static ImageLoader imageLoader = GameUIManager.getImageLoader(); - protected AffineTransform af = new AffineTransform(); + protected RenderingHints renderingHints = null; public static final double DEG60 = Math.PI / 3; @@ -248,11 +247,32 @@ public class GUITile { tileScale = scale; } + private RenderingHints getTileRenderingHints() { + if (renderingHints == null) { + renderingHints = new RenderingHints(null); + renderingHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, + RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); + renderingHints.put(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + renderingHints.put(RenderingHints.KEY_COLOR_RENDERING, + RenderingHints.VALUE_COLOR_RENDER_QUALITY); + renderingHints.put(RenderingHints.KEY_DITHERING, + RenderingHints.VALUE_DITHER_DISABLE); + renderingHints.put(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BICUBIC); + renderingHints.put(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + } + return renderingHints; + } + public void paintTile(Graphics2D g2, int x, int y) { int zoomStep = guiHex.getHexMap().getZoomStep(); - tileImage = imageLoader.getTile(picId, zoomStep); + BufferedImage tileImage = imageLoader.getTile(picId, zoomStep); if (tileImage != null) { @@ -262,33 +282,89 @@ public class GUITile { int yCenter = (int) Math.round(tileImage.getHeight() * SVG_Y_CENTER_LOC * tileScale); - af = AffineTransform.getRotateInstance(radians, xCenter, yCenter); + AffineTransform af = AffineTransform.getRotateInstance(radians, xCenter, yCenter); af.scale(tileScale, tileScale); - RenderingHints rh = new RenderingHints(null); - rh.put(RenderingHints.KEY_ALPHA_INTERPOLATION, - RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); - rh.put(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - rh.put(RenderingHints.KEY_COLOR_RENDERING, - RenderingHints.VALUE_COLOR_RENDER_QUALITY); - rh.put(RenderingHints.KEY_DITHERING, - RenderingHints.VALUE_DITHER_DISABLE); - rh.put(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BICUBIC); - rh.put(RenderingHints.KEY_RENDERING, - RenderingHints.VALUE_RENDER_QUALITY); - rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, - RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - - AffineTransformOp aop = new AffineTransformOp(af, rh); + AffineTransformOp aop = new AffineTransformOp(af, + getTileRenderingHints()); g2.drawImage(tileImage, aop, x - xCenter, y - yCenter); + } else { - log.error("No image for tile "+tileId+" on hex "+guiHex.getName()); + log.error("No image for tile "+tileId+" on hex "+guiHex.getName()); } } + + /** + * Provides the image of the tile based on the zoomStep. + * tileScale is not considered for producing this image. + */ + public BufferedImage getTileImage(int zoomStep) { + + // STEP 1: GET IMAGE FROM SVG + // image not centered as there will be a bottom border to assign square bounds to the image + + BufferedImage uncenteredTileImage = imageLoader.getTile(picId, zoomStep); + if (uncenteredTileImage == null) return null; + + //svg always in NS orientation, hence wide diagonal can be directly taken from image size + int wideDiagonal = uncenteredTileImage.getWidth(); + + //narrow diagonal cannot be taken from image height due to the bottom border + int narrowDiagonal = (int)Math.round( wideDiagonal * 0.5 * Math.sqrt(3) ); + + int border = wideDiagonal - narrowDiagonal; + + // STEP 2: CENTER TILE IN IMAGE + // apply the bottom border also the left / top / right + + //center tile by translation + AffineTransform centeringAT = AffineTransform.getTranslateInstance( border, border ); + AffineTransformOp centeringATOp = new AffineTransformOp(centeringAT, null); + + //centered tile image create manually since it also needs a border on the right + BufferedImage centeredTileImage = new BufferedImage( + uncenteredTileImage.getWidth() + border * 2, + uncenteredTileImage.getHeight() + border, + uncenteredTileImage.getType()); + + centeringATOp.filter(uncenteredTileImage, centeredTileImage); + + // STEP 3: ROTATE TILE IMAGE + // feasible only now since there are enough margins to ensure tile won't exceed bounds + + double radians = baseRotation + rotation * DEG60; + int xCenter = (int) Math.round(centeredTileImage.getWidth() / 2 ); + int yCenter = (int) Math.round(centeredTileImage.getHeight() / 2 ); + + AffineTransform af = AffineTransform.getRotateInstance(radians, xCenter, yCenter); + AffineTransformOp aop = new AffineTransformOp(af, getTileRenderingHints()); + + BufferedImage rotatedTileImage = aop.filter(centeredTileImage, null); + + // STEP 4: CROP ROTATED TILE IMAGE + // rotation result will have additional borders on the right/bottom as a result of the AOP + + int croppedWidth, croppedHeight; + if (baseRotation == 0) { + //tile in NS orientation after rotation + croppedWidth = wideDiagonal; + croppedHeight = narrowDiagonal; + } else { + //tile in EW orientation after rotation + croppedWidth = narrowDiagonal; + croppedHeight = wideDiagonal; + } + BufferedImage croppedTileImage = rotatedTileImage.getSubimage( + xCenter - croppedWidth / 2, + yCenter - croppedHeight / 2, + croppedWidth, + croppedHeight ); + + return croppedTileImage; + } + public TileI getTile() { return tile; } |
From: Stefan F. <ste...@us...> - 2012-02-01 12:38:56
|
rails/game/StockRound.java | 3 readme.txt | 21 - test/data/bugs/1830_sellPresidency.rails |binary test/data/bugs/1830_sellPresidency.report | 408 ++++++++++++++++++++++++++++++ version.number | 2 5 files changed, 417 insertions(+), 17 deletions(-) New commits: commit 113af81105b505713fac94237b72735dc2a11564 Author: Stefan Frey <ste...@we...> Date: Wed Feb 1 07:39:30 2012 +0100 added test case for fixed sell presidency bug (cherry picked from commit a7c513c2ba686d4b9e542491bac68a7d3718dc37) diff --git a/test/data/bugs/1830_sellPresidency.rails b/test/data/bugs/1830_sellPresidency.rails new file mode 100644 index 0000000..c3fd78c Binary files /dev/null and b/test/data/bugs/1830_sellPresidency.rails differ diff --git a/test/data/bugs/1830_sellPresidency.report b/test/data/bugs/1830_sellPresidency.report new file mode 100644 index 0000000..f2ed980 --- /dev/null +++ b/test/data/bugs/1830_sellPresidency.report @@ -0,0 +1,408 @@ +GameIs,1830 +PlayerIs,1,Palmiro +PlayerIs,2,Danilo +PlayerIs,3,Giancarlo +PlayerIs,4,Glauco +PlayerIs,5,Roberto +PlayerCash,480 +BankHas,9600 +StartOfPhase,2 +BankSizeIs,9600 +StartOfInitialRound +HasPriority,Palmiro +BID_ITEM_LOG,Palmiro,165,C&A,315 +BID_ITEM_LOG,Danilo,75,D&H,405 +BID_ITEM_LOG,Giancarlo,115,M&H,365 +BID_ITEM_LOG,Glauco,45,C&StL,435 +BID_ITEM_LOG,Roberto,170,C&A,310 +BID_ITEM_LOG,Palmiro,80,D&H,235 +BID_ITEM_LOG,Danilo,120,M&H,285 +BID_ITEM_LOG,Giancarlo,50,C&StL,315 +BuysItemFor,Glauco,SVNRR,20 +TO_AUCTION,C&StL +BID_ITEM_LOG,Glauco,55,C&StL,405 +BID_ITEM_LOG,Giancarlo,60,C&StL,305 +PASSES,Glauco +BuysItemFor,Giancarlo,C&StL,60 +TO_AUCTION,D&H +BID_ITEM_LOG,Danilo,85,D&H,275 +BID_ITEM_LOG,Palmiro,90,D&H,225 +PASSES,Danilo +BuysItemFor,Palmiro,D&H,90 +TO_AUCTION,M&H +BID_ITEM_LOG,Giancarlo,125,M&H,295 +BID_ITEM_LOG,Danilo,130,M&H,350 +BID_ITEM_LOG,Giancarlo,135,M&H,285 +BID_ITEM_LOG,Danilo,140,M&H,340 +PASSES,Giancarlo +BuysItemFor,Danilo,M&H,140 +TO_AUCTION,C&A +BID_ITEM_LOG,Palmiro,175,C&A,215 +BID_ITEM_LOG,Roberto,180,C&A,300 +BID_ITEM_LOG,Palmiro,185,C&A,205 +BID_ITEM_LOG,Roberto,190,C&A,290 +BID_ITEM_LOG,Palmiro,195,C&A,195 +BID_ITEM_LOG,Roberto,200,C&A,280 +BID_ITEM_LOG,Palmiro,210,C&A,180 +BID_ITEM_LOG,Roberto,215,C&A,265 +BID_ITEM_LOG,Palmiro,220,C&A,170 +BID_ITEM_LOG,Roberto,225,C&A,255 +BID_ITEM_LOG,Palmiro,230,C&A,160 +PASSES,Roberto +BuysItemFor,Palmiro,C&A,230 +ALSO_GETS,Palmiro,CERT_NAME,PRR,10 +PASSES,Roberto +PASSES,Danilo +BuysItemFor,Giancarlo,B&O,220 +ALSO_GETS,Giancarlo,PRES_CERT_NAME,B&O,20 +Has,Palmiro,160 +Has,Danilo,340 +Has,Giancarlo,200 +Has,Glauco,460 +Has,Roberto,480 +StartStockRound,1 +HasPriority,Glauco +START_COMPANY_LOG,Glauco,NYNH,76,152,2,20,BANK +START_COMPANY_LOG,Roberto,C&O,76,152,2,20,BANK +START_COMPANY_LOG,Palmiro,PRR,76,152,2,20,BANK +BUY_SHARE_LOG,Danilo,10,B&O,IPO,100 +PASSES,Giancarlo +BUY_SHARE_LOG,Glauco,10,NYNH,IPO,76 +BUY_SHARE_LOG,Roberto,10,C&O,IPO,76 +PASSES,Palmiro +BUY_SHARE_LOG,Danilo,10,B&O,IPO,100 +BUY_SHARE_LOG,Giancarlo,10,B&O,IPO,100 +BUY_SHARE_LOG,Glauco,10,NYNH,IPO,76 +BUY_SHARE_LOG,Roberto,10,C&O,IPO,76 +Autopasses,Palmiro +BUY_SHARE_LOG,Danilo,10,B&O,IPO,100 +FloatsWithCash,B&O,1000 +BUY_SHARE_LOG,Giancarlo,10,NYNH,IPO,76 +BUY_SHARE_LOG,Glauco,10,NYNH,IPO,76 +FloatsWithCash,NYNH,760 +BUY_SHARE_LOG,Roberto,10,C&O,IPO,76 +Autopasses,Palmiro +PASSES,Danilo +PASSES,Giancarlo +BUY_SHARE_LOG,Glauco,10,NYNH,IPO,76 +BUY_SHARE_LOG,Roberto,10,C&O,IPO,76 +FloatsWithCash,C&O,760 +Autopasses,Palmiro +PASSES,Danilo +Autopasses,Giancarlo +Autopasses,Glauco +Autopasses,Roberto + +END_SR,1 +Has,B&O,1000 +Has,C&O,760 +Has,NYNH,760 +Has,Palmiro,8 +Has,Danilo,40 +Has,Giancarlo,24 +Has,Glauco,4 +Has,Roberto,24 +START_OR,1.1 +ReceivesFor,Glauco,5,SVNRR +ReceivesFor,Giancarlo,10,C&StL +ReceivesFor,Palmiro,15,D&H +ReceivesFor,Danilo,20,M&H +ReceivesFor,Palmiro,25,C&A +ReceivesFor,Giancarlo,30,B&O + +CompanyOperates,B&O,Giancarlo +LaysTileAtFor,B&O,57,J14,SW,80 +LAYS_TOKEN_ON,B&O,J14,40 +CompanyDoesNotPayDividend,B&O +PRICE_MOVES_LOG,B&O,100,G1,90,F1 +BuysTrain,B&O,2,IPO,80 +PrivateCloses,B&O +FirstTrainBought,2 +BuysTrain,B&O,2,IPO,80 +BuysTrain,B&O,2,IPO,80 + +CompanyOperates,NYNH,Glauco +LaysTileAt,NYNH,56,F20,NW +CompanyDoesNotPayDividend,NYNH +PRICE_MOVES_LOG,NYNH,76,G4,71,F4 +BuysTrain,NYNH,2,IPO,80 +BuysTrain,NYNH,2,IPO,80 + +CompanyOperates,C&O,Roberto +LaysTileAt,C&O,8,G5,W +CompanyDoesNotPayDividend,C&O +PRICE_MOVES_LOG,C&O,76,G4,71,F4 +BuysTrain,C&O,2,IPO,80 +All 2-trains are sold out, 3-trains now available + +EndOfOperatingRound,1.1 +ORWorthIncrease,Palmiro,1.1,40 +ORWorthIncrease,Danilo,1.1,-10 +ORWorthIncrease,Giancarlo,1.1,-215 +ORWorthIncrease,Glauco,1.1,-25 +ORWorthIncrease,Roberto,1.1,-30 +Has,B&O,640 +Has,C&O,680 +Has,NYNH,600 +Has,Palmiro,48 +Has,Danilo,60 +Has,Giancarlo,64 +Has,Glauco,9 +Has,Roberto,24 +StartStockRound,2 +HasPriority,Palmiro +SELL_SHARE_LOG,Palmiro,10,PRR,76 +PRICE_MOVES_LOG,PRR,76,G4,71,G5 +PASSES,Danilo +PASSES,Giancarlo +PASSES,Glauco +PASSES,Roberto +BUY_SHARE_LOG,Palmiro,10,C&O,IPO,76 +PASSES,Danilo +PASSES,Giancarlo +PASSES,Glauco +PASSES,Roberto +PASSES,Palmiro + +END_SR,2 +Has,B&O,640 +Has,C&O,680 +Has,NYNH,600 +Has,Palmiro,48 +Has,Danilo,60 +Has,Giancarlo,64 +Has,Glauco,9 +Has,Roberto,24 +START_OR,2.1 +ReceivesFor,Glauco,5,SVNRR +ReceivesFor,Giancarlo,10,C&StL +ReceivesFor,Palmiro,15,D&H +ReceivesFor,Danilo,20,M&H +ReceivesFor,Palmiro,25,C&A + +CompanyOperates,B&O,Giancarlo +LaysTileAtFor,B&O,9,I17,W,80 +CompanyRevenue,B&O,140 +CompanyWithholds,B&O,140 +PRICE_MOVES_LOG,B&O,90,F1,82,E1 +BuysTrain,B&O,3,IPO,180 +FirstTrainBought,3 +StartOfPhase,3 +BuysPrivateFromFor,B&O,C&StL,Giancarlo,80 + +CompanyOperates,NYNH,Glauco +LaysTileAt,NYNH,57,E19,NW +CompanyRevenue,NYNH,50 +CompanyPaysOutFull,NYNH,50 +Payout,Giancarlo,5,1,10 +Payout,Glauco,30,6,10 +PRICE_MOVES_LOG,NYNH,71,F4,76,G4 +BuysPrivateFromFor,NYNH,SVNRR,Glauco,40 + +CompanyOperates,C&O,Roberto +LaysTileAt,C&O,8,G3,NW +CompanyRevenue,C&O,70 +CompanyPaysOutFull,C&O,70 +Payout,Palmiro,7,1,10 +Payout,Roberto,42,6,10 +PRICE_MOVES_LOG,C&O,71,F4,76,G4 +BuysTrain,C&O,3,IPO,180 + +EndOfOperatingRound,2.1 +ORWorthIncrease,Palmiro,2.1,52 +ORWorthIncrease,Danilo,2.1,-4 +ORWorthIncrease,Giancarlo,2.1,36 +ORWorthIncrease,Glauco,2.1,85 +ORWorthIncrease,Roberto,2.1,72 +Has,B&O,440 +Has,C&O,500 +Has,NYNH,560 +Has,Palmiro,95 +Has,Danilo,80 +Has,Giancarlo,159 +Has,Glauco,84 +Has,Roberto,66 +StartStockRound,3 +HasPriority,Danilo +BUY_SHARE_LOG,Danilo,10,C&O,IPO,76 +BUY_SHARE_LOG,Giancarlo,10,C&O,IPO,76 +BUY_SHARE_LOG,Glauco,10,C&O,IPO,76 +PASSES,Roberto +BUY_SHARE_LOG,Palmiro,10,PRR,IPO,76 +PASSES,Danilo +BUY_SHARE_LOG,Giancarlo,10,NYNH,IPO,76 +SELL_SHARES_LOG,Giancarlo,2,10,20,NYNH,152 +PRICE_MOVES_LOG,NYNH,76,G4,67,G6 +PASSES,Glauco +PASSES,Roberto +SELL_SHARE_LOG,Palmiro,10,C&O,76 +PRICE_MOVES_LOG,C&O,76,G4,71,G5 +BUY_SHARE_LOG,Palmiro,10,PRR,IPO,76 +PASSES,Danilo +BUY_SHARE_LOG,Giancarlo,10,PRR,Pool,71 +SELL_SHARE_LOG,Giancarlo,10,PRR,71 +PRICE_MOVES_LOG,PRR,71,G5,67,G6 +PASSES,Glauco +PASSES,Roberto +SELL_SHARE_LOG,Palmiro,10,PRR,67 +PRICE_MOVES_LOG,PRR,67,G6,67,G7 +BUY_SHARE_LOG,Palmiro,10,NYNH,Pool,67 +PASSES,Danilo +BUY_SHARE_LOG,Giancarlo,10,B&O,IPO,100 +PASSES,Glauco +PASSES,Roberto +PASSES,Palmiro +PASSES,Danilo +PASSES,Giancarlo + +END_SR,3 +Has,B&O,440 +Has,C&O,500 +Has,NYNH,560 +Has,Palmiro,19 +Has,Danilo,4 +Has,Giancarlo,59 +Has,Glauco,8 +Has,Roberto,66 +START_OR,3.1 +ReceivesFor,NYNH,5,SVNRR +ReceivesFor,B&O,10,C&StL +ReceivesFor,Palmiro,15,D&H +ReceivesFor,Danilo,20,M&H +ReceivesFor,Palmiro,25,C&A + +CompanyOperates,B&O,Giancarlo +LaysTileAt,B&O,14,J14,NW +CompanyRevenue,B&O,210 +CompanyWithholds,B&O,210 +PRICE_MOVES_LOG,B&O,82,E1,76,D1 + +CompanyOperates,C&O,Roberto +LaysTileAt,C&O,2,G7,SE +CompanyRevenue,C&O,110 +CompanyPaysOutFull,C&O,110 +Payout,Roberto,66,6,10 +Payout,Glauco,11,1,10 +Payout,Giancarlo,11,1,10 +Payout,Danilo,11,1,10 +Payout,C&O,11,1,10 +PRICE_MOVES_LOG,C&O,71,G5,76,H5 + +CompanyOperates,NYNH,Glauco +LaysTileAt,NYNH,14,E19,NW +LAYS_TOKEN_ON,NYNH,E19,40 +CompanyRevenue,NYNH,90 +CompanyPaysOutFull,NYNH,90 +Payout,Palmiro,9,1,10 +Payout,Glauco,54,6,10 +Payout,NYNH,9,1,10 +PRICE_MOVES_LOG,NYNH,67,G6,71,H6 + +EndOfOperatingRound,3.1 +ORWorthIncrease,Palmiro,3.1,53 +ORWorthIncrease,Danilo,3.1,18 +ORWorthIncrease,Giancarlo,3.1,-8 +ORWorthIncrease,Glauco,3.1,94 +ORWorthIncrease,Roberto,3.1,96 +Has,B&O,660 +Has,C&O,511 +Has,NYNH,534 +Has,Palmiro,68 +Has,Danilo,35 +Has,Giancarlo,70 +Has,Glauco,73 +Has,Roberto,132 +START_OR,3.2 +ReceivesFor,NYNH,5,SVNRR +ReceivesFor,B&O,10,C&StL +ReceivesFor,Palmiro,15,D&H +ReceivesFor,Danilo,20,M&H +ReceivesFor,Palmiro,25,C&A + +CompanyOperates,C&O,Roberto +LaysTileAt,C&O,8,H8,NW +CompanyRevenue,C&O,110 +CompanyPaysOutFull,C&O,110 +Payout,Roberto,66,6,10 +Payout,Glauco,11,1,10 +Payout,Danilo,11,1,10 +Payout,Giancarlo,11,1,10 +Payout,C&O,11,1,10 +PRICE_MOVES_LOG,C&O,76,H5,82,I5 + +CompanyOperates,B&O,Giancarlo +LaysTileAt,B&O,53,I15,SW +CompanyRevenue,B&O,250 +CompanyPaysOutFull,B&O,250 +Payout,Danilo,75,3,10 +Payout,Giancarlo,100,4,10 +PRICE_MOVES_LOG,B&O,76,D1,82,E1 + +CompanyOperates,NYNH,Glauco +LaysTileAt,NYNH,9,F18,SW +CompanyRevenue,NYNH,90 +CompanyPaysOutFull,NYNH,90 +Payout,Palmiro,9,1,10 +Payout,Glauco,54,6,10 +Payout,NYNH,9,1,10 +PRICE_MOVES_LOG,NYNH,71,H6,75,I6 +BuysTrain,NYNH,3,IPO,180 +BuysTrain,NYNH,3,IPO,180 + +EndOfOperatingRound,3.2 +ORWorthIncrease,Palmiro,3.2,53 +ORWorthIncrease,Danilo,3.2,130 +ORWorthIncrease,Giancarlo,3.2,141 +ORWorthIncrease,Glauco,3.2,95 +ORWorthIncrease,Roberto,3.2,102 +Has,B&O,670 +Has,C&O,522 +Has,NYNH,188 +Has,Palmiro,117 +Has,Danilo,141 +Has,Giancarlo,181 +Has,Glauco,138 +Has,Roberto,198 +StartStockRound,4 +HasPriority,Glauco +SELL_SHARE_LOG,Glauco,10,C&O,82 +PRICE_MOVES_LOG,C&O,82,I5,75,I6 +SELL_SHARES_LOG,Glauco,4,10,40,NYNH,300 +PRICE_MOVES_LOG,NYNH,75,I6,70,I7 +START_COMPANY_LOG,Glauco,NYC,82,164,2,20,BANK +SELL_SHARE_LOG,Roberto,10,C&O,75 +PRICE_MOVES_LOG,C&O,75,I6,70,I7 +BUY_SHARE_LOG,Roberto,10,NYNH,Pool,70 +SELL_SHARE_LOG,Palmiro,10,NYNH,70 +BUY_SHARE_LOG,Palmiro,10,PRR,Pool,67 +SELL_SHARES_LOG,Danilo,3,10,30,B&O,246 +PRICE_MOVES_LOG,B&O,82,E1,66,E4 +SELL_SHARE_LOG,Danilo,10,C&O,70 +START_COMPANY_LOG,Danilo,Erie,76,152,2,20,BANK +BUY_SHARE_LOG,Giancarlo,10,NYNH,Pool,70 +BUY_SHARE_LOG,Glauco,10,PRR,Pool,67 +SELL_SHARE_LOG,Glauco,10,PRR,67 +PRICE_MOVES_LOG,PRR,67,G7,67,G8 +BUY_SHARE_LOG,Roberto,10,NYNH,IPO,76 +BUY_SHARE_LOG,Palmiro,10,B&O,Pool,66 +SELL_SHARE_LOG,Palmiro,10,B&O,66 +PRICE_MOVES_LOG,B&O,66,E4,62,E5 +BUY_SHARE_LOG,Danilo,10,Erie,IPO,76 +BUY_SHARE_LOG,Giancarlo,10,NYC,IPO,82 +SELL_SHARE_LOG,Giancarlo,10,NYC,82 +PRICE_MOVES_LOG,NYC,82,G3,76,G4 +BUY_SHARE_LOG,Glauco,10,NYC,Pool,76 +PASSES,Roberto +BUY_SHARE_LOG,Palmiro,10,PRR,IPO,76 +FloatsWithCash,PRR,760 +BUY_SHARE_LOG,Danilo,10,Erie,IPO,76 +BUY_SHARE_LOG,Giancarlo,10,NYNH,Pool,70 +SELL_SHARE_LOG,Glauco,10,NYNH,70 +IS_NOW_PRES_OF,Roberto,NYNH +PASSES,Roberto +PASSES,Palmiro +BUY_SHARE_LOG,Danilo,10,NYNH,Pool,70 +PASSES,Giancarlo +PASSES,Glauco +SELL_SHARES_LOG,Roberto,2,10,20,NYNH,140 +IS_NOW_PRES_OF,Giancarlo,NYNH commit 1b472e8aae62cf0a68d9966f41d61345481c494e Author: Stefan Frey <ste...@we...> Date: Wed Feb 1 13:23:07 2012 +0100 Updated readme.txt for 1.6.2 diff --git a/readme.txt b/readme.txt index f26c93f..a496617 100644 --- a/readme.txt +++ b/readme.txt @@ -1,18 +1,9 @@ -Rails release 1.6.1: +Rails release 1.6.2: -A maintenance release for the 1.6.x branch. +A bug-fix release for the 1.6.x branch. -Contributors: Frederick Weld, Erik Vos -Bugs reported by Bill Probst. +Contributor: Erik Vos +Bug reported by Bill Probst. -List of bugs fixed and further changes: -- Enforced that the DynamicReportWindow stays on top during time warp -- Added background map for 1889 (courtesy of Frederick Weld) -- Fixed autosave functionality (handling of 18xx_autosave.xxx files) -- Fixed retrieval of default game options (if options pane was not opened) -- Fixed 1856 background map's mini-map (Windsor area) -- Enforce selling over-limit shares first -- Fixed wrong price of 6 train (630 => 600) in 18TN - -Note: To show a background map, the option has to be switched on in Configuration => Map/Report => Display background map. -Background maps are only available for 1856, 1889, 18EU, 18GA (incl. Cotton Port) and 18AL so far. +Single bug fixed: +A sole presidency share could not be dumped. \ No newline at end of file commit f86c3aa27724e73aa6c904ef9a4612ff43c93b0f Author: Stefan Frey <ste...@we...> Date: Wed Feb 1 13:21:37 2012 +0100 Changed version number to 1.6.2 diff --git a/version.number b/version.number index d54f51c..70672b0 100644 --- a/version.number +++ b/version.number @@ -1,5 +1,5 @@ #Property file that contains version number and the develop indicator -version=1.6.1 +version=1.6.2 # the following string "@DEVELOP@ is replaced by an empty string in the release version # this is done automatically by ant develop=@DEVELOP@ \ No newline at end of file commit 2c91b6c26f7f7117534477f7b08f5f220dd25daa Author: Erik Vos <eri...@xs...> Date: Wed Feb 1 13:20:43 2012 +0100 Fixed: a sole presidency share could not be dumped. This is hand-picked from the commit of Erik Vos: a26c98646bc379d17a48121a74b49e8cc54cea05 diff --git a/rails/game/StockRound.java b/rails/game/StockRound.java index 037d2cc..1446fb5 100644 --- a/rails/game/StockRound.java +++ b/rails/game/StockRound.java @@ -471,11 +471,12 @@ public class StockRound extends Round { /* Allow for different share units (as in 1835) */ for (int shareSize = 1; shareSize <= 4; shareSize++) { number = shareCountPerUnit[shareSize]; - if (number == 0) continue; // If you can dump a presidency, you may sell additional single shares that you don't own if (shareSize == 1) number += extraSingleShares; + if (number == 0) continue; + /* In some games (1856), a just bought share may not be sold */ // This code ignores the possibility of different share units if ((Boolean)gameManager.getGameParameter(GameDef.Parm.NO_SALE_OF_JUST_BOUGHT_CERT) |
From: Stefan F. <ste...@us...> - 2012-02-01 06:40:24
|
test/data/bugs/1830_sellPresidency.rails |binary test/data/bugs/1830_sellPresidency.report | 408 ++++++++++++++++++++++++++++++ 2 files changed, 408 insertions(+) New commits: commit a7c513c2ba686d4b9e542491bac68a7d3718dc37 Author: Stefan Frey <ste...@we...> Date: Wed Feb 1 07:39:30 2012 +0100 added test case for fixed sell presidency bug diff --git a/test/data/bugs/1830_sellPresidency.rails b/test/data/bugs/1830_sellPresidency.rails new file mode 100644 index 0000000..c3fd78c Binary files /dev/null and b/test/data/bugs/1830_sellPresidency.rails differ diff --git a/test/data/bugs/1830_sellPresidency.report b/test/data/bugs/1830_sellPresidency.report new file mode 100644 index 0000000..f2ed980 --- /dev/null +++ b/test/data/bugs/1830_sellPresidency.report @@ -0,0 +1,408 @@ +GameIs,1830 +PlayerIs,1,Palmiro +PlayerIs,2,Danilo +PlayerIs,3,Giancarlo +PlayerIs,4,Glauco +PlayerIs,5,Roberto +PlayerCash,480 +BankHas,9600 +StartOfPhase,2 +BankSizeIs,9600 +StartOfInitialRound +HasPriority,Palmiro +BID_ITEM_LOG,Palmiro,165,C&A,315 +BID_ITEM_LOG,Danilo,75,D&H,405 +BID_ITEM_LOG,Giancarlo,115,M&H,365 +BID_ITEM_LOG,Glauco,45,C&StL,435 +BID_ITEM_LOG,Roberto,170,C&A,310 +BID_ITEM_LOG,Palmiro,80,D&H,235 +BID_ITEM_LOG,Danilo,120,M&H,285 +BID_ITEM_LOG,Giancarlo,50,C&StL,315 +BuysItemFor,Glauco,SVNRR,20 +TO_AUCTION,C&StL +BID_ITEM_LOG,Glauco,55,C&StL,405 +BID_ITEM_LOG,Giancarlo,60,C&StL,305 +PASSES,Glauco +BuysItemFor,Giancarlo,C&StL,60 +TO_AUCTION,D&H +BID_ITEM_LOG,Danilo,85,D&H,275 +BID_ITEM_LOG,Palmiro,90,D&H,225 +PASSES,Danilo +BuysItemFor,Palmiro,D&H,90 +TO_AUCTION,M&H +BID_ITEM_LOG,Giancarlo,125,M&H,295 +BID_ITEM_LOG,Danilo,130,M&H,350 +BID_ITEM_LOG,Giancarlo,135,M&H,285 +BID_ITEM_LOG,Danilo,140,M&H,340 +PASSES,Giancarlo +BuysItemFor,Danilo,M&H,140 +TO_AUCTION,C&A +BID_ITEM_LOG,Palmiro,175,C&A,215 +BID_ITEM_LOG,Roberto,180,C&A,300 +BID_ITEM_LOG,Palmiro,185,C&A,205 +BID_ITEM_LOG,Roberto,190,C&A,290 +BID_ITEM_LOG,Palmiro,195,C&A,195 +BID_ITEM_LOG,Roberto,200,C&A,280 +BID_ITEM_LOG,Palmiro,210,C&A,180 +BID_ITEM_LOG,Roberto,215,C&A,265 +BID_ITEM_LOG,Palmiro,220,C&A,170 +BID_ITEM_LOG,Roberto,225,C&A,255 +BID_ITEM_LOG,Palmiro,230,C&A,160 +PASSES,Roberto +BuysItemFor,Palmiro,C&A,230 +ALSO_GETS,Palmiro,CERT_NAME,PRR,10 +PASSES,Roberto +PASSES,Danilo +BuysItemFor,Giancarlo,B&O,220 +ALSO_GETS,Giancarlo,PRES_CERT_NAME,B&O,20 +Has,Palmiro,160 +Has,Danilo,340 +Has,Giancarlo,200 +Has,Glauco,460 +Has,Roberto,480 +StartStockRound,1 +HasPriority,Glauco +START_COMPANY_LOG,Glauco,NYNH,76,152,2,20,BANK +START_COMPANY_LOG,Roberto,C&O,76,152,2,20,BANK +START_COMPANY_LOG,Palmiro,PRR,76,152,2,20,BANK +BUY_SHARE_LOG,Danilo,10,B&O,IPO,100 +PASSES,Giancarlo +BUY_SHARE_LOG,Glauco,10,NYNH,IPO,76 +BUY_SHARE_LOG,Roberto,10,C&O,IPO,76 +PASSES,Palmiro +BUY_SHARE_LOG,Danilo,10,B&O,IPO,100 +BUY_SHARE_LOG,Giancarlo,10,B&O,IPO,100 +BUY_SHARE_LOG,Glauco,10,NYNH,IPO,76 +BUY_SHARE_LOG,Roberto,10,C&O,IPO,76 +Autopasses,Palmiro +BUY_SHARE_LOG,Danilo,10,B&O,IPO,100 +FloatsWithCash,B&O,1000 +BUY_SHARE_LOG,Giancarlo,10,NYNH,IPO,76 +BUY_SHARE_LOG,Glauco,10,NYNH,IPO,76 +FloatsWithCash,NYNH,760 +BUY_SHARE_LOG,Roberto,10,C&O,IPO,76 +Autopasses,Palmiro +PASSES,Danilo +PASSES,Giancarlo +BUY_SHARE_LOG,Glauco,10,NYNH,IPO,76 +BUY_SHARE_LOG,Roberto,10,C&O,IPO,76 +FloatsWithCash,C&O,760 +Autopasses,Palmiro +PASSES,Danilo +Autopasses,Giancarlo +Autopasses,Glauco +Autopasses,Roberto + +END_SR,1 +Has,B&O,1000 +Has,C&O,760 +Has,NYNH,760 +Has,Palmiro,8 +Has,Danilo,40 +Has,Giancarlo,24 +Has,Glauco,4 +Has,Roberto,24 +START_OR,1.1 +ReceivesFor,Glauco,5,SVNRR +ReceivesFor,Giancarlo,10,C&StL +ReceivesFor,Palmiro,15,D&H +ReceivesFor,Danilo,20,M&H +ReceivesFor,Palmiro,25,C&A +ReceivesFor,Giancarlo,30,B&O + +CompanyOperates,B&O,Giancarlo +LaysTileAtFor,B&O,57,J14,SW,80 +LAYS_TOKEN_ON,B&O,J14,40 +CompanyDoesNotPayDividend,B&O +PRICE_MOVES_LOG,B&O,100,G1,90,F1 +BuysTrain,B&O,2,IPO,80 +PrivateCloses,B&O +FirstTrainBought,2 +BuysTrain,B&O,2,IPO,80 +BuysTrain,B&O,2,IPO,80 + +CompanyOperates,NYNH,Glauco +LaysTileAt,NYNH,56,F20,NW +CompanyDoesNotPayDividend,NYNH +PRICE_MOVES_LOG,NYNH,76,G4,71,F4 +BuysTrain,NYNH,2,IPO,80 +BuysTrain,NYNH,2,IPO,80 + +CompanyOperates,C&O,Roberto +LaysTileAt,C&O,8,G5,W +CompanyDoesNotPayDividend,C&O +PRICE_MOVES_LOG,C&O,76,G4,71,F4 +BuysTrain,C&O,2,IPO,80 +All 2-trains are sold out, 3-trains now available + +EndOfOperatingRound,1.1 +ORWorthIncrease,Palmiro,1.1,40 +ORWorthIncrease,Danilo,1.1,-10 +ORWorthIncrease,Giancarlo,1.1,-215 +ORWorthIncrease,Glauco,1.1,-25 +ORWorthIncrease,Roberto,1.1,-30 +Has,B&O,640 +Has,C&O,680 +Has,NYNH,600 +Has,Palmiro,48 +Has,Danilo,60 +Has,Giancarlo,64 +Has,Glauco,9 +Has,Roberto,24 +StartStockRound,2 +HasPriority,Palmiro +SELL_SHARE_LOG,Palmiro,10,PRR,76 +PRICE_MOVES_LOG,PRR,76,G4,71,G5 +PASSES,Danilo +PASSES,Giancarlo +PASSES,Glauco +PASSES,Roberto +BUY_SHARE_LOG,Palmiro,10,C&O,IPO,76 +PASSES,Danilo +PASSES,Giancarlo +PASSES,Glauco +PASSES,Roberto +PASSES,Palmiro + +END_SR,2 +Has,B&O,640 +Has,C&O,680 +Has,NYNH,600 +Has,Palmiro,48 +Has,Danilo,60 +Has,Giancarlo,64 +Has,Glauco,9 +Has,Roberto,24 +START_OR,2.1 +ReceivesFor,Glauco,5,SVNRR +ReceivesFor,Giancarlo,10,C&StL +ReceivesFor,Palmiro,15,D&H +ReceivesFor,Danilo,20,M&H +ReceivesFor,Palmiro,25,C&A + +CompanyOperates,B&O,Giancarlo +LaysTileAtFor,B&O,9,I17,W,80 +CompanyRevenue,B&O,140 +CompanyWithholds,B&O,140 +PRICE_MOVES_LOG,B&O,90,F1,82,E1 +BuysTrain,B&O,3,IPO,180 +FirstTrainBought,3 +StartOfPhase,3 +BuysPrivateFromFor,B&O,C&StL,Giancarlo,80 + +CompanyOperates,NYNH,Glauco +LaysTileAt,NYNH,57,E19,NW +CompanyRevenue,NYNH,50 +CompanyPaysOutFull,NYNH,50 +Payout,Giancarlo,5,1,10 +Payout,Glauco,30,6,10 +PRICE_MOVES_LOG,NYNH,71,F4,76,G4 +BuysPrivateFromFor,NYNH,SVNRR,Glauco,40 + +CompanyOperates,C&O,Roberto +LaysTileAt,C&O,8,G3,NW +CompanyRevenue,C&O,70 +CompanyPaysOutFull,C&O,70 +Payout,Palmiro,7,1,10 +Payout,Roberto,42,6,10 +PRICE_MOVES_LOG,C&O,71,F4,76,G4 +BuysTrain,C&O,3,IPO,180 + +EndOfOperatingRound,2.1 +ORWorthIncrease,Palmiro,2.1,52 +ORWorthIncrease,Danilo,2.1,-4 +ORWorthIncrease,Giancarlo,2.1,36 +ORWorthIncrease,Glauco,2.1,85 +ORWorthIncrease,Roberto,2.1,72 +Has,B&O,440 +Has,C&O,500 +Has,NYNH,560 +Has,Palmiro,95 +Has,Danilo,80 +Has,Giancarlo,159 +Has,Glauco,84 +Has,Roberto,66 +StartStockRound,3 +HasPriority,Danilo +BUY_SHARE_LOG,Danilo,10,C&O,IPO,76 +BUY_SHARE_LOG,Giancarlo,10,C&O,IPO,76 +BUY_SHARE_LOG,Glauco,10,C&O,IPO,76 +PASSES,Roberto +BUY_SHARE_LOG,Palmiro,10,PRR,IPO,76 +PASSES,Danilo +BUY_SHARE_LOG,Giancarlo,10,NYNH,IPO,76 +SELL_SHARES_LOG,Giancarlo,2,10,20,NYNH,152 +PRICE_MOVES_LOG,NYNH,76,G4,67,G6 +PASSES,Glauco +PASSES,Roberto +SELL_SHARE_LOG,Palmiro,10,C&O,76 +PRICE_MOVES_LOG,C&O,76,G4,71,G5 +BUY_SHARE_LOG,Palmiro,10,PRR,IPO,76 +PASSES,Danilo +BUY_SHARE_LOG,Giancarlo,10,PRR,Pool,71 +SELL_SHARE_LOG,Giancarlo,10,PRR,71 +PRICE_MOVES_LOG,PRR,71,G5,67,G6 +PASSES,Glauco +PASSES,Roberto +SELL_SHARE_LOG,Palmiro,10,PRR,67 +PRICE_MOVES_LOG,PRR,67,G6,67,G7 +BUY_SHARE_LOG,Palmiro,10,NYNH,Pool,67 +PASSES,Danilo +BUY_SHARE_LOG,Giancarlo,10,B&O,IPO,100 +PASSES,Glauco +PASSES,Roberto +PASSES,Palmiro +PASSES,Danilo +PASSES,Giancarlo + +END_SR,3 +Has,B&O,440 +Has,C&O,500 +Has,NYNH,560 +Has,Palmiro,19 +Has,Danilo,4 +Has,Giancarlo,59 +Has,Glauco,8 +Has,Roberto,66 +START_OR,3.1 +ReceivesFor,NYNH,5,SVNRR +ReceivesFor,B&O,10,C&StL +ReceivesFor,Palmiro,15,D&H +ReceivesFor,Danilo,20,M&H +ReceivesFor,Palmiro,25,C&A + +CompanyOperates,B&O,Giancarlo +LaysTileAt,B&O,14,J14,NW +CompanyRevenue,B&O,210 +CompanyWithholds,B&O,210 +PRICE_MOVES_LOG,B&O,82,E1,76,D1 + +CompanyOperates,C&O,Roberto +LaysTileAt,C&O,2,G7,SE +CompanyRevenue,C&O,110 +CompanyPaysOutFull,C&O,110 +Payout,Roberto,66,6,10 +Payout,Glauco,11,1,10 +Payout,Giancarlo,11,1,10 +Payout,Danilo,11,1,10 +Payout,C&O,11,1,10 +PRICE_MOVES_LOG,C&O,71,G5,76,H5 + +CompanyOperates,NYNH,Glauco +LaysTileAt,NYNH,14,E19,NW +LAYS_TOKEN_ON,NYNH,E19,40 +CompanyRevenue,NYNH,90 +CompanyPaysOutFull,NYNH,90 +Payout,Palmiro,9,1,10 +Payout,Glauco,54,6,10 +Payout,NYNH,9,1,10 +PRICE_MOVES_LOG,NYNH,67,G6,71,H6 + +EndOfOperatingRound,3.1 +ORWorthIncrease,Palmiro,3.1,53 +ORWorthIncrease,Danilo,3.1,18 +ORWorthIncrease,Giancarlo,3.1,-8 +ORWorthIncrease,Glauco,3.1,94 +ORWorthIncrease,Roberto,3.1,96 +Has,B&O,660 +Has,C&O,511 +Has,NYNH,534 +Has,Palmiro,68 +Has,Danilo,35 +Has,Giancarlo,70 +Has,Glauco,73 +Has,Roberto,132 +START_OR,3.2 +ReceivesFor,NYNH,5,SVNRR +ReceivesFor,B&O,10,C&StL +ReceivesFor,Palmiro,15,D&H +ReceivesFor,Danilo,20,M&H +ReceivesFor,Palmiro,25,C&A + +CompanyOperates,C&O,Roberto +LaysTileAt,C&O,8,H8,NW +CompanyRevenue,C&O,110 +CompanyPaysOutFull,C&O,110 +Payout,Roberto,66,6,10 +Payout,Glauco,11,1,10 +Payout,Danilo,11,1,10 +Payout,Giancarlo,11,1,10 +Payout,C&O,11,1,10 +PRICE_MOVES_LOG,C&O,76,H5,82,I5 + +CompanyOperates,B&O,Giancarlo +LaysTileAt,B&O,53,I15,SW +CompanyRevenue,B&O,250 +CompanyPaysOutFull,B&O,250 +Payout,Danilo,75,3,10 +Payout,Giancarlo,100,4,10 +PRICE_MOVES_LOG,B&O,76,D1,82,E1 + +CompanyOperates,NYNH,Glauco +LaysTileAt,NYNH,9,F18,SW +CompanyRevenue,NYNH,90 +CompanyPaysOutFull,NYNH,90 +Payout,Palmiro,9,1,10 +Payout,Glauco,54,6,10 +Payout,NYNH,9,1,10 +PRICE_MOVES_LOG,NYNH,71,H6,75,I6 +BuysTrain,NYNH,3,IPO,180 +BuysTrain,NYNH,3,IPO,180 + +EndOfOperatingRound,3.2 +ORWorthIncrease,Palmiro,3.2,53 +ORWorthIncrease,Danilo,3.2,130 +ORWorthIncrease,Giancarlo,3.2,141 +ORWorthIncrease,Glauco,3.2,95 +ORWorthIncrease,Roberto,3.2,102 +Has,B&O,670 +Has,C&O,522 +Has,NYNH,188 +Has,Palmiro,117 +Has,Danilo,141 +Has,Giancarlo,181 +Has,Glauco,138 +Has,Roberto,198 +StartStockRound,4 +HasPriority,Glauco +SELL_SHARE_LOG,Glauco,10,C&O,82 +PRICE_MOVES_LOG,C&O,82,I5,75,I6 +SELL_SHARES_LOG,Glauco,4,10,40,NYNH,300 +PRICE_MOVES_LOG,NYNH,75,I6,70,I7 +START_COMPANY_LOG,Glauco,NYC,82,164,2,20,BANK +SELL_SHARE_LOG,Roberto,10,C&O,75 +PRICE_MOVES_LOG,C&O,75,I6,70,I7 +BUY_SHARE_LOG,Roberto,10,NYNH,Pool,70 +SELL_SHARE_LOG,Palmiro,10,NYNH,70 +BUY_SHARE_LOG,Palmiro,10,PRR,Pool,67 +SELL_SHARES_LOG,Danilo,3,10,30,B&O,246 +PRICE_MOVES_LOG,B&O,82,E1,66,E4 +SELL_SHARE_LOG,Danilo,10,C&O,70 +START_COMPANY_LOG,Danilo,Erie,76,152,2,20,BANK +BUY_SHARE_LOG,Giancarlo,10,NYNH,Pool,70 +BUY_SHARE_LOG,Glauco,10,PRR,Pool,67 +SELL_SHARE_LOG,Glauco,10,PRR,67 +PRICE_MOVES_LOG,PRR,67,G7,67,G8 +BUY_SHARE_LOG,Roberto,10,NYNH,IPO,76 +BUY_SHARE_LOG,Palmiro,10,B&O,Pool,66 +SELL_SHARE_LOG,Palmiro,10,B&O,66 +PRICE_MOVES_LOG,B&O,66,E4,62,E5 +BUY_SHARE_LOG,Danilo,10,Erie,IPO,76 +BUY_SHARE_LOG,Giancarlo,10,NYC,IPO,82 +SELL_SHARE_LOG,Giancarlo,10,NYC,82 +PRICE_MOVES_LOG,NYC,82,G3,76,G4 +BUY_SHARE_LOG,Glauco,10,NYC,Pool,76 +PASSES,Roberto +BUY_SHARE_LOG,Palmiro,10,PRR,IPO,76 +FloatsWithCash,PRR,760 +BUY_SHARE_LOG,Danilo,10,Erie,IPO,76 +BUY_SHARE_LOG,Giancarlo,10,NYNH,Pool,70 +SELL_SHARE_LOG,Glauco,10,NYNH,70 +IS_NOW_PRES_OF,Roberto,NYNH +PASSES,Roberto +PASSES,Palmiro +BUY_SHARE_LOG,Danilo,10,NYNH,Pool,70 +PASSES,Giancarlo +PASSES,Glauco +SELL_SHARES_LOG,Roberto,2,10,20,NYNH,140 +IS_NOW_PRES_OF,Giancarlo,NYNH |
From: Erik V. <ev...@us...> - 2012-01-31 21:14:23
|
rails/game/StockRound.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) New commits: commit ab22d0a0c83984486ede637b247322fb0030eb09 Merge: a26c986 98248e7 Author: Erik Vos <eri...@xs...> Date: Tue Jan 31 22:13:53 2012 +0100 Merge branch 'master' of ssh://rails.git.sourceforge.net/gitroot/rails/rails commit a26c98646bc379d17a48121a74b49e8cc54cea05 Author: Erik Vos <eri...@xs...> Date: Tue Jan 31 22:12:45 2012 +0100 Fixed: a sole presidency share could not be dumped. diff --git a/LocalisedText.properties b/LocalisedText.properties index 8ef0a7f..b8ff06d 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -177,6 +177,7 @@ Config.infoText.sound.backgroundMusic=The only music file type supported is mp3. Config.infoText.sound.backgroundMusic.stockRound=<html>Enter assignment of music files 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 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.infoText.sound.sfx=The only sound effects file type supported is mp3. +Config.infoText.sound.sfx.gen.newCurrentPlayer=<html>Enter assignment of sound effect files to player names.<br>The assigned sound is played if the player becomes the active one - meaning, the user interface is responsive for this player's commands.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax playerName=complete file path<li>Default sound effect is defined by omitting "playerName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\ChangeActivePlayer.mp3</code><li>Set player-dependent sound effect and a default (for all other players): <br><code>Tom=c:\ChangeActivePlayer_Tom.mp3,Sarah=c:\ChangeActivePlayer_Sarah.mp3,c:\ChangeActivePlayer_default.mp3</code></ul> </html> Config.infoText.sound.sfx.or.buyTrain=<html>Enter assignment of sound effect files to train types.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax trainName=complete file path<li>Default sound effect is defined by omitting "trainName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\BuyTrain-default.mp3</code><li>Set train-dependent sound effect and a default (for trains above 6): <br><code>2=c:\BuyTrain-2.mp3,3=c:\BuyTrain-3.mp3,4=c:\BuyTrain-4.mp3,5=c:\BuyTrain-5.mp3,6=c:\BuyTrain-6.mp3,c:\BuyTrain-D.mp3</code></ul> </html> Config.infoText.sound.sfx.or.setRevenue=<html><ul><li>Only the latter portion of this file is played.<ul><li>For an average revenue, the last third is played.</ul><li>The higher the company's revenue the longer this file is played.<ul><li>But the file is at most played once as a whole.</li></ul></html> Config.infoText.sound.sfx.sr.newPresident=This also includes becoming the president when buying the president share. @@ -213,7 +214,9 @@ Config.label.sound.backgroundMusic.startRound=Start Round Config.label.sound.backgroundMusic.stockRound=Stock Round (several files) Config.label.sound.backgroundMusic.operatingRound=Operating Round (several files) Config.label.sound.sfx=Sound Effects +Config.label.sound.sfx.gen.newCurrentPlayer=Change of active player Config.label.sound.sfx.gen.pass=Pass +Config.label.sound.sfx.gen.select=Select (hexes, click fields) Config.label.sound.sfx.str.bidStartItem=Bid on Start Item Config.label.sound.sfx.str.buyStartItem=Buy Start Item Config.label.sound.sfx.or.buyP |
From: Stefan F. <ste...@us...> - 2012-01-31 14:30:14
|
rails/common/parser/GameFileParser.java | 8 - rails/game/Game.java | 2 rails/game/GameManager.java | 10 - rails/game/OperatingRound.java | 2 rails/game/PublicCompany.java | 14 - rails/game/Round.java | 4 rails/game/ShareSellingRound.java | 2 rails/game/StockMarket.java | 141 ++++++++++--------- rails/game/StockMarketI.java | 51 ------- rails/game/StockRound.java | 18 +- rails/game/StockSpace.java | 112 ++++++++++----- rails/game/StockSpaceI.java | 160 ---------------------- rails/game/StockSpaceType.java | 37 ++++- rails/game/StockSpaceTypeI.java | 86 ----------- rails/game/TreasuryShareRound.java | 2 rails/game/model/PriceModel.java | 68 +++------ rails/game/model/ViewUpdate.java | 2 rails/game/specific/_1825/PublicCompany_1825.java | 4 rails/game/specific/_1835/StockRound_1835.java | 4 rails/game/specific/_1856/CGRFormationRound.java | 2 rails/game/specific/_1856/PublicCompany_1856.java | 2 rails/game/specific/_18EU/StockRound_18EU.java | 4 rails/game/state/PriceMove.java | 51 ------- rails/game/state/PriceTokenMove.java | 52 ------- rails/ui/swing/StartRoundWindow.java | 10 - rails/ui/swing/StockChart.java | 4 rails/ui/swing/elements/GUIStockSpace.java | 6 test/GameTestServlet.java | 8 - test/StockMarketTestServlet.java | 6 test/StockTest.java | 4 30 files changed, 269 insertions(+), 607 deletions(-) New commits: commit 0bd58a3e647b7840c035b9f6642668df5fb23960 Author: Stefan Frey <ste...@we...> Date: Mon Jan 30 16:44:21 2012 +0100 rewrote StockSpace classes and PriceMove mechanism diff --git a/rails/common/parser/GameFileParser.java b/rails/common/parser/GameFileParser.java index d6eb4ec..31bc10a 100644 --- a/rails/common/parser/GameFileParser.java +++ b/rails/common/parser/GameFileParser.java @@ -12,7 +12,7 @@ import rails.game.GameManager; import rails.game.MapManager; import rails.game.PhaseManager; import rails.game.PlayerManager; -import rails.game.StockMarketI; +import rails.game.StockMarket; import rails.game.TileManager; import rails.game.TrainManager; import rails.game.state.Context; @@ -28,7 +28,7 @@ public class GameFileParser extends XMLParser { private PlayerManager playerManager; private PhaseManager phaseManager; private TrainManager trainManager; - private StockMarketI stockMarket; + private StockMarket stockMarket; private MapManager mapManager; private TileManager tileManager; private RevenueManager revenueManager; @@ -48,7 +48,7 @@ public class GameFileParser extends XMLParser { playerManager = (PlayerManager) componentManager.findComponent("PlayerManager"); bank = (Bank) componentManager.findComponent("Bank"); companyManager = (CompanyManagerI) componentManager.findComponent(CompanyManagerI.COMPONENT_NAME); - stockMarket = (StockMarketI) componentManager.findComponent(StockMarketI.COMPONENT_NAME); + stockMarket = (StockMarket) componentManager.findComponent(StockMarket.COMPONENT_NAME); gameManager = (GameManager) componentManager.findComponent("GameManager"); phaseManager = (PhaseManager) componentManager.findComponent("PhaseManager"); trainManager = (TrainManager) componentManager.findComponent("TrainManager"); @@ -110,7 +110,7 @@ public class GameFileParser extends XMLParser { /** * @return the stockMarket */ - public StockMarketI getStockMarket() { + public StockMarket getStockMarket() { return stockMarket; } diff --git a/rails/game/Game.java b/rails/game/Game.java index db247c3..bab64de 100644 --- a/rails/game/Game.java +++ b/rails/game/Game.java @@ -22,7 +22,7 @@ public class Game { protected PlayerManager playerManager; protected PhaseManager phaseManager; protected TrainManager trainManager; - protected StockMarketI stockMarket; + protected StockMarket stockMarket; protected MapManager mapManager; protected TileManager tileManager; protected RevenueManager revenueManager; diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java index c36d563..f476031 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -59,7 +59,7 @@ public class GameManager extends GameItem implements Owner, ConfigurableComponen protected CompanyManagerI companyManager; protected PhaseManager phaseManager; protected TrainManager trainManager; - protected StockMarketI stockMarket; + protected StockMarket stockMarket; protected MapManager mapManager; protected TileManager tileManager; protected RevenueManager revenueManager; @@ -532,7 +532,7 @@ public class GameManager extends GameItem implements Owner, ConfigurableComponen CompanyManagerI companyManager, PhaseManager phaseManager, TrainManager trainManager, - StockMarketI stockMarket, + StockMarket stockMarket, MapManager mapManager, TileManager tileManager, RevenueManager revenueManager, @@ -1317,7 +1317,7 @@ public class GameManager extends GameItem implements Owner, ConfigurableComponen addToNextPlayerMessages(msg, true); } - public void registerMaxedSharePrice(PublicCompany company, StockSpaceI space){ + public void registerMaxedSharePrice(PublicCompany company, StockSpace space){ gameOverPending.set(true); ReportBuffer.add(LocalText.getText("MaxedSharePriceReportText", company.getId(), @@ -1581,7 +1581,7 @@ public class GameManager extends GameItem implements Owner, ConfigurableComponen return trainManager; } - public StockMarketI getStockMarket() { + public StockMarket getStockMarket() { return stockMarket; } @@ -1806,7 +1806,7 @@ public class GameManager extends GameItem implements Owner, ConfigurableComponen Map<Integer, PublicCompany> operatingCompanies = new TreeMap<Integer, PublicCompany>(); - StockSpaceI space; + StockSpace space; int key; int minorNo = 0; for (PublicCompany company : companyManager.getAllPublicCompanies()) { diff --git a/rails/game/OperatingRound.java b/rails/game/OperatingRound.java index 7f592f6..abf8a41 100644 --- a/rails/game/OperatingRound.java +++ b/rails/game/OperatingRound.java @@ -2375,7 +2375,7 @@ public class OperatingRound extends Round implements Observer { if (!company.hasStockPrice()) return; // Check if company has entered a closing area - StockSpaceI newSpace = company.getCurrentSpace(); + StockSpace newSpace = company.getCurrentSpace(); if (newSpace.closesCompany() && company.canClose()) { company.setClosed(); ReportBuffer.add(LocalText.getText("CompanyClosesAt", diff --git a/rails/game/PublicCompany.java b/rails/game/PublicCompany.java index 6f022a6..7b9f364 100644 --- a/rails/game/PublicCompany.java +++ b/rails/game/PublicCompany.java @@ -279,7 +279,7 @@ public class PublicCompany extends Company implements CashOwner { protected GameManager gameManager; protected Bank bank; - protected StockMarketI stockMarket; + protected StockMarket stockMarket; protected MapManager mapManager; /** Rights */ @@ -911,7 +911,7 @@ public class PublicCompany extends Company implements CashOwner { return mustHaveOperatedToTradeShares; } - public void start(StockSpaceI startSpace) { + public void start(StockSpace startSpace) { hasStarted.set(true); if (hasStockPrice) buyable.set(true); @@ -932,7 +932,7 @@ public class PublicCompany extends Company implements CashOwner { } public void start(int price) { - StockSpaceI startSpace = stockMarket.getStartSpace(price); + StockSpace startSpace = stockMarket.getStartSpace(price); if (startSpace == null) { log.error("Invalid start price " + Bank.format(price)); } else { @@ -1099,7 +1099,7 @@ public class PublicCompany extends Company implements CashOwner { * * @param spaceI */ - public void setParSpace(StockSpaceI space) { + public void setParSpace(StockSpace space) { if (hasStockPrice) { if (space != null) { parPrice.setPrice(space); @@ -1113,7 +1113,7 @@ public class PublicCompany extends Company implements CashOwner { * @return StockSpace object, which defines the company start position on * the stock chart. */ - public StockSpaceI getStartSpace() { + public StockSpace getStartSpace() { if (hasParPrice) { return parPrice != null ? parPrice.getPrice() : null; } else { @@ -1156,7 +1156,7 @@ public class PublicCompany extends Company implements CashOwner { * @param price The StockSpace object that defines the new location on the * stock market. */ - public void setCurrentSpace(StockSpaceI price) { + public void setCurrentSpace(StockSpace price) { if (price != null) { currentPrice.setPrice(price); } @@ -1179,7 +1179,7 @@ public class PublicCompany extends Company implements CashOwner { * @return The StockSpace object that defines the current location on the * stock market. */ - public StockSpaceI getCurrentSpace() { + public StockSpace getCurrentSpace() { return currentPrice != null ? currentPrice.getPrice() : null; } diff --git a/rails/game/Round.java b/rails/game/Round.java index d7151f5..058fd7a 100644 --- a/rails/game/Round.java +++ b/rails/game/Round.java @@ -38,7 +38,7 @@ public abstract class Round extends GameItem implements RoundI { protected Portfolio pool = null; protected Portfolio unavailable = null; protected Portfolio scrapHeap = null; - protected StockMarketI stockMarket = null; + protected StockMarket stockMarket = null; protected MapManager mapManager = null; //protected Class<? extends RoundI> roundTypeForUI = null; @@ -272,7 +272,7 @@ public abstract class Round extends GameItem implements RoundI { Map<Integer, PublicCompany> operatingCompanies = new TreeMap<Integer, PublicCompany>(); List<PublicCompany> newOperatingCompanies; - StockSpaceI space; + StockSpace space; int key; int minorNo = 0; boolean reorder = gameManager.isDynamicOperatingOrder() diff --git a/rails/game/ShareSellingRound.java b/rails/game/ShareSellingRound.java index c01459c..b9308f8 100644 --- a/rails/game/ShareSellingRound.java +++ b/rails/game/ShareSellingRound.java @@ -351,7 +351,7 @@ public class ShareSellingRound extends StockRound { } // All seems OK, now do the selling. - StockSpaceI sellPrice; + StockSpace sellPrice; int price; // Get the sell price (does not change within a turn) diff --git a/rails/game/StockMarket.java b/rails/game/StockMarket.java index 6d2bdae..0adf178 100644 --- a/rails/game/StockMarket.java +++ b/rails/game/StockMarket.java @@ -1,7 +1,8 @@ -/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/StockMarket.java,v 1.27 2010/03/10 17:26:45 stefanfrey Exp $ */ package rails.game; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import rails.common.LocalText; import rails.common.parser.ConfigurableComponentI; @@ -9,21 +10,28 @@ import rails.common.parser.ConfigurationException; import rails.common.parser.Tag; import rails.game.state.GameItem; import rails.game.state.BooleanState; -import rails.game.state.PriceTokenMove; -public class StockMarket extends GameItem implements StockMarketI, ConfigurableComponentI { +public class StockMarket extends GameItem implements ConfigurableComponentI { - protected HashMap<String, StockSpaceTypeI> stockSpaceTypes = - new HashMap<String, StockSpaceTypeI>(); - protected HashMap<String, StockSpaceI> stockChartSpaces = - new HashMap<String, StockSpaceI>(); - protected StockSpaceI stockChart[][]; - protected StockSpaceI currentSquare; + /** + * This is the name by which the CompanyManager should be registered with + * the ComponentManager. + */ + public static final String COMPONENT_NAME = "StockMarket"; + + + protected HashMap<String, StockSpaceType> stockSpaceTypes = + new HashMap<String, StockSpaceType>(); + protected HashMap<String, StockSpace> stockChartSpaces = + new HashMap<String, StockSpace>(); + + protected StockSpace stockChart[][]; + protected StockSpace currentSquare; protected int numRows = 0; protected int numCols = 0; - protected ArrayList<StockSpaceI> startSpaces = new ArrayList<StockSpaceI>(); + protected ArrayList<StockSpace> startSpaces = new ArrayList<StockSpace>(); protected int[] startPrices; - protected StockSpaceTypeI defaultType; + protected StockSpaceType defaultType; GameManager gameManager; @@ -55,19 +63,19 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC stockSpaceTypes.put (DEFAULT, defaultType); /* Read and configure the stock market space types */ - List<Tag> typeTags = tag.getChildren(StockSpaceTypeI.ELEMENT_ID); + List<Tag> typeTags = tag.getChildren(StockSpaceType.ELEMENT_ID); if (typeTags != null) { for (Tag typeTag : typeTags) { /* Extract the attributes of the Stock space type */ String name = - typeTag.getAttributeAsString(StockSpaceTypeI.NAME_TAG); + typeTag.getAttributeAsString(StockSpaceType.NAME_TAG); if (name == null) { throw new ConfigurationException( LocalText.getText("UnnamedStockSpaceType")); } String colour = - typeTag.getAttributeAsString(StockSpaceTypeI.COLOUR_TAG); + typeTag.getAttributeAsString(StockSpaceType.COLOUR_TAG); /* Check for duplicates */ if (stockSpaceTypes.get(name) != null) { @@ -76,36 +84,36 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC } /* Create the type */ - StockSpaceTypeI type = new StockSpaceType(name, colour); + StockSpaceType type = new StockSpaceType(name, colour); stockSpaceTypes.put(name, type); // Check the stock space type flags - type.setNoBuyLimit(typeTag.getChild(StockSpaceTypeI.NO_BUY_LIMIT_TAG) != null); - type.setNoCertLimit(typeTag.getChild(StockSpaceTypeI.NO_CERT_LIMIT_TAG) != null); - type.setNoHoldLimit(typeTag.getChild(StockSpaceTypeI.NO_HOLD_LIMIT_TAG) != null); + type.setNoBuyLimit(typeTag.getChild(StockSpaceType.NO_BUY_LIMIT_TAG) != null); + type.setNoCertLimit(typeTag.getChild(StockSpaceType.NO_CERT_LIMIT_TAG) != null); + type.setNoHoldLimit(typeTag.getChild(StockSpaceType.NO_HOLD_LIMIT_TAG) != null); } } /* Read and configure the stock market spaces */ - List<Tag> spaceTags = tag.getChildren(StockSpaceI.ELEMENT_ID); - StockSpaceTypeI type; + List<Tag> spaceTags = tag.getChildren(StockSpace.ELEMENT_ID); + StockSpaceType type; int row, col; for (Tag spaceTag : spaceTags) { type = null; // Extract the attributes of the Stock space - String name = spaceTag.getAttributeAsString(StockSpaceI.NAME_TAG); + String name = spaceTag.getAttributeAsString(StockSpace.NAME_TAG); if (name == null) { throw new ConfigurationException( LocalText.getText("UnnamedStockSpace")); } - String price = spaceTag.getAttributeAsString(StockSpaceI.PRICE_TAG); + String price = spaceTag.getAttributeAsString(StockSpace.PRICE_TAG); if (price == null) { throw new ConfigurationException(LocalText.getText( "StockSpaceHasNoPrice", name)); } String typeName = - spaceTag.getAttributeAsString(StockSpaceI.TYPE_TAG); + spaceTag.getAttributeAsString(StockSpace.TYPE_TAG); if (typeName != null && (type = stockSpaceTypes.get(typeName)) == null) { throw new ConfigurationException(LocalText.getText( @@ -115,11 +123,10 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC if (stockChartSpaces.get(name) != null) { throw new ConfigurationException(LocalText.getText( - "StockSpaceIsConfiguredTwice", name)); + "StockSpacesConfiguredTwice", name)); } - StockSpaceI space = - new StockSpace(this, name, Integer.parseInt(price), type); + StockSpace space = StockSpace.create(this, name, Integer.parseInt(price), type); stockChartSpaces.put(name, space); row = Integer.parseInt(name.substring(1)); @@ -128,14 +135,14 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC if (col > numCols) numCols = col; // Loop through the stock space flags - if (spaceTag.getChild(StockSpaceI.START_SPACE_TAG) != null) { + if (spaceTag.getChild(StockSpace.START_SPACE_TAG) != null) { space.setStart(true); startSpaces.add(space); } - space.setClosesCompany(spaceTag.getChild(StockSpaceI.CLOSES_COMPANY_TAG) != null); - space.setEndsGame(spaceTag.getChild(StockSpaceI.GAME_OVER_TAG) != null); - space.setBelowLedge(spaceTag.getChild(StockSpaceI.BELOW_LEDGE_TAG) != null); - space.setLeftOfLedge(spaceTag.getChild(StockSpaceI.LEFT_OF_LEDGE_TAG) != null); + space.setClosesCompany(spaceTag.getChild(StockSpace.CLOSES_COMPANY_TAG) != null); + space.setEndsGame(spaceTag.getChild(StockSpace.GAME_OVER_TAG) != null); + space.setBelowLedge(spaceTag.getChild(StockSpace.BELOW_LEDGE_TAG) != null); + space.setLeftOfLedge(spaceTag.getChild(StockSpace.LEFT_OF_LEDGE_TAG) != null); } @@ -144,8 +151,8 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC startPrices[i] = (startSpaces.get(i)).getPrice(); } - stockChart = new StockSpaceI[numRows][numCols]; - for (StockSpaceI space : stockChartSpaces.values()) { + stockChart = new StockSpace[numRows][numCols]; + for (StockSpace space : stockChartSpaces.values()) { stockChart[space.getRow()][space.getColumn()] = space; } @@ -172,11 +179,11 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC /** * @return */ - public StockSpaceI[][] getStockChart() { + public StockSpace[][] getStockChart() { return stockChart; } - public StockSpaceI getStockSpace(int row, int col) { + public StockSpace getStockSpace(int row, int col) { if (row >= 0 && row < numRows && col >= 0 && col < numCols) { return stockChart[row][col]; } else { @@ -190,7 +197,7 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC /*--- Actions ---*/ - public void start(PublicCompany company, StockSpaceI price) { + public void start(PublicCompany company, StockSpace price) { prepareMove(company, null, price); } @@ -211,8 +218,8 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC } public void moveUp(PublicCompany company) { - StockSpaceI oldsquare = company.getCurrentSpace(); - StockSpaceI newsquare = oldsquare; + StockSpace oldsquare = company.getCurrentSpace(); + StockSpace newsquare = oldsquare; int row = oldsquare.getRow(); int col = oldsquare.getColumn(); if (row > 0) { @@ -228,8 +235,8 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC } protected void moveDown(PublicCompany company, int numberOfSpaces) { - StockSpaceI oldsquare = company.getCurrentSpace(); - StockSpaceI newsquare = oldsquare; + StockSpace oldsquare = company.getCurrentSpace(); + StockSpace newsquare = oldsquare; int row = oldsquare.getRow(); int col = oldsquare.getColumn(); @@ -261,8 +268,8 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC protected void moveRightOrUp(PublicCompany company) { /* Ignore the amount for now */ - StockSpaceI oldsquare = company.getCurrentSpace(); - StockSpaceI newsquare = oldsquare; + StockSpace oldsquare = company.getCurrentSpace(); + StockSpace newsquare = oldsquare; int row = oldsquare.getRow(); int col = oldsquare.getColumn(); if (col < numCols - 1 && !oldsquare.isLeftOfLedge() @@ -273,8 +280,8 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC } protected void moveLeftOrDown(PublicCompany company) { - StockSpaceI oldsquare = company.getCurrentSpace(); - StockSpaceI newsquare = oldsquare; + StockSpace oldsquare = company.getCurrentSpace(); + StockSpace newsquare = oldsquare; int row = oldsquare.getRow(); int col = oldsquare.getColumn(); if (col > 0 && (newsquare = getStockSpace(row, col - 1)) != null) {} @@ -286,8 +293,8 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC prepareMove(company, oldsquare, newsquare); } - protected void prepareMove(PublicCompany company, StockSpaceI from, - StockSpaceI to) { + protected void prepareMove(PublicCompany company, StockSpace from, + StockSpace to) { // To be written to a log file in the future. if (from != null && from == to) { ReportBuffer.add(LocalText.getText("PRICE_STAYS_LOG", @@ -313,27 +320,31 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC } company.setCurrentSpace(to); - new PriceTokenMove(company, from, to, this); - } - - public void processMove(PublicCompany company, StockSpaceI from, - StockSpaceI to) { - if (from != null) from.removeToken(company); - if (to != null) to.addToken(company); - company.updatePlayersWorth(); - } - - public void processMoveToStackPosition(PublicCompany company, StockSpaceI from, - StockSpaceI to, int toStackPosition) { - if (from != null) from.removeToken(company); - if (to != null) to.addTokenAtStackPosition(company, toStackPosition); - company.updatePlayersWorth(); + + // the following 2 commands replaced: new PriceTokenMove(company, from, to, this); + to.addToken(company); + from.removeToken(company); } + + // TODO: Check what states effect players worth and link those +// public void processMove(PublicCompany company, StockSpace from, +// StockSpace to) { +// if (from != null) from.removeToken(company); +// if (to != null) to.addToken(company); +// company.updatePlayersWorth(); +// } +// +// public void processMoveToStackPosition(PublicCompany company, StockSpace from, +// StockSpace to, int toStackPosition) { +// if (from != null) from.removeToken(company); +// if (to != null) to.addTokenAtStackPosition(company, toStackPosition); +// company.updatePlayersWorth(); +// } /** * @return */ - public List<StockSpaceI> getStartSpaces() { + public List<StockSpace> getStartSpaces() { return startSpaces; } @@ -346,8 +357,8 @@ public class StockMarket extends GameItem implements StockMarketI, ConfigurableC return startPrices; } - public StockSpaceI getStartSpace(int price) { - for (StockSpaceI square : startSpaces) { + public StockSpace getStartSpace(int price) { + for (StockSpace square : startSpaces) { if (square.getPrice() == price) return square; } return null; diff --git a/rails/game/StockMarketI.java b/rails/game/StockMarketI.java deleted file mode 100644 index 2596225..0000000 --- a/rails/game/StockMarketI.java +++ /dev/null @@ -1,51 +0,0 @@ -/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/StockMarketI.java,v 1.10 2010/03/10 17:26:49 stefanfrey Exp $ */ -package rails.game; - -import java.util.List; - -import rails.common.parser.ConfigurableComponentI; - -public interface StockMarketI extends ConfigurableComponentI { - - /** - * This is the name by which the CompanyManager should be registered with - * the ComponentManager. - */ - static final String COMPONENT_NAME = "StockMarket"; - - public StockSpaceI[][] getStockChart(); - - public StockSpaceI getStockSpace(int row, int col); - - public StockSpaceI getStockSpace(String name); - - public void start(PublicCompany company, StockSpaceI price); - - public void payOut(PublicCompany company); - - public void withhold(PublicCompany company); - - public void sell(PublicCompany company, int numberOfShares); - - public void soldOut(PublicCompany company); - - public void moveUp(PublicCompany company); - - public void close (PublicCompany company); - - public int getNumberOfColumns(); - - public int getNumberOfRows(); - - public List<StockSpaceI> getStartSpaces(); - - public int[] getStartPrices(); - - public StockSpaceI getStartSpace(int price); - - public void processMove(PublicCompany company, StockSpaceI from, - StockSpaceI to); - - public void processMoveToStackPosition(PublicCompany company, StockSpaceI from, - StockSpaceI to, int toStackPosition); -} diff --git a/rails/game/StockRound.java b/rails/game/StockRound.java index 647b101..3940ea9 100644 --- a/rails/game/StockRound.java +++ b/rails/game/StockRound.java @@ -39,8 +39,8 @@ public class StockRound extends Round { protected IntegerState numPasses = IntegerState.create(this, "StockRoundPasses"); - protected Map<PublicCompany, StockSpaceI> sellPrices = - new HashMap<PublicCompany, StockSpaceI>(); + protected Map<PublicCompany, StockSpace> sellPrices = + new HashMap<PublicCompany, StockSpace>(); /** Records lifted share selling obligations in the current round<p> * Example: >60% ownership allowed after a merger in 18EU. @@ -166,7 +166,7 @@ public class StockRound extends Round { List<PublicCertificate> certs; PublicCertificate cert; PublicCompany comp; - StockSpaceI stockSpace; + StockSpace stockSpace; Portfolio from; int price; int number; @@ -544,7 +544,7 @@ public class StockRound extends Round { int shares = action.getNumberBought(); String errMsg = null; - StockSpaceI startSpace = null; + StockSpace startSpace = null; int numberOfCertsToBuy = 0; PublicCertificate cert = null; String companyName = company.getId(); @@ -748,7 +748,7 @@ public class StockRound extends Round { break; } - StockSpaceI currentSpace; + StockSpace currentSpace; if (from == ipo && company.hasParPrice()) { currentSpace = company.getStartSpace(); } else { @@ -873,7 +873,7 @@ public class StockRound extends Round { } /** Allow different price setting in subclasses (i.e. 1835 Nationalisation) */ - protected int getBuyPrice (BuyCertificate action, StockSpaceI currentSpace) { + protected int getBuyPrice (BuyCertificate action, StockSpace currentSpace) { return currentSpace.getPrice(); } @@ -1163,7 +1163,7 @@ public class StockRound extends Round { stockMarket.sell(company, numberSold); - StockSpaceI newSpace = company.getCurrentSpace(); + StockSpace newSpace = company.getCurrentSpace(); if (newSpace.closesCompany() && company.canClose()) { company.setClosed(); @@ -1322,9 +1322,9 @@ public class StockRound extends Round { /* Check if any companies are sold out. */ for (PublicCompany company : gameManager.getCompaniesInRunningOrder()) { if (company.hasStockPrice() && company.isSoldOut()) { - StockSpaceI oldSpace = company.getCurrentSpace(); + StockSpace oldSpace = company.getCurrentSpace(); stockMarket.soldOut(company); - StockSpaceI newSpace = company.getCurrentSpace(); + StockSpace newSpace = company.getCurrentSpace(); if (newSpace != oldSpace) { ReportBuffer.add(LocalText.getText("SoldOut", company.getId(), diff --git a/rails/game/StockSpace.java b/rails/game/StockSpace.java index 5583a02..03afbec 100644 --- a/rails/game/StockSpace.java +++ b/rails/game/StockSpace.java @@ -1,20 +1,54 @@ package rails.game; import java.awt.Color; -import java.util.ArrayList; -import java.util.List; import org.apache.log4j.Logger; +import com.google.common.collect.ImmutableList; + import rails.game.model.Model; -import rails.game.state.GameItem; +import rails.game.state.ArrayListState; +import rails.game.state.Item; /** * Objects of this class represent a square on the StockMarket. */ -public class StockSpace extends Model implements StockSpaceI { +public class StockSpace extends Model { /*--- Class attributes ---*/ + /*--- Constants ---*/ + /** The name of the XML tag used to configure a stock space. */ + public static final String ELEMENT_ID = "StockSpace"; + + /** + * The name of the XML attribute for the stock price's name (like "A1" - + * naming is like spreadsheet cells. + */ + public static final String NAME_TAG = "name"; + + /** The name of the XML attribute for the stock price. */ + public static final String PRICE_TAG = "price"; + + /** The name of the XML attribute for the stock price type (optional). */ + public static final String TYPE_TAG = "type"; + + /** + * The name of the XML tag for the "startSpace" property. (indicating an + * allowed PAR price) + */ + public static final String START_SPACE_TAG = "StartSpace"; + + /** The name of the XML tag for the "below ledge" property. */ + public static final String BELOW_LEDGE_TAG = "BelowLedge"; + + /** The name of the XML tag for the "left of ledge" property. */ + public static final String LEFT_OF_LEDGE_TAG = "LeftOfLedge"; + + /** The name of the XML tag for the "closes company" property. */ + public static final String CLOSES_COMPANY_TAG = "ClosesCompany"; + + /** The name of the XML tag for the "gamn over" property. */ + public static final String GAME_OVER_TAG = "GameOver"; /*--- Instance attributes ---*/ protected String name; @@ -27,27 +61,46 @@ public class StockSpace extends Model implements StockSpaceI { protected boolean closesCompany = false;// For 1856 and other games protected boolean endsGame = false; // For 1841 and other games protected boolean start = false; // Company may start here - protected StockSpaceTypeI type = null; - protected ArrayList<PublicCompany> tokens = - new ArrayList<PublicCompany>(); - protected ArrayList<PublicCompany> fixedStartPrices = - new ArrayList<PublicCompany>(); + protected StockSpaceType type = null; + + + /*--- State fields */ + protected final ArrayListState<PublicCompany> tokens = ArrayListState.create("tokens"); + protected final ArrayListState<PublicCompany> fixedStartPrices = ArrayListState.create("fixedStartPrices"); protected static Logger log = Logger.getLogger(StockSpace.class.getPackage().getName()); /*--- Contructors ---*/ - public StockSpace(GameItem owner, String name, int price, StockSpaceTypeI type) { - super(owner, name); - this.name = name; + private StockSpace(String id, int price, StockSpaceType type) { + super(id); + this.name = id; this.price = price; this.type = type; - this.row = Integer.parseInt(name.substring(1)) - 1; - this.column = (name.toUpperCase().charAt(0) - '@') - 1; + this.row = Integer.parseInt(id.substring(1)) - 1; + this.column = (id.toUpperCase().charAt(0) - '@') - 1; } - public StockSpace(GameItem owner, String name, int price) { - this(owner, name, price, null); + /** + * Factory method for initialized StockSpace + */ + public static StockSpace create(Item parent, String id, int price, StockSpaceType type) { + return new StockSpace(id, price, type).init(parent); + } + + /** + * Factory method for initialized StockSpace with default StockSpaceType + */ + public static StockSpace create (Item parent, String id, int price) { + return create(parent, id, price, null); + } + + @Override + public StockSpace init(Item parent){ + super.init(parent); + tokens.init(this); + fixedStartPrices.init(this); + return this; } @@ -64,16 +117,12 @@ public class StockSpace extends Model implements StockSpaceI { public boolean addToken(PublicCompany company) { log.debug(company.getId() + " price token added to " + name); tokens.add(company); - // TODO: is this still required? - update(); return true; } public boolean addTokenAtStackPosition(PublicCompany company, int stackPosition) { log.debug(company.getId() + " price token added to " + name + " at stack position "+stackPosition); tokens.add(stackPosition, company); - // TODO: is this still required? - update(); return true; } @@ -85,22 +134,11 @@ public class StockSpace extends Model implements StockSpaceI { */ public boolean removeToken(PublicCompany company) { log.debug(company.getId() + " price token removed from " + name); - int index = tokens.indexOf(company); - if (index >= 0) { - tokens.remove(index); - // TODO: is this still required? - update(); - return true; - } else { - return false; - } + return tokens.remove(company); } - /** - * @return - */ - public List<PublicCompany> getTokens() { - return tokens; + public ImmutableList<PublicCompany> getTokens() { + return tokens.view(); } /** @@ -118,8 +156,8 @@ public class StockSpace extends Model implements StockSpaceI { fixedStartPrices.add(company); } - public List<PublicCompany> getFixedStartPrices() { - return fixedStartPrices; + public ImmutableList<PublicCompany> getFixedStartPrices() { + return fixedStartPrices.view(); } /*--- Getters ---*/ @@ -179,7 +217,7 @@ public class StockSpace extends Model implements StockSpaceI { /** * @return */ - public StockSpaceTypeI getType() { + public StockSpaceType getType() { return type; } diff --git a/rails/game/StockSpaceI.java b/rails/game/StockSpaceI.java deleted file mode 100644 index c6dfbdd..0000000 --- a/rails/game/StockSpaceI.java +++ /dev/null @@ -1,160 +0,0 @@ -/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/StockSpaceI.java,v 1.6 2010/03/10 17:26:49 stefanfrey Exp $ */ -package rails.game; - -import java.awt.Color; -import java.util.*; - -import rails.game.model.Model; - -public interface StockSpaceI extends Model<String> // extends HolderModel<Token>I -{ - - /*--- Constants ---*/ - /** The name of the XML tag used to configure a stock space. */ - public static final String ELEMENT_ID = "StockSpace"; - - /** - * The name of the XML attribute for the stock price's name (like "A1" - - * naming is like spreadsheet cells. - */ - public static final String NAME_TAG = "name"; - - /** The name of the XML attribute for the stock price. */ - public static final String PRICE_TAG = "price"; - - /** The name of the XML attribute for the stock price type (optional). */ - public static final String TYPE_TAG = "type"; - - /** - * The name of the XML tag for the "startSpace" property. (indicating an - * allowed PAR price) - */ - public static final String START_SPACE_TAG = "StartSpace"; - - /** The name of the XML tag for the "below ledge" property. */ - public static final String BELOW_LEDGE_TAG = "BelowLedge"; - - /** The name of the XML tag for the "left of ledge" property. */ - public static final String LEFT_OF_LEDGE_TAG = "LeftOfLedge"; - - /** The name of the XML tag for the "closes company" property. */ - public static final String CLOSES_COMPANY_TAG = "ClosesCompany"; - - /** The name of the XML tag for the "gamn over" property. */ - public static final String GAME_OVER_TAG = "GameOver"; - - // No constructors (yet) for the booleans, which are rarely needed. Use the - // setters. - public abstract boolean isBelowLedge(); - - /** - * @return TRUE if the square closes companies landing on it. - */ - public abstract boolean closesCompany(); - - /** - * @return The square's colour. - */ - public abstract Color getColour(); - - /** - * @return TRUE if the rails.game ends if a company lands on this square. - */ - public abstract boolean endsGame(); - - /** - * @return The stock price associated with the square. - */ - public abstract int getPrice(); - - /** - * @return - */ - public abstract int getColumn(); - - /** - * @return - */ - public abstract String getName(); - - /** - * @return - */ - public abstract int getRow(); - - /** - * @return - */ - public abstract StockSpaceTypeI getType(); - - /** - * @param b - */ - public abstract boolean isStart(); - - /*--- Setters ---*/ - public abstract void setBelowLedge(boolean b); - - /** - * @param b See isClosesCompany. - */ - public abstract void setClosesCompany(boolean b); - - /** - * @param b See isEndsGame. - */ - public abstract void setEndsGame(boolean b); - - /** - * @return - */ - public abstract void setStart(boolean b); - - /** - * Find the stack position of a company token - * - * @return Stock position: 0 = top, increasing towards the bottom. -1 if not - * found. - */ - public int getStackPosition(PublicCompany company); - - public void addFixedStartPrice(PublicCompany company); - - public List<PublicCompany> getFixedStartPrices(); - - /** - * @return - */ - public abstract boolean isLeftOfLedge(); - - /** - * @param b - */ - public abstract void setLeftOfLedge(boolean b); - - /** - * @return - */ - public boolean isNoBuyLimit(); - - /** - * @return - */ - public boolean isNoCertLimit(); - - /** - * @return - */ - public boolean isNoHoldLimit(); - - public boolean addToken(PublicCompany company); - - public boolean addTokenAtStackPosition(PublicCompany company, int stackPosition); - - public boolean removeToken(PublicCompany company); - - public boolean hasTokens(); - - public List<PublicCompany> getTokens(); - -} diff --git a/rails/game/StockSpaceType.java b/rails/game/StockSpaceType.java index 6e5295f..a0accd9 100644 --- a/rails/game/StockSpaceType.java +++ b/rails/game/StockSpaceType.java @@ -1,4 +1,3 @@ -/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/StockSpaceType.java,v 1.4 2009/12/13 16:39:49 evos Exp $ */ package rails.game; import java.awt.Color; @@ -11,9 +10,43 @@ import rails.util.Util; * special properties,usually represented by a non-white square colour. The * default type is "white", which has no special properties. */ -public class StockSpaceType implements StockSpaceTypeI { +public class StockSpaceType { /*--- Class attributes ---*/ + /*--- Constants ---*/ + /** The name of the XML tag used to configure a stock space. */ + public static final String ELEMENT_ID = "StockSpaceType"; + + /** + * The name of the XML attribute for the stock price type's name (any + * string, usually the space colour). + */ + public static final String NAME_TAG = "name"; + + /** + * The name of the XML attribute for the stock price's colour. (optional; + * only provided as a possible help to the UI, which is free to redefine the + * colour as it seems fit). + */ + public static final String COLOUR_TAG = "colour"; + + /** + * The name of the XML tag for the "NoCertLimit" property. (1830: yellow + * stock market area) + */ + public static final String NO_CERT_LIMIT_TAG = "NoCertLimit"; + + /** + * The name of the XML tag for the "NoHoldLimit" property. (1830: orange + * area) + */ + public static final String NO_HOLD_LIMIT_TAG = "NoHoldLimit"; + + /** + * The name of the XML tag for the "NoBuyLimit" property. (1830: brown area) + */ + public static final String NO_BUY_LIMIT_TAG = "NoBuyLimit"; + /*--- Instance attributes ---*/ protected String name; diff --git a/rails/game/StockSpaceTypeI.java b/rails/game/StockSpaceTypeI.java deleted file mode 100644 index ca896f7..0000000 --- a/rails/game/StockSpaceTypeI.java +++ /dev/null @@ -1,86 +0,0 @@ -/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/StockSpaceTypeI.java,v 1.4 2009/12/13 16:39:48 evos Exp $ */ -package rails.game; - -import java.awt.Color; - -/** - * The interface for StockSpaceType. - */ -public interface StockSpaceTypeI { - - /*--- Constants ---*/ - /** The name of the XML tag used to configure a stock space. */ - public static final String ELEMENT_ID = "StockSpaceType"; - - /** - * The name of the XML attribute for the stock price type's name (any - * string, usually the space colour). - */ - public static final String NAME_TAG = "name"; - - /** - * The name of the XML attribute for the stock price's colour. (optional; - * only provided as a possible help to the UI, which is free to redefine the - * colour as it seems fit). - */ - public static final String COLOUR_TAG = "colour"; - - /** - * The name of the XML tag for the "NoCertLimit" property. (1830: yellow - * stock market area) - */ - public static final String NO_CERT_LIMIT_TAG = "NoCertLimit"; - - /** - * The name of the XML tag for the "NoHoldLimit" property. (1830: orange - * area) - */ - public static final String NO_HOLD_LIMIT_TAG = "NoHoldLimit"; - - /** - * The name of the XML tag for the "NoBuyLimit" property. (1830: brown area) - */ - public static final String NO_BUY_LIMIT_TAG = "NoBuyLimit"; - - /** - * @return Color - */ - public abstract Color getColour(); - - /** - * @return Name - */ - public abstract String getName(); - - /** - * @return if space triggers No Purchase Limit for stock - */ - public boolean isNoBuyLimit(); - - /** - * @return if space triggers Stock not counting toward certificate ownership - * limit - */ - public boolean isNoCertLimit(); - - /** - * @return if space triggers Stock not counting toward certificate limit - */ - public boolean isNoHoldLimit(); - - /** - * @param b - */ - public void setNoBuyLimit(boolean b); - - /** - * @param b - */ - public void setNoCertLimit(boolean b); - - /** - * @param b - */ - public void setNoHoldLimit(boolean b); - -} diff --git a/rails/game/TreasuryShareRound.java b/rails/game/TreasuryShareRound.java index b74ac95..73a5f13 100644 --- a/rails/game/TreasuryShareRound.java +++ b/rails/game/TreasuryShareRound.java @@ -474,7 +474,7 @@ public class TreasuryShareRound extends StockRound { } // All seems OK, now do the selling. - StockSpaceI sellPrice; + StockSpace sellPrice; int price; // Get the sell price (does not change within a turn) diff --git a/rails/game/model/PriceModel.java b/rails/game/model/PriceModel.java index 3af0a20..ea74079 100644 --- a/rails/game/model/PriceModel.java +++ b/rails/game/model/PriceModel.java @@ -2,18 +2,19 @@ package rails.game.model; import rails.game.Bank; import rails.game.PublicCompany; -import rails.game.StockSpaceI; +import rails.game.StockSpace; +import rails.game.state.GenericState; import rails.game.state.Item; -import rails.game.state.PriceMove; - -// TODO: Requires a complete rewrite public class PriceModel extends Model { - private StockSpaceI stockPrice = null; + // fields private PublicCompany company = null; - private String name = null; + // states + private final GenericState<StockSpace> stockPrice = GenericState.create("stockPrice"); + + private PriceModel(String id) { super(id); } @@ -36,17 +37,16 @@ public class PriceModel extends Model { } else { throw new IllegalArgumentException("PriceModel init() only works for PublicCompanies"); } + stockPrice.init(this); return this; } - - // TODO: This has to be changed - public void setPrice(StockSpaceI price) { - new PriceMove(this, stockPrice, price); + public void setPrice(StockSpace price) { + stockPrice.set(price); } - public StockSpaceI getPrice() { - return stockPrice; + public StockSpace getPrice() { + return stockPrice.get(); } public PublicCompany getCompany() { @@ -54,45 +54,23 @@ public class PriceModel extends Model { } // FIXME: This is a reference to the usage of ViewUpdate - public Object getUpdate() { - if (stockPrice != null) { - return new ViewUpdate(getText()) - .addObject(ViewUpdate.BGCOLOUR, stockPrice.getColour()); - } else { - return getText(); - } - } + // TODO: The color reference has to be taken care of, remove view update +// public Object getUpdate() { +// if (stockPrice != null) { +// return new ViewUpdate(getText()) +// .addObject(ViewUpdate.BGCOLOUR, stockPrice.getColour()); +// } else { +// return getText(); +// } +// } @Override public String toString() { if (stockPrice != null) { - return Bank.format(stockPrice.getPrice()) + " (" - + stockPrice.getName() + ")"; + return Bank.format(stockPrice.get().getPrice()) + " (" + + stockPrice.get().getName() + ")"; } return ""; } - // StateI required methods - public Object get() { - return stockPrice; - } - - public void setState(Object object) { - if (object == null) { - stockPrice = null; - update(); - } else if (object instanceof StockSpaceI) { - stockPrice = (StockSpaceI) object; - update(); - } else { - new Exception("Incompatible object type " - + object.getClass().getName() - + "passed to PriceModel " + name).printStackTrace(); - } - } - - public String getName() { - return name; - } - } diff --git a/rails/game/model/ViewUpdate.java b/rails/game/model/ViewUpdate.java index a6ec674..5a5e068 100644 --- a/rails/game/model/ViewUpdate.java +++ b/rails/game/model/ViewUpdate.java @@ -9,6 +9,8 @@ import java.util.*; * <p> The current version has text, background colour and foreground colour. * Receiving view objects must be prepared to handle extensions. * @author VosE + * + * TODO: Replace all previous use cases for this class * */ @Deprecated diff --git a/rails/game/specific/_1825/PublicCompany_1825.java b/rails/game/specific/_1825/PublicCompany_1825.java index a0187c9..260e8cb 100644 --- a/rails/game/specific/_1825/PublicCompany_1825.java +++ b/rails/game/specific/_1825/PublicCompany_1825.java @@ -1,14 +1,14 @@ package rails.game.specific._1825; import rails.game.PublicCompany; -import rails.game.StockSpaceI; +import rails.game.StockSpace; import rails.game.state.IntegerState; public class PublicCompany_1825 extends PublicCompany { protected IntegerState formationOrderIndex; - public void start(StockSpaceI startSpace) { + public void start(StockSpace startSpace) { super.start(startSpace); //PD: used to track flotation order formationOrderIndex = IntegerState.create(this, name+"_formationOrderIndex"); diff --git a/rails/game/specific/_1835/StockRound_1835.java b/rails/game/specific/_1835/StockRound_1835.java index fd117f5..3383520 100644 --- a/rails/game/specific/_1835/StockRound_1835.java +++ b/rails/game/specific/_1835/StockRound_1835.java @@ -47,7 +47,7 @@ public class StockRound_1835 extends StockRound { for (PublicCertificate cert : company.getCertificates()) { owner = cert.getHolder().getOwner(); /* Would the player exceed the total certificate limit? */ - StockSpaceI stockSpace = company.getCurrentSpace(); + StockSpace stockSpace = company.getCurrentSpace(); if ((stockSpace == null || !stockSpace.isNoCertLimit()) && !mayPlayerBuyCertificate( currentPlayer, company, cert.getCertificateCount())) continue; // only nationalize other players @@ -75,7 +75,7 @@ public class StockRound_1835 extends StockRound { } @Override - protected int getBuyPrice (BuyCertificate action, StockSpaceI currentSpace) { + protected int getBuyPrice (BuyCertificate action, StockSpace currentSpace) { int price = currentSpace.getPrice(); if (action.getFromPortfolio().getOwner() instanceof Player) { price *= 1.5; diff --git a/rails/game/specific/_1856/CGRFormationRound.java b/rails/game/specific/_1856/CGRFormationRound.java index d79e51d..173ddf9 100644 --- a/rails/game/specific/_1856/CGRFormationRound.java +++ b/rails/game/specific/_1856/CGRFormationRound.java @@ -484,7 +484,7 @@ public class CGRFormationRound extends SwitchableUIRound { } else { int prevColPrice = 100; int colPrice; - StockSpaceI startSpace; + StockSpace startSpace; for (int col=6; col <= stockMarket.getNumberOfColumns(); col++) { colPrice = stockMarket.getStockSpace(1, col).getPrice(); if (cgrPrice > colPrice) continue; diff --git a/rails/game/specific/_1856/PublicCompany_1856.java b/rails/game/specific/_1856/PublicCompany_1856.java index 92220bc..70044b3 100644 --- a/rails/game/specific/_1856/PublicCompany_1856.java +++ b/rails/game/specific/_1856/PublicCompany_1856.java @@ -13,7 +13,7 @@ public class PublicCompany_1856 extends PublicCompany { private boolean hadPermanentTrain = false; @Override - public void start(StockSpaceI startSpace) { + public void start(StockSpace startSpace) { super.start(startSpace); diff --git a/rails/game/specific/_18EU/StockRound_18EU.java b/rails/game/specific/_18EU/StockRound_18EU.java index 09cd691..47debdc 100644 --- a/rails/game/specific/_18EU/StockRound_18EU.java +++ b/rails/game/specific/_18EU/StockRound_18EU.java @@ -73,7 +73,7 @@ public class StockRound_18EU extends StockRound { List<PublicCertificate> certs; PublicCertificate cert; PublicCompany comp; - StockSpaceI stockSpace; + StockSpace stockSpace; Portfolio from; int price; @@ -282,7 +282,7 @@ public class StockRound_18EU extends StockRound { int shares = action.getNumberBought(); String errMsg = null; - StockSpaceI startSpace = null; + StockSpace startSpace = null; int numberOfCertsToBuy = 0; PublicCertificate cert = null; String companyName = company.getId(); diff --git a/rails/game/state/PriceMove.java b/rails/game/state/PriceMove.java deleted file mode 100644 index dfc26ee..0000000 --- a/rails/game/state/PriceMove.java +++ /dev/null @@ -1,51 +0,0 @@ -/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/move/PriceMove.java,v 1.5 2008/06/04 19:00:33 evos Exp $ - * - * Created on 18-Jul-2006 - * Change Log: - */ -package rails.game.state; - -import rails.game.StockSpaceI; -import rails.game.model.PriceModel; - -/** - * @author Erik Vos - */ -@Deprecated -//FIXME: Rewrite this mechanism -public class PriceMove { - - protected StockSpaceI from, to; - protected PriceModel price; - - public PriceMove(PriceModel price, StockSpaceI from, StockSpaceI to) { - this.from = from; - this.to = to; - this.price = price; -// MoveSet.add(this); - } - - public boolean execute() { - price.setState(to); - return true; - } - - /* - * (non-Javadoc) - * - * @see rails.rails.game.action.Move#undo() - */ - public boolean undo() { - price.setState(from); - return true; - } - - public Object getObject() { - return price; - } - - public String toString() { - return "PriceMove: " + price.getName() + " from " + from + " to " + to; - } - -} diff --git a/rails/game/state/PriceTokenMove.java b/rails/game/state/PriceTokenMove.java deleted file mode 100644 index 21b0f9c..0000000 --- a/rails/game/state/PriceTokenMove.java +++ /dev/null @@ -1,52 +0,0 @@ -/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/move/PriceTokenMove.java,v 1.7 2010/03/10 17:26:49 stefanfrey Exp $ - * - * Created on 22-Jul-2006 - * Change Log: - */ -package rails.game.state; - -import rails.game.*; - -/** - * @author Erik Vos - */ -@Deprecated -//FIXME: Rewrite this mechanism -public class PriceTokenMove { - - private PublicCompany company; - private StockSpaceI from, to; - private int fromStackPosition; - private StockMarketI stockMarket = null; - - public PriceTokenMove(PublicCompany company, StockSpaceI from, - StockSpaceI to, StockMarketI stockMarket) { - this.company = company; - this.from = from; - this.to = to; - if (from != null) - fromStackPosition = from.getStackPosition(company); - else - fromStackPosition = 0; - this.stockMarket = stockMarket; - -// MoveSet.add(this); - } - - public boolean execute() { - stockMarket.processMove(company, from, to); - return true; - } - - public boolean undo() { - stockMarket.processMoveToStackPosition(company, to, from, fromStackPosition); - return true; - } - - @Override - public String toString() { - return "PriceTokenMove: " + company.getId() + " from " + from + " (at stack " - + fromStackPosition + ") to " + to; - } - -} diff --git a/rails/ui/swing/StartRoundWindow.java b/rails/ui/swing/StartRoundWindow.java index 6389f79..888a269 100644 --- a/rails/ui/swing/StartRoundWindow.java +++ b/rails/ui/swing/StartRoundWindow.java @@ -604,15 +604,15 @@ public class StartRoundWindow extends JFrame implements ActionListener, if (activeItem.hasSharePriceToSet()) { String compName = activeItem.getCompanyToSetPriceFor(); - StockMarketI stockMarket = gameUIManager.getGameManager().getStockMarket(); + StockMarket stockMarket = gameUIManager.getGameManager().getStockMarket(); // Get a sorted prices List // TODO: should be included in BuyStartItem - List<StockSpaceI> startSpaces = stockMarket.getStartSpaces(); - Map<Integer, StockSpaceI> spacePerPrice = - new HashMap<Integer, StockSpaceI>(); + List<StockSpace> startSpaces = stockMarket.getStartSpaces(); + Map<Integer, StockSpace> spacePerPrice = + new HashMap<Integer, StockSpace>(); int[] prices = new int[startSpaces.size()]; - StockSpaceI[] options = new StockSpaceI[startSpaces.size()]; + StockSpace[] options = new StockSpace[startSpaces.size()]; for (int i = 0; i < startSpaces.size(); i++) { prices[i] = startSpaces.get(i).getPrice(); spacePerPrice.put(prices[i], startSpaces.get(i)); diff --git a/rails/ui/swing/StockChart.java b/rails/ui/swing/StockChart.java index 379fa03..a88dab1 100644 --- a/rails/ui/swing/StockChart.java +++ b/rails/ui/swing/StockChart.java @@ -6,7 +6,7 @@ import java.awt.event.*; import javax.swing.*; -import rails.game.StockSpaceI; +import rails.game.StockSpace; import rails.ui.swing.elements.GUIStockSpace; /** @@ -20,7 +20,7 @@ public class StockChart extends JFrame implements KeyListener { private GridLayout stockGrid; private GridBagConstraints gc; - private StockSpaceI[][] market; + private StockSpace[][] market; private GameUIManager gameUIManager; public StockChart(GameUIManager gameUIManager) { diff --git a/rails/ui/swing/elements/GUIStockSpace.java b/rails/ui/swing/elements/GUIStockSpace.java index f880cb5..0608ec7 100644 --- a/rails/ui/swing/elements/GUIStockSpace.java +++ b/rails/ui/swing/elements/GUIStockSpace.java @@ -14,7 +14,7 @@ import javax.swing.SwingConstants; import org.apache.log4j.Logger; import rails.game.PublicCompany; -import rails.game.StockSpaceI; +import rails.game.StockSpace; import rails.game.model.Model; import rails.game.state.Observable; import rails.game.state.Observer; @@ -26,7 +26,7 @@ import rails.util.Util; public class GUIStockSpace extends JLayeredPane implements Observer { private static final long serialVersionUID = 1L; - StockSpaceI model; + StockSpace model; JLabel priceLabel; int depth = 0; @@ -43,7 +43,7 @@ public class GUIStockSpace extends JLayeredPane implements Observer { protected static Logger log = Logger.getLogger(GUIStockSpace.class.getPackage().getName()); - public GUIStockSpace(int x, int y, StockSpaceI model) { + public GUIStockSpace(int x, int y, StockSpace model) { this.model = model; diff --git a/test/GameTestServlet.java b/test/GameTestServlet.java index 29dd5a9..3c3deaf 100644 --- a/test/GameTestServlet.java +++ b/test/GameTestServlet.java @@ -33,7 +33,7 @@ * * private static final String servletName = "test.GameTestServlet"; * - * private StockMarketI stockMarket = null; + * private StockMarket stockMarket = null; * * private Game game = null; * @@ -91,7 +91,7 @@ * protected void doWork(HttpServletRequest request, HttpServletResponse * response) throws ServletException, IOException { * - * int row, col; StockSpaceI square; Company comp; PublicCompany company; + * int row, col; StockSpace square; Company comp; PublicCompany company; * String companyName; PublicCertificate cert; int companyNumber; Iterator * iterator, iterator2; int i; List startSpaces; int price; * @@ -333,7 +333,7 @@ * out.append("<input type=hidden name=Company value=\"") * .append(currCo.getName()).append("\">\n"); out.append("<select * name=StartPrice>\n"); Iterator it = Game.getStockMarket()... [truncated message content] |
From: Frederick W. <fre...@us...> - 2012-01-31 13:56:50
|
LocalisedText.properties | 2 ++ data/Properties.xml | 1 + rails/game/GameManager.java | 4 ++++ rails/game/GameManagerI.java | 2 ++ rails/sound/SoundConfig.java | 1 + rails/sound/SoundEventInterpreter.java | 29 +++++++++++++++++++++++++++-- 6 files changed, 37 insertions(+), 2 deletions(-) New commits: commit 98248e796b9dfdcf8565f6395e46207051ccc8ca Author: Frederick Weld <fre...@gm...> Date: Tue Jan 31 14:52:02 2012 +0100 Added new sfx option (change of current player - player-dependent sfx) Users are able to define in the config window a sound on a per player basis and a default sound (for players that do not have any associated sounds). diff --git a/LocalisedText.properties b/LocalisedText.properties index 956079e..b8ff06d 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -177,6 +177,7 @@ Config.infoText.sound.backgroundMusic=The only music file type supported is mp3. Config.infoText.sound.backgroundMusic.stockRound=<html>Enter assignment of music files 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 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.infoText.sound.sfx=The only sound effects file type supported is mp3. +Config.infoText.sound.sfx.gen.newCurrentPlayer=<html>Enter assignment of sound effect files to player names.<br>The assigned sound is played if the player becomes the active one - meaning, the user interface is responsive for this player's commands.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax playerName=complete file path<li>Default sound effect is defined by omitting "playerName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\ChangeActivePlayer.mp3</code><li>Set player-dependent sound effect and a default (for all other players): <br><code>Tom=c:\ChangeActivePlayer_Tom.mp3,Sarah=c:\ChangeActivePlayer_Sarah.mp3,c:\ChangeActivePlayer_default.mp3</code></ul> </html> Config.infoText.sound.sfx.or.buyTrain=<html>Enter assignment of sound effect files to train types.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax trainName=complete file path<li>Default sound effect is defined by omitting "trainName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\BuyTrain-default.mp3</code><li>Set train-dependent sound effect and a default (for trains above 6): <br><code>2=c:\BuyTrain-2.mp3,3=c:\BuyTrain-3.mp3,4=c:\BuyTrain-4.mp3,5=c:\BuyTrain-5.mp3,6=c:\BuyTrain-6.mp3,c:\BuyTrain-D.mp3</code></ul> </html> Config.infoText.sound.sfx.or.setRevenue=<html><ul><li>Only the latter portion of this file is played.<ul><li>For an average revenue, the last third is played.</ul><li>The higher the company's revenue the longer this file is played.<ul><li>But the file is at most played once as a whole.</li></ul></html> Config.infoText.sound.sfx.sr.newPresident=This also includes becoming the president when buying the president share. @@ -213,6 +214,7 @@ Config.label.sound.backgroundMusic.startRound=Start Round Config.label.sound.backgroundMusic.stockRound=Stock Round (several files) Config.label.sound.backgroundMusic.operatingRound=Operating Round (several files) Config.label.sound.sfx=Sound Effects +Config.label.sound.sfx.gen.newCurrentPlayer=Change of active player Config.label.sound.sfx.gen.pass=Pass Config.label.sound.sfx.gen.select=Select (hexes, click fields) Config.label.sound.sfx.str.bidStartItem=Bid on Start Item diff --git a/data/Properties.xml b/data/Properties.xml index 43e64c2..a5b1e51 100644 --- a/data/Properties.xml +++ b/data/Properties.xml @@ -75,6 +75,7 @@ <Property name="sound.sfx" type="LIST" values="disabled,enabled" /> <Property name="sound.sfx.gen.pass" type="FILE" /> <Property name="sound.sfx.gen.select" type="FILE" /> + <Property name="sound.sfx.gen.newCurrentPlayer" type="STRING" /> <Property name="sound.sfx.str.bidStartItem" type="FILE" /> <Property name="sound.sfx.str.buyStartItem" type="FILE" /> <Property name="sound.sfx.sr.openingBell" type="FILE" /> diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index 2cb1dc0..4e86877 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -26,6 +26,7 @@ public class SoundConfig { public static final String KEY_SFX_Enabled = "sound.sfx"; public static final String KEY_SFX_GEN_Pass = "sound.sfx.gen.pass"; public static final String KEY_SFX_GEN_Select = "sound.sfx.gen.select"; + public static final String KEY_SFX_GEN_NewCurrentPlayer = "sound.sfx.gen.newCurrentPlayer"; public static final String KEY_SFX_STR_BidStartItem = "sound.sfx.str.bidStartItem"; public static final String KEY_SFX_STR_BuyStartItem = "sound.sfx.str.buyStartItem"; public static final String KEY_SFX_SR_OpeningBell = "sound.sfx.sr.openingBell"; diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java index 28dfe13..ac6e640 100644 --- a/rails/sound/SoundEventInterpreter.java +++ b/rails/sound/SoundEventInterpreter.java @@ -11,15 +11,34 @@ import rails.ui.swing.ORUIManager; /** * Converts processed actions and model updates to triggers for playing sounds. * - * Model observers get their own inner classes since their constructors are parameterized + * Some model observers get their own inner classes since their constructors are parameterized * (needed to initialize member variables among others - especially important if game is - * loaded). + * loaded since game status will not be initial upon initialization of the sound framework). * * @author Frederick Weld * */ public class SoundEventInterpreter { + private class CurrentPlayerModelObserver implements Observer { + private Player formerCurrentPlayer = null; + private GameManagerI gm; + public CurrentPlayerModelObserver(GameManagerI gm) { + this.gm = gm; + if (gm != null) formerCurrentPlayer = gm.getCurrentPlayer(); + } + public void update(Observable o, Object arg) { + if (formerCurrentPlayer != gm.getCurrentPlayer()) { + formerCurrentPlayer = gm.getCurrentPlayer(); + if (SoundConfig.isSFXEnabled()) { + player.playSFXByConfigKey ( + SoundConfig.KEY_SFX_GEN_NewCurrentPlayer, + gm.getCurrentPlayer().getName()); + } + } + } + } + private class PresidentModelObserver implements Observer { private PublicCompanyI pc; private Player formerPresident = null; @@ -149,6 +168,12 @@ public class SoundEventInterpreter { } } public void notifyOfGameInit(GameManagerI gameManager) { + //subscribe to current player changes + if (gameManager.getCurrentPlayerModel() != null) { + gameManager.getCurrentPlayerModel().addObserver( + new CurrentPlayerModelObserver(gameManager)); + } + //subscribe to round changes if (gameManager.getCurrentRoundModel() != null) { gameManager.getCurrentRoundModel().addObserver( commit cba0274cf22b8feab79e0ab071fd037432e48835 Author: Frederick Weld <fre...@gm...> Date: Tue Jan 31 14:50:23 2012 +0100 Exposed CurrentPlayerModel in GameManager(I) - needed for SFX Model was already part of GameManager implementation - this is just about exposing it in the interface. diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java index 791dd01..c4c2289 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -1428,6 +1428,10 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { return currentRound; } + public ModelObject getCurrentPlayerModel() { + return currentPlayer; + } + /* (non-Javadoc) * @see rails.game.GameManagerI#getCurrentPlayerIndex() */ diff --git a/rails/game/GameManagerI.java b/rails/game/GameManagerI.java index c7bc6d7..f098de6 100644 --- a/rails/game/GameManagerI.java +++ b/rails/game/GameManagerI.java @@ -100,6 +100,8 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI { public abstract ModelObject getCurrentRoundModel(); + public abstract ModelObject getCurrentPlayerModel(); + /** * @return Returns the currentPlayerIndex. */ |
From: Frederick W. <fre...@us...> - 2012-01-30 19:04:25
|
LocalisedText.properties | 2 - rails/sound/SoundConfig.java | 1 rails/sound/SoundContext.java | 38 +++++++++++---------------------- rails/sound/SoundEventInterpreter.java | 4 ++- rails/sound/SoundPlayer.java | 38 +++++++++++++++------------------ rails/ui/swing/GameStatus.java | 4 +++ rails/ui/swing/GameUIManager.java | 11 ++++++--- rails/ui/swing/ORPanel.java | 36 ++++++++++++++++++++++++------- rails/ui/swing/hexmap/HexMapImage.java | 8 +----- 9 files changed, 77 insertions(+), 65 deletions(-) New commits: commit adee00213cca57e5b8b4a3290f226cb3148b2e6c Author: Frederick Weld <fre...@gm...> Date: Mon Jan 30 20:02:25 2012 +0100 Added selection sfx for stock market click field selections Buy/Sell sfx are still played upon confirmation ("ok") as before. diff --git a/LocalisedText.properties b/LocalisedText.properties index 137b73c..956079e 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -214,7 +214,7 @@ Config.label.sound.backgroundMusic.stockRound=Stock Round (several files) Config.label.sound.backgroundMusic.operatingRound=Operating Round (several files) Config.label.sound.sfx=Sound Effects Config.label.sound.sfx.gen.pass=Pass -Config.label.sound.sfx.gen.select=Select (hex, start item) +Config.label.sound.sfx.gen.select=Select (hexes, click fields) Config.label.sound.sfx.str.bidStartItem=Bid on Start Item Config.label.sound.sfx.str.buyStartItem=Buy Start Item Config.label.sound.sfx.or.buyPrivate=Buy Private (as a company) diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index f1e1c2b..2cb1dc0 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -53,7 +53,7 @@ public class SoundConfig { (Arrays.asList( new String[] { KEY_SFX_GEN_Pass, KEY_SFX_GEN_Select, - KEY_SFX_OR_RotateTile, + KEY_SFX_OR_RotateTile })); //if set to true, sfx is reported not to be enabled irrespective of the configuration diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java index 304c09a..28dfe13 100644 --- a/rails/sound/SoundEventInterpreter.java +++ b/rails/sound/SoundEventInterpreter.java @@ -219,7 +219,9 @@ public class SoundEventInterpreter { public void notifyOfClickFieldSelection(PossibleAction clickFieldAction) { if (SoundConfig.isSFXEnabled()) { if (clickFieldAction instanceof BidStartItem - || clickFieldAction instanceof BuyStartItem) { + || clickFieldAction instanceof BuyStartItem + || clickFieldAction instanceof BuyCertificate + || clickFieldAction instanceof SellShares) { player.playSFXByConfigKey(SoundConfig.KEY_SFX_GEN_Select); } } diff --git a/rails/ui/swing/GameStatus.java b/rails/ui/swing/GameStatus.java index b15bd42..dd8e00e 100644 --- a/rails/ui/swing/GameStatus.java +++ b/rails/ui/swing/GameStatus.java @@ -14,6 +14,7 @@ import rails.common.LocalText; import rails.game.*; import rails.game.action.*; import rails.game.correct.CashCorrectionAction; +import rails.sound.SoundManager; import rails.ui.swing.elements.*; import rails.ui.swing.hexmap.HexHighlightMouseListener; import rails.util.Util; @@ -614,6 +615,9 @@ public class GameStatus extends GridPanel implements ActionListener { gbc = gb.getConstraints(source); actions = ((ClickField) source).getPossibleActions(); + //notify sound manager that click field has been selected + SoundManager.notifyOfClickFieldSelection(actions.get(0)); + // Assume that we will have either sell or buy actions // under one ClickField, not both. This seems guaranteed. log.debug("Action is " + actions.get(0).toString()); commit bbf64f2ee3c94bc4a8570c5fcdae5c33aec4e42d Author: Frederick Weld <fre...@gm...> Date: Mon Jan 30 19:25:56 2012 +0100 Improved sfx/bgm ordering and further SoundPlayer refactoring SFX is now played in the logical order (eg., "buy share" -> "float"). For this purpose, notification of action processing has been placed before action processing itself (within GameUIManager). Furthermore, new BGM is now only played after completion of all SFX. On top of being desirable, this also removes the need for the more complex handling of the stock market opening bell - leading to deletion of that code fragment and further Sound Player streamlining. diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index 849be21..f1e1c2b 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -51,8 +51,9 @@ public class SoundConfig { */ public static final Set<String> KEYS_SFX_IMMEDIATE_PLAYING = new HashSet<String> (Arrays.asList( new String[] { + KEY_SFX_GEN_Pass, KEY_SFX_GEN_Select, - KEY_SFX_OR_RotateTile + KEY_SFX_OR_RotateTile, })); //if set to true, sfx is reported not to be enabled irrespective of the configuration diff --git a/rails/sound/SoundContext.java b/rails/sound/SoundContext.java index 9f4ac58..c38b334 100644 --- a/rails/sound/SoundContext.java +++ b/rails/sound/SoundContext.java @@ -69,14 +69,9 @@ public class SoundContext { + averageRevenue * (1 - slidingAverageAdjustmentFactor); } - /** - * @return true if new background music is played - */ - private boolean playBackgroundMusic() { - boolean isNewMusicPlayed = false; - + private void playBackgroundMusic() { //do nothing if music is not enabled - if (!SoundConfig.isBGMEnabled()) return false; + if (!SoundConfig.isBGMEnabled()) return; String currentRoundConfigKey = null; if (currentRound instanceof StartRound) { @@ -96,19 +91,9 @@ public class SoundContext { currentRoundConfigKey, currentPhaseName); if (!newBackgroundMusicFileName.equals(currentBackgroundMusicFileName)) { currentBackgroundMusicFileName = newBackgroundMusicFileName; - isNewMusicPlayed = true; - - //additionally play stock market opening bell if appropriate - if (SoundConfig.isSFXEnabled() && currentRound instanceof StockRound) { - player.playSFXByConfigKeyWithFollowupBGM( - SoundConfig.KEY_SFX_SR_OpeningBell, - newBackgroundMusicFileName); - } else { - player.playBGM(newBackgroundMusicFileName); - } + player.playBGM(newBackgroundMusicFileName); } } - return isNewMusicPlayed; } public void notifyOfPhase(PhaseI newPhase) { if (!newPhase.equals(currentPhase)) { @@ -119,15 +104,18 @@ public class SoundContext { public void notifyOfRound(RoundI newRound) { if (!newRound.equals(currentRound)) { - currentRound = newRound; - boolean isNewMusicPlayed = playBackgroundMusic(); - - //play stock market opening bell for stock rounds without new background music - //(e.g., if music is disabled but sfx is enabled) - if (!isNewMusicPlayed && SoundConfig.isSFXEnabled() - && currentRound instanceof StockRound) { + + //play stock market opening bell if stock round became current round + //and the round before was not + if (SoundConfig.isSFXEnabled() + && !(currentRound instanceof StockRound) + && newRound instanceof StockRound) { player.playSFXByConfigKey(SoundConfig.KEY_SFX_SR_OpeningBell); } + + currentRound = newRound; + + playBackgroundMusic(); } } public void notifyOfGameSetup() { diff --git a/rails/sound/SoundPlayer.java b/rails/sound/SoundPlayer.java index d35c783..be380d3 100644 --- a/rails/sound/SoundPlayer.java +++ b/rails/sound/SoundPlayer.java @@ -50,7 +50,7 @@ public class SoundPlayer { //wake the subsequent thread if there is one waiting synchronized (this) { - notify(); + notifyAll(); playingDone = true; } } @@ -125,11 +125,17 @@ public class SoundPlayer { private class LoopPlayerThread extends PlayerThread { boolean isStopped = false; Player player = null; + LoopPlayerThread previousLoopPlayerThread = null; public LoopPlayerThread(String fileName) { super(fileName); } public void play() { try { + //stop prior BGM music + if (previousLoopPlayerThread != null) { + previousLoopPlayerThread.interrupt(); + } + while (!isStopped) { FileInputStream fis = new FileInputStream(fileName); BufferedInputStream bis = new BufferedInputStream(fis); @@ -148,16 +154,8 @@ public class SoundPlayer { isStopped = true; if (player!=null) player.close(); } - } - private class PlayerThreadWithFollowupBGM extends PlayerThread { - private String bgmFileName; - public PlayerThreadWithFollowupBGM(String fileName, String bgmFileName) { - super(fileName); - this.bgmFileName = bgmFileName; - } - public void play() { - super.play(); - playBGM(bgmFileName); + public void setPreviousLoopPlayer(LoopPlayerThread previousLoopPlayerThread) { + this.previousLoopPlayerThread = previousLoopPlayerThread; } } @@ -226,19 +224,19 @@ public class SoundPlayer { } /** - * Plays the specified SFX and, after completing SFX play, the specified BGM - * is launched. + * Plays new background music and stops old BGM only after all currently playing + * sfx are finished. */ - public void playSFXByConfigKeyWithFollowupBGM(String sfxConfigKey,String bgmFileName) { - playSFX(new PlayerThreadWithFollowupBGM ( - SoundConfig.get(sfxConfigKey),bgmFileName), - SoundConfig.KEYS_SFX_IMMEDIATE_PLAYING.contains(sfxConfigKey)); - } - public void playBGM(String backgroundMusicFileName) { LoopPlayerThread newPlayerThread = new LoopPlayerThread(backgroundMusicFileName); LoopPlayerThread oldPlayerThread = adjustLastBGMThread(newPlayerThread); - if (oldPlayerThread != null) oldPlayerThread.interrupt(); + + //interrupt old bgm when starting the new bgm + newPlayerThread.setPreviousLoopPlayer(oldPlayerThread); + + //wait for playing new bgm until all sfx have finished playing + newPlayerThread.setPriorThread(lastSFXThread); + newPlayerThread.start(); } diff --git a/rails/ui/swing/GameUIManager.java b/rails/ui/swing/GameUIManager.java index 1a05e38..b081250 100644 --- a/rails/ui/swing/GameUIManager.java +++ b/rails/ui/swing/GameUIManager.java @@ -250,6 +250,13 @@ public class GameUIManager implements DialogOwner { Player oldPlayer = getCurrentPlayer(); boolean wasMyTurn = oldPlayer.getName().equals(localPlayerName); + // Notify the Sound Manager about this action, as it could lead to + // playing sfx or music. + // Notification has to be done before action processing so that + // resulting sfx are played in the correct order (first the action + // related sfx and then model-change related sfx) + SoundManager.notifyOfActionProcessing(gameManager, action); + // Process the action on the server result = previousResult = processOnServer (action); @@ -281,10 +288,6 @@ public class GameUIManager implements DialogOwner { } } - // Inform the Sound Manager about this action, as it could lead to - // playing sfx or music - SoundManager.notifyOfActionProcessing(gameManager, action); - // Check in which round we are now, // and make sure that the right window is active. updateUI(); diff --git a/rails/ui/swing/hexmap/HexMapImage.java b/rails/ui/swing/hexmap/HexMapImage.java index b8e95f4..fc934fb 100644 --- a/rails/ui/swing/hexmap/HexMapImage.java +++ b/rails/ui/swing/hexmap/HexMapImage.java @@ -2,13 +2,7 @@ package rails.ui.swing.hexmap; import java.awt.*; -import java.awt.event.*; import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferedImage; -import java.io.File; - -import javax.swing.*; import org.apache.batik.swing.JSVGCanvas; import org.apache.batik.swing.gvt.GVTTreeRendererAdapter; @@ -26,6 +20,8 @@ import rails.util.Util; */ public final class HexMapImage extends JSVGCanvas { + private static final long serialVersionUID = 1L; + protected static Logger log = Logger.getLogger(HexMapImage.class.getPackage().getName()); commit 1c68f09d713183272287f249aa80d47c2d127ef8 Author: Frederick Weld <fre...@gm...> Date: Mon Jan 30 19:24:43 2012 +0100 Added temporary workaround for avoiding exception prints for 0-revenue diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java index 566b06b..cdaad11 100644 --- a/rails/ui/swing/ORPanel.java +++ b/rails/ui/swing/ORPanel.java @@ -741,7 +741,11 @@ implements ActionListener, KeyListener, RevenueListener { int revenueValue = ra.calculateRevenue(); log.debug("Revenue Value:" + revenueValue); log.debug("Revenue Run:" + ra.getOptimalRunPrettyPrint(true)); - ra.drawOptimalRunAsPath(orUIManager.getMap()); + + //try-catch clause temporary workaround as revenue adapter's + //convertRcRun might erroneously raise exceptions + try {revenueAdapter.drawOptimalRunAsPath(orUIManager.getMap());} + catch (Exception e) {} if (!Game.getDevelop()) { //parent component is ORPanel so that dialog won't hide the routes painted on the map @@ -770,7 +774,12 @@ implements ActionListener, KeyListener, RevenueListener { //clean up the paths on the map orUIManager.getMap().setTrainPaths(null); //but retain paths already existing before - if (revenueAdapter != null) revenueAdapter.drawOptimalRunAsPath(orUIManager.getMap()); + if (revenueAdapter != null) { + //try-catch clause temporary workaround as revenue adapter's + //convertRcRun might erroneously raise exceptions + try {revenueAdapter.drawOptimalRunAsPath(orUIManager.getMap());} + catch (Exception e) {} + } } } @@ -798,7 +807,10 @@ implements ActionListener, KeyListener, RevenueListener { public void redrawRoutes() { if (revenueAdapter != null && isDisplayRoutes()) { - revenueAdapter.drawOptimalRunAsPath(orUIManager.getMap()); + //try-catch clause temporary workaround as revenue adapter's + //convertRcRun might erroneously raise exceptions + try {revenueAdapter.drawOptimalRunAsPath(orUIManager.getMap());} + catch (Exception e) {} } } @@ -1069,12 +1081,20 @@ implements ActionListener, KeyListener, RevenueListener { } if (finalResult) { orUIManager.getMap().setTrainPaths(null); - revenueAdapter.drawOptimalRunAsPath(orUIManager.getMap()); - if (isRevenueValueToBeSet) { - orUIManager.setInformation("Best Run Value = " + bestRevenue + - " with " + Util.convertToHtml(revenueAdapter.getOptimalRunPrettyPrint(false))); - orUIManager.setDetail(Util.convertToHtml(revenueAdapter.getOptimalRunPrettyPrint(true))); + //try-catch clause temporary workaround as revenue adapter's + //convertRcRun might erroneously raise exceptions + //leaving on exception is admissible as exception only occur + //if revenue would be 0. + try { + revenueAdapter.drawOptimalRunAsPath(orUIManager.getMap()); + + if (isRevenueValueToBeSet) { + orUIManager.setInformation("Best Run Value = " + bestRevenue + + " with " + Util.convertToHtml(revenueAdapter.getOptimalRunPrettyPrint(false))); + orUIManager.setDetail(Util.convertToHtml(revenueAdapter.getOptimalRunPrettyPrint(true))); + } } + catch (Exception e) {} } } |
From: Frederick W. <fre...@us...> - 2012-01-30 14:41:33
|
LocalisedText.properties | 1 data/Properties.xml | 1 rails/sound/SoundConfig.java | 15 +++++++++++ rails/sound/SoundContext.java | 4 +- rails/sound/SoundEventInterpreter.java | 41 ++++++++++++++++++++++++++---- rails/sound/SoundManager.java | 8 ++++- rails/sound/SoundPlayer.java | 45 +++++++++++++-------------------- rails/ui/swing/ORUIManager.java | 11 ++++---- rails/ui/swing/StartRoundWindow.java | 4 ++ 9 files changed, 90 insertions(+), 40 deletions(-) New commits: commit e6074467587ead46896cf6a5668a8acf62b88942 Author: Frederick Weld <fre...@gm...> Date: Mon Jan 30 15:34:42 2012 +0100 Refactored SoundPlayer: immediate/deferred sfx play defined declaratively Some sfx are to be played without waiting for the completion of prior sfx (applies to selection / rotate tile sfx). Before, the caller of the SoundPlayer had to specify whether to wait or not. Now, sfx to be immediately played are tagged as such in SoundConfig so that SoundPlayer takes care of scheduling without necessiting that information by the caller. diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index ecff5cd..849be21 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -1,5 +1,9 @@ package rails.sound; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + import rails.common.parser.Config; /** @@ -41,6 +45,16 @@ public class SoundConfig { public static final String KEY_SFX_OR_BuyTrain = "sound.sfx.or.buyTrain"; public static final String KEY_SFX_OR_BuyPrivate = "sound.sfx.or.buyPrivate"; + /** + * list of sfx which are to be played immediately (without waiting for completion of + * prior sfx threads) + */ + public static final Set<String> KEYS_SFX_IMMEDIATE_PLAYING = new HashSet<String> + (Arrays.asList( new String[] { + KEY_SFX_GEN_Select, + KEY_SFX_OR_RotateTile + })); + //if set to true, sfx is reported not to be enabled irrespective of the configuration private static boolean isSFXDisabled = false; diff --git a/rails/sound/SoundContext.java b/rails/sound/SoundContext.java index 4d4be08..9f4ac58 100644 --- a/rails/sound/SoundContext.java +++ b/rails/sound/SoundContext.java @@ -100,8 +100,8 @@ public class SoundContext { //additionally play stock market opening bell if appropriate if (SoundConfig.isSFXEnabled() && currentRound instanceof StockRound) { - player.playSFXWithFollowupBGM( - SoundConfig.get(SoundConfig.KEY_SFX_SR_OpeningBell), + player.playSFXByConfigKeyWithFollowupBGM( + SoundConfig.KEY_SFX_SR_OpeningBell, newBackgroundMusicFileName); } else { player.playBGM(newBackgroundMusicFileName); diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java index d45407c..304c09a 100644 --- a/rails/sound/SoundEventInterpreter.java +++ b/rails/sound/SoundEventInterpreter.java @@ -199,9 +199,7 @@ public class SoundEventInterpreter { if (SoundConfig.isSFXEnabled()) { //play rotate sound if tile has been rotated or is now ready for rotations if (currentStep == ORUIManager.ROTATE_OR_CONFIRM_TILE) { - //don't wait for prior SFX playing end, otherwise quickly repeated - //rotations would lead to a long queue of sequentially played sfx - player.playSFXByConfigKey(SoundConfig.KEY_SFX_OR_RotateTile,false); + player.playSFXByConfigKey(SoundConfig.KEY_SFX_OR_RotateTile); } //play hex selection sound if the follow-up step (select tile/token) is active @@ -209,9 +207,7 @@ public class SoundEventInterpreter { // can also be selected during selectTile/Token) else if ( currentStep == ORUIManager.SELECT_TILE || currentStep == ORUIManager.SELECT_TOKEN ) { - //don't wait for prior SFX playing end, otherwise quickly repeated - //hex selections would lead to a long queue of sequentially played sfx - player.playSFXByConfigKey(SoundConfig.KEY_SFX_GEN_Select,false); + player.playSFXByConfigKey(SoundConfig.KEY_SFX_GEN_Select); } } @@ -224,9 +220,7 @@ public class SoundEventInterpreter { if (SoundConfig.isSFXEnabled()) { if (clickFieldAction instanceof BidStartItem || clickFieldAction instanceof BuyStartItem) { - //don't wait for prior SFX playing end, otherwise quickly repeated - //selections would lead to a long queue of sequentially played sfx - player.playSFXByConfigKey(SoundConfig.KEY_SFX_GEN_Select,false); + player.playSFXByConfigKey(SoundConfig.KEY_SFX_GEN_Select); } } } diff --git a/rails/sound/SoundPlayer.java b/rails/sound/SoundPlayer.java index 45fbf8f..d35c783 100644 --- a/rails/sound/SoundPlayer.java +++ b/rails/sound/SoundPlayer.java @@ -187,59 +187,52 @@ public class SoundPlayer { return pt; } - private void playSFX(PlayerThread newPlayerThread,boolean waitForEndOfPriorSFX) { + private void playSFX(PlayerThread newPlayerThread,boolean playImmediately) { PlayerThread oldPlayerThread = adjustLastSFXThread(newPlayerThread); - if (waitForEndOfPriorSFX) { + if (!playImmediately) { newPlayerThread.setPriorThread(oldPlayerThread); } newPlayerThread.start(); } - /** - * SFX played after prior SFX playing has been completed - */ - public void playSFX(String fileName) { - playSFX(fileName,true); + private void playSFX(String fileName, boolean playImmediately) { + playSFX(new PlayerThread (fileName),playImmediately); } - public void playSFX(String fileName, boolean waitForEndOfPriorSFX) { - playSFX(new PlayerThread (fileName),waitForEndOfPriorSFX); + + private void playSFX(String fileName, double playSoundProportion, boolean playImmediately) { + playSFX(new PortionPlayerThread (fileName, 1 - playSoundProportion, 1) + ,playImmediately); } + /** * SFX played after prior SFX playing has been completed */ public void playSFXByConfigKey(String configKey) { - playSFXByConfigKey(configKey, true); - } - public void playSFXByConfigKey(String configKey, boolean waitForEndOfPriorSFX) { - playSFX(SoundConfig.get(configKey), waitForEndOfPriorSFX); + playSFX(SoundConfig.get(configKey), + SoundConfig.KEYS_SFX_IMMEDIATE_PLAYING.contains(configKey)); } public void playSFXByConfigKey(String configKey,String parameter) { - playSFX(SoundConfig.get(configKey,parameter)); + playSFX(SoundConfig.get(configKey,parameter), + SoundConfig.KEYS_SFX_IMMEDIATE_PLAYING.contains(configKey)); } - public void playSFX(String fileName, double playSoundProportion) { - playSFX(new PortionPlayerThread (fileName, 1 - playSoundProportion, 1),true); - } - /** * The latter part of the sfx is played. * @param playSoundProportion The length of this part relatively to the overall sound duration. */ public void playSFXByConfigKey(String configKey, double playSoundProportion) { - playSFX(SoundConfig.get(configKey), playSoundProportion); - } - - public void playSFXWithFollowupBGM(String sfxFileName,String bgmFileName) { - playSFX(new PlayerThreadWithFollowupBGM (sfxFileName,bgmFileName),true); + playSFX(SoundConfig.get(configKey), playSoundProportion, + SoundConfig.KEYS_SFX_IMMEDIATE_PLAYING.contains(configKey)); } /** * Plays the specified SFX and, after completing SFX play, the specified BGM * is launched. */ - public void playSFXWithFollowupBGMByConfigKey(String sfxConfigKey, String bgmConfigKey) { - playSFXWithFollowupBGM( - SoundConfig.get(sfxConfigKey),SoundConfig.get(bgmConfigKey)); + public void playSFXByConfigKeyWithFollowupBGM(String sfxConfigKey,String bgmFileName) { + playSFX(new PlayerThreadWithFollowupBGM ( + SoundConfig.get(sfxConfigKey),bgmFileName), + SoundConfig.KEYS_SFX_IMMEDIATE_PLAYING.contains(sfxConfigKey)); } public void playBGM(String backgroundMusicFileName) { commit 0711aea4fce98d414e13315873549c7c8345c795 Author: Frederick Weld <fre...@gm...> Date: Mon Jan 30 14:42:01 2012 +0100 Added new sfx options (select hex / start item) Sound framework now notified within set local step of ORUIManager in a generic manner (could be expanded upon in the future if there is a pull for more sound options). Added notification trigger into start round window's click field actionPerformed. diff --git a/LocalisedText.properties b/LocalisedText.properties index 8ef0a7f..137b73c 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -214,6 +214,7 @@ Config.label.sound.backgroundMusic.stockRound=Stock Round (several files) Config.label.sound.backgroundMusic.operatingRound=Operating Round (several files) Config.label.sound.sfx=Sound Effects Config.label.sound.sfx.gen.pass=Pass +Config.label.sound.sfx.gen.select=Select (hex, start item) Config.label.sound.sfx.str.bidStartItem=Bid on Start Item Config.label.sound.sfx.str.buyStartItem=Buy Start Item Config.label.sound.sfx.or.buyPrivate=Buy Private (as a company) diff --git a/data/Properties.xml b/data/Properties.xml index d2a9153..43e64c2 100644 --- a/data/Properties.xml +++ b/data/Properties.xml @@ -74,6 +74,7 @@ <Section name="SFX"> <Property name="sound.sfx" type="LIST" values="disabled,enabled" /> <Property name="sound.sfx.gen.pass" type="FILE" /> + <Property name="sound.sfx.gen.select" type="FILE" /> <Property name="sound.sfx.str.bidStartItem" type="FILE" /> <Property name="sound.sfx.str.buyStartItem" type="FILE" /> <Property name="sound.sfx.sr.openingBell" type="FILE" /> diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index 14adb30..ecff5cd 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -21,6 +21,7 @@ public class SoundConfig { public static final String KEY_BGM_EndOfGameRound = "sound.backgroundMusic.endOfGameRound"; public static final String KEY_SFX_Enabled = "sound.sfx"; public static final String KEY_SFX_GEN_Pass = "sound.sfx.gen.pass"; + public static final String KEY_SFX_GEN_Select = "sound.sfx.gen.select"; public static final String KEY_SFX_STR_BidStartItem = "sound.sfx.str.bidStartItem"; public static final String KEY_SFX_STR_BuyStartItem = "sound.sfx.str.buyStartItem"; public static final String KEY_SFX_SR_OpeningBell = "sound.sfx.sr.openingBell"; diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java index 1f5590c..d45407c 100644 --- a/rails/sound/SoundEventInterpreter.java +++ b/rails/sound/SoundEventInterpreter.java @@ -6,6 +6,7 @@ import java.util.Observer; import rails.game.*; import rails.game.action.*; import rails.game.state.*; +import rails.ui.swing.ORUIManager; /** * Converts processed actions and model updates to triggers for playing sounds. @@ -72,7 +73,8 @@ public class SoundEventInterpreter { //General actions if (action instanceof NullAction) { - if (((NullAction)action).getMode() == NullAction.PASS) { + if (((NullAction)action).getMode() == NullAction.PASS + || ((NullAction)action).getMode() == NullAction.AUTOPASS) { player.playSFXByConfigKey (SoundConfig.KEY_SFX_GEN_Pass); } @@ -186,11 +188,46 @@ public class SoundEventInterpreter { public void notifyOfTimeWarp(boolean timeWarpMode) { SoundConfig.setSFXDisabled(timeWarpMode); } - public void notifyOfRotateTile() { + /** + * Interprets changes/status of OR local steps in order to trigger sfx that + * are related to neither model changes nor game engine actions. + * Is triggered whenever some step changes (but priorStep is allowed to be + * equal to currentStep) + * @param currentStep Step as defined as constant in ORUIManager + */ + public void notifyOfORLocalStep(int currentStep) { if (SoundConfig.isSFXEnabled()) { - //don't wait for prior SFX playing end, otherwise quickly repeated - //rotations would lead to a long queue of sequentially played sfx - player.playSFXByConfigKey(SoundConfig.KEY_SFX_OR_RotateTile,false); + //play rotate sound if tile has been rotated or is now ready for rotations + if (currentStep == ORUIManager.ROTATE_OR_CONFIRM_TILE) { + //don't wait for prior SFX playing end, otherwise quickly repeated + //rotations would lead to a long queue of sequentially played sfx + player.playSFXByConfigKey(SoundConfig.KEY_SFX_OR_RotateTile,false); + } + + //play hex selection sound if the follow-up step (select tile/token) is active + //(don't consider whether prior step was "select hex..." because hexes + // can also be selected during selectTile/Token) + else if ( currentStep == ORUIManager.SELECT_TILE + || currentStep == ORUIManager.SELECT_TOKEN ) { + //don't wait for prior SFX playing end, otherwise quickly repeated + //hex selections would lead to a long queue of sequentially played sfx + player.playSFXByConfigKey(SoundConfig.KEY_SFX_GEN_Select,false); + + } + } + } + /** + * Interprets selections of ClickFields + * @param clickFieldAction The action associated with the click field + */ + public void notifyOfClickFieldSelection(PossibleAction clickFieldAction) { + if (SoundConfig.isSFXEnabled()) { + if (clickFieldAction instanceof BidStartItem + || clickFieldAction instanceof BuyStartItem) { + //don't wait for prior SFX playing end, otherwise quickly repeated + //selections would lead to a long queue of sequentially played sfx + player.playSFXByConfigKey(SoundConfig.KEY_SFX_GEN_Select,false); + } } } } diff --git a/rails/sound/SoundManager.java b/rails/sound/SoundManager.java index d3a9e33..7a357d6 100644 --- a/rails/sound/SoundManager.java +++ b/rails/sound/SoundManager.java @@ -2,6 +2,7 @@ package rails.sound; import rails.game.GameManagerI; import rails.game.action.PossibleAction; +import rails.game.action.StartItemAction; /** * This is a singleton class as there should never be two @@ -58,7 +59,10 @@ public class SoundManager { public static void notifyOfTimeWarp(boolean timeWarpMode) { getInstance().eventInterpreter.notifyOfTimeWarp(timeWarpMode); } - public static void notifyOfRotateTile() { - getInstance().eventInterpreter.notifyOfRotateTile(); + public static void notifyOfORLocalStep(int currentStep) { + getInstance().eventInterpreter.notifyOfORLocalStep(currentStep); + } + public static void notifyOfClickFieldSelection(PossibleAction clickFieldAction) { + getInstance().eventInterpreter.notifyOfClickFieldSelection(clickFieldAction); } } diff --git a/rails/ui/swing/ORUIManager.java b/rails/ui/swing/ORUIManager.java index 30441d6..6f7f8c6 100644 --- a/rails/ui/swing/ORUIManager.java +++ b/rails/ui/swing/ORUIManager.java @@ -664,11 +664,9 @@ public class ORUIManager implements DialogOwner { if (localStep == ROTATE_OR_CONFIRM_TILE && clickedHex == selectedHex) { selectedHex.rotateTile(); - //directly inform sound framework of "rotate tile" as this is - //neither an action nor a model change - //call not put to GUIHex so that sound notification calls are - //centrally done by UIManagers (Game, OR) - SoundManager.notifyOfRotateTile(); + //directly inform sound framework of "rotate tile" local step + //as notification via "set local step" does not occur + SoundManager.notifyOfORLocalStep(localStep); return true; } else { @@ -1795,6 +1793,9 @@ public class ORUIManager implements DialogOwner { public void setLocalStep(int localStep) { log.debug("Setting upgrade step to " + localStep + " " + ORUIManager.messageKey[localStep]); + + SoundManager.notifyOfORLocalStep(localStep); + this.localStep = localStep; updateMessage(); diff --git a/rails/ui/swing/StartRoundWindow.java b/rails/ui/swing/StartRoundWindow.java index 1b9af8a..47f0a9a 100644 --- a/rails/ui/swing/StartRoundWindow.java +++ b/rails/ui/swing/StartRoundWindow.java @@ -15,6 +15,7 @@ import rails.common.LocalText; import rails.game.*; import rails.game.action.*; import rails.game.special.SpecialPropertyI; +import rails.sound.SoundManager; import rails.ui.swing.elements.*; import rails.ui.swing.hexmap.HexHighlightMouseListener; @@ -563,6 +564,9 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { StartItemAction currentActiveItem = (StartItemAction) ((ClickField) source).getPossibleActions().get( 0); + + //notify sound manager that click field has been selected + SoundManager.notifyOfClickFieldSelection(currentActiveItem); if (currentActiveItem instanceof BuyStartItem) { buyButton.setEnabled(true); |
From: Stefan F. <ste...@us...> - 2012-01-30 13:03:53
|
Tag 'v1.6.1' created by Stefan Frey <ste...@we...> at 2012-01-30 13:02 +0000 version 1.6.1 Changes since v1.5.0-91: --- 0 files changed --- |
From: Stefan F. <ste...@us...> - 2012-01-30 13:03:46
|
buildRails.xml | 2 data/1856/MapImage.svg | 14 data/1889/Map.xml | 53 data/1889/MapImage.svg | 4259 ++++++++++++++++++++++++++++++++ data/18TN/Game.xml | 2 rails/game/GameManager.java | 13 rails/game/StockRound.java | 79 rails/ui/swing/GameSetupWindow.java | 3 rails/ui/swing/ReportWindowDynamic.java | 24 readme.txt | 23 test/data/real/18TN_A.rails |binary test/data/real/18TN_A.report | 612 ++++ version.number | 2 13 files changed, 4996 insertions(+), 90 deletions(-) New commits: commit 0f7757081388a42d0df9e02abbc54c9c5b5fa0d0 Author: Stefan Frey <ste...@we...> Date: Mon Jan 30 13:28:36 2012 +0100 updated version number to 1.6.1 diff --git a/version.number b/version.number index 79c0ece..d54f51c 100644 --- a/version.number +++ b/version.number @@ -1,5 +1,5 @@ #Property file that contains version number and the develop indicator -version=1.6.0 +version=1.6.1 # the following string "@DEVELOP@ is replaced by an empty string in the release version # this is done automatically by ant develop=@DEVELOP@ \ No newline at end of file commit afa90772b6b8aaa6093ba04b855d39380010b23d Author: Stefan Frey <ste...@we...> Date: Sun Jan 29 18:57:29 2012 +0100 18TN test game added(cherry picked from commit 6f3e1b37eec99dda21eef3bd7b66eb6a1c0716ea) diff --git a/test/data/real/18TN_A.rails b/test/data/real/18TN_A.rails new file mode 100644 index 0000000..6936faa Binary files /dev/null and b/test/data/real/18TN_A.rails differ diff --git a/test/data/real/18TN_A.report b/test/data/real/18TN_A.report new file mode 100644 index 0000000..2771851 --- /dev/null +++ b/test/data/real/18TN_A.report @@ -0,0 +1,612 @@ +GameIs,18TN +PlayerIs,1,Bob +PlayerIs,2,Chester +PlayerIs,3,Joshua +PlayerIs,4,Rob +PlayerCash,450 +BankHas,6200 +StartOfPhase,2 +BankSizeIs,6200 +StartOfInitialRound +HasPriority,Bob +BID_ITEM_LOG,Bob,75,M&C,375 +BID_ITEM_LOG,Chester,180,L&N,270 +BID_ITEM_LOG,Joshua,105,O&W,345 +BID_ITEM_LOG,Rob,185,L&N,265 +BuysItemFor,Bob,TCC,20 +BuysItemFor,Chester,ET&WNC,40 +BuysItemFor,Bob,M&C,75 +BuysItemFor,Joshua,O&W,105 +TO_AUCTION,L&N +BID_ITEM_LOG,Chester,190,L&N,220 +BID_ITEM_LOG,Rob,195,L&N,255 +PASSES,Chester +BuysItemFor,Rob,PRES_CERT_NAME,L&N,20,195 +FloatsWithCash,L&N,800 +Has,L&N,800 +Has,Bob,355 +Has,Chester,410 +Has,Joshua,345 +Has,Rob,255 +StartStockRound,1 +HasPriority,Joshua +PASSES,Joshua +BUY_SHARE_LOG,Rob,10,L&N,IPO,80 +BUY_SHARE_LOG,Bob,10,L&N,IPO,80 +START_COMPANY_LOG,Chester,SOU,65,130,2,20,BANK +BUY_SHARE_LOG,Joshua,10,L&N,IPO,80 +BUY_SHARE_LOG,Rob,10,L&N,IPO,80 +PASSES,Bob +BUY_SHARE_LOG,Chester,10,SOU,IPO,65 +BUY_SHARE_LOG,Joshua,10,L&N,IPO,80 +BUY_SHARE_LOG,Rob,10,L&N,IPO,80 +PASSES,Bob +BUY_SHARE_LOG,Chester,10,SOU,IPO,65 +BUY_SHARE_LOG,Joshua,10,L&N,IPO,80 +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,L&N,IPO,80 +BUY_SHARE_LOG,Chester,10,SOU,IPO,65 +PASSES,Joshua +Autopasses,Rob +PASSES,Bob +BUY_SHARE_LOG,Chester,10,SOU,IPO,65 +FloatsWithCash,SOU,650 +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,SOU,IPO,65 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,SOU,IPO,65 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,SOU,IPO,65 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +PASSES,Bob + +END_SR,1 +PRICE_MOVES_LOG,L&N,80,E3,90,E2 +SoldOut,L&N,80,E3,90,E2 +Has,L&N,800 +Has,SOU,650 +Has,Bob,0 +Has,Chester,20 +Has,Joshua,105 +Has,Rob,15 +START_OR,1.1 +ReceivesFor,Bob,5,TCC +ReceivesFor,Chester,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAtFor,L&N,9,B15,W,60 +LaysTileAt,L&N,5,B17,NE +LAYS_TOKEN_ON,L&N,B17,40 +CompanyDoesNotPayDividend,L&N +PRICE_MOVES_LOG,L&N,90,E2,80,D2 +BuysTrain,L&N,2,IPO,80 +FirstTrainBought,2 + +CompanyOperates,SOU,Chester +BuysPrivateFromFor,SOU,ET&WNC,Chester,40 +LaysTileAt,SOU,8,F19,W +LaysTileAt,SOU,8,E20,E +LaysTileAtFor,SOU,57,F17,W,40 +CompanyDoesNotPayDividend,SOU +PRICE_MOVES_LOG,SOU,65,D4,55,C4 +BuysTrain,SOU,2,IPO,80 + +EndOfOperatingRound,1.1 +ORWorthIncrease,Bob,1.1,-30 +ORWorthIncrease,Chester,1.1,-50 +ORWorthIncrease,Joshua,1.1,-10 +ORWorthIncrease,Rob,1.1,-50 +Has,L&N,620 +Has,SOU,490 +Has,Bob,20 +Has,Chester,70 +Has,Joshua,125 +Has,Rob,15 +StartStockRound,2 +HasPriority,Chester +PASSES,Chester +BUY_SHARE_LOG,Joshua,10,SOU,IPO,65 +Autopasses,Rob +PASSES,Bob +PASSES,Chester +Autopasses,Joshua + +END_SR,2 +PRICE_MOVES_LOG,L&N,80,D2,90,D1 +SoldOut,L&N,80,D2,90,D1 +PRICE_MOVES_LOG,SOU,55,C4,60,C3 +SoldOut,SOU,55,C4,60,C3 +Has,L&N,620 +Has,SOU,490 +Has,Bob,20 +Has,Chester,70 +Has,Joshua,60 +Has,Rob,15 +START_OR,2.1 +ReceivesFor,Bob,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,58,E10,NE +LaysTileAtFor,L&N,57,F11,NW,40 +CompanyRevenue,L&N,70 +CompanyPaysOutFull,L&N,70 +Payout,Joshua,21,3,10 +Payout,Bob,14,2,10 +Payout,Rob,35,5,10 +PRICE_MOVES_LOG,L&N,90,D1,100,E1 +BuysTrain,L&N,2,IPO,80 + +CompanyOperates,SOU,Chester +LaysTileAtFor,SOU,9,F15,E,60 +LaysTileAt,SOU,58,F13,E +CompanyRevenue,SOU,80 +CompanyPaysOutFull,SOU,80 +Payout,Joshua,8,1,10 +Payout,Bob,24,3,10 +Payout,Chester,48,6,10 +PRICE_MOVES_LOG,SOU,60,C3,70,D3 +BuysTrain,SOU,2,IPO,80 + +EndOfOperatingRound,2.1 +ORWorthIncrease,Bob,2.1,108 +ORWorthIncrease,Chester,2.1,108 +ORWorthIncrease,Joshua,2.1,89 +ORWorthIncrease,Rob,2.1,85 +Has,L&N,500 +Has,SOU,360 +Has,Bob,78 +Has,Chester,118 +Has,Joshua,109 +Has,Rob,50 +StartStockRound,3 +HasPriority,Rob +PASSES,Rob +SELL_SHARES_LOG,Bob,2,10,20,L&N,200 +PRICE_MOVES_LOG,L&N,100,E1,80,E3 +SELL_SHARES_LOG,Bob,3,10,30,SOU,210 +PRICE_MOVES_LOG,SOU,70,D3,55,D6 +START_COMPANY_LOG,Bob,TC,80,160,2,20,BANK +BUY_SHARE_LOG,Chester,10,L&N,Pool,80 +BUY_SHARE_LOG,Joshua,10,L&N,Pool,80 +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,TC,IPO,80 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,TC,IPO,80 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,TC,IPO,80 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,TC,IPO,80 +FloatsWithCash,TC,800 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +PASSES,Bob + +END_SR,3 +PRICE_MOVES_LOG,L&N,80,E3,90,E2 +SoldOut,L&N,80,E3,90,E2 +Has,L&N,500 +Has,SOU,360 +Has,TC,800 +Has,Bob,8 +Has,Chester,38 +Has,Joshua,29 +Has,Rob,50 +START_OR,3.1 +ReceivesFor,Bob,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,5,G12,E +LAYS_TOKEN_ON,L&N,G12,100 +CompanyRevenue,L&N,120 +CompanyPaysOutFull,L&N,120 +Payout,Joshua,48,4,10 +Payout,Rob,60,5,10 +Payout,Chester,12,1,10 +PRICE_MOVES_LOG,L&N,90,E2,100,F2 + +CompanyOperates,TC,Bob +CompanyDoesNotPayDividend,TC +PRICE_MOVES_LOG,TC,80,E3,70,D3 +BuysTrain,TC,2,IPO,80 +All 2-trains are sold out, 3-trains now available + +CompanyOperates,SOU,Chester +CompanyRevenue,SOU,110 +CompanyPaysOutFull,SOU,110 +Payout,Joshua,11,1,10 +Payout,Chester,66,6,10 +Payout,SOU,33,3,10 +PRICE_MOVES_LOG,SOU,55,D6,65,E6 +BuysTrain,SOU,3,IPO,180 +FirstTrainBought,3 +StartOfPhase,3 + +EndOfOperatingRound,3.1 +ORWorthIncrease,Bob,3.1,-40 +ORWorthIncrease,Chester,3.1,148 +ORWorthIncrease,Joshua,3.1,129 +ORWorthIncrease,Rob,3.1,110 +Has,L&N,400 +Has,SOU,223 +Has,TC,720 +Has,Bob,28 +Has,Chester,116 +Has,Joshua,108 +Has,Rob,110 +StartStockRound,4 +HasPriority,Chester +BUY_SHARE_LOG,Chester,10,TC,IPO,80 +SELL_SHARES_LOG,Joshua,4,10,40,L&N,400 +PRICE_MOVES_LOG,L&N,100,F2,75,F5 +SELL_SHARE_LOG,Joshua,10,SOU,65 +PRICE_MOVES_LOG,SOU,65,E6,60,E7 +START_COMPANY_LOG,Joshua,GMO,90,180,2,20,BANK +BUY_SHARE_LOG,Rob,10,L&N,Pool,75 +Autopasses,Bob +Autopasses,Chester +BUY_SHARE_LOG,Joshua,10,GMO,IPO,90 +Autopasses,Rob +Autopasses,Bob +Autopasses,Chester +BUY_SHARE_LOG,Joshua,10,GMO,IPO,90 +Autopasses,Rob +Autopasses,Bob +Autopasses,Chester +BUY_SHARE_LOG,Joshua,10,GMO,IPO,90 +Autopasses,Rob +Autopasses,Bob +Autopasses,Chester +BUY_SHARE_LOG,Joshua,10,GMO,IPO,90 +FloatsWithCash,GMO,900 +Autopasses,Rob +Autopasses,Bob +Autopasses,Chester +PASSES,Joshua + +END_SR,4 +Has,GMO,900 +Has,L&N,400 +Has,SOU,223 +Has,TC,720 +Has,Bob,28 +Has,Chester,36 +Has,Joshua,33 +Has,Rob,35 +START_OR,4.1 +ReceivesFor,Bob,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,GMO,Joshua +LaysTileAt,GMO,6,H7,NE +LaysTileAt,GMO,8,F7,SW +CompanyDoesNotPayDividend,GMO +PRICE_MOVES_LOG,GMO,90,E2,80,D2 +BuysTrain,GMO,3,IPO,180 + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,15,B17,SE +CompanyRevenue,L&N,140 +CompanyPaysOutFull,L&N,140 +Payout,Chester,14,1,10 +Payout,Rob,84,6,10 +Payout,L&N,42,3,10 +PRICE_MOVES_LOG,L&N,75,F5,80,G5 +BuysTrain,L&N,3,IPO,180 + +CompanyOperates,TC,Bob +LaysTileAtFor,TC,8,C18,SW,60 +LaysTileAt,TC,8,D17,NE +LAYS_TOKEN_ON,TC,B17,40 +CompanyRevenue,TC,80 +CompanyPaysOutFull,TC,80 +Payout,Chester,8,1,10 +Payout,Bob,48,6,10 +PRICE_MOVES_LOG,TC,70,D3,80,E3 +BuysTrain,TC,3,IPO,180 +StartOfPhase,3½ + +CompanyOperates,SOU,Chester +LaysTileAt,SOU,619,G12,SW +CompanyRevenue,SOU,140 +CompanyPaysOutFull,SOU,140 +Payout,Chester,84,6,10 +Payout,SOU,56,4,10 +PRICE_MOVES_LOG,SOU,60,E7,65,E6 + +EndOfOperatingRound,4.1 +ORWorthIncrease,Bob,4.1,128 +ORWorthIncrease,Chester,4.1,151 +ORWorthIncrease,Joshua,4.1,-40 +ORWorthIncrease,Rob,4.1,114 +Has,GMO,720 +Has,L&N,262 +Has,SOU,289 +Has,TC,440 +Has,Bob,96 +Has,Chester,142 +Has,Joshua,53 +Has,Rob,119 +START_OR,4.2 +ReceivesFor,Bob,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,15,F17,E +LAYS_TOKEN_ON,L&N,F17,100 +CompanyRevenue,L&N,200 +CompanyPaysOutFull,L&N,200 +Payout,Chester,20,1,10 +Payout,Rob,120,6,10 +Payout,L&N,60,3,10 +PRICE_MOVES_LOG,L&N,80,G5,85,G4 + +CompanyOperates,TC,Bob +BuysPrivateFromFor,TC,TCC,Bob,40 +BuysPrivateFromFor,TC,M&C,Bob,120 +LaysTileAt,TC,8,H5,NW +LaysTileAt,TC,599,F11,NE +CompanyRevenue,TC,110 +CompanyPaysOutFull,TC,110 +Payout,Bob,66,6,10 +Payout,Chester,11,1,10 +PRICE_MOVES_LOG,TC,80,E3,90,F3 + +CompanyOperates,GMO,Joshua +LaysTileAt,GMO,9,I6,SW +LaysTileAt,GMO,8,E6,NE +BuysPrivateFromFor,GMO,O&W,Joshua,200 +CompanyRevenue,GMO,0 +CompanyDoesNotPayDividend,GMO +BuysTrain,GMO,3,IPO,180 +All 3-trains are sold out, 4-trains now available + +CompanyOperates,SOU,Chester +LaysTileAt,SOU,9,E12,SW +LaysTileAt,SOU,8,D13,SW +LAYS_TOKEN_ON,SOU,F11,40 +CompanyRevenue,SOU,230 +CompanyPaysOutFull,SOU,230 +Payout,Chester,138,6,10 +Payout,SOU,92,4,10 +PRICE_MOVES_LOG,SOU,65,E6,70,E5 +BuysTrain,SOU,4,IPO,300 +FirstTrainBought,4 +StartOfPhase,4 + +EndOfOperatingRound,4.2 +ORWorthIncrease,Bob,4.2,216 +ORWorthIncrease,Chester,4.2,214 +ORWorthIncrease,Joshua,4.2,120 +ORWorthIncrease,Rob,4.2,150 +Has,GMO,340 +Has,L&N,222 +Has,SOU,51 +Has,TC,280 +Has,Bob,342 +Has,Chester,311 +Has,Joshua,273 +Has,Rob,239 +StartStockRound,5 +HasPriority,Rob +SELL_SHARES_LOG,Rob,2,10,20,L&N,170 +PRICE_MOVES_LOG,L&N,85,G4,80,G5 +START_COMPANY_LOG,Rob,IC,65,195,3,30,BANK +SELL_SHARE_LOG,Bob,10,TC,90 +PRICE_MOVES_LOG,TC,90,F3,80,F4 +BUY_SHARE_LOG,Bob,10,SOU,Pool,70 +SELL_SHARE_LOG,Chester,10,TC,80 +PRICE_MOVES_LOG,TC,80,F4,75,F5 +SELL_SHARE_LOG,Chester,10,SOU,70 +PRICE_MOVES_LOG,SOU,70,E5,65,E6 +START_COMPANY_LOG,Chester,NC,75,150,2,20,BANK +BUY_SHARE_LOG,Joshua,10,SOU,Pool,65 +BUY_SHARE_LOG,Rob,10,IC,IPO,65 +BUY_SHARE_LOG,Bob,10,SOU,Pool,65 +BUY_SHARE_LOG,Chester,10,GMO,IPO,90 +BUY_SHARE_LOG,Joshua,10,SOU,Pool,65 +BUY_SHARE_LOG,Rob,10,IC,IPO,65 +BUY_SHARE_LOG,Bob,10,SOU,Pool,65 +BUY_SHARE_LOG,Chester,10,NC,IPO,75 +BUY_SHARE_LOG,Joshua,10,TC,Pool,75 +BUY_SHARE_LOG,Rob,10,IC,IPO,65 +FloatsWithCash,IC,650 +BUY_SHARE_LOG,Bob,10,IC,IPO,65 +BUY_SHARE_LOG,Chester,10,NC,IPO,75 +SELL_SHARE_LOG,Chester,10,GMO,80 +PRICE_MOVES_LOG,GMO,80,D2,70,D3 +BUY_SHARE_LOG,Joshua,10,IC,IPO,65 +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,IC,IPO,65 +SELL_SHARES_LOG,Bob,2,10,20,IC,130 +PRICE_MOVES_LOG,IC,65,D4,55,D6 +BUY_SHARE_LOG,Chester,10,NC,IPO,75 +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,GMO,Pool,70 +BUY_SHARE_LOG,Chester,10,NC,IPO,75 +FloatsWithCash,NC,750 +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,NC,IPO,75 +Autopasses,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,NC,IPO,75 +SELL_SHARES_LOG,Bob,2,10,20,NC,150 +PRICE_MOVES_LOG,NC,75,E4,65,E6 +Autopasses,Chester +Autopasses,Joshua +Autopasses,Rob +SELL_SHARE_LOG,Bob,10,SOU,65 +PRICE_MOVES_LOG,SOU,65,E6,60,E7 +BUY_SHARE_LOG,Bob,10,L&N,Pool,80 +Autopasses,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,GMO,IPO,90 +Autopasses,Chester +Autopasses,Joshua +Autopasses,Rob +PASSES,Bob + +END_SR,5 +Has,GMO,340 +Has,IC,650 +Has,L&N,222 +Has,NC,750 +Has,SOU,51 +Has,TC,280 +Has,Bob,57 +Has,Chester,1 +Has,Joshua,3 +Has,Rob,19 +START_OR,5.1 +ReceivesFor,TC,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,TC,15,M&C +ReceivesFor,GMO,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,141,E10,SW +CompanyRevenue,L&N,110 +CompanyWithholds,L&N,110 +PRICE_MOVES_LOG,L&N,80,G5,75,F5 +BuysTrain,L&N,4,IPO,300 + +CompanyOperates,TC,Bob +LaysTileAt,TC,24,C12,NE +CompanyRevenue,TC,120 +CompanyPaysOutFull,TC,120 +Payout,Bob,60,5,10 +Payout,Joshua,12,1,10 +Payout,TC,12,1,10 +PRICE_MOVES_LOG,TC,75,F5,80,G5 +BuysTrain,TC,4,IPO,300 +All 4-trains are sold out, 5-trains now available + +CompanyOperates,GMO,Joshua +LaysTileAtFor,GMO,6,D7,NE,40 +LaysTileAt,GMO,8,C6,SE +CompanyRevenue,GMO,150 +CompanyPaysOutFull,GMO,150 +Payout,Bob,30,2,10 +Payout,Joshua,90,6,10 +PRICE_MOVES_LOG,GMO,70,D3,80,E3 + +CompanyOperates,NC,Chester +LaysTileAtFor,NC,8,H13,NW,60 +LaysTileAt,NC,9,G10,W +CompanyDoesNotPayDividend,NC +PRICE_MOVES_LOG,NC,65,E6,55,D6 +BuysTrain,NC,5,IPO,450 +FirstTrainBought,5 +StartOfPhase,5 +PrivateCloses,TCC +PrivateCloses,ET&WNC +PrivateCloses,M&C +PrivateCloses,O&W +BuysTrain,NC,3,SOU,240 + +CompanyOperates,SOU,Chester +LaysTileAt,SOU,24,B15,W +CompanyRevenue,SOU,170 +CompanyWithholds,SOU,170 +PRICE_MOVES_LOG,SOU,60,E7,50,D7 +BuysTrain,SOU,5,IPO,450 +All 5-trains are sold out, 6-trains now available + +CompanyOperates,IC,Rob +LaysTileAt,IC,619,D7,W +CompanyDoesNotPayDividend,IC +PRICE_MOVES_LOG,IC,55,D6,45,C6 +BuysTrain,IC,6,IPO,630 +FirstTrainBought,6 +StartOfPhase,6 + +EndOfOperatingRound,5.1 +ORWorthIncrease,Bob,5.1,110 +ORWorthIncrease,Chester,5.1,-115 +ORWorthIncrease,Joshua,5.1,137 +ORWorthIncrease,Rob,5.1,-80 +Has,GMO,320 +Has,IC,20 +Has,L&N,32 +Has,NC,0 +Has,SOU,21 +Has,TC,12 +Has,Bob,147 +Has,Chester,1 +Has,Joshua,105 +Has,Rob,19 +START_OR,5.2 + +CompanyOperates,TC,Bob +LaysTileAt,TC,170,F11,SW +CompanyRevenue,TC,190 +CompanyPaysOutFull,TC,190 +Payout,Bob,95,5,10 +Payout,Joshua,19,1,10 +Payout,TC,19,1,10 +PRICE_MOVES_LOG,TC,80,G5,85,G4 + +CompanyOperates,GMO,Joshua +LaysTileAt,GMO,14,G6,NW +LAYS_TOKEN_ON,GMO,D7,40 +CompanyDoesNotPayDividend,GMO +PRICE_MOVES_LOG,GMO,80,E3,70,D3 +PlayerMustSellShares,Joshua,226 +SELL_SHARES_LOG,Joshua,1,10,10,TC,85 +PRICE_MOVES_LOG,TC,85,G4,80,G5 +SELL_SHARES_LOG,Joshua,1,10,10,IC,45 +PRICE_MOVES_LOG,IC,45,C6,40,C7 +SELL_SHARES_LOG,Joshua,2,10,20,SOU,100 +PresidentAddsCash,GMO,Joshua,350 +BuysTrain,GMO,6,IPO,630 +All 6-trains are sold out, 8-trains now available +StartOfPhase,6½ + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,8,D9,SE +LaysTileAt,L&N,8,E18,NW +CompanyRevenue,L&N,190 +CompanyWithholds,L&N,190 +PRICE_MOVES_LOG,L&N,75,F5,70,E5 +TrainsObsoleteRusted,4,L&N +PlayerMustSellShares,Rob,459 +SELL_SHARES_LOG,Rob,2,10,20,IC,80 +SELL_SHARES_LOG,Rob,1,10,10,L&N,70 +PRICE_MOVES_LOG,L&N,70,E5,65,E6 +PlayerIsBankrupt,Rob +GameOver +EoGWinnerBob! +EoGFinalRanking : +1. 947 Bob +2. 646 Chester +3. 424 Joshua +4. 355 Rob commit 7cf721f93cdb3a54a8519feaf0085567627f5629 Author: Stefan Frey <ste...@we...> Date: Mon Jan 30 13:27:19 2012 +0100 updated readme.txt for 1.6.1 release diff --git a/readme.txt b/readme.txt index b6a6249..f26c93f 100644 --- a/readme.txt +++ b/readme.txt @@ -1,17 +1,18 @@ -Rails release 1.6.0: +Rails release 1.6.1: -This release celebrates that 1835 is declared fully playable. +A maintenance release for the 1.6.x branch. -Warning this release might not work with existing save files (see below). - -Contributors: Martin Brumm, Stefan Frey, Erik Vos, Frederick Weld +Contributors: Frederick Weld, Erik Vos +Bugs reported by Bill Probst. List of bugs fixed and further changes: -- 18EU: Fixed that share price could raise at the end of the merger round -- 1825: Update to Minors -- Background map: Fixed glitches at 18GA display -- All games: Fixes to make entering special tile lays more efficient -WARNING: The last fix might make existing save files unloadable. +- Enforced that the DynamicReportWindow stays on top during time warp +- Added background map for 1889 (courtesy of Frederick Weld) +- Fixed autosave functionality (handling of 18xx_autosave.xxx files) +- Fixed retrieval of default game options (if options pane was not opened) +- Fixed 1856 background map's mini-map (Windsor area) +- Enforce selling over-limit shares first +- Fixed wrong price of 6 train (630 => 600) in 18TN Note: To show a background map, the option has to be switched on in Configuration => Map/Report => Display background map. -Background maps are only available for 1856, 18EU, 18GA (incl. Cotton Port) and 18AL so far. +Background maps are only available for 1856, 1889, 18EU, 18GA (incl. Cotton Port) and 18AL so far. commit 4046342a471b3e672276d27138f9cc67713db8f2 Author: Stefan Frey <ste...@we...> Date: Sun Jan 29 16:57:51 2012 +0100 Fixed wrong price of 6 train (630 => 600) Reported by Bob Probst (cherry picked from commit 18c9e92b41cbbf6d2c386682c4354b0a485bd7c8) diff --git a/data/18TN/Game.xml b/data/18TN/Game.xml index 191ee87..62f3209 100644 --- a/data/18TN/Game.xml +++ b/data/18TN/Game.xml @@ -79,7 +79,7 @@ <TrainType name="5" majorStops="5" cost="450" quantity="2"> <NewPhase phaseName="5"/> </TrainType> - <TrainType name="6" majorStops="6" cost="630" quantity="2"> + <TrainType name="6" majorStops="6" cost="600" quantity="2"> <NewPhase phaseName="6"/> <NewPhase phaseName="6½" trainIndex="2"/> </TrainType> commit 2874b608449471d3e4615e46f1729696b07a0c75 Author: Erik Vos <eri...@xs...> Date: Fri Jan 6 16:51:04 2012 +0100 Enforce selling over-limit shares first. Being over limits was announced but immediate selling was not enforced.(cherry picked from commit 73886c53437f48e72a2bc3868d075be322e4ddbd) Conflicts: rails/game/StockRound.java diff --git a/rails/game/StockRound.java b/rails/game/StockRound.java index 03bb17a..037d2cc 100644 --- a/rails/game/StockRound.java +++ b/rails/game/StockRound.java @@ -58,6 +58,10 @@ public class StockRound extends Round { protected int sequenceRule; protected boolean raiseIfSoldOut = false; + /* Temporary variables */ + protected boolean isOverLimits = false; + protected String overLimitsDetail = null; + /** * Constructor with the GameManager, will call super class (Round's) Constructor to initialize * @@ -113,13 +117,9 @@ public class StockRound extends Round { setSellableShares(); - // check certification limits and display warning - if (isPlayerOverLimits (currentPlayer)) { - DisplayBuffer.add(LocalText.getText("ExceedCertificateLimit" - , currentPlayer.getName() - , isPlayerOverLimitsDetail(currentPlayer) - ) - ); + // Certificate limits must be obeyed by selling excess shares + // before any other action is allowed. + if (isOverLimits) { return true; } @@ -355,6 +355,7 @@ public class StockRound extends Round { * @return List of sellable certificates. */ public void setSellableShares() { + if (!mayCurrentPlayerSellAnything()) return; String compName; @@ -365,6 +366,9 @@ public class StockRound extends Round { int extraSingleShares = 0; boolean choiceOfPresidentExchangeCerts = false; Portfolio playerPortfolio = currentPlayer.getPortfolio(); + isOverLimits = false; + overLimitsDetail = null; + StringBuilder violations = new StringBuilder(); /* * First check of which companies the player owns stock, and what @@ -386,6 +390,22 @@ public class StockRound extends Round { - pool.getShare(company)); if (maxShareToSell == 0) continue; + // Is player over the hold limit of this company? + if (!checkAgainstHoldLimit(currentPlayer, company, 0)) { + // The first time this happens, remove all non-over-limits sell options + if (!isOverLimits) possibleActions.clear(); + isOverLimits = true; + violations.append(LocalText.getText("ExceedCertificateLimitCompany", + company.getName(), + playerPortfolio.getShare(company), + getGameParameterAsInt(GameDef.Parm.PLAYER_SHARE_LIMIT) + )); + + } else { + // If within limits, but an over-limits situation exists: correct that first. + if (isOverLimits) continue; + } + /* * If the current Player is president, check if he can dump the * presidency onto someone else. @@ -483,6 +503,23 @@ public class StockRound extends Round { } } } + + // Is player over the total certificate hold limit? + float certificateCount = playerPortfolio.getCertificateCount(); + int certificateLimit = gameManager.getPlayerCertificateLimit(currentPlayer); + if (certificateCount > certificateLimit) { + violations.append(LocalText.getText("ExceedCertificateLimitTotal", + certificateCount, + certificateLimit)); + isOverLimits = true; + } + + if (isOverLimits) { + DisplayBuffer.add(LocalText.getText("ExceedCertificateLimit" + , currentPlayer.getName() + , violations.toString() + )); + } } protected void setSpecialActions() { @@ -1431,7 +1468,6 @@ public class StockRound extends Round { hasSoldThisTurnBeforeBuying.set(false); hasActed.set(false); if (currentPlayer == startingPlayer) ReportBuffer.add(""); - } /** @@ -1489,44 +1525,31 @@ public class StockRound extends Round { /** * Can the current player do any buying? + * <p>Note: requires sellable shares to be checked BEFORE buyable shares * * @return True if any buying is allowed. */ public boolean mayCurrentPlayerBuyAnything() { - return !isPlayerOverLimits(currentPlayer) - && companyBoughtThisTurnWrapper.get() == null; + return !isOverLimits && companyBoughtThisTurnWrapper.get() == null; } + // Only used now to check if Autopass must be reset. protected boolean isPlayerOverLimits(Player player) { - return (isPlayerOverLimitsDetail(player) != null); - } - - protected String isPlayerOverLimitsDetail(Player player) { - StringBuffer violations = new StringBuffer(); // Over the total certificate hold Limit? if (player.getPortfolio().getCertificateCount() > gameManager.getPlayerCertificateLimit(player)) { - violations.append(LocalText.getText("ExceedCertificateLimitTotal", - player.getPortfolio().getCertificateCount(), - gameManager.getPlayerCertificateLimit(player))); + return true; } // Over the hold limit of any company? for (PublicCompanyI company : companyManager.getAllPublicCompanies()) { if (company.hasStarted() && company.hasStockPrice() && !checkAgainstHoldLimit(player, company, 0)) { - violations.append(LocalText.getText("ExceedCertificateLimitCompany", - company.getName(), - player.getPortfolio().getShare(company), - getGameParameterAsInt(GameDef.Parm.PLAYER_SHARE_LIMIT) - )); + return true; } } - if (violations.length() != 0) { - return violations.toString(); - } else { - return null; - } + + return false; } /** commit a7ec76db12bc2ee97839234cbfeab103d282e502 Author: Frederick Weld <fre...@gm...> Date: Sun Jan 1 07:01:15 2012 +0100 Fixed 1856 background map's mini-map (Windsor area) (cherry picked from commit c873a449f712e7934e80a467069af09807e0dd05) diff --git a/data/1856/MapImage.svg b/data/1856/MapImage.svg index 01dda31..595254a 100644 --- a/data/1856/MapImage.svg +++ b/data/1856/MapImage.svg @@ -150,12 +150,12 @@ inkscape:cx="2556" inkscape:cy="1957.5" inkscape:document-units="px" - inkscape:current-layer="layer3" + inkscape:current-layer="layer6" showgrid="false" inkscape:object-nodes="false" inkscape:window-width="1737" inkscape:window-height="1047" - inkscape:window-x="1452" + inkscape:window-x="172" inkscape:window-y="-11" inkscape:window-maximized="1" borderlayer="true" @@ -1558,6 +1558,16 @@ d="m 1316.1025,687.05754 c 11.3544,-9.50442 24.1951,-17.25146 37.7619,-23.13985 6.2666,-1.10258 11.5539,-4.50634 15.843,-9.11459 5.1019,-4.93631 11.9991,-7.33276 17.1024,-12.28326 3.9779,-3.49579 7.8596,-7.15447 12.7095,-9.4214 6.6475,-3.43833 12.4263,-8.89027 20.0869,-9.98548 6.6565,-1.63694 13.7417,-0.0944 20.2432,-2.34671" id="path3981" inkscape:connector-curvature="0" /> + <path + style="fill:#ffeaea;fill-opacity:1;stroke:none" + d="m 777.21379,820.08532 c -0.51563,-0.18361 -4.45313,-1.69384 -8.75,-3.35606 -4.29688,-1.66222 -10.20313,-3.49521 -13.125,-4.0733 -6.3968,-1.26562 -7.98154,-2.16641 -12.99328,-7.38562 -5.83181,-6.07323 -6.47767,-9.05655 -3.1495,-14.54801 2.4301,-4.00964 5.77457,-5.97601 12.52268,-7.36267 7.54706,-1.55084 10.51302,-1.32889 15.72195,1.1765 2.47731,1.19154 6.53809,2.51521 9.02396,2.94149 l 4.51977,0.77505 -0.16654,15.96477 c -0.16114,15.44732 -0.20706,15.9686 -1.41654,16.08323 -0.6875,0.0652 -1.67188,-0.0318 -2.1875,-0.21538 z" + id="path4752" + inkscape:connector-curvature="0" /> + <path + style="fill:#ffeaea;fill-opacity:1;stroke:none" + d="" + id="path4754" + inkscape:connector-curvature="0" /> </g> <g inkscape:groupmode="layer" commit f3ee09a2da26efc14456164b39e4e7651b61d520 Author: frederickweld <fre...@gm...> Date: Tue Dec 27 19:41:21 2011 +0100 Fixed retrieval of default game options (if options pane was not opened) Game options have to be read from GamesList.xml and not from the respective game's Games.xml GameOption tags. Before the fix, this was not the case if the options pane had not been opened (which is the moment at which the GamesList's default options were loaded). This fix also solves Bug 3448429, as the reported missing 18EU route calculation was due to inconsistent defaulting between GamesList (default=suggest) and Games (default=deactivate). Now, the defaults are always taken from GamesList. (cherry picked from commit ee46d990d508904fc6a542f20f8b4c30c53f4203) diff --git a/rails/ui/swing/GameSetupWindow.java b/rails/ui/swing/GameSetupWindow.java index 3f282b1..d9652ec 100644 --- a/rails/ui/swing/GameSetupWindow.java +++ b/rails/ui/swing/GameSetupWindow.java @@ -477,10 +477,11 @@ public class GameSetupWindow extends JDialog implements ActionListener { log.info("Game option " + option.getName() + " set to " + value); } } else { - // No options selected: take the defaults GameOption option; String value; + // No options selected: take the defaults (from the games list!) + availableOptions = this.getSelectedGameInfo().getOptions(); for (int i = 0; i < availableOptions.size(); i++) { option = availableOptions.get(i); value = option.getDefaultValue(); commit 34107056b41e4dab439f4399d91d9d887aeeeeb6 Author: frederickweld <fre...@gm...> Date: Tue Dec 27 17:48:19 2011 +0100 Fixed autosave functionality (handling of 18xx_autosave.xxx files) Target design is that (1) new temp file (.tmp) is created (2) former autosave (.rails) becomes the backup autosave (.rails.bak) (3) temp file (.tmp) becomes the new autosave (.rails) Prior to the fix, the implementation did not process step (2) correctly, as backup autosaves were never dropped. This meant that autosave resulted in an error message and three files in the autosave folder (.tmp , .rails , .rails.bak). That's why autosave had never worked for me (and I doubt that it could have worked for others). (cherry picked from commit 9d832d70a9f91944f1e1d8fba124f97c00f097cd) diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java index 8507931..f514d1a 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -1101,7 +1101,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { // rename the temp file to the recover file File recoveryFile = null; - boolean result; + boolean result = false; try { log.debug("Created temporary recovery file, path = " + tempFile.getPath()); // check if previous save file exists @@ -1110,11 +1110,12 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { if (recoveryFile.exists()) { log.debug("Potential recovery filePath = " + recoveryFile.getPath()); File backupFile = new File(filePath + ".bak"); - if (recoveryFile.renameTo(backupFile)) { - result = tempFile.renameTo(recoveryFile); - } else { - result = backupFile.renameTo(recoveryFile); - } + //delete backup file if existing + if (backupFile.exists()) backupFile.delete(); + //old recovery file becomes new backup file + recoveryFile.renameTo(backupFile); + //temp file becomes new recoveryFile + result = tempFile.renameTo(recoveryFile); } else { log.debug("Tries to rename temporary file"); result = tempFile.renameTo(recoveryFile); commit 00422b053131be30abc147f1c7ac5924044dcd33 Author: frederickweld <fre...@gm...> Date: Mon Dec 26 09:29:41 2011 +0100 1889: Aligned hex tooltip with style of background map The background map displays all names in Kanji and Romaji (latin alphabet). However, the hex tooltip only displayed the Romaji. Hence, the Kanji have been added to the Map.xml. (cherry picked from commit b26560a6877bcff52d78bdd686f86a06174bf879) diff --git a/data/1889/Map.xml b/data/1889/Map.xml index 19ea9a4..2f42650 100644 --- a/data/1889/Map.xml +++ b/data/1889/Map.xml @@ -1,72 +1,72 @@ <Map tileOrientation="NS" letterOrientation="horizontal" even="A"> <Image file="1889/MapImage.svg" x="6" y="5" scale="0.1632" /> <Hex name="A8" tile="0" cost="80"/> - <Hex name="A10" tile="-10" city="Sukomo"/> + <Hex name="A10" tile="-10" city="宿毛 - Sukomo"/> - <Hex name="B3" tile="-89030" orientation="0" city="Yawatahama"/> <!--NEW TILE:-890030--> + <Hex name="B3" tile="-89030" orientation="0" city="八幡浜 - Yawatahama"/> <!--NEW TILE:-890030--> <Hex name="B5" tile="0"/> - <Hex name="B7" tile="-89511" orientation="0" city="Uwajima"/> <!--NEW TILE:-89511--> + <Hex name="B7" tile="-89511" orientation="0" city="宇和島 - Uwajima"/> <!--NEW TILE:-89511--> <Hex name="B9" tile="0" cost="80"/> - <Hex name="B11" tile="-1" city="Nakamura"/> + <Hex name="B11" tile="-1" city="中村 - Nakamura"/> - <Hex name="C4" tile="-89115" orientation="0" city="Ohzu"/> + <Hex name="C4" tile="-89115" orientation="0" city="大洲 - Ohzu"/> <Hex name="C6" tile="0" cost="80"/> <Hex name="C8" tile="0"/> - <Hex name="C10" tile="-10" city="Kubokawa"/> + <Hex name="C10" tile="-10" city="窪川 - Kubokawa"/> <Hex name="D3" tile="0"/> <Hex name="D5" tile="0" cost="80"/> <Hex name="D7" tile="0" cost="80"/> <Hex name="D9" tile="0"/> - <Hex name="E2" tile="-10" city="Matsuyama"/> + <Hex name="E2" tile="-10" city="松山 - Matsuyama"/> <Hex name="E4" tile="0" cost="80"/> <Hex name="E6" tile="0" cost="80"/> <Hex name="E8" tile="0"/> - <Hex name="F1" tile="-902" orientation="2" value="30,60" city="Imabari"> + <Hex name="F1" tile="-902" orientation="2" value="30,60" city="今治 - Imabari"> <RevenueBonus value="40"> <Vertex id="-1"/> <Train type="D"/> </RevenueBonus> </Hex> - <Hex name="F3" tile="-10" city="Saijou"/> + <Hex name="F3" tile="-10" city="西條 - Saijou"/> <Hex name="F5" tile="0" cost="80"/> <Hex name="F7" tile="0" cost="80"/> - <Hex name="F9" tile="-89015" orientation="0" city="Kouchi" cost="80"/> <!--NEW TILE:-89015--> + <Hex name="F9" tile="-89015" orientation="0" city="高知 - Kouchi" cost="80"/> <!--NEW TILE:-89015--> - <Hex name="G4" tile="-10" city="Niihama"/> + <Hex name="G4" tile="-10" city="新居浜 - Niihama"/> <Hex name="G6" tile="0" cost="80"/> <Hex name="G8" tile="0" cost="80"/> - <Hex name="G10" tile="-1" city="Nangoku"/> - <Hex name="G12" tile="-10" city="Nahari"/> - <Hex name="G14" tile="-89031" orientation="0" city="Muroto"/> <!--NEW TILE:-890031--> + <Hex name="G10" tile="-1" city="南国 - Nangoku"/> + <Hex name="G12" tile="-10" city="奈半利 - Nahari"/> + <Hex name="G14" tile="-89031" orientation="0" city="室戸 - Muroto"/> <!--NEW TILE:-890031--> <Hex name="H3" tile="0"/> <Hex name="H5" tile="0" cost="80" label="River"/> - <Hex name="H7" tile="-10" city="Ikeda"/> + <Hex name="H7" tile="-10" city="池田 - Ikeda"/> <Hex name="H9" tile="0" cost="80"/> <Hex name="H11" tile="0" cost="80"/> <Hex name="H13" tile="0" cost="80"/> - <Hex name="I2" tile="-10" city="Marugame"/> - <Hex name="I4" tile="-89010" orientation="0" city="Kotohira" cost="80,80,80"/> <!-- NEW TILE: -89010 --> + <Hex name="I2" tile="-10" city="丸亀 - Marugame"/> + <Hex name="I4" tile="-89010" orientation="0" city="琴平 - Kotohira" cost="80,80,80"/> <!-- NEW TILE: -89010 --> <Hex name="I6" tile="0" cost="80" label="River"/> <Hex name="I8" tile="0"/> <Hex name="I10" tile="0"/> - <Hex name="I12" tile="-1" city="Muki"/> + <Hex name="I12" tile="-1" city="牟岐 - Muki"/> - <Hex name="J1" tile="-902" orientation="2" value="20,40" city="Sakaide & Okoyama"> + <Hex name="J1" tile="-902" orientation="2" value="20,40" city="坂出 & 岡山 - Sakaide & Okoyama"> <RevenueBonus value="40"> <Vertex id="-1"/> <Train type="D"/> </RevenueBonus> </Hex> <Hex name="J3" tile="0"/> - <Hex name="J5" tile="-1" city="Ritsurin Kouen"/> + <Hex name="J5" tile="-1" city="栗林公園 - Ritsurin Kouen"/> <Hex name="J7" tile="-8" orientation="2" label="River"/> - <Hex name="J9" tile="-1" city="Komatsujima"/> - <Hex name="J11" tile="-10" city="Anan"/> + <Hex name="J9" tile="-1" city="小松島 - Komatsujima"/> + <Hex name="J11" tile="-10" city="阿南 - Anan"/> - <Hex name="K4" tile="-89012" orientation="0" city="Takamatsu"/> <!--NEW TILE: -89012--> + <Hex name="K4" tile="-89012" orientation="0" city="高松 - Takamatsu"/> <!--NEW TILE: -89012--> <Hex name="K6" tile="0" cost="80" lablel="River"/> - <Hex name="K8" tile="-10" city="Tokushima"/> + <Hex name="K8" tile="-10" city="徳島 - Tokushima"/> - <Hex name="L7" tile="-902" orientation="3" value="20,40" city="Naruto & Awaji"> + <Hex name="L7" tile="-902" orientation="3" value="20,40" city="鳴門 & 淡路 - Naruto & Awaji"> <RevenueBonus value="40"> <Vertex id="-1"/> <Train type="D"/> </RevenueBonus> </Hex> commit e616a2a37758dd90e9112d2d94e54db12df3d100 Author: frederickweld <fre...@gm...> Date: Sun Dec 25 13:16:31 2011 +0100 Added background map for 1889 (cherry picked from commit dc1a96cdf357f43cb8cf219eb14063bf7e77376a) diff --git a/data/1889/Map.xml b/data/1889/Map.xml index 68d38a4..19ea9a4 100644 --- a/data/1889/Map.xml +++ b/data/1889/Map.xml @@ -1,5 +1,6 @@ <Map tileOrientation="NS" letterOrientation="horizontal" even="A"> - <Hex name="A8" tile="0" cost="80"/> + <Image file="1889/MapImage.svg" x="6" y="5" scale="0.1632" /> + <Hex name="A8" tile="0" cost="80"/> <Hex name="A10" tile="-10" city="Sukomo"/> <Hex name="B3" tile="-89030" orientation="0" city="Yawatahama"/> <!--NEW TILE:-890030--> diff --git a/data/1889/MapImage.svg b/data/1889/MapImage.svg new file mode 100644 index 0000000..7e02ff2 --- /dev/null +++ b/data/1889/MapImage.svg @@ -0,0 +1,4259 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="3698" + height="2703" + id="svg2" + version="1.1" + inkscape:version="0.48.2 r9819" + sodipodi:docname="MapImage.svg"> + <defs + id="defs4"> + <linearGradient + id="linearGradient4411"> + <stop + style="stop-color:#3584cf;stop-opacity:0.27450982;" + offset="0" + id="stop4413" /> + <stop + style="stop-color:#3584cf;stop-opacity:1;" + offset="1" + id="stop4415" /> + </linearGradient> + <polygon + id="pt" + points="-0.16245985,0 0,-0.5 0.16245985,0 " + transform="scale(0.0616,0.0616)" + style="fill:#ffffff" /> + <g + id="star"> + <use + xlink:href="#pt" + transform="matrix(-0.80901699,-0.58778525,0.58778525,-0.80901699,0,0)" + id="use4787" + x="0" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#pt" + transform="matrix(0.30901699,-0.95105652,0.95105652,0.30901699,0,0)" + id="use4789" + x="0" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#pt" + id="use4791" + x="0" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#pt" + transform="matrix(0.30901699,0.95105652,-0.95105652,0.30901699,0,0)" + id="use4793" + x="0" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#pt" + transform="matrix(-0.80901699,0.58778525,-0.58778525,-0.80901699,0,0)" + id="use4795" + x="0" + y="0" + width="5112" + height="3915" /> + </g> + <g + id="s5"> + <use + xlink:href="#star" + x="-0.252" + id="use4798" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#star" + x="-0.126" + id="use4800" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#star" + id="use4802" + x="0" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#star" + x="0.126" + id="use4804" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#star" + x="0.252" + id="use4806" + y="0" + width="5112" + height="3915" /> + </g> + <g + id="s6"> + <use + xlink:href="#s5" + x="-0.063000001" + id="use4809" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#star" + x="0.315" + id="use4811" + y="0" + width="5112" + height="3915" /> + </g> + <g + id="x4"> + <use + xlink:href="#s6" + id="use4814" + x="0" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#s5" + y="0.054000001" + id="use4816" + x="0" + width="5112" + height="3915" /> + <use + xlink:href="#s6" + y="0.108" + id="use4818" + x="0" + width="5112" + height="3915" /> + <use + xlink:href="#s5" + y="0.162" + id="use4820" + x="0" + width="5112" + height="3915" /> + </g> + <g + id="u"> + <use + xlink:href="#x4" + y="-0.21600001" + id="use4823" + x="0" + width="5112" + height="3915" /> + <use + xlink:href="#x4" + id="use4825" + x="0" + y="0" + width="5112" + height="3915" /> + <use + xlink:href="#s6" + y="0.21600001" + id="use4827" + x="0" + width="5112" + height="3915" /> + </g> + <rect + id="stripe" + width="1235" + height="50" + x="0" + y="0" + style="fill:#b22234" /> + <inkscape:perspective + id="perspective64" + inkscape:persp3d-origin="479.5 : 197.66667 : 1" + inkscape:vp_z="959 : 296.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 296.5 : 1" + sodipodi:type="inkscape:persp3d" /> + <filter + inkscape:collect="always" + id="filter9017"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="5.4802153" + id="feGaussianBlur9019" /> + </filter> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient4411" + id="linearGradient4417" + x1="2255.0874" + y1="5269.3853" + x2="3294.2241" + y2="5269.3853" + gradientUnits="userSpaceOnUse" + spreadMethod="pad" /> + <filter + color-interpolation-filters="sRGB" + inkscape:collect="always" + id="filter23757"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="5.8877422" + id="feGaussianBlur23759" /> + </filter> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#ff6666" + borderopacity="1" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.28967814" + inkscape:cx="1386.4176" + inkscape:cy="1357.2216" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + inkscape:object-nodes="false" + inkscape:window-width="1737" + inkscape:window-height="1047" + inkscape:window-x="1452" + inkscape:window-y="-11" + inkscape:window-maximized="1" + borderlayer="true" + showguides="true" + inkscape:guide-bbox="true" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Geo" + style="display:inline" + transform="translate(0,-4297.3599)"> + <rect + style="fill:#a1c6e9;fill-opacity:1;stroke:none" + id="rect5187" + width="3698.0801" + height="2696.8806" + x="3.0000001e-007" + y="4303.4795" /> + <path + inkscape:connector-curvature="0" + style="fill:#348d4c;fill-opacity:1;stroke:#000000;stroke-width:5.95329189;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.86369991;stroke-dasharray:none" + d="m 2898.9121,4306.4953 1.7674,9.5811 -9.55,28.8052 -9.8292,13.3949 -0.5891,40.8669 16.1855,11.3175 7.8757,29.9214 c -0.6394,-27.5779 11.457,-47.6508 23.069,-72.6177 l 36.2469,-0.155 -1.2402,10.1391 c 15.4632,24.7539 22.6196,39.0043 29.0842,72.2457 l 14.6973,9.9222 -2.5427,16.4646 17.674,12.6817 15.5963,-15.5963 -6.7285,23.8441 12.9609,-2.9766 -0.1551,-7.6897 10.0151,-5.7362 -0.341,-15.3484 17.0228,-18.0769 4.4028,4.1239 21.3637,-17.7668 0.2481,11.5345 8.7129,0.5581 10.6663,-42.7583 c 11.6971,-14.5281 28.0225,-22.3652 41.58,-21.5497 l 9.023,15.9375 -8.2168,22.4798 4.8681,23.3481 7.0384,-8.4958 -3.3487,-21.9528 10.0151,-5.7363 4,-15.0692 c 7.5557,-8.7468 15.1742,-15.9748 24.2472,-18.8521 l 7.8137,26.1076 11.3485,-12.0306 4.527,7.9688 2.6976,-8.7749 5.7362,-2.1705 2.6355,-12.6197 15.5965,-15.5964 14.6351,6.0773 c 3.8592,-16.7652 7.2568,-33.6019 10.5114,-50.4479 l -2.6667,-5.3022 -122.8176,0 -2.0775,3.2557 -3.5037,-3.2557 -250.2554,0 z m 400.1108,0 -4.1858,11.4105 21.5186,-10.0772 5.9224,5.4882 c -12.5135,4.6136 -24.2009,14.4428 -32.6812,29.7975 l 6.2324,20.8675 15.9375,-0.217 -0.8992,25.5185 27.534,-0.7442 11.9066,14.8523 17.1776,-10.3563 11.6585,3.3177 11.2555,-15.8755 8.775,4.403 15.5963,-15.5654 0.4031,19.1932 18.914,2.5426 c 10.783,-13.934 23.9181,-22.66 37.1152,-25.6736 l -10.3563,-9.6431 7.9687,-34.0144 5.7363,-2.1704 7.8137,26.1076 18.573,-12.8368 -0.186,-7.6896 18.9761,6.3563 -3.0387,-6.5734 7.0695,-8.4959 4.5271,7.9688 20.1853,-3.7828 -5.8603,-14.1081 -243.5889,0 z m 248.426,0 6.6044,4.2789 3.5658,-4.2789 -10.1702,0 z m 18.201,0 1.3952,1.3023 3.4418,-1.3023 -4.837,0 z m 12.9608,0 0.093,4.62 6.4494,-4.62 -6.5423,0 z m 99.8416,0 1.9534,16.4646 15.5964,-4.9921 0,-11.4725 -17.5498,0 z m -47.1613,2044.8627 -5.6741,6.0154 -1.5504,-5.2091 -7.2245,0.8061 1.7364,12.8678 -7.1626,4.651 -11.8135,-11.0073 -7.1317,4.6199 4.8371,23.3481 -11.2554,15.8754 -7.3176,-3.0386 -1.2092,10.1392 35.0685,13.829 -1.3022,6.2944 c -13.9861,-1.3348 -28.8538,0.5228 -43.2854,8.6508 l -1.2403,10.1392 -28.9913,-0.6201 -4.2789,3.534 |
From: Erik V. <ev...@us...> - 2012-01-30 12:32:40
|
rails/ui/swing/GameStatus.java | 1 rails/ui/swing/GameUIManager.java | 3 rails/ui/swing/ORUIManager.java | 6 rails/ui/swing/StartRoundWindow.java | 4 rails/ui/swing/elements/CheckBoxDialog.java | 107 ++-------- rails/ui/swing/elements/MessageDialog.java | 78 ------- rails/ui/swing/elements/NonModalDialog.java | 137 ++++++++++++++ rails/ui/swing/elements/RadioButtonDialog.java | 110 ++--------- rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java | 6 rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java | 4 rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java | 5 rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java | 7 12 files changed, 208 insertions(+), 260 deletions(-) New commits: commit 423369599568b645e0a86cbc2dc7d028ee1c3a77 Author: Erik Vos <eri...@xs...> Date: Mon Jan 30 13:29:51 2012 +0100 Refactored nonmodal dialog classes II Added MessageDialog. diff --git a/rails/ui/swing/elements/CheckBoxDialog.java b/rails/ui/swing/elements/CheckBoxDialog.java index 9c30081..0a56e91 100644 --- a/rails/ui/swing/elements/CheckBoxDialog.java +++ b/rails/ui/swing/elements/CheckBoxDialog.java @@ -46,7 +46,7 @@ public class CheckBoxDialog extends NonModalDialog { } @Override - protected void initializeContent() { + protected void initializeInput() { checkBoxes = new JCheckBox[numOptions]; diff --git a/rails/ui/swing/elements/MessageDialog.java b/rails/ui/swing/elements/MessageDialog.java index 47e6353..e4bfe66 100644 --- a/rails/ui/swing/elements/MessageDialog.java +++ b/rails/ui/swing/elements/MessageDialog.java @@ -1,93 +1,21 @@ /* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/ui/swing/elements/MessageDialog.java,v 1.1 2010/01/19 19:49:39 evos Exp $*/ package rails.ui.swing.elements; -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; - -import org.apache.log4j.Logger; - -import rails.common.LocalText; +import javax.swing.JFrame; /** * A generic dialog for presenting choices by checkboxes. */ -public class MessageDialog extends JDialog implements ActionListener { +public class MessageDialog extends NonModalDialog { private static final long serialVersionUID = 1L; - protected DialogOwner owner = null; - GridBagConstraints gc; - JPanel optionsPane, buttonPane; - JButton okButton; - Dimension size, optSize; - - String message; - - protected static Logger log = - Logger.getLogger(MessageDialog.class.getPackage().getName()); - public MessageDialog(DialogOwner owner, JFrame window, String title, String message) { - super((Frame) null, title, false); // Non-modal - this.owner = owner; - this.message = message; + super (Type.MESSAGE, null, owner, window, title, message, false); initialize(); - pack(); - - // Center on window - int x = (int) window.getLocationOnScreen().getX() - + (window.getWidth() - getWidth()) / 2; - int y = (int) window.getLocationOnScreen().getY() - + (window.getHeight() - getHeight()) / 2; - setLocation(x, y); - - setVisible(true); - toFront(); - } - - private void initialize() { - gc = new GridBagConstraints(); - - optionsPane = new JPanel(); - buttonPane = new JPanel(); - - okButton = new JButton(LocalText.getText("OK")); - okButton.setMnemonic(KeyEvent.VK_O); - okButton.addActionListener(this); - buttonPane.add(okButton); - - getContentPane().setLayout(new GridBagLayout()); - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - - optionsPane.setLayout(new GridBagLayout()); - optionsPane.add(new JLabel(message), constraints(0, 0, 10, 10, 10, 10)); - - getContentPane().add(optionsPane, constraints(0, 0, 0, 0, 0, 0)); - getContentPane().add(buttonPane, constraints(0, 1, 0, 0, 0, 0)); - } - - private GridBagConstraints constraints(int gridx, int gridy, int leftinset, - int topinset, int rightinset, int bottominset) { - if (gridx >= 0) gc.gridx = gridx; - if (gridy >= 0) gc.gridy = gridy; - gc.fill = GridBagConstraints.BOTH; - gc.weightx = 0.5; - gc.weighty = 0.5; - if (leftinset >= 0) gc.insets.left = leftinset; - if (topinset >= 0) gc.insets.top = topinset; - if (rightinset >= 0) gc.insets.right = rightinset; - if (bottominset >= 0) gc.insets.bottom = bottominset; - - return gc; - } - public void actionPerformed(ActionEvent arg0) { - setVisible(false); - dispose(); - owner.dialogActionPerformed (); } } diff --git a/rails/ui/swing/elements/NonModalDialog.java b/rails/ui/swing/elements/NonModalDialog.java index fff6538..0fe730c 100644 --- a/rails/ui/swing/elements/NonModalDialog.java +++ b/rails/ui/swing/elements/NonModalDialog.java @@ -39,7 +39,8 @@ public abstract class NonModalDialog extends JDialog implements ActionListener { public static enum Type { CHECKBOX, RADIO, - MESSAGE + MESSAGE, + MIXED } protected static Logger log = @@ -83,7 +84,7 @@ public abstract class NonModalDialog extends JDialog implements ActionListener { optionsPane.setLayout(new GridBagLayout()); optionsPane.add(new JLabel(message), constraints(0, 0, 10, 10, 10, 10)); - initializeContent(); + initializeInput(); getContentPane().add(optionsPane, constraints(0, 0, 0, 0, 0, 0)); getContentPane().add(buttonPane, constraints(0, 1, 0, 0, 0, 0)); @@ -101,7 +102,8 @@ public abstract class NonModalDialog extends JDialog implements ActionListener { setAlwaysOnTop(true); } - protected abstract void initializeContent(); + protected void initializeInput() { + } protected GridBagConstraints constraints(int gridx, int gridy, int leftinset, int topinset, int rightinset, int bottominset) { @@ -129,7 +131,7 @@ public abstract class NonModalDialog extends JDialog implements ActionListener { owner.dialogActionPerformed (); } - protected abstract void processOK (ActionEvent actionEvent); + protected void processOK (ActionEvent actionEvent) {}; - protected abstract void processCancel (ActionEvent actionEvent); + protected void processCancel (ActionEvent actionEvent) {}; } diff --git a/rails/ui/swing/elements/RadioButtonDialog.java b/rails/ui/swing/elements/RadioButtonDialog.java index a40b1a7..1d7cc59 100644 --- a/rails/ui/swing/elements/RadioButtonDialog.java +++ b/rails/ui/swing/elements/RadioButtonDialog.java @@ -35,7 +35,7 @@ public class RadioButtonDialog extends NonModalDialog { } @Override - protected void initializeContent() { + protected void initializeInput() { choiceButtons = new JRadioButton[numOptions]; group = new ButtonGroup(); commit 3d8a7a01e36779e6cf92ce6ea54d720d621d496a Merge: 6716550 6f3e1b3 Author: Erik Vos <eri...@xs...> Date: Mon Jan 30 12:49:33 2012 +0100 Merge branch 'master' of ssh://rails.git.sourceforge.net/gitroot/rails/rails into nonmodal commit 6716550625b1eca8cac294f59c38418d690e44c5 Author: Erik Vos <eri...@xs...> Date: Wed Jan 25 14:18:29 2012 +0100 Refactored non-modal dialog classes. All are now subclasses of a new abstract class NonModalDialog, which contains most of the common code. diff --git a/rails/ui/swing/GameStatus.java b/rails/ui/swing/GameStatus.java index 3e30944..b15bd42 100644 --- a/rails/ui/swing/GameStatus.java +++ b/rails/ui/swing/GameStatus.java @@ -764,6 +764,7 @@ public class GameStatus extends GridPanel implements ActionListener { if (options.size() > 1) { if (startCompany) { RadioButtonDialog dialog = new RadioButtonDialog ( + NonModalDialog.Usage.COMPANY_START_PRICE, gameUIManager, parent, LocalText.getText("PleaseSelect"), diff --git a/rails/ui/swing/GameUIManager.java b/rails/ui/swing/GameUIManager.java index e50d32e..ae71267 100644 --- a/rails/ui/swing/GameUIManager.java +++ b/rails/ui/swing/GameUIManager.java @@ -620,7 +620,8 @@ public class GameUIManager implements DialogOwner { orWindow.setVisible(true); orWindow.toFront(); - CheckBoxDialog dialog = new CheckBoxDialog(this, + CheckBoxDialog dialog = new CheckBoxDialog(NonModalDialog.Usage.EXCHANGE_TOKENS, + this, orWindow, LocalText.getText("ExchangeTokens"), prompt, diff --git a/rails/ui/swing/ORUIManager.java b/rails/ui/swing/ORUIManager.java index db96ac7..b31dd09 100644 --- a/rails/ui/swing/ORUIManager.java +++ b/rails/ui/swing/ORUIManager.java @@ -547,7 +547,8 @@ public class ORUIManager implements DialogOwner { orWindow.setVisible(true); orWindow.toFront(); - CheckBoxDialog dialog = new CheckBoxDialog(this, + CheckBoxDialog dialog = new CheckBoxDialog(NonModalDialog.Usage.SELECT_DESTINATION_COMPANIES, + this, orWindow, LocalText.getText("DestinationsReached"), LocalText.getText("DestinationsReachedPrompt"), @@ -1462,7 +1463,8 @@ public class ORUIManager implements DialogOwner { Bank.format(i * loanAmount)); } } - RadioButtonDialog currentDialog = new RadioButtonDialog (gameUIManager, + RadioButtonDialog currentDialog = new RadioButtonDialog (NonModalDialog.Usage.REPAY_LOANS, + gameUIManager, orWindow, LocalText.getText("Select"), LocalText.getText("SelectLoansToRepay", action.getCompanyName()), diff --git a/rails/ui/swing/StartRoundWindow.java b/rails/ui/swing/StartRoundWindow.java index 4cf1b88..1b9af8a 100644 --- a/rails/ui/swing/StartRoundWindow.java +++ b/rails/ui/swing/StartRoundWindow.java @@ -648,7 +648,9 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { options[i] = Bank.format(spacePerPrice.get(startPrices[i]).getPrice()); } - RadioButtonDialog dialog = new RadioButtonDialog(this, + RadioButtonDialog dialog = new RadioButtonDialog( + NonModalDialog.Usage.COMPANY_START_PRICE, + this, this, LocalText.getText("PleaseSelect"), LocalText.getText("WHICH_START_PRICE", diff --git a/rails/ui/swing/elements/CheckBoxDialog.java b/rails/ui/swing/elements/CheckBoxDialog.java index 910180c..9c30081 100644 --- a/rails/ui/swing/elements/CheckBoxDialog.java +++ b/rails/ui/swing/elements/CheckBoxDialog.java @@ -1,26 +1,18 @@ /* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/ui/swing/elements/CheckBoxDialog.java,v 1.9 2010/06/16 20:59:10 evos Exp $*/ package rails.ui.swing.elements; -import java.awt.*; -import java.awt.event.*; +import java.awt.Dimension; +import java.awt.event.ActionEvent; import javax.swing.*; -import org.apache.log4j.Logger; - -import rails.common.LocalText; - /** * A generic dialog for presenting choices by checkboxes. */ -public class CheckBoxDialog extends JDialog implements ActionListener { +public class CheckBoxDialog extends NonModalDialog { private static final long serialVersionUID = 1L; - protected DialogOwner owner = null; - GridBagConstraints gc; - JPanel optionsPane, buttonPane; - JButton okButton, cancelButton; JCheckBox[] checkBoxes; Dimension size, optSize; ButtonGroup group; @@ -32,22 +24,18 @@ public class CheckBoxDialog extends JDialog implements ActionListener { int chosenOption = -1; boolean hasCancelButton = false; - protected static Logger log = - Logger.getLogger(CheckBoxDialog.class.getPackage().getName()); - - public CheckBoxDialog(DialogOwner owner, JFrame window, String title, String message, + public CheckBoxDialog(Usage usage, DialogOwner owner, JFrame window, String title, String message, String[] options) { - this (owner, window, title, message, options, null, false); + this (usage, owner, window, title, message, options, null, false); } - public CheckBoxDialog(DialogOwner owner, JFrame window, String title, String message, + public CheckBoxDialog(Usage usage, DialogOwner owner, JFrame window, String title, String message, String[] options, boolean[] selectedOptions, boolean addCancelButton) { - super((Frame) null, title, false); // Non-modal - this.owner = owner; - this.message = message; + + super (Type.CHECKBOX, usage, owner, window, title, message, addCancelButton); + this.options = options; this.numOptions = options.length; - this.hasCancelButton = addCancelButton; if (selectedOptions != null) { this.selectedOptions = selectedOptions; } else { @@ -55,84 +43,31 @@ public class CheckBoxDialog extends JDialog implements ActionListener { } initialize(); - pack(); - - // Center on owner - int x = (int) window.getLocationOnScreen().getX() - + (window.getWidth() - getWidth()) / 2; - int y = (int) window.getLocationOnScreen().getY() - + (window.getHeight() - getHeight()) / 2; - setLocation(x, y); - - setVisible(true); - setAlwaysOnTop(true); } - private void initialize() { - gc = new GridBagConstraints(); - - optionsPane = new JPanel(); - buttonPane = new JPanel(); - - okButton = new JButton(LocalText.getText("OK")); - okButton.setMnemonic(KeyEvent.VK_O); - okButton.addActionListener(this); - buttonPane.add(okButton); - - if (hasCancelButton) { - cancelButton = new JButton(LocalText.getText("Cancel")); - cancelButton.setMnemonic(KeyEvent.VK_C); - cancelButton.addActionListener(this); - buttonPane.add(cancelButton); - } - - checkBoxes = new JCheckBox[numOptions]; - - getContentPane().setLayout(new GridBagLayout()); - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - - optionsPane.setLayout(new GridBagLayout()); - optionsPane.add(new JLabel(message), constraints(0, 0, 10, 10, 10, 10)); + @Override + protected void initializeContent() { checkBoxes = new JCheckBox[numOptions]; for (int i = 0; i < numOptions; i++) { checkBoxes[i] = - new JCheckBox(options[i], selectedOptions[i]); + new JCheckBox(options[i], selectedOptions[i]); optionsPane.add(checkBoxes[i], constraints(0, 1 + i, 0, 0, 0, 0)); - checkBoxes[i].setPreferredSize(size); + //checkBoxes[i].setPreferredSize(size); } - - getContentPane().add(optionsPane, constraints(0, 0, 0, 0, 0, 0)); - getContentPane().add(buttonPane, constraints(0, 1, 0, 0, 0, 0)); } - private GridBagConstraints constraints(int gridx, int gridy, int leftinset, - int topinset, int rightinset, int bottominset) { - if (gridx >= 0) gc.gridx = gridx; - if (gridy >= 0) gc.gridy = gridy; - gc.fill = GridBagConstraints.BOTH; - gc.weightx = 0.5; - gc.weighty = 0.5; - if (leftinset >= 0) gc.insets.left = leftinset; - if (topinset >= 0) gc.insets.top = topinset; - if (rightinset >= 0) gc.insets.right = rightinset; - if (bottominset >= 0) gc.insets.bottom = bottominset; - - return gc; + @Override + protected void processOK (ActionEvent actionEvent) { + for (int i = 0; i < numOptions; i++) { + selectedOptions[i] = checkBoxes[i].isSelected(); + } } - public void actionPerformed(ActionEvent arg0) { - if (arg0.getSource().equals(okButton)) { - for (int i = 0; i < numOptions; i++) { - selectedOptions[i] = checkBoxes[i].isSelected(); - } - } else if (arg0.getSource().equals(cancelButton)) { - // return; - } - setVisible(false); - dispose(); - owner.dialogActionPerformed (); + @Override + protected void processCancel (ActionEvent actionEvent) { + } public String[] getOptions () { diff --git a/rails/ui/swing/elements/NonModalDialog.java b/rails/ui/swing/elements/NonModalDialog.java new file mode 100644 index 0000000..fff6538 --- /dev/null +++ b/rails/ui/swing/elements/NonModalDialog.java @@ -0,0 +1,135 @@ +package rails.ui.swing.elements; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; + +import org.apache.log4j.Logger; + +import rails.common.LocalText; + +public abstract class NonModalDialog extends JDialog implements ActionListener { + + private static final long serialVersionUID = 1L; + + protected Type type; + protected Usage usage; + protected DialogOwner owner = null; + protected JFrame window = null; + protected String message; + protected boolean hasCancelButton = false; + + GridBagConstraints gc; + JPanel optionsPane, buttonPane; + JButton okButton, cancelButton; + + public static enum Usage { + REPAY_LOANS, + DESTINATION_REACHED, + BUY_WHICH_TRAIN, + COMPANY_START_PRICE, + EXCHANGE_TOKENS, + SELECT_FOLDING_COMPANIES, + SELECT_DESTINATION_COMPANIES, + SELECT_COMPANY, + SELECT_HOME_STATION + } + + public static enum Type { + CHECKBOX, + RADIO, + MESSAGE + } + + protected static Logger log = + Logger.getLogger(NonModalDialog.class.getPackage().getName()); + + public NonModalDialog(Type type, Usage usage, + DialogOwner owner, JFrame window, String title, String message, + boolean addCancelButton) { + + super((Frame) null, title, false); // Non-modal + this.type = type; + this.usage = usage; + this.owner = owner; + this.window = window; + this.message = message; + hasCancelButton = addCancelButton; + } + + protected final void initialize() { + + gc = new GridBagConstraints(); + + optionsPane = new JPanel(); + buttonPane = new JPanel(); + + okButton = new JButton(LocalText.getText("OK")); + okButton.setMnemonic(KeyEvent.VK_O); + okButton.addActionListener(this); + buttonPane.add(okButton); + + if (hasCancelButton) { + cancelButton = new JButton(LocalText.getText("Cancel")); + cancelButton.setMnemonic(KeyEvent.VK_C); + cancelButton.addActionListener(this); + buttonPane.add(cancelButton); + } + + getContentPane().setLayout(new GridBagLayout()); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + optionsPane.setLayout(new GridBagLayout()); + optionsPane.add(new JLabel(message), constraints(0, 0, 10, 10, 10, 10)); + + initializeContent(); + + getContentPane().add(optionsPane, constraints(0, 0, 0, 0, 0, 0)); + getContentPane().add(buttonPane, constraints(0, 1, 0, 0, 0, 0)); + + pack(); + + // Center on owner + int x = (int) window.getLocationOnScreen().getX() + + (window.getWidth() - getWidth()) / 2; + int y = (int) window.getLocationOnScreen().getY() + + (window.getHeight() - getHeight()) / 2; + setLocation(x, y); + + setVisible(true); + setAlwaysOnTop(true); + } + + protected abstract void initializeContent(); + + protected GridBagConstraints constraints(int gridx, int gridy, int leftinset, + int topinset, int rightinset, int bottominset) { + if (gridx >= 0) gc.gridx = gridx; + if (gridy >= 0) gc.gridy = gridy; + gc.fill = GridBagConstraints.BOTH; + gc.weightx = 0.5; + gc.weighty = 0.5; + if (leftinset >= 0) gc.insets.left = leftinset; + if (topinset >= 0) gc.insets.top = topinset; + if (rightinset >= 0) gc.insets.right = rightinset; + if (bottominset >= 0) gc.insets.bottom = bottominset; + + return gc; + } + + public void actionPerformed(ActionEvent actionEvent) { + if (actionEvent.getSource().equals(okButton)) { + processOK(actionEvent); + } else if (actionEvent.getSource().equals(cancelButton)) { + processCancel (actionEvent); + } + setVisible(false); + dispose(); + owner.dialogActionPerformed (); + } + + protected abstract void processOK (ActionEvent actionEvent); + + protected abstract void processCancel (ActionEvent actionEvent); +} diff --git a/rails/ui/swing/elements/RadioButtonDialog.java b/rails/ui/swing/elements/RadioButtonDialog.java index 5041ed5..a40b1a7 100644 --- a/rails/ui/swing/elements/RadioButtonDialog.java +++ b/rails/ui/swing/elements/RadioButtonDialog.java @@ -1,133 +1,67 @@ /* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/ui/swing/elements/RadioButtonDialog.java,v 1.8 2010/01/31 22:22:34 macfreek Exp $*/ package rails.ui.swing.elements; -import java.awt.*; -import java.awt.event.*; +import java.awt.Dimension; +import java.awt.event.ActionEvent; import javax.swing.*; -import org.apache.log4j.Logger; - -import rails.common.LocalText; - /** * A generic dialog for presenting choices by radio buttons. */ -public class RadioButtonDialog extends JDialog implements ActionListener { +public class RadioButtonDialog extends NonModalDialog { private static final long serialVersionUID = 1L; - GridBagConstraints gc; - JPanel optionsPane, buttonPane; - JButton okButton, cancelButton; + JRadioButton[] choiceButtons; Dimension size, optSize; ButtonGroup group; - DialogOwner owner; - String message; int numOptions; String[] options; int selectedOption; int chosenOption = -1; - protected static Logger log = - Logger.getLogger(RadioButtonDialog.class.getPackage().getName()); - - public RadioButtonDialog(DialogOwner owner, JFrame window, String title, String message, + public RadioButtonDialog(Usage usage, DialogOwner owner, JFrame window, String title, String message, String[] options, int selectedOption) { - super((Frame) null, title, false); // Non-modal - this.owner = owner; - this.message = message; + + super (Type.RADIO, usage, owner, window, title, message, selectedOption < 0); + this.options = options; this.numOptions = options.length; this.selectedOption = selectedOption; initialize(); - pack(); - - // Center on window - int x = (int) window.getLocationOnScreen().getX() - + (window.getWidth() - getWidth()) / 2; - int y = (int) window.getLocationOnScreen().getY() - + (window.getHeight() - getHeight()) / 2; - setLocation(x, y); - - setVisible(true); - setAlwaysOnTop(true); } - private void initialize() { - gc = new GridBagConstraints(); - - optionsPane = new JPanel(); - buttonPane = new JPanel(); - - okButton = new JButton(LocalText.getText("OK")); - okButton.setMnemonic(KeyEvent.VK_O); - okButton.addActionListener(this); - buttonPane.add(okButton); - - if (selectedOption < 0) { - // If an option has been preselected, selection is mandatory. - cancelButton = new JButton(LocalText.getText("Cancel")); - cancelButton.setMnemonic(KeyEvent.VK_C); - cancelButton.addActionListener(this); - buttonPane.add(cancelButton); - } - - choiceButtons = new JRadioButton[numOptions]; - - getContentPane().setLayout(new GridBagLayout()); - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - - optionsPane.setLayout(new GridBagLayout()); - // optionsPane.setBorder(BorderFactory.createLoweredBevelBorder()); - optionsPane.add(new JLabel(message), constraints(0, 0, 10, 10, 10, 10)); + @Override + protected void initializeContent() { choiceButtons = new JRadioButton[numOptions]; group = new ButtonGroup(); for (int i = 0; i < numOptions; i++) { choiceButtons[i] = - new JRadioButton(options[i], i == selectedOption); + new JRadioButton(options[i], i == selectedOption); optionsPane.add(choiceButtons[i], constraints(0, 1 + i, 0, 0, 0, 0)); choiceButtons[i].setPreferredSize(size); group.add(choiceButtons[i]); } - - getContentPane().add(optionsPane, constraints(0, 0, 0, 0, 0, 0)); - getContentPane().add(buttonPane, constraints(0, 1, 0, 0, 0, 0)); } - private GridBagConstraints constraints(int gridx, int gridy, int leftinset, - int topinset, int rightinset, int bottominset) { - if (gridx >= 0) gc.gridx = gridx; - if (gridy >= 0) gc.gridy = gridy; - gc.fill = GridBagConstraints.BOTH; - gc.weightx = 0.5; - gc.weighty = 0.5; - if (leftinset >= 0) gc.insets.left = leftinset; - if (topinset >= 0) gc.insets.top = topinset; - if (rightinset >= 0) gc.insets.right = rightinset; - if (bottominset >= 0) gc.insets.bottom = bottominset; - - return gc; - } - - public void actionPerformed(ActionEvent arg0) { - if (arg0.getSource().equals(okButton)) { - for (int i = 0; i < numOptions; i++) { - if (choiceButtons[i].isSelected()) { - chosenOption = i; - break; - } + @Override + protected void processOK(ActionEvent arg0) { + for (int i = 0; i < numOptions; i++) { + if (choiceButtons[i].isSelected()) { + chosenOption = i; + break; } - } else if (arg0.getSource().equals(cancelButton)) { - chosenOption = -1; } - this.setVisible(false); - this.dispose(); - owner.dialogActionPerformed(); + } + + @Override + protected void processCancel(ActionEvent arg0) { + chosenOption = -1; } public synchronized int getSelectedOption() { diff --git a/rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java b/rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java index d1bf925..aed46cc 100644 --- a/rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java +++ b/rails/ui/swing/gamespecific/_1835/StatusWindow_1835.java @@ -11,8 +11,7 @@ import rails.game.special.ExchangeForShare; import rails.game.specific._1835.*; import rails.ui.swing.GameUIManager; import rails.ui.swing.StatusWindow; -import rails.ui.swing.elements.CheckBoxDialog; -import rails.ui.swing.elements.ConfirmationDialog; +import rails.ui.swing.elements.*; public class StatusWindow_1835 extends StatusWindow { @@ -88,7 +87,8 @@ public class StatusWindow_1835 extends StatusWindow { ((ExchangeForShare)(company.getSpecialProperties().get(0))).getShare() ); } - currentDialog = new CheckBoxDialog (gameUIManager, + currentDialog = new CheckBoxDialog (NonModalDialog.Usage.SELECT_FOLDING_COMPANIES, + gameUIManager, this, LocalText.getText("Select"), LocalText.getText("SelectCompaniesToFold", diff --git a/rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java b/rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java index 884c516..b48d117 100644 --- a/rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java +++ b/rails/ui/swing/gamespecific/_1856/StatusWindow_1856.java @@ -9,6 +9,7 @@ import rails.game.RoundI; import rails.game.action.*; import rails.game.specific._1856.CGRFormationRound; import rails.ui.swing.StatusWindow; +import rails.ui.swing.elements.NonModalDialog; import rails.ui.swing.elements.RadioButtonDialog; import rails.util.Util; @@ -99,7 +100,8 @@ public class StatusWindow_1856 extends StatusWindow { + "<br>" + message; } - RadioButtonDialog currentDialog = new RadioButtonDialog (gameUIManager, + RadioButtonDialog currentDialog = new RadioButtonDialog (NonModalDialog.Usage.REPAY_LOANS, + gameUIManager, this, LocalText.getText("1856MergerDialog", action.getCompanyName()), message, diff --git a/rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java b/rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java index 70ce9df..81e816d 100644 --- a/rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java +++ b/rails/ui/swing/gamespecific/_18EU/GameStatus_18EU.java @@ -8,6 +8,7 @@ import rails.game.PublicCompanyI; import rails.game.action.MergeCompanies; import rails.game.action.PossibleAction; import rails.ui.swing.GameStatus; +import rails.ui.swing.elements.NonModalDialog; import rails.ui.swing.elements.RadioButtonDialog; /** @@ -69,7 +70,9 @@ public class GameStatus_18EU extends GameStatus { } } - RadioButtonDialog dialog = new RadioButtonDialog (gameUIManager, + RadioButtonDialog dialog = new RadioButtonDialog ( + NonModalDialog.Usage.SELECT_COMPANY, + gameUIManager, parent, LocalText.getText("PleaseSelect"), LocalText.getText("SelectCompanyToMergeMinorInto", diff --git a/rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java b/rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java index b881a5f..5c17748 100644 --- a/rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java +++ b/rails/ui/swing/gamespecific/_18EU/GameUIManager_18EU.java @@ -10,6 +10,7 @@ import rails.game.Stop; import rails.game.action.MergeCompanies; import rails.game.specific._18EU.StartCompany_18EU; import rails.ui.swing.GameUIManager; +import rails.ui.swing.elements.NonModalDialog; import rails.ui.swing.elements.RadioButtonDialog; public class GameUIManager_18EU extends GameUIManager { @@ -72,7 +73,8 @@ public class GameUIManager_18EU extends GameUIManager { "Minor " + minor.getName() + " " + minor.getLongName(); } - dialog = new RadioButtonDialog (this, + dialog = new RadioButtonDialog (NonModalDialog.Usage.SELECT_FOLDING_COMPANIES, + this, statusWindow, LocalText.getText("PleaseSelect"), LocalText.getText( @@ -91,7 +93,8 @@ public class GameUIManager_18EU extends GameUIManager { for (int i = 0; i < options.length; i++) { options[i] = cities.get(i).toString(); } - dialog = new RadioButtonDialog (this, + dialog = new RadioButtonDialog (NonModalDialog.Usage.SELECT_HOME_STATION, + this, statusWindow, LocalText.getText("PleaseSelect"), LocalText.getText( |
From: Stefan F. <ste...@us...> - 2012-01-30 10:59:35
|
New branch 'rails1.6.x' available with the following commits: commit ef3c25c55af0fd5d30e5ab7525fe9d12ef2c6807 Author: Stefan Frey <ste...@we...> Date: Fri Dec 23 11:48:57 2011 +0100 added update RailsBuild.xml to support missing batik jar file |
From: Stefan F. <ste...@us...> - 2012-01-30 10:50:40
|
.classpath | 25 LocalisedText.properties | 9 build.xml | 301 - buildRails.xml | 159 buildinfo.xml | 16 data/1835/CompanyManager.xml | 5 data/1870/TileSet.xml | 2 data/18AL/18AL_Map_gamekit.svg | 1435 ++++++ data/18AL/Map.xml | 1 data/18AL/TileSet.xml | 2 data/18Kaas/TileSet.xml | 2 data/Properties.xml | 2 dev/null |binary rails.bat | 3 rails.sh | 3 rails/common/parser/Config.java | 15 rails/game/Game.java | 31 rails/game/MapHex.java | 2 rails/game/MapManager.java | 2 rails/game/OperatingRound.java | 31 rails/game/Portfolio.java | 62 rails/game/PublicCompany.java | 6 rails/game/ShareSellingRound.java | 51 rails/game/StockRound.java | 117 rails/game/TreasuryShareRound.java | 77 rails/game/action/SellShares.java | 71 rails/game/model/ShareModel.java | 31 rails/game/model/ViewUpdate.java | 2 rails/game/specific/_1835/PrussianFormationRound.java | 18 rails/game/specific/_1835/StockRound_1835.java | 92 rails/game/specific/_1856/CGRFormationRound.java | 64 rails/ui/swing/GameStatus.java | 45 rails/ui/swing/ORPanel.java | 4 rails/ui/swing/elements/Field.java | 26 rails/ui/swing/hexmap/HexMapImage.java | 7 rails/util/GameFileIO.java | 225 test/SVGApplication.java | 105 test/SVGOffscreenLoader.java | 192 test/data/real/18EU_A.report | 4197 +++++++++--------- test/data/real/18GA_A.report | 1532 +----- test/data/test/1830_SellFullPresCert.rails |binary test/data/test/1830_SellFullPresCert.report | 267 + test/data/test/1830_SellHalfPresCert.rails |binary test/data/test/1830_SellHalfPresCert.report | 267 + test/data/test/1835_NatDoubleShare.rails |binary test/data/test/1835_NatDoubleShare.report | 884 +++ test/data/test/1835_NatSingleShare.rails |binary test/data/test/1835_NatSingleShare.report | 77 test/data/test/1835_PRHasTwoExcessTrains.rails |binary test/data/test/1835_PRHasTwoExcessTrains.report | 1141 ++++ test/data/test/1835_SwapPresForDoubleShare.rails |binary test/data/test/1835_SwapPresForDoubleShare.report | 77 version.number | 5 53 files changed, 7593 insertions(+), 4095 deletions(-) New commits: commit a689df92f8e36e14427fe7c5d95b9f9adb0c9152 Author: Stefan Frey <ste...@we...> Date: Wed Nov 30 22:44:14 2011 +0100 additional commit for 1.5.4: fixed issue with the develop flag and removed calibrate from menu (cherry picked from commit f3a0308761bca73a19bc6e7d4a7bd0e3d72c0e98) diff --git a/rails/common/parser/Config.java b/rails/common/parser/Config.java index 63308d1..c7f64ed 100644 --- a/rails/common/parser/Config.java +++ b/rails/common/parser/Config.java @@ -438,17 +438,18 @@ public final class Config { propertiesLoaded = true; } - /* Load version number as resource */ + /* Load version number and develop flag */ Properties versionNumber = new Properties(); loadPropertyFile(versionNumber, "version.number", true); + String version = versionNumber.getProperty("version"); - String develop = versionNumber.getProperty("develop"); if (Util.hasValue("version")) { - if (Util.hasValue(develop)) { - Game.version = version + "+"; - } else { - Game.version = version; - } + Game.setVersion(version); + } + + String develop = versionNumber.getProperty("develop"); + if (Util.hasValue(develop)) { + Game.setDevelop(develop != ""); } } diff --git a/rails/game/Game.java b/rails/game/Game.java index a24cbc5..de85c55 100644 --- a/rails/game/Game.java +++ b/rails/game/Game.java @@ -14,11 +14,37 @@ import rails.game.action.PossibleAction; import rails.util.GameFileIO; public class Game { - // the correct version number is set during initialLoad in Config class - public static String version = "unknown"; - - public static String develop = "@DEVELOP@"; + // the correct version number and develop status + // is set during initialLoad in Config class + private static String version = "unknown"; + private static boolean develop = false; + public static void setVersion(String version) { + Game.version = version; + } + + public static String getVersion() { + return version; + } + + public static String getFullVersion() { + if (develop) { + return version + "+"; + } else { + return version; + } + } + + public static void setDevelop(boolean develop) { + Game.develop = develop; + } + + public static boolean getDevelop() { + return develop; + } + + // in the following the Game objects are defined + /** The component Manager */ protected GameManager gameManager; protected CompanyManagerI companyManager; diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java index 8b6383c..0eaba7e 100644 --- a/rails/ui/swing/ORPanel.java +++ b/rails/ui/swing/ORPanel.java @@ -213,7 +213,7 @@ implements ActionListener, KeyListener, RevenueListener { zoomMenu.add(zoomOut); calibrateMap = new JMenuItem("CalibrateMap"); calibrateMap.addActionListener(this); - calibrateMap.setEnabled(true); + calibrateMap.setEnabled(Game.getDevelop()); zoomMenu.add(calibrateMap); menuBar.add(zoomMenu); @@ -599,7 +599,7 @@ implements ActionListener, KeyListener, RevenueListener { if (networkInfoMenu != null) infoMenu.remove(networkInfoMenu); networkInfoMenu = createNetworkInfo(); if (networkInfoMenu == null) return; - networkInfoMenu.setEnabled(true); + networkInfoMenu.setEnabled(Game.getDevelop()); infoMenu.add(networkInfoMenu); } diff --git a/rails/util/GameFileIO.java b/rails/util/GameFileIO.java index 628ba98..ec682df 100644 --- a/rails/util/GameFileIO.java +++ b/rails/util/GameFileIO.java @@ -240,7 +240,7 @@ public class GameFileIO { * sets the meta data required for a game save */ public void initSave(Long saveFileVersionID, String gameName, Map<String, String> gameOptions, List<String> playerNames) { - gameData.meta.version = Game.version+" "+BuildInfo.buildDate; + gameData.meta.version = Game.getFullVersion() +" "+BuildInfo.buildDate; gameData.meta.date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); gameData.meta.fileVersionID = saveFileVersionID; gameData.meta.gameName = gameName; commit 465f0034fed34180798c814a06dd2f4331ea27d1 Author: Stefan Frey <ste...@we...> Date: Wed Nov 30 13:16:24 2011 +0100 prepared release 1.5.4 (cherry picked from commit c400dd6d4270b8eb484f64d8e473faa1bf13213e) diff --git a/version.number b/version.number index b52774a..26b5665 100644 --- a/version.number +++ b/version.number @@ -1,5 +1,5 @@ #Property file that contains version number and the develop indicator -version=1.5.3 +version=1.5.4 # the following string "@DEVELOP@ is replaced by an empty string in the release version # this is done automatically by ant develop=@DEVELOP@ \ No newline at end of file commit 7be27cb6adbd294b0b022e14d7a7fb355797cd83 Author: Stefan Frey <ste...@we...> Date: Mon Nov 28 16:34:12 2011 +0100 Further additions to get working build (cherry picked from commit afa0b856fe9eb2940de45b24d0eb29d0c03abf6c) diff --git a/.classpath b/.classpath index 25b28ed..d69b9b9 100644 --- a/.classpath +++ b/.classpath @@ -5,12 +5,25 @@ <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"/> <classpathentry exported="true" kind="lib" path="lib/jgraph5/jgraph.jar"/> - <classpathentry exported="true" kind="lib" path="lib/batik-1.7/batik.jar"/> - <classpathentry exported="true" kind="lib" path="lib/batik-1.7/lib/batik-bridge.jar"/> - <classpathentry exported="true" kind="lib" path="lib/batik-1.7/lib/batik-dom.jar"/> - <classpathentry exported="true" kind="lib" path="lib/batik-1.7/lib/batik-ext.jar"/> - <classpathentry exported="true" kind="lib" path="lib/batik-1.7/lib/batik-gvt.jar"/> - <classpathentry exported="true" kind="lib" path="lib/batik-1.7/lib/batik-util.jar"/> <classpathentry kind="lib" path="lib/junit-4.8.2/junit.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-transcoder.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-dom.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-swing.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-bridge.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/xml-apis.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-ext.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-gui-util.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-util.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-awt-util.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-css.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-gvt.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-parser.jar"/> + <classpathentry kind="lib" path="lib/batik-1.7/lib/batik-script.jar"/> + <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/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"/> <classpathentry kind="output" path="classes"/> </classpath> diff --git a/build.xml b/build.xml index 107fde2..2943231 100644 --- a/build.xml +++ b/build.xml @@ -16,17 +16,32 @@ <pathelement location="lib/log4j-1.2/log4j-1.2.14.jar"/> <pathelement location="lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar"/> <pathelement location="lib/jgraph5/jgraph.jar"/> - <pathelement location="lib/batik-1.7/batik.jar"/> - <pathelement location="lib/batik-1.7/lib/batik-bridge.jar"/> + <pathelement location="lib/junit-4.8.2/junit.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"/> + <pathelement location="lib/batik-1.7/lib/batik-bridge.jar"/> + <pathelement location="lib/batik-1.7/lib/xml-apis.jar"/> <pathelement location="lib/batik-1.7/lib/batik-ext.jar"/> - <pathelement location="lib/batik-1.7/lib/batik-gvt.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-gui-util.jar"/> <pathelement location="lib/batik-1.7/lib/batik-util.jar"/> - <pathelement location="lib/junit-4.8.2/junit.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-awt-util.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-css.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-gvt.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-parser.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-script.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-svg-dom.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-xml.jar"/> + <pathelement location="lib/batik-1.7/lib/js.jar"/> + <pathelement location="lib/batik-1.7/lib/xerces_2_5_0.jar"/> + <pathelement location="lib/batik-1.7/lib/xml-apis-ext.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-anim.jar"/> </path> <target name="init"> <mkdir dir="classes"/> + <!-- this is added --> <copy includeemptydirs="false" todir="classes"> + <filterset refid="developFilter"/> <fileset dir="."> <exclude name="**/*.launch"/> <exclude name="**/*.java"/> diff --git a/buildRails.xml b/buildRails.xml index 142d350..3185488 100644 --- a/buildRails.xml +++ b/buildRails.xml @@ -1,7 +1,13 @@ <?eclipse.ant.import ?> <!-- Extensions to the automatic ant file created by eclipse --> <project basedir="." default="build" name="Rails"> - + + <!-- Sourceforge properties --> + <property name="sf.uri" value="frs.sourceforge.net:/home/frs/project/r/ra/rails/"/> + <property name="sf.filedir" value="Rails/"/> + <property name="sf.user" value="stefanfrey"/> + <!-- Password is asked for --> + <!-- Define a property for the version number --> <property file="version.number"/> @@ -9,13 +15,14 @@ <filterset id="versionFilter"> <filter token="VERSION" value="${version}"/> </filterset> - + <!-- Define a filter to substitute develop tag to version number --> + <filterset id="developFilter"> + <filter token="DEVELOP" value=""/> + </filterset> + <!-- Clean the current release --> <target name="clean-release"> - <delete> - <fileset dir="jar"/> - <fileset dir="rails-${version}"/> - </delete> + <delete dir="rails-${version}"/> </target> <!-- Target that creates the release jar @@ -23,7 +30,6 @@ <target name="build-release" depends="clean-release,clean,build"> <mkdir dir="jar"/> <copy includeemptydirs="false" todir="jar"> - <filterset refid="versionFilter"/> <fileset dir="classes"> <exclude name="**/*.launch"/> <exclude name="**/*.java"/> @@ -33,7 +39,6 @@ <exclude name="18xx.log"/> <exclude name="build.xml"/> <exclude name="buildinfo.xml"/> - <exclude name="user.profiles"/> <exclude name="manifest"/> <exclude name="doc/*"/> <exclude name="html/*"/> @@ -42,7 +47,6 @@ <exclude name="rails-*-${version}/**"/> <exclude name="rails.bat"/> <exclude name="rails.sh"/> - <exclude name="version.number"/> <exclude name=".project"/> <exclude name=".classpath"/> <exclude name=".git/**"/> @@ -54,36 +58,102 @@ </fileset> </copy> <mkdir dir="rails-${version}"/> + <copy includeemptydirs="false" todir="rails-${version}/lib"> + <fileset dir="./lib"> + <include name="log4j-1.2/log4j-1.2.14.jar" /> + <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="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" /> + <include name="batik-1.7/lib/batik-bridge.jar" /> + <include name="batik-1.7/lib/xml-apis.jar" /> + <include name="batik-1.7/lib/batik-ext.jar" /> + <include name="batik-1.7/lib/batik-gui-util.jar" /> + <include name="batik-1.7/lib/batik-util.jar" /> + <include name="batik-1.7/lib/batik-awt-util.jar" /> + <include name="batik-1.7/lib/batik-css.jar" /> + <include name="batik-1.7/lib/batik-gvt.jar" /> + <include name="batik-1.7/lib/batik-parser.jar" /> + <include name="batik-1.7/lib/batik-script.jar" /> + <include name="batik-1.7/lib/batik-svg-dom.jar" /> + <include name="batik-1.7/lib/batik-xml.jar" /> + <include name="batik-1.7/lib/js.jar" /> + <include name="batik-1.7/lib/xerces_2_5_0.jar" /> + <include name="batik-1.7/lib/xml-apis-ext.jar" /> + <include name="batik-1.7/lib/batik-anim.jar" /> + </fileset> + </copy> <copy includeemptydirs="false" todir="rails-${version}"> - <filterset refid="versionFilter"/> - <fileset dir="."> + <filterset refid="versionFilter"/> + <fileset dir="."> <include name="LICENSE"/> <include name="README"/> <include name="AUTHORS"/> <include name="rails.bat"/> <include name="rails.sh"/> - <include name="my.properties"/> - <include name="LocalisedText.properties"/> - <include name="games.properties"/> - <include name="lib/**"/> </fileset> </copy> + <!-- adds executable flags to rails.sh --> + <chmod file="rails-${version}/rails.sh" perm="ugo+rx"/> + <jar destfile="rails-${version}/rails-${version}.jar" basedir="jar" duplicate="preserve"> <manifest> <attribute name="Main-Class" value="rails.util.RunGame" /> - <attribute name="Class-Path" value="./my.properties + <attribute name="Class-Path" value=" ./LocalisedText.properties - ./lib/log4j-1.2/log4j-1.2.14.jar - ./lib/batik-1.7/batik.jar - ./lib/batik-1.7/lib/batik-util.jar - ./lib/batik-1.7/lib/batik-dom.jar - ./lib/batik-1.7/lib/batik-bridge.jar - ./lib/batik-1.7/lib/batik-ext.jar - ./lib/batik-1.7/lib/batik-gvt.jar - ./lib/jgraph5/jgraph.jar - ./lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar" /> + ./log4j.properties + ./lib/log4j-1.2/log4j-1.2.14.jar + ./lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar + ./lib/jgraph5/jgraph.jar + ./lib/junit-4.8.2/junit.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 + ./lib/batik-1.7/lib/batik-bridge.jar + ./lib/batik-1.7/lib/xml-apis.jar + ./lib/batik-1.7/lib/batik-ext.jar + ./lib/batik-1.7/lib/batik-gui-util.jar + ./lib/batik-1.7/lib/batik-util.jar + ./lib/batik-1.7/lib/batik-awt-util.jar + ./lib/batik-1.7/lib/batik-css.jar + ./lib/batik-1.7/lib/batik-gvt.jar + ./lib/batik-1.7/lib/batik-parser.jar + ./lib/batik-1.7/lib/batik-script.jar + ./lib/batik-1.7/lib/batik-svg-dom.jar + ./lib/batik-1.7/lib/batik-xml.jar + ./lib/batik-1.7/lib/js.jar + ./lib/batik-1.7/lib/xerces_2_5_0.jar + ./lib/batik-1.7/lib/xml-apis-ext.jar + ./lib/batik-1.7/lib/batik-anim.jar"/> </manifest> - </jar> - </target> - + </jar> + <delete dir="jar"/> + <tar destfile="../rails-${version}.tar.gz" compression="gzip"> + <!-- adds executable flags to rails.sh, has to be done again for the tar (see above) --> + <tarfileset dir="." filemode="755"> + <include name="rails-${version}/rails.sh"/> + </tarfileset> + <tarfileset dir="."> + <include name="rails-${version}/**"/> + <exclude name="rails-${version}/rails.sh"/> + </tarfileset> + </tar> + <zip destfile="../rails-${version}.zip" basedir="." includes="rails-${version}/**"/> + </target> + <target name="publish-release"> + <exec executable="rsync" dir=".." failonerror="true"> + <arg value="-avP"/> + <arg value="-e"/> + <arg value="ssh"/> + <arg value="rails-${version}.zip"/> + <arg value="rails-${version}.tar.gz"/> + <arg value="${sf.user},rails@${sf.uri}${sf.filedir}${version}/"/> + </exec> + <exec executable="scp" dir="../rails-${version}" failonerror="true"> + <arg value="Readme.txt"/> + <arg value="${sf.user},rails@${sf.uri}${sf.filedir}${version}/"/> + </exec> + </target> </project> \ No newline at end of file diff --git a/rails/common/parser/Config.java b/rails/common/parser/Config.java index b1895e7..63308d1 100644 --- a/rails/common/parser/Config.java +++ b/rails/common/parser/Config.java @@ -16,6 +16,7 @@ import java.util.Properties; import org.apache.log4j.Logger; +import rails.game.Game; import rails.game.GameManager; import rails.util.Util; @@ -436,6 +437,19 @@ public final class Config { loadProfile(selectedProfile); propertiesLoaded = true; } + + /* Load version number as resource */ + Properties versionNumber = new Properties(); + loadPropertyFile(versionNumber, "version.number", true); + String version = versionNumber.getProperty("version"); + String develop = versionNumber.getProperty("develop"); + if (Util.hasValue("version")) { + if (Util.hasValue(develop)) { + Game.version = version + "+"; + } else { + Game.version = version; + } + } } diff --git a/rails/game/Game.java b/rails/game/Game.java index 250e6b4..a24cbc5 100644 --- a/rails/game/Game.java +++ b/rails/game/Game.java @@ -14,7 +14,10 @@ import rails.game.action.PossibleAction; import rails.util.GameFileIO; public class Game { - public static final String version = "@VERSION@"; + // the correct version number is set during initialLoad in Config class + public static String version = "unknown"; + + public static String develop = "@DEVELOP@"; /** The component Manager */ protected GameManager gameManager; diff --git a/test/SVGApplication.java b/test/SVGApplication.java deleted file mode 100644 index 8b583ec..0000000 --- a/test/SVGApplication.java +++ /dev/null @@ -1,105 +0,0 @@ -package test; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import javax.swing.*; - -import org.apache.batik.swing.JSVGCanvas; -import org.apache.batik.swing.gvt.GVTTreeRendererAdapter; -import org.apache.batik.swing.gvt.GVTTreeRendererEvent; -import org.apache.batik.swing.svg.SVGDocumentLoaderAdapter; -import org.apache.batik.swing.svg.SVGDocumentLoaderEvent; -import org.apache.batik.swing.svg.GVTTreeBuilderAdapter; -import org.apache.batik.swing.svg.GVTTreeBuilderEvent; - -public class SVGApplication { - - public static void main(String[] args) { - JFrame f = new JFrame("Batik"); - SVGApplication app = new SVGApplication(f); - f.getContentPane().add(app.createComponents()); - - f.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - System.exit(0); - } - }); - f.setSize(400, 400); - f.setVisible(true); - } - - JFrame frame; - JButton button = new JButton("Load..."); - JLabel label = new JLabel(); - JSVGCanvas svgCanvas = new JSVGCanvas(); - - public SVGApplication(JFrame f) { - frame = f; - } - - public JComponent createComponents() { - final JPanel panel = new JPanel(new BorderLayout()); - - JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT)); - p.add(button); - p.add(label); - - panel.add("North", p); - panel.add("Center", svgCanvas); - - // Set the button action. - button.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent ae) { - JFileChooser fc = new JFileChooser("."); - int choice = fc.showOpenDialog(panel); - if (choice == JFileChooser.APPROVE_OPTION) { - File f = fc.getSelectedFile(); - try { - svgCanvas.setURI(f.toURL().toString()); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - } - }); - - // Set the JSVGCanvas listeners. - svgCanvas.addSVGDocumentLoaderListener(new SVGDocumentLoaderAdapter() { - - public void documentLoadingStarted(SVGDocumentLoaderEvent e) { - label.setText("Document Loading..."); - } - - public void documentLoadingCompleted(SVGDocumentLoaderEvent e) { - label.setText("Document Loaded."); - } - }); - - svgCanvas.addGVTTreeBuilderListener(new GVTTreeBuilderAdapter() { - - public void gvtBuildStarted(GVTTreeBuilderEvent e) { - label.setText("Build Started..."); - } - - public void gvtBuildCompleted(GVTTreeBuilderEvent e) { - label.setText("Build Done."); - frame.pack(); - } - }); - - svgCanvas.addGVTTreeRendererListener(new GVTTreeRendererAdapter() { - - public void gvtRenderingPrepare(GVTTreeRendererEvent e) { - label.setText("Rendering Started..."); - } - - public void gvtRenderingCompleted(GVTTreeRendererEvent e) { - label.setText(""); - } - }); - - return panel; - } -} diff --git a/test/SVGOffscreenLoader.java b/test/SVGOffscreenLoader.java deleted file mode 100644 index 5426d5f..0000000 --- a/test/SVGOffscreenLoader.java +++ /dev/null @@ -1,192 +0,0 @@ -package test; - -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; -import java.io.*; -import java.util.List; - -import org.apache.batik.bridge.*; -import org.apache.batik.dom.svg.SAXSVGDocumentFactory; -import org.apache.batik.ext.awt.image.codec.png.PNGEncodeParam; -import org.apache.batik.ext.awt.image.codec.png.PNGImageEncoder; -import org.apache.batik.gvt.*; -import org.apache.batik.gvt.renderer.*; -import org.apache.batik.util.RunnableQueue; -import org.apache.batik.util.XMLResourceDescriptor; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -public class SVGOffscreenLoader { - - static final String SVGNS = "http://www.w3.org/2000/svg"; - - Document document; - UserAgentAdapter userAgent; - GVTBuilder builder; - BridgeContext ctx; - ImageRenderer renderer; - AffineTransform curTxf; - UpdateManager manager; - GraphicsNode gvtRoot; - int DISPLAY_WIDTH = 1280; - int DISPLAY_HEIGHT = 1024; - - public SVGOffscreenLoader(Document doc) { - userAgent = new UserAgentAdapter(); - ctx = new BridgeContext(userAgent); - builder = new GVTBuilder(); - document = doc; - } - - public void init() { - GraphicsNode gvtRoot = null; - - try { - ctx.setDynamicState(BridgeContext.DYNAMIC); - gvtRoot = builder.build(ctx, document); - } catch (BridgeException e) { - e.printStackTrace(); - System.exit(1); - } - - ImageRendererFactory rendererFactory; - rendererFactory = new ConcreteImageRendererFactory(); - renderer = rendererFactory.createDynamicImageRenderer(); - renderer.setDoubleBuffered(false); - - float docWidth = (float) ctx.getDocumentSize().getWidth(); - float docHeight = (float) ctx.getDocumentSize().getHeight(); - - float xscale = DISPLAY_WIDTH / docWidth; - float yscale = DISPLAY_HEIGHT / docHeight; - float scale = Math.min(xscale, yscale); - - AffineTransform px = AffineTransform.getScaleInstance(scale, scale); - - double tx = -0 + (DISPLAY_WIDTH / scale - docWidth) / 2; - double ty = -0 + (DISPLAY_WIDTH / scale - docHeight) / 2; - px.translate(tx, ty); - CanvasGraphicsNode cgn = getGraphicsNode(gvtRoot); - if (cgn != null) { - cgn.setViewingTransform(px); - curTxf = new AffineTransform(); - } else { - curTxf = px; - } - manager = new UpdateManager(ctx, gvtRoot, document); - // 'setMinRepaintTime' was added to SVN. This isn't - // essential but prevents 'frame skipping' (useful - // for "recording" content, not needed for live display). - // manager.setMinRepaintTime(-1); - - try { - manager.dispatchSVGLoadEvent(); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - - renderer.updateOffScreen(DISPLAY_WIDTH, DISPLAY_HEIGHT); - renderer.setTree(gvtRoot); - renderer.setTransform(curTxf); - renderer.clearOffScreen(); - renderer.repaint(new Rectangle(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT)); - manager.addUpdateManagerListener(new UpdateManagerAdapter() { - - @Override - public void updateCompleted(UpdateManagerEvent e) { - render(e.getImage()); - } - - @Override - public void managerSuspended(UpdateManagerEvent e) { - // Make sure pending updates are completed. - System.exit(0); - } - }); - manager.manageUpdates(renderer); - this.gvtRoot = gvtRoot; - } - - private CanvasGraphicsNode getGraphicsNode(GraphicsNode gn) { - if (!(gn instanceof CompositeGraphicsNode)) return null; - CompositeGraphicsNode cgn = (CompositeGraphicsNode) gn; - List<?> children = cgn.getChildren(); - if (children.size() == 0) return null; - gn = (GraphicsNode) children.get(0); - if (!(gn instanceof CanvasGraphicsNode)) return null; - return (CanvasGraphicsNode) gn; - - } - - int imgCount = 1; - - public void render(java.awt.image.BufferedImage img) { - // paint the image or stream the image to the client display - try { - String file = "frame." + (imgCount++) + ".png"; - System.err.println("Output: " + file); - OutputStream os = new FileOutputStream(file); - - PNGEncodeParam params = PNGEncodeParam.getDefaultEncodeParam(img); - PNGImageEncoder pngEncoder = new PNGImageEncoder(os, params); - pngEncoder.encode(img); - os.flush(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - - /** - * @param args - */ - public static void main(String[] args) { - /* - * if (args.length < 1) { System.out.println("You must provide - * background SVG file"); System.exit(1); } - */ - String docStr = "tiles/svg/tile-901.svg"; - - String xmlParser = XMLResourceDescriptor.getXMLParserClassName(); - SAXSVGDocumentFactory df; - df = new SAXSVGDocumentFactory(xmlParser); - Document doc = null; - SVGOffscreenLoader render = null; - Element r = null; - try { - File f = new File(docStr); - doc = df.createSVGDocument(f.toURL().toString()); - r = doc.createElementNS(SVGNS, "rect"); - r.setAttributeNS(null, "x", "100"); - r.setAttributeNS(null, "y", "200"); - r.setAttributeNS(null, "width", "200"); - r.setAttributeNS(null, "height", "150"); - r.setAttributeNS(null, "fill", "crimson"); - r.setAttributeNS(null, "stroke", "gold"); - r.setAttributeNS(null, "stroke-width", "3"); - doc.getDocumentElement().appendChild(r); - render = new SVGOffscreenLoader(doc); - render.init(); - } catch (IOException ioe) { - ioe.printStackTrace(); - System.exit(0); - } - - final Element rect = r; - - RunnableQueue rq = render.manager.getUpdateRunnableQueue(); - for (int i = 1; i < 10; i++) { - final int x = 100 + (i * 10); - try { - rq.invokeAndWait(new Runnable() { - - public void run() { - rect.setAttributeNS(null, "x", "" + x); - } - }); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - } - render.manager.suspend(); - } -} diff --git a/tools/lib/jarbundler-2.1.0.jar b/tools/lib/jarbundler-2.1.0.jar deleted file mode 100644 index 5127987..0000000 Binary files a/tools/lib/jarbundler-2.1.0.jar and /dev/null differ diff --git a/version.number b/version.number index 72b919f..b52774a 100644 --- a/version.number +++ b/version.number @@ -1,2 +1,5 @@ -#Property file that contains only the version number -version=1.5.3+ \ No newline at end of file +#Property file that contains version number and the develop indicator +version=1.5.3 +# the following string "@DEVELOP@ is replaced by an empty string in the release version +# this is done automatically by ant +develop=@DEVELOP@ \ No newline at end of file commit 65ea6b36afb28670781bb27dc40030d69f0df297 Author: Stefan Frey <ste...@we...> Date: Mon Nov 28 13:37:11 2011 +0100 Updated ant build files to increase automation diff --git a/build.xml b/build.xml index 3900603..107fde2 100644 --- a/build.xml +++ b/build.xml @@ -1,180 +1,112 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- WARNING: Eclipse auto-generated file. - Any modifications will be overwritten. - To include a user specific buildfile here, simply create one in the same - directory with the processing instruction <?eclipse.ant.import?> - as the first entry and export the buildfile again. --> -<project basedir="." default="build" name="18xx"> - <property environment="env"/> - <property name="debuglevel" value="source,lines,vars"/> - <property name="target" value="1.5"/> - <property name="source" value="1.5"/> - <property name="version" value="1.5.3"/> - <taskdef name="jarbundler" - classpath="tools/lib/jarbundler-2.1.0.jar" - classname="net.sourceforge.jarbundler.JarBundler" /> - <path id="18xx.classpath"> - <pathelement location="classes"/> - <pathelement location="lib/log4j-1.2/log4j-1.2.14.jar"/> - <pathelement location="lib/batik-1.7/batik.jar"/> - <pathelement location="lib/batik-1.7/lib/batik-dom.jar"/> - <pathelement location="lib/batik-1.7/lib/batik-bridge.jar"/> - <pathelement location="lib/batik-1.7/lib/batik-util.jar"/> - <pathelement location="lib/batik-1.7/lib/batik-gvt.jar"/> - <pathelement location="lib/batik-1.7/lib/batik-ext.jar"/> - <pathelement location="lib/jgraph5/jgraph.jar"/> - <pathelement location="lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar"/> - <pathelement location="lib/junit-4.8.2/junit.jar"/> - </path> - <target depends="clean" name="init"> - <mkdir dir="classes"/> - <copy includeemptydirs="false" todir="classes"> - <fileset dir="."> - <exclude name="**/*.launch"/> - <exclude name="**/*.java"/> - <exclude name="tools/**"/> - <exclude name="images/**"/> - </fileset> - </copy> - </target> - <target name="clean"> - <delete dir="classes"/> - <delete dir="jar"/> - </target> - <target depends="clean" name="cleanall"> - <delete dir="rails-${version}"/> - <delete dir="rails-mac-${version}"/> - <delete file="18xx.log"/> - </target> - <target depends="build-subprojects,build-project,build-release" name="build"/> - <target name="build-subprojects"/> - <target depends="init" name="build-project"> - <echo message="${ant.project.name}: ${ant.file}"/> - <javac debug="true" debuglevel="${debuglevel}" destdir="classes" source="${source}" target="${target}"> - <src path="."/> - <classpath refid="18xx.classpath"/> - </javac> - </target> - <target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/> - <target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler"> - <copy todir="${ant.library.dir}"> - <fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/> - </copy> - <unzip dest="${ant.library.dir}"> - <patternset includes="jdtCompilerAdapter.jar"/> - <fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/> - </unzip> - </target> - <target description="compile project with Eclipse compiler" name="build-eclipse-compiler"> - <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/> - <antcall target="build"/> - </target> - <target name="build-release"> - <mkdir dir="jar"/> - <copy includeemptydirs="false" todir="jar"> - <fileset dir="classes"> - <exclude name="**/*.launch"/> - <exclude name="**/*.java"/> - <exclude name="rails/test/*"/> - <exclude name="test/**"/> - <exclude name="tiles/*.*"/> - <exclude name="18xx.log"/> - <exclude name="build.xml"/> - <exclude name="buildinfo.xml"/> - <exclude name="user.profiles"/> - <exclude name="manifest"/> - <exclude name="doc/*"/> - <exclude name="html/*"/> - <exclude name="lib/**"/> - <exclude name="rails-${version}/**"/> - <exclude name="rails-*-${version}/**"/> - <exclude name="rails.bat"/> - <exclude name="rails.sh"/> - <exclude name=".project"/> - <exclude name=".classpath"/> - <exclude name=".git/**"/> - <exclude name=".gitignore"/> - <exclude name="Rails-format.xml"/> - <exclude name="**/CVS/*"/> - <exclude name="**/.settings/*"/> - <exclude name="**/rails-${version}.jar"/> - </fileset> - </copy> - <mkdir dir="rails-${version}"/> - <copy includeemptydirs="false" todir="rails-${version}"> - <fileset dir="."> - <include name="LICENSE"/> - <include name="README"/> - <include name="AUTHORS"/> - <include name="rails.bat"/> - <include name="rails.sh"/> - <include name="my.properties"/> - <include name="LocalisedText.properties"/> - <include name="games.properties"/> - <include name="lib/**"/> - </fileset> - </copy> - <jar destfile="rails-${version}/rails-${version}.jar" basedir="jar" duplicate="preserve"> - <manifest> - <attribute name="Main-Class" value="rails.util.RunGame" /> - <attribute name="Class-Path" value="./my.properties - ./LocalisedText.properties - ./lib/log4j-1.2/log4j-1.2.14.jar - ./lib/batik-1.7/batik.jar - ./lib/batik-1.7/lib/batik-util.jar - ./lib/batik-1.7/lib/batik-dom.jar - ./lib/batik-1.7/lib/batik-bridge.jar - ./lib/batik-1.7/lib/batik-ext.jar - ./lib/batik-1.7/lib/batik-gvt.jar - ./lib/jgraph5/jgraph.jar - ./lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar" /> - </manifest> - </jar> - </target> - <target name="build-mac"> - <mkdir dir="rails-mac-${version}" /> - <copy includeemptydirs="false" todir="rails-mac-${version}"> - <fileset dir="."> - <include name="LICENSE"/> - <include name="README"/> - <include name="AUTHORS"/> - <include name="my.properties"/> - </fileset> - </copy> - <jarbundler dir="rails-mac-${version}" - name="Rails" - mainclass="rails.util.RunGame" - icon="images/icon/rails.icns" - version="${version}"> - <jarfileset dir="rails-${version}"> - <include name="rails-${version}.jar"/> - <include name="lib/**"/> - </jarfileset> - <javaproperty name="apple.laf.useScreenMenuBar" value="true"/> - </jarbundler> - </target> - <target name="RunGame"> - <java classname="rails.util.RunGame" failonerror="true" fork="yes"> - <classpath refid="18xx.classpath"/> - </java> - </target> - <target name="TestGames"> - <property name="test.xml.dir" value="test/xml"/> - <property name="test.report.dir" value="test/report"/> - <mkdir dir="${test.xml.dir}"/> - <mkdir dir="${test.report.dir}"/> - <junit> - <classpath refid="18xx.classpath"/> - <formatter type="brief" usefile="false" /> - <formatter type="xml" /> - <test name ="test.TestGameBuilder" todir="${test.xml.dir}"/> - </junit> - <junitreport todir="${test.xml.dir}"> - <fileset dir="${test.xml.dir}"> - <include name="TEST-*.xml"/> - </fileset> - <report format="noframes" todir="${test.report.dir}"/> - </junitreport> - </target> - + Any modifications will be overwritten. + To include a user specific buildfile here, simply create one in the same + directory with the processing instruction <?eclipse.ant.import?> + as the first entry and export the buildfile again. --> +<project basedir="." default="build" name="Rails"> + <property environment="env"/> + <property name="junit.output.dir" value="junit"/> + <property name="debuglevel" value="source,lines,vars"/> + <property name="target" value="1.5"/> + <property name="source" value="1.5"/> + <import file="buildRails.xml"/> + <path id="Rails.classpath"> + <pathelement location="classes"/> + <pathelement location="lib/log4j-1.2/log4j-1.2.14.jar"/> + <pathelement location="lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar"/> + <pathelement location="lib/jgraph5/jgraph.jar"/> + <pathelement location="lib/batik-1.7/batik.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-bridge.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-dom.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-ext.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-gvt.jar"/> + <pathelement location="lib/batik-1.7/lib/batik-util.jar"/> + <pathelement location="lib/junit-4.8.2/junit.jar"/> + </path> + <target name="init"> + <mkdir dir="classes"/> + <copy includeemptydirs="false" todir="classes"> + <fileset dir="."> + <exclude name="**/*.launch"/> + <exclude name="**/*.java"/> + <exclude name="lib/batik-1.7/"/> + <exclude name="lib/batik-1.7/"/> + <exclude name="lib/batik-1.7/lib/"/> + <exclude name="lib/batik-1.7/lib/"/> + <exclude name="lib/jgraph5/"/> + <exclude name="lib/jgraph5/"/> + <exclude name="lib/jgrapht-0.7.3/"/> + <exclude name="lib/jgrapht-0.7.3/"/> + <exclude name="lib/junit-4.8.2"/> + <exclude name="lib/log4j-1.2/"/> + <exclude name="lib/log4j-1.2/"/> + </fileset> + </copy> + </target> + <target name="clean"> + <delete dir="classes"/> + </target> + <target depends="clean" name="cleanall"/> + <target depends="build-subprojects,build-project" name="build"/> + <target name="build-subprojects"/> + <target depends="init" name="build-project"> + <echo message="${ant.project.name}: ${ant.file}"/> + <javac debug="true" debuglevel="${debuglevel}" destdir="classes" includeantruntime="false" source="${source}" target="${target}"> + <src path="."/> + <exclude name="lib/batik-1.7/"/> + <exclude name="lib/batik-1.7/"/> + <exclude name="lib/batik-1.7/lib/"/> + <exclude name="lib/batik-1.7/lib/"/> + <exclude name="lib/jgraph5/"/> + <exclude name="lib/jgraph5/"/> + <exclude name="lib/jgrapht-0.7.3/"/> + <exclude name="lib/jgrapht-0.7.3/"/> + <exclude name="lib/junit-4.8.2"/> + <exclude name="lib/log4j-1.2/"/> + <exclude name="lib/log4j-1.2/"/> + <classpath refid="Rails.classpath"/> + </javac> + </target> + <target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/> + <target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler"> + <copy todir="${ant.library.dir}"> + <fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/> + </copy> + <unzip dest="${ant.library.dir}"> + <patternset includes="jdtCompilerAdapter.jar"/> + <fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/> + </unzip> + </target> + <target description="compile project with Eclipse compiler" name="build-eclipse-compiler"> + <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/> + <antcall target="build"/> + </target> + <target name="TestGameBuilder (1)"> + <java classname="test.TestGameBuilder" failonerror="true" fork="yes"> + <classpath refid="Rails.classpath"/> + </java> + </target> + <target name="RunGame"> + <java classname="rails.util.RunGame" failonerror="true" fork="yes"> + <jvmarg line="-DRevenueCalculation=suggest -Dswing.defaultlaf=com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"/> + <classpath refid="Rails.classpath"/> + </java> + </target> + <target name="TestGameBuilder"> + <mkdir dir="${junit.output.dir}"/> + <junit fork="yes" printsummary="withOutAndErr"> + <formatter type="xml"/> + <test name="test.TestGameBuilder" todir="${junit.output.dir}"/> + <classpath refid="Rails.classpath"/> + </junit> + </target> + <target name="junitreport"> + <junitreport todir="${junit.output.dir}"> + <fileset dir="${junit.output.dir}"> + <include name="TEST-*.xml"/> + </fileset> + <report format="frames" todir="${junit.output.dir}"/> + </junitreport> + </target> </project> diff --git a/buildRails.xml b/buildRails.xml new file mode 100644 index 0000000..142d350 --- /dev/null +++ b/buildRails.xml @@ -0,0 +1,89 @@ +<?eclipse.ant.import ?> + <!-- Extensions to the automatic ant file created by eclipse --> +<project basedir="." default="build" name="Rails"> + + <!-- Define a property for the version number --> + <property file="version.number"/> + + <!-- Define a filter to substitute version number --> + <filterset id="versionFilter"> + <filter token="VERSION" value="${version}"/> + </filterset> + + <!-- Clean the current release --> + <target name="clean-release"> + <delete> + <fileset dir="jar"/> + <fileset dir="rails-${version}"/> + </delete> + </target> + + <!-- Target that creates the release jar + this is legacy code --> + <target name="build-release" depends="clean-release,clean,build"> + <mkdir dir="jar"/> + <copy includeemptydirs="false" todir="jar"> + <filterset refid="versionFilter"/> + <fileset dir="classes"> + <exclude name="**/*.launch"/> + <exclude name="**/*.java"/> + <exclude name="rails/test/*"/> + <exclude name="test/**"/> + <exclude name="tiles/*.*"/> + <exclude name="18xx.log"/> + <exclude name="build.xml"/> + <exclude name="buildinfo.xml"/> + <exclude name="user.profiles"/> + <exclude name="manifest"/> + <exclude name="doc/*"/> + <exclude name="html/*"/> + <exclude name="lib/**"/> + <exclude name="rails-${version}/**"/> + <exclude name="rails-*-${version}/**"/> + <exclude name="rails.bat"/> + <exclude name="rails.sh"/> + <exclude name="version.number"/> + <exclude name=".project"/> + <exclude name=".classpath"/> + <exclude name=".git/**"/> + <exclude name=".gitignore"/> + <exclude name="Rails-format.xml"/> + <exclude name="**/CVS/*"/> + <exclude name="**/.settings/*"/> + <exclude name="**/rails-${version}.jar"/> + </fileset> + </copy> + <mkdir dir="rails-${version}"/> + <copy includeemptydirs="false" todir="rails-${version}"> + <filterset refid="versionFilter"/> + <fileset dir="."> + <include name="LICENSE"/> + <include name="README"/> + <include name="AUTHORS"/> + <include name="rails.bat"/> + <include name="rails.sh"/> + <include name="my.properties"/> + <include name="LocalisedText.properties"/> + <include name="games.properties"/> + <include name="lib/**"/> + </fileset> + </copy> + <jar destfile="rails-${version}/rails-${version}.jar" basedir="jar" duplicate="preserve"> + <manifest> + <attribute name="Main-Class" value="rails.util.RunGame" /> + <attribute name="Class-Path" value="./my.properties + ./LocalisedText.properties + ./lib/log4j-1.2/log4j-1.2.14.jar + ./lib/batik-1.7/batik.jar + ./lib/batik-1.7/lib/batik-util.jar + ./lib/batik-1.7/lib/batik-dom.jar + ./lib/batik-1.7/lib/batik-bridge.jar + ./lib/batik-1.7/lib/batik-ext.jar + ./lib/batik-1.7/lib/batik-gvt.jar + ./lib/jgraph5/jgraph.jar + ./lib/jgrapht-0.7.3/jgrapht-jdk1.5.jar" /> + </manifest> + </jar> + </target> + +</project> \ No newline at end of file diff --git a/buildinfo.xml b/buildinfo.xml deleted file mode 100644 index 6c1fb15..0000000 --- a/buildinfo.xml +++ /dev/null @@ -1,16 +0,0 @@ -<!-- Generate a java class with the current svn revision number --> -<project name="buildinfo " default="makeBuildInfo" basedir="."> - <target name="makeBuildInfo" description="Create a BuildInfo source"> - <tstamp> - <format property="TODAY" pattern="yyyy-MM-dd"/> - </tstamp> - <!-- the source code of the java class --> - <echo file="${basedir}/rails/util/BuildInfo.java"> -package rails.util; - -public class BuildInfo { - public static final String buildDate = "${TODAY}"; -} -</echo> - </target> -</project> \ No newline at end of file diff --git a/rails.bat b/rails.bat index a314500..515bc30 100644 --- a/rails.bat +++ b/rails.bat @@ -1,2 +1 @@ - -java -jar rails-1.5.3.jar %1 \ No newline at end of file +java -jar rails-@VERSION@.jar %1 diff --git a/rails.sh b/rails.sh index ec6c136..91b8bbd 100644 --- a/rails.sh +++ b/rails.sh @@ -1,3 +1,2 @@ #!/bin/bash - -java -jar ./rails-1.5.3.jar $1 \ No newline at end of file +java -jar ./rails-@VERSION@.jar $1 diff --git a/rails/game/Game.java b/rails/game/Game.java index 2ca9752..250e6b4 100644 --- a/rails/game/Game.java +++ b/rails/game/Game.java @@ -14,7 +14,7 @@ import rails.game.action.PossibleAction; import rails.util.GameFileIO; public class Game { - public static final String version = "1.5.3"; + public static final String version = "@VERSION@"; /** The component Manager */ protected GameManager gameManager; diff --git a/version.number b/version.number new file mode 100644 index 0000000..72b919f --- /dev/null +++ b/version.number @@ -0,0 +1,2 @@ +#Property file that contains only the version number +version=1.5.3+ \ No newline at end of file commit e393b4f6911123f70a977d35e9e22718afd82887 Author: Stefan Frey <ste...@we...> Date: Mon Nov 28 11:42:11 2011 +0100 Fixed reference in properties file for the setLocale method as the class was moved previously(cherry picked from commit 760a9358b8a2e9e16e0b7542c5df9a1c64e188d5) diff --git a/data/Properties.xml b/data/Properties.xml index b54129b..eb95d4c 100644 --- a/data/Properties.xml +++ b/data/Properties.xml @@ -4,7 +4,7 @@ <Properties> <Section name="General"> <Property name="locale" type="LIST" values="en_US,te_ST" - initClass="rails.util.LocalText" initMethod="setLocale" + initClass="rails.common.LocalText" initMethod="setLocale" initParameter="yes" /> <Property name="default_game" type="STRING" /> <Property name="default_players" type="STRING" /> commit ab859d02322c58ecfeb24b607fd14f50d39d7f26 Author: Stefan Frey <ste...@we...> Date: Fri Nov 25 15:15:47 2011 +0100 Fixed bug that prevented loading MapImage from jar(cherry picked from commit 572d4fa812f40923634d460a94236d4d94b5a453) diff --git a/rails/game/MapManager.java b/rails/game/MapManager.java index dd85c46..f45dd10 100644 --- a/rails/game/MapManager.java +++ b/rails/game/MapManager.java @@ -245,7 +245,7 @@ public class MapManager implements ConfigurableComponentI { if (!rails.util.Util.hasValue(rootDirectory)) { rootDirectory = "data"; } - mapImageFilepath = rootDirectory + "/" + mapImageFilename; + mapImageFilepath = "/" + rootDirectory + "/" + mapImageFilename; } for (String hexName : mHexes.keySet()) { diff --git a/rails/ui/swing/hexmap/HexMapImage.java b/rails/ui/swing/hexmap/HexMapImage.java index e360245..a1435e6 100644 --- a/rails/ui/swing/hexmap/HexMapImage.java +++ b/rails/ui/swing/hexmap/HexMapImage.java @@ -67,9 +67,10 @@ public final class HexMapImage extends JSVGCanvas { private void loadMap() { try { - File imageFile = new File (mapManager.getMapImageFilepath()); - setURI(imageFile.toURI().toString()); - log.debug("ImageFile="+ imageFile.getName()); +// File imageFile = new File (mapManager.getMapImageFilepath()); +// setURI(imageFile.toURI().toString()); +// log.debug("ImageFile="+ imageFile.getName()); + setURI(getClass().getResource(mapManager.getMapImageFilepath()).toString()); } catch (Exception e) { log.error ("Cannot load map image file " + mapManager.getMapImageFilepath(), e); } commit e4c179c4deee4e2db6a10deb5ecd23b820412c3b Author: Erik Vos <eri...@xs...> Date: Fri Nov 25 11:06:41 2011 +0100 Interrupted load now reports action count. Three test cases refreshed again.(cherry picked from commit a638a2bd036c47a706c0545859310cecfd135b79) diff --git a/LocalisedText.properties b/LocalisedText.properties index 5d32604..ac33c51 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -362,7 +362,7 @@ LoadFailed=Load failed.\n\Reason = {0}\n\To improve Rails please submit save fil LoadGame=Load Game LoadRecentGame=Load Recent LOAD=Load -LoadInterrupted=Load interrupted at this point, you can continue play from here.\n\To improve Rails please submit save file to Rails user list at \n\ rai...@li... +LoadInterrupted=Load interrupted at action {0}, you can continue play from here.\n\To improve Rails please submit save file to Rails user list at \n\ rai...@li... LoansNotAllowed={0} may not take any loans Major=Major MAP=Map diff --git a/rails/util/GameFileIO.java b/rails/util/GameFileIO.java index 59f0142..628ba98 100644 --- a/rails/util/GameFileIO.java +++ b/rails/util/GameFileIO.java @@ -1,29 +1,15 @@ package rails.util; -import java.io.EOFException; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; +import java.util.*; import org.apache.log4j.Logger; import rails.common.DisplayBuffer; import rails.common.LocalText; import rails.common.parser.ConfigurationException; -import rails.game.Game; -import rails.game.GameManager; -import rails.game.GameManagerI; -import rails.game.ReportBuffer; +import rails.game.*; import rails.game.action.PossibleAction; /** @@ -36,7 +22,7 @@ public class GameFileIO { protected static Logger log = Logger.getLogger(Game.class.getPackage().getName()); - + private GameData gameData = new GameData(); // fields for data load @@ -44,26 +30,26 @@ public class GameFileIO { private Game loadedGame = null; private boolean dataLoadDone = false; private boolean initialized = false; - + // fields for data save private boolean initSave = false; public String getGameDataAsText() { return gameData.metaDataAsText() + gameData.gameOptionsAsText() + gameData.playerNamesAsText(); } - + public Game getGame() { return loadedGame; } - + public List<PossibleAction> getActions() { return gameData.actions; } - + public void setActions(List<PossibleAction> actions) { gameData.actions = actions; } - + public SortedMap<Integer, String> getComments() { return gameData.userComments; } @@ -71,12 +57,12 @@ public class GameFileIO { public void setComments(SortedMap<Integer, String> comments) { gameData.userComments = comments; } - + @SuppressWarnings("unchecked") public void loadGameData(String filepath) { dataLoadDone = true; - + log.info("Loading game from file " + filepath); String filename = filepath.replaceAll(".*[/\\\\]", ""); @@ -93,7 +79,7 @@ public class GameFileIO { // Allow for older saved file versions. gameData.meta.version = "pre-1.0.7"; } - + log.info("Reading Rails " + gameData.meta.version +" saved file "+filename); if (object instanceof String) { @@ -106,30 +92,30 @@ public class GameFileIO { gameData.meta.fileVersionID = (Long) object; log.debug("Saved versionID="+gameData.meta.fileVersionID+" (object="+object+")"); long GMsaveFileVersionID = GameManager.saveFileVersionID; - + if (gameData.meta.fileVersionID != GMsaveFileVersionID) { throw new Exception("Save version " + gameData.meta.fileVersionID - + " is incompatible with current version " - + GMsaveFileVersionID); + + " is incompatible with current version " + + GMsaveFileVersionID); } // read name of saved game gameData.meta.gameName = (String) ois.readObject(); log.debug("Saved game="+ gameData.meta.gameName); - + // read selected game options and player names gameData.gameOptions = (Map<String, String>) ois.readObject(); log.debug("Selected game options = " + gameData.gameOptions); gameData.playerNames = (List<String>) ois.readObject(); log.debug("Player names = " + gameData.playerNames); - + } catch (Exception e) { dataLoadDone = false; log.fatal("Load failed", e); DisplayBuffer.add(LocalText.getText("LoadFailed", e.getMessage())); } } - + public Game initGame() throws ConfigurationException { // check if initial load was done @@ -152,105 +138,108 @@ public class GameFileIO { return loadedGame; } - - + + @SuppressWarnings("unchecked") public boolean loadActionsAndComments() throws ConfigurationException { if (!dataLoadDone) { throw new ConfigurationException("No game was loaded"); } - // Read game actions into gameData.listOfActions - try { - // read next object in stream - Object actionObject = null; - while (true) { // Single-pass loop. - try { - actionObject = ois.readObject(); - } catch (EOFException e) { - // Allow saved file at start of game (with no actions). - break; - - } - if (actionObject instanceof List) { - // Until Rails 1.3: one List of PossibleAction - gameData.actions = (List<PossibleAction>) actionObject; - } else if (actionObject instanceof PossibleAction) { - gameData.actions = new ArrayList<PossibleAction>(); - // Since Rails 1.3.1: separate PossibleActionsObjects - while (actionObject instanceof PossibleAction) { - gameData.actions.add((PossibleAction)actionObject); - try { - actionObject = ois.readObject(); - } catch (EOFException e) { - break; - } - } - } - break; - } - /** + // Read game actions into gameData.listOfActions + try { + // read next object in stream + Object actionObject = null; + while (true) { // Single-pass loop. + try { + actionObject = ois.readObject(); + } catch (EOFException e) { + // Allow saved file at start of game (with no actions). + break; + + } + if (actionObject instan... [truncated message content] |
From: Stefan F. <ste...@us...> - 2012-01-29 17:57:58
|
test/data/real/18TN_A.rails |binary test/data/real/18TN_A.report | 612 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 612 insertions(+) New commits: commit 6f3e1b37eec99dda21eef3bd7b66eb6a1c0716ea Author: Stefan Frey <ste...@we...> Date: Sun Jan 29 18:57:29 2012 +0100 18TN test game added diff --git a/test/data/real/18TN_A.rails b/test/data/real/18TN_A.rails new file mode 100644 index 0000000..6936faa Binary files /dev/null and b/test/data/real/18TN_A.rails differ diff --git a/test/data/real/18TN_A.report b/test/data/real/18TN_A.report new file mode 100644 index 0000000..2771851 --- /dev/null +++ b/test/data/real/18TN_A.report @@ -0,0 +1,612 @@ +GameIs,18TN +PlayerIs,1,Bob +PlayerIs,2,Chester +PlayerIs,3,Joshua +PlayerIs,4,Rob +PlayerCash,450 +BankHas,6200 +StartOfPhase,2 +BankSizeIs,6200 +StartOfInitialRound +HasPriority,Bob +BID_ITEM_LOG,Bob,75,M&C,375 +BID_ITEM_LOG,Chester,180,L&N,270 +BID_ITEM_LOG,Joshua,105,O&W,345 +BID_ITEM_LOG,Rob,185,L&N,265 +BuysItemFor,Bob,TCC,20 +BuysItemFor,Chester,ET&WNC,40 +BuysItemFor,Bob,M&C,75 +BuysItemFor,Joshua,O&W,105 +TO_AUCTION,L&N +BID_ITEM_LOG,Chester,190,L&N,220 +BID_ITEM_LOG,Rob,195,L&N,255 +PASSES,Chester +BuysItemFor,Rob,PRES_CERT_NAME,L&N,20,195 +FloatsWithCash,L&N,800 +Has,L&N,800 +Has,Bob,355 +Has,Chester,410 +Has,Joshua,345 +Has,Rob,255 +StartStockRound,1 +HasPriority,Joshua +PASSES,Joshua +BUY_SHARE_LOG,Rob,10,L&N,IPO,80 +BUY_SHARE_LOG,Bob,10,L&N,IPO,80 +START_COMPANY_LOG,Chester,SOU,65,130,2,20,BANK +BUY_SHARE_LOG,Joshua,10,L&N,IPO,80 +BUY_SHARE_LOG,Rob,10,L&N,IPO,80 +PASSES,Bob +BUY_SHARE_LOG,Chester,10,SOU,IPO,65 +BUY_SHARE_LOG,Joshua,10,L&N,IPO,80 +BUY_SHARE_LOG,Rob,10,L&N,IPO,80 +PASSES,Bob +BUY_SHARE_LOG,Chester,10,SOU,IPO,65 +BUY_SHARE_LOG,Joshua,10,L&N,IPO,80 +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,L&N,IPO,80 +BUY_SHARE_LOG,Chester,10,SOU,IPO,65 +PASSES,Joshua +Autopasses,Rob +PASSES,Bob +BUY_SHARE_LOG,Chester,10,SOU,IPO,65 +FloatsWithCash,SOU,650 +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,SOU,IPO,65 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,SOU,IPO,65 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,SOU,IPO,65 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +PASSES,Bob + +END_SR,1 +PRICE_MOVES_LOG,L&N,80,E3,90,E2 +SoldOut,L&N,80,E3,90,E2 +Has,L&N,800 +Has,SOU,650 +Has,Bob,0 +Has,Chester,20 +Has,Joshua,105 +Has,Rob,15 +START_OR,1.1 +ReceivesFor,Bob,5,TCC +ReceivesFor,Chester,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAtFor,L&N,9,B15,W,60 +LaysTileAt,L&N,5,B17,NE +LAYS_TOKEN_ON,L&N,B17,40 +CompanyDoesNotPayDividend,L&N +PRICE_MOVES_LOG,L&N,90,E2,80,D2 +BuysTrain,L&N,2,IPO,80 +FirstTrainBought,2 + +CompanyOperates,SOU,Chester +BuysPrivateFromFor,SOU,ET&WNC,Chester,40 +LaysTileAt,SOU,8,F19,W +LaysTileAt,SOU,8,E20,E +LaysTileAtFor,SOU,57,F17,W,40 +CompanyDoesNotPayDividend,SOU +PRICE_MOVES_LOG,SOU,65,D4,55,C4 +BuysTrain,SOU,2,IPO,80 + +EndOfOperatingRound,1.1 +ORWorthIncrease,Bob,1.1,-30 +ORWorthIncrease,Chester,1.1,-50 +ORWorthIncrease,Joshua,1.1,-10 +ORWorthIncrease,Rob,1.1,-50 +Has,L&N,620 +Has,SOU,490 +Has,Bob,20 +Has,Chester,70 +Has,Joshua,125 +Has,Rob,15 +StartStockRound,2 +HasPriority,Chester +PASSES,Chester +BUY_SHARE_LOG,Joshua,10,SOU,IPO,65 +Autopasses,Rob +PASSES,Bob +PASSES,Chester +Autopasses,Joshua + +END_SR,2 +PRICE_MOVES_LOG,L&N,80,D2,90,D1 +SoldOut,L&N,80,D2,90,D1 +PRICE_MOVES_LOG,SOU,55,C4,60,C3 +SoldOut,SOU,55,C4,60,C3 +Has,L&N,620 +Has,SOU,490 +Has,Bob,20 +Has,Chester,70 +Has,Joshua,60 +Has,Rob,15 +START_OR,2.1 +ReceivesFor,Bob,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,58,E10,NE +LaysTileAtFor,L&N,57,F11,NW,40 +CompanyRevenue,L&N,70 +CompanyPaysOutFull,L&N,70 +Payout,Joshua,21,3,10 +Payout,Bob,14,2,10 +Payout,Rob,35,5,10 +PRICE_MOVES_LOG,L&N,90,D1,100,E1 +BuysTrain,L&N,2,IPO,80 + +CompanyOperates,SOU,Chester +LaysTileAtFor,SOU,9,F15,E,60 +LaysTileAt,SOU,58,F13,E +CompanyRevenue,SOU,80 +CompanyPaysOutFull,SOU,80 +Payout,Joshua,8,1,10 +Payout,Bob,24,3,10 +Payout,Chester,48,6,10 +PRICE_MOVES_LOG,SOU,60,C3,70,D3 +BuysTrain,SOU,2,IPO,80 + +EndOfOperatingRound,2.1 +ORWorthIncrease,Bob,2.1,108 +ORWorthIncrease,Chester,2.1,108 +ORWorthIncrease,Joshua,2.1,89 +ORWorthIncrease,Rob,2.1,85 +Has,L&N,500 +Has,SOU,360 +Has,Bob,78 +Has,Chester,118 +Has,Joshua,109 +Has,Rob,50 +StartStockRound,3 +HasPriority,Rob +PASSES,Rob +SELL_SHARES_LOG,Bob,2,10,20,L&N,200 +PRICE_MOVES_LOG,L&N,100,E1,80,E3 +SELL_SHARES_LOG,Bob,3,10,30,SOU,210 +PRICE_MOVES_LOG,SOU,70,D3,55,D6 +START_COMPANY_LOG,Bob,TC,80,160,2,20,BANK +BUY_SHARE_LOG,Chester,10,L&N,Pool,80 +BUY_SHARE_LOG,Joshua,10,L&N,Pool,80 +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,TC,IPO,80 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,TC,IPO,80 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,TC,IPO,80 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,TC,IPO,80 +FloatsWithCash,TC,800 +PASSES,Chester +Autopasses,Joshua +Autopasses,Rob +PASSES,Bob + +END_SR,3 +PRICE_MOVES_LOG,L&N,80,E3,90,E2 +SoldOut,L&N,80,E3,90,E2 +Has,L&N,500 +Has,SOU,360 +Has,TC,800 +Has,Bob,8 +Has,Chester,38 +Has,Joshua,29 +Has,Rob,50 +START_OR,3.1 +ReceivesFor,Bob,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,5,G12,E +LAYS_TOKEN_ON,L&N,G12,100 +CompanyRevenue,L&N,120 +CompanyPaysOutFull,L&N,120 +Payout,Joshua,48,4,10 +Payout,Rob,60,5,10 +Payout,Chester,12,1,10 +PRICE_MOVES_LOG,L&N,90,E2,100,F2 + +CompanyOperates,TC,Bob +CompanyDoesNotPayDividend,TC +PRICE_MOVES_LOG,TC,80,E3,70,D3 +BuysTrain,TC,2,IPO,80 +All 2-trains are sold out, 3-trains now available + +CompanyOperates,SOU,Chester +CompanyRevenue,SOU,110 +CompanyPaysOutFull,SOU,110 +Payout,Joshua,11,1,10 +Payout,Chester,66,6,10 +Payout,SOU,33,3,10 +PRICE_MOVES_LOG,SOU,55,D6,65,E6 +BuysTrain,SOU,3,IPO,180 +FirstTrainBought,3 +StartOfPhase,3 + +EndOfOperatingRound,3.1 +ORWorthIncrease,Bob,3.1,-40 +ORWorthIncrease,Chester,3.1,148 +ORWorthIncrease,Joshua,3.1,129 +ORWorthIncrease,Rob,3.1,110 +Has,L&N,400 +Has,SOU,223 +Has,TC,720 +Has,Bob,28 +Has,Chester,116 +Has,Joshua,108 +Has,Rob,110 +StartStockRound,4 +HasPriority,Chester +BUY_SHARE_LOG,Chester,10,TC,IPO,80 +SELL_SHARES_LOG,Joshua,4,10,40,L&N,400 +PRICE_MOVES_LOG,L&N,100,F2,75,F5 +SELL_SHARE_LOG,Joshua,10,SOU,65 +PRICE_MOVES_LOG,SOU,65,E6,60,E7 +START_COMPANY_LOG,Joshua,GMO,90,180,2,20,BANK +BUY_SHARE_LOG,Rob,10,L&N,Pool,75 +Autopasses,Bob +Autopasses,Chester +BUY_SHARE_LOG,Joshua,10,GMO,IPO,90 +Autopasses,Rob +Autopasses,Bob +Autopasses,Chester +BUY_SHARE_LOG,Joshua,10,GMO,IPO,90 +Autopasses,Rob +Autopasses,Bob +Autopasses,Chester +BUY_SHARE_LOG,Joshua,10,GMO,IPO,90 +Autopasses,Rob +Autopasses,Bob +Autopasses,Chester +BUY_SHARE_LOG,Joshua,10,GMO,IPO,90 +FloatsWithCash,GMO,900 +Autopasses,Rob +Autopasses,Bob +Autopasses,Chester +PASSES,Joshua + +END_SR,4 +Has,GMO,900 +Has,L&N,400 +Has,SOU,223 +Has,TC,720 +Has,Bob,28 +Has,Chester,36 +Has,Joshua,33 +Has,Rob,35 +START_OR,4.1 +ReceivesFor,Bob,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,GMO,Joshua +LaysTileAt,GMO,6,H7,NE +LaysTileAt,GMO,8,F7,SW +CompanyDoesNotPayDividend,GMO +PRICE_MOVES_LOG,GMO,90,E2,80,D2 +BuysTrain,GMO,3,IPO,180 + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,15,B17,SE +CompanyRevenue,L&N,140 +CompanyPaysOutFull,L&N,140 +Payout,Chester,14,1,10 +Payout,Rob,84,6,10 +Payout,L&N,42,3,10 +PRICE_MOVES_LOG,L&N,75,F5,80,G5 +BuysTrain,L&N,3,IPO,180 + +CompanyOperates,TC,Bob +LaysTileAtFor,TC,8,C18,SW,60 +LaysTileAt,TC,8,D17,NE +LAYS_TOKEN_ON,TC,B17,40 +CompanyRevenue,TC,80 +CompanyPaysOutFull,TC,80 +Payout,Chester,8,1,10 +Payout,Bob,48,6,10 +PRICE_MOVES_LOG,TC,70,D3,80,E3 +BuysTrain,TC,3,IPO,180 +StartOfPhase,3½ + +CompanyOperates,SOU,Chester +LaysTileAt,SOU,619,G12,SW +CompanyRevenue,SOU,140 +CompanyPaysOutFull,SOU,140 +Payout,Chester,84,6,10 +Payout,SOU,56,4,10 +PRICE_MOVES_LOG,SOU,60,E7,65,E6 + +EndOfOperatingRound,4.1 +ORWorthIncrease,Bob,4.1,128 +ORWorthIncrease,Chester,4.1,151 +ORWorthIncrease,Joshua,4.1,-40 +ORWorthIncrease,Rob,4.1,114 +Has,GMO,720 +Has,L&N,262 +Has,SOU,289 +Has,TC,440 +Has,Bob,96 +Has,Chester,142 +Has,Joshua,53 +Has,Rob,119 +START_OR,4.2 +ReceivesFor,Bob,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,Bob,15,M&C +ReceivesFor,Joshua,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,15,F17,E +LAYS_TOKEN_ON,L&N,F17,100 +CompanyRevenue,L&N,200 +CompanyPaysOutFull,L&N,200 +Payout,Chester,20,1,10 +Payout,Rob,120,6,10 +Payout,L&N,60,3,10 +PRICE_MOVES_LOG,L&N,80,G5,85,G4 + +CompanyOperates,TC,Bob +BuysPrivateFromFor,TC,TCC,Bob,40 +BuysPrivateFromFor,TC,M&C,Bob,120 +LaysTileAt,TC,8,H5,NW +LaysTileAt,TC,599,F11,NE +CompanyRevenue,TC,110 +CompanyPaysOutFull,TC,110 +Payout,Bob,66,6,10 +Payout,Chester,11,1,10 +PRICE_MOVES_LOG,TC,80,E3,90,F3 + +CompanyOperates,GMO,Joshua +LaysTileAt,GMO,9,I6,SW +LaysTileAt,GMO,8,E6,NE +BuysPrivateFromFor,GMO,O&W,Joshua,200 +CompanyRevenue,GMO,0 +CompanyDoesNotPayDividend,GMO +BuysTrain,GMO,3,IPO,180 +All 3-trains are sold out, 4-trains now available + +CompanyOperates,SOU,Chester +LaysTileAt,SOU,9,E12,SW +LaysTileAt,SOU,8,D13,SW +LAYS_TOKEN_ON,SOU,F11,40 +CompanyRevenue,SOU,230 +CompanyPaysOutFull,SOU,230 +Payout,Chester,138,6,10 +Payout,SOU,92,4,10 +PRICE_MOVES_LOG,SOU,65,E6,70,E5 +BuysTrain,SOU,4,IPO,300 +FirstTrainBought,4 +StartOfPhase,4 + +EndOfOperatingRound,4.2 +ORWorthIncrease,Bob,4.2,216 +ORWorthIncrease,Chester,4.2,214 +ORWorthIncrease,Joshua,4.2,120 +ORWorthIncrease,Rob,4.2,150 +Has,GMO,340 +Has,L&N,222 +Has,SOU,51 +Has,TC,280 +Has,Bob,342 +Has,Chester,311 +Has,Joshua,273 +Has,Rob,239 +StartStockRound,5 +HasPriority,Rob +SELL_SHARES_LOG,Rob,2,10,20,L&N,170 +PRICE_MOVES_LOG,L&N,85,G4,80,G5 +START_COMPANY_LOG,Rob,IC,65,195,3,30,BANK +SELL_SHARE_LOG,Bob,10,TC,90 +PRICE_MOVES_LOG,TC,90,F3,80,F4 +BUY_SHARE_LOG,Bob,10,SOU,Pool,70 +SELL_SHARE_LOG,Chester,10,TC,80 +PRICE_MOVES_LOG,TC,80,F4,75,F5 +SELL_SHARE_LOG,Chester,10,SOU,70 +PRICE_MOVES_LOG,SOU,70,E5,65,E6 +START_COMPANY_LOG,Chester,NC,75,150,2,20,BANK +BUY_SHARE_LOG,Joshua,10,SOU,Pool,65 +BUY_SHARE_LOG,Rob,10,IC,IPO,65 +BUY_SHARE_LOG,Bob,10,SOU,Pool,65 +BUY_SHARE_LOG,Chester,10,GMO,IPO,90 +BUY_SHARE_LOG,Joshua,10,SOU,Pool,65 +BUY_SHARE_LOG,Rob,10,IC,IPO,65 +BUY_SHARE_LOG,Bob,10,SOU,Pool,65 +BUY_SHARE_LOG,Chester,10,NC,IPO,75 +BUY_SHARE_LOG,Joshua,10,TC,Pool,75 +BUY_SHARE_LOG,Rob,10,IC,IPO,65 +FloatsWithCash,IC,650 +BUY_SHARE_LOG,Bob,10,IC,IPO,65 +BUY_SHARE_LOG,Chester,10,NC,IPO,75 +SELL_SHARE_LOG,Chester,10,GMO,80 +PRICE_MOVES_LOG,GMO,80,D2,70,D3 +BUY_SHARE_LOG,Joshua,10,IC,IPO,65 +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,IC,IPO,65 +SELL_SHARES_LOG,Bob,2,10,20,IC,130 +PRICE_MOVES_LOG,IC,65,D4,55,D6 +BUY_SHARE_LOG,Chester,10,NC,IPO,75 +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,GMO,Pool,70 +BUY_SHARE_LOG,Chester,10,NC,IPO,75 +FloatsWithCash,NC,750 +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,NC,IPO,75 +Autopasses,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,NC,IPO,75 +SELL_SHARES_LOG,Bob,2,10,20,NC,150 +PRICE_MOVES_LOG,NC,75,E4,65,E6 +Autopasses,Chester +Autopasses,Joshua +Autopasses,Rob +SELL_SHARE_LOG,Bob,10,SOU,65 +PRICE_MOVES_LOG,SOU,65,E6,60,E7 +BUY_SHARE_LOG,Bob,10,L&N,Pool,80 +Autopasses,Chester +Autopasses,Joshua +Autopasses,Rob +BUY_SHARE_LOG,Bob,10,GMO,IPO,90 +Autopasses,Chester +Autopasses,Joshua +Autopasses,Rob +PASSES,Bob + +END_SR,5 +Has,GMO,340 +Has,IC,650 +Has,L&N,222 +Has,NC,750 +Has,SOU,51 +Has,TC,280 +Has,Bob,57 +Has,Chester,1 +Has,Joshua,3 +Has,Rob,19 +START_OR,5.1 +ReceivesFor,TC,5,TCC +ReceivesFor,SOU,10,ET&WNC +ReceivesFor,TC,15,M&C +ReceivesFor,GMO,20,O&W + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,141,E10,SW +CompanyRevenue,L&N,110 +CompanyWithholds,L&N,110 +PRICE_MOVES_LOG,L&N,80,G5,75,F5 +BuysTrain,L&N,4,IPO,300 + +CompanyOperates,TC,Bob +LaysTileAt,TC,24,C12,NE +CompanyRevenue,TC,120 +CompanyPaysOutFull,TC,120 +Payout,Bob,60,5,10 +Payout,Joshua,12,1,10 +Payout,TC,12,1,10 +PRICE_MOVES_LOG,TC,75,F5,80,G5 +BuysTrain,TC,4,IPO,300 +All 4-trains are sold out, 5-trains now available + +CompanyOperates,GMO,Joshua +LaysTileAtFor,GMO,6,D7,NE,40 +LaysTileAt,GMO,8,C6,SE +CompanyRevenue,GMO,150 +CompanyPaysOutFull,GMO,150 +Payout,Bob,30,2,10 +Payout,Joshua,90,6,10 +PRICE_MOVES_LOG,GMO,70,D3,80,E3 + +CompanyOperates,NC,Chester +LaysTileAtFor,NC,8,H13,NW,60 +LaysTileAt,NC,9,G10,W +CompanyDoesNotPayDividend,NC +PRICE_MOVES_LOG,NC,65,E6,55,D6 +BuysTrain,NC,5,IPO,450 +FirstTrainBought,5 +StartOfPhase,5 +PrivateCloses,TCC +PrivateCloses,ET&WNC +PrivateCloses,M&C +PrivateCloses,O&W +BuysTrain,NC,3,SOU,240 + +CompanyOperates,SOU,Chester +LaysTileAt,SOU,24,B15,W +CompanyRevenue,SOU,170 +CompanyWithholds,SOU,170 +PRICE_MOVES_LOG,SOU,60,E7,50,D7 +BuysTrain,SOU,5,IPO,450 +All 5-trains are sold out, 6-trains now available + +CompanyOperates,IC,Rob +LaysTileAt,IC,619,D7,W +CompanyDoesNotPayDividend,IC +PRICE_MOVES_LOG,IC,55,D6,45,C6 +BuysTrain,IC,6,IPO,630 +FirstTrainBought,6 +StartOfPhase,6 + +EndOfOperatingRound,5.1 +ORWorthIncrease,Bob,5.1,110 +ORWorthIncrease,Chester,5.1,-115 +ORWorthIncrease,Joshua,5.1,137 +ORWorthIncrease,Rob,5.1,-80 +Has,GMO,320 +Has,IC,20 +Has,L&N,32 +Has,NC,0 +Has,SOU,21 +Has,TC,12 +Has,Bob,147 +Has,Chester,1 +Has,Joshua,105 +Has,Rob,19 +START_OR,5.2 + +CompanyOperates,TC,Bob +LaysTileAt,TC,170,F11,SW +CompanyRevenue,TC,190 +CompanyPaysOutFull,TC,190 +Payout,Bob,95,5,10 +Payout,Joshua,19,1,10 +Payout,TC,19,1,10 +PRICE_MOVES_LOG,TC,80,G5,85,G4 + +CompanyOperates,GMO,Joshua +LaysTileAt,GMO,14,G6,NW +LAYS_TOKEN_ON,GMO,D7,40 +CompanyDoesNotPayDividend,GMO +PRICE_MOVES_LOG,GMO,80,E3,70,D3 +PlayerMustSellShares,Joshua,226 +SELL_SHARES_LOG,Joshua,1,10,10,TC,85 +PRICE_MOVES_LOG,TC,85,G4,80,G5 +SELL_SHARES_LOG,Joshua,1,10,10,IC,45 +PRICE_MOVES_LOG,IC,45,C6,40,C7 +SELL_SHARES_LOG,Joshua,2,10,20,SOU,100 +PresidentAddsCash,GMO,Joshua,350 +BuysTrain,GMO,6,IPO,630 +All 6-trains are sold out, 8-trains now available +StartOfPhase,6½ + +CompanyOperates,L&N,Rob +LaysTileAt,L&N,8,D9,SE +LaysTileAt,L&N,8,E18,NW +CompanyRevenue,L&N,190 +CompanyWithholds,L&N,190 +PRICE_MOVES_LOG,L&N,75,F5,70,E5 +TrainsObsoleteRusted,4,L&N +PlayerMustSellShares,Rob,459 +SELL_SHARES_LOG,Rob,2,10,20,IC,80 +SELL_SHARES_LOG,Rob,1,10,10,L&N,70 +PRICE_MOVES_LOG,L&N,70,E5,65,E6 +PlayerIsBankrupt,Rob +GameOver +EoGWinnerBob! +EoGFinalRanking : +1. 947 Bob +2. 646 Chester +3. 424 Joshua +4. 355 Rob |
From: Stefan F. <ste...@us...> - 2012-01-29 15:58:26
|
data/18TN/Game.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) New commits: commit 18c9e92b41cbbf6d2c386682c4354b0a485bd7c8 Author: Stefan Frey <ste...@we...> Date: Sun Jan 29 16:57:51 2012 +0100 Fixed wrong price of 6 train (630 => 600) Reported by Bob Probst diff --git a/data/18TN/Game.xml b/data/18TN/Game.xml index 191ee87..62f3209 100644 --- a/data/18TN/Game.xml +++ b/data/18TN/Game.xml @@ -79,7 +79,7 @@ <TrainType name="5" majorStops="5" cost="450" quantity="2"> <NewPhase phaseName="5"/> </TrainType> - <TrainType name="6" majorStops="6" cost="630" quantity="2"> + <TrainType name="6" majorStops="6" cost="600" quantity="2"> <NewPhase phaseName="6"/> <NewPhase phaseName="6½" trainIndex="2"/> </TrainType> |
From: Frederick W. <fre...@us...> - 2012-01-29 06:13:07
|
LocalisedText.properties | 2 ++ data/Properties.xml | 2 ++ rails/sound/SoundConfig.java | 2 ++ rails/sound/SoundEventInterpreter.java | 18 +++++++++++++++++- rails/sound/SoundManager.java | 3 +++ rails/sound/SoundPlayer.java | 28 +++++++++++++++++++++------- rails/ui/swing/ORUIManager.java | 5 +++++ 7 files changed, 52 insertions(+), 8 deletions(-) New commits: commit b001a3100117b2591ec1eeb2ad52d863e9c37640 Author: Frederick Weld <fre...@gm...> Date: Sun Jan 29 07:10:57 2012 +0100 Added new sfx options (pass, rotate tile) Sound framework is notified of Rotate tile by ORUIManager (neither action nor model change). Design decision here is to put all such non-standard notification calls to the UI Managers (Game, OR) instead of the UI elements (GUIHex...) so that they do not spread over the complete UI layer. diff --git a/LocalisedText.properties b/LocalisedText.properties index df07a3b..8ef0a7f 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -213,6 +213,7 @@ Config.label.sound.backgroundMusic.startRound=Start Round Config.label.sound.backgroundMusic.stockRound=Stock Round (several files) Config.label.sound.backgroundMusic.operatingRound=Operating Round (several files) Config.label.sound.sfx=Sound Effects +Config.label.sound.sfx.gen.pass=Pass Config.label.sound.sfx.str.bidStartItem=Bid on Start Item Config.label.sound.sfx.str.buyStartItem=Buy Start Item Config.label.sound.sfx.or.buyPrivate=Buy Private (as a company) @@ -222,6 +223,7 @@ Config.label.sound.sfx.or.decision.split=Split Revenue Config.label.sound.sfx.or.decision.withhold=Withhold Revenue Config.label.sound.sfx.or.layTile=Lay Tile Config.label.sound.sfx.or.layToken=Lay Token +Config.label.sound.sfx.or.rotateTile=Rotate Tile Config.label.sound.sfx.or.setRevenue=Set Revenue Config.label.sound.sfx.sr.buyShare.president=Buy Share (of presided company) Config.label.sound.sfx.sr.buyShare.nonPresident=Buy Share (of other company) diff --git a/data/Properties.xml b/data/Properties.xml index ac703c0..d2a9153 100644 --- a/data/Properties.xml +++ b/data/Properties.xml @@ -73,6 +73,7 @@ </Section> <Section name="SFX"> <Property name="sound.sfx" type="LIST" values="disabled,enabled" /> + <Property name="sound.sfx.gen.pass" type="FILE" /> <Property name="sound.sfx.str.bidStartItem" type="FILE" /> <Property name="sound.sfx.str.buyStartItem" type="FILE" /> <Property name="sound.sfx.sr.openingBell" type="FILE" /> @@ -82,6 +83,7 @@ <Property name="sound.sfx.sr.sellShare.president" type="FILE" /> <Property name="sound.sfx.sr.sellShare.nonPresident" type="FILE" /> <Property name="sound.sfx.sr.companyFloats" type="FILE" /> + <Property name="sound.sfx.or.rotateTile" type="FILE" /> <Property name="sound.sfx.or.layTile" type="FILE" /> <Property name="sound.sfx.or.layToken" type="FILE" /> <Property name="sound.sfx.or.setRevenue" type="FILE" /> diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index c9ea6c5..14adb30 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -20,6 +20,7 @@ public class SoundConfig { public static final String KEY_BGM_OperatingRound = "sound.backgroundMusic.operatingRound"; public static final String KEY_BGM_EndOfGameRound = "sound.backgroundMusic.endOfGameRound"; public static final String KEY_SFX_Enabled = "sound.sfx"; + public static final String KEY_SFX_GEN_Pass = "sound.sfx.gen.pass"; public static final String KEY_SFX_STR_BidStartItem = "sound.sfx.str.bidStartItem"; public static final String KEY_SFX_STR_BuyStartItem = "sound.sfx.str.buyStartItem"; public static final String KEY_SFX_SR_OpeningBell = "sound.sfx.sr.openingBell"; @@ -29,6 +30,7 @@ public class SoundConfig { public static final String KEY_SFX_SR_SellShare_President = "sound.sfx.sr.sellShare.president"; public static final String KEY_SFX_SR_SellShare_NonPresident = "sound.sfx.sr.sellShare.nonPresident"; public static final String KEY_SFX_SR_CompanyFloats = "sound.sfx.sr.companyFloats"; + public static final String KEY_SFX_OR_RotateTile = "sound.sfx.or.rotateTile"; public static final String KEY_SFX_OR_LayTile = "sound.sfx.or.layTile"; public static final String KEY_SFX_OR_LayToken = "sound.sfx.or.layToken"; public static final String KEY_SFX_OR_SetRevenue = "sound.sfx.or.setRevenue"; diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java index f494655..1f5590c 100644 --- a/rails/sound/SoundEventInterpreter.java +++ b/rails/sound/SoundEventInterpreter.java @@ -69,9 +69,18 @@ public class SoundEventInterpreter { if (SoundConfig.isSFXEnabled()) { + //General actions + + if (action instanceof NullAction) { + if (((NullAction)action).getMode() == NullAction.PASS) { + player.playSFXByConfigKey (SoundConfig.KEY_SFX_GEN_Pass); + } + + } + //OR actions - if (action instanceof LayTile) { + else if (action instanceof LayTile) { player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile); } else if (action instanceof LayToken) { @@ -177,4 +186,11 @@ public class SoundEventInterpreter { public void notifyOfTimeWarp(boolean timeWarpMode) { SoundConfig.setSFXDisabled(timeWarpMode); } + public void notifyOfRotateTile() { + if (SoundConfig.isSFXEnabled()) { + //don't wait for prior SFX playing end, otherwise quickly repeated + //rotations would lead to a long queue of sequentially played sfx + player.playSFXByConfigKey(SoundConfig.KEY_SFX_OR_RotateTile,false); + } + } } diff --git a/rails/sound/SoundManager.java b/rails/sound/SoundManager.java index 0e04c4f..d3a9e33 100644 --- a/rails/sound/SoundManager.java +++ b/rails/sound/SoundManager.java @@ -58,4 +58,7 @@ public class SoundManager { public static void notifyOfTimeWarp(boolean timeWarpMode) { getInstance().eventInterpreter.notifyOfTimeWarp(timeWarpMode); } + public static void notifyOfRotateTile() { + getInstance().eventInterpreter.notifyOfRotateTile(); + } } diff --git a/rails/sound/SoundPlayer.java b/rails/sound/SoundPlayer.java index 2e53c03..45fbf8f 100644 --- a/rails/sound/SoundPlayer.java +++ b/rails/sound/SoundPlayer.java @@ -187,24 +187,38 @@ public class SoundPlayer { return pt; } - private void playSFX(PlayerThread newPlayerThread) { + private void playSFX(PlayerThread newPlayerThread,boolean waitForEndOfPriorSFX) { PlayerThread oldPlayerThread = adjustLastSFXThread(newPlayerThread); - newPlayerThread.setPriorThread(oldPlayerThread); + if (waitForEndOfPriorSFX) { + newPlayerThread.setPriorThread(oldPlayerThread); + } newPlayerThread.start(); } + /** + * SFX played after prior SFX playing has been completed + */ public void playSFX(String fileName) { - playSFX(new PlayerThread (fileName)); + playSFX(fileName,true); } + public void playSFX(String fileName, boolean waitForEndOfPriorSFX) { + playSFX(new PlayerThread (fileName),waitForEndOfPriorSFX); + } + /** + * SFX played after prior SFX playing has been completed + */ public void playSFXByConfigKey(String configKey) { - playSFX(SoundConfig.get(configKey)); + playSFXByConfigKey(configKey, true); + } + public void playSFXByConfigKey(String configKey, boolean waitForEndOfPriorSFX) { + playSFX(SoundConfig.get(configKey), waitForEndOfPriorSFX); } public void playSFXByConfigKey(String configKey,String parameter) { playSFX(SoundConfig.get(configKey,parameter)); } public void playSFX(String fileName, double playSoundProportion) { - playSFX(new PortionPlayerThread (fileName, 1 - playSoundProportion, 1)); + playSFX(new PortionPlayerThread (fileName, 1 - playSoundProportion, 1),true); } /** @@ -216,7 +230,7 @@ public class SoundPlayer { } public void playSFXWithFollowupBGM(String sfxFileName,String bgmFileName) { - playSFX(new PlayerThreadWithFollowupBGM (sfxFileName,bgmFileName)); + playSFX(new PlayerThreadWithFollowupBGM (sfxFileName,bgmFileName),true); } /** @@ -227,7 +241,7 @@ public class SoundPlayer { playSFXWithFollowupBGM( SoundConfig.get(sfxConfigKey),SoundConfig.get(bgmConfigKey)); } - + public void playBGM(String backgroundMusicFileName) { LoopPlayerThread newPlayerThread = new LoopPlayerThread(backgroundMusicFileName); LoopPlayerThread oldPlayerThread = adjustLastBGMThread(newPlayerThread); diff --git a/rails/ui/swing/ORUIManager.java b/rails/ui/swing/ORUIManager.java index f10d2a4..89ef997 100644 --- a/rails/ui/swing/ORUIManager.java +++ b/rails/ui/swing/ORUIManager.java @@ -663,6 +663,11 @@ public class ORUIManager implements DialogOwner { if (localStep == ROTATE_OR_CONFIRM_TILE && clickedHex == selectedHex) { selectedHex.rotateTile(); + //directly inform sound framework of "rotate tile" as this is + //neither an action nor a model change + //call not put to GUIHex so that sound notification calls are + //centrally done by UIManagers (Game, OR) + SoundManager.notifyOfRotateTile(); return true; } else { |
From: Frederick W. <fre...@us...> - 2012-01-28 18:22:52
|
LocalisedText.properties | 37 ++- data/Properties.xml | 34 ++ rails/common/parser/Config.java | 2 rails/common/parser/ConfigItem.java | 9 rails/game/Game.java | 7 rails/game/GameManager.java | 5 rails/game/GameManagerI.java | 2 rails/game/OperatingRound.java | 3 rails/game/Phase.java | 3 rails/game/PublicCompany.java | 4 rails/game/PublicCompanyI.java | 2 rails/game/StockRound.java | 3 rails/game/specific/_1880/OperatingRound_1880.java | 3 rails/sound/BackgroundMusicManager.java | 174 -------------- rails/sound/SoundConfig.java | 82 ++++++ rails/sound/SoundContext.java | 137 +++++++++++ rails/sound/SoundEventInterpreter.java | 180 +++++++++++++++ rails/sound/SoundManager.java | 61 +++++ rails/sound/SoundPlayer.java | 250 +++++++++++++++++++++ rails/ui/swing/ConfigWindow.java | 17 + rails/ui/swing/GameSetupWindow.java | 4 rails/ui/swing/GameUIManager.java | 8 rails/ui/swing/ORUIManager.java | 7 rails/ui/swing/ReportWindowDynamic.java | 9 24 files changed, 832 insertions(+), 211 deletions(-) New commits: commit c9ae6202c1b83402661f2bf47c95d01d695e53f4 Author: Frederick Weld <fre...@gm...> Date: Sat Jan 28 14:15:45 2012 +0100 Added stock market opening bell Background music only changes after bell ringing is completed (as in SimTex's 1830). diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index f6dfd8b..c9ea6c5 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -22,7 +22,6 @@ public class SoundConfig { public static final String KEY_SFX_Enabled = "sound.sfx"; public static final String KEY_SFX_STR_BidStartItem = "sound.sfx.str.bidStartItem"; public static final String KEY_SFX_STR_BuyStartItem = "sound.sfx.str.buyStartItem"; - //TODO Opening Bell public static final String KEY_SFX_SR_OpeningBell = "sound.sfx.sr.openingBell"; public static final String KEY_SFX_SR_NewPresident = "sound.sfx.sr.newPresident"; public static final String KEY_SFX_SR_BuyShare_President = "sound.sfx.sr.buyShare.president"; diff --git a/rails/sound/SoundContext.java b/rails/sound/SoundContext.java index 13b4c5a..4d4be08 100644 --- a/rails/sound/SoundContext.java +++ b/rails/sound/SoundContext.java @@ -69,9 +69,14 @@ public class SoundContext { + averageRevenue * (1 - slidingAverageAdjustmentFactor); } - private void playBackgroundMusic() { + /** + * @return true if new background music is played + */ + private boolean playBackgroundMusic() { + boolean isNewMusicPlayed = false; + //do nothing if music is not enabled - if (!SoundConfig.isBGMEnabled()) return; + if (!SoundConfig.isBGMEnabled()) return false; String currentRoundConfigKey = null; if (currentRound instanceof StartRound) { @@ -91,9 +96,19 @@ public class SoundContext { currentRoundConfigKey, currentPhaseName); if (!newBackgroundMusicFileName.equals(currentBackgroundMusicFileName)) { currentBackgroundMusicFileName = newBackgroundMusicFileName; - player.playBGM(newBackgroundMusicFileName); + isNewMusicPlayed = true; + + //additionally play stock market opening bell if appropriate + if (SoundConfig.isSFXEnabled() && currentRound instanceof StockRound) { + player.playSFXWithFollowupBGM( + SoundConfig.get(SoundConfig.KEY_SFX_SR_OpeningBell), + newBackgroundMusicFileName); + } else { + player.playBGM(newBackgroundMusicFileName); + } } } + return isNewMusicPlayed; } public void notifyOfPhase(PhaseI newPhase) { if (!newPhase.equals(currentPhase)) { @@ -105,7 +120,14 @@ public class SoundContext { public void notifyOfRound(RoundI newRound) { if (!newRound.equals(currentRound)) { currentRound = newRound; - playBackgroundMusic(); + boolean isNewMusicPlayed = playBackgroundMusic(); + + //play stock market opening bell for stock rounds without new background music + //(e.g., if music is disabled but sfx is enabled) + if (!isNewMusicPlayed && SoundConfig.isSFXEnabled() + && currentRound instanceof StockRound) { + player.playSFXByConfigKey(SoundConfig.KEY_SFX_SR_OpeningBell); + } } } public void notifyOfGameSetup() { diff --git a/rails/sound/SoundPlayer.java b/rails/sound/SoundPlayer.java index b5614f9..2e53c03 100644 --- a/rails/sound/SoundPlayer.java +++ b/rails/sound/SoundPlayer.java @@ -149,6 +149,17 @@ public class SoundPlayer { if (player!=null) player.close(); } } + private class PlayerThreadWithFollowupBGM extends PlayerThread { + private String bgmFileName; + public PlayerThreadWithFollowupBGM(String fileName, String bgmFileName) { + super(fileName); + this.bgmFileName = bgmFileName; + } + public void play() { + super.play(); + playBGM(bgmFileName); + } + } private PlayerThread lastSFXThread = null; @@ -203,6 +214,19 @@ public class SoundPlayer { public void playSFXByConfigKey(String configKey, double playSoundProportion) { playSFX(SoundConfig.get(configKey), playSoundProportion); } + + public void playSFXWithFollowupBGM(String sfxFileName,String bgmFileName) { + playSFX(new PlayerThreadWithFollowupBGM (sfxFileName,bgmFileName)); + } + + /** + * Plays the specified SFX and, after completing SFX play, the specified BGM + * is launched. + */ + public void playSFXWithFollowupBGMByConfigKey(String sfxConfigKey, String bgmConfigKey) { + playSFXWithFollowupBGM( + SoundConfig.get(sfxConfigKey),SoundConfig.get(bgmConfigKey)); + } public void playBGM(String backgroundMusicFileName) { LoopPlayerThread newPlayerThread = new LoopPlayerThread(backgroundMusicFileName); commit e67cb1a9452a655e75ba3450f79fbb3bef710157 Author: Frederick Weld <fre...@gm...> Date: Sat Jan 28 13:06:53 2012 +0100 Considered load, timewarp, music/sfx config for enabling sounds Now, sound framework correctly handles these situations: - timewarp (sfx disabled) - game loading (sfx/music disabled) - changing enabled/disabled config within the game In order to achieve this, some parts of rails had to be adjusted: - new config item option that init is executed even from the game setup - dynamic reported window now correctly first sets the time warp mode and only then goes to the clicked the step. diff --git a/data/Properties.xml b/data/Properties.xml index 5dd4f7b..ac703c0 100644 --- a/data/Properties.xml +++ b/data/Properties.xml @@ -63,7 +63,8 @@ </Section> <Section name="Music"> <Property name="sound.backgroundMusic" type="LIST" values="disabled,enabled" - initClass="rails.sound.SoundManager" initMethod="init"/> + initClass="rails.sound.SoundManager" initMethod="init" + alwaysCallInit="true"/> <Property name="sound.backgroundMusic.gameSetup" type="FILE" /> <Property name="sound.backgroundMusic.startRound" type="FILE" /> <Property name="sound.backgroundMusic.stockRound" type="STRING" /> diff --git a/rails/common/parser/Config.java b/rails/common/parser/Config.java index c7f64ed..107e888 100644 --- a/rails/common/parser/Config.java +++ b/rails/common/parser/Config.java @@ -145,7 +145,7 @@ public final class Config { continue; } userProperties.setProperty(item.name, item.getNewValue()); - if (applyInitMethods) item.callInitMethod(); + item.callInitMethod(applyInitMethods); log.debug("Changed property name = " + item.name + " to value = " + item.getNewValue()); item.setNewValue(null); } diff --git a/rails/common/parser/ConfigItem.java b/rails/common/parser/ConfigItem.java index dc9feb7..ab2bab6 100644 --- a/rails/common/parser/ConfigItem.java +++ b/rails/common/parser/ConfigItem.java @@ -33,6 +33,7 @@ public final class ConfigItem { // method call attributes private final String initClass; private final String initMethod; + private final boolean alwaysCallInit; private final boolean initParameter; @@ -75,6 +76,7 @@ public final class ConfigItem { // optional: init method attributes initClass = tag.getAttributeAsString("initClass"); initMethod = tag.getAttributeAsString("initMethod"); + alwaysCallInit = tag.getAttributeAsBoolean("alwaysCallInit",false); initParameter = tag.getAttributeAsBoolean("initParameter", false); // initialize newValue @@ -107,7 +109,12 @@ public final class ConfigItem { return Config.get(this.name); } - void callInitMethod() { + /** + * @param applyInitMethod Specifies whether init should be called. Can be overruled + * by an additional tag alwaysCallInit + */ + void callInitMethod(boolean applyInitMethod) { + if (!applyInitMethod && !alwaysCallInit) return; if (initClass == null || initMethod == null) return; // call without parameter diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index b1bd84b..f6dfd8b 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -39,6 +39,9 @@ public class SoundConfig { public static final String KEY_SFX_OR_BuyTrain = "sound.sfx.or.buyTrain"; public static final String KEY_SFX_OR_BuyPrivate = "sound.sfx.or.buyPrivate"; + //if set to true, sfx is reported not to be enabled irrespective of the configuration + private static boolean isSFXDisabled = false; + public static String get(String configKey) { return get(configKey,null); } @@ -69,10 +72,12 @@ public class SoundConfig { return isEnabled(KEY_BGM_Enabled); } public static boolean isSFXEnabled() { - return isEnabled(KEY_SFX_Enabled); + return isEnabled(KEY_SFX_Enabled) && !isSFXDisabled; } private static boolean isEnabled(String key) { - //TODO add consideration for load replays (temporary disabled) return "enabled".equals(get(key)); } + public static void setSFXDisabled(boolean timeWarpMode) { + isSFXDisabled = timeWarpMode; + } } diff --git a/rails/sound/SoundContext.java b/rails/sound/SoundContext.java index 01ae6fd..13b4c5a 100644 --- a/rails/sound/SoundContext.java +++ b/rails/sound/SoundContext.java @@ -33,8 +33,23 @@ public class SoundContext { } public void notifyOfMusicEnablement(boolean musicEnabled) { - // TODO notifyOfMusicEnablement - + if (!musicEnabled && player.isBGMPlaying()) { + player.stopBGM(); + } + if (musicEnabled && !player.isBGMPlaying()) { + String musicFileNamePriorToDisable = currentBackgroundMusicFileName; + + //try to start BGM based on rounds / phases + currentBackgroundMusicFileName = null; + playBackgroundMusic(); + + //if no BGM could be started, replay the music that was active before disabling + //BGM music + if (currentBackgroundMusicFileName == null) { + currentBackgroundMusicFileName = musicFileNamePriorToDisable; + player.playBGM(musicFileNamePriorToDisable); + } + } } public void notifyOfSetRevenue(int actualRevenue) { @@ -93,5 +108,8 @@ public class SoundContext { playBackgroundMusic(); } } - + public void notifyOfGameSetup() { + currentBackgroundMusicFileName = SoundConfig.get(SoundConfig.KEY_BGM_GameSetup); + if (SoundConfig.isBGMEnabled()) player.playBGM(currentBackgroundMusicFileName); + } } diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java index 09ed9a6..f494655 100644 --- a/rails/sound/SoundEventInterpreter.java +++ b/rails/sound/SoundEventInterpreter.java @@ -9,6 +9,10 @@ import rails.game.state.*; /** * Converts processed actions and model updates to triggers for playing sounds. + * + * Model observers get their own inner classes since their constructors are parameterized + * (needed to initialize member variables among others - especially important if game is + * loaded). * * @author Frederick Weld * @@ -20,6 +24,7 @@ public class SoundEventInterpreter { private Player formerPresident = null; public PresidentModelObserver(PublicCompanyI pc) { this.pc = pc; + if (pc != null) formerPresident = pc.getPresident(); } public void update(Observable o, Object arg) { if (formerPresident != pc.getPresident()) { @@ -31,6 +36,23 @@ public class SoundEventInterpreter { } } + private class CompanyFloatsModelObserver implements Observer { + private PublicCompanyI pc; + Boolean hasFloated = false; + public CompanyFloatsModelObserver(PublicCompanyI pc) { + this.pc = pc; + if (pc != null) hasFloated = pc.hasFloated(); + } + public void update(Observable o, Object arg) { + if (hasFloated != pc.hasFloated()) { + hasFloated = pc.hasFloated(); + if (SoundConfig.isSFXEnabled()) { + player.playSFXByConfigKey (SoundConfig.KEY_SFX_SR_CompanyFloats); + } + } + } + } + private SoundContext context; private SoundPlayer player; @@ -147,26 +169,12 @@ public class SoundEventInterpreter { for (PublicCompanyI c : gameManager.getCompanyManager().getAllPublicCompanies() ) { //presidency changes c.getPresidentModel().addObserver(new PresidentModelObserver(c)); - //company floats - c.getFloatedModel().addObserver(new Observer() { - Boolean hasFloated = false; - public void update(Observable o, Object arg) { - if (arg instanceof Boolean && arg != null) { - if (!((Boolean)arg).booleanValue() == hasFloated) { - hasFloated = ((Boolean)arg).booleanValue(); - if (SoundConfig.isSFXEnabled()) { - player.playSFXByConfigKey ( - SoundConfig.KEY_SFX_SR_CompanyFloats); - } - } - } - } - }); + c.getFloatedModel().addObserver(new CompanyFloatsModelObserver(c)); } } } - public void notifyOfGameSetup() { - if (SoundConfig.isBGMEnabled()) player.playBGMByConfigKey(SoundConfig.KEY_BGM_GameSetup); + public void notifyOfTimeWarp(boolean timeWarpMode) { + SoundConfig.setSFXDisabled(timeWarpMode); } } diff --git a/rails/sound/SoundManager.java b/rails/sound/SoundManager.java index 22d14f9..0e04c4f 100644 --- a/rails/sound/SoundManager.java +++ b/rails/sound/SoundManager.java @@ -2,7 +2,6 @@ package rails.sound; import rails.game.GameManagerI; import rails.game.action.PossibleAction; -import rails.game.action.SetDividend; /** * This is a singleton class as there should never be two @@ -54,6 +53,9 @@ public class SoundManager { * Called when game setup window initially opens */ public static void notifyOfGameSetup() { - getInstance().eventInterpreter.notifyOfGameSetup(); + getInstance().context.notifyOfGameSetup(); + } + public static void notifyOfTimeWarp(boolean timeWarpMode) { + getInstance().eventInterpreter.notifyOfTimeWarp(timeWarpMode); } } diff --git a/rails/sound/SoundPlayer.java b/rails/sound/SoundPlayer.java index ad73f1e..b5614f9 100644 --- a/rails/sound/SoundPlayer.java +++ b/rails/sound/SoundPlayer.java @@ -214,4 +214,13 @@ public class SoundPlayer { public void playBGMByConfigKey(String configKey) { playBGM(SoundConfig.get(configKey)); } + + public void stopBGM() { + LoopPlayerThread oldPlayerThread = adjustLastBGMThread(null); + if (oldPlayerThread != null) oldPlayerThread.interrupt(); + } + + public boolean isBGMPlaying() { + return (lastBGMThread != null); + } } diff --git a/rails/ui/swing/ReportWindowDynamic.java b/rails/ui/swing/ReportWindowDynamic.java index e2935da..a5c6128 100644 --- a/rails/ui/swing/ReportWindowDynamic.java +++ b/rails/ui/swing/ReportWindowDynamic.java @@ -20,6 +20,7 @@ import rails.game.ReportBuffer; import rails.game.action.GameAction; import rails.game.action.PossibleActions; import rails.game.move.MoveStack; +import rails.sound.SoundManager; import rails.ui.swing.elements.ActionButton; /** @@ -208,11 +209,12 @@ public class ReportWindowDynamic extends AbstractReportWindow implements Action public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + activateTimeWarp(); URL url = e.getURL(); -// String protocol = e.getURL().getProtocol(); +// String protocol = e.getURL().getProtocol(); int index = url.getPort(); gotoIndex(index + 1); - activateTimeWarp(); + toFront(); } } @@ -242,8 +244,8 @@ public class ReportWindowDynamic extends AbstractReportWindow implements Action gameUIManager.setEnabledAllWindows(false, this); timeWarpMode = true; closeable = false; + SoundManager.notifyOfTimeWarp(timeWarpMode); } - toFront(); } private void deactivateTimeWarp() { @@ -252,6 +254,7 @@ public class ReportWindowDynamic extends AbstractReportWindow implements Action playFromHereButton.setVisible(false); returnButton.setVisible(false); timeWarpMode = false; + SoundManager.notifyOfTimeWarp(timeWarpMode); closeable = true; } } commit 775ef65fbe5f73e84e2ecc420d7969a0597f59d3 Author: Frederick Weld <fre...@gm...> Date: Sat Jan 28 11:59:31 2012 +0100 Enhanced sound framework for rails 2.0 compliance The old BackgroundMusicManager is deleted together with all calls to him that had been placed inside the game engine. The new sound framework is notified as an observer to the relevant game models. Hence, it complies to the publish/subscriber paradigm that will be enforced in rails 2.0. As a sidenote, GameManagerI and PublicCompanyI had to be extended with a getter-method for required game models (getCurrentRoundModel and getFloatedModel respectively). diff --git a/LocalisedText.properties b/LocalisedText.properties index 0886408..df07a3b 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -213,6 +213,8 @@ Config.label.sound.backgroundMusic.startRound=Start Round Config.label.sound.backgroundMusic.stockRound=Stock Round (several files) Config.label.sound.backgroundMusic.operatingRound=Operating Round (several files) Config.label.sound.sfx=Sound Effects +Config.label.sound.sfx.str.bidStartItem=Bid on Start Item +Config.label.sound.sfx.str.buyStartItem=Buy Start Item Config.label.sound.sfx.or.buyPrivate=Buy Private (as a company) Config.label.sound.sfx.or.buyTrain=Buy Train (several files) Config.label.sound.sfx.or.decision.payout=Payout Revenue diff --git a/data/Properties.xml b/data/Properties.xml index fd9d582..5dd4f7b 100644 --- a/data/Properties.xml +++ b/data/Properties.xml @@ -72,6 +72,8 @@ </Section> <Section name="SFX"> <Property name="sound.sfx" type="LIST" values="disabled,enabled" /> + <Property name="sound.sfx.str.bidStartItem" type="FILE" /> + <Property name="sound.sfx.str.buyStartItem" type="FILE" /> <Property name="sound.sfx.sr.openingBell" type="FILE" /> <Property name="sound.sfx.sr.newPresident" type="FILE" /> <Property name="sound.sfx.sr.buyShare.president" type="FILE" /> diff --git a/rails/game/Game.java b/rails/game/Game.java index 3f7dfa8..a882493 100644 --- a/rails/game/Game.java +++ b/rails/game/Game.java @@ -11,7 +11,6 @@ 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 { @@ -147,16 +146,12 @@ 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); @@ -174,8 +169,6 @@ 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 886aa80..791dd01 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -13,6 +13,7 @@ import rails.common.*; import rails.common.parser.*; import rails.game.action.*; import rails.game.correct.*; +import rails.game.model.ModelObject; import rails.game.move.*; import rails.game.special.SpecialPropertyI; import rails.game.special.SpecialTokenLay; @@ -1423,6 +1424,10 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { return (RoundI) currentRound.get(); } + public ModelObject getCurrentRoundModel() { + return currentRound; + } + /* (non-Javadoc) * @see rails.game.GameManagerI#getCurrentPlayerIndex() */ diff --git a/rails/game/GameManagerI.java b/rails/game/GameManagerI.java index a321507..c7bc6d7 100644 --- a/rails/game/GameManagerI.java +++ b/rails/game/GameManagerI.java @@ -98,6 +98,8 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI { */ public abstract RoundI getCurrentRound(); + public abstract ModelObject getCurrentRoundModel(); + /** * @return Returns the currentPlayerIndex. */ diff --git a/rails/game/OperatingRound.java b/rails/game/OperatingRound.java index c7099a7..d799ad9 100644 --- a/rails/game/OperatingRound.java +++ b/rails/game/OperatingRound.java @@ -11,7 +11,6 @@ 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; /** @@ -107,8 +106,6 @@ 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 2e3f7b3..add140e 100644 --- a/rails/game/Phase.java +++ b/rails/game/Phase.java @@ -8,7 +8,6 @@ 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 { @@ -314,8 +313,6 @@ public class Phase implements PhaseI { } } - BackgroundMusicManager.setPhase(name); - if (actions != null && !actions.isEmpty()) { for (String actionName : actions.keySet()) { gameManager.processPhaseAction (actionName, actions.get(actionName)); diff --git a/rails/game/PublicCompany.java b/rails/game/PublicCompany.java index 3ad1c2c..3a8377c 100644 --- a/rails/game/PublicCompany.java +++ b/rails/game/PublicCompany.java @@ -1024,6 +1024,10 @@ public class PublicCompany extends Company implements PublicCompanyI { public boolean hasFloated() { return hasFloated.booleanValue(); } + + public ModelObject getFloatedModel() { + return hasFloated; + } /** * Has the company already operated? diff --git a/rails/game/PublicCompanyI.java b/rails/game/PublicCompanyI.java index ab08a06..ecd928f 100644 --- a/rails/game/PublicCompanyI.java +++ b/rails/game/PublicCompanyI.java @@ -96,6 +96,8 @@ public interface PublicCompanyI extends CompanyI, CashHolder, TokenHolder { */ public boolean hasFloated(); + + public ModelObject getFloatedModel(); /** * Has the company already operated? diff --git a/rails/game/StockRound.java b/rails/game/StockRound.java index 0d3fcf8..4f0b40b 100644 --- a/rails/game/StockRound.java +++ b/rails/game/StockRound.java @@ -8,7 +8,6 @@ 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 @@ -91,8 +90,6 @@ 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/game/specific/_1880/OperatingRound_1880.java b/rails/game/specific/_1880/OperatingRound_1880.java index 7d9a9ee..d3b094d 100644 --- a/rails/game/specific/_1880/OperatingRound_1880.java +++ b/rails/game/specific/_1880/OperatingRound_1880.java @@ -48,7 +48,6 @@ import rails.game.special.SpecialTrainBuy; import rails.game.specific._1880.PublicCompany_1880; import rails.game.specific._1880.GameManager_1880; import rails.game.state.EnumState; -import rails.sound.BackgroundMusicManager; /** * @author Martin @@ -169,8 +168,6 @@ public class OperatingRound_1880 extends OperatingRound { ReportBuffer.add(LocalText.getText("START_OR", thisOrNumber)); - BackgroundMusicManager.notifyOfOperatingRoundStart(); - for (Player player : gameManager.getPlayers()) { player.setWorthAtORStart(); } diff --git a/rails/sound/BackgroundMusicManager.java b/rails/sound/BackgroundMusicManager.java deleted file mode 100644 index ca34604..0000000 --- a/rails/sound/BackgroundMusicManager.java +++ /dev/null @@ -1,176 +0,0 @@ -/** - * - */ -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 { - //TODO Kill old music manager - - 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; - 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; - contextToMusicFileMapping = new HashMap<Context,String>(); - 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 { - stopMusic(); - 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() { - isMute = false; - playNewMusic(); - } - - private static void playNewMusic() { - if (!isMute && !isDisabled) { - 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; - boolean isKilled = false; - public void run() { - try { - 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) { - //if anything goes wrong, don't play anything - log.error(e); - } - } - public void interrupt() { - super.interrupt(); - isKilled = true; - if (player!=null) player.close(); - } - }; - playingThread.start(); - isPlaying = true; - } - } - } - } - private static void stopMusic() { - if (isPlaying) { - playingThread.interrupt(); - isPlaying = false; - currentMusicFileName = null; - } - } -} diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java index ef3bad3..b1bd84b 100644 --- a/rails/sound/SoundConfig.java +++ b/rails/sound/SoundConfig.java @@ -14,34 +14,24 @@ import rails.common.parser.Config; */ public class SoundConfig { public static final String KEY_BGM_Enabled = "sound.backgroundMusic"; - //TODO GameSetup public static final String KEY_BGM_GameSetup = "sound.backgroundMusic.gameSetup"; - //TODO StartRound public static final String KEY_BGM_StartRound = "sound.backgroundMusic.startRound"; - //TODO StockRound public static final String KEY_BGM_StockRound = "sound.backgroundMusic.stockRound"; - //TODO OperatingRound public static final String KEY_BGM_OperatingRound = "sound.backgroundMusic.operatingRound"; - //TODO EndOfGame Round public static final String KEY_BGM_EndOfGameRound = "sound.backgroundMusic.endOfGameRound"; public static final String KEY_SFX_Enabled = "sound.sfx"; + public static final String KEY_SFX_STR_BidStartItem = "sound.sfx.str.bidStartItem"; + public static final String KEY_SFX_STR_BuyStartItem = "sound.sfx.str.buyStartItem"; //TODO Opening Bell public static final String KEY_SFX_SR_OpeningBell = "sound.sfx.sr.openingBell"; - //TODO New president public static final String KEY_SFX_SR_NewPresident = "sound.sfx.sr.newPresident"; - //TODO Buy Share Pres public static final String KEY_SFX_SR_BuyShare_President = "sound.sfx.sr.buyShare.president"; - //TODO Buy Share non Pres public static final String KEY_SFX_SR_BuyShare_NonPresident = "sound.sfx.sr.buyShare.nonPresident"; - //TODO Sell Share Pres public static final String KEY_SFX_SR_SellShare_President = "sound.sfx.sr.sellShare.president"; - //TODO Sell Share non Pres public static final String KEY_SFX_SR_SellShare_NonPresident = "sound.sfx.sr.sellShare.nonPresident"; - //TODO Company Floats public static final String KEY_SFX_SR_CompanyFloats = "sound.sfx.sr.companyFloats"; public static final String KEY_SFX_OR_LayTile = "sound.sfx.or.layTile"; public static final String KEY_SFX_OR_LayToken = "sound.sfx.or.layToken"; - //TODO Set Revenue public static final String KEY_SFX_OR_SetRevenue = "sound.sfx.or.setRevenue"; public static final String KEY_SFX_OR_Decision_Payout = "sound.sfx.or.decision.payout"; public static final String KEY_SFX_OR_Decision_Split = "sound.sfx.or.decision.split"; @@ -75,13 +65,14 @@ public class SoundConfig { if (resultValue == null) resultValue = ""; return resultValue; } - public static boolean isMusicEnabled() { + public static boolean isBGMEnabled() { return isEnabled(KEY_BGM_Enabled); } public static boolean isSFXEnabled() { return isEnabled(KEY_SFX_Enabled); } private static boolean isEnabled(String key) { + //TODO add consideration for load replays (temporary disabled) return "enabled".equals(get(key)); } } diff --git a/rails/sound/SoundContext.java b/rails/sound/SoundContext.java index 9292371..01ae6fd 100644 --- a/rails/sound/SoundContext.java +++ b/rails/sound/SoundContext.java @@ -3,6 +3,8 @@ */ package rails.sound; +import rails.game.*; + /** * Takes care of the current context from a music/sfx perspective. * Reacts on context changes by triggering changes to the played music/sfx. @@ -11,10 +13,85 @@ package rails.sound; * */ public class SoundContext { - + private double averageRevenue = 50; + //to which degree (from 0=none to 1=full) is new revenue considered for determining + //the new average revenue value + private final static double slidingAverageAdjustmentFactor = 0.2; + //how much percent of the set revenue sfx is played if the revenue is average + private final static double averageSetRevenuePlaySoundProportion = 0.4; + //how much percent of the set revenue sfx is played if the revenue is epsilon; + private final static double minimumSetRevenuePlaySoundProportion = 0.167; + + private RoundI currentRound = null; + private PhaseI currentPhase = null; + private String currentBackgroundMusicFileName = null; + + private SoundPlayer player; + + public SoundContext(SoundPlayer player) { + this.player = player; + } + public void notifyOfMusicEnablement(boolean musicEnabled) { // TODO notifyOfMusicEnablement } + public void notifyOfSetRevenue(int actualRevenue) { + //ignore zero revenue + if (actualRevenue <= 0) return; + + double playSoundProportion = minimumSetRevenuePlaySoundProportion + + ( 1 - minimumSetRevenuePlaySoundProportion ) + * ( averageSetRevenuePlaySoundProportion - minimumSetRevenuePlaySoundProportion ) + * actualRevenue / averageRevenue; + if (playSoundProportion > 1) playSoundProportion = 1; + + player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_SetRevenue, + playSoundProportion); + + averageRevenue = actualRevenue * slidingAverageAdjustmentFactor + + averageRevenue * (1 - slidingAverageAdjustmentFactor); + } + + private void playBackgroundMusic() { + //do nothing if music is not enabled + if (!SoundConfig.isBGMEnabled()) return; + + String currentRoundConfigKey = null; + if (currentRound instanceof StartRound) { + currentRoundConfigKey = SoundConfig.KEY_BGM_StartRound; + } else if (currentRound instanceof StockRound) { + currentRoundConfigKey = SoundConfig.KEY_BGM_StockRound; + } else if (currentRound instanceof OperatingRound) { + currentRoundConfigKey = SoundConfig.KEY_BGM_OperatingRound; + } else if (currentRound instanceof EndOfGameRound) { + currentRoundConfigKey = SoundConfig.KEY_BGM_EndOfGameRound; + } + //only play anything if round is recognized and new music is to be played + if (currentRoundConfigKey != null) { + String currentPhaseName = ""; + if (currentPhase != null) currentPhaseName = currentPhase.getName(); + String newBackgroundMusicFileName = SoundConfig.get( + currentRoundConfigKey, currentPhaseName); + if (!newBackgroundMusicFileName.equals(currentBackgroundMusicFileName)) { + currentBackgroundMusicFileName = newBackgroundMusicFileName; + player.playBGM(newBackgroundMusicFileName); + } + } + } + public void notifyOfPhase(PhaseI newPhase) { + if (!newPhase.equals(currentPhase)) { + currentPhase = newPhase; + playBackgroundMusic(); + } + } + + public void notifyOfRound(RoundI newRound) { + if (!newRound.equals(currentRound)) { + currentRound = newRound; + playBackgroundMusic(); + } + } + } diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java index db40e1b..09ed9a6 100644 --- a/rails/sound/SoundEventInterpreter.java +++ b/rails/sound/SoundEventInterpreter.java @@ -1,7 +1,11 @@ package rails.sound; -import rails.game.GameManagerI; +import java.util.Observable; +import java.util.Observer; + +import rails.game.*; import rails.game.action.*; +import rails.game.state.*; /** * Converts processed actions and model updates to triggers for playing sounds. @@ -10,8 +14,27 @@ import rails.game.action.*; * */ public class SoundEventInterpreter { + + private class PresidentModelObserver implements Observer { + private PublicCompanyI pc; + private Player formerPresident = null; + public PresidentModelObserver(PublicCompanyI pc) { + this.pc = pc; + } + public void update(Observable o, Object arg) { + if (formerPresident != pc.getPresident()) { + formerPresident = pc.getPresident(); + if (SoundConfig.isSFXEnabled()) { + player.playSFXByConfigKey (SoundConfig.KEY_SFX_SR_NewPresident); + } + } + } + } + private SoundContext context; private SoundPlayer player; + + public SoundEventInterpreter (SoundContext context,SoundPlayer player) { this.context = context; this.player = player; @@ -19,7 +42,7 @@ public class SoundEventInterpreter { public void notifyOfActionProcessing(GameManagerI gm,PossibleAction action) { /** - * Interpretation of events for which only sfx is relevant + * Interpretation of events for which are only sfx is relevant */ if (SoundConfig.isSFXEnabled()) { @@ -33,6 +56,7 @@ public class SoundEventInterpreter { player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayToken); } else if (action instanceof SetDividend) { + //set revenue not treated here SetDividend sd = (SetDividend)action; if (sd.getRevenueAllocation() == SetDividend.PAYOUT) { player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_Decision_Payout); @@ -49,7 +73,100 @@ public class SoundEventInterpreter { } else if (action instanceof BuyPrivate) { player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_BuyPrivate); + } + + //SR actions + + else if (action instanceof BuyCertificate) { + BuyCertificate bc = (BuyCertificate)action; + String presidentName = ""; + if (bc.getCompany().getPresident() != null) { + presidentName = bc.getCompany().getPresident().getName(); + } + if (presidentName.equals(bc.getPlayerName())) { + player.playSFXByConfigKey (SoundConfig.KEY_SFX_SR_BuyShare_President); + } else { + player.playSFXByConfigKey (SoundConfig.KEY_SFX_SR_BuyShare_NonPresident); + } + + } else if (action instanceof SellShares) { + SellShares ss = (SellShares)action; + String presidentName = ""; + if (ss.getCompany().getPresident() != null) { + presidentName = ss.getCompany().getPresident().getName(); + } + if (presidentName.equals(ss.getPlayerName())) { + player.playSFXByConfigKey (SoundConfig.KEY_SFX_SR_SellShare_President); + } else { + player.playSFXByConfigKey (SoundConfig.KEY_SFX_SR_SellShare_NonPresident); + } + + } + + //Start Round actions + + else if (action instanceof rails.game.action.BidStartItem) { + player.playSFXByConfigKey (SoundConfig.KEY_SFX_STR_BidStartItem); + + } else if (action instanceof rails.game.action.BuyStartItem) { + player.playSFXByConfigKey (SoundConfig.KEY_SFX_STR_BuyStartItem); + + } + + } + } + public void notifyOfGameInit(GameManagerI gameManager) { + //subscribe to round changes + if (gameManager.getCurrentRoundModel() != null) { + gameManager.getCurrentRoundModel().addObserver( + new Observer() { + public void update(Observable o, Object arg) { + if (o instanceof State) { + State s = (State)o; + context.notifyOfRound((RoundI)s.get()); + } + } + }); + } + + //subscribe to phase changes + if (gameManager.getPhaseManager() != null) { + gameManager.getPhaseManager().getCurrentPhaseModel().addObserver( + new Observer() { + public void update(Observable o, Object arg) { + if (o instanceof State) { + State s = (State)o; + context.notifyOfPhase((PhaseI)s.get()); + } + } + }); + } + + //subscribe to company events + if (gameManager.getCompanyManager() != null) { + for (PublicCompanyI c : gameManager.getCompanyManager().getAllPublicCompanies() ) { + //presidency changes + c.getPresidentModel().addObserver(new PresidentModelObserver(c)); + + //company floats + c.getFloatedModel().addObserver(new Observer() { + Boolean hasFloated = false; + public void update(Observable o, Object arg) { + if (arg instanceof Boolean && arg != null) { + if (!((Boolean)arg).booleanValue() == hasFloated) { + hasFloated = ((Boolean)arg).booleanValue(); + if (SoundConfig.isSFXEnabled()) { + player.playSFXByConfigKey ( + SoundConfig.KEY_SFX_SR_CompanyFloats); + } + } + } + } + }); } } } + public void notifyOfGameSetup() { + if (SoundConfig.isBGMEnabled()) player.playBGMByConfigKey(SoundConfig.KEY_BGM_GameSetup); + } } diff --git a/rails/sound/SoundManager.java b/rails/sound/SoundManager.java index bc4f7cc..22d14f9 100644 --- a/rails/sound/SoundManager.java +++ b/rails/sound/SoundManager.java @@ -2,6 +2,7 @@ package rails.sound; import rails.game.GameManagerI; import rails.game.action.PossibleAction; +import rails.game.action.SetDividend; /** * This is a singleton class as there should never be two @@ -25,7 +26,7 @@ public class SoundManager { private SoundManager() { player = new SoundPlayer(); - context = new SoundContext(); + context = new SoundContext(player); eventInterpreter = new SoundEventInterpreter(context,player); } public static SoundManager getInstance() { @@ -33,9 +34,26 @@ public class SoundManager { return manager; } public static void init() { - getInstance().context.notifyOfMusicEnablement(SoundConfig.isMusicEnabled()); + getInstance().context.notifyOfMusicEnablement(SoundConfig.isBGMEnabled()); } public static void notifyOfActionProcessing(GameManagerI gm,PossibleAction action) { getInstance().eventInterpreter.notifyOfActionProcessing(gm,action); } + public static void notifyOfSetRevenue(int actualRevenue) { + if (SoundConfig.isSFXEnabled()) { + getInstance().context.notifyOfSetRevenue(actualRevenue); + } + } + /** + * Called when game engine has been instantiated for a specific game + */ + public static void notifyOfGameInit(GameManagerI gameManager) { + getInstance().eventInterpreter.notifyOfGameInit(gameManager); + } + /** + * Called when game setup window initially opens + */ + public static void notifyOfGameSetup() { + getInstance().eventInterpreter.notifyOfGameSetup(); + } } diff --git a/rails/sound/SoundPlayer.java b/rails/sound/SoundPlayer.java index d695a90..ad73f1e 100644 --- a/rails/sound/SoundPlayer.java +++ b/rails/sound/SoundPlayer.java @@ -6,7 +6,9 @@ package rails.sound; import java.io.BufferedInputStream; import java.io.FileInputStream; +import javazoom.jl.decoder.JavaLayerException; import javazoom.jl.player.Player; +import javazoom.jl.player.advanced.AdvancedPlayer; /** * Handles play requests for music and sfx. @@ -43,6 +45,16 @@ public class SoundPlayer { //wait until prior thread has finished playing if (priorThread != null) priorThread.waitForPlayingDone(); priorThread = null; //release handle + + play(); + + //wake the subsequent thread if there is one waiting + synchronized (this) { + notify(); + playingDone = true; + } + } + public void play() { try { FileInputStream fis = new FileInputStream(fileName); BufferedInputStream bis = new BufferedInputStream(fis); @@ -53,16 +65,95 @@ public class SoundPlayer { catch (Exception e) { //if anything goes wrong, don't play anything } - //wake the subsequent thread if there is one waiting - synchronized (this) { - notify(); - playingDone = true; + } + } + private class PortionPlayerThread extends PlayerThread { + private double startPos; + private double endPos; + /** + * @param startPos Relative offset [0..1] - first mp3 frame played + * @param endPos Relative offset [0..1] - last mp3 frame played + */ + public PortionPlayerThread(String fileName, double startPos, double endPos) { + super(fileName); + this.startPos = startPos; + this.endPos = endPos; + } + @Override + public void play() { + try { + FileInputStream fis = new FileInputStream(fileName); + BufferedInputStream bis = new BufferedInputStream(fis); + PortionPlayer player = new PortionPlayer(bis); + player.play(startPos, endPos); + player.close(); + } + catch (Exception e) { + //if anything goes wrong, don't play anything + } + } + } + private class PortionPlayer extends AdvancedPlayer { + BufferedInputStream bis; + public PortionPlayer(BufferedInputStream bis) throws JavaLayerException { + super(bis); + this.bis = bis; + } + /** + * @param startPos Relative offset [0..1] - first mp3 frame played + * @param endPos Relative offset [0..1] - last mp3 frame played + */ + public void play(double startPos, double endPos) { + try { + //first get number of frames + bis.mark(Integer.MAX_VALUE); + int frameNum = 0; + while (skipFrame()) { + frameNum++; + } + int startFrame = (int)Math.floor(startPos * frameNum); + int endFrame = (int)Math.ceil(endPos * frameNum); + if (startFrame < endFrame) { + bis.reset(); + play(startFrame, endFrame); + } + } catch (Exception e) { + //if anything goes wrong, don't play anything } } } + private class LoopPlayerThread extends PlayerThread { + boolean isStopped = false; + Player player = null; + public LoopPlayerThread(String fileName) { + super(fileName); + } + public void play() { + try { + while (!isStopped) { + FileInputStream fis = new FileInputStream(fileName); + BufferedInputStream bis = new BufferedInputStream(fis); + player = new Player(bis); + player.play(); + player.close(); + } + } + catch (Exception e) { + //if anything goes wrong, don't play anything + } + } + @Override + public void interrupt() { + super.interrupt(); + isStopped = true; + if (player!=null) player.close(); + } + } private PlayerThread lastSFXThread = null; + private LoopPlayerThread lastBGMThread = null; + /** * atomic switching of the pointer to the last thread which played an sfx. * @param newThread Player thread for the new sfx @@ -74,16 +165,53 @@ public class SoundPlayer { return pt; } - public void playSFX(String fileName) { - PlayerThread newPlayerThread = new PlayerThread (fileName); + /** + * atomic switching of the pointer to the last thread which played music. + * @param newThread Player thread for the new music + * @return Player thread which was the last to play music + */ + synchronized private LoopPlayerThread adjustLastBGMThread(LoopPlayerThread newThread) { + LoopPlayerThread pt = lastBGMThread; + lastBGMThread = newThread; + return pt; + } + + private void playSFX(PlayerThread newPlayerThread) { PlayerThread oldPlayerThread = adjustLastSFXThread(newPlayerThread); newPlayerThread.setPriorThread(oldPlayerThread); newPlayerThread.start(); } + + public void playSFX(String fileName) { + playSFX(new PlayerThread (fileName)); + } public void playSFXByConfigKey(String configKey) { playSFX(SoundConfig.get(configKey)); } public void playSFXByConfigKey(String configKey,String parameter) { playSFX(SoundConfig.get(configKey,parameter)); } + + public void playSFX(String fileName, double playSoundProportion) { + playSFX(new PortionPlayerThread (fileName, 1 - playSoundProportion, 1)); + } + + /** + * The latter part of the sfx is played. + * @param playSoundProportion The length of this part relatively to the overall sound duration. + */ + public void playSFXByConfigKey(String configKey, double playSoundProportion) { + playSFX(SoundConfig.get(configKey), playSoundProportion); + } + + public void playBGM(String backgroundMusicFileName) { + LoopPlayerThread newPlayerThread = new LoopPlayerThread(backgroundMusicFileName); + LoopPlayerThread oldPlayerThread = adjustLastBGMThread(newPlayerThread); + if (oldPlayerThread != null) oldPlayerThread.interrupt(); + newPlayerThread.start(); + } + + public void playBGMByConfigKey(String configKey) { + playBGM(SoundConfig.get(configKey)); + } } diff --git a/rails/ui/swing/GameSetupWindow.java b/rails/ui/swing/GameSetupWindow.java index d9652ec..e91880d 100644 --- a/rails/ui/swing/GameSetupWindow.java +++ b/rails/ui/swing/GameSetupWindow.java @@ -20,6 +20,7 @@ import rails.common.parser.Config; import rails.common.parser.GameOption; import rails.common.parser.GameInfo; import rails.game.*; +import rails.sound.SoundManager; import rails.util.*; /** @@ -147,6 +148,9 @@ public class GameSetupWindow extends JDialog implements ActionListener { // This needs to happen after we have a valid gameName. fillPlayersPane(); + + // Notify the sound manager about having started the setup menu + SoundManager.notifyOfGameSetup(); } private void populateGridBag() { diff --git a/rails/ui/swing/GameUIManager.java b/rails/ui/swing/GameUIManager.java index 5154bf1..81b700f 100644 --- a/rails/ui/swing/GameUIManager.java +++ b/rails/ui/swing/GameUIManager.java @@ -221,6 +221,9 @@ public class GameUIManager implements DialogOwner { // define configWindow configWindow = new ConfigWindow(true); configWindow.init(); + + // notify sound manager of game initialization + SoundManager.notifyOfGameInit(gameManager); } public void startLoadedGame() { diff --git a/rails/ui/swing/ORUIManager.java b/rails/ui/swing/ORUIManager.java index db96ac7..f10d2a4 100644 --- a/rails/ui/swing/ORUIManager.java +++ b/rails/ui/swing/ORUIManager.java @@ -17,6 +17,7 @@ import rails.game.action.*; import rails.game.correct.*; import rails.game.correct.MapCorrectionManager.ActionStep; import rails.game.special.*; +import rails.sound.SoundManager; import rails.ui.swing.elements.*; import rails.ui.swing.hexmap.GUIHex; import rails.ui.swing.hexmap.HexMap; @@ -493,6 +494,12 @@ public class ORUIManager implements DialogOwner { orPanel.stopRevenueUpdate(); log.debug("Set revenue amount is " + amount); action.setActualRevenue(amount); + + // notify sound manager of set revenue amount as soon as + // set revenue is pressed (not waiting for the completion + // of the set dividend action) + SoundManager.notifyOfSetRevenue(amount); + if (amount == 0 || action.getRevenueAllocation() != SetDividend.UNKNOWN) { log.debug("Allocation is known: " + action.getRevenueAllocation()); commit cd230ed207c83462c4eeeac9006abfeefca03669 Author: Frederick Weld <fre...@gm...> Date: Fri Jan 27 20:27:01 2012 +0100 Created new framework for playing music and sound effects Playing sounds (both bgm / sfx) is disabled by default. Background music (BGM) is configurable on a per-round-type and per-phase basis. (currently 5 round types supported) There are 15 sound effects (SFX) types, of which - one is parameterizable (train type for buy train) - one is played for a varying amount of time (set revenue depending on the revenue - similar to RRT1) The framework classes are found in rails.sound. As a facade to the rest of rails, the Sound Manager is notified of - processed events (by GameUIManager) - this covers close to 90% of the triggers of playing sounds - model updates (by the respective models) The input received by the framework is evaluated by the event interpreter who - triggers sound playing directly (straightforward cases) - triggers sound context adjustment (complex case - eg. phase bgm) - which triggers in turn playing sounds diff --git a/Loca... [truncated message content] |
From: Stefan F. <ste...@us...> - 2012-01-28 11:18:22
|
rails/algorithms/RevenueManager.java | 10 rails/common/DisplayBuffer.java | 1 rails/common/GuiHints.java | 8 rails/common/parser/ComponentManager.java | 6 rails/common/parser/GameFileParser.java | 7 rails/game/Bank.java | 10 rails/game/Company.java | 2 rails/game/CompanyManager.java | 2 rails/game/Game.java | 4 rails/game/GameManager.java | 32 +- rails/game/MapHex.java | 10 rails/game/MapManager.java | 4 rails/game/OperatingRound.java | 32 ++ rails/game/PhaseManager.java | 6 rails/game/Player.java | 18 - rails/game/PlayerManager.java | 4 rails/game/PrivateCompany.java | 4 rails/game/PublicCompany.java | 97 +++---- rails/game/Round.java | 18 - rails/game/ShareSellingRound.java | 2 rails/game/StartItem.java | 22 - rails/game/StartRound.java | 19 - rails/game/StartRoundI.java | 8 rails/game/StartRound_1835.java | 4 rails/game/StockMarket.java | 6 rails/game/StockRound.java | 12 rails/game/StockSpace.java | 11 rails/game/Stop.java | 4 rails/game/Tile.java | 8 rails/game/TileI.java | 3 rails/game/TileManager.java | 2 rails/game/Train.java | 4 rails/game/TrainCertificateType.java | 10 rails/game/TrainManager.java | 4 rails/game/TreasuryShareRound.java | 4 rails/game/action/BuyTrain.java | 8 rails/game/correct/CashCorrectionAction.java | 1 rails/game/correct/CashCorrectionManager.java | 12 rails/game/correct/CorrectionManager.java | 6 rails/game/model/AbstractModel.java | 52 ---- rails/game/model/AbstractOwnable.java | 15 - rails/game/model/BaseTokensModel.java | 66 ++++- rails/game/model/BonusModel.java | 38 ++- rails/game/model/CalculatedMoneyModel.java | 49 +++ rails/game/model/CashModel.java | 63 +++-- rails/game/model/CertificateCountModel.java | 46 +++ rails/game/model/CertificatesModel.java | 52 +++- rails/game/model/DirectCashOwner.java | 20 + rails/game/model/DirectOwner.java | 4 rails/game/model/Model.java | 46 +++ rails/game/model/MoneyModel.java | 53 +++- rails/game/model/Observer.java | 14 - rails/game/model/Owner.java | 1 rails/game/model/OwnerState.java | 16 - rails/game/model/Portfolio.java | 50 ++-- rails/game/model/PortfolioCashOwner.java | 13 - rails/game/model/PortfolioOwner.java | 14 - rails/game/model/PresidentModel.java | 58 ++++ rails/game/model/PriceModel.java | 43 ++- rails/game/model/PrivatesModel.java | 4 rails/game/model/SingleOwner.java | 18 + rails/game/model/StorageModel.java | 55 +++- rails/game/model/TrainsModel.java | 14 - rails/game/round/RoundContext.java | 3 rails/game/special/SellBonusToken.java | 4 rails/game/special/SpecialProperty.java | 6 rails/game/special/SpecialRight.java | 1 rails/game/special/SpecialTrainBuy.java | 1 rails/game/specific/_1825/DoubleHeadingModifier.java | 1 rails/game/specific/_1825/PublicCompany_1825.java | 3 rails/game/specific/_1835/GameManager_1835.java | 4 rails/game/specific/_1835/OperatingRound_1835.java | 21 + rails/game/specific/_1851/BirminghamTileModifier.java | 1 rails/game/specific/_1856/CGRFormationRound.java | 4 rails/game/specific/_1856/GameManager_1856.java | 4 rails/game/specific/_1856/OperatingRound_1856.java | 2 rails/game/specific/_1856/PublicCompany_1856.java | 4 rails/game/specific/_1856/PublicCompany_CGR.java | 16 - rails/game/specific/_1856/ShareSellingRound_1856.java | 4 rails/game/specific/_1856/StockRound_1856.java | 4 rails/game/specific/_1880/PublicCompany_1880.java | 4 rails/game/specific/_1880/StartRound_1880.java | 14 - rails/game/specific/_1880/StockRound_1880.java | 8 rails/game/specific/_1889/OperatingRound_1889.java | 4 rails/game/specific/_18AL/NameableTrain.java | 2 rails/game/specific/_18EU/GameManager_18EU.java | 15 - rails/game/specific/_18EU/OperatingRound_18EU.java | 2 rails/game/specific/_18EU/StartRound_18EU.java | 8 rails/game/specific/_18EU/StockRound_18EU.java | 7 rails/game/specific/_18TN/OperatingRound_18TN.java | 2 rails/game/specific/_18TN/PublicCompany_18TN.java | 6 rails/game/state/AbstractContext.java | 65 ----- rails/game/state/AbstractItem.java | 68 ----- rails/game/state/AbstractState.java | 122 --------- rails/game/state/ArrayListMultimapState.java | 29 +- rails/game/state/ArrayListState.java | 42 ++- rails/game/state/BooleanState.java | 41 ++- rails/game/state/ChangeSet.java | 3 rails/game/state/Context.java | 113 ++++++++- rails/game/state/Formatter.java | 2 rails/game/state/GameContext.java | 55 ---- rails/game/state/GameItem.java | 130 ++++------ rails/game/state/GenericState.java | 39 ++- rails/game/state/HashMapState.java | 56 +++- rails/game/state/HashMultimapState.java | 30 +- rails/game/state/HashSetChange.java | 2 rails/game/state/HashSetState.java | 43 ++- rails/game/state/IntegerState.java | 46 +++ rails/game/state/Item.java | 2 rails/game/state/MultimapChange.java | 2 rails/game/state/MultimapState.java | 15 - rails/game/state/Observable.java | 69 ++++- rails/game/state/Observer.java | 18 + rails/game/state/State.java | 76 +++++- rails/game/state/StateManager.java | 221 ++++++++---------- rails/game/state/StringState.java | 39 ++- rails/game/state/Triggerable.java | 7 rails/ui/swing/GridPanel.java | 76 +++--- rails/ui/swing/ORUIManager.java | 6 rails/ui/swing/RemainingTilesWindow.java | 2 rails/ui/swing/elements/Caption.java | 1 rails/ui/swing/elements/Field.java | 88 +++---- rails/ui/swing/elements/GUIStockSpace.java | 31 +- rails/ui/swing/elements/ViewObject.java | 13 - rails/ui/swing/hexmap/GUIHex.java | 48 +++ rails/ui/swing/hexmap/GUITile.java | 2 rails/ui/swing/hexmap/HexMap.java | 38 ++- rails/ui/swing/hexmap/HexMapImage.java | 13 - rails/util/GameFileIO.java | 1 rails/util/Util.java | 2 tools/ListAndFixSavedFiles.java | 33 ++ 131 files changed, 1783 insertions(+), 1290 deletions(-) New commits: commit 8e75b2c1ad5f74332133ca95cc8922e00b571119 Author: Stefan Frey <ste...@we...> Date: Mon Jan 23 15:34:24 2012 +0100 changed creation of states to factory method create() only diff --git a/rails/algorithms/RevenueManager.java b/rails/algorithms/RevenueManager.java index 7a2aa1f..06c506f 100644 --- a/rails/algorithms/RevenueManager.java +++ b/rails/algorithms/RevenueManager.java @@ -41,9 +41,9 @@ public final class RevenueManager extends GameItem implements ConfigurableCompon private RevenueDynamicModifier activeCalculator; public RevenueManager() { - graphModifiers = new ArrayListState<NetworkGraphModifier>(this, "NetworkGraphModifiers"); - staticModifiers = new ArrayListState<RevenueStaticModifier>(this, "RevenueStaticModifiers"); - dynamicModifiers = new ArrayListState<RevenueDynamicModifier>(this, "RevenueDynamicModifiers"); + graphModifiers = ArrayListState.create(this, "NetworkGraphModifiers"); + staticModifiers = ArrayListState.create(this, "RevenueStaticModifiers"); + dynamicModifiers = ArrayListState.create(this, "RevenueDynamicModifiers"); configurableModifiers = new HashSet<ConfigurableComponentI>(); activeStaticModifiers = new ArrayList<RevenueStaticModifier>(); diff --git a/rails/common/DisplayBuffer.java b/rails/common/DisplayBuffer.java index 68ad46f..114d886 100644 --- a/rails/common/DisplayBuffer.java +++ b/rails/common/DisplayBuffer.java @@ -7,7 +7,6 @@ import java.util.List; import org.apache.log4j.Logger; import rails.game.GameManager; -import rails.game.GameManager; import rails.util.Util; /** diff --git a/rails/common/GuiHints.java b/rails/common/GuiHints.java index ddef0db..64d8dde 100644 --- a/rails/common/GuiHints.java +++ b/rails/common/GuiHints.java @@ -35,7 +35,7 @@ public class GuiHints extends GameItem implements Serializable{ public void setCurrentRoundType(Class<? extends RoundI> currentRoundType) { if (this.currentRoundType == null) { - this.currentRoundType = new GenericState<Class<? extends RoundI>> + this.currentRoundType = GenericState.<Class<? extends RoundI>>create (this, "CurrentRoundType", currentRoundType); } else { this.currentRoundType.set(currentRoundType); @@ -67,7 +67,7 @@ public class GuiHints extends GameItem implements Serializable{ public void setActivePanel(GuiDef.Panel activePanel) { if (this.activePanel == null) { - this.activePanel = new GenericState<GuiDef.Panel>(this, "ActivePanel", activePanel); + this.activePanel = GenericState.create(this, "ActivePanel", activePanel); } else { this.activePanel.set(activePanel); } diff --git a/rails/common/parser/GameFileParser.java b/rails/common/parser/GameFileParser.java index f0baa49..d6eb4ec 100644 --- a/rails/common/parser/GameFileParser.java +++ b/rails/common/parser/GameFileParser.java @@ -2,9 +2,6 @@ package rails.common.parser; import java.util.Map; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - import rails.algorithms.RevenueManager; import rails.common.DisplayBuffer; import rails.common.LocalText; diff --git a/rails/game/Bank.java b/rails/game/Bank.java index e386b29..07addf3 100644 --- a/rails/game/Bank.java +++ b/rails/game/Bank.java @@ -43,7 +43,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI private static Bank instance = null; /** Is the bank broken (remains true once set) */ - private BooleanState broken = new BooleanState(this, "Bank.broken", false); + private BooleanState broken = BooleanState.create(this, "Bank.broken", false); /** * The money format template. '@' is replaced by the numeric amount, the @@ -58,7 +58,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI instance = this; - money = new CashModel(this); + money = CashModel.create(this); // Create the IPO and the Bank Pool. ipo = new Portfolio(ipo, IPO_NAME); pool = new Portfolio(pool, POOL_NAME); @@ -103,7 +103,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI public void finishConfiguration (GameManager gameManager) { ReportBuffer.add(LocalText.getText("BankSizeIs", - format(money.getText()))); + format(money.value()))); // Add privates List<PrivateCompany> privates = @@ -141,7 +141,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI * @return Bank's current cash level */ public int getCashValue() { - return money.getText(); + return money.value(); } /** @@ -155,7 +155,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI * Check if the bank has broken. In some games <0 could apply, so this * will become configurable. */ - if (money.getText() <= 0 && !broken.booleanValue()) { + if (money.value() <= 0 && !broken.booleanValue()) { broken.set(true); money.setText(LocalText.getText("BROKEN")); GameManager.getInstance().registerBrokenBank(); @@ -188,7 +188,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI } public String getFormattedCash() { - return money.getData(); + return money.getText(); } public static String format(int amount) { @@ -210,7 +210,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI // end sfy 1889 public int getCash() { - return money.getText(); + return money.value(); } public CashModel getCashModel() { diff --git a/rails/game/Company.java b/rails/game/Company.java index 6483953..bb8cb00 100644 --- a/rails/game/Company.java +++ b/rails/game/Company.java @@ -69,7 +69,7 @@ Cloneable, Comparable<Company> { public void init(String name, CompanyTypeI type) { this.name = name; this.type = type; - closedObject = new BooleanState(this, name + "_Closed", false); + closedObject = BooleanState.create(this, name + "_Closed", false); } /** Only to be called from subclasses */ diff --git a/rails/game/CompanyManager.java b/rails/game/CompanyManager.java index 184d130..25f946a 100644 --- a/rails/game/CompanyManager.java +++ b/rails/game/CompanyManager.java @@ -1 +1 @@ -package rails.game; import java.util.*; import org.apache.log4j.Logger; import rails.common.LocalText; import rails.common.parser.ConfigurableComponentI; import rails.common.parser.ConfigurationException; import rails.common.parser.Tag; import rails.game.state.GameItem; import rails.game.state.Context; public class CompanyManager extends GameItem implements CompanyManagerI, ConfigurableComponentI { /** A List with all private companies */ private List<PrivateCompany> lPrivateCompanies = new ArrayList<PrivateCompany>(); /** A List with all public companies */ private List<PublicCompany> lPublicCompanies = new ArrayList<PublicCompany>(); /** A map with all private companies by name */ private Map<String, PrivateCompany> mPrivateCompanies = new HashMap<String, PrivateCompany>(); /** A map with all public (i.e. non-private) companies by name */ private Map<String, PublicCompany> mPublicCompanies = new HashMap<String, PublicCompany>(); /** A map of all type names to maps of companies of that type by name */ // TODO Redundant, current usage can be replaced. private Map<String, Map<String, Company>> mCompaniesByTypeAndName = new HashMap<String, Map<String, Company>>(); /** A list of all company types */ private List<CompanyTypeI> lCompanyTypes = new ArrayList<CompanyTypeI>(); /** A list of all start packets (usually one) */ private List<StartPacket> startPackets = new ArrayList<StartPacket>(); /** A map of all start packets, keyed by name. Default name is "Initial" */ private Map<String, StartPacket> startPacketMap = new HashMap<String, StartPacket>(); /** A map to enable translating aliases to names */ protected Map<String, String> aliases = null; private int numberOfPublicCompanies = 0; protected static Logger log = Logger.getLogger(CompanyManager.class.getPackage().getName()); protected GameManager gameManager; /* * NOTES: 1. |
From: Erik V. <ev...@us...> - 2012-01-27 20:42:22
|
rails/common/GuiDef.java | 3 rails/game/GameManager.java | 32 +++++-- rails/game/GameManagerI.java | 2 rails/game/specific/_1880/GameManager_1880.java | 99 ++++++++++++------------ rails/game/state/ArrayListState.java | 5 - rails/ui/swing/GameStatus.java | 73 +++++++++-------- rails/ui/swing/GridPanel.java | 78 +++++++++--------- rails/ui/swing/ORPanel.java | 14 +-- rails/ui/swing/StartRoundWindow.java | 43 ++++++---- rails/ui/swing/elements/Caption.java | 31 +------ rails/ui/swing/elements/Cell.java | 46 +++++++++++ rails/ui/swing/elements/Field.java | 29 +------ 12 files changed, 249 insertions(+), 206 deletions(-) New commits: commit b95fd7fd0bf822a8f275166402ca7c3a9f701ef9 Author: Erik Vos <eri...@xs...> Date: Fri Jan 27 21:39:51 2012 +0100 Player captions made variable to reflect player reordering. Capability is game-dependent. Setting it is currently hardcoded in GameManager[_1880].setGuiParameters(). The list of players in GameManager is now an ArrayListState. As ArrayListState does not inherit from ModelObject, a separate StringState[] array had to be created to hold the player names for use in the GUI. A new Cell superclass for Caption and Field allows Field to get a caption background and also centralises highlighting. diff --git a/rails/common/GuiDef.java b/rails/common/GuiDef.java index 5d75906..5f746de 100644 --- a/rails/common/GuiDef.java +++ b/rails/common/GuiDef.java @@ -41,7 +41,8 @@ public class GuiDef { HAS_ANY_RIGHTS, NO_MAP_MODE, REVENUE_SUGGEST, - ROUTE_HIGHLIGHT + ROUTE_HIGHLIGHT, + PLAYER_ORDER_VARIES } /** diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java index d18cba0..886aa80 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -65,11 +65,12 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { protected String gameName; protected Map<String, String> gameOptions; - protected List<Player> players; + protected ArrayListState<Player> players; protected List<String> originalPlayerNamesList; protected int numberOfPlayers; protected State currentPlayer = new State("CurrentPlayer", Player.class); protected State priorityPlayer = new State("PriorityPlayer", Player.class); + protected StringState[] playerNameModels; /** Map relating portfolio names and objects, to enable deserialization. * OBSOLETE since Rails 1.3.1, but still required to enable reading old saved files */ @@ -549,11 +550,15 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { this.revenueManager = revenueManager; this.bank = bank; - players = playerManager.getPlayers(); + players = new ArrayListState<Player> ("Players", playerManager.getPlayers()); originalPlayerNamesList = playerManager.getPlayerNames(); numberOfPlayers = players.size(); priorityPlayer.setState(players.get(0)); setPlayerCertificateLimit (playerManager.getInitialPlayerCertificateLimit()); + playerNameModels = new StringState[numberOfPlayers]; + for (int i=0; i<numberOfPlayers; i++) { + playerNameModels[i] = new StringState ("Player_"+(i+1), players.get(i).getName()); + } showCompositeORNumber = !"simple".equalsIgnoreCase(Config.get("or.number_format")); } @@ -578,7 +583,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { moveStack.enable(); } - private void setGuiParameters () { + protected void setGuiParameters () { for (PublicCompanyI company : companyManager.getAllPublicCompanies()) { if (company.hasParPrice()) guiParameters.put(GuiDef.Parm.HAS_ANY_PAR_PRICE, true); @@ -595,7 +600,6 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { break loop; } } - } // define guiParameters from gameOptions @@ -1392,7 +1396,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { /* Sort players by total worth */ List<Player> rankedPlayers = new ArrayList<Player>(); - for (Player player : players) { + for (Player player : getPlayers()) { rankedPlayers.add(player); } Collections.sort(rankedPlayers); @@ -1488,7 +1492,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { * @see rails.game.GameManagerI#getPlayers() */ public List<Player> getPlayers() { - return players; + return players.viewList(); } /* (non-Javadoc) @@ -1888,23 +1892,31 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { public Player reorderPlayersByCash (boolean ascending) { final boolean _ascending = ascending; - Collections.sort (this.players, new Comparator<Player>() { + List<Player> reorderedPlayers = new ArrayList<Player>(players.viewList()); + Collections.sort(reorderedPlayers, new Comparator<Player>() { public int compare (Player p1, Player p2) { return _ascending ? p1.getCash() - p2.getCash() : p2.getCash() - p1.getCash(); } }); + players.clear(); + Player player; - for (int i=0; i<this.players.size(); i++) { - player = this.players.get(i); + for (int i=0; i<reorderedPlayers.size(); i++) { + player = reorderedPlayers.get(i); + players.add(player); player.setIndex (i); - //this.originalPlayerNamesList.set (i, player.getName()); + playerNameModels[i].set(player.getName()); log.debug("New player "+i+" is "+player.getName() +" (cash="+Bank.format(player.getCash())+")"); } return this.players.get(0); } + public StringState getPlayerNameModel(int index) { + return playerNameModels[index]; + } + public void resetStorage() { objectStorage = new HashMap<String, Object>(); storageIds = new HashMap<String, Integer>(); diff --git a/rails/game/GameManagerI.java b/rails/game/GameManagerI.java index 2703019..a321507 100644 --- a/rails/game/GameManagerI.java +++ b/rails/game/GameManagerI.java @@ -13,6 +13,7 @@ import rails.game.model.ModelObject; import rails.game.move.MoveStack; import rails.game.move.MoveableHolder; import rails.game.special.SpecialPropertyI; +import rails.game.state.StringState; public interface GameManagerI extends MoveableHolder, ConfigurableComponentI { @@ -213,6 +214,7 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI { public void setSkipDone (GameDef.OrStep step); public Player reorderPlayersByCash(boolean high); + public StringState getPlayerNameModel(int index) ; /** * reset the storage for other elements like tokens, special property diff --git a/rails/game/specific/_1880/GameManager_1880.java b/rails/game/specific/_1880/GameManager_1880.java index 6fded62..8facac2 100644 --- a/rails/game/specific/_1880/GameManager_1880.java +++ b/rails/game/specific/_1880/GameManager_1880.java @@ -3,11 +3,8 @@ */ package rails.game.specific._1880; -import rails.game.GameManager; -import rails.game.PhaseI; -import rails.game.RoundI; -import rails.game.StartRound; -import rails.game.StockRound; +import rails.common.GuiDef; +import rails.game.*; import rails.game.state.IntegerState; /** @@ -16,18 +13,24 @@ import rails.game.state.IntegerState; * */ public class GameManager_1880 extends GameManager { - + private RoundI previousRound = null; public IntegerState numOfORs = new IntegerState("numOfORs"); - //Keeps track of the company that purchased the last train + //Keeps track of the company that purchased the last train private PublicCompany_1880 lastTrainBuyingCompany; - /** + /** * */ public GameManager_1880() { super(); } + @Override + protected void setGuiParameters () { + super.setGuiParameters(); + guiParameters.put(GuiDef.Parm.PLAYER_ORDER_VARIES, true); + } + /* (non-Javadoc) * @see rails.game.GameManager#nextRound(rails.game.RoundI) */ @@ -36,41 +39,41 @@ public class GameManager_1880 extends GameManager { if (round instanceof StartRound) { // BCR Operates only if all privates are sold out if (startPacket != null && !startPacket.areAllSold()) { startOperatingRound(runIfStartPacketIsNotCompletelySold()); - } else { - startStockRound(); - } + } else { + startStockRound(); + } numOfORs.set(10); - } else if (round instanceof StockRound) { - if (interruptedRound != null) { - setRound(interruptedRound); - interruptedRound.resume(); - interruptedRound = null; - } else { // First StockRound after StartRound... - PhaseI currentPhase = getCurrentPhase(); - if (currentPhase == null) log.error ("Current Phase is null??", new Exception ("")); - // Create a new OperatingRound (never more than one Stock Round) - // OperatingRound.resetRelativeORNumber(); - - relativeORNumber.set(1); - - startOperatingRound(true); - } - } else if ( round instanceof OperatingRound_1880) { - if (gameOverPending.booleanValue() && !gameEndsAfterSetOfORs) { + } else if (round instanceof StockRound) { + if (interruptedRound != null) { + setRound(interruptedRound); + interruptedRound.resume(); + interruptedRound = null; + } else { // First StockRound after StartRound... + PhaseI currentPhase = getCurrentPhase(); + if (currentPhase == null) log.error ("Current Phase is null??", new Exception ("")); + // Create a new OperatingRound (never more than one Stock Round) + // OperatingRound.resetRelativeORNumber(); - finishGame(); + relativeORNumber.set(1); - } else if (relativeORNumber.add(1) <= numOfORs.intValue()) { - // There will be another OR - startOperatingRound(true); - } else if (startPacket != null && !startPacket.areAllSold()) { - startStartRound(); - } else { - if (gameOverPending.booleanValue() && gameEndsAfterSetOfORs) { - finishGame(); - } + startOperatingRound(true); + } + } else if ( round instanceof OperatingRound_1880) { + if (gameOverPending.booleanValue() && !gameEndsAfterSetOfORs) { + + finishGame(); + + } else if (relativeORNumber.add(1) <= numOfORs.intValue()) { + // There will be another OR + startOperatingRound(true); + } else if (startPacket != null && !startPacket.areAllSold()) { + startStartRound(); + } else { + if (gameOverPending.booleanValue() && gameEndsAfterSetOfORs) { + finishGame(); } } + } }// End of nextRound /** @@ -87,16 +90,16 @@ public class GameManager_1880 extends GameManager { this.lastTrainBuyingCompany = lastTrainBuyingCompany; } - /* (non-Javadoc) - * @see rails.game.GameManager#startStockRound() - */ - - protected void startStockRound_1880(OperatingRound_1880 or) { - // TODO Auto-generated method stub - interruptedRound = or; - super.startStockRound(); - } + /* (non-Javadoc) + * @see rails.game.GameManager#startStockRound() + */ + + protected void startStockRound_1880(OperatingRound_1880 or) { + // TODO Auto-generated method stub + interruptedRound = or; + super.startStockRound(); + } + - } diff --git a/rails/game/state/ArrayListState.java b/rails/game/state/ArrayListState.java index 320ed4f..011dd6f 100644 --- a/rails/game/state/ArrayListState.java +++ b/rails/game/state/ArrayListState.java @@ -58,13 +58,14 @@ public class ArrayListState<E> { public void move (E element, int toIndex) { if (remove (element)) add (toIndex, element); } - + public boolean contains (E element) { return list.contains(element); } public void clear() { - for (E element:list) { + List<E> copy = new ArrayList<E> (list); + for (E element:copy) { remove(element); } } diff --git a/rails/ui/swing/GameStatus.java b/rails/ui/swing/GameStatus.java index c2e51b3..3e30944 100644 --- a/rails/ui/swing/GameStatus.java +++ b/rails/ui/swing/GameStatus.java @@ -1,9 +1,7 @@ package rails.ui.swing; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseListener; +import java.awt.event.*; import java.util.*; import java.util.List; @@ -89,8 +87,8 @@ public class GameStatus extends GridPanel implements ActionListener { protected int futureTrainsXOffset, futureTrainsYOffset, futureTrainsWidth; protected int rightCompCaptionXOffset; - protected Caption[] upperPlayerCaption; - protected Caption[] lowerPlayerCaption; + protected Cell[] upperPlayerCaption; + protected Cell[] lowerPlayerCaption; protected Caption treasurySharesCaption; protected Portfolio ipo, pool; @@ -117,7 +115,6 @@ public class GameStatus extends GridPanel implements ActionListener { protected Map<PublicCompanyI, Integer> companyIndex = new HashMap<PublicCompanyI, Integer>(); - protected Map<Player, Integer> playerIndex = new HashMap<Player, Integer>(); protected static Logger log = Logger.getLogger(GameStatus.class.getPackage().getName()); @@ -145,7 +142,7 @@ public class GameStatus extends GridPanel implements ActionListener { setBorder(BorderFactory.createEtchedBorder()); setOpaque(false); - players = gameUIManager.getPlayers().toArray(new Player[0]); + players = gameUIManager.getPlayers(); np = gameUIManager.getNumberOfPlayers(); companies = gameUIManager.getAllPublicCompanies().toArray(new PublicCompanyI[0]); nc = companies.length; @@ -186,8 +183,8 @@ public class GameStatus extends GridPanel implements ActionListener { playerWorth = new Field[np]; playerORWorthIncrease = new Field[np]; playerCertCount = new Field[np]; - upperPlayerCaption = new Caption[np]; - lowerPlayerCaption = new Caption[np]; + upperPlayerCaption = new Cell[np]; + lowerPlayerCaption = new Cell[np]; MouseListener companyCaptionMouseClickListener = gameUIManager.getORUIManager().getORPanel().getCompanyCaptionMouseClickListener(); @@ -258,15 +255,21 @@ public class GameStatus extends GridPanel implements ActionListener { fields = new JComponent[1+lastX][2+lastY]; rowVisibilityObservers = new RowVisibility[nc]; + // Top captions addField(new Caption(LocalText.getText("COMPANY")), 0, 0, 1, 2, WIDE_BOTTOM, true); addField(new Caption(LocalText.getText("PLAYERS")), certPerPlayerXOffset, 0, np, 1, WIDE_LEFT + WIDE_RIGHT, true); + boolean playerOrderCanVary = gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.PLAYER_ORDER_VARIES); for (int i = 0; i < np; i++) { - playerIndex.put(players[i], new Integer(i)); - f = upperPlayerCaption[i] = new Caption(players[i].getNameAndPriority()); - int wideGapPosition = WIDE_BOTTOM + - ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); + if (playerOrderCanVary) { + f = upperPlayerCaption[i] = new Field(gameUIManager.getGameManager().getPlayerNameModel(i)); + upperPlayerCaption[i].setNormalBgColour(Cell.NORMAL_CAPTION_BG_COLOUR); + } else { + f = upperPlayerCaption[i] = new Caption(players.get(i).getNameAndPriority()); + } + int wideGapPosition = WIDE_BOTTOM + + ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); addField(f, certPerPlayerXOffset + i, 1, 1, 1, wideGapPosition, true); } addField(new Caption(LocalText.getText("BANK_SHARES")), @@ -341,7 +344,7 @@ public class GameStatus extends GridPanel implements ActionListener { f = certPerPlayer[i][j] = new Field( - players[j].getPortfolio().getShareModel( + players.get(j).getPortfolio().getShareModel( c)); int wideGapPosition = ((j==0)? WIDE_LEFT : 0) + ((j==np-1)? WIDE_RIGHT : 0); addField(f, certPerPlayerXOffset + j, certPerPlayerYOffset + i, @@ -364,7 +367,7 @@ public class GameStatus extends GridPanel implements ActionListener { LocalText.getText("ClickToSelectForBuying"), this, buySellGroup); addField(f, certInIPOXOffset, certInIPOYOffset + i, 1, 1, 0, false); - + //no size alignment as button size could also be smaller than the field's one //certInIPO[i].setPreferredSize(certInIPOButton[i].getPreferredSize()); @@ -471,9 +474,9 @@ public class GameStatus extends GridPanel implements ActionListener { addField(new Caption(LocalText.getText("CASH")), 0, playerCashYOffset, 1, 1, WIDE_TOP , true); for (int i = 0; i < np; i++) { - f = playerCash[i] = new Field(players[i].getCashModel()); - int wideGapPosition = WIDE_TOP + - ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); + f = playerCash[i] = new Field(players.get(i).getCashModel()); + int wideGapPosition = WIDE_TOP + + ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); addField(f, playerCashXOffset + i, playerCashYOffset, 1, 1, wideGapPosition, true); f = @@ -493,10 +496,10 @@ public class GameStatus extends GridPanel implements ActionListener { f = playerPrivates[i] = new Field( - players[i].getPortfolio().getPrivatesOwnedModel()); + players.get(i).getPortfolio().getPrivatesOwnedModel()); HexHighlightMouseListener.addMouseListener(f, gameUIManager.getORUIManager(), - players[i].getPortfolio()); + players.get(i).getPortfolio()); int wideGapPosition = ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); addField(f, playerPrivatesXOffset + i, playerPrivatesYOffset, 1, 1, wideGapPosition, true); @@ -505,7 +508,7 @@ public class GameStatus extends GridPanel implements ActionListener { addField(new Caption(LocalText.getText("WORTH")), 0, playerWorthYOffset, 1, 1, 0, true); for (int i = 0; i < np; i++) { - f = playerWorth[i] = new Field(players[i].getWorthModel()); + f = playerWorth[i] = new Field(players.get(i).getWorthModel()); int wideGapPosition = ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); addField(f, playerWorthXOffset + i, playerWorthYOffset, 1, 1, wideGapPosition, true); } @@ -513,7 +516,7 @@ public class GameStatus extends GridPanel implements ActionListener { addField(new Caption(LocalText.getText("ORWORTHINCR")), 0, playerORWorthIncreaseYOffset, 1, 1, 0, true); for (int i = 0; i < np; i++) { - f = playerORWorthIncrease[i] = new Field(players[i].getLastORWorthIncrease()); + f = playerORWorthIncrease[i] = new Field(players.get(i).getLastORWorthIncrease()); int wideGapPosition = ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); addField(f, playerORWorthIncreaseXOffset + i, playerORWorthIncreaseYOffset, 1, 1, wideGapPosition, true); } @@ -523,17 +526,23 @@ public class GameStatus extends GridPanel implements ActionListener { for (int i = 0; i < np; i++) { f = playerCertCount[i] = - new Field(players[i].getCertCountModel(), false, true); - int wideGapPosition = WIDE_TOP + - ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); + new Field(players.get(i).getCertCountModel(), false, true); + int wideGapPosition = WIDE_TOP + + ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); addField(f, playerCertCountXOffset + i, playerCertCountYOffset, 1, 1, wideGapPosition, true); } - + + // Bottom player captions for (int i = 0; i < np; i++) { - f = lowerPlayerCaption[i] = new Caption(players[i].getName()); - int wideGapPosition = WIDE_TOP + - ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); + if (playerOrderCanVary) { + f = lowerPlayerCaption[i] = new Field(gameUIManager.getGameManager().getPlayerNameModel(i)); + lowerPlayerCaption[i].setNormalBgColour(Cell.NORMAL_CAPTION_BG_COLOUR); + } else { + f = lowerPlayerCaption[i] = new Caption(players.get(i).getNameAndPriority()); + } + int wideGapPosition = WIDE_TOP + + ((i==0)? WIDE_LEFT : 0) + ((i==np-1)? WIDE_RIGHT : 0); addField(f, i + 1, playerCertCountYOffset + 1, 1, 1, wideGapPosition, true); } @@ -948,7 +957,7 @@ public class GameStatus extends GridPanel implements ActionListener { } if (ch instanceof Player) { Player p = (Player)ch; - int i = playerIndex.get(p); + int i = players.indexOf(p); setPlayerCashButton(i, true, a); } } @@ -961,7 +970,7 @@ public class GameStatus extends GridPanel implements ActionListener { public void setPriorityPlayer(int index) { for (int j = 0; j < np; j++) { - upperPlayerCaption[j].setText(players[j].getName() + upperPlayerCaption[j].setText(players.get(j).getName() + (j == index ? " PD" : "")); } } @@ -982,7 +991,7 @@ public class GameStatus extends GridPanel implements ActionListener { public String getSRPlayer() { if (actorIndex >= 0) - return players[actorIndex].getName(); + return players.get(actorIndex).getName(); else return ""; } diff --git a/rails/ui/swing/GridPanel.java b/rails/ui/swing/GridPanel.java index 6644dd1..9f11f42 100644 --- a/rails/ui/swing/GridPanel.java +++ b/rails/ui/swing/GridPanel.java @@ -7,9 +7,7 @@ import java.util.*; import java.util.List; import javax.swing.*; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import javax.swing.border.CompoundBorder; +import javax.swing.border.*; import org.apache.log4j.Logger; @@ -17,10 +15,7 @@ import rails.common.parser.Config; import rails.game.*; import rails.game.model.ModelObject; import rails.game.state.BooleanState; -import rails.ui.swing.elements.Caption; -import rails.ui.swing.elements.ClickField; -import rails.ui.swing.elements.Field; -import rails.ui.swing.elements.ViewObject; +import rails.ui.swing.elements.*; public abstract class GridPanel extends JPanel implements ActionListener, KeyListener { @@ -43,7 +38,7 @@ implements ActionListener, KeyListener { protected static Color buttonHighlight = new Color(255, 160, 80); protected int np; - protected Player[] players; + protected List<Player> players; protected int nc; protected PublicCompanyI[] companies; protected RoundI round; @@ -66,7 +61,7 @@ implements ActionListener, KeyListener { protected Color tableBorderColor; protected Color cellOutlineColor; protected Color highlightedBorderColor; - + public GridPanel() { //initialize border colors according to the configuration if ("enabled".equals(Config.get("gridPanel.tableBorders"))) { @@ -117,29 +112,29 @@ implements ActionListener, KeyListener { padTop = (wideGapPositions & WIDE_TOP) > 0 ? WIDE_GAP - NARROW_GAP : 0; padLeft = (wideGapPositions & WIDE_LEFT) > 0 ? WIDE_GAP - NARROW_GAP : 0; padBottom = - (wideGapPositions & WIDE_BOTTOM) > 0 ? WIDE_GAP - NARROW_GAP : 0; - padRight = (wideGapPositions & WIDE_RIGHT) > 0 ? WIDE_GAP - NARROW_GAP : 0; - - //set field borders - //- inner border: the field's native border - //- outline border: the field's outline (in narrow_gap thickness) - //- outer border: grid table lines (in wide_gap - narrow_gap thickness) - - comp.setBorder(new FieldBorder(comp.getBorder(), - new DynamicBorder(cellOutlineColor,NARROW_GAP), - new DynamicBorder(tableBorderColor,padTop,padLeft,padBottom,padRight))); - - gridPanel.add(comp, gbc); - - if (comp instanceof ViewObject - && ((ViewObject) comp).getModel() != null) { - observers.add((ViewObject) comp); - } + (wideGapPositions & WIDE_BOTTOM) > 0 ? WIDE_GAP - NARROW_GAP : 0; + padRight = (wideGapPositions & WIDE_RIGHT) > 0 ? WIDE_GAP - NARROW_GAP : 0; + + //set field borders + //- inner border: the field's native border + //- outline border: the field's outline (in narrow_gap thickness) + //- outer border: grid table lines (in wide_gap - narrow_gap thickness) + + comp.setBorder(new FieldBorder(comp.getBorder(), + new DynamicBorder(cellOutlineColor,NARROW_GAP), + new DynamicBorder(tableBorderColor,padTop,padLeft,padBottom,padRight))); + + gridPanel.add(comp, gbc); + + if (comp instanceof ViewObject + && ((ViewObject) comp).getModel() != null) { + observers.add((ViewObject) comp); + } - if (fields != null && fields[x][y] == null) fields[x][y] = comp; - comp.setVisible(visible); + if (fields != null && fields[x][y] == null) fields[x][y] = comp; + comp.setVisible(visible); } - + /** * highlights given component by altering its border's attributes */ @@ -147,7 +142,7 @@ implements ActionListener, KeyListener { //quit if nothing is to be done if (isToBeHighlighted && highlightedComps.contains(comp)) return; if (!isToBeHighlighted && !highlightedComps.contains(comp)) return; - + if (comp.getBorder() instanceof FieldBorder) { FieldBorder fb = (FieldBorder)comp.getBorder(); fb.setHighlight(isToBeHighlighted); @@ -159,7 +154,7 @@ implements ActionListener, KeyListener { } } } - + protected void removeAllHighlights() { for (JComponent c : highlightedComps) { if (c.getBorder() instanceof FieldBorder) { @@ -170,7 +165,7 @@ implements ActionListener, KeyListener { } highlightedComps.clear(); } - + public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_F1) { HelpWindow.displayHelp(GameManager.getInstance().getHelp()); @@ -242,7 +237,7 @@ implements ActionListener, KeyListener { } /** - * Wrapper for three level compound borders and directly accessing border constituents + * Wrapper for three level compound borders and directly accessing border constituents * @author Frederick Weld * */ @@ -266,13 +261,13 @@ implements ActionListener, KeyListener { } public void setHighlight(boolean isToBeHighlighted) { outlineBorder.setHighlight(isToBeHighlighted); - this.insideBorder = isToBeHighlighted ? + this.insideBorder = isToBeHighlighted ? highlightedInnerBorder : nativeInnerBorder; } } /** - * A potentially asymmetric line border providing methods for changing the look + * A potentially asymmetric line border providing methods for changing the look * @author Frederick Weld * */ @@ -289,7 +284,7 @@ implements ActionListener, KeyListener { this.padRight = symmetricPad; this.borderColor = borderColor; } - + public DynamicBorder (Color borderColor,int padTop, int padLeft, int padBottom, int padRight) { this.padTop = padTop; this.padLeft = padLeft; @@ -297,13 +292,14 @@ implements ActionListener, KeyListener { this.padRight = padRight; this.borderColor = borderColor; } - + public void setHighlight(boolean isToBeHighlighted) { if (isHighlighted != isToBeHighlighted) { isHighlighted = isToBeHighlighted; } } + @Override public void paintBorder(Component c,Graphics g, int x, int y, int width,int height) { Graphics2D g2d = (Graphics2D)g; if (isHighlighted) { @@ -331,12 +327,14 @@ implements ActionListener, KeyListener { g2d.setStroke(oldStroke); } + @Override public Insets getBorderInsets (Component c) { return new Insets(padTop,padLeft,padBottom,padRight); } - public boolean isBorderOpaque() { - return true; + @Override + public boolean isBorderOpaque() { + return true; } } } diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java index c8193ac..566b06b 100644 --- a/rails/ui/swing/ORPanel.java +++ b/rails/ui/swing/ORPanel.java @@ -149,7 +149,7 @@ implements ActionListener, KeyListener, RevenueListener { initButtonPanel(); gbc = new GridBagConstraints(); - players = gameUIManager.getPlayers().toArray(new Player[0]); + players = gameUIManager.getPlayers(); if (round instanceof OperatingRound) { companies = ((OperatingRound) round).getOperatingCompanies().toArray(new PublicCompanyI[0]); @@ -790,7 +790,7 @@ implements ActionListener, KeyListener, RevenueListener { redoButton.setEnabled(false); disableRoutesDisplay(); - + //clear all highlighting (president column and beyond) resetActions(); @@ -1005,9 +1005,9 @@ implements ActionListener, KeyListener, RevenueListener { this.orComp = orComp; this.orCompIndex = orCompIndex; president[orCompIndex].setHighlight(true); - + removeAllHighlights(); - + buttonOC.clearPossibleActions(); button1.clearPossibleActions(); button2.clearPossibleActions(); @@ -1021,7 +1021,7 @@ implements ActionListener, KeyListener, RevenueListener { updateCurrentRoutes(false); } - + public void initTileLayingStep() { tileCaption.setHighlight(true); @@ -1244,7 +1244,7 @@ implements ActionListener, KeyListener, RevenueListener { button1.setEnabled(false); orCompIndex = -1; - + orUIManager.getMap().setTrainPaths(null); } @@ -1255,7 +1255,7 @@ implements ActionListener, KeyListener, RevenueListener { public String getORPlayer() { if (playerIndex >= 0) - return players[playerIndex].getName(); + return players.get(playerIndex).getName(); else return ""; } diff --git a/rails/ui/swing/StartRoundWindow.java b/rails/ui/swing/StartRoundWindow.java index 8f33970..4cf1b88 100644 --- a/rails/ui/swing/StartRoundWindow.java +++ b/rails/ui/swing/StartRoundWindow.java @@ -10,6 +10,7 @@ import javax.swing.*; import org.apache.log4j.Logger; +import rails.common.GuiDef; import rails.common.LocalText; import rails.game.*; import rails.game.action.*; @@ -62,8 +63,8 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { private int infoXOffset, infoYOffset; private Field itemStatus[]; // Remains invisible, only used for status tooltip - private Caption[] upperPlayerCaption; - private Caption[] lowerPlayerCaption; + private Cell[] upperPlayerCaption; + private Cell[] lowerPlayerCaption; private ActionButton bidButton; private ActionButton buyButton; @@ -110,13 +111,10 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { private boolean includeBidding; private boolean showBasePrices; - // private boolean repacked = false; - protected static Logger log = Logger.getLogger(StartRoundWindow.class.getPackage().getName()); public void init(StartRound round, GameUIManager parent) { - //super(); this.round = round; includeBidding = round.hasBidding(); showBasePrices = round.hasBasePrices(); @@ -238,8 +236,8 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { bidPerPlayer = new Field[ni][np]; info = new Field[ni]; itemStatus = new Field[ni]; - upperPlayerCaption = new Caption[np]; - lowerPlayerCaption = new Caption[np]; + upperPlayerCaption = new Cell[np]; + lowerPlayerCaption = new Cell[np]; playerBids = new Field[np]; playerFree = new Field[np]; @@ -279,27 +277,35 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { addField(new Caption(LocalText.getText("MINIMUM_BID")), minBidXOffset, 0, 1, 2, WIDE_BOTTOM + WIDE_RIGHT); } + + // Top player captions addField(new Caption(LocalText.getText("PLAYERS")), bidPerPlayerXOffset, 0, np, 1, 0); + boolean playerOrderCanVary = getGameUIManager().getGameParameterAsBoolean(GuiDef.Parm.PLAYER_ORDER_VARIES); for (int i = 0; i < np; i++) { - f = upperPlayerCaption[i] = new Caption(players[i].getName()); + if (playerOrderCanVary) { + f = upperPlayerCaption[i] = new Field(getGameUIManager().getGameManager().getPlayerNameModel(i)); + upperPlayerCaption[i].setNormalBgColour(Cell.NORMAL_CAPTION_BG_COLOUR); + } else { + f = upperPlayerCaption[i] = new Caption(players[i].getName()); + } addField(f, bidPerPlayerXOffset + i, 1, 1, 1, WIDE_BOTTOM); } for (int i = 0; i < ni; i++) { si = items[i]; f = itemName[i] = new Caption(si.getName()); - HexHighlightMouseListener.addMouseListener(f, + HexHighlightMouseListener.addMouseListener(f, gameUIManager.getORUIManager(), - si); + si); addField(f, itemNameXOffset, itemNameYOffset + i, 1, 1, WIDE_RIGHT); f = itemNameButton[i] = new ClickField(si.getName(), "", "", this, itemGroup); - HexHighlightMouseListener.addMouseListener(f, + HexHighlightMouseListener.addMouseListener(f, gameUIManager.getORUIManager(), - si); + si); addField(f, itemNameXOffset, itemNameYOffset + i, 1, 1, WIDE_RIGHT); // Prevent row height resizing after every buy action itemName[i].setPreferredSize(itemNameButton[i].getPreferredSize()); @@ -322,9 +328,9 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { f = info[i] = new Field (infoIcon); f.setToolTipText(getStartItemDescription(si)); - HexHighlightMouseListener.addMouseListener(f, + HexHighlightMouseListener.addMouseListener(f, gameUIManager.getORUIManager(), - si); + si); addField (f, infoXOffset, infoYOffset + i, 1, 1, WIDE_LEFT); // Invisible field, only used to hold current item status. @@ -360,7 +366,12 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { } for (int i = 0; i < np; i++) { - f = lowerPlayerCaption[i] = new Caption(players[i].getName()); + if (playerOrderCanVary) { + f = lowerPlayerCaption[i] = new Field(getGameUIManager().getGameManager().getPlayerNameModel(i)); + lowerPlayerCaption[i].setNormalBgColour(Cell.NORMAL_CAPTION_BG_COLOUR); + } else { + f = lowerPlayerCaption[i] = new Caption(players[i].getName()); + } addField(f, playerFreeCashXOffset + i, playerFreeCashYOffset + 1, 1, 1, WIDE_TOP); } @@ -702,7 +713,7 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner { } public void setSRPlayerTurn(int selectedPlayerIndex) { - + highlightCurrentPlayer(selectedPlayerIndex); } diff --git a/rails/ui/swing/elements/Caption.java b/rails/ui/swing/elements/Caption.java index aacaa96..78c6610 100644 --- a/rails/ui/swing/elements/Caption.java +++ b/rails/ui/swing/elements/Caption.java @@ -1,38 +1,17 @@ /* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/ui/swing/elements/Caption.java,v 1.4 2008/06/04 19:00:38 evos Exp $*/ package rails.ui.swing.elements; -import java.awt.Color; +import javax.swing.ImageIcon; -import javax.swing.*; -import javax.swing.border.Border; - -public class Caption extends JLabel { +public class Caption extends Cell { private static final long serialVersionUID = 1L; - private Border labelBorder = BorderFactory.createEmptyBorder(1, 2, 1, 2); - - private static final Color NORMAL_BG_COLOUR = new Color(240, 240, 240); - - private static final Color HIGHLIGHT_BG_COLOUR = new Color(255, 255, 80); - - private static final Color NORMAL_FG_COLOUR = new Color (0, 0, 0); - - private static final Color LOCAL_PLAYER_COLOUR = new Color (255, 0, 0); - public Caption(String text) { - super(text); - this.setForeground(NORMAL_FG_COLOUR); - this.setBackground(NORMAL_BG_COLOUR); - this.setHorizontalAlignment(SwingConstants.CENTER); - this.setBorder(labelBorder); - this.setOpaque(true); + super(text, true); } - public void setHighlight(boolean highlight) { - this.setBackground(highlight ? HIGHLIGHT_BG_COLOUR : NORMAL_BG_COLOUR); + public Caption (ImageIcon icon) { + super (icon, true); } - public void setLocalPlayer (boolean highlight) { - this.setForeground(highlight ? LOCAL_PLAYER_COLOUR : NORMAL_FG_COLOUR); - } } diff --git a/rails/ui/swing/elements/Cell.java b/rails/ui/swing/elements/Cell.java new file mode 100644 index 0000000..54d5c87 --- /dev/null +++ b/rails/ui/swing/elements/Cell.java @@ -0,0 +1,46 @@ +/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/ui/swing/elements/Cell.java,v 1.4 2008/06/04 19:00:38 evos Exp $*/ +package rails.ui.swing.elements; + +import java.awt.Color; + +import javax.swing.*; +import javax.swing.border.Border; + +public abstract class Cell extends JLabel { + private static final long serialVersionUID = 1L; + + protected Border labelBorder = BorderFactory.createEmptyBorder(1, 2, 1, 2); + + public static final Color NORMAL_CAPTION_BG_COLOUR = new Color(240, 240, 240); + public static final Color NORMAL_FIELD_BG_COLOUR = Color.WHITE; + public static final Color HIGHLIGHT_BG_COLOUR = new Color(255, 255, 80); + public static final Color NORMAL_FG_COLOUR = new Color (0, 0, 0); + public static final Color LOCAL_PLAYER_COLOUR = new Color (255, 0, 0); + + protected Color normalBgColour = NORMAL_FIELD_BG_COLOUR; + + public Cell(String text, boolean asCaption) { + super(text); + setForeground(NORMAL_FG_COLOUR); + setNormalBgColour (asCaption ? NORMAL_CAPTION_BG_COLOUR : NORMAL_FIELD_BG_COLOUR); + setHorizontalAlignment(SwingConstants.CENTER); + setBorder(labelBorder); + setOpaque(true); + } + + public Cell (ImageIcon icon, boolean asCaption) { + super (icon); + } + + public void setHighlight(boolean highlight) { + this.setBackground(highlight ? HIGHLIGHT_BG_COLOUR : normalBgColour); + } + + public void setNormalBgColour (Color colour) { + setBackground (normalBgColour = colour); + } + + public void setLocalPlayer (boolean highlight) { + this.setForeground(highlight ? LOCAL_PLAYER_COLOUR : NORMAL_FG_COLOUR); + } +} diff --git a/rails/ui/swing/elements/Field.java b/rails/ui/swing/elements/Field.java index eee384b..ede39b7 100644 --- a/rails/ui/swing/elements/Field.java +++ b/rails/ui/swing/elements/Field.java @@ -5,25 +5,18 @@ import java.awt.Color; import java.awt.Graphics; import java.util.*; -import javax.swing.*; -import javax.swing.border.Border; +import javax.swing.ImageIcon; +import javax.swing.JComponent; import rails.game.model.ModelObject; import rails.game.model.ViewUpdate; import rails.util.Util; -public class Field extends JLabel implements ViewObject { +public class Field extends Cell implements ViewObject { private static final long serialVersionUID = 1L; - private Border labelBorder = BorderFactory.createEmptyBorder(1, 2, 1, 2); - - private static final Color NORMAL_BG_COLOUR = Color.WHITE; - - private static final Color HIGHLIGHT_BG_COLOUR = new Color(255, 255, 80); - private ModelObject modelObject; - private Color normalBgColour = NORMAL_BG_COLOUR; private List<JComponent> dependents = null; @@ -35,19 +28,11 @@ public class Field extends JLabel implements ViewObject { private String baseToolTipInfo = null; public Field(String text) { - super(text.equals("0%") ? "" : text); - this.setBackground(NORMAL_BG_COLOUR); - this.setHorizontalAlignment(SwingConstants.CENTER); - this.setBorder(labelBorder); - this.setOpaque(true); + super(text.equals("0%") ? "" : text, false); } public Field(ImageIcon info) { - super(info); - this.setBackground(NORMAL_BG_COLOUR); - this.setHorizontalAlignment(SwingConstants.CENTER); - this.setBorder(labelBorder); - this.setOpaque(true); + super(info, false); } public Field(ModelObject modelObject) { @@ -81,10 +66,6 @@ public class Field extends JLabel implements ViewObject { update(null, null); } - public void setHighlight(boolean highlight) { - setBackground(highlight ? HIGHLIGHT_BG_COLOUR : normalBgColour); - } - /** This method is mainly needed when NOT using the Observer pattern. */ @Override |
From: Erik V. <ev...@us...> - 2012-01-26 21:09:28
|
rails/game/GameManager.java | 15 +++++++-------- rails/game/GameManagerI.java | 26 ++++++++++++-------------- rails/ui/swing/GameUIManager.java | 8 ++++---- 3 files changed, 23 insertions(+), 26 deletions(-) New commits: commit fb01a78aa7fc7de3b7c66bcc2e4a074cb14b72ce Author: Erik Vos <eri...@xs...> Date: Thu Jan 26 22:08:29 2012 +0100 Fixed 1880 reloading. The original player names sequence is now saved, rather than the reordered list. Method getPlayerNames() has been removed from teh GameManagerI interface; it was hardly used. diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java index 8058d91..d18cba0 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -17,7 +17,6 @@ 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; @@ -67,7 +66,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { protected Map<String, String> gameOptions; protected List<Player> players; - protected List<String> playerNames; + protected List<String> originalPlayerNamesList; protected int numberOfPlayers; protected State currentPlayer = new State("CurrentPlayer", Player.class); protected State priorityPlayer = new State("PriorityPlayer", Player.class); @@ -551,7 +550,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { this.bank = bank; players = playerManager.getPlayers(); - playerNames = playerManager.getPlayerNames(); + originalPlayerNamesList = playerManager.getPlayerNames(); numberOfPlayers = players.size(); priorityPlayer.setState(players.get(0)); setPlayerCertificateLimit (playerManager.getInitialPlayerCertificateLimit()); @@ -1152,7 +1151,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { protected boolean save(File file, boolean displayErrorMessage, String errorMessageKey) { GameFileIO gameSaver = new GameFileIO(); - gameSaver.initSave(saveFileVersionID, gameName, gameOptions, playerNames); + gameSaver.initSave(saveFileVersionID, gameName, gameOptions, originalPlayerNamesList); gameSaver.setActions(executedActions); gameSaver.setComments(ReportBuffer.getCommentItems()); return gameSaver.saveGame(file, displayErrorMessage, errorMessageKey); @@ -1502,9 +1501,9 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { /* (non-Javadoc) * @see rails.game.GameManagerI#getPlayerNames() */ - public List<String> getPlayerNames() { - return playerNames; - } + //public List<String> getPlayerNames() { + // return originalPlayerNamesList; + //} public int getPlayerCertificateLimit(Player player) { return playerCertificateLimit.intValue(); @@ -1899,7 +1898,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { for (int i=0; i<this.players.size(); i++) { player = this.players.get(i); player.setIndex (i); - this.playerNames.set (i, player.getName()); + //this.originalPlayerNamesList.set (i, player.getName()); log.debug("New player "+i+" is "+player.getName() +" (cash="+Bank.format(player.getCash())+")"); } diff --git a/rails/game/GameManagerI.java b/rails/game/GameManagerI.java index 01253a0..2703019 100644 --- a/rails/game/GameManagerI.java +++ b/rails/game/GameManagerI.java @@ -4,9 +4,7 @@ import java.util.List; import java.util.Map; import rails.algorithms.RevenueManager; -import rails.common.DisplayBuffer; -import rails.common.GuiDef; -import rails.common.GuiHints; +import rails.common.*; import rails.common.parser.ConfigurableComponentI; import rails.game.action.PossibleAction; import rails.game.correct.CorrectionManagerI; @@ -71,7 +69,7 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI { public abstract void registerBrokenBank(); public void registerMaxedSharePrice(PublicCompanyI company, StockSpaceI space); - + public boolean isDynamicOperatingOrder(); /** @@ -136,7 +134,7 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI { public abstract int getNumberOfPlayers(); - public abstract List<String> getPlayerNames(); + //public abstract List<String> getPlayerNames(); public abstract List<PublicCompanyI> getAllPublicCompanies(); @@ -210,28 +208,28 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI { public CorrectionManagerI getCorrectionManager(CorrectionType ct); public List<PublicCompanyI> getCompaniesInRunningOrder (); - public boolean isReloading(); - public void setReloading(boolean reloading); - public void setSkipDone (GameDef.OrStep step); - - public Player reorderPlayersByCash(boolean high); + public boolean isReloading(); + public void setReloading(boolean reloading); + public void setSkipDone (GameDef.OrStep step); + + public Player reorderPlayersByCash(boolean high); /** * reset the storage for other elements like tokens, special property * that a referred by unique ids * TODO */ - public void resetStorage(); - + public void resetStorage(); + /** * store element in storage * @param name to identify the type of the object to retrieve * @param object to store - * @return unique id of the object in the storage + * @return unique id of the object in the storage * TODO move to a better place */ public int storeObject(String typeName, Object object); - + /** * ask storage for object * @param name to identify the type of the object to retrieve diff --git a/rails/ui/swing/GameUIManager.java b/rails/ui/swing/GameUIManager.java index 07b5726..e50d32e 100644 --- a/rails/ui/swing/GameUIManager.java +++ b/rails/ui/swing/GameUIManager.java @@ -149,7 +149,7 @@ public class GameUIManager implements DialogOwner { if (Util.hasValue(saveSuffixSpec) && !saveSuffixSpec.equals(NEXT_PLAYER_SUFFIX)) { saveSuffix = saveSuffixSpec; } else { - saveSuffix = getPlayerNames().get(0); + saveSuffix = getPlayers().get(0).getName(); } log.debug("Initial save suffix: "+saveSuffix); } @@ -1030,9 +1030,9 @@ public class GameUIManager implements DialogOwner { return gameManager.getPlayers(); } - public List<String> getPlayerNames() { - return gameManager.getPlayerNames(); - } + //public List<String> getPlayerNames() { + // return gameManager.getPlayerNames(); + //} public Player getCurrentPlayer() { return gameManager.getCurrentPlayer(); |
From: Erik V. <ev...@us...> - 2012-01-25 14:01:30
|
LocalisedText.properties | 6 data/1880/CompanyManager.xml | 59 + data/1880/Game.xml | 29 data/1880/StockMarket.xml | 8 data/1880/Tiles.xml | 2 rails/game/Company.java | 2 rails/game/GameManager.java | 16 rails/game/PublicCompany.java | 5 rails/game/PublicCompanyI.java | 2 rails/game/Round.java | 3 rails/game/StockMarket.java | 13 rails/game/StockMarketI.java | 1 rails/game/StockRound.java | 4 rails/game/StockSpace.java | 2 rails/game/StockSpaceI.java | 5 rails/game/StockSpaceType.java | 17 rails/game/StockSpaceTypeI.java | 16 rails/game/action/BuyStartItem.java | 12 rails/game/specific/_1880/BuyStartItem_1880.java | 164 +++++ rails/game/specific/_1880/GameManager_1880.java | 102 +++ rails/game/specific/_1880/OperatingRound_1880.java | 334 ++++++++++- rails/game/specific/_1880/PublicCompany_1880.java | 169 +++++ rails/game/specific/_1880/StartRound_1880.java | 70 +- rails/game/specific/_1880/StockMarket_1880.java | 169 +++++ rails/game/specific/_1880/StockRound_1880.java | 121 +++ rails/ui/swing/StartRoundWindow.java | 46 - rails/ui/swing/gamespecific/_1880/StartRoundWindow_1880.java | 121 +++ rails/ui/swing/gamespecific/_1880/StatusWindow_1880.java | 34 + tiles/TileDictionary.18t | 25 tiles/TileDictionary.xml | 4 tiles/svg/tile235.svg | 145 ++++ 31 files changed, 1577 insertions(+), 129 deletions(-) New commits: commit b1d3ff5d36d8bfd9c0a226e6c5f433c917ecd8fd Author: Erik Vos <eri...@xs...> Date: Wed Jan 25 14:55:51 2012 +0100 1880 tile 235 added to TileDesigner diff --git a/tiles/TileDictionary.18t b/tiles/TileDictionary.18t index d14e28d..9038379 100644 --- a/tiles/TileDictionary.18t +++ b/tiles/TileDictionary.18t @@ -17417,5 +17417,30 @@ object TTilesWrapper JunType = jtCity Revenue = 40 end> + end + item + Code = 235 + LongName = 'OO' + Category = 'OO' + CategoryPosition = tp2CornerC + Level = tlMapUpgradableToGreen + Connections = < + item + Position1 = tp2SideF + Position2 = tp4SideF + end> + Junctions = < + item + JunType = jtCity + Position = tp2SideD + Revenue = 30 + RevenuePosition = tp3CornerB + end + item + JunType = jtCity + Position = tp2SideF + Revenue = 30 + RevenuePosition = tp3CornerB + end> end> end commit 90483652116407d14af524316c5482d9db3687bc Author: Martin Brumm <dr....@t-...> Date: Wed Jan 25 14:30:11 2012 +0100 1880 patches diff --git a/LocalisedText.properties b/LocalisedText.properties index ee9b8a4..27d1085 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -688,9 +688,11 @@ Version=Version VersionOf=version of {0} WantToReplaceToken=Do you want to replace the {0} home token with one of {1}? WarningNeedCash=Warning: {0} will be deducted from the company revenue or from your personal cash +WHICH_BUILDING_RIGHT={0} please choose the Building Rights for {1} WHICH_PRICE=Which price? WHICH_PRIVATE=Which Private? -WHICH_PRIVATE_PRICE=Buy {0} for which price (valid range {1} to {2})? +WHICH_PRIVATE_PRICE=Buy {0} for which price (valid range {1} to {2})? +WHICH_RIGHT=Which Building Right ? WHICH_START_PRICE={0} please set the start price for {1} WhichStation=Which Station? WHICH_TRAIN=Which train @@ -729,4 +731,4 @@ YouMustRaiseCash=You must raise {0} cash by selling shares YouMustRaiseCashButCannot=You must still raise {0}, but you can''t sell any more shares. YouMustSelect1=You must select {0} item(s) YouMustSelect2=You must select between {0} and {1} items -YourTurn={0}, it''s your turn again \ No newline at end of file +YourTurn={0}, it''s your turn again diff --git a/data/1880/CompanyManager.xml b/data/1880/CompanyManager.xml index ecaea80..c4b55f7 100644 --- a/data/1880/CompanyManager.xml +++ b/data/1880/CompanyManager.xml @@ -12,7 +12,7 @@ <Payout split="no"/> </CompanyType> - <CompanyType name="Minor" class="rails.game.PublicCompany"> + <CompanyType name="Minor" class="rails.game.specific._1880.PublicCompany_1880"> <ShareUnit percentage="100"/> <Certificate type="President" shares="1"/> <StockPrice market="no"/> @@ -21,18 +21,18 @@ </BaseTokens> <Payout split="no"/> <Trains limit="1" mandatory="no"/> + <CanUseSpecialProperties/> + <!-- Specialproperties --> + <!-- Specialproperty condition="ifNotConnected" when="orTurn" + class="rails.game.special.TrainLoan" --> + <!-- /Specialproperty--> + <!-- /Specialproperties--> </CompanyType> <CompanyType name="Private" class="rails.game.PrivateCompany"/> - <CompanyType name="Major" class="rails.game.PublicCompany" - capitalisation="incremental"> - <Capitalisation Type="incremental"/> - <!--TileLays> - <Number colour="yellow" phase="2+2,3,3+3,4,4+4,6,6e,8,8e,10" - number="2"/> - </TileLays--> - <Float percentage="60"/> + <CompanyType name="Major" class="rails.game.specific._1880.PublicCompany_1880"> + <Float percentage="20"/> <StockPrice par="yes"/> <ShareUnit percentage="10"/> <Certificate type="President" shares="2"/> @@ -40,9 +40,9 @@ <BaseTokens> <LayCost method="sequence" cost="0,40,100"/> </BaseTokens> - <Capitalisation type="incremental"/> <Trains limit="4,3,2"/> <CanUseSpecialProperties/> + </CompanyType> <Company name="WR" longname="Woosong Railway" type="Private" basePrice="5" @@ -60,28 +60,40 @@ <Phase>4</Phase> </ClosingConditions> </Company> - <Company name="YC" longname="Yanda Ferry - Company" type="Private" + <Company name="YC" longname="Yanda Ferry Company" type="Private" basePrice="25" revenue="10"> - <!-- SpecialProperty condition="ifOwnedByPlayer" when="revenuecalcStep" revenue="10" --> + <SpecialProperties> + <SpecialProperty condition="ifOwnedByPlayer" when="revenueStep" + class="rails.game.special.LocatedBonus" transfer="toCompany"> + <LocatedBonus name="Ferry" location="F12,F14,I15" value="10"/> + </SpecialProperty> + </SpecialProperties> </Company> <Company name="TL" longname="Taiwan Western Line" type="Private" basePrice="45" revenue="15"> - <!-- SpecialProperty condition="ifOwnedByPlayer" when="revenuecalcStep" revenue="20" --> - </Company> - <Company name="CC" longname="Chinese Rivers Ferry - Company" type="Private" + <SpecialProperties> + <SpecialProperty condition="ifOwnedByPlayer" when="revenueStep" + class="rails.game.special.LocatedBonus" transfer="toCompany"> + <LocatedBonus name="Taiwan" location="N16" value="20"/> + </SpecialProperty> + </SpecialProperties> + </Company> + <Company name="CC" longname="Chinese Rivers Ferry Company" type="Private" basePrice="70" revenue="20"> + <SpecialProperties> <SpecialProperty condition="ifOwnedByPlayer" when="tileLayingStep" class="rails.game.special.SpecialTileLay"> <SpecialTileLay location="M15" extra="no" free="yes"/> </SpecialProperty> + </SpecialProperties> </Company> <Company name="JO" longname="Jeme Tien Yow Engineer Office" type="Private" basePrice="70" revenue="20"> - <SpecialProperty condition="ifOwnedByPlayer" when="tileLayingStep" - class="rails.game.specific._1880.BuildingPermit"> - </SpecialProperty> + <!-- SpecialProperties--> + <!-- SpecialProperty condition="ifOwnedByPlayer" when="tileLayingStep" + class="rails.game.specific._1880.BuildingPermit"--> + <!-- /SpecialProperty--> + <!-- -->/SpecialProperties--> </Company> <Company name="IG" longname="Imperial Qing Government" type="Private" basePrice="160" revenue="20"> @@ -89,17 +101,18 @@ </Company> <Company name="RC" longname="Rocket Company" type="Private" basePrice="70" revenue="0"> - <SpecialProperty condition="ifOwnedByPlayer" when="trainBuyingStep" - class="rails.game.special.SpecialTrainBuy"/> + <!-- SpecialProperties--> + <!-- SpecialProperty condition="ifOwnedByPlayer" when="trainBuyingStep" + class="rails.game.special.SpecialTrainBuy"/--> <!-- Kostenfreie Lok bei Phasenwechsel durch Lokkauf --> <!-- Can exchange Certificate for actual train in one phase 2,2+3,3,3+3,4 as soon as train has been bought --> <!-- The train can be moved upon purchase into one company owned by the owner of the certificate --> <!-- Company must have space for the new train, but can hand back an older train to bank (2+2,3,3+3) --> + <!-- /SpecialProperties--> <ClosingConditions> <Phase>5</Phase> - <SpecialProperties condition="ifExercised"/> </ClosingConditions> </Company> <Company name="BCR" longname="Baocheng Railway" type="Major" tokens="3" diff --git a/data/1880/Game.xml b/data/1880/Game.xml index 1a0ff10..814f622 100644 --- a/data/1880/Game.xml +++ b/data/1880/Game.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> <ComponentManager> - <Component name="GameManager" class="rails.game.GameManager"> + <Component name="GameManager" class="rails.game.specific._1880.GameManager_1880"> <Game name="1880"/> <GameOption name="RouteAwareness" values="Highlight,Deactivate" default="Deactivate"/> @@ -23,7 +23,7 @@ <StatusWindow class="rails.ui.swing.StatusWindow"/> <StartRoundWindow class="rails.ui.swing.gamespecific._1880.StartRoundWindow_1880"/> - </GuiClasses> + </GuiClasses> <EndOfGame/> <!-- need to implement the 3 OR set limit after purchase of first 8 TrainType --> @@ -92,7 +92,8 @@ <Component name="PhaseManager" class="rails.game.PhaseManager"> <Phase name="2" realName="A1"> <Tiles colour="yellow"> - <Lays companyType="Major" colour="yellow" number="2"/> + <Lays companyType="Major" colour="yellow" number="1"/> + <Lays companyType="Minor" colour="yellow" number="1"/> </Tiles> <OperatingRounds number="-1"/> <Float percentage="20"/> @@ -103,28 +104,37 @@ </Phase> <Phase name="3" realName="B1"> <Tiles colour="yellow,green"/> + <Lays companyType="Major" colour="yellow" number="2"/> + <Lays companyType="Minor" colour="yellow" number="1"/> + <Lays companyType="Major" colour="green" number="1"/> + <Lays companyType="Minor" colour="green" number="1"/> + <Float percentage="30"/> <Stocks avail="10"/> <OffBoardRevenue step="2"/> + <Action name="RaisingCertAvailability"/> </Phase> <Phase name="3+3" realName="B2"> <OffBoardRevenue step="2"/> </Phase> <Phase name="4" realName="B3"> + <Action name="CommunistTakeOver"/> <OffBoardRevenue step="2"/> <Privates close="yes"/> <Investors active="no"/> - <Communists active="yes"/> <Float percentage="40"/> <Trains limitStep="2" rusted="2"/> </Phase> <Phase name="4+4" realName="C1"> <Tiles colour="yellow,green,brown"/> + <Lays companyType="Major" colour="yellow" number="2"/> + <Lays companyType="Major" colour="green" number="1"/> + <Lays companyType="Major" colour="brown" number="1"/> <OffBoardRevenue step="3"/> <Trains rusted="2+2"/> </Phase> <Phase name="6" realName="C2"> - <Communists active="no"/> + <Action name="ShanghaiExchangeOpen"/> <Float percentage="60"/> <OffBoardRevenue step="3"/> <Trains limitStep="3" rusted="3"/> @@ -135,6 +145,10 @@ </Phase> <Phase name="8" realName="D1"> <Tiles colour="yellow,green,brown,grey"/> + <Lays companyType="Major" colour="yellow" number="2"/> + <Lays companyType="Major" colour="green" number="1"/> + <Lays companyType="Major" colour="brown" number="1"/> + <Lays companyType="Major" colour="grey" number="1"/> <OffBoardRevenue step="4"/> <Trains limitStep="3" rusted="4"/> </Phase> @@ -150,8 +164,5 @@ class="rails.game.specific._1880.ExpressTrainRevenueModifier"/> </Component> </Component> - <Component name="RevenueManager" class="rails.algorithms.RevenueManager"> - <Modifier class="rails.game.specific._1826.TGVModifier"/> - </Component> - + </ComponentManager> \ No newline at end of file diff --git a/data/1880/StockMarket.xml b/data/1880/StockMarket.xml index 5960108..c3dfccf 100644 --- a/data/1880/StockMarket.xml +++ b/data/1880/StockMarket.xml @@ -42,19 +42,19 @@ <StockSpace name="C9" price="60" /> <StockSpace name="D1" price="105" /> <StockSpace name="D2" price="100" > - <StartSpace parslots="4"/> + <StartSpace/> </StockSpace> <StockSpace name="D3" price="95" /> <StockSpace name="D4" price="90" > - <StartSpace parslots="4"/> + <StartSpace/> </StockSpace> <StockSpace name="D5" price="85" /> <StockSpace name="D6" price="80" > - <StartSpace parslots="4"/> + <StartSpace/> </StockSpace> <StockSpace name="D7" price="75" /> <StockSpace name="D8" price="70" > - <StartSpace parslots="4"/> + <StartSpace/> </StockSpace> <StockSpace name="D9" price="65" /> <StockSpace name="E1" price="110" /> diff --git a/data/1880/Tiles.xml b/data/1880/Tiles.xml index 34f548a..6ed5fd7 100644 --- a/data/1880/Tiles.xml +++ b/data/1880/Tiles.xml @@ -62,7 +62,7 @@ <Track from="city1" gauge="normal" to="side0"/> </Tile><Tile colour="yellow" id="235" name="235"> <Station id="city1" position="502" slots="1" type="City" value="20"/> - <Station id="city2" position="352" slots="1" type="City" value="20"/> + <Station id="city2" position="352" slots="1" type="City"/> <Track from="city1" gauge="normal" to="side5"/> </Tile><Tile colour="yellow" id="8850" name="8850"> <Station id="city1" position="352" type="Town" value="20"/> diff --git a/rails/game/Company.java b/rails/game/Company.java index f96b3a8..0b2aa2f 100644 --- a/rails/game/Company.java +++ b/rails/game/Company.java @@ -46,7 +46,7 @@ Cloneable, Comparable<Company> { /** Closed state */ protected BooleanState closedObject; - // Moved here from PrivayeCOmpany on behalf of 1835 + // Moved here from PrivateCompany on behalf of 1835 protected List<SpecialPropertyI> specialProperties = null; protected static Logger log = diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java index 8046968..8058d91 100644 --- a/rails/game/GameManager.java +++ b/rails/game/GameManager.java @@ -226,6 +226,10 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { protected static Logger log = Logger.getLogger(GameManager.class.getPackage().getName()); + //State variable to be able to determine a changed playerorder after a Startround Sub Phase + //Currently use in 1880 (1853, 1844, 1837, or any other game that reorders players after result of startinground) + public BooleanState playerOrderHasChanged = new BooleanState("PlayerOrderHasChange", false); + public GameManager() { gmName = GM_NAME; gmKey = GM_KEY; @@ -1341,7 +1345,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { addToNextPlayerMessages(msg, true); } - private void finishGame() { + protected void finishGame() { gameOver.set(true); String message = LocalText.getText("GameOver"); @@ -1885,21 +1889,21 @@ public class GameManager implements ConfigurableComponentI, GameManagerI { public Player reorderPlayersByCash (boolean ascending) { final boolean _ascending = ascending; - Collections.sort (players, new Comparator<Player>() { + Collections.sort (this.players, new Comparator<Player>() { public int compare (Player p1, Player p2) { return _ascending ? p1.getCash() - p2.getCash() : p2.getCash() - p1.getCash(); } }); Player player; - for (int i=0; i<players.size(); i++) { - player = players.get(i); + for (int i=0; i<this.players.size(); i++) { + player = this.players.get(i); player.setIndex (i); - playerNames.set (i, player.getName()); + this.playerNames.set (i, player.getName()); log.debug("New player "+i+" is "+player.getName() +" (cash="+Bank.format(player.getCash())+")"); } - return players.get(0); + return this.players.get(0); } public void resetStorage() { diff --git a/rails/game/PublicCompany.java b/rails/game/PublicCompany.java index 16c25ee..3ad1c2c 100644 --- a/rails/game/PublicCompany.java +++ b/rails/game/PublicCompany.java @@ -792,6 +792,7 @@ public class PublicCompany extends Company implements PublicCompanyI { name + "_" + colour + "_ExtraTileTurns", turns)); } + /** Reset turn objects */ public void initTurn() { @@ -1963,6 +1964,7 @@ public class PublicCompany extends Company implements PublicCompanyI { // New style int tileLays = phase.getTileLaysPerColour(getTypeName(), tileColour); + if (tileLays <= 1) { extraTileLays = null; return tileLays; @@ -1973,6 +1975,8 @@ public class PublicCompany extends Company implements PublicCompanyI { if (turnsWithExtraTileLays != null) { extraTiles = turnsWithExtraTileLays.get(tileColour); } + + if (extraTiles != null) { if (extraTiles.intValue() == 0) { extraTiles = null; @@ -2091,4 +2095,5 @@ public class PublicCompany extends Company implements PublicCompanyI { public boolean hasRoute() { return true; } + } diff --git a/rails/game/PublicCompanyI.java b/rails/game/PublicCompanyI.java index f39b619..ab08a06 100644 --- a/rails/game/PublicCompanyI.java +++ b/rails/game/PublicCompanyI.java @@ -16,7 +16,7 @@ public interface PublicCompanyI extends CompanyI, CashHolder, TokenHolder { public static final int CAPITALISE_INCREMENTAL = 1; public static final int CAPITALISE_WHEN_BOUGHT = 2; - + public void setIndex (int index); diff --git a/rails/game/Round.java b/rails/game/Round.java index b162080..0dcfd98 100644 --- a/rails/game/Round.java +++ b/rails/game/Round.java @@ -13,6 +13,7 @@ import rails.common.*; import rails.game.action.*; import rails.game.move.*; import rails.game.special.SpecialPropertyI; +import rails.game.specific._1880.PublicCompany_1880; import rails.game.state.BooleanState; /** @@ -373,7 +374,7 @@ public abstract class Round implements RoundI { } else if (capitalisationMode == PublicCompanyI.CAPITALISE_WHEN_BOUGHT) { // Cash goes directly to treasury at each buy (as in 1856 before phase 6) capFactor = 0; - } + } int price = company.getIPOPrice(); cash = capFactor * price; } else { diff --git a/rails/game/StockMarket.java b/rails/game/StockMarket.java index c117ead..d64e167 100644 --- a/rails/game/StockMarket.java +++ b/rails/game/StockMarket.java @@ -130,6 +130,7 @@ public class StockMarket implements StockMarketI, ConfigurableComponentI { if (spaceTag.getChild(StockSpaceI.START_SPACE_TAG) != null) { space.setStart(true); startSpaces.add(space); + } space.setClosesCompany(spaceTag.getChild(StockSpaceI.CLOSES_COMPANY_TAG) != null); space.setEndsGame(spaceTag.getChild(StockSpaceI.GAME_OVER_TAG) != null); @@ -344,14 +345,14 @@ public class StockMarket implements StockMarketI, ConfigurableComponentI { public int[] getStartPrices() { return startPrices; } - + public StockSpaceI getStartSpace(int price) { for (StockSpaceI square : startSpaces) { if (square.getPrice() == price) return square; } return null; } - + public PublicCertificate removeShareFromPile(PublicCertificate stock) { if (ipoPile.contains(stock)) { int index = ipoPile.lastIndexOf(stock); @@ -378,4 +379,12 @@ public class StockMarket implements StockMarketI, ConfigurableComponentI { return numRows; } + public int getNumberOfStartPrices() { + int result = 0; + for(int i=0; i< startPrices.length; i++) { + if (startPrices[i]!= 0) result++; + } + return result; + } + } diff --git a/rails/game/StockMarketI.java b/rails/game/StockMarketI.java index a878360..96ed186 100644 --- a/rails/game/StockMarketI.java +++ b/rails/game/StockMarketI.java @@ -48,4 +48,5 @@ public interface StockMarketI extends ConfigurableComponentI { public void processMoveToStackPosition(PublicCompanyI company, StockSpaceI from, StockSpaceI to, int toStackPosition); + } diff --git a/rails/game/StockRound.java b/rails/game/StockRound.java index ca25bf3..0d3fcf8 100644 --- a/rails/game/StockRound.java +++ b/rails/game/StockRound.java @@ -1657,4 +1657,8 @@ public class StockRound extends Round { sellObligationLifted.add(company); } + /* (non-Javadoc) + * @see rails.game.Round#floatCompany(rails.game.PublicCompanyI) + */ + } diff --git a/rails/game/StockSpace.java b/rails/game/StockSpace.java index 1945cbf..5853946 100644 --- a/rails/game/StockSpace.java +++ b/rails/game/StockSpace.java @@ -247,7 +247,7 @@ public class StockSpace extends ModelObject implements StockSpaceI { public void setStart(boolean b) { start = b; } - + /** * @param set if token is left of ledge */ diff --git a/rails/game/StockSpaceI.java b/rails/game/StockSpaceI.java index 83cc3e7..578a6d5 100644 --- a/rails/game/StockSpaceI.java +++ b/rails/game/StockSpaceI.java @@ -29,6 +29,9 @@ public interface StockSpaceI // extends TokenHolderI */ public static final String START_SPACE_TAG = "StartSpace"; + /** The name of the XML tag for the number of Parslots per Startprice */ + public static final String START_SPACE_SLOTS_TAG ="ParSlots"; + /** The name of the XML tag for the "below ledge" property. */ public static final String BELOW_LEDGE_TAG = "BelowLedge"; @@ -38,7 +41,7 @@ public interface StockSpaceI // extends TokenHolderI /** The name of the XML tag for the "closes company" property. */ public static final String CLOSES_COMPANY_TAG = "ClosesCompany"; - /** The name of the XML tag for the "gamn over" property. */ + /** The name of the XML tag for the "game over" property. */ public static final String GAME_OVER_TAG = "GameOver"; // No constructors (yet) for the booleans, which are rarely needed. Use the diff --git a/rails/game/StockSpaceType.java b/rails/game/StockSpaceType.java index 6e5295f..c1e965d 100644 --- a/rails/game/StockSpaceType.java +++ b/rails/game/StockSpaceType.java @@ -22,6 +22,7 @@ public class StockSpaceType implements StockSpaceTypeI { protected boolean noCertLimit = false; // In yellow zone protected boolean noHoldLimit = false; // In orange zone (1830) protected boolean noBuyLimit = false; // In brown zone (1830) + protected int addRevenue = 0; // additional revenue for company listed at that space (1880) public static final String WHITE = "FFFFFF"; @@ -72,6 +73,14 @@ public class StockSpaceType implements StockSpaceTypeI { public boolean isNoHoldLimit() { return noHoldLimit; } + + /** + * @return returns the additional revenue per 10% share + */ + public int hasAddRevenue() { + return addRevenue; + } + /*--- Setters ---*/ /** @@ -94,5 +103,11 @@ public class StockSpaceType implements StockSpaceTypeI { public void setNoHoldLimit(boolean b) { noHoldLimit = b; } - + /** + * @param revenue additional Revenue for a company listed at this space + */ + public void setAddRevenue(int revenue) { + addRevenue = revenue; + } + } diff --git a/rails/game/StockSpaceTypeI.java b/rails/game/StockSpaceTypeI.java index ca896f7..a84aa63 100644 --- a/rails/game/StockSpaceTypeI.java +++ b/rails/game/StockSpaceTypeI.java @@ -41,8 +41,8 @@ public interface StockSpaceTypeI { * The name of the XML tag for the "NoBuyLimit" property. (1830: brown area) */ public static final String NO_BUY_LIMIT_TAG = "NoBuyLimit"; - - /** + + /** * @return Color */ public abstract Color getColour(); @@ -67,6 +67,11 @@ public interface StockSpaceTypeI { * @return if space triggers Stock not counting toward certificate limit */ public boolean isNoHoldLimit(); + + /** + * @return returns the additional revenue per 10% share + */ + public int hasAddRevenue(); /** * @param b @@ -82,5 +87,10 @@ public interface StockSpaceTypeI { * @param b */ public void setNoHoldLimit(boolean b); - + + /** + * @param revenue additional Revenue for a company listed at this space + */ + public void setAddRevenue(int revenue); + } diff --git a/rails/game/action/BuyStartItem.java b/rails/game/action/BuyStartItem.java index 2b203a7..a66ac7e 100644 --- a/rails/game/action/BuyStartItem.java +++ b/rails/game/action/BuyStartItem.java @@ -5,6 +5,8 @@ */ package rails.game.action; +import java.util.BitSet; + import rails.game.PublicCompanyI; import rails.game.StartItem; @@ -16,12 +18,13 @@ public class BuyStartItem extends StartItemAction { /* Server-provided fields */ private int price; private boolean selected; - private boolean sharePriceToSet = false; - private String companyNeedingSharePrice = null; - private boolean setSharePriceOnly = false; + protected boolean sharePriceToSet = false; + protected String companyNeedingSharePrice = null; + protected boolean setSharePriceOnly = false; // Client-provided fields private int associatedSharePrice; + private BitSet associatedBuildingRight; public static final long serialVersionUID = 1L; @@ -38,7 +41,7 @@ public class BuyStartItem extends StartItemAction { PublicCompanyI company; if ((company = startItem.needsPriceSetting()) != null) { - sharePriceToSet = true; + sharePriceToSet=true; companyNeedingSharePrice = company.getName(); } } @@ -102,4 +105,5 @@ public class BuyStartItem extends StartItemAction { return b.toString(); } + } diff --git a/rails/game/specific/_1880/BuyStartItem_1880.java b/rails/game/specific/_1880/BuyStartItem_1880.java new file mode 100644 index 0000000..3efa52c --- /dev/null +++ b/rails/game/specific/_1880/BuyStartItem_1880.java @@ -0,0 +1,164 @@ +/** + * + */ +package rails.game.specific._1880; + +import rails.game.StartItem; +import rails.game.action.BuyStartItem; + +import java.util.BitSet; + +import rails.game.PublicCompanyI; +import rails.game.action.PossibleAction; +/** + * @author Martin Brumm + * + */ +public class BuyStartItem_1880 extends BuyStartItem { + + public static final long serialVersionUID = 1L; + + private BitSet buildingRights; + + private BitSet associatedBuildingRight; + /** + * @param startItem + * @param price + * @param selected + * @param setSharePriceOnly + */ + public BuyStartItem_1880(StartItem startItem, int price, boolean selected, + boolean setSharePriceOnly) { + + + super(startItem, price, selected, setSharePriceOnly); + // TODO Auto-generated constructor stub + this.buildingRights = new BitSet(4); + } + + + public BuyStartItem_1880(StartItem startItem, int price, boolean selected, + boolean setSharePriceOnly, BitSet buildingRight) { + + super(startItem,price,selected,setSharePriceOnly); + this.buildingRights = buildingRight; + + PublicCompanyI company; + if ((company = startItem.needsPriceSetting()) != null) { + sharePriceToSet = true; + companyNeedingSharePrice = company.getName(); + } + } + + /** + * @param startItem + * @param price + * @param selected + */ + public BuyStartItem_1880(StartItem startItem, int price, boolean selected) { + super(startItem, price, selected); + // TODO Auto-generated constructor stub + this.buildingRights = new BitSet(4); + } + + public boolean equalsAsOption(PossibleAction action) { + if (!(action instanceof BuyStartItem_1880)) return false; + BuyStartItem_1880 a = (BuyStartItem_1880) action; + return a.startItem == startItem && a.itemIndex == itemIndex + && a.getPrice() == getPrice() && a.buildingRights == buildingRights; + } + public boolean equalsAsAction(PossibleAction action) { + if (!(action instanceof BuyStartItem_1880)) return false; + BuyStartItem_1880 a = (BuyStartItem_1880) action; + return a.equalsAsOption(this) + && a.getAssociatedSharePrice() == getAssociatedSharePrice() + && a.associatedBuildingRight == associatedBuildingRight; + } + public String toString() { + StringBuffer b = new StringBuffer(); + b.append("BuyStartItem_1880 ").append(startItemName).append(" price=").append( + getPrice()).append(" selected=").append(isSelected()); + + if (sharePriceToSet) { + b.append(" shareprice=").append(getAssociatedSharePrice()).append(" BuildingRight=").append(buildingRightToString(buildingRights)).append( + " for company " + companyNeedingSharePrice); + } + return b.toString(); + } + + /** + * @return the buildingRights + */ + public BitSet getAssociatedBuildingRight() { + return associatedBuildingRight; + } + /** + * @param buildingRights the buildingRights to set + */ + public void setAssociatedBuildingRight(BitSet buildingRight ) { + this.associatedBuildingRight = buildingRight; + } + + public void setAssociatedBuildingRight(String buildingRightString ) { + BitSet buildingRight = new BitSet(); + + if (buildingRightString == "A") { + buildingRight.set(0); + } else if (buildingRightString == "B") { + buildingRight.set(1); + } else if (buildingRightString == "C") { + buildingRight.set(2); + } else if (buildingRightString == "D") { + buildingRight.set(3); + } else if (buildingRightString == "A+B") { + buildingRight.set(0,1); + } else if (buildingRightString == "A+B+C") { + buildingRight.set(0,2); + } else if (buildingRightString == "B+C") { + buildingRight.set(1,2); + } else if (buildingRightString == "B+C+D") { + buildingRight.set(1,3); + } else if (buildingRightString == "C+D") { + buildingRight.set(2,3); + } + + this.associatedBuildingRight = buildingRight; + } + + public String buildingRightToString (BitSet buildingRight){ + String buildingRightString = null; + + if (! buildingRight.isEmpty()){ + if (buildingRight.get(0)== true) { + buildingRightString = "A"; + if (buildingRight.get(1) == true) { + buildingRightString = "A+B"; + if (buildingRight.get(2) == true) { + buildingRightString = "A+B+C"; + } + } + } + else if (buildingRight.get(1) == true) { + buildingRightString = "B"; + if (buildingRight.get(2) == true) { + buildingRightString = "B+C"; + if (buildingRight.get(3) == true){ + buildingRightString = "B+C+D"; + } + } + } + else if (buildingRight.get(2) == true){ + buildingRightString = "C"; + if (buildingRight.get(3) == true){ + buildingRightString = "C+D"; + } + } + else if (buildingRight.get(3) == true){ + buildingRightString= "D"; + } + return buildingRightString; + } + return "None"; + } + +} \ No newline at end of file diff --git a/rails/game/specific/_1880/GameManager_1880.java b/rails/game/specific/_1880/GameManager_1880.java new file mode 100644 index 0000000..6fded62 --- /dev/null +++ b/rails/game/specific/_1880/GameManager_1880.java @@ -0,0 +1,102 @@ +/** + * + */ +package rails.game.specific._1880; + +import rails.game.GameManager; +import rails.game.PhaseI; +import rails.game.RoundI; +import rails.game.StartRound; +import rails.game.StockRound; +import rails.game.state.IntegerState; + +/** + * @author Martin Brumm + * @date 21.1.2012 + * + */ +public class GameManager_1880 extends GameManager { + + private RoundI previousRound = null; + public IntegerState numOfORs = new IntegerState("numOfORs"); + //Keeps track of the company that purchased the last train + private PublicCompany_1880 lastTrainBuyingCompany; + /** + * + */ + public GameManager_1880() { + super(); + } + + /* (non-Javadoc) + * @see rails.game.GameManager#nextRound(rails.game.RoundI) + */ + @Override + public void nextRound(RoundI round) { + if (round instanceof StartRound) { // BCR Operates only if all privates are sold out + if (startPacket != null && !startPacket.areAllSold()) { + startOperatingRound(runIfStartPacketIsNotCompletelySold()); + } else { + startStockRound(); + } + numOfORs.set(10); + } else if (round instanceof StockRound) { + if (interruptedRound != null) { + setRound(interruptedRound); + interruptedRound.resume(); + interruptedRound = null; + } else { // First StockRound after StartRound... + PhaseI currentPhase = getCurrentPhase(); + if (currentPhase == null) log.error ("Current Phase is null??", new Exception ("")); + // Create a new OperatingRound (never more than one Stock Round) + // OperatingRound.resetRelativeORNumber(); + + relativeORNumber.set(1); + + startOperatingRound(true); + } + } else if ( round instanceof OperatingRound_1880) { + if (gameOverPending.booleanValue() && !gameEndsAfterSetOfORs) { + + finishGame(); + + } else if (relativeORNumber.add(1) <= numOfORs.intValue()) { + // There will be another OR + startOperatingRound(true); + } else if (startPacket != null && !startPacket.areAllSold()) { + startStartRound(); + } else { + if (gameOverPending.booleanValue() && gameEndsAfterSetOfORs) { + finishGame(); + } + } + } + }// End of nextRound + + /** + * @return the lastTrainBuyingCompany + */ + public PublicCompany_1880 getLastTrainBuyingCompany() { + return lastTrainBuyingCompany; + } + + /** + * @param lastTrainBuyingCompany the lastTrainBuyingCompany to set + */ + public void setLastTrainBuyingCompany(PublicCompany_1880 lastTrainBuyingCompany) { + this.lastTrainBuyingCompany = lastTrainBuyingCompany; + } + + /* (non-Javadoc) + * @see rails.game.GameManager#startStockRound() + */ + + protected void startStockRound_1880(OperatingRound_1880 or) { + // TODO Auto-generated method stub + interruptedRound = or; + super.startStockRound(); + } + + + +} diff --git a/rails/game/specific/_1880/OperatingRound_1880.java b/rails/game/specific/_1880/OperatingRound_1880.java index 3471cfa..7d9a9ee 100644 --- a/rails/game/specific/_1880/OperatingRound_1880.java +++ b/rails/game/specific/_1880/OperatingRound_1880.java @@ -3,8 +3,52 @@ */ package rails.game.specific._1880; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import rails.common.DisplayBuffer; +import rails.common.GuiDef; +import rails.common.LocalText; +import rails.game.Bank; +import rails.game.Bonus; +import rails.game.GameDef; import rails.game.GameManagerI; +import rails.game.MapHex; import rails.game.OperatingRound; +import rails.game.PhaseI; +import rails.game.Player; +import rails.game.Portfolio; +import rails.game.PrivateCompanyI; +import rails.game.PublicCompanyI; +import rails.game.ReportBuffer; +import rails.game.TrainCertificateType; +import rails.game.TrainI; +import rails.game.TrainManager; +import rails.game.TrainType; +import rails.game.action.BuyBonusToken; +import rails.game.action.BuyPrivate; +import rails.game.action.BuyTrain; +import rails.game.action.DiscardTrain; +import rails.game.action.LayBaseToken; +import rails.game.action.NullAction; +import rails.game.action.PossibleAction; +import rails.game.action.PossibleORAction; +import rails.game.action.SetDividend; +import rails.game.action.UseSpecialProperty; +import rails.game.correct.ClosePrivate; +import rails.game.move.AddToList; +import rails.game.move.CashMove; +import rails.game.move.ObjectMove; +import rails.game.special.SellBonusToken; +import rails.game.special.SpecialPropertyI; +import rails.game.special.SpecialTileLay; +import rails.game.special.SpecialTokenLay; +import rails.game.special.SpecialTrainBuy; +import rails.game.specific._1880.PublicCompany_1880; +import rails.game.specific._1880.GameManager_1880; +import rails.game.state.EnumState; +import rails.sound.BackgroundMusicManager; /** * @author Martin @@ -12,12 +56,298 @@ import rails.game.OperatingRound; */ public class OperatingRound_1880 extends OperatingRound { + + protected GameDef.OrStep[] steps = + new GameDef.OrStep[] { + GameDef.OrStep.INITIAL, + GameDef.OrStep.LAY_TRACK, + GameDef.OrStep.LAY_TOKEN, + GameDef.OrStep.CALC_REVENUE, + GameDef.OrStep.PAYOUT, + GameDef.OrStep.BUY_TRAIN, + GameDef.OrStep.TRADE_SHARES, + GameDef.OrStep.FINAL }; + /** * @param gameManager */ - public OperatingRound_1880(GameManagerI gameManager) { - super(gameManager); + public OperatingRound_1880(GameManagerI gameManager_1880) { + super(gameManager_1880); // TODO Auto-generated constructor stub } + @Override + public void processPhaseAction (String name, String value) { + if (name.equalsIgnoreCase("RaisingCertAvailability")){ + for (PublicCompanyI company : gameManager.getAllPublicCompanies()){ + if (!company.hasFloated()){ + ((PublicCompany_1880) company).setFloatPercentage(30); + } + } + } + if (name.equalsIgnoreCase("CommunistTakeOver")) { + for (PublicCompanyI company : getOperatingCompanies()) { + if (company.hasFloated()) { + ((PublicCompany_1880)company).setCommunistTakeOver(true); + } + } + for (PublicCompanyI company : gameManager.getAllPublicCompanies()){ + if (!company.hasFloated()){ + ((PublicCompany_1880) company).setFloatPercentage(40); + } + } + } + if (name.equalsIgnoreCase("ShanghaiExchangeOpen")) { + for (PublicCompanyI company : getOperatingCompanies()) { + if (company.hasFloated()) { + ((PublicCompany_1880)company).setCommunistTakeOver(false); + } + } + for (PublicCompanyI company : gameManager.getAllPublicCompanies()){ + if (!company.hasFloated()){ + ((PublicCompany_1880) company).setFloatPercentage(60); + } + } + } + } + + @Override + protected void prepareRevenueAndDividendAction () { + + int[] allowedRevenueActions = new int[] {}; + // There is only revenue if there are any trains + if (operatingCompany.get().canRunTrains()) { + if (operatingCompany.get().hasStockPrice()) { + allowedRevenueActions = + operatingCompany.get().isSplitAlways() + ? new int[] { SetDividend.SPLIT } + : operatingCompany.get().isSplitAllowed() + ? new int[] { SetDividend.PAYOUT, + SetDividend.SPLIT, + SetDividend.WITHHOLD } + : new int[] { SetDividend.PAYOUT, + SetDividend.WITHHOLD }; + } + else { //Minors in 1880 are not allowed to hand out Cash except in Closing + allowedRevenueActions = new int[] {SetDividend.WITHHOLD }; + } + + possibleActions.add(new SetDividend( + operatingCompany.get().getLastRevenue(), true, + allowedRevenueActions)); + } + } + + /* (non-Javadoc) + * @see rails.game.OperatingRound#initNormalTileLays() + */ + @Override + protected void initNormalTileLays() { + /** + * Create a List of allowed normal tile lays (see LayTile class). This + * method should be called only once per company turn in an OR: at the start + * of the tile laying step. + */ + String opCompany = operatingCompany.get().getName(); + // duplicate the phase colours + Map<String, Integer> newTileColours = new HashMap<String, Integer>(); + for (String colour : getCurrentPhase().getTileColours()) { + int allowedNumber = operatingCompany.get().getNumberOfTileLays(colour); + // Replace the null map value with the allowed number of lays + newTileColours.put(colour, new Integer(allowedNumber)); + } + // store to state + tileLaysPerColour.initFromMap(newTileColours); + } + + /* (non-Javadoc) + * @see rails.game.OperatingRound#start() + */ + @Override + public void start() { + thisOrNumber = gameManager.getORId(); + + ReportBuffer.add(LocalText.getText("START_OR", thisOrNumber)); + + BackgroundMusicManager.notifyOfOperatingRoundStart(); + + for (Player player : gameManager.getPlayers()) { + player.setWorthAtORStart(); + } + + privatesPayOut(); + + if ((operatingCompanies.size() > 0) && (gameManager.getAbsoluteORNumber()>= 1)){ + // even if the BCR is sold she doesn't operate until all privates have been sold + //the absolute OR value is not incremented if not the startpacket has been sold completely + + StringBuilder msg = new StringBuilder(); + for (PublicCompanyI company : operatingCompanies.viewList()) { + msg.append(",").append(company.getName()); + } + if (msg.length() > 0) msg.deleteCharAt(0); + log.info("Initial operating sequence is "+msg.toString()); + + if (stepObject == null) { + stepObject = new EnumState<GameDef.OrStep>("ORStep", GameDef.OrStep.INITIAL); + stepObject.addObserver(this); + } + + if (setNextOperatingCompany(true)){ + setStep(GameDef.OrStep.INITIAL); + } + return; + } + + // No operating companies yet: close the round. + String text = LocalText.getText("ShortORExecuted"); + ReportBuffer.add(text); + DisplayBuffer.add(text); + finishRound(); + } + + /* (non-Javadoc) + * @see rails.game.OperatingRound#buyTrain(rails.game.action.BuyTrain) + */ + @Override + public boolean buyTrain(BuyTrain action) { + + SpecialTrainBuy stb = null; + PublicCompany_1880 oldLastTrainBuyingCompany = null; + TrainManager TrainMgr=gameManager.getTrainManager(); + List<TrainI> trains; + boolean lastTrainOfType = false; + + stb = action.getSpecialProperty(); + + trains=TrainMgr.getAvailableNewTrains(); + + if ((trains.size() == 1)&& (ipo.getTrainsPerType(trains.get(0).getType()).length==1 )){ // Last available train of a type is on for grabs.. + lastTrainOfType=true; + } + + if (stb != null) { // A special Train buying right that gets exercised doesnt prolong the train rush + + oldLastTrainBuyingCompany= ((GameManager_1880) gameManager).getLastTrainBuyingCompany(); + + if (super.buyTrain(action)) { + if (stb.isExercised()){ + ((GameManager_1880) gameManager).setLastTrainBuyingCompany(oldLastTrainBuyingCompany); + } else { + ((GameManager_1880) gameManager).setLastTrainBuyingCompany((PublicCompany_1880) operatingCompany.get()); + } + //Check: Did we just buy the last Train of that Type ? Then we fire up the Stockround + if (lastTrainOfType) { + ((GameManager_1880) gameManager).startStockRound_1880(this); + } + return true; + } else { + return false; + } + } else { + if (super.buyTrain(action)) { + ((GameManager_1880) gameManager).setLastTrainBuyingCompany((PublicCompany_1880) operatingCompany.get()); + //Check: Did we just buy the last Train of that Type ? Then we fire up the Stockround + if (lastTrainOfType) { + ((GameManager_1880) gameManager).startStockRound_1880(this); + } + return true; + } else { + return false; + } + } + } + + /* (non-Javadoc) + * @see rails.game.OperatingRound#newPhaseChecks() + */ + @Override + protected void newPhaseChecks() { + PhaseI newPhase = getCurrentPhase(); + if (newPhase.getName()=="8") { + ((GameManager_1880) gameManager).numOfORs.set(2); // After the first 8 has been bought there will be a last Stockround and two ORs. + } + else { + if (newPhase.getName() == "8e") { + return; + } + } + + } + + @Override + public void resume () { + + guiHints.setActivePanel(GuiDef.Panel.MAP); + guiHints.setCurrentRoundType(getClass()); + + if (getOperatingCompany() != null) { + setStep(GameDef.OrStep.BUY_TRAIN); + } else { + finishOR(); + } + wasInterrupted.set(true); + } + + /* (non-Javadoc) + * @see rails.game.OperatingRound#process(rails.game.action.PossibleAction) + */ + @Override + public boolean process(PossibleAction action) { + + boolean result = false; + + if (action instanceof PossibleORAction + && !(action instanceof DiscardTrain)) { + PublicCompanyI company = ((PossibleORAction) action).getCompany(); + if (company != operatingCompany.get()) { + DisplayBuffer.add(LocalText.getText("WrongCompany", + company.getName(), + operatingCompany.get().getName() )); + return false; + } + } + + selectedAction = action; + + if (selectedAction instanceof NullAction) { + + NullAction nullAction = (NullAction) action; + switch (nullAction.getMode()) { + case NullAction.DONE: //Making Sure that the NullAction.DONE is in the Buy_Train Step.. + if (getStep() != GameDef.OrStep.BUY_TRAIN){ + result = done(); + break; + } + if (operatingCompany.get() == ((GameManager_1880) gameManager).getLastTrainBuyingCompany()){ + if (trainsBoughtThisTurn.isEmpty()) { + // The current Company is the Company that has bought the last train and that purchase was not in this OR.. + // we now discard the remaining active trains of that Subphase and start a stockround... + List<TrainI> trains = trainManager.getAvailableNewTrains(); + TrainType currentType = trains.get(0).getType(); + for (TrainI train: trains){ + new ObjectMove(train,ipo,scrapHeap); + } + ((GameManager_1880) gameManager).startStockRound_1880(this); + } + } + result = done(); + break; + case NullAction.PASS: + result = done(); + break; + case NullAction.SKIP: + skip(); + result = true; + break; + } + return result; + } + else { + return super.process(action); + } + } + } + + diff --git a/rails/game/specific/_1880/PublicCompany_1880.java b/rails/game/specific/_1880/PublicCompany_1880.java index 0add471..885d364 100644 --- a/rails/game/specific/_1880/PublicCompany_1880.java +++ b/rails/game/specific/_1880/PublicCompany_1880.java @@ -3,8 +3,16 @@ */ package rails.game.specific._1880; +import java.util.BitSet; + +import rails.common.GuiDef; +import rails.common.parser.ConfigurationException; +import rails.common.parser.Tag; import rails.game.*; -import rails.game.state.IntegerState; +import rails.game.model.ModelObject; +import rails.game.state.BooleanState; +import rails.game.state.HashMapState; + /** * @author Martin @@ -12,12 +20,169 @@ import rails.game.state.IntegerState; */ public class PublicCompany_1880 extends PublicCompany { + + /** + * Buildingrights belong to Phases in 1880 the player will be asked to choose which combination + * he wants and subsequently his company will be granted the appropriate rights. Further the value + * of the presidents share depends on the building right. + * A Player has the maximum of 3 phases without the use of a special power of a certain private paper. + * Example : A) Player chooses to build in Phase A+B+C (or B+C+D) this will lead to a president share value of 20% + * B) Player chooses to build in Phase A+B (or B+C or C+D) this will lead to a president share value of 30 % + * C) Player chooses to build in Phase A (or B or C or D) this will lead to a president share value of 40 % + * The BitSet BuildingRights should be able to handle the information : + * Bit 0 set True Player can build in Phase A + * Bit 1 set True Player can build in Phase B + * Bit 2 set True Player can build in Phase C + * Bit 3 set True Player can build in Phase D + * + */ + private BitSet buildingRights = new BitSet(4); + + + + //Implementation of PhaseAction to be able to handle the CommunistPhase + private BooleanState communistTakeOver = new BooleanState ("communistTakeOver",false); + + //Implementation of PhaseAction to be able to handle the Change in Capitalisation + private BooleanState capitalChanged = new BooleanState ("capitalChanged",false); + + //Implementation of Phase Action to be able to handle the Post Communist Phase + private BooleanState shanghaiExchangeFounded = new BooleanState ("shanghaiExchangeFounded",false); + + + /** * */ + public PublicCompany_1880() { + super(); + // TODO Auto-generated constructor stub + } + + /* (non-Javadoc) + * @see rails.game.PublicCompany#configureFromXML(rails.common.parser.Tag) + */ + @Override + public void configureFromXML(Tag tag) throws ConfigurationException { + // TODO Auto-generated method stub + super.configureFromXML(tag); + } + + /* (non-Javadoc) + * @see rails.game.PublicCompany#finishConfiguration(rails.game.GameManagerI) + */ + @Override + public void finishConfiguration(GameManagerI gameManager) + throws ConfigurationException { + // TODO Auto-generated method stub + super.finishConfiguration(gameManager); + // Introducing the rights field in the Display to be used by Building Rights Display and other Special Properties... + gameManager.setGuiParameter (GuiDef.Parm.HAS_ANY_RIGHTS, true); + if (rights == null) rights = new HashMapState<String, String>(name+"_Rights"); + } + + /** + * @return the buildingRights + */ + public BitSet getBuildingRights() { + return buildingRights; + } + /** + * @param buildingRights the buildingRights to set + */ + public void setBuildingRights(BitSet buildingRights) { + this.buildingRights = buildingRights; + } - + public void setCommunistTakeOver(boolean b) { + communistTakeOver.set(b); + + } + /** + * @return the communistTakeOver + */ + public Boolean isCommunistPhase() { + return communistTakeOver.booleanValue(); + } + + public ModelObject getCommunistTakeOver() { + return communistTakeOver; + } + + /** Don't move the space if the company is withholding train income during the CommunistPhase + * + */ + @Override + public void withhold(int amount) { + if (isCommunistPhase()) return; + if (hasStockPrice) stockMarket.withhold(this); + } + + public void setFloatPercentage(int i) { + this.floatPerc=i; + + } + + @Override + public boolean canRunTrains() { + if (!isCommunistPhase() && (!hasStockPrice()) ){ + return true; + } + return portfolio.getNumberOfTrains() > 0; + + } + + + + /* (non-Javadoc) + * @see rails.game.PublicCompany#getNumberOfTileLays(java.lang.String) + */ + @Override + public int getNumberOfTileLays(String tileColour) { + + if ((tileColour.equals("yellow")) && (this.getName().equals("BCR"))) { + int result=2; + return result; + } else { + return super.getNumberOfTileLays(tileColour); + } + } + + /** + * @return the capitalChanged + */ + public BooleanState getCapitalChanged() { + return capitalChanged; + } + + /** + * @param capitalChanged the capitalChanged to set + */ + public void setCapitalChanged(BooleanState capitalChanged) { + this.capitalChanged = capitalChanged; + } + + public boolean shouldBeCapitalisedFull() { + return this.capitalChanged.booleanValue(); + } + + /** + * @return the shanghaiExchangeFounded + */ + public BooleanState getShanghaiExchangeFounded() { + return shanghaiExchangeFounded; + } + + /** + * @param shanghaiExchangeFounded the shanghaiExchangeFounded to set + */ + public void setShanghaiExchangeFounded(BooleanState shanghaiExchangeFounded) { + this.shanghaiExchangeFounded = shanghaiExchangeFounded; + } + public boolean shanghaiExchangeIsOperational(){ + return this.shanghaiExchangeFounded.booleanValue(); + } } diff --git a/rails/game/specific/_1880/StartRound_1880.java b/rails/game/specific/_1880/StartRound_1880.java index ca9a01d..b7433e2 100644 --- a/rails/game/specific/_1880/StartRound_1880.java +++ b/rails/game/specific/_1880/StartRound_1880.java @@ -7,6 +7,7 @@ import rails.common.DisplayBuffer; import rails.common.LocalText; import rails.game.*; import rails.game.action.*; +import rails.game.move.CashMove; import rails.game.state.IntegerState; import rails.game.state.State; import rails.game.state.ArrayListState; @@ -96,18 +97,18 @@ public class StartRound_1880 extends StartRound { if (item.getStatus() == StartItem.NEEDS_SHARE_PRICE) { //still necessary ?? /* This status is set in buy() if a share price is missing */ setPlayer(item.getBidder()); - possibleActions.add(new BuyStartItem(item, item.getBid(), false, true)); + possibleActions.add(new BuyStartItem_1880(item, item.getBid(), false, true)); return true; // No more actions } if ((item.getBidder() == currentPlayer) && (numPasses.intValue() == getNumberOfPlayers()-1)){ // Current Player is highest Bidder & all others have passed if (item.needsPriceSetting() != null ){ - BuyStartItem possibleAction = new BuyStartItem(item,item.getBid(), true, true); + BuyStartItem_1880 possibleAction = new BuyStartItem_1880(item,item.getBid(), true, true); possibleActions.add(possibleAction); return true; // No more actions// no further Actions possible }else{ - BuyStartItem possibleAction = new BuyStartItem(item,item.getBid(),true); + BuyStartItem_1880 possibleAction = new BuyStartItem_1880(item,item.getBid(),true); possibleActions.add(possibleAction); return true; // No more actions// no further Actions possible @@ -148,21 +149,11 @@ public class StartRound_1880 extends StartRound { startingPlayer.set(currentPlayer); gameManager.setPriorityPlayer((Player) startingPlayer.get()); // Method doesn't exist in Startround ??? } - if (investorChosen.intValue() == getNumberOfPlayers()) { - for ( StartItem item1 : itemsToSell) { - if (!item1.isSold()){ - item1.setStatus(StartItem.UNAVAILABLE); - item1.setStatus(StartItem.SOLD); - - } - } - finishRound(); - return false; - } else { - for ( StartItem item1 : itemsToSell) { + + for ( StartItem item1 : itemsToSell) { if (!item1.isSold()){ item1.setStatus(StartItem.BUYABLE); - BuyStartItem possibleAction = new BuyStartItem(item1, 0, false); + BuyStartItem_1880 possibleAction = new BuyStartItem_1880(item1, 0, false); possibleActions.add(possibleAction); } } @@ -170,8 +161,7 @@ public class StartRound_1880 extends StartRound { return true; } - } - } + } /* (non-Javadoc) * @see rails.game.StartRound#bid(java.lang.String, rails.game.action.BidStartItem) @@ -381,5 +371,49 @@ public class StartRound_1880 extends StartRound { startingPlayer.set(gameManager.getPlayerB... [truncated message content] |
From: Frederick W. <fre...@us...> - 2012-01-22 12:38:30
|
LocalisedText.properties | 2 rails/ui/swing/GridPanel.java | 72 ++++--------- rails/ui/swing/ORUIManager.java | 2 rails/ui/swing/UpgradesPanel.java | 103 ++++++++++++++----- rails/ui/swing/hexmap/HexHighlightMouseListener.java | 29 +++++ rails/ui/swing/hexmap/HexMap.java | 11 ++ 6 files changed, 146 insertions(+), 73 deletions(-) New commits: commit 542796f830cf17bf0d8110b3eda239aa559e1ac3 Author: Frederick Weld <fre...@gm...> Date: Sun Jan 22 13:27:35 2012 +0100 Added hex highlighting for invalid tile lays (displays where tiles are) Motivation was that players often want to see what hex they have to update in order to make the needed tile available again. No configuration option has been added to disable such highlighting. diff --git a/rails/ui/swing/UpgradesPanel.java b/rails/ui/swing/UpgradesPanel.java index b650981..16486b5 100644 --- a/rails/ui/swing/UpgradesPanel.java +++ b/rails/ui/swing/UpgradesPanel.java @@ -19,6 +19,7 @@ import rails.game.action.*; import rails.game.correct.MapCorrectionAction; import rails.ui.swing.elements.ActionLabel; import rails.ui.swing.hexmap.GUIHex; +import rails.ui.swing.hexmap.HexHighlightMouseListener; import rails.ui.swing.hexmap.HexMap; public class UpgradesPanel extends Box implements MouseListener, ActionListener { @@ -201,6 +202,11 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener LocalText.getText(invalidTileUpgrades.get(tile))); hexLabel.setEnabled(false); hexLabel.setToolTipText(hexLabel.getToolTip()); + //highlight where tiles of this ID have been laid if no tiles left + if (invalidTileUpgrades.get(tile).equals(invalidUpgradeNoTilesLeft)) { + HexHighlightMouseListener.addMouseListener(hexLabel, + orUIManager, tile.getId(), true); + } upgradePanel.add(hexLabel); } } diff --git a/rails/ui/swing/hexmap/HexHighlightMouseListener.java b/rails/ui/swing/hexmap/HexHighlightMouseListener.java index 7cc2a96..89118b4 100644 --- a/rails/ui/swing/hexmap/HexHighlightMouseListener.java +++ b/rails/ui/swing/hexmap/HexHighlightMouseListener.java @@ -33,6 +33,7 @@ public class HexHighlightMouseListener implements MouseListener { HexMap hexMap; ORUIManager orUIManager; Portfolio portfolio; + int tileId; /** * lazy creation of the gui hex list for these reasons: @@ -104,6 +105,16 @@ public class HexHighlightMouseListener implements MouseListener { initPrivateCompanies(portfolio.getPrivateCompanies()); } + private void initTileIdHexList () { + //initially get hex map if not yet available + if (hexMap == null) hexMap = orUIManager.getMap(); + + //build the list of hexes the current tiles of which have the given tile ID + if (hexMap != null) { + guiHexList = hexMap.getHexesByCurrentTileId(tileId); + } + } + /** * @param orUIManager The OR UI manager containing the map where the highlighting * should occur @@ -128,6 +139,21 @@ public class HexHighlightMouseListener implements MouseListener { } /** + * @param tileId ID of the tile the occurrences of which should be highlighted on + * the map + * @param enableIrrespectiveOfHighlightConfig If true, the mouse listener is + * enabled irrespective of the base configuration. Needed since some highlighting + * should not be disabled by configuration. + */ + public static void addMouseListener(JComponent c,ORUIManager orUIManager,int tileId,boolean enableIrrespectiveOfHighlightConfig) { + if (isEnabled(enableIrrespectiveOfHighlightConfig)) { + HexHighlightMouseListener l = new HexHighlightMouseListener(orUIManager); + l.tileId = tileId; + c.addMouseListener(l); + } + } + + /** * @param p Private company the hexes associated to which are * to be highlighted (in case of events) * @param enableIrrespectiveOfHighlightConfig If true, the mouse listener is @@ -185,6 +211,7 @@ public class HexHighlightMouseListener implements MouseListener { public void mouseEntered(MouseEvent e) { if (portfolio != null) initPortfolioHexList(); + if (tileId != 0) initTileIdHexList(); initGuiHexList(); if (hexMap != null && guiHexList.size() > 0) { for (GUIHex guiHex : guiHexList) { @@ -199,7 +226,7 @@ public class HexHighlightMouseListener implements MouseListener { guiHex.removeHighlightRequest(); } } - if (portfolio != null) clearHexList(); + if (portfolio != null || tileId != 0) clearHexList(); } public void mouseClicked(MouseEvent e) { diff --git a/rails/ui/swing/hexmap/HexMap.java b/rails/ui/swing/hexmap/HexMap.java index 5d2188d..a9246a0 100644 --- a/rails/ui/swing/hexmap/HexMap.java +++ b/rails/ui/swing/hexmap/HexMap.java @@ -737,6 +737,17 @@ public abstract class HexMap implements MouseListener, { return selectedHex != null; } + + public List<GUIHex> getHexesByCurrentTileId (int tileId) { + List<GUIHex> hs = new ArrayList<GUIHex>(); + for (GUIHex h : hexes) { + TileI tile = h.getCurrentTile(); + if (tile != null && tile.getId() == tileId) { + hs.add(h); + } + } + return hs; + } public void setAllowedTileLays(List<LayTile> allowedTileLays) { commit 0085f9f6174978b9d8d4f41a4bec37da48d1a5a9 Author: Frederick Weld <fre...@gm...> Date: Sun Jan 22 12:42:57 2012 +0100 Added invalid tile lays to upgrade panel (grayed out & reason) Only two reasons are implementated (others do not appear to be valid): - no valid orientation - no tiles left Reasons are communicated by tooltips. diff --git a/LocalisedText.properties b/LocalisedText.properties index ee42f0c..ee9b8a4 100644 --- a/LocalisedText.properties +++ b/LocalisedText.properties @@ -435,6 +435,7 @@ NoSpecialProperty=No special property notExtra=not extra NoTile=No Tile NoTiles=At the moment there is no valid tile or upgrade for this hex. Select another hex or press the No Tile button. +NoTilesLeft=No tiles left NoTilesTag=No Tiles tag found in Tiles file NoTilesXML=No Tiles XML file specified NoToken=No Token @@ -451,6 +452,7 @@ NotBiddable=Item is not available for bidding NotYetFloated={0} has not yet floated. NotYetOperated={0} has not yet operated. NotYetStarted={0} is not yet started. +NoValidOrientation=No valid orientation NumberOfNormalTileLaysExceeded=Number of normal tile lays of colour {0} would be exceeded Obsolete4Trains=Delayed obsolescence 4-trains OCAmountEntry=free entry diff --git a/rails/ui/swing/ORUIManager.java b/rails/ui/swing/ORUIManager.java index 4bed76d..db96ac7 100644 --- a/rails/ui/swing/ORUIManager.java +++ b/rails/ui/swing/ORUIManager.java @@ -740,7 +740,7 @@ public class ORUIManager implements DialogOwner { } } - private boolean isTileUpgradeValid(GUIHex hex, TileI tile) { + public boolean isTileUpgradeValid(GUIHex hex, TileI tile) { // Check if the new tile must be connected to some other track return hex.isTileUpgradeValid(tile.getId(), getMustConnectRequirement(hex,tile)); diff --git a/rails/ui/swing/UpgradesPanel.java b/rails/ui/swing/UpgradesPanel.java index 7c67112..b650981 100644 --- a/rails/ui/swing/UpgradesPanel.java +++ b/rails/ui/swing/UpgradesPanel.java @@ -46,6 +46,11 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener new JButton(LocalText.getText(INIT_CANCEL_TEXT)); private JButton doneButton = new JButton(LocalText.getText(INIT_DONE_TEXT)); private HexMap hexMap; + + //list of tiles with an attached reason why it would represent an invalid upgrade + private Map<TileI,String> invalidTileUpgrades = null; + private static final String invalidUpgradeNoTilesLeft = "NoTilesLeft"; + private static final String invalidUpgradeNoValidOrientation = "NoValidOrientation"; protected static Logger log = Logger.getLogger(UpgradesPanel.class.getPackage().getName()); @@ -109,6 +114,22 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener } } } + + //determine invalid upgrades + //duplicates game engine logic to some degree + //but this is indispensable since the game engine's services not sufficient here + invalidTileUpgrades = new HashMap<TileI,String>(); + for (TileI tile : uiHex.getCurrentTile().getUpgrades(hex, currentPhase)) { + if (!orUIManager.tileUpgrades.contains(tile)) { + if (!currentPhase.isTileColourAllowed(tile.getColourName())) { + //current design decision: don't display tiles for invalid phases + } else if (!orUIManager.isTileUpgradeValid(uiHex, tile)) { + invalidTileUpgrades.put(tile, invalidUpgradeNoValidOrientation); + } else if (tile.countFreeTiles() == 0) { + invalidTileUpgrades.put(tile, invalidUpgradeNoTilesLeft); + } + } + } } public void showUpgrades() { @@ -164,37 +185,53 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener } else if (orUIManager.tileUpgrades == null) { ; - } else if (orUIManager.tileUpgrades.size() == 0) { - orUIManager.setMessage(LocalText.getText("NoTiles")); - } else { - for (TileI tile : orUIManager.tileUpgrades) { - BufferedImage hexImage = getHexImage(tile.getPictureId()); - ImageIcon hexIcon = new ImageIcon(hexImage); - - // Cheap n' Easy rescaling. - hexIcon.setImage(hexIcon.getImage().getScaledInstance( - (int) (hexIcon.getIconWidth() * GUIHex.NORMAL_SCALE * 0.8), - (int) (hexIcon.getIconHeight() * GUIHex.NORMAL_SCALE * 0.8), - Image.SCALE_SMOOTH)); - - HexLabel hexLabel = new HexLabel(hexIcon, tile.getId()); - hexLabel.setName(tile.getName()); - hexLabel.setTextFromTile(tile); - hexLabel.setOpaque(true); - hexLabel.setVisible(true); - hexLabel.setBorder(border); - hexLabel.addMouseListener(this); - - upgradePanel.add(hexLabel); + } else { + if (orUIManager.tileUpgrades.size() == 0) { + orUIManager.setMessage(LocalText.getText("NoTiles")); + } else { + for (TileI tile : orUIManager.tileUpgrades) { + HexLabel hexLabel = createHexLabel(tile,null); + hexLabel.addMouseListener(this); + upgradePanel.add(hexLabel); + } + } + if (invalidTileUpgrades != null) { + for (TileI tile : invalidTileUpgrades.keySet()) { + HexLabel hexLabel = createHexLabel(tile, + LocalText.getText(invalidTileUpgrades.get(tile))); + hexLabel.setEnabled(false); + hexLabel.setToolTipText(hexLabel.getToolTip()); + upgradePanel.add(hexLabel); + } } } - + upgradePanel.add(doneButton); upgradePanel.add(cancelButton); //repaint(); revalidate(); } + + private HexLabel createHexLabel(TileI tile,String toolTipHeaderLine) { + BufferedImage hexImage = getHexImage(tile.getPictureId()); + ImageIcon hexIcon = new ImageIcon(hexImage); + + // Cheap n' Easy rescaling. + hexIcon.setImage(hexIcon.getImage().getScaledInstance( + (int) (hexIcon.getIconWidth() * GUIHex.NORMAL_SCALE * 0.8), + (int) (hexIcon.getIconHeight() * GUIHex.NORMAL_SCALE * 0.8), + Image.SCALE_SMOOTH)); + + HexLabel hexLabel = new HexLabel(hexIcon, tile.getId(),toolTipHeaderLine); + hexLabel.setName(tile.getName()); + hexLabel.setTextFromTile(tile); + hexLabel.setOpaque(true); + hexLabel.setVisible(true); + hexLabel.setBorder(border); + + return hexLabel; + } // populate version for corrections public void showCorrectionTileUpgrades() { @@ -482,11 +519,15 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener int internalId; HexLabel(ImageIcon hexIcon, int internalId) { + this(hexIcon,internalId,null); + } + + HexLabel(ImageIcon hexIcon, int internalId, String toolTipHeaderLine) { super(hexIcon); this.internalId = internalId; - this.setToolTip(); + this.setToolTip(toolTipHeaderLine); } - + int getInternalId() { return internalId; } @@ -508,8 +549,14 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener } protected void setToolTip() { + setToolTip(null); + } + protected void setToolTip (String headerLine) { TileI currentTile = orUIManager.getGameUIManager().getGameManager().getTileManager().getTile(internalId); StringBuffer tt = new StringBuffer("<html>"); + if (headerLine != null && !headerLine.equals("")) { + tt.append("<b><u>"+headerLine+"</u></b><br>"); + } tt.append("<b>Tile</b>: ").append(currentTile.getName()); // or // getId() if (currentTile.hasStations()) { commit 4a2e4fb1758d403f25abfb63a311ddd6d34323c9 Author: Frederick Weld <fre...@gm...> Date: Sun Jan 22 07:01:45 2012 +0100 Refactored GridPanel's DynamicBorders Generalized symmetric / asymmetric dynamic borders to a general one. diff --git a/rails/ui/swing/GridPanel.java b/rails/ui/swing/GridPanel.java index a64f955..6644dd1 100644 --- a/rails/ui/swing/GridPanel.java +++ b/rails/ui/swing/GridPanel.java @@ -126,8 +126,8 @@ implements ActionListener, KeyListener { //- outer border: grid table lines (in wide_gap - narrow_gap thickness) comp.setBorder(new FieldBorder(comp.getBorder(), - new DynamicSymmetricBorder(cellOutlineColor,NARROW_GAP), - new DynamicAsymmetricBorder(tableBorderColor,padTop,padLeft,padBottom,padRight))); + new DynamicBorder(cellOutlineColor,NARROW_GAP), + new DynamicBorder(tableBorderColor,padTop,padLeft,padBottom,padRight))); gridPanel.add(comp, gbc); @@ -249,15 +249,15 @@ implements ActionListener, KeyListener { private class FieldBorder extends CompoundBorder { private static final long serialVersionUID = 1L; Border nativeInnerBorder; - DynamicAsymmetricBorder highlightedInnerBorder; - DynamicSymmetricBorder outlineBorder; - DynamicAsymmetricBorder outerBorder; - public FieldBorder(Border innerBorder,DynamicSymmetricBorder outlineBorder,DynamicAsymmetricBorder outerBorder) { + DynamicBorder highlightedInnerBorder; + DynamicBorder outlineBorder; + DynamicBorder outerBorder; + public FieldBorder(Border innerBorder,DynamicBorder outlineBorder,DynamicBorder outerBorder) { super(new CompoundBorder(outerBorder,outlineBorder),innerBorder); this.nativeInnerBorder = innerBorder; this.outlineBorder = outlineBorder; this.outerBorder = outerBorder; - this.highlightedInnerBorder = new DynamicAsymmetricBorder( + this.highlightedInnerBorder = new DynamicBorder( highlightedBorderColor, nativeInnerBorder.getBorderInsets(null).top, nativeInnerBorder.getBorderInsets(null).left, @@ -272,65 +272,45 @@ implements ActionListener, KeyListener { } /** - * A line border providing methods for changing the look + * A potentially asymmetric line border providing methods for changing the look * @author Frederick Weld * */ - private class DynamicSymmetricBorder extends AbstractBorder { + private class DynamicBorder extends AbstractBorder { private static final long serialVersionUID = 1L; - private int thickness; + private int padTop, padLeft, padBottom, padRight; private Color borderColor; private boolean isHighlighted = false; - public DynamicSymmetricBorder (Color borderColor,int thickness) { - this.thickness = thickness; + + public DynamicBorder (Color borderColor,int symmetricPad) { + this.padTop = symmetricPad; + this.padLeft = symmetricPad; + this.padBottom = symmetricPad; + this.padRight = symmetricPad; + this.borderColor = borderColor; + } + + public DynamicBorder (Color borderColor,int padTop, int padLeft, int padBottom, int padRight) { + this.padTop = padTop; + this.padLeft = padLeft; + this.padBottom = padBottom; + this.padRight = padRight; this.borderColor = borderColor; } + public void setHighlight(boolean isToBeHighlighted) { if (isHighlighted != isToBeHighlighted) { isHighlighted = isToBeHighlighted; } } - + public void paintBorder(Component c,Graphics g, int x, int y, int width,int height) { Graphics2D g2d = (Graphics2D)g; - Stroke oldStroke = g2d.getStroke(); - g2d.setStroke(new BasicStroke(thickness)); if (isHighlighted) { g2d.setColor(highlightedBorderColor); } else { g2d.setColor(borderColor); } - g2d.drawRect(x, y, width-1, height-1); - g2d.setStroke(oldStroke); - } - - public Insets getBorderInsets (Component c) { - return new Insets(thickness,thickness,thickness,thickness); - } - - public boolean isBorderOpaque() { - return true; - } - } - /** - * An asymmetric line border providing methods for changing the look - * @author Frederick Weld - * - */ - private class DynamicAsymmetricBorder extends AbstractBorder { - private static final long serialVersionUID = 1L; - private int padTop, padLeft, padBottom, padRight; - private Color borderColor; - public DynamicAsymmetricBorder (Color borderColor,int padTop, int padLeft, int padBottom, int padRight) { - this.padTop = padTop; - this.padLeft = padLeft; - this.padBottom = padBottom; - this.padRight = padRight; - this.borderColor = borderColor; - } - public void paintBorder(Component c,Graphics g, int x, int y, int width,int height) { - Graphics2D g2d = (Graphics2D)g; - g2d.setColor(borderColor); Stroke oldStroke = g2d.getStroke(); if (padTop > 0) { g2d.setStroke(new BasicStroke(padTop)); |