From: <ev...@us...> - 2011-06-30 15:19:19
|
Revision: 1595 http://rails.svn.sourceforge.net/rails/?rev=1595&view=rev Author: evos Date: 2011-06-30 15:19:12 +0000 (Thu, 30 Jun 2011) Log Message: ----------- Implemented 1830 Coalfields right buying option. It is implemented using a new generic "rights" object. Each company can have a separate set of rights. To make this work, public company initialization had to be refactored. 'Dummy' companies per type are no longer needed. New 'Rights' columns have been added to the OR and GameStatus windows if needed. 'Coalfields' is shown for each company that has that right. Caveat: Undoing a Coalfields right by action does not reset the UI. This cannot be implemented in the usual way as long HashMapState does not extend ModelObject. Modified Paths: -------------- trunk/18xx/LocalisedText.properties trunk/18xx/data/1830/CompanyManager.xml trunk/18xx/rails/common/GuiDef.java trunk/18xx/rails/game/CompanyManager.java trunk/18xx/rails/game/CompanyType.java trunk/18xx/rails/game/CompanyTypeI.java trunk/18xx/rails/game/Game.java trunk/18xx/rails/game/GameManager.java trunk/18xx/rails/game/GameManagerI.java trunk/18xx/rails/game/OperatingRound.java trunk/18xx/rails/game/PublicCompany.java trunk/18xx/rails/game/PublicCompanyI.java trunk/18xx/rails/game/special/SpecialProperty.java trunk/18xx/rails/game/special/SpecialPropertyI.java trunk/18xx/rails/game/state/HashMapState.java trunk/18xx/rails/ui/swing/GameStatus.java trunk/18xx/rails/ui/swing/ORPanel.java trunk/18xx/rails/util/ListAndFixSavedFiles.java Added Paths: ----------- trunk/18xx/rails/game/model/RightsModel.java trunk/18xx/rails/game/special/SpecialRight.java Modified: trunk/18xx/LocalisedText.properties =================================================================== --- trunk/18xx/LocalisedText.properties 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/LocalisedText.properties 2011-06-30 15:19:12 UTC (rev 1595) @@ -40,6 +40,7 @@ BUY_WHICH_TRAIN=Buy which train? # Note: in the next item, {0} MUST be in front BuyPrivatePrompt={0} from {1} for {2} +BuyRight=Buy {0} right for {1} BankIsBrokenDisplayText=Bank is broken. Play continues until {0} BankIsBrokenReportText=Bank is broken gameOverPlaySetOfORs=the current set of operating rounds is finished. @@ -56,6 +57,7 @@ BuysBonusTokenFrom={0} buys a {1} +{2} bonus token from {3} for {4} BuysItemFor={0} buys {1} for {2} BuysPrivateFromFor={0} buys private {1} from {2} for {3} +BuysRight={0} buys the ''{1}'' right for {2} BuysTrain={0} buys a {1}-train from {2} for {3}. BuysTrainUsingSP={0} buys a {1}-train from {2} for {3} using {4}. BYFloatsAt=Bayern floats at @@ -64,6 +66,7 @@ CanOperate={0} can operate this round CannotOperate={0} cannot operate this round CannotBuyAnything={0} cannot buy anything +CannotBuyRight={1} cannot buy '{1}' right for {2}: {3} CERT_NAME={0} {1}% share CLOSE=Close CloseMinor=Close minor {0} @@ -526,6 +529,7 @@ RevenueStationsIgnoreMinors=, Cities = {0} ReceivesFor={0} receives {1} for {2}. RevenueWithNoTrains={0} owns no trains, so revenue is {1}. +RIGHTS=Rights RotateTile=Click tile to rotate it, or select another tile or hex, or press Lay Tile to confirm tile, or press the No Tile button. RouteAwareness=support for tile and token lays RunsWithBorrowedTrain={0} runs with a borrowed {1}-train and must withhold revenue Modified: trunk/18xx/data/1830/CompanyManager.xml =================================================================== --- trunk/18xx/data/1830/CompanyManager.xml 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/data/1830/CompanyManager.xml 2011-06-30 15:19:12 UTC (rev 1595) @@ -22,6 +22,14 @@ <Certificate shares="1" number="8"/> <Trains limit="4,4,3,2"/> <CanUseSpecialProperties/> + <IfOption name="Variant" value="Coalfields,Coalfields&Reading"> + <CanUseSpecialProperties/> + <SpecialProperties> + <SpecialProperty condition="ifOwnedByCompany" when="orTurn" class="rails.game.special.SpecialRight"> + <SpecialRight name="Coalfields" cost="140"/> + </SpecialProperty> + </SpecialProperties> + </IfOption> </CompanyType> <Company name="SVNRR" type="Private" basePrice="20" revenue="5" longname="Schuylkill Valley Navigation & Railroad Company"> Modified: trunk/18xx/rails/common/GuiDef.java =================================================================== --- trunk/18xx/rails/common/GuiDef.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/common/GuiDef.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -37,6 +37,7 @@ CAN_ANY_COMPANY_BUY_PRIVATES, DO_BONUS_TOKENS_EXIST, HAS_ANY_COMPANY_LOANS, + HAS_ANY_RIGHTS, NO_MAP_MODE, REVENUE_SUGGEST, ROUTE_HIGHLIGHT Modified: trunk/18xx/rails/game/CompanyManager.java =================================================================== --- trunk/18xx/rails/game/CompanyManager.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/CompanyManager.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -74,6 +74,9 @@ // Localised here as it has no permanent use Map<String, CompanyTypeI> mCompanyTypes = new HashMap<String, CompanyTypeI>(); + + //NEW// + Map<String, Tag> typeTags = new HashMap<String, Tag>(); for (Tag compTypeTag : tag.getChildren(CompanyTypeI.ELEMENT_ID)) { // Extract the attributes of the Component @@ -101,6 +104,8 @@ // Further parsing is done within CompanyType companyType.configureFromXML(compTypeTag); + //NEW// + typeTags.put(name, compTypeTag); } /* Read and configure the companies */ @@ -125,7 +130,9 @@ } try { - CompanyI company = cType.createCompany(name, companyTag); + //NEW//CompanyI company = cType.createCompany(name, companyTag); + Tag typeTag = typeTags.get(type); + CompanyI company = cType.createCompany(name, typeTag, companyTag); /* Private or public */ if (company instanceof PrivateCompanyI) { Modified: trunk/18xx/rails/game/CompanyType.java =================================================================== --- trunk/18xx/rails/game/CompanyType.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/CompanyType.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -24,8 +24,6 @@ protected String className; protected int capitalisation = PublicCompanyI.CAPITALISE_FULL; - private CompanyI dummyCompany; - protected List<CompanyI> companies = new ArrayList<CompanyI>(); /** @@ -46,44 +44,26 @@ * @see rails.game.ConfigurableComponentI#configureFromXML(org.w3c.dom.Element) */ public void configureFromXML(Tag tag) throws ConfigurationException { - - /* Create a dummy company implementing this company type */ - try { - dummyCompany = (Company) Class.forName(className).newInstance(); - } catch (Exception e) { - throw new ConfigurationException(LocalText.getText( - "ClassCannotBeInstantiated", className), e); - } - dummyCompany.init("", this); - dummyCompany.configureFromXML(tag); - - /* - * Must be rewritten to a new tag String capitalMode = - * XmlUtils.extractStringAttribute(nnp, "capitalisation", "full"); - * setCapitalisation(capitalMode); - */ - + //No longer needed. } public void finishConfiguration (GameManagerI gameManager) { } - public CompanyI createCompany(String name, Tag tag) - throws ConfigurationException { + public CompanyI createCompany(String name, Tag typeTag, Tag tag) + throws ConfigurationException { CompanyI newCompany = null; try { - newCompany = (CompanyI) dummyCompany.clone(); - if (newCompany == null) { - throw new ConfigurationException("Cannot clone company " + name); - } - newCompany.init(name, this); - newCompany.configureFromXML(tag); - companies.add(newCompany); - } catch (CloneNotSupportedException e) { - DisplayBuffer.add(LocalText.getText("CantCloneCompany", - name, this.name )); + newCompany = (Company) Class.forName(className).newInstance(); + } catch (Exception e) { + throw new ConfigurationException(LocalText.getText( + "ClassCannotBeInstantiated", className), e); } + newCompany.init(name, this); + newCompany.configureFromXML(typeTag); + newCompany.configureFromXML(tag); + companies.add(newCompany); return newCompany; } @@ -126,7 +106,4 @@ return capitalisation; } - public CompanyI getDummyCompany() { - return dummyCompany; - } } Modified: trunk/18xx/rails/game/CompanyTypeI.java =================================================================== --- trunk/18xx/rails/game/CompanyTypeI.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/CompanyTypeI.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -28,7 +28,7 @@ // public void configureFromXML(Element el) throws ConfigurationException; - public CompanyI createCompany(String name, Tag tag) + public CompanyI createCompany(String name, Tag typeTag, Tag tag) throws ConfigurationException; /** @@ -48,6 +48,4 @@ public void setCapitalisation(String mode); public int getCapitalisation(); - - public CompanyI getDummyCompany(); } \ No newline at end of file Modified: trunk/18xx/rails/game/Game.java =================================================================== --- trunk/18xx/rails/game/Game.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/Game.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -258,13 +258,14 @@ return null; } GameManagerI gameManager = game.getGameManager(); - int numberOfActions = 0; log.debug("Starting to execute loaded actions"); gameManager.setReloading(true); Object actionObject = null; + int actionIndex = 0; + while (true) { // Single-pass loop. try { actionObject = ois.readObject(); @@ -276,8 +277,8 @@ // Old-style: one List of PossibleActions List<PossibleAction> executedActions = (List<PossibleAction>) actionObject; - numberOfActions = executedActions.size(); for (PossibleAction action : executedActions) { + ++actionIndex; try { if (!gameManager.processOnReload(action)) { log.error ("Load interrupted"); @@ -285,14 +286,14 @@ break; } } catch (Exception e) { - log.fatal("Action '"+action+"' reload exception", e); + log.fatal("Action "+actionIndex+" '"+action+"' reload exception", e); throw new Exception ("Reload exception", e); } } } else if (actionObject instanceof PossibleAction) { // New style: separate PossibleActionsObjects, since Rails 1.3.1 while (actionObject instanceof PossibleAction) { - numberOfActions++; + ++actionIndex; try { if (!gameManager.processOnReload((PossibleAction)actionObject)) { log.error ("Load interrupted"); @@ -300,7 +301,7 @@ break; } } catch (Exception e) { - log.fatal("Action '"+((PossibleAction)actionObject).toString() + log.fatal("Action "+actionIndex+" '"+((PossibleAction)actionObject).toString() +"' reload exception", e); throw new Exception ("Reload exception", e); } Modified: trunk/18xx/rails/game/GameManager.java =================================================================== --- trunk/18xx/rails/game/GameManager.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/GameManager.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -1706,6 +1706,10 @@ return false; } } + + public void setGuiParameter (GuiDef.Parm key, boolean value) { + guiParameters.put (key, value); + } public void setGameParameter (GameDef.Parm key, Object value) { gameParameters.put(key, value); Modified: trunk/18xx/rails/game/GameManagerI.java =================================================================== --- trunk/18xx/rails/game/GameManagerI.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/GameManagerI.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -188,6 +188,7 @@ public abstract String getClassName(GuiDef.ClassName key); + public void setGuiParameter (GuiDef.Parm key, boolean value); public abstract Object getGuiParameter(GuiDef.Parm key); public Object getGameParameter (GameDef.Parm key); public void setGameParameter (GameDef.Parm key, Object value); Modified: trunk/18xx/rails/game/OperatingRound.java =================================================================== --- trunk/18xx/rails/game/OperatingRound.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/OperatingRound.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -241,6 +241,11 @@ } else if (selectedAction instanceof ClosePrivate) { result = executeClosePrivate((ClosePrivate)selectedAction); + + } else if (selectedAction instanceof UseSpecialProperty + && ((UseSpecialProperty)selectedAction).getSpecialProperty() instanceof SpecialRight) { + + result = buyRight ((UseSpecialProperty)selectedAction); } else if (selectedAction instanceof NullAction) { @@ -2305,6 +2310,44 @@ return numberOfLoans * operatingCompany.get().getValuePerLoan(); } + protected boolean buyRight (UseSpecialProperty action) { + + String errMsg = null; + + SpecialPropertyI sp = action.getSpecialProperty(); + if (!(sp instanceof SpecialRight)) { + errMsg = "Wrong right property class: "+sp.toString(); + } + + SpecialRight right = (SpecialRight) sp; + String rightName = right.getName(); + String rightValue = right.getValue(); + + if (errMsg != null) { + DisplayBuffer.add(LocalText.getText("CannotBuyRight", + action.getCompanyName(), + rightName, + Bank.format(right.getCost()), + errMsg)); + + return false; + } + + moveStack.start(true); + + operatingCompany.get().setRight(rightName, rightValue); + new CashMove (operatingCompany.get(), bank, right.getCost()); + + ReportBuffer.add(LocalText.getText("BuysRight", + operatingCompany.get().getName(), + rightName, + Bank.format(right.getCost()))); + + sp.setExercised(); + + return true; + } + /*----- METHODS TO BE CALLED TO SET UP THE NEXT TURN -----*/ /** @@ -2486,10 +2529,13 @@ // Are there other step-independent special properties owned by the company? List<SpecialPropertyI> orsps = operatingCompany.get().getPortfolio().getAllSpecialProperties(); + List<SpecialPropertyI> compsps = operatingCompany.get().getSpecialProperties(); + if (compsps != null) orsps.addAll(compsps); + if (orsps != null) { for (SpecialPropertyI sp : orsps) { if (!sp.isExercised() && sp.isUsableIfOwnedByCompany() - && sp.isUsableDuringOR()) { + && sp.isUsableDuringOR(step)) { if (sp instanceof SpecialTokenLay) { if (getStep() != GameDef.OrStep.LAY_TOKEN) { possibleActions.add(new LayBaseToken((SpecialTokenLay)sp)); @@ -2505,7 +2551,7 @@ if (orsps != null) { for (SpecialPropertyI sp : orsps) { if (!sp.isExercised() && sp.isUsableIfOwnedByPlayer() - && sp.isUsableDuringOR()) { + && sp.isUsableDuringOR(step)) { if (sp instanceof SpecialTokenLay) { if (getStep() != GameDef.OrStep.LAY_TOKEN) { possibleActions.add(new LayBaseToken((SpecialTokenLay)sp)); Modified: trunk/18xx/rails/game/PublicCompany.java =================================================================== --- trunk/18xx/rails/game/PublicCompany.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/PublicCompany.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -4,11 +4,11 @@ import java.awt.Color; import java.util.*; +import rails.common.GuiDef; import rails.game.action.SetDividend; import rails.game.model.*; import rails.game.move.*; -import rails.game.special.SellBonusToken; -import rails.game.special.SpecialPropertyI; +import rails.game.special.*; import rails.game.state.*; import rails.util.*; @@ -274,6 +274,11 @@ protected Bank bank; protected StockMarketI stockMarket; protected MapManager mapManager; + + /** Rights */ + protected HashMapState<String, String> rights = null; + protected RightsModel rightsModel = new RightsModel(); + /** * The constructor. The way this class is instantiated does not allow @@ -607,6 +612,7 @@ ("mustTradeTrainsAtFixedPrice", mustTradeTrainsAtFixedPrice); canClose = optionsTag.getAttributeAsBoolean("canClose", canClose); } + } /** Initialisation, to be called directly after instantiation (cloning) */ @@ -652,29 +658,8 @@ canSharePriceVary = new BooleanState (name+"_CanSharePriceVary", true); } - if (turnsWithExtraTileLaysInit != null) { - turnsWithExtraTileLays = new HashMap<String, IntegerState>(); - for (String colour : turnsWithExtraTileLaysInit.keySet()) { - turnsWithExtraTileLays.put(colour, new IntegerState( - name + "_" + colour + "_ExtraTileTurns", - turnsWithExtraTileLaysInit.get(colour))); - } - } + } - PublicCompanyI dummyCompany = (PublicCompanyI) type.getDummyCompany(); - if (dummyCompany != null) { - fgHexColour = dummyCompany.getHexFgColour(); - bgHexColour = dummyCompany.getHexBgColour(); - } - - if (maxNumberOfLoans != 0) { - currentNumberOfLoans = new IntegerState (name+"_Loans", 0); - currentLoanValue = new MoneyModel (name+"_LoanValue", 0); - currentLoanValue.setOption(MoneyModel.SUPPRESS_ZERO); - } - - } - public void setIndex (int index) { publicNumber = index; } @@ -690,6 +675,21 @@ stockMarket = gameManager.getStockMarket(); mapManager = gameManager.getMapManager(); + if (turnsWithExtraTileLaysInit != null) { + turnsWithExtraTileLays = new HashMap<String, IntegerState>(); + for (String colour : turnsWithExtraTileLaysInit.keySet()) { + turnsWithExtraTileLays.put(colour, new IntegerState( + name + "_" + colour + "_ExtraTileTurns", + turnsWithExtraTileLaysInit.get(colour))); + } + } + + if (maxNumberOfLoans != 0) { + currentNumberOfLoans = new IntegerState (name+"_Loans", 0); + currentLoanValue = new MoneyModel (name+"_LoanValue", 0); + currentLoanValue.setOption(MoneyModel.SUPPRESS_ZERO); + } + if (hasStockPrice && Util.hasValue(startSpace)) { parPrice.setPrice(stockMarket.getStockSpace( startSpace)); @@ -756,6 +756,15 @@ infoText += parentInfoText; parentInfoText = ""; + + // Can companies acquire special rights (such as in 1830 Coalfields)? + if (specialProperties != null) { + for (SpecialPropertyI sp : specialProperties) { + if (sp instanceof SpecialRight) { + gameManager.setGuiParameter (GuiDef.Parm.HAS_ANY_RIGHTS, true); + } + } + } } /** Reset turn objects */ @@ -1973,11 +1982,32 @@ public MoneyModel getLoanValueModel () { return currentLoanValue; } + + public RightsModel getRightsModel () { + return rightsModel; + } public boolean canClose() { return canClose; } - + + public void setRight (String nameOfRight, String value) { + if (rights == null) { + rights = new HashMapState<String, String>(name+"_Rights"); + rightsModel.init (rights); + } + rights.put(nameOfRight, value); + rightsModel.update(); + } + + public boolean hasRight (String nameOfRight) { + return rights != null && rights.hasKey(nameOfRight); + } + + public String getRight (String nameOfRight) { + return rights != null ? rights.get(nameOfRight) : null; + } + @Override public Object clone() { @@ -1996,6 +2026,9 @@ if (certificates != null) { ((PublicCompanyI) clone).setCertificates(certificates); } + if (specialProperties != null) { + ((PublicCompany) clone).specialProperties = new ArrayList<SpecialPropertyI>(specialProperties); + } return clone; } Modified: trunk/18xx/rails/game/PublicCompanyI.java =================================================================== --- trunk/18xx/rails/game/PublicCompanyI.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/PublicCompanyI.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -342,10 +342,15 @@ public int getMaxLoansPerRound(); public int getValuePerLoan(); public MoneyModel getLoanValueModel (); + public RightsModel getRightsModel (); public int sharesOwnedByPlayers(); public String getExtraShareMarks (); + public void setRight (String nameOfRight, String value); + public boolean hasRight (String nameOfRight); + public String getRight (String nameOfRight); + public ModelObject getInGameModel (); public ModelObject getIsClosedModel (); Added: trunk/18xx/rails/game/model/RightsModel.java =================================================================== --- trunk/18xx/rails/game/model/RightsModel.java (rev 0) +++ trunk/18xx/rails/game/model/RightsModel.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -0,0 +1,37 @@ +/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/model/RightsModel.java,v 1.6 2008/06/04 19:00:37 evos Exp $*/ +package rails.game.model; + +import rails.game.state.HashMapState; +import tools.Util; + +public class RightsModel extends ModelObject { + + private HashMapState<String, String> rights; + + public RightsModel() { + } + + /** Split off from the constructor to allow the rights map to exist only if needed */ + public void init (HashMapState<String, String> rights) { + this.rights = rights; + } + + public String getText() { + + if (rights == null) return ""; + + StringBuilder buf = new StringBuilder("<html>"); + for (String name : rights.viewKeySet()) { + if (buf.length() > 6) buf.append("<br>"); + buf.append(name); + String value = rights.get(name); + if (Util.hasValue(value)) buf.append("=").append(value); + } + if (buf.length() > 6) { + buf.append("</html>"); + } + return buf.toString(); + + } + +} Property changes on: trunk/18xx/rails/game/model/RightsModel.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: trunk/18xx/rails/game/special/SpecialProperty.java =================================================================== --- trunk/18xx/rails/game/special/SpecialProperty.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/special/SpecialProperty.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -169,8 +169,18 @@ } - public boolean isUsableDuringOR() { - return usableDuringOR; + public boolean isUsableDuringOR(GameDef.OrStep step) { + + if (usableDuringOR) return true; + + switch (step) { + case LAY_TRACK: + return usableDuringTileLayingStep; + case LAY_TOKEN: + return usableDuringTokenLayingStep; + default: + return false; + } } public void setUsableDuringOR(boolean usableDuringOR) { Modified: trunk/18xx/rails/game/special/SpecialPropertyI.java =================================================================== --- trunk/18xx/rails/game/special/SpecialPropertyI.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/special/SpecialPropertyI.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -1,8 +1,7 @@ /* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/special/SpecialPropertyI.java,v 1.12 2010/03/16 21:21:59 evos Exp $ */ package rails.game.special; -import rails.game.CompanyI; -import rails.game.ConfigurableComponentI; +import rails.game.*; import rails.game.move.Moveable; import rails.game.move.MoveableHolder; @@ -25,7 +24,7 @@ public void setUsableIfOwnedByPlayer(boolean usableIfOwnedByPlayer); - public boolean isUsableDuringOR(); + public boolean isUsableDuringOR(GameDef.OrStep step); public void setUsableDuringOR(boolean usableDuringOR); Added: trunk/18xx/rails/game/special/SpecialRight.java =================================================================== --- trunk/18xx/rails/game/special/SpecialRight.java (rev 0) +++ trunk/18xx/rails/game/special/SpecialRight.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -0,0 +1,76 @@ +/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/game/special/SpecialRight.java,v 1.19 2010/05/05 21:37:18 evos Exp $ */ +package rails.game.special; + +import rails.game.*; +import rails.util.*; + +public class SpecialRight extends SpecialProperty { + + /** The public company of which a share can be obtained. */ + protected String rightName; + protected String rightDefaultValue; + protected String rightValue; + protected int cost; + + @Override + public void configureFromXML(Tag tag) throws ConfigurationException { + + super.configureFromXML(tag); + + Tag rightTag = tag.getChild("SpecialRight"); + if (rightTag == null) { + throw new ConfigurationException("<SpecialRight> tag missing"); + } + + rightName = rightTag.getAttributeAsString("name"); + if (!Util.hasValue(rightName)) + throw new ConfigurationException( + "SpecialRight: no Right name specified"); + + rightDefaultValue = rightValue = rightTag.getAttributeAsString("defaultValue", null); + + cost = rightTag.getAttributeAsInteger("cost", 0); + } + + public boolean isExecutionable() { + + return originalCompany.getPortfolio().getOwner() instanceof Player; + } + + + public String getName() { + return rightName; + } + + public String getDefaultValue() { + return rightDefaultValue; + } + + public String getValue() { + return rightValue; + } + + public void setValue(String rightValue) { + this.rightValue = rightValue; + } + + public int getCost() { + return cost; + } + + @Override + public String toString() { + return "Buy '" + rightName + "' right for " + Bank.format(cost); + } + + @Override + public String toMenu() { + return LocalText.getText("BuyRight", + rightName, + Bank.format(cost)); + } + + public String getInfo() { + return toMenu(); + } +} Property changes on: trunk/18xx/rails/game/special/SpecialRight.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: trunk/18xx/rails/game/state/HashMapState.java =================================================================== --- trunk/18xx/rails/game/state/HashMapState.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/game/state/HashMapState.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -59,6 +59,10 @@ new RemoveFromMap<K,V>(map, key); } + public boolean hasKey(K key) { + return map.containsKey(key); + } + public void clear() { // Two-step process to avoid concurrent modification exception List<K> keys = new ArrayList<K>(); Modified: trunk/18xx/rails/ui/swing/GameStatus.java =================================================================== --- trunk/18xx/rails/ui/swing/GameStatus.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/ui/swing/GameStatus.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -61,6 +61,8 @@ protected int compPrivatesXOffset, compPrivatesYOffset; protected Field compLoans[]; protected int compLoansXOffset, compLoansYOffset; + protected int rightsXOffset, rightsYOffset; + protected Field rights[]; protected Field playerCash[]; protected ClickField playerCashButton[]; protected int playerCashXOffset, playerCashYOffset; @@ -100,6 +102,7 @@ protected boolean compCanHoldOwnShares = false; protected boolean compCanHoldForeignShares = false; // NOT YET USED protected boolean hasCompanyLoans = false; + protected boolean hasRights; // Current actor. // Players: 0, 1, 2, ... @@ -148,6 +151,7 @@ compCanBuyPrivates = gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.CAN_ANY_COMPANY_BUY_PRIVATES); compCanHoldOwnShares = gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.CAN_ANY_COMPANY_HOLD_OWN_SHARES); hasCompanyLoans = gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.HAS_ANY_COMPANY_LOANS); + hasRights = gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.HAS_ANY_RIGHTS); ipo = bank.getIpo(); pool = bank.getPool(); @@ -171,6 +175,7 @@ compTokens = new Field[nc]; compPrivates = new Field[nc]; compLoans = new Field[nc]; + if (hasRights) rights = new Field[nc]; playerCash = new Field[np]; playerCashButton = new ClickField[np]; @@ -215,6 +220,10 @@ compLoansXOffset = ++lastX; compLoansYOffset = lastY; } + if (hasRights) { + rightsXOffset = ++lastX; + rightsYOffset = lastY; + } rightCompCaptionXOffset = ++lastX; playerCashXOffset = certPerPlayerXOffset; @@ -297,6 +306,10 @@ addField (new Caption (LocalText.getText("LOANS")), compLoansXOffset, 1, 1, 1, WIDE_BOTTOM, true); } + if (hasRights) { + addField (new Caption(LocalText.getText("RIGHTS")), + rightsXOffset, 1, 1, 1, WIDE_BOTTOM, true); + } addField(new Caption(LocalText.getText("COMPANY")), rightCompCaptionXOffset, 0, 1, 2, WIDE_LEFT + WIDE_BOTTOM, true); @@ -419,7 +432,13 @@ } addField (f, compLoansXOffset, compLoansYOffset+i, 1, 1, 0, visible); } + + if (hasRights) { + f = rights[i] = new Field (c.getRightsModel()); + addField (f, rightsXOffset, rightsYOffset + i, 1, 1, 0, visible); + } + f = new Caption(c.getName()); f.setForeground(c.getFgColour()); f.setBackground(c.getBgColour()); Modified: trunk/18xx/rails/ui/swing/ORPanel.java =================================================================== --- trunk/18xx/rails/ui/swing/ORPanel.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/ui/swing/ORPanel.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -90,10 +90,13 @@ private Field trains[]; private int trainsXOffset, trainsYOffset; private Field newTrainCost[]; + private int rightsXOffset, rightsYOffset; + private Field rights[]; private boolean privatesCanBeBought = false; private boolean bonusTokensExist = false; private boolean hasCompanyLoans = false; + private boolean hasRights; private Caption tileCaption, tokenCaption, revenueCaption, trainCaption, privatesCaption, loansCaption; @@ -138,6 +141,7 @@ privatesCanBeBought = gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.CAN_ANY_COMPANY_BUY_PRIVATES); bonusTokensExist = gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.DO_BONUS_TOKENS_EXIST); hasCompanyLoans = gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.HAS_ANY_COMPANY_LOANS); + hasRights = gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.HAS_ANY_RIGHTS); initButtonPanel(); gbc = new GridBagConstraints(); @@ -296,6 +300,7 @@ tokensLeft = new Field[nc]; if (bonusTokensExist) tokenBonus = new Field[nc]; if (hasCompanyLoans) compLoans = new Field[nc]; + if (hasRights) rights = new Field[nc]; revenue = new Field[nc]; revenueSelect = new Spinner[nc]; decision = new Field[nc]; @@ -343,6 +348,13 @@ addField (loansCaption = new Caption(LocalText.getText("LOANS")), loansXOffset, 0, lastXWidth = 1, 2, WIDE_RIGHT); } + + if (hasRights) { + rightsXOffset = currentXOffset += lastXWidth; + rightsYOffset = leftCompNameYOffset; + addField (new Caption(LocalText.getText("RIGHTS")), + rightsXOffset, 0, lastXWidth = 1, 2, WIDE_RIGHT); + } tilesXOffset = currentXOffset += lastXWidth; tilesYOffset = leftCompNameYOffset; @@ -441,6 +453,11 @@ } addField (f, loansXOffset, loansYOffset + i, 1, 1, WIDE_RIGHT, visible); } + + if (hasRights) { + f = rights[i] = new Field (c.getRightsModel()); + addField (f, rightsXOffset, rightsYOffset + i, 1, 1, WIDE_RIGHT, visible); + } f = tiles[i] = new Field(c.getTilesLaidThisTurnModel()); addField(f, tilesXOffset, tilesYOffset + i, 1, 1, 0, visible); Modified: trunk/18xx/rails/util/ListAndFixSavedFiles.java =================================================================== --- trunk/18xx/rails/util/ListAndFixSavedFiles.java 2011-06-28 17:08:29 UTC (rev 1594) +++ trunk/18xx/rails/util/ListAndFixSavedFiles.java 2011-06-30 15:19:12 UTC (rev 1595) @@ -302,10 +302,12 @@ if (Util.hasValue(result)) { try { int index = Integer.parseInt(result); - executedActions.remove(index); + PossibleAction action = executedActions.get(index); + executedActions.remove(action); + savedObjects.remove(action); setReportText(false); } catch (NumberFormatException e) { - + log.error("Number format exception for '"+result+"'", e); } } } else if ("SAVE".equalsIgnoreCase(command)) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |