Update of /cvsroot/rails/18xx/rails/game In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv3137/rails/game Modified Files: StockMarket.java PhaseManager.java MapHex.java TileManager.java TrainType.java Game.java PlayerManager.java ConfigurableComponentI.java PublicCompany.java TrainManager.java GameManager.java Phase.java CompanyManagerI.java PublicCompanyI.java StockMarketI.java CompanyManager.java CompanyType.java Bank.java GameManagerI.java MapManager.java PrivateCompany.java Log Message: Extended ConfiguableComponentI interface to include final (post XML-parsing) initialisation. Used it to remove several more static methods & calls. Index: Bank.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/Bank.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** Bank.java 3 Oct 2009 14:00:36 -0000 1.13 --- Bank.java 9 Oct 2009 20:20:34 -0000 1.14 *************** *** 96,118 **** DEFAULT_BANK_AMOUNT)); } - ReportBuffer.add(LocalText.getText("BankSizeIs", - format(money.getCash()))); } ! /** ! * @param percentage of a company allowed to be in the Bank pool. ! */ ! public void setPoolShareLimit(int percentage) { ! poolShareLimit = percentage; ! } - /** - * Put all available certificates in the IPO - */ - public void initCertificates() { // Add privates List<PrivateCompanyI> privates = ! Game.getCompanyManager().getAllPrivateCompanies(); for (PrivateCompanyI priv : privates) { ipo.addPrivate(priv); --- 96,110 ---- DEFAULT_BANK_AMOUNT)); } } ! public void finishConfiguration (GameManager gameManager) { ! ! ReportBuffer.add(LocalText.getText("BankSizeIs", ! format(money.getCash()))); // Add privates List<PrivateCompanyI> privates = ! gameManager.getCompanyManager().getAllPrivateCompanies(); for (PrivateCompanyI priv : privates) { ipo.addPrivate(priv); *************** *** 121,125 **** // Add public companies List<PublicCompanyI> companies = ! Game.getCompanyManager().getAllPublicCompanies(); for (PublicCompanyI comp : companies) { for (PublicCertificateI cert : comp.getCertificates()) { --- 113,117 ---- // Add public companies List<PublicCompanyI> companies = ! gameManager.getCompanyManager().getAllPublicCompanies(); for (PublicCompanyI comp : companies) { for (PublicCertificateI cert : comp.getCertificates()) { *************** *** 131,134 **** --- 123,133 ---- } } + } + + /** + * @param percentage of a company allowed to be in the Bank pool. + */ + public void setPoolShareLimit(int percentage) { + poolShareLimit = percentage; } Index: StockMarketI.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/StockMarketI.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** StockMarketI.java 4 May 2009 20:29:14 -0000 1.8 --- StockMarketI.java 9 Oct 2009 20:20:34 -0000 1.9 *************** *** 4,8 **** import java.util.List; ! public interface StockMarketI { /** --- 4,8 ---- import java.util.List; ! public interface StockMarketI extends ConfigurableComponentI { /** *************** *** 12,17 **** static final String COMPONENT_NAME = "StockMarket"; - public void init(); - public StockSpaceI[][] getStockChart(); --- 12,15 ---- Index: CompanyManager.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/CompanyManager.java,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** CompanyManager.java 11 Sep 2009 19:27:23 -0000 1.15 --- CompanyManager.java 9 Oct 2009 20:20:34 -0000 1.16 *************** *** 1 **** ! /* $Header$ */ package rails.game; import java.util.*; import org.apache.log4j.Logger; import rails.util.LocalText; import rails.util.Tag; public class CompanyManager implements CompanyManagerI, ConfigurableComponentI { /** A List with all private companies */ private List<PrivateCompanyI> lPrivateCompanies = new ArrayList<PrivateCompanyI>(); /** A List with all public companies */ private List<PublicCompanyI> lPublicCompanies = new ArrayList<PublicCompanyI>(); /** A map with all private companies by name */ private Map<String, PrivateCompanyI> mPrivateCompanies = new HashMap<String, PrivateCompanyI>(); /** A map with all public (i.e. non-private) companies by name */ private Map<String, PublicCompanyI> mPublicCompanies = new HashMap<String, PublicCompanyI>(); /** 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, HashMap<String, CompanyI>> mCompaniesByTypeAndName = new HashMap<String, HashMap<String, CompanyI>>(); /** 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>(); private int numberOfPublicCompanies = 0; protected static Logger log = Logger.getLogger(CompanyManager.class.getPackage().getName()); /* * NOTES: 1. we don't have a map over all companies, because some games have * duplicate names, e.g. B&O in 1830. 2. we have both a map and a list of * private/public companies to preserve configuration sequence while * allowing direct access. */ /** * No-args constructor. */ public CompanyManager() { // Nothing to do here, everything happens when configured. } /** * @see rails.game.ConfigurableComponentI#configureFromXML(org.w3c.dom.Element) */ public void configureFromXML(Tag tag) throws ConfigurationException { /** A map with all company types, by type name */ // Localised here as it has no permanent use Map<String, CompanyTypeI> mCompanyTypes = new HashMap<String, CompanyTypeI>(); for (Tag compTypeTag : tag.getChildren(CompanyTypeI.ELEMENT_ID)) { // Extract the attributes of the Component String name = compTypeTag.getAttributeAsString(CompanyTypeI.NAME_TAG); if (name == null) { throw new ConfigurationException( LocalText.getText("UnnamedCompanyType")); } String className = compTypeTag.getAttributeAsString(CompanyTypeI.CLASS_TAG); if (className == null) { throw new ConfigurationException(LocalText.getText( "CompanyTypeHasNoClass", name)); } if (mCompanyTypes.get(name) != null) { throw new ConfigurationException(LocalText.getText( "CompanyTypeConfiguredTwice", name)); } CompanyTypeI companyType = new CompanyType(name, className); mCompanyTypes.put(name, companyType); // Further parsing is done within CompanyType companyType.configureFromXML(compTypeTag); } /* Read and configure the companies */ for (Tag companyTag : tag.getChildren(CompanyI.COMPANY_ELEMENT_ID)) { // Extract the attributes of the Component String name = companyTag.getAttributeAsString(CompanyI.COMPANY_NAME_TAG); if (name == null) { throw new ConfigurationException( LocalText.getText("UnnamedCompany")); } String type = companyTag.getAttributeAsString(CompanyI.COMPANY_TYPE_TAG); if (type == null) { throw new ConfigurationException(LocalText.getText( "CompanyHasNoType", name)); } CompanyTypeI cType = mCompanyTypes.get(type); if (cType == null) { throw new ConfigurationException(LocalText.getText( "CompanyHasUnknownType", name, type )); } try { CompanyI company = cType.createCompany(name, companyTag); /* Private or public */ if (company instanceof PrivateCompanyI) { mPrivateCompanies.put(name, (PrivateCompanyI) company); lPrivateCompanies.add((PrivateCompanyI) company); } else if (company instanceof PublicCompanyI) { ((PublicCompanyI)company).setIndex (numberOfPublicCompanies++); mPublicCompanies.put(name, (PublicCompanyI) company); lPublicCompanies.add((PublicCompanyI) company); } /* By type and name */ if (!mCompaniesByTypeAndName.containsKey(type)) mCompaniesByTypeAndName.put(type, new HashMap<String, CompanyI>()); ((Map<String, CompanyI>) mCompaniesByTypeAndName.get(type)).put( name, company); } catch (Exception e) { throw new ConfigurationException(LocalText.getText( "ClassCannotBeInstantiated", cType.getClassName()), e); } } /* Read and configure the start packets */ List<Tag> packetTags = tag.getChildren("StartPacket"); if (packetTags != null) { for (Tag packetTag : tag.getChildren("StartPacket")) { // Extract the attributes of the Component String name = packetTag.getAttributeAsString("name", StartPacket.DEFAULT_NAME); String roundClass = packetTag.getAttributeAsString("roundClass"); if (roundClass == null) { throw new ConfigurationException(LocalText.getText( "StartPacketHasNoClass", name)); } StartPacket sp = new StartPacket(name, roundClass); startPackets.add(sp); startPacketMap.put(name, sp); sp.configureFromXML(packetTag); } } /* Read and configure additional rules */ /* This part may move later to a GameRules or GameManager XML */ Tag rulesTag = tag.getChild("StockRoundRules"); if (rulesTag != null) { for (String ruleTagName : rulesTag.getChildren().keySet()) { if (ruleTagName.equals("NoSaleInFirstSR")) { StockRound.setNoSaleInFirstSR(); } else if (ruleTagName.equals("NoSaleIfNotOperated")) { StockRound.setNoSaleIfNotOperated(); } } } } // Post XML parsing initialisations public void initCompanies(GameManagerI gameManager, List<Player> players ) throws ConfigurationException { for (PublicCompanyI comp : lPublicCompanies) { comp.init2(gameManager); } } /** * @see rails.game.CompanyManagerI#getCompany(java.lang.String) * */ public PrivateCompanyI getPrivateCompany(String name) { return mPrivateCompanies.get(name); } public PublicCompanyI getPublicCompany(String name) { return mPublicCompanies.get(name); } public List<PrivateCompanyI> getAllPrivateCompanies() { return lPrivateCompanies; } public List<PublicCompanyI> getAllPublicCompanies() { return lPublicCompanies; } public PublicCompanyI getCompanyByName(String name) { for (int i = 0; i < lPublicCompanies.size(); i++) { PublicCompany co = (PublicCompany) lPublicCompanies.get(i); if (name.equalsIgnoreCase(co.getName())) { return lPublicCompanies.get(i); } } return null; } public CompanyI getCompany(String type, String name) { if (mCompaniesByTypeAndName.containsKey(type)) { return (mCompaniesByTypeAndName.get(type)).get(name); } else { return null; } } public void closeAllPrivates() { if (lPrivateCompanies == null) return; for (PrivateCompanyI priv : lPrivateCompanies) { priv.setClosed(); } } public List<PrivateCompanyI> getPrivatesOwnedByPlayers() { List<PrivateCompanyI> privatesOwnedByPlayers = new ArrayList<PrivateCompanyI>(); for (PrivateCompanyI priv : getAllPrivateCompanies()) { if (priv.getPortfolio().getOwner() instanceof Player) { privatesOwnedByPlayers.add(priv); } } return privatesOwnedByPlayers; } public StartPacket getStartPacket (int index) { return startPackets.get(index); } public StartPacket getStartPacket (String name) { return startPacketMap.get(name); } } \ No newline at end of file --- 1 ---- ! /* $Header$ */ package rails.game; import java.util.*; import org.apache.log4j.Logger; import rails.util.LocalText; import rails.util.Tag; public class CompanyManager implements CompanyManagerI, ConfigurableComponentI { /** A List with all private companies */ private List<PrivateCompanyI> lPrivateCompanies = new ArrayList<PrivateCompanyI>(); /** A List with all public companies */ private List<PublicCompanyI> lPublicCompanies = new ArrayList<PublicCompanyI>(); /** A map with all private companies by name */ private Map<String, PrivateCompanyI> mPrivateCompanies = new HashMap<String, PrivateCompanyI>(); /** A map with all public (i.e. non-private) companies by name */ private Map<String, PublicCompanyI> mPublicCompanies = new HashMap<String, PublicCompanyI>(); /** 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, HashMap<String, CompanyI>> mCompaniesByTypeAndName = new HashMap<String, HashMap<String, CompanyI>>(); /** 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>(); private int numberOfPublicCompanies = 0; protected static Logger log = Logger.getLogger(CompanyManager.class.getPackage().getName()); /* * NOTES: 1. we don't have a map over all companies, because some games have * duplicate names, e.g. B&O in 1830. 2. we have both a map and a list of * private/public companies to preserve configuration sequence while * allowing direct access. */ /** * No-args constructor. */ public CompanyManager() { // Nothing to do here, everything happens when configured. } /** * @see rails.game.ConfigurableComponentI#configureFromXML(org.w3c.dom.Element) */ public void configureFromXML(Tag tag) throws ConfigurationException { /** A map with all company types, by type name */ // Localised here as it has no permanent use Map<String, CompanyTypeI> mCompanyTypes = new HashMap<String, CompanyTypeI>(); for (Tag compTypeTag : tag.getChildren(CompanyTypeI.ELEMENT_ID)) { // Extract the attributes of the Component String name = compTypeTag.getAttributeAsString(CompanyTypeI.NAME_TAG); if (name == null) { throw new ConfigurationException( LocalText.getText("UnnamedCompanyType")); } String className = compTypeTag.getAttributeAsString(CompanyTypeI.CLASS_TAG); if (className == null) { throw new ConfigurationException(LocalText.getText( "CompanyTypeHasNoClass", name)); } if (mCompanyTypes.get(name) != null) { throw new ConfigurationException(LocalText.getText( "CompanyTypeConfiguredTwice", name)); } CompanyTypeI companyType = new CompanyType(name, className); mCompanyTypes.put(name, companyType); // Further parsing is done within CompanyType companyType.configureFromXML(compTypeTag); } /* Read and configure the companies */ for (Tag companyTag : tag.getChildren(CompanyI.COMPANY_ELEMENT_ID)) { // Extract the attributes of the Component String name = companyTag.getAttributeAsString(CompanyI.COMPANY_NAME_TAG); if (name == null) { throw new ConfigurationException( LocalText.getText("UnnamedCompany")); } String type = companyTag.getAttributeAsString(CompanyI.COMPANY_TYPE_TAG); if (type == null) { throw new ConfigurationException(LocalText.getText( "CompanyHasNoType", name)); } CompanyTypeI cType = mCompanyTypes.get(type); if (cType == null) { throw new ConfigurationException(LocalText.getText( "CompanyHasUnknownType", name, type )); } try { CompanyI company = cType.createCompany(name, companyTag); /* Private or public */ if (company instanceof PrivateCompanyI) { mPrivateCompanies.put(name, (PrivateCompanyI) company); lPrivateCompanies.add((PrivateCompanyI) company); } else if (company instanceof PublicCompanyI) { ((PublicCompanyI)company).setIndex (numberOfPublicCompanies++); mPublicCompanies.put(name, (PublicCompanyI) company); lPublicCompanies.add((PublicCompanyI) company); } /* By type and name */ if (!mCompaniesByTypeAndName.containsKey(type)) mCompaniesByTypeAndName.put(type, new HashMap<String, CompanyI>()); ((Map<String, CompanyI>) mCompaniesByTypeAndName.get(type)).put( name, company); } catch (Exception e) { throw new ConfigurationException(LocalText.getText( "ClassCannotBeInstantiated", cType.getClassName()), e); } } /* Read and configure the start packets */ List<Tag> packetTags = tag.getChildren("StartPacket"); if (packetTags != null) { for (Tag packetTag : tag.getChildren("StartPacket")) { // Extract the attributes of the Component String name = packetTag.getAttributeAsString("name", StartPacket.DEFAULT_NAME); String roundClass = packetTag.getAttributeAsString("roundClass"); if (roundClass == null) { throw new ConfigurationException(LocalText.getText( "StartPacketHasNoClass", name)); } StartPacket sp = new StartPacket(name, roundClass); startPackets.add(sp); startPacketMap.put(name, sp); sp.configureFromXML(packetTag); } } /* Read and configure additional rules */ /* This part may move later to a GameRules or GameManager XML */ Tag rulesTag = tag.getChild("StockRoundRules"); if (rulesTag != null) { for (String ruleTagName : rulesTag.getChildren().keySet()) { if (ruleTagName.equals("NoSaleInFirstSR")) { StockRound.setNoSaleInFirstSR(); } else if (ruleTagName.equals("NoSaleIfNotOperated")) { StockRound.setNoSaleIfNotOperated(); } } } } // Post XML parsing initialisations public void finishConfiguration (GameManager gameManager) throws ConfigurationException { for (PublicCompanyI comp : lPublicCompanies) { comp.finishConfiguration(gameManager); } } /** * @see rails.game.CompanyManagerI#getCompany(java.lang.String) * */ public PrivateCompanyI getPrivateCompany(String name) { return mPrivateCompanies.get(name); } public PublicCompanyI getPublicCompany(String name) { return mPublicCompanies.get(name); } public List<PrivateCompanyI> getAllPrivateCompanies() { return lPrivateCompanies; } public List<PublicCompanyI> getAllPublicCompanies() { return lPublicCompanies; } public PublicCompanyI getCompanyByName(String name) { for (int i = 0; i < lPublicCompanies.size(); i++) { PublicCompany co = (PublicCompany) lPublicCompanies.get(i); if (name.equalsIgnoreCase(co.getName())) { return lPublicCompanies.get(i); } } return null; } public CompanyI getCompany(String type, String name) { if (mCompaniesByTypeAndName.containsKey(type)) { return (mCompaniesByTypeAndName.get(type)).get(name); } else { return null; } } public void closeAllPrivates() { if (lPrivateCompanies == null) return; for (PrivateCompanyI priv : lPrivateCompanies) { priv.setClosed(); } } public List<PrivateCompanyI> getPrivatesOwnedByPlayers() { List<PrivateCompanyI> privatesOwnedByPlayers = new ArrayList<PrivateCompanyI>(); for (PrivateCompanyI priv : getAllPrivateCompanies()) { if (priv.getPortfolio().getOwner() instanceof Player) { privatesOwnedByPlayers.add(priv); } } return privatesOwnedByPlayers; } public StartPacket getStartPacket (int index) { return startPackets.get(index); } public StartPacket getStartPacket (String name) { return startPacketMap.get(name); } } \ No newline at end of file Index: PublicCompany.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/PublicCompany.java,v retrieving revision 1.67 retrieving revision 1.68 diff -C2 -d -r1.67 -r1.68 *** PublicCompany.java 9 Oct 2009 19:03:49 -0000 1.67 --- PublicCompany.java 9 Oct 2009 20:20:34 -0000 1.68 *************** *** 22,25 **** --- 22,26 ---- */ public class PublicCompany extends Company implements PublicCompanyI { + protected static final int DEFAULT_SHARE_UNIT = 10; *************** *** 626,630 **** * Final initialisation, after all XML has been processed. */ ! public void init2(GameManagerI gameManager) throws ConfigurationException { --- 627,631 ---- * Final initialisation, after all XML has been processed. */ ! public void finishConfiguration(GameManager gameManager) throws ConfigurationException { *************** *** 684,687 **** --- 685,695 ---- } } + + if (Util.hasValue(privateToCloseOnFirstTrainName)) { + privateToCloseOnFirstTrain = + gameManager.getCompanyManager().getPrivateCompany( + privateToCloseOnFirstTrainName); + } + } *************** *** 805,816 **** stockMarket.start(this, startSpace); ! /* Final initialisations */ ! if (Util.hasValue(privateToCloseOnFirstTrainName)) { ! privateToCloseOnFirstTrain = ! Game.getCompanyManager().getPrivateCompany( ! privateToCloseOnFirstTrainName); ! } ! ! if (homeBaseTokensLayTime == WHEN_STARTED) { layHomeBaseTokens(); } --- 813,817 ---- stockMarket.start(this, startSpace); ! if (homeBaseTokensLayTime == WHEN_STARTED) { layHomeBaseTokens(); } *************** *** 867,871 **** if (sharePriceUpOnFloating) { ! Game.getStockMarket().moveUp(this); } --- 868,872 ---- if (sharePriceUpOnFloating) { ! stockMarket.moveUp(this); } *************** *** 1236,1241 **** // Move the token if (hasStockPrice ! && (!payoutMustExceedPriceToMove || amount >= currentPrice.getPrice().getPrice())) { ! Game.getStockMarket().payOut(this); } --- 1237,1243 ---- // Move the token if (hasStockPrice ! && (!payoutMustExceedPriceToMove ! || amount >= currentPrice.getPrice().getPrice())) { ! stockMarket.payOut(this); } *************** *** 1263,1267 **** if (amount > 0) new CashMove(bank, this, amount); // Move the token ! if (hasStockPrice) Game.getStockMarket().withhold(this); } --- 1265,1269 ---- if (amount > 0) new CashMove(bank, this, amount); // Move the token ! if (hasStockPrice) stockMarket.withhold(this); } Index: TileManager.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/TileManager.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** TileManager.java 9 Oct 2009 19:03:49 -0000 1.9 --- TileManager.java 9 Oct 2009 20:20:34 -0000 1.10 *************** *** 1 **** ! /* $Header$ */ package rails.game; import java.util.*; import rails.util.LocalText; import rails.util.Tag; public class TileManager implements ConfigurableComponentI { protected static TileManager instance = null; protected Map<Integer, TileI> tileMap = new HashMap<Integer, TileI>(); protected List<Integer> tileIds = new ArrayList<Integer>(); private static List<String> directories = new ArrayList<String>(); /** * No-args constructor. */ public TileManager() { instance = this; } public static TileManager get() { return instance; } /** * @see rails.game.ConfigurableComponentI#configureFromXML(org.w3c.dom.Element) */ public void configureFromXML(Tag tileSetTop) throws ConfigurationException { /* * Note: prefix se is used for elements from TileSet.xml, prefix te for * elements from Tiles.xml. */ String tileDefFileName = tileSetTop.getAttributeAsString("tiles"); if (tileDefFileName == null) throw new ConfigurationException(LocalText.getText("NoTilesXML")); directories.add("data/" + ComponentManager.getGameName()); Tag tileDefTop = Tag.findTopTagInFile(tileDefFileName, directories, "Tiles"); if (tileDefTop == null) throw new ConfigurationException(LocalText.getText("NoTilesTag")); List<Tag> tileSetList = tileSetTop.getChildren("Tile"); List<Tag> tileDefList = tileDefTop.getChildren("Tile"); /* * The XML files TileSet.xml and Tiles.xml are read side by side, as * each one configures different tile aspects. The reason for having two * XML files is, that Tiles.xml defines per-tile aspects that are the * same for all games (such as the colour, tracks and stations; this * file is an automatically generated subset of the generic file * tiles/Tiles.xml), whereas TileSet.xml specifies the aspects that are * (or can be) specific to each rails.game (such as the possible * upgrades). <p>TileSet.xml is leading. */ int tileId; TileI tile; // Creates maps to the tile definitions in both files. Map<Integer, Tag> tileSetMap = new HashMap<Integer, Tag>(); Map<Integer, Tag> tileDefMap = new HashMap<Integer, Tag>(); for (Tag tileSetTag : tileSetList) { tileId = tileSetTag.getAttributeAsInteger("id"); /* * Check for duplicates (this also covers missing tile ids, as this * returns 0, and we always have a tile numbered 0! */ if (tileSetMap.containsKey(tileId)) { throw new ConfigurationException(LocalText.getText( "DuplicateTilesetID", String.valueOf(tileId))); } tileSetMap.put(tileId, tileSetTag); tileIds.add(tileId); } for (Tag tileDefTag : tileDefList) { tileId = tileDefTag.getAttributeAsInteger("id"); /* * Check for duplicates (this also covers missing tile ids, as this * returns 0, and we always have a tile numbered 0! */ if (tileDefMap.containsKey(tileId)) { throw new ConfigurationException(LocalText.getText( "DuplicateTileID", String.valueOf(tileId))); } else if (!tileSetMap.containsKey(tileId)) { throw new ConfigurationException(LocalText.getText( "TileMissingInTileSet", String.valueOf(tileId))); } tileDefMap.put(tileId, tileDefTag); } // Create the Tile objects (must be done before further parsing) for (Integer id : tileSetMap.keySet()) { tile = new Tile(id); tileMap.put(id, tile); } // Finally, parse the <Tile> subtags for (Integer id : tileMap.keySet()) { tile = tileMap.get(id); tile.configureFromXML(tileSetMap.get(id), tileDefMap.get(id)); } } public TileI getTile(int id) { return tileMap.get(id); } /** Get the tile IDs in the XML definition sequence */ public List<Integer> getTileIds() { return tileIds; } } \ No newline at end of file --- 1 ---- ! /* $Header$ */ package rails.game; import java.util.*; import rails.util.LocalText; import rails.util.Tag; public class TileManager implements ConfigurableComponentI { protected static TileManager instance = null; protected Map<Integer, TileI> tileMap = new HashMap<Integer, TileI>(); protected List<Integer> tileIds = new ArrayList<Integer>(); private static List<String> directories = new ArrayList<String>(); /** * No-args constructor. */ public TileManager() { instance = this; } public static TileManager get() { return instance; } /** * @see rails.game.ConfigurableComponentI#configureFromXML(org.w3c.dom.Element) */ public void configureFromXML(Tag tileSetTop) throws ConfigurationException { /* * Note: prefix se is used for elements from TileSet.xml, prefix te for * elements from Tiles.xml. */ String tileDefFileName = tileSetTop.getAttributeAsString("tiles"); if (tileDefFileName == null) throw new ConfigurationException(LocalText.getText("NoTilesXML")); directories.add("data/" + ComponentManager.getGameName()); Tag tileDefTop = Tag.findTopTagInFile(tileDefFileName, directories, "Tiles"); if (tileDefTop == null) throw new ConfigurationException(LocalText.getText("NoTilesTag")); List<Tag> tileSetList = tileSetTop.getChildren("Tile"); List<Tag> tileDefList = tileDefTop.getChildren("Tile"); /* * The XML files TileSet.xml and Tiles.xml are read side by side, as * each one configures different tile aspects. The reason for having two * XML files is, that Tiles.xml defines per-tile aspects that are the * same for all games (such as the colour, tracks and stations; this * file is an automatically generated subset of the generic file * tiles/Tiles.xml), whereas TileSet.xml specifies the aspects that are * (or can be) specific to each rails.game (such as the possible * upgrades). <p>TileSet.xml is leading. */ int tileId; TileI tile; // Creates maps to the tile definitions in both files. Map<Integer, Tag> tileSetMap = new HashMap<Integer, Tag>(); Map<Integer, Tag> tileDefMap = new HashMap<Integer, Tag>(); for (Tag tileSetTag : tileSetList) { tileId = tileSetTag.getAttributeAsInteger("id"); /* * Check for duplicates (this also covers missing tile ids, as this * returns 0, and we always have a tile numbered 0! */ if (tileSetMap.containsKey(tileId)) { throw new ConfigurationException(LocalText.getText( "DuplicateTilesetID", String.valueOf(tileId))); } tileSetMap.put(tileId, tileSetTag); tileIds.add(tileId); } for (Tag tileDefTag : tileDefList) { tileId = tileDefTag.getAttributeAsInteger("id"); /* * Check for duplicates (this also covers missing tile ids, as this * returns 0, and we always have a tile numbered 0! */ if (tileDefMap.containsKey(tileId)) { throw new ConfigurationException(LocalText.getText( "DuplicateTileID", String.valueOf(tileId))); } else if (!tileSetMap.containsKey(tileId)) { throw new ConfigurationException(LocalText.getText( "TileMissingInTileSet", String.valueOf(tileId))); } tileDefMap.put(tileId, tileDefTag); } // Create the Tile objects (must be done before further parsing) for (Integer id : tileSetMap.keySet()) { tile = new Tile(id); tileMap.put(id, tile); } // Finally, parse the <Tile> subtags for (Integer id : tileMap.keySet()) { tile = tileMap.get(id); tile.configureFromXML(tileSetMap.get(id), tileDefMap.get(id)); } } public void finishConfiguration (GameManager gameManager) {} public TileI getTile(int id) { return tileMap.get(id); } /** Get the tile IDs in the XML definition sequence */ public List<Integer> getTileIds() { return tileIds; } } \ No newline at end of file Index: TrainManager.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/TrainManager.java,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** TrainManager.java 9 Oct 2009 19:03:49 -0000 1.19 --- TrainManager.java 9 Oct 2009 20:20:34 -0000 1.20 *************** *** 1 **** ! /* $Header$ */ package rails.game; import java.util.*; import rails.game.state.IntegerState; import rails.util.LocalText; import rails.util.Tag; public class TrainManager implements ConfigurableComponentI { // Static attributes protected List<TrainTypeI> lTrainTypes = new ArrayList<TrainTypeI>(); protected Map<String, TrainTypeI> mTrainTypes = new HashMap<String, TrainTypeI>(); protected boolean buyAtFaceValueBetweenDifferentPresidents = false; // Dynamic attributes protected Portfolio unavailable = null; protected IntegerState newTypeIndex; protected boolean trainsHaveRusted = false; protected boolean phaseHasChanged = false; protected boolean trainAvailabilityChanged = false; protected List<PublicCompanyI> companiesWithExcessTrains; protected GameManagerI gameManager = null; protected Bank bank = null; // Non-game attributes private static TrainManager instance = null; protected Portfolio ipo = null; /** * No-args constructor. */ public TrainManager() { instance = this; // Nothing to do here, everything happens when configured. newTypeIndex = new IntegerState("NewTrainTypeIndex", 0); } /** * @see rails.game.ConfigurableComponentI#configureFromXML(org.w3c.dom.Element) */ public void configureFromXML(Tag tag) throws ConfigurationException { TrainType defaultType = null; TrainType newType; Tag defaultsTag = tag.getChild("Defaults"); if (defaultsTag != null) { defaultType = new TrainType(false); defaultType.configureFromXML(defaultsTag); } List<Tag> typeTags = tag.getChildren("Train"); for (Tag typeTag : typeTags) { if (defaultType != null) { newType = (TrainType) defaultType.clone(); if (newType == null) { throw new ConfigurationException("Cannot clone traintype " + defaultType.getName()); } } else { newType = new TrainType(true); } lTrainTypes.add(newType); newType.configureFromXML(typeTag); mTrainTypes.put(newType.getName(), newType); } // Special train buying rules Tag rulesTag = tag.getChild("TrainBuyingRules"); if (rulesTag != null) { // A 1851 special buyAtFaceValueBetweenDifferentPresidents = rulesTag.getChild("FaceValueIfDifferentPresidents") != null; } // Finish initialisation of the train types for (TrainTypeI type : lTrainTypes) { if (type.getReleasedTrainTypeName() != null) { type.setReleasedTrainType(mTrainTypes.get(type.getReleasedTrainTypeName())); } if (type.getRustedTrainTypeName() != null) { type.setRustedTrainType(mTrainTypes.get(type.getRustedTrainTypeName())); mTrainTypes.get(type.getRustedTrainTypeName()).setPermanent(false); } } } public void init (GameManagerI gameManager) { this.gameManager = gameManager; bank = gameManager.getBank(); ipo = bank.getIpo(); unavailable = bank.getUnavailable(); // By default, set the first train type to "available". newTypeIndex.set(0); lTrainTypes.get(newTypeIndex.intValue()).setAvailable(bank); } /** * Make an abbreviated list of trains, like "2(6) 3(5)" etc, to show in the * IPO. * * @param holder The Portfolio for which this list will be made (always * IPO). */ public static String makeAbbreviatedList(Portfolio holder) { StringBuffer b = new StringBuffer(); TrainI[] trains; for (TrainTypeI type : instance.getTrainTypes()) { trains = holder.getTrainsPerType(type); if (trains.length > 0) { if (b.length() > 0) b.append(" "); b.append(type.getName()).append("("); if (type.hasInfiniteAmount()) { b.append("+"); } else { b.append(trains.length); } b.append(")"); } } return b.toString(); } /** * Make a full list of trains, like "2 2 3 3", to show in any field * describing train possessions, except the IPO. * * @param holder The Portfolio for which this list will be made. */ public static String makeFullList(Portfolio holder) { List<TrainI> trains = holder.getTrainList(); if (trains == null || trains.size() == 0) return ""; return makeFullList(trains); } public static String makeFullList(List<TrainI> trains) { StringBuffer b = new StringBuffer(); for (TrainI train : trains) { if (b.length() > 0) b.append(" "); if (train.isObsolete()) b.append("("); b.append(train.toDisplay()); if (train.isObsolete()) b.append(")"); } return b.toString(); } /** * This method handles any consequences of new train buying (from the IPO), * such as rusting and phase changes. It must be called <b>after</b> the * train has been transferred. * */ public void checkTrainAvailability(TrainI train, Portfolio from) { trainsHaveRusted = false; phaseHasChanged = false; if (from != ipo) return; TrainTypeI boughtType, nextType; boughtType = train.getType(); if (boughtType == (lTrainTypes.get(newTypeIndex.intValue())) && ipo.getTrainOfType(boughtType) == null) { // Last train bought, make a new type available. newTypeIndex.add(1); nextType = (lTrainTypes.get(newTypeIndex.intValue())); if (nextType != null) { if (!nextType.isAvailable()) nextType.setAvailable(bank); trainAvailabilityChanged = true; ReportBuffer.add("All " + boughtType.getName() + "-trains are sold out, " + nextType.getName() + "-trains now available"); } } if (boughtType.getNumberBoughtFromIPO() == 1) { // First train of a new type bought ReportBuffer.add(LocalText.getText("FirstTrainBought", boughtType.getName())); String newPhase = boughtType.getStartedPhaseName(); if (newPhase != null) { gameManager.getPhaseManager().setPhase(newPhase); phaseHasChanged = true; } TrainTypeI rustedType = boughtType.getRustedTrainType(); if (rustedType != null && !rustedType.hasRusted()) { rustedType.setRusted(train.getHolder()); // Or obsolete, // where applicable ReportBuffer.add(LocalText.getText("TrainsRusted", rustedType.getName())); trainsHaveRusted = true; trainAvailabilityChanged = true; } TrainTypeI releasedType = boughtType.getReleasedTrainType(); if (releasedType != null) { if (!releasedType.isAvailable()) releasedType.setAvailable(bank); ReportBuffer.add(LocalText.getText("TrainsAvailable", releasedType.getName())); trainAvailabilityChanged = true; } } } public List<TrainI> getAvailableNewTrains() { List<TrainI> availableTrains = new ArrayList<TrainI>(); TrainI train; for (TrainTypeI type : lTrainTypes) { if (type.isAvailable()) { train = ipo.getTrainOfType(type); if (train != null) { availableTrains.add(train); } } } return availableTrains; } public TrainTypeI getTypeByName(String name) { return mTrainTypes.get(name); } public List<TrainTypeI> getTrainTypes() { return lTrainTypes; } public boolean hasAvailabilityChanged() { return trainAvailabilityChanged; } public void resetAvailabilityChanged() { trainAvailabilityChanged = false; } public boolean hasPhaseChanged() { return phaseHasChanged; } public boolean buyAtFaceValueBetweenDifferentPresidents() { return buyAtFaceValueBetweenDifferentPresidents; } } \ No newline at end of file --- 1 ---- ! /* $Header$ */ package rails.game; import java.util.*; import rails.game.state.IntegerState; import rails.util.LocalText; import rails.util.Tag; public class TrainManager implements ConfigurableComponentI { // Static attributes protected List<TrainTypeI> lTrainTypes = new ArrayList<TrainTypeI>(); protected Map<String, TrainTypeI> mTrainTypes = new HashMap<String, TrainTypeI>(); protected boolean buyAtFaceValueBetweenDifferentPresidents = false; // Dynamic attributes protected Portfolio unavailable = null; protected IntegerState newTypeIndex; protected boolean trainsHaveRusted = false; protected boolean phaseHasChanged = false; protected boolean trainAvailabilityChanged = false; protected List<PublicCompanyI> companiesWithExcessTrains; protected GameManagerI gameManager = null; protected Bank bank = null; // Non-game attributes private static TrainManager instance = null; protected Portfolio ipo = null; /** * No-args constructor. */ public TrainManager() { instance = this; // Nothing to do here, everything happens when configured. newTypeIndex = new IntegerState("NewTrainTypeIndex", 0); } /** * @see rails.game.ConfigurableComponentI#configureFromXML(org.w3c.dom.Element) */ public void configureFromXML(Tag tag) throws ConfigurationException { TrainType defaultType = null; TrainType newType; Tag defaultsTag = tag.getChild("Defaults"); if (defaultsTag != null) { defaultType = new TrainType(false); defaultType.configureFromXML(defaultsTag); } List<Tag> typeTags = tag.getChildren("Train"); for (Tag typeTag : typeTags) { if (defaultType != null) { newType = (TrainType) defaultType.clone(); if (newType == null) { throw new ConfigurationException("Cannot clone traintype " + defaultType.getName()); } } else { newType = new TrainType(true); } lTrainTypes.add(newType); newType.configureFromXML(typeTag); mTrainTypes.put(newType.getName(), newType); } // Special train buying rules Tag rulesTag = tag.getChild("TrainBuyingRules"); if (rulesTag != null) { // A 1851 special buyAtFaceValueBetweenDifferentPresidents = rulesTag.getChild("FaceValueIfDifferentPresidents") != null; } // Finish initialisation of the train types for (TrainTypeI type : lTrainTypes) { if (type.getReleasedTrainTypeName() != null) { type.setReleasedTrainType(mTrainTypes.get(type.getReleasedTrainTypeName())); } if (type.getRustedTrainTypeName() != null) { type.setRustedTrainType(mTrainTypes.get(type.getRustedTrainTypeName())); mTrainTypes.get(type.getRustedTrainTypeName()).setPermanent(false); } } } public void finishConfiguration (GameManager gameManager) { this.gameManager = gameManager; bank = gameManager.getBank(); ipo = bank.getIpo(); unavailable = bank.getUnavailable(); // By default, set the first train type to "available". newTypeIndex.set(0); lTrainTypes.get(newTypeIndex.intValue()).setAvailable(bank); } /** * Make an abbreviated list of trains, like "2(6) 3(5)" etc, to show in the * IPO. * * @param holder The Portfolio for which this list will be made (always * IPO). */ public static String makeAbbreviatedList(Portfolio holder) { StringBuffer b = new StringBuffer(); TrainI[] trains; for (TrainTypeI type : instance.getTrainTypes()) { trains = holder.getTrainsPerType(type); if (trains.length > 0) { if (b.length() > 0) b.append(" "); b.append(type.getName()).append("("); if (type.hasInfiniteAmount()) { b.append("+"); } else { b.append(trains.length); } b.append(")"); } } return b.toString(); } /** * Make a full list of trains, like "2 2 3 3", to show in any field * describing train possessions, except the IPO. * * @param holder The Portfolio for which this list will be made. */ public static String makeFullList(Portfolio holder) { List<TrainI> trains = holder.getTrainList(); if (trains == null || trains.size() == 0) return ""; return makeFullList(trains); } public static String makeFullList(List<TrainI> trains) { StringBuffer b = new StringBuffer(); for (TrainI train : trains) { if (b.length() > 0) b.append(" "); if (train.isObsolete()) b.append("("); b.append(train.toDisplay()); if (train.isObsolete()) b.append(")"); } return b.toString(); } /** * This method handles any consequences of new train buying (from the IPO), * such as rusting and phase changes. It must be called <b>after</b> the * train has been transferred. * */ public void checkTrainAvailability(TrainI train, Portfolio from) { trainsHaveRusted = false; phaseHasChanged = false; if (from != ipo) return; TrainTypeI boughtType, nextType; boughtType = train.getType(); if (boughtType == (lTrainTypes.get(newTypeIndex.intValue())) && ipo.getTrainOfType(boughtType) == null) { // Last train bought, make a new type available. newTypeIndex.add(1); nextType = (lTrainTypes.get(newTypeIndex.intValue())); if (nextType != null) { if (!nextType.isAvailable()) nextType.setAvailable(bank); trainAvailabilityChanged = true; ReportBuffer.add("All " + boughtType.getName() + "-trains are sold out, " + nextType.getName() + "-trains now available"); } } if (boughtType.getNumberBoughtFromIPO() == 1) { // First train of a new type bought ReportBuffer.add(LocalText.getText("FirstTrainBought", boughtType.getName())); String newPhase = boughtType.getStartedPhaseName(); if (newPhase != null) { gameManager.getPhaseManager().setPhase(newPhase); phaseHasChanged = true; } TrainTypeI rustedType = boughtType.getRustedTrainType(); if (rustedType != null && !rustedType.hasRusted()) { rustedType.setRusted(train.getHolder()); // Or obsolete, // where applicable ReportBuffer.add(LocalText.getText("TrainsRusted", rustedType.getName())); trainsHaveRusted = true; trainAvailabilityChanged = true; } TrainTypeI releasedType = boughtType.getReleasedTrainType(); if (releasedType != null) { if (!releasedType.isAvailable()) releasedType.setAvailable(bank); ReportBuffer.add(LocalText.getText("TrainsAvailable", releasedType.getName())); trainAvailabilityChanged = true; } } } public List<TrainI> getAvailableNewTrains() { List<TrainI> availableTrains = new ArrayList<TrainI>(); TrainI train; for (TrainTypeI type : lTrainTypes) { if (type.isAvailable()) { train = ipo.getTrainOfType(type); if (train != null) { availableTrains.add(train); } } } return availableTrains; } public TrainTypeI getTypeByName(String name) { return mTrainTypes.get(name); } public List<TrainTypeI> getTrainTypes() { return lTrainTypes; } public boolean hasAvailabilityChanged() { return trainAvailabilityChanged; } public void resetAvailabilityChanged() { trainAvailabilityChanged = false; } public boolean hasPhaseChanged() { return phaseHasChanged; } public boolean buyAtFaceValueBetweenDifferentPresidents() { return buyAtFaceValueBetweenDifferentPresidents; } } \ No newline at end of file Index: PrivateCompany.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/PrivateCompany.java,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** PrivateCompany.java 25 Sep 2009 19:13:01 -0000 1.22 --- PrivateCompany.java 9 Oct 2009 20:20:34 -0000 1.23 *************** *** 111,114 **** --- 111,116 ---- } + public void finishConfiguration (GameManager gameManager) {} + /** Initialisation, to be called directly after instantiation (cloning) */ @Override Index: PlayerManager.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/PlayerManager.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** PlayerManager.java 25 Sep 2009 19:13:01 -0000 1.10 --- PlayerManager.java 9 Oct 2009 20:20:34 -0000 1.11 *************** *** 45,49 **** } ! public void setPlayers (List<String> playerNames, Bank bank) { Player player; --- 45,51 ---- } ! public void finishConfiguration (GameManager gameManager) {} ! ! public void setPlayers (List<String> playerNames, Bank bank) { Player player; Index: CompanyType.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/CompanyType.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** CompanyType.java 24 Jan 2009 15:10:28 -0000 1.8 --- CompanyType.java 9 Oct 2009 20:20:34 -0000 1.9 *************** *** 61,65 **** } ! public CompanyI createCompany(String name, Tag tag) throws ConfigurationException { CompanyI newCompany = null; --- 61,69 ---- } ! public void finishConfiguration (GameManager gameManager) { ! ! } ! ! public CompanyI createCompany(String name, Tag tag) throws ConfigurationException { CompanyI newCompany = null; Index: ConfigurableComponentI.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/ConfigurableComponentI.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** ConfigurableComponentI.java 4 Jun 2008 19:00:31 -0000 1.4 --- ConfigurableComponentI.java 9 Oct 2009 20:20:34 -0000 1.5 *************** *** 14,21 **** * element. * ! * @param el the XML element containing the configuration * @throws ConfigurationException */ void configureFromXML(Tag tag) throws ConfigurationException; } --- 14,37 ---- * element. * ! * @param element the XML element containing the configuration * @throws ConfigurationException */ void configureFromXML(Tag tag) throws ConfigurationException; + + /** + * This method is intended to be called for each configurable + * component, to perforn any initialisation activities that + * require any other components to be initialised first. + * This includes creating any required relationships to other + * configured components and objects. + * <p>This method should be called where necessary after all + * XML file parsing has completed, so that all objects that + * need to be related to do exist. + * @param parent The 'parent' configurable component is passed to allow + * the 'child' to access any other object without the need to resort to + * static calls where possible. + */ + void finishConfiguration (GameManager parent) + throws ConfigurationException; } Index: GameManager.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/GameManager.java,v retrieving revision 1.60 retrieving revision 1.61 diff -C2 -d -r1.60 -r1.61 *** GameManager.java 9 Oct 2009 19:03:49 -0000 1.60 --- GameManager.java 9 Oct 2009 20:20:34 -0000 1.61 *************** *** 354,357 **** --- 354,359 ---- } + public void finishConfiguration (GameManager gameManager) {} + /** Check if a classname can be instantiated. * Throws a ConfiguratioNException if not. Index: MapManager.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/MapManager.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** MapManager.java 3 Oct 2009 14:02:28 -0000 1.8 --- MapManager.java 9 Oct 2009 20:20:34 -0000 1.9 *************** *** 128,131 **** --- 128,144 ---- } + public void finishConfiguration (GameManager gameManager) { + MapHex hex; + + for (PublicCompanyI company : gameManager.getCompanyManager().getAllPublicCompanies()) { + if ((hex = company.getHomeHex()) != null) { + hex.addHome(company, company.getHomeCityNumber()); + } + if ((hex = company.getDestinationHex()) != null) { + hex.addDestination(company); + } + } + } + /** * @return an instance of the MapManager *************** *** 174,196 **** } - /** - * Necessary mechanism for delaying assignment of companyDestination until - * after all of the proper elements of the XML have been loaded. - * - * Called by Game.initialise() - */ - protected static void assignHomesAndDestinations() { - MapHex hex; - - for (PublicCompanyI company : Game.getCompanyManager().getAllPublicCompanies()) { - if ((hex = company.getHomeHex()) != null) { - hex.addHome(company, company.getHomeCityNumber()); - } - if ((hex = company.getDestinationHex()) != null) { - hex.addDestination(company); - } - } - } - public List<City> getCurrentStations() { List<City> stations = new ArrayList<City>(); --- 187,190 ---- Index: Game.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/Game.java,v retrieving revision 1.30 retrieving revision 1.31 diff -C2 -d -r1.30 -r1.31 *** Game.java 9 Oct 2009 19:03:49 -0000 1.30 --- Game.java 9 Oct 2009 20:20:34 -0000 1.31 *************** *** 21,25 **** /** The component Manager */ protected ComponentManager componentManager; ! protected GameManagerI gameManager; protected CompanyManagerI companyManager; protected PlayerManager playerManager; --- 21,25 ---- /** The component Manager */ protected ComponentManager componentManager; ! protected GameManager gameManager; protected CompanyManagerI companyManager; protected PlayerManager playerManager; *************** *** 124,128 **** } gameManager = ! (GameManagerI) componentManager.findComponent("GameManager"); if (gameManager == null) { throw new ConfigurationException( --- 124,128 ---- } gameManager = ! (GameManager) componentManager.findComponent("GameManager"); if (gameManager == null) { throw new ConfigurationException( *************** *** 163,173 **** phaseManager, trainManager, stockMarket, mapManager, bank); ! companyManager.initCompanies(gameManager, playerManager.getPlayers()); ! trainManager.init(gameManager); ! phaseManager.init(gameManager); ! bank.initCertificates(); //StartPacket.init(); //companyManager.initCompanies(gameManager); ! stockMarket.init(); } catch (Exception e) { String message = --- 163,174 ---- p... [truncated message content] |