From: Erik V. <ev...@us...> - 2009-01-14 20:45:19
|
Update of /cvsroot/rails/18xx/rails/game/specific/_1856 In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv24082/rails/game/specific/_1856 Modified Files: OperatingRound_1856.java Log Message: Added 1856 loan interest payment (from all possible sources). Index: OperatingRound_1856.java =================================================================== RCS file: /cvsroot/rails/18xx/rails/game/specific/_1856/OperatingRound_1856.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** OperatingRound_1856.java 11 Jan 2009 17:24:46 -0000 1.4 --- OperatingRound_1856.java 14 Jan 2009 20:45:07 -0000 1.5 *************** *** 4,17 **** import java.util.List; ! import rails.game.Bank; ! import rails.game.DisplayBuffer; ! import rails.game.GameManagerI; ! import rails.game.OperatingRound; ! import rails.game.PublicCompanyI; ! import rails.game.ReportBuffer; ! import rails.game.TrainI; ! import rails.game.TrainManager; ! import rails.game.action.ReachDestinations; ! import rails.game.action.TakeLoans; import rails.game.move.CashMove; import rails.game.state.IntegerState; --- 4,9 ---- import java.util.List; ! import rails.game.*; ! import rails.game.action.*; import rails.game.move.CashMove; import rails.game.state.IntegerState; *************** *** 19,39 **** public class OperatingRound_1856 extends OperatingRound { ! public OperatingRound_1856 (GameManagerI gameManager) { super (gameManager); ! } ! /** * Implements special rules for first time operating in 1856 */ protected boolean setNextOperatingCompany(boolean initial) { ! ! if (operatingCompanyIndexObject == null) { operatingCompanyIndexObject = new IntegerState("OperatingCompanyIndex"); } ! while (true) { if (initial) { --- 11,32 ---- public class OperatingRound_1856 extends OperatingRound { ! public OperatingRound_1856 (GameManagerI gameManager) { super (gameManager); ! } ! /** * Implements special rules for first time operating in 1856 */ + @Override protected boolean setNextOperatingCompany(boolean initial) { ! ! if (operatingCompanyIndexObject == null) { operatingCompanyIndexObject = new IntegerState("OperatingCompanyIndex"); } ! while (true) { if (initial) { *************** *** 43,62 **** operatingCompanyIndexObject.add(1); } ! operatingCompanyIndex = operatingCompanyIndexObject.intValue(); ! if (operatingCompanyIndex >= operatingCompanyArray.length) { return false; } else { operatingCompany = operatingCompanyArray[operatingCompanyIndex]; ! // 1856 special: check if the company may operate if (!operatingCompany.hasOperated()) { ! int soldPercentage = 100 - operatingCompany.getUnsoldPercentage(); ! TrainI nextAvailableTrain = TrainManager.get().getAvailableNewTrains().get(0); int trainNumber; ! try { trainNumber = Integer.parseInt(nextAvailableTrain.getName()); } catch (NumberFormatException e) { --- 36,55 ---- operatingCompanyIndexObject.add(1); } ! operatingCompanyIndex = operatingCompanyIndexObject.intValue(); ! if (operatingCompanyIndex >= operatingCompanyArray.length) { return false; } else { operatingCompany = operatingCompanyArray[operatingCompanyIndex]; ! // 1856 special: check if the company may operate if (!operatingCompany.hasOperated()) { ! int soldPercentage = 100 - operatingCompany.getUnsoldPercentage(); ! TrainI nextAvailableTrain = TrainManager.get().getAvailableNewTrains().get(0); int trainNumber; ! try { trainNumber = Integer.parseInt(nextAvailableTrain.getName()); } catch (NumberFormatException e) { *************** *** 64,71 **** } int floatPercentage = 10 * trainNumber; ! log.debug ("Float percentage is "+floatPercentage +" sold percentage is "+soldPercentage); ! if (soldPercentage < floatPercentage) { --- 57,64 ---- } int floatPercentage = 10 * trainNumber; ! log.debug ("Float percentage is "+floatPercentage +" sold percentage is "+soldPercentage); ! if (soldPercentage < floatPercentage) { *************** *** 78,82 **** continue; } ! } return true; --- 71,75 ---- continue; } ! } return true; *************** *** 85,90 **** } protected void setDestinationActions() { ! List<PublicCompanyI> possibleDestinations = new ArrayList<PublicCompanyI>(); for (PublicCompanyI comp : operatingCompanyArray) { --- 78,236 ---- } + @Override + protected void prepareRevenueAndDividendAction () { + + int requiredCash = 0; + + // Check if any loan interest can be paid + int loanValue = operatingCompany.getLoanValueModel().intValue(); + if (loanValue > 0) { + int interest = loanValue * operatingCompany.getLoanInterestPct() / 100; + int compCash = (operatingCompany.getCash() / 10) * 10; + requiredCash = Math.max(interest - compCash, 0); + } + + // There is only revenue if there are any trains + if (operatingCompany.getPortfolio().getNumberOfTrains() > 0) { + int[] allowedRevenueActions = + operatingCompany.isSplitAlways() + ? new int[] { SetDividend.SPLIT } + : operatingCompany.isSplitAllowed() + ? new int[] { SetDividend.PAYOUT, + SetDividend.SPLIT, + SetDividend.WITHHOLD } + : new int[] { SetDividend.PAYOUT, + SetDividend.WITHHOLD }; + + possibleActions.add(new SetDividend( + operatingCompany.getLastRevenue(), true, + allowedRevenueActions, + requiredCash)); + // UI directions: + // Any nonzero required cash should be reported to the user. + // If the revenue is less than that, the allocation + // question should be suppressed. + // In that case, the follow-up is done from this class. + } + } + + @Override + protected int checkForDeductions (SetDividend action) { + + int amount = action.getActualRevenue(); + int due = calculateLoanInterest(operatingCompany.getCurrentNumberOfLoans()); + if (due == 0) return amount; + int remainder = due; + + ReportBuffer.add((LocalText.getText("CompanyMustPayLoanInterest", + operatingCompany.getName(), + Bank.format(due)))); + + // Can it be paid from company treasury? + int payment = Math.min(due, (operatingCompany.getCash() / 10) * 10); + if (payment > 0) { + remainder -= payment; + } + if (remainder == 0) return amount; + + // Can any remainder be paid from revenue? + payment = Math.min (remainder, amount); + if (payment > 0) { + remainder -= payment; + // This reduces train income + amount -= payment; + } + if (remainder == 0) return amount; + + // Pay any remainder from president cash + // First check if president has enough cash + Player president = operatingCompany.getPresident(); + int presCash = president.getCash(); + if (remainder > presCash) { + // Start a share selling round + cashToBeRaisedByPresident = remainder - presCash; + log.info("A share selling round must be started as the president cannot pay $" + + remainder + " loan interest"); + log.info("President has $"+presCash+", so $"+cashToBeRaisedByPresident+" must be added"); + savedAction = action; + gameManager.startShareSellingRound(this, operatingCompany, + cashToBeRaisedByPresident); + // Return arbitrary negative value to signal end of processing to caller. + return -remainder; + + } else { + // OK, nothing more to here + } + + return amount; + } + + @Override + protected int executeDeductions (SetDividend action) { + + int amount = action.getActualRevenue(); + int due = calculateLoanInterest(operatingCompany.getCurrentNumberOfLoans()); + if (due == 0) return amount; + int remainder = due; + + // Pay from company treasury + int payment = Math.min(due, (operatingCompany.getCash() / 10) * 10); + if (payment > 0) { + new CashMove (operatingCompany, null, payment); + if (payment == due) { + ReportBuffer.add (LocalText.getText("InterestPaidFromTreasury", + operatingCompany.getName(), + Bank.format(payment))); + } else { + ReportBuffer.add (LocalText.getText("InterestPartlyPaidFromTreasury", + operatingCompany.getName(), + Bank.format(payment), + Bank.format(due))); + } + remainder -= payment; + } + if (remainder == 0) return amount; + + // Pay any remainder from revenue + payment = Math.min (remainder, amount); + if (payment > 0) { + // Payment money remains in the bank + remainder -= payment; + ReportBuffer.add (LocalText.getText("InterestPaidFromRevenue", + operatingCompany.getName(), + Bank.format(payment), + Bank.format(due))); + // This reduces train income + amount -= payment; + } + if (remainder == 0) return amount; + + // Pay any remainder from president cash + // First check if president has enough cash + Player president = operatingCompany.getPresident(); + int presCash = president.getCash(); + if (remainder > presCash) { + // This can't happen in this stage, log an error + log.error("??? The president still cannot pay $" + + remainder + " loan interest???"); + return 0; + + } else { + + payment = remainder; + new CashMove (president, null, payment); + ReportBuffer.add (LocalText.getText("InterestPaidFromPresidentCash", + operatingCompany.getName(), + Bank.format(payment), + Bank.format(due), + president.getName())); + } + + return amount; + } + + @Override protected void setDestinationActions() { ! List<PublicCompanyI> possibleDestinations = new ArrayList<PublicCompanyI>(); for (PublicCompanyI comp : operatingCompanyArray) { *************** *** 99,103 **** } } ! protected void reachDestination (PublicCompanyI company) { --- 245,250 ---- } } ! ! @Override protected void reachDestination (PublicCompanyI company) { *************** *** 113,141 **** } - - protected void setGameSpecificPossibleActions() { // Take a loan if ((loansThisRound == null || !loansThisRound.containsKey(operatingCompany) || loansThisRound.get(operatingCompany) == 0) ! && gameManager.getCurrentPhase().getIndex() <= gameManager.getPhaseManager().getPhaseByName("4").getIndex() ! && operatingCompany.getCurrentNumberOfLoans() < operatingCompany.sharesOwnedByPlayers()) { ! possibleActions.add(new TakeLoans(operatingCompany, 1, operatingCompany.getValuePerLoan())); } } protected String validateTakeLoans (TakeLoans action) { ! String errMsg = super.validateTakeLoans(action); ! if (errMsg == null) { ! while (true) { // Still allowed in current phase? ! if (gameManager.getCurrentPhase().getIndex() > gameManager.getPhaseManager().getPhaseByName("4").getIndex()) { errMsg = LocalText.getText("WrongPhase", --- 260,289 ---- } + @Override + protected void setGameSpecificPossibleActions() { // Take a loan if ((loansThisRound == null || !loansThisRound.containsKey(operatingCompany) || loansThisRound.get(operatingCompany) == 0) ! && gameManager.getCurrentPhase().getIndex() <= gameManager.getPhaseManager().getPhaseByName("4").getIndex() ! && operatingCompany.getCurrentNumberOfLoans() < operatingCompany.sharesOwnedByPlayers()) { ! possibleActions.add(new TakeLoans(operatingCompany, 1, operatingCompany.getValuePerLoan())); } } + @Override protected String validateTakeLoans (TakeLoans action) { ! String errMsg = super.validateTakeLoans(action); ! if (errMsg == null) { ! while (true) { // Still allowed in current phase? ! if (gameManager.getCurrentPhase().getIndex() > gameManager.getPhaseManager().getPhaseByName("4").getIndex()) { errMsg = LocalText.getText("WrongPhase", *************** *** 158,174 **** } protected int calculateLoanAmount (int numberOfLoans) { ! int amount = super.calculateLoanAmount(numberOfLoans); ! // Deduct interest immediately? if (stepObject.intValue() > STEP_PAYOUT) { ! int interest = numberOfLoans ! * operatingCompany.getValuePerLoan() ! * operatingCompany.getLoanInterestPct() / 100; ! amount -= interest; } ! return amount; } } --- 306,327 ---- } + @Override protected int calculateLoanAmount (int numberOfLoans) { ! int amount = super.calculateLoanAmount(numberOfLoans); ! // Deduct interest immediately? if (stepObject.intValue() > STEP_PAYOUT) { ! amount -= calculateLoanInterest(numberOfLoans); } ! return amount; } + + protected int calculateLoanInterest (int numberOfLoans) { + + return numberOfLoans + * operatingCompany.getValuePerLoan() + * operatingCompany.getLoanInterestPct() / 100; + } } |