From 57a5da122b269ae3a78e8c4c409961461e2a69e3 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 6 Oct 2018 17:39:02 +0200 Subject: [PATCH 01/45] Creating Maven Setup POM.XML --- .classpath | 41 ++- .gitignore | 1 + .project | 6 + .settings/org.eclipse.core.resources.prefs | 3 - .settings/org.eclipse.jdt.core.prefs | 2 + .settings/org.eclipse.m2e.core.prefs | 4 + pom.xml | 279 +++++++++++++++++++++ 7 files changed, 327 insertions(+), 9 deletions(-) delete mode 100644 .settings/org.eclipse.core.resources.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 pom.xml diff --git a/.classpath b/.classpath index f2184a15a..a099b8e94 100644 --- a/.classpath +++ b/.classpath @@ -1,10 +1,39 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + diff --git a/.gitignore b/.gitignore index 3f201678f..4d74ecef1 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ # failed Rails test files **/*.failed /bin/ +/target/ diff --git a/.project b/.project index 5c39c57f7..b08b8511c 100644 --- a/.project +++ b/.project @@ -15,8 +15,14 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature org.eclipse.buildship.core.gradleprojectnature diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index cdaed21ec..000000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Fri Oct 28 23:03:32 CEST 2011 -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 3e904e60a..7fae57d64 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -9,6 +9,8 @@ org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.6 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 000000000..f897a7f1c --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..a376fafba --- /dev/null +++ b/pom.xml @@ -0,0 +1,279 @@ + + + 4.0.0 + + net.sf + rails + jar + 2.0-RC4 + + rails + A Java playing aid for playing 18xx based games via email or in Hotseat mode. + + + net.sf.rails + + + + scm:git:https://github.com/Rails-18xx/Rails + + + + UTF-8 + 1.6 + + + + + junit + junit + 4.12 + test + + + + org.easytesting + fest-assert-core + 2.0M10 + test + + + + org.easytesting + fest-util + 1.2.5 + test + + + + org.mockito + mockito-all + 1.10.19 + test + + + + commons-io + commons-io + 2.1 + + + + jgraph + jgraph + 5.13.0.0 + + + + org.jgrapht + jgrapht-core + 1.0.1 + + + + org.jgrapht + jgrapht-ext + 1.0.1 + + + + org.slf4j + slf4j-api + 1.7.25 + + + + org.apache.xmlgraphics + batik-bridge + 1.9 + + + + org.apache.xmlgraphics + batik-transcoder + 1.9 + + + + org.apache.xmlgraphics + batik-svggen + 1.9 + + + + org.apache.xmlgraphics + batik-ext + 1.9 + + + + org.apache.xmlgraphics + batik-swing + 1.9 + + + + javazoom + jlayer + 1.0.1 + + + + ch.qos.logback + logback-classic + 1.2.3 + + + + com.google.guava + guava + 19.0 + + + + net.java.dev.designgridlayout + designgridlayout + 1.11 + + + + org.dockingframes + docking-frames-common + 1.1.1 + + + + com.googlecode.combinatoricslib + combinatoricslib + 2.1 + + + + + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.9 + + true + false + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + ${jdk.version} + ${jdk.version} + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20 + + + + test/TestGame.java + + + + + + maven-assembly-plugin + 3.0.0 + + + jar-with-dependencies + + + + net.sf.rails.util.RunGame + + + + + + make-assembly + package + + single + + + + + + + + com.akathist.maven.plugins.launch4j + launch4j-maven-plugin + 1.7.18 + + + l4j-gui + package + + launch4j + + + gui + target/${project.name}-${project.version}-jar-with-dependencies.jar + target/${project.name}-${project.version}.exe + Rails + target/classes/build/rails.ico + + + net.sf.rails.util.RunGame + false + anything + + + + 1.6.0 + + + + 2.0.0.0 + 2.0.0.0 + ${project.version} + ${project.version} + ${project.name} + GPL + ${project.name} + ${project.name} + original.exe + + + + + + + + + sh.tak.appbundler + appbundle-maven-plugin + 1.2.0 + + net.sf.rails.util.RunGame + build/rails.ico + true + + + + package + + bundle + + + + + + + \ No newline at end of file From be81e2f0c8eaab8f142a53192e33917bd3a5945f Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sun, 7 Oct 2018 14:16:41 +0200 Subject: [PATCH 02/45] Fixes the problem that a upon creation of the CGR, if that is opened with only 10 shares, the last 10 shares get deleted even though they might be owned by a player. This stems from the fact that findcertificate() returns the certificates within rails 2.0 in a different order than previous releases. --- .../specific/_1856/PublicCompany_CGR.java | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/main/java/net/sf/rails/game/specific/_1856/PublicCompany_CGR.java b/src/main/java/net/sf/rails/game/specific/_1856/PublicCompany_CGR.java index 69d5f3018..3aae348a6 100644 --- a/src/main/java/net/sf/rails/game/specific/_1856/PublicCompany_CGR.java +++ b/src/main/java/net/sf/rails/game/specific/_1856/PublicCompany_CGR.java @@ -28,12 +28,12 @@ public final class PublicCompany_CGR extends PublicCompany implements RevenueSta private final GenericState temporaryPresident = GenericState.create(this, "temporaryPresident"); public PublicCompany_CGR(RailsItem parent, String id) { - super(parent, id); + super(parent, id); // Share price is initially fixed // TODO: Is this the correct location or should that moved to some stage later? - canSharePriceVary.set(false); + this.canSharePriceVary.set(false); } - + @Override public void finishConfiguration(RailsRoot root) throws ConfigurationException { super.finishConfiguration(root); @@ -41,14 +41,14 @@ public void finishConfiguration(RailsRoot root) throws ConfigurationException { // add revenue modifier for the case that there is no train getRoot().getRevenueManager().addStaticModifier(this); } - + public boolean hadPermanentTrain() { - return hadPermanentTrain.value(); + return this.hadPermanentTrain.value(); } public void setHadPermanentTrain(boolean hadPermanentTrain) { this.hadPermanentTrain.set(hadPermanentTrain); - canSharePriceVary.set(true); + this.canSharePriceVary.set(true); } public boolean hasTemporaryPresident () { @@ -56,13 +56,14 @@ public boolean hasTemporaryPresident () { } public Player getTemporaryPresident() { - if (temporaryPresident != null) { - return (Player) temporaryPresident.value(); + if (this.temporaryPresident != null) { + return (Player) this.temporaryPresident.value(); } else { return null; } } - + + @Override public boolean mayBuyTrainType (Train train) { return !"4".equals(train.toText()); } @@ -101,7 +102,7 @@ public boolean runsWithBorrowedTrain () { */ @Override public void withhold(int amount) { - if (hasStockPrice && canSharePriceVary.value()) { + if (this.hasStockPrice && this.canSharePriceVary.value()) { getRoot().getStockMarket().withhold(this); } } @@ -109,27 +110,30 @@ public void withhold(int amount) { @Override public void buyTrain(Train train, int price) { super.buyTrain (train, price); - if (train.isPermanent()) setHadPermanentTrain(true); + if (train.isPermanent()) { + setHadPermanentTrain(true); + } } + @SuppressWarnings("deprecation") public void setShareUnit (int percentage) { // Only allowed for CGR, the value must be 10 - if (shareUnit.value() == 5 + if (this.shareUnit.value() == 5 && percentage == 10) { - shareUnit.set(percentage); + this.shareUnit.set(percentage); // Drop the last 10 shares - Listcerts = new ArrayList(certificates.view()); - int share = 0; + //2018-10-07-MBr: With the remodeled base classes this approach isnt valid anymore as shares + //with the id-10 are assigned before shares with the id-2 + Listcerts = new ArrayList(this.certificates.view()); BankPortfolio scrapHeap = getRoot().getBank().getScrapHeap(); - for (PublicCertificate cert : certs) { - if (share >= 100) { - cert.moveTo(scrapHeap); - certificates.remove(cert); - } else { - cert.setCertificateCount(1.0f); - share += cert.getShare(); + for (PublicCertificate cert : certs) { + if (cert.getOwner().getId()== "Unavailable" ) { + cert.moveTo(scrapHeap); + this.certificates.remove(cert); + } else { + cert.setCertificateCount(1.0f); + } } - } // Update all owner ShareModels (once) // to have the UI get the correct percentage @@ -162,10 +166,13 @@ public String getExtraShareMarks () { return (hasTemporaryPresident() ? "T" : ""); } + @Override public boolean modifyCalculator(RevenueAdapter revenueAdapter) { // check if the running company is the cgr - if (revenueAdapter.getCompany() != this) return false; - + if (revenueAdapter.getCompany() != this) { + return false; + } + // add the diesel train if (runsWithBorrowedTrain()) { revenueAdapter.addTrainByString("D"); @@ -174,8 +181,9 @@ public boolean modifyCalculator(RevenueAdapter revenueAdapter) { return false; } + @Override public String prettyPrint(RevenueAdapter revenueAdapter) { - + return null; } } From 856dec92dc069fce664e98068be442697d7ef620 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sun, 7 Oct 2018 14:16:41 +0200 Subject: [PATCH 03/45] Fixes the problem that a upon creation of the CGR, if that is opened with only 10 shares, the last 10 shares get deleted even though they might be owned by a player. This stems from the fact that findcertificate() returns the certificates within rails 2.0 in a different order than previous releases. From fad9cc36445b9dae13992bfce2facd1485457d38 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sun, 21 Oct 2018 15:27:34 +0200 Subject: [PATCH 04/45] Fixing the Game Tests.- Adding the 1856 Game from BGG for teh test of 10 Share conversion CGR --- .classpath | 37 ++-- .../data/real/1856_CGR-10Shares-Test.rails | Bin 0 -> 29985 bytes src/test/resources/data/real/1880_ATG1.rails | Bin 45001 -> 44698 bytes src/test/resources/data/real/1880_ATG1.report | 179 +++++++++--------- .../data/test/1835_ShareSelling_Test.rails | Bin 22560 -> 22309 bytes .../data/test/1835_ShareSelling_Test.report | 38 ++-- 6 files changed, 130 insertions(+), 124 deletions(-) create mode 100644 src/test/resources/data/real/1856_CGR-10Shares-Test.rails diff --git a/.classpath b/.classpath index a099b8e94..49b418df5 100644 --- a/.classpath +++ b/.classpath @@ -1,39 +1,30 @@ - + - - + + - + - - - + + - + - + + - + - - - - - - - + + + - - - - - - + diff --git a/src/test/resources/data/real/1856_CGR-10Shares-Test.rails b/src/test/resources/data/real/1856_CGR-10Shares-Test.rails new file mode 100644 index 0000000000000000000000000000000000000000..bdf070e72298fb0d76f7f5068174740b2c62d9c5 GIT binary patch literal 29985 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 Woc{Np-u1pCV1WF$Qp#@hJO2Y%@$~fo literal 0 HcmV?d00001 diff --git a/src/test/resources/data/real/1880_ATG1.rails b/src/test/resources/data/real/1880_ATG1.rails index 21bd62087004b2513510dc4cca57c5ba2efe475e..b7d89b187ad61dff1755f04b39a690865a1ebb85 100644 GIT binary patch delta 5789 zcmb_gdr*^C7S9*>q7X>PkOU3SXcQ1Z0zm~@0R>6L2e_j6L{hO*c?d)Wq%Dft`T)US zwLU;`ZIxQ_(d@cATf5rMwA)UdTL0+m>{wdeKOEQD?PI39vz^^`_T2j=U%p_O*`YGS z^}FYsd+vGs&N&x9{z`pfSZ%xb50&Uvjmt<&Pg^?A;Z{Xvq}ykw+S5}r>&O)>y`RJy^^3RGxvHC%Y%Hyn>vLQAWg>S~&sYqnK;ARIJ|3)?a@{77Q4lSL}ByzAaeP7J?flmrP4CuaLhDCKK|aMbChFmU<)+*V`j-Z<`M0iF+RB zO*}h-X2WTV@?xg={9`ghlgA@1=3NEdg7DN3m|`~s&<2b;492ck&{FYKT!muqb1W1e zDd>suWj-0tOYx1$C~;58sW{BAw)=!AdJ_GX_4o*y3F#?1ygq59tVFMzyu&B&xj*?+ z|3%lPbom&_pJ77f)ZdNRi@2GqLs8;7nSLR0rTm>g<7pHpU03Wa+~{wMgE2q(odEhp z=Oh$P3!r%tQf~Q;kqi(i#Py1U%&16QNF5wO^BFcBw-YDg!?b9b|1eDsD>?NWnVvtx zZ``c(HU-`2xs{$0>?3%7a-8v7b#7**%m|zHfggEgg*Gx(htQn0J^_>!W?&%4A1fyF z^k4`wa-UVm*eIr(<-I-6hRu6JP}*nmxSx94e=}n+1h8N>&yf@3vF8baLTmH;6x!kt zSMauCZ^PRB2rQhQfc&g+$e7z2z+)GDKlhI^jafWAuTHV=QG83@n2P)b%H(h6M&h?c zpUZN+^WT!c?RoL|c%~j<#pBUhJXNNjEB;Xaw&yu;-Z`MyGnEDUGKS5a&^2++_&ti{9RD)FYN8-xzQwsSg)UNPDwxB!; zMHRgP{O>CY<$d1DPvvjpDu0uBY1M6+esWDbN~&x)w)($5n&;%27lNmI`z7_vphne; zLG^4&VM_yB3f(Hv)zq+EBBLyS8tSWFvMUaez;jL2)slc)rD?6Mt!>!O&$8uRwxqP+ zYI`z@UGF9#!|~S*6HWeO zf_z5`gj5rzRPV6)x!m=iwFSWpJm3a-7!3>agy;No}KM!qEL=2J6CAjs-Sr#OVQgAjk?AVBy~(c z&r%cS95La`mkoj*J2yt-)UHysNT2I+ae1dkq;$}(vBQS1cIr`iI1CRqMyN#t*Rp6& zs9;9HUU~{F)o?wQgW>q0GnolkOKtds6#l)FsWvROG2+g3Hr&`9jb9xx;KxoaR%aUU zpV=Yo#>S3Z_!MTNd{Zng?b%G~nYmee8wCdnN=b*AbWB0tCL@--63flYQCJWX7evL+ zegyh0r{7TTFRK|bhr2kZM#Ew;cU8G;B=g@)Mn>bVEd<6_&eG0WIt5pbSa2^>k1Ly^ zLB8?(%D72i)sWRrx;h(QAJO2RM#N{C@m!F3?DPt0@ZSDxtdB_NoUZ*2uEIsayp>b5DWTkLG%HKsbt0;Hn5R59#ACsub&SM*OFuHB5|Js>2EJmBd{q&x3+EfZX@ zHkdKL+nnd`Lcxk&Dt0P+skkS=9=9r(dTuMfikeFdjad_VEIPI5!WZ2&xOpm=a$j=D z63Ikz=&U2fQJKNRbQ)(I7Ia+J>KLz|vfe~isw>bqkg68@araPMcsHebcBP%m_u#$E zB$PI4Fi0v!?Yzo7NuNnlYASLiddCPh#S;9)X<47p+CAd`bc;=w~Se(#}tfSVH9EO9yAK`Ph z-@-%YV39p5M>`&sB?Npet{zRxRAie;9c4==TV7+!9=05lX~+2&?1N@Oi@evI9Mwa( zztXsHLBH6_bBInFr7hFBzYgpuHkrCyLc z!j)4-O2*}5abY>kXutOiYa-V4g=j?sgAN=zuH_Ea zVBomqsu^E4gVU#jUxFr0|TO$TvZ z_*Y-*n1V#3StGg#L>FMU+0Zk<+sPmLy&3%*$MYkqw|GQM2|+}RNi90S_(P9pT*_oW zT23t#aOLn7&o7EXiUF2Y~EVwIbAYA9O4B*?^^G_ zymgEJ#C?Z(>;Ym*>wN*T`tAsN$eN9M8ylfP57~WEadzXzK$eCBe;F3JZ0Km4%sS)A zGbL&oSP##Xq={xG&WX@d3&ETqpm7Kr5CJv}cmv)Dg-CvvIGL zrq$7fEtUY@!f8!oaIsBy4@ z(PSwLX1eI$x%Mr)Sjzdc%ZnG6@}PH4^Pbp`Z_dqR<2ms>>1PF}DdhT#Pl3v2`ux}cL-R+}lAW7)_~M;Bd@djMRlz=YRP>*8&t!U$wC@QdPcfI` z-W)$g995?RS?rH3Ew`BL`5HAH#D$S3gK83%^FL(7b+x1L6+UPO9!2nL+v@P$<;4V`>cRm|}XoW_f>^Pa?X zpxLA0<dD`(5+|hS3*@uT^Ld? b>Bm|>Y+RkZM7VZ=*A2(@6Rw-y%d`In5w81s delta 6122 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 Date: Sun, 21 Oct 2018 15:46:00 +0200 Subject: [PATCH 05/45] Fixing failed Test Games for CI Test. --- .../resources/data/real/1835_KoIT3.report | 2 + .../resources/data/real/1835_Stoll_12.report | 1 + src/test/resources/data/real/1856_A.report | 2 +- .../data/real/1856_CGR-10Shares-Test.report | 1346 +++++++++++++++++ 4 files changed, 1350 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/data/real/1856_CGR-10Shares-Test.report diff --git a/src/test/resources/data/real/1835_KoIT3.report b/src/test/resources/data/real/1835_KoIT3.report index 871610b48..d9a783857 100644 --- a/src/test/resources/data/real/1835_KoIT3.report +++ b/src/test/resources/data/real/1835_KoIT3.report @@ -704,6 +704,7 @@ PriceIsPaidTo,84,BA BUY_SHARE_LOG,Ronnie,10,BY,Pool,90 BUY_SHARE_LOG,Helmut,10,WT,IPO,84 SELL_SHARE_LOG,Lonny,10,BY,90 +PASSES,Lonny PASSES,Stefan Autopasses,Ronnie BUY_SHARE_LOG,Helmut,10,WT,IPO,84 @@ -1057,6 +1058,7 @@ SELL_SHARE_LOG,Helmut,5,PR,77 PRICE_MOVES_LOG,PR,154,I4,140,I5 SELL_SHARE_LOG,Helmut,10,PR,154 SELL_SHARE_LOG,Helmut,10,PR,154 +PASSES,Helmut SELL_SHARE_LOG,Lonny,10,BA,74 PRICE_MOVES_LOG,BA,74,B6,66,B7 BUY_SHARE_LOG,Lonny,10,HE,IPO,84 diff --git a/src/test/resources/data/real/1835_Stoll_12.report b/src/test/resources/data/real/1835_Stoll_12.report index db40b567a..6efe7ee48 100644 --- a/src/test/resources/data/real/1835_Stoll_12.report +++ b/src/test/resources/data/real/1835_Stoll_12.report @@ -996,6 +996,7 @@ PriceIsPaidTo,84,HE PASSES,Eyal SELL_SHARE_LOG,Marco,10,WT,84 PRICE_MOVES_LOG,WT,84,B4,80,B5 +PASSES,Marco BUY_SHARE_LOG,Nick,10,WT,Pool,80 PASSES,Christian PASSES,Eyal diff --git a/src/test/resources/data/real/1856_A.report b/src/test/resources/data/real/1856_A.report index 1df3a731c..e87ada9b2 100644 --- a/src/test/resources/data/real/1856_A.report +++ b/src/test/resources/data/real/1856_A.report @@ -1155,7 +1155,6 @@ HasMergedShares,POOL,13,5,CGR CompanyHasShares,CGR,20,5 IS_NOW_PRES_OF,Ed,CGR Floats,CGR -CertificateLimit,10,5,6 ExchangesBaseToken,CGR,CA,D17/1 ExchangesBaseToken,CGR,TGB,K8/1 ExchangesBaseToken,CGR,GT,P9/1 @@ -1192,6 +1191,7 @@ Has,Ed,280 Has,Stefan,554 Has,Joakim,101 START_OR,5.3 +CertificateLimit,10,5,6 CompanyOperates,GW,Stefan LaysTileAt,GW,125,F17,S diff --git a/src/test/resources/data/real/1856_CGR-10Shares-Test.report b/src/test/resources/data/real/1856_CGR-10Shares-Test.report new file mode 100644 index 000000000..e4eb75c25 --- /dev/null +++ b/src/test/resources/data/real/1856_CGR-10Shares-Test.report @@ -0,0 +1,1346 @@ +GameIs,1856 +PlayerIs,1,Lonny +PlayerIs,2,Tyler +PlayerIs,3,Ron +PlayerIs,4,Justin +PlayerCash,375 +BankHas,10500 +StartOfPhase,2 +BankSizeIs,10500 +StartOfInitialRound +HasPriority,Lonny +BID_ITEM_LOG,Lonny,105,Tunn,270 +BID_ITEM_LOG,Tyler,75,Ship,300 +BID_ITEM_LOG,Ron,105,Brdg,270 +BID_ITEM_LOG,Justin,80,Ship,295 +BID_ITEM_LOG,Lonny,45,W&SR,225 +BID_ITEM_LOG,Tyler,55,TCC,245 +BID_ITEM_LOG,Ron,110,Tunn,160 +BID_ITEM_LOG,Justin,50,W&SR,245 +BID_ITEM_LOG,Lonny,60,TCC,165 +BuysItemFor,Tyler,Flos,20 +TO_AUCTION,W&SR +BID_ITEM_LOG,Lonny,55,W&SR,155 +BID_ITEM_LOG,Justin,60,W&SR,235 +PASSES,Lonny +BuysItemFor,Justin,W&SR,60 +TO_AUCTION,TCC +BID_ITEM_LOG,Tyler,65,TCC,215 +PASSES,Lonny +BuysItemFor,Tyler,TCC,65 +TO_AUCTION,Ship +BID_ITEM_LOG,Tyler,85,Ship,205 +BID_ITEM_LOG,Justin,90,Ship,225 +BID_ITEM_LOG,Tyler,95,Ship,195 +BID_ITEM_LOG,Justin,100,Ship,215 +PASSES,Tyler +BuysItemFor,Justin,Ship,100 +BuysItemFor,Ron,Brdg,105 +TO_AUCTION,Tunn +BID_ITEM_LOG,Lonny,115,Tunn,260 +BID_ITEM_LOG,Ron,120,Tunn,150 +BID_ITEM_LOG,Lonny,125,Tunn,250 +BID_ITEM_LOG,Ron,130,Tunn,140 +PASSES,Lonny +BuysItemFor,Ron,Tunn,130 +Has,Lonny,375 +Has,Tyler,290 +Has,Ron,140 +Has,Justin,215 +StartStockRound,1 +HasPriority,Ron +PASSES,Ron +PASSES,Justin +START_COMPANY_LOG,Lonny,LPS,65,130,2,20,LPS +Floats,LPS +START_COMPANY_LOG,Tyler,WR,65,130,2,20,WR +Floats,WR +BUY_SHARE_LOG,Ron,10,LPS,IPO,65 +PriceIsPaidTo,65,LPS +START_COMPANY_LOG,Justin,GT,65,130,2,20,GT +Floats,GT +BUY_SHARE_LOG,Lonny,10,LPS,IPO,65 +PriceIsPaidTo,65,LPS +BUY_SHARE_LOG,Tyler,10,WR,IPO,65 +PriceIsPaidTo,65,WR +BUY_SHARE_LOG,Ron,10,WR,IPO,65 +PriceIsPaidTo,65,WR +BUY_SHARE_LOG,Justin,10,GT,IPO,65 +PriceIsPaidTo,65,GT +BUY_SHARE_LOG,Lonny,10,LPS,IPO,65 +PriceIsPaidTo,65,LPS +BUY_SHARE_LOG,Tyler,10,WR,IPO,65 +PriceIsPaidTo,65,WR +Autopasses,Ron +Autopasses,Justin +HoldMoneyInEscrow,65,65,LPS +BUY_SHARE_LOG,Lonny,10,LPS,IPO,65 +PASSES,Tyler +Autopasses,Ron +Autopasses,Justin +PASSES,Lonny + +END_SR,1 +Has,GT,195 +Has,LPS,325 +Has,WR,325 +Has,Lonny,50 +Has,Tyler,30 +Has,Ron,10 +Has,Justin,20 +START_OR,1.1 +ReceivesFor,Tyler,5,Flos +ReceivesFor,Justin,10,W&SR +ReceivesFor,Tyler,10,TCC +ReceivesFor,Justin,15,Ship +ReceivesFor,Ron,20,Brdg +ReceivesFor,Ron,20,Tunn + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,5,C14,N +CompanyDoesNotPayDividend,LPS +PRICE_MOVES_LOG,LPS,65,E6,60,D6 +CompanyTakesLoan,LPS,100,90 +BuysTrain,LPS,2,IPO,100 +FirstTrainBought,2 +BuysTrain,LPS,2,IPO,100 + +CompanyOperates,WR,Tyler +LaysTileAt,WR,5,O16,SW +CompanyDoesNotPayDividend,WR +PRICE_MOVES_LOG,WR,65,E6,60,D6 +BuysTrain,WR,2,IPO,100 +CompanyTakesLoan,WR,100,90 +BuysTrain,WR,2,IPO,100 + +CompanyOperates,GT,Justin +CompanyTakesLoan,GT,100,100 +LaysTileAt,GT,57,P9,SW +InterestPaidFromTreasury,GT,10 +CompanyDoesNotPayDividend,GT +PRICE_MOVES_LOG,GT,65,E6,60,D6 +BuysTrain,GT,2,IPO,100 +BuysTrain,GT,2,IPO,100 +All 2-trains are sold out, 3-trains now available + +EndOfOperatingRound,1.1 +ORWorthIncrease,Lonny,1.1,-75 +ORWorthIncrease,Tyler,1.1,-45 +ORWorthIncrease,Ron,1.1,10 +ORWorthIncrease,Justin,1.1,-20 +Has,GT,85 +Has,LPS,215 +Has,WR,215 +Has,Lonny,50 +Has,Tyler,45 +Has,Ron,50 +Has,Justin,45 +StartStockRound,2 +HasPriority,Tyler +SELL_SHARE_LOG,Tyler,10,WR,60 +PRICE_MOVES_LOG,WR,60,D6,55,D7 +HoldMoneyInEscrow,65,130,LPS +BUY_SHARE_LOG,Tyler,10,LPS,IPO,65 +PASSES,Ron +Autopasses,Justin +SELL_SHARE_LOG,Lonny,10,LPS,60 +PRICE_MOVES_LOG,LPS,60,D6,55,D7 +BUY_SHARE_LOG,Lonny,10,WR,Pool,55 +PASSES,Tyler +PASSES,Ron +Autopasses,Justin +PASSES,Lonny + +END_SR,2 +Has,GT,85 +Has,LPS,215 +Has,WR,215 +Has,Lonny,55 +Has,Tyler,40 +Has,Ron,50 +Has,Justin,45 +START_OR,2.1 +ReceivesFor,Tyler,5,Flos +ReceivesFor,Justin,10,W&SR +ReceivesFor,Tyler,10,TCC +ReceivesFor,Justin,15,Ship +ReceivesFor,Ron,20,Brdg +ReceivesFor,Ron,20,Tunn + +CompanyOperates,GT,Justin +LaysTileAt,GT,9,O10,SW +CompanyRevenue,GT,90 +CompanyMustPayLoanInterest,GT,10 +InterestPaidFromTreasury,GT,10 +CompanyPaysOutFull,GT,90 +Payout,Justin,27,3,10 +PRICE_MOVES_LOG,GT,60,D6,65,E6 +CompanyTakesLoan,GT,100,90 + +CompanyOperates,WR,Tyler +LaysTileAt,WR,6,O18,S +CompanyRevenue,WR,90 +CompanyMustPayLoanInterest,WR,10 +InterestPaidFromTreasury,WR,10 +CompanyPaysOutFull,WR,90 +Payout,Ron,9,1,10 +Payout,Tyler,27,3,10 +Payout,Lonny,9,1,10 +PRICE_MOVES_LOG,WR,55,D7,60,E7 +CompanyTakesLoan,WR,100,90 +BuysTrain,WR,3,IPO,225 +FirstTrainBought,3 +StartOfPhase,3 + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,7,B15,N +CompanyRevenue,LPS,100 +CompanyMustPayLoanInterest,LPS,10 +InterestPaidFromTreasury,LPS,10 +CompanyPaysOutFull,LPS,100 +Payout,Ron,10,1,10 +Payout,Tyler,10,1,10 +Payout,Lonny,40,4,10 +Payout,LPS,10,1,10 +PRICE_MOVES_LOG,LPS,55,D7,60,E7 +CompanyTakesLoan,LPS,100,90 +BuysTrain,LPS,3,IPO,225 + +EndOfOperatingRound,2.1 +ORWorthIncrease,Lonny,2.1,24 +ORWorthIncrease,Tyler,2.1,32 +ORWorthIncrease,Ron,2.1,49 +ORWorthIncrease,Justin,2.1,37 +Has,GT,165 +Has,LPS,80 +Has,WR,70 +Has,Lonny,104 +Has,Tyler,92 +Has,Ron,109 +Has,Justin,97 +StartStockRound,3 +HasPriority,Tyler +HoldMoneyInEscrow,65,65,WR +BUY_SHARE_LOG,Tyler,10,WR,IPO,65 +BUY_SHARE_LOG,Ron,10,GT,IPO,65 +PriceIsPaidTo,65,GT +BUY_SHARE_LOG,Justin,10,GT,IPO,65 +PriceIsPaidTo,65,GT +SELL_SHARE_LOG,Lonny,10,WR,60 +PRICE_MOVES_LOG,WR,60,E7,55,E8 +SELL_SHARE_LOG,Lonny,10,LPS,60 +PRICE_MOVES_LOG,LPS,60,E7,55,E8 +START_COMPANY_LOG,Lonny,CA,70,140,2,20,CA +PASSES,Tyler +PASSES,Ron +PASSES,Justin +BUY_SHARE_LOG,Lonny,10,CA,IPO,70 +PriceIsPaidTo,70,CA +Floats,CA +PASSES,Tyler +PASSES,Ron +PASSES,Justin +PASSES,Lonny + +END_SR,3 +Has,GT,295 +Has,LPS,80 +Has,WR,70 +Has,CA,210 +Has,Lonny,14 +Has,Tyler,27 +Has,Ron,44 +Has,Justin,32 +START_OR,3.1 +ReceivesFor,Tyler,5,Flos +ReceivesFor,Justin,10,W&SR +ReceivesFor,Tyler,10,TCC +ReceivesFor,Justin,15,Ship +ReceivesFor,Ron,20,Brdg +ReceivesFor,Ron,20,Tunn + +CompanyOperates,CA,Lonny +LaysTileAt,CA,6,D17,NE +CompanyDoesNotPayDividend,CA +PRICE_MOVES_LOG,CA,70,E5,65,D5 +CompanyTakesLoan,CA,100,90 +BuysTrain,CA,3,IPO,225 +BuysTrain,CA,2,LPS,74 + +CompanyOperates,GT,Justin +LaysTileAt,GT,120,N11,NE +CompanyTakesLoan,GT,100,100 +CompanyRevenue,GT,120 +CompanyMustPayLoanInterest,GT,30 +InterestPaidFromTreasury,GT,30 +CompanyPaysOutFull,GT,120 +Payout,Ron,12,1,10 +Payout,Justin,48,4,10 +PRICE_MOVES_LOG,GT,65,E6,70,F6 +BuysTrain,GT,3,IPO,225 + +CompanyOperates,WR,Tyler +LaysTileAt,WR,15,O16,SE +LAYS_TOKEN_ON,WR,O18,40 +CompanyRevenue,WR,160 +CompanyMustPayLoanInterest,WR,20 +InterestPaidFromTreasury,WR,20 +CompanyPaysOutFull,WR,160 +Payout,Ron,16,1,10 +Payout,Tyler,64,4,10 +Payout,WR,16,1,10 +PRICE_MOVES_LOG,WR,55,E8,60,F8 + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,15,C14,SE +CompanyRevenue,LPS,120 +CompanyMustPayLoanInterest,LPS,20 +InterestPaidFromTreasury,LPS,20 +CompanyPaysOutFull,LPS,120 +Payout,Ron,12,1,10 +Payout,Tyler,12,1,10 +Payout,Lonny,36,3,10 +Payout,LPS,24,2,10 +PRICE_MOVES_LOG,LPS,55,E8,60,F8 +CompanyTakesLoan,LPS,100,90 +BuysTrain,LPS,3,IPO,225 +All 3-trains are sold out, 4-trains now available + +EndOfOperatingRound,3.1 +ORWorthIncrease,Lonny,3.1,-24 +ORWorthIncrease,Tyler,3.1,106 +ORWorthIncrease,Ron,3.1,75 +ORWorthIncrease,Justin,3.1,53 +Has,GT,140 +Has,LPS,23 +Has,WR,26 +Has,CA,1 +Has,Lonny,50 +Has,Tyler,118 +Has,Ron,124 +Has,Justin,105 +START_OR,3.2 +ReceivesFor,Tyler,5,Flos +ReceivesFor,Justin,10,W&SR +ReceivesFor,Tyler,10,TCC +ReceivesFor,Justin,15,Ship +ReceivesFor,Ron,20,Brdg +ReceivesFor,Ron,20,Tunn + +CompanyOperates,GT,Justin +CompanyTakesLoan,GT,100,100 +BuysPrivateFromFor,GT,Ship,Justin,140 +BuysPrivateFromFor,GT,W&SR,Justin,80 +LaysTileAt,GT,14,P9,SW +CompanyRevenue,GT,190 +CompanyMustPayLoanInterest,GT,40 +InterestPartlyPaidFromTreasury,GT,20,40 +InterestPaidFromRevenue,GT,20,40 +CompanyPaysOutFull,GT,170 +Payout,Justin,68,4,10 +Payout,Ron,17,1,10 +PRICE_MOVES_LOG,GT,70,F6,75,G6 + +CompanyOperates,CA,Lonny +LaysTileAt,CA,8,D15,S +CompanyTakesLoan,CA,100,100 +LAYS_TOKEN_ON,CA,C14,40 +CompanyRevenue,CA,140 +CompanyMustPayLoanInterest,CA,20 +InterestPaidFromTreasury,CA,20 +CompanyPaysOutFull,CA,140 +Payout,Lonny,42,3,10 +PRICE_MOVES_LOG,CA,65,D5,70,E5 + +CompanyOperates,WR,Tyler +LaysTileAt,WR,59,N17,NE +CompanyRevenue,WR,210 +CompanyMustPayLoanInterest,WR,20 +InterestPaidFromTreasury,WR,20 +CompanyPaysOutFull,WR,210 +Payout,Ron,21,1,10 +Payout,Tyler,84,4,10 +Payout,WR,21,1,10 +PRICE_MOVES_LOG,WR,60,F8,65,F7 +CompanyTakesLoan,WR,100,90 +BuysPrivateFromFor,WR,TCC,Tyler,100 + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,15,D17,SW +CompanyTakesLoan,LPS,100,100 +LAYS_TOKEN_ON,LPS,D17,40 +CompanyRevenue,LPS,180 +CompanyMustPayLoanInterest,LPS,40 +InterestPaidFromTreasury,LPS,40 +CompanyPaysOutFull,LPS,180 +Payout,Tyler,18,1,10 +Payout,Ron,18,1,10 +Payout,Lonny,54,3,10 +Payout,LPS,36,2,10 +PRICE_MOVES_LOG,LPS,60,F8,65,F7 + +EndOfOperatingRound,3.2 +ORWorthIncrease,Lonny,3.2,66 +ORWorthIncrease,Tyler,3.2,142 +ORWorthIncrease,Ron,3.2,81 +ORWorthIncrease,Justin,3.2,183 +Has,GT,0 +Has,LPS,79 +Has,WR,17 +Has,CA,41 +Has,Lonny,146 +Has,Tyler,335 +Has,Ron,220 +Has,Justin,418 +StartStockRound,4 +HasPriority,Tyler +START_COMPANY_LOG,Tyler,THB,90,180,2,20,THB +START_COMPANY_LOG,Ron,CV,100,200,2,20,CV +SELL_SHARE_LOG,Ron,10,GT,75 +PRICE_MOVES_LOG,GT,75,G6,70,G7 +SELL_SHARE_LOG,Ron,10,WR,65 +PRICE_MOVES_LOG,WR,65,F7,60,F8 +SELL_SHARE_LOG,Ron,10,LPS,65 +PRICE_MOVES_LOG,LPS,65,F7,60,F8 +START_COMPANY_LOG,Justin,TGB,100,200,2,20,TGB +HoldMoneyInEscrow,65,195,LPS +BUY_SHARE_LOG,Lonny,10,LPS,IPO,65 +BUY_SHARE_LOG,Tyler,10,THB,IPO,90 +PriceIsPaidTo,90,THB +SELL_SHARE_LOG,Tyler,10,LPS,60 +BUY_SHARE_LOG,Ron,10,CV,IPO,100 +PriceIsPaidTo,100,CV +HoldMoneyInEscrow,65,65,GT +BUY_SHARE_LOG,Justin,10,GT,IPO,65 +HoldMoneyInEscrow,65,260,LPS +BUY_SHARE_LOG,Lonny,10,LPS,IPO,65 +BUY_SHARE_LOG,Tyler,10,THB,IPO,90 +PriceIsPaidTo,90,THB +Floats,THB +BUY_SHARE_LOG,Ron,10,CV,IPO,100 +PriceIsPaidTo,100,CV +Floats,CV +HoldMoneyInEscrow,65,130,GT +BUY_SHARE_LOG,Justin,10,GT,IPO,65 +PASSES,Lonny +SELL_SHARE_LOG,Tyler,10,THB,90 +PRICE_MOVES_LOG,THB,90,E2,80,E3 +HoldMoneyInEscrow,65,130,WR +BUY_SHARE_LOG,Tyler,10,WR,IPO,65 +Autopasses,Ron +SELL_SHARE_LOG,Justin,10,GT,70 +BUY_SHARE_LOG,Justin,10,CV,IPO,100 +PriceIsPaidTo,100,CV +PASSES,Lonny +PASSES,Tyler +Autopasses,Ron +SELL_SHARE_LOG,Justin,10,GT,70 +BUY_SHARE_LOG,Justin,10,TGB,IPO,100 +PriceIsPaidTo,100,TGB +SELL_SHARE_LOG,Lonny,10,CA,70 +PRICE_MOVES_LOG,CA,70,E5,65,E6 +HoldMoneyInEscrow,65,325,LPS +BUY_SHARE_LOG,Lonny,10,LPS,IPO,65 +PASSES,Tyler +Autopasses,Ron +SELL_SHARE_LOG,Justin,10,CV,100 +PRICE_MOVES_LOG,CV,100,E1,90,E2 +BUY_SHARE_LOG,Justin,10,TGB,IPO,100 +PriceIsPaidTo,100,TGB +Floats,TGB +PASSES,Lonny +PASSES,Tyler +Autopasses,Ron +PASSES,Justin + +END_SR,4 +Has,GT,0 +Has,THB,360 +Has,LPS,79 +Has,WR,17 +Has,CV,500 +Has,CA,41 +Has,TGB,400 +Has,Lonny,21 +Has,Tyler,60 +Has,Ron,25 +Has,Justin,28 +START_OR,4.1 +ReceivesFor,Tyler,5,Flos +ReceivesFor,GT,10,W&SR +ReceivesFor,WR,10,TCC +ReceivesFor,GT,15,Ship +ReceivesFor,Ron,20,Brdg +ReceivesFor,Ron,20,Tunn + +CompanyOperates,TGB,Justin +LaysTileAt,TGB,6,K8,SE +CompanyTakesLoan,TGB,100,100 +InterestPaidFromTreasury,TGB,10 +CompanyDoesNotPayDividend,TGB +PRICE_MOVES_LOG,TGB,100,E1,90,D1 +BuysTrain,TGB,2,GT,140 +BuysTrain,TGB,4,IPO,350 +FirstTrainBought,4 +StartOfPhase,4 +TrainsRusted,2 + +CompanyOperates,CV,Ron +LaysTileAt,CV,9,M12,SW +CompanyDoesNotPayDividend,CV +PRICE_MOVES_LOG,CV,90,E2,80,D2 +BuysTrain,CV,4,IPO,350 + +CompanyOperates,THB,Tyler +LaysTileAtFor,THB,59,L15,SW,40 +CompanyDoesNotPayDividend,THB +PRICE_MOVES_LOG,THB,80,E3,75,D3 +CompanyTakesLoan,THB,100,90 +BuysTrain,THB,4,IPO,350 + +CompanyOperates,GT,Justin +LaysTileAt,GT,8,O8,SE +CompanyRevenue,GT,110 +CompanyMustPayLoanInterest,GT,40 +InterestPaidFromTreasury,GT,40 +CompanyPaysOutFull,GT,110 +Payout,Justin,44,4,10 +Payout,GT,33,3,10 +PRICE_MOVES_LOG,GT,70,G7,75,G6 +BuysTrain,GT,4,TGB,1 + +CompanyOperates,CA,Lonny +LaysTileAt,CA,8,C16,N +CompanyRevenue,CA,90 +CompanyMustPayLoanInterest,CA,20 +InterestPaidFromTreasury,CA,20 +CompanyWithholds,CA,90 +PRICE_MOVES_LOG,CA,65,E6,60,D6 + +CompanyOperates,WR,Tyler +CompanyTakesLoan,WR,100,100 +LaysTileAtFor,WR,8,N15,SE,40 +CompanyRevenue,WR,100 +CompanyMustPayLoanInterest,WR,40 +InterestPaidFromTreasury,WR,40 +CompanyPaysOutFull,WR,100 +Payout,Tyler,50,5,10 +Payout,WR,20,2,10 +PRICE_MOVES_LOG,WR,60,F8,65,F7 + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,8,E16,SE +CompanyRevenue,LPS,180 +CompanyMustPayLoanInterest,LPS,40 +InterestPaidFromTreasury,LPS,40 +CompanyPaysOutFull,LPS,180 +Payout,Lonny,108,6,10 +Payout,LPS,72,4,10 +PRICE_MOVES_LOG,LPS,60,F8,65,F7 +BuysTrain,LPS,3,CA,1 +CompanyRepaysLoans,LPS,100,100,1,100 + +EndOfOperatingRound,4.1 +ORWorthIncrease,Lonny,4.1,188 +ORWorthIncrease,Tyler,4.1,-15 +ORWorthIncrease,Ron,4.1,0 +ORWorthIncrease,Justin,4.1,-16 +Has,GT,157 +Has,THB,60 +Has,LPS,10 +Has,WR,67 +Has,CV,150 +Has,CA,112 +Has,TGB,1 +Has,Lonny,129 +Has,Tyler,115 +Has,Ron,65 +Has,Justin,72 +START_OR,4.2 +ReceivesFor,Tyler,5,Flos +ReceivesFor,GT,10,W&SR +ReceivesFor,WR,10,TCC +ReceivesFor,GT,15,Ship +ReceivesFor,Ron,20,Brdg +ReceivesFor,Ron,20,Tunn + +CompanyOperates,TGB,Justin +LaysTileAt,TGB,8,L7,SE +CompanyTakesLoan,TGB,100,100 +InterestPaidFromTreasury,TGB,20 +CompanyDoesNotPayDividend,TGB +PRICE_MOVES_LOG,TGB,90,D1,80,C1 + +CompanyOperates,CV,Ron +LaysTileAt,CV,57,L13,SW +LAYS_TOKEN_ON,CV,L13,40 +CompanyRevenue,CV,80 +CompanyPaysOutFull,CV,80 +Payout,Ron,32,4,10 +Payout,CV,8,1,10 +PRICE_MOVES_LOG,CV,80,D2,90,E2 +BuysPrivateFromFor,CV,Tunn,Ron,118 +AcquiresBonus,CV,Tunnel,10,B13 + +CompanyOperates,GT,Justin +LaysTileAt,GT,58,N9,NE +LaysBonusTokenOn,GT,Port,20,H5 +PrivateCloses,Ship +CompanyRevenue,GT,230 +CompanyMustPayLoanInterest,GT,40 +InterestPaidFromTreasury,GT,40 +CompanyPaysOutFull,GT,230 +Payout,Justin,92,4,10 +Payout,GT,69,3,10 +PRICE_MOVES_LOG,GT,75,G6,80,H6 + +CompanyOperates,THB,Tyler +LaysTileAtFor,THB,8,M16,NW,40 +CompanyRevenue,THB,110 +CompanyMustPayLoanInterest,THB,10 +InterestPaidFromTreasury,THB,10 +CompanyPaysOutFull,THB,110 +Payout,Tyler,33,3,10 +Payout,THB,11,1,10 +PRICE_MOVES_LOG,THB,75,D3,80,E3 + +CompanyOperates,WR,Tyler +DestinationReached,WR,L15 +ReleasedFromEscrow,WR,130 +LaysTileAt,WR,15,O18,NW +CompanyRevenue,WR,110 +CompanyMustPayLoanInterest,WR,40 +InterestPaidFromTreasury,WR,40 +CompanyPaysOutFull,WR,110 +Payout,Tyler,55,5,10 +Payout,WR,22,2,10 +PRICE_MOVES_LOG,WR,65,F7,70,G7 +BuysPrivateFromFor,WR,Flos,Tyler,40 +CompanyRepaysLoans,WR,100,100,1,100 + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,5,F17,NE +DestinationReached,LPS,F17 +ReleasedFromEscrow,LPS,325 +CompanyRevenue,LPS,260 +CompanyMustPayLoanInterest,LPS,30 +InterestPaidFromTreasury,LPS,30 +CompanyPaysOutFull,LPS,260 +Payout,Lonny,156,6,10 +Payout,LPS,104,4,10 +PRICE_MOVES_LOG,LPS,65,F7,70,G7 +CompanyRepaysLoans,LPS,300,300,3,100 + +CompanyOperates,CA,Lonny +LaysTileAt,CA,8,G14,SE +InterestPaidFromTreasury,CA,20 +CompanyDoesNotPayDividend,CA +PRICE_MOVES_LOG,CA,60,D6,55,C6 +BuysTrain,CA,3,LPS,92 + +EndOfOperatingRound,4.2 +ORWorthIncrease,Lonny,4.2,356 +ORWorthIncrease,Tyler,4.2,203 +ORWorthIncrease,Ron,4.2,130 +ORWorthIncrease,Justin,4.2,32 +Has,GT,211 +Has,THB,21 +Has,LPS,201 +Has,WR,49 +Has,CV,0 +Has,CA,0 +Has,TGB,81 +Has,Lonny,285 +Has,Tyler,248 +Has,Ron,255 +Has,Justin,164 +StartStockRound,5 +HasPriority,Lonny +BUY_SHARE_LOG,Lonny,10,CA,IPO,70 +PriceIsPaidTo,70,CA +BUY_SHARE_LOG,Tyler,10,THB,IPO,90 +PriceIsPaidTo,90,THB +HoldMoneyInEscrow,65,195,GT +BUY_SHARE_LOG,Ron,10,GT,IPO,65 +HoldMoneyInEscrow,65,260,GT +BUY_SHARE_LOG,Justin,10,GT,IPO,65 +BUY_SHARE_LOG,Lonny,10,CA,IPO,70 +PriceIsPaidTo,70,CA +HoldMoneyInEscrow,65,325,GT +BUY_SHARE_LOG,Tyler,10,GT,IPO,65 +HoldMoneyInEscrow,90,90,THB +BUY_SHARE_LOG,Ron,10,THB,IPO,90 +BUY_SHARE_LOG,Justin,10,GT,Pool,80 +HoldMoneyInEscrow,70,70,CA +BUY_SHARE_LOG,Lonny,10,CA,IPO,70 +HoldMoneyInEscrow,90,180,THB +BUY_SHARE_LOG,Tyler,10,THB,IPO,90 +BUY_SHARE_LOG,Ron,10,LPS,Pool,70 +PASSES,Justin +HoldMoneyInEscrow,70,140,CA +BUY_SHARE_LOG,Lonny,10,CA,IPO,70 +PASSES,Tyler +PASSES,Ron +PASSES,Justin +SELL_SHARES_LOG,Lonny,2,10,20,CA,110 +PRICE_MOVES_LOG,CA,55,C6,45,C8 +BUY_SHARE_LOG,Lonny,10,THB,Pool,80 +PASSES,Tyler +PASSES,Ron +PASSES,Justin +SELL_SHARE_LOG,Lonny,10,THB,80 +PRICE_MOVES_LOG,THB,80,E3,75,E4 +BUY_SHARE_LOG,Lonny,10,GT,Pool,80 +PASSES,Tyler +Autopasses,Ron +PASSES,Justin +PASSES,Lonny + +END_SR,5 +Has,GT,211 +Has,THB,111 +Has,LPS,201 +Has,WR,49 +Has,CV,0 +Has,CA,140 +Has,TGB,81 +Has,Lonny,35 +Has,Tyler,3 +Has,Ron,30 +Has,Justin,19 +START_OR,5.1 +ReceivesFor,WR,5,Flos +ReceivesFor,GT,10,W&SR +ReceivesFor,WR,10,TCC +ReceivesFor,Ron,20,Brdg +ReceivesFor,CV,20,Tunn + +CompanyOperates,CV,Ron +LaysTileAt,CV,14,L13,S +CompanyRevenue,CV,90 +CompanyPaysOutFull,CV,90 +Payout,Ron,36,4,10 +Payout,CV,9,1,10 +PRICE_MOVES_LOG,CV,90,E2,100,F2 + +CompanyOperates,GT,Justin +LaysTileAt,GT,24,O8,SE +CompanyRevenue,GT,230 +CompanyMustPayLoanInterest,GT,40 +InterestPaidFromTreasury,GT,40 +CompanyPaysOutFull,GT,230 +Payout,Ron,23,1,10 +Payout,Lonny,23,1,10 +Payout,Tyler,23,1,10 +Payout,Justin,138,6,10 +Payout,GT,23,1,10 +PRICE_MOVES_LOG,GT,80,H6,90,I6 +CompanyRepaysLoans,GT,200,200,2,100 + +CompanyOperates,TGB,Justin +CompanyTakesLoan,TGB,100,100 +LaysTileAt,TGB,8,M8,NW +InterestPaidFromTreasury,TGB,30 +CompanyDoesNotPayDividend,TGB +PRICE_MOVES_LOG,TGB,80,C1,75,B1 + +CompanyOperates,THB,Tyler +LaysTileAt,THB,24,M16,NW +CompanyRevenue,THB,130 +CompanyMustPayLoanInterest,THB,10 +InterestPaidFromTreasury,THB,10 +CompanyPaysOutFull,THB,130 +Payout,Ron,13,1,10 +Payout,Tyler,65,5,10 +Payout,THB,13,1,10 +PRICE_MOVES_LOG,THB,75,E4,80,F4 +CompanyRepaysLoans,THB,100,100,1,100 + +CompanyOperates,WR,Tyler +CompanyRevenue,WR,110 +CompanyMustPayLoanInterest,WR,30 +InterestPaidFromTreasury,WR,30 +CompanyPaysOutFull,WR,110 +Payout,Tyler,55,5,10 +Payout,WR,22,2,10 +PRICE_MOVES_LOG,WR,70,G7,75,G6 +CompanyTakesLoan,WR,100,90 + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,121,F15,SW +CompanyRevenue,LPS,190 +CompanyPaysOutFull,LPS,190 +Payout,Ron,19,1,10 +Payout,Lonny,114,6,10 +Payout,LPS,57,3,10 +PRICE_MOVES_LOG,LPS,70,G7,75,G6 + +CompanyOperates,CA,Lonny +LaysTileAt,CA,25,E16,SW +CompanyRevenue,CA,100 +CompanyMustPayLoanInterest,CA,20 +InterestPaidFromTreasury,CA,20 +CompanyPaysOutFull,CA,100 +Payout,Lonny,40,4,10 +Payout,CA,30,3,10 +PRICE_MOVES_LOG,CA,45,C8,50,D8 +CompanyTakesLoan,CA,100,90 + +EndOfOperatingRound,5.1 +ORWorthIncrease,Lonny,5.1,217 +ORWorthIncrease,Tyler,5.1,223 +ORWorthIncrease,Ron,5.1,201 +ORWorthIncrease,Justin,5.1,258 +Has,GT,4 +Has,THB,14 +Has,LPS,258 +Has,WR,146 +Has,CV,29 +Has,CA,240 +Has,TGB,151 +Has,Lonny,212 +Has,Tyler,146 +Has,Ron,141 +Has,Justin,157 +START_OR,5.2 +ReceivesFor,WR,5,Flos +ReceivesFor,GT,10,W&SR +ReceivesFor,WR,10,TCC +ReceivesFor,Ron,20,Brdg +ReceivesFor,CV,20,Tunn + +CompanyOperates,CV,Ron +LaysTileAt,CV,8,L11,S +CompanyRevenue,CV,90 +CompanyPaysOutFull,CV,90 +Payout,Ron,36,4,10 +Payout,CV,9,1,10 +PRICE_MOVES_LOG,CV,100,F2,110,G2 + +CompanyOperates,GT,Justin +DestinationReached,GT,K8 +ReleasedFromEscrow,GT,325 +LaysTileAt,GT,8,N7,SE +CompanyRevenue,GT,230 +CompanyMustPayLoanInterest,GT,20 +InterestPaidFromTreasury,GT,20 +CompanyPaysOutFull,GT,230 +Payout,Ron,23,1,10 +Payout,Lonny,23,1,10 +Payout,Tyler,23,1,10 +Payout,Justin,138,6,10 +Payout,GT,23,1,10 +PRICE_MOVES_LOG,GT,90,I6,100,I5 + +CompanyOperates,THB,Tyler +CompanyRevenue,THB,130 +CompanyWithholds,THB,130 +PRICE_MOVES_LOG,THB,80,F4,75,E4 +BuysTrain,THB,3,WR,144 + +CompanyOperates,WR,Tyler +InterestPaidFromTreasury,WR,40 +CompanyDoesNotPayDividend,WR +PRICE_MOVES_LOG,WR,75,G6,70,F6 +CompanyTakesLoan,WR,100,90 +BuysTrain,WR,4,IPO,350 +All 4-trains are sold out, 5-trains now available + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,7,E14,SE +CompanyRevenue,LPS,200 +CompanyPaysOutFull,LPS,200 +Payout,Ron,20,1,10 +Payout,Lonny,120,6,10 +Payout,LPS,60,3,10 +PRICE_MOVES_LOG,LPS,75,G6,80,H6 + +CompanyOperates,TGB,Justin +LaysTileAt,TGB,14,K8,SW +InterestPaidFromTreasury,TGB,30 +CompanyDoesNotPayDividend,TGB +PRICE_MOVES_LOG,TGB,75,B1,70,A1 +CompanyTakesLoan,TGB,100,90 +BuysTrain,TGB,3,GT,211 + +CompanyOperates,CA,Lonny +LaysTileAt,CA,5,H15,N +DestinationReached,CA,H15 +ReleasedFromEscrow,CA,140 +CompanyRevenue,CA,110 +CompanyMustPayLoanInterest,CA,30 +InterestPaidFromTreasury,CA,30 +CompanyPaysOutFull,CA,110 +Payout,Lonny,44,4,10 +Payout,CA,33,3,10 +PRICE_MOVES_LOG,CA,50,D8,55,E8 +CompanyTakesLoan,CA,100,90 +BuysTrain,CA,3,LPS,473 + +EndOfOperatingRound,5.2 +ORWorthIncrease,Lonny,5.2,207 +ORWorthIncrease,Tyler,5.2,-67 +ORWorthIncrease,Ron,5.2,149 +ORWorthIncrease,Justin,5.2,138 +Has,GT,553 +Has,THB,0 +Has,LPS,791 +Has,WR,5 +Has,CV,58 +Has,CA,0 +Has,TGB,0 +Has,Lonny,399 +Has,Tyler,169 +Has,Ron,240 +Has,Justin,295 +StartStockRound,6 +HasPriority,Tyler +BUY_SHARE_LOG,Tyler,10,GT,Pool,100 +HoldMoneyInEscrow,100,100,CV +BUY_SHARE_LOG,Ron,10,CV,IPO,100 +SELL_SHARES_LOG,Justin,2,10,20,TGB,140 +PRICE_MOVES_LOG,TGB,70,A1,60,A3 +BUY_SHARE_LOG,Justin,10,LPS,Pool,80 +SELL_SHARE_LOG,Lonny,10,GT,100 +PRICE_MOVES_LOG,GT,100,I5,90,I6 +SELL_SHARES_LOG,Lonny,2,10,20,CA,110 +PRICE_MOVES_LOG,CA,55,E8,45,E10 +START_COMPANY_LOG,Lonny,GW,100,200,2,20,GW +BUY_SHARE_LOG,Tyler,10,WR,IPO,65 +PriceIsPaidTo,65,WR +HoldMoneyInEscrow,100,200,CV +BUY_SHARE_LOG,Ron,10,CV,IPO,100 +BUY_SHARE_LOG,Justin,10,CA,Pool,45 +HoldMoneyInEscrow,100,300,CV +BUY_SHARE_LOG,Lonny,10,CV,IPO,100 +PASSES,Tyler +Autopasses,Ron +BUY_SHARE_LOG,Justin,10,CA,Pool,45 +SELL_SHARE_LOG,Lonny,10,CV,110 +PRICE_MOVES_LOG,CV,110,G2,100,G3 +BUY_SHARE_LOG,Lonny,10,GW,IPO,100 +PriceIsPaidTo,100,GW +Autopasses,Tyler +Autopasses,Ron +BUY_SHARE_LOG,Justin,10,CA,Pool,45 +IS_NOW_PRES_OF,Justin,CA +BUY_SHARE_LOG,Lonny,10,GW,IPO,100 +PriceIsPaidTo,100,GW +Autopasses,Tyler +Autopasses,Ron +BUY_SHARE_LOG,Justin,10,CA,Pool,45 +BUY_SHARE_LOG,Lonny,10,GW,IPO,100 +PriceIsPaidTo,100,GW +Floats,GW +Autopasses,Tyler +Autopasses,Ron +BUY_SHARE_LOG,Justin,10,CA,Pool,45 +BUY_SHARE_LOG,Lonny,10,THB,Pool,75 +Autopasses,Tyler +Autopasses,Ron +BUY_SHARE_LOG,Justin,10,LPS,Pool,80 +SELL_SHARE_LOG,Lonny,10,THB,75 +PRICE_MOVES_LOG,THB,75,E4,70,E5 +BUY_SHARE_LOG,Lonny,10,GW,IPO,100 +PriceIsPaidTo,100,GW +Autopasses,Tyler +Autopasses,Ron +PASSES,Justin +PASSES,Lonny + +END_SR,6 +Has,GT,553 +Has,THB,0 +Has,LPS,791 +Has,WR,70 +Has,CV,58 +Has,CA,0 +Has,TGB,0 +Has,GW,600 +Has,Lonny,19 +Has,Tyler,4 +Has,Ron,40 +Has,Justin,50 +START_OR,6.1 +ReceivesFor,WR,5,Flos +ReceivesFor,GT,10,W&SR +ReceivesFor,WR,10,TCC +ReceivesFor,Ron,20,Brdg +ReceivesFor,CV,20,Tunn + +CompanyOperates,CV,Ron +LaysTileAtFor,CV,9,K14,SW,40 +CompanyRevenue,CV,90 +CompanyPaysOutFull,CV,90 +Payout,Ron,54,6,10 +Payout,CV,18,2,10 +PRICE_MOVES_LOG,CV,100,G3,110,H3 + +CompanyOperates,GW,Lonny +LaysTileAt,GW,14,H15,SW +LAYS_TOKEN_ON,GW,H15,40 +CompanyDoesNotPayDividend,GW +PRICE_MOVES_LOG,GW,100,E1,90,D1 +BuysTrain,GW,5,IPO,550 +FirstTrainBought,5 +StartOfPhase,5 +PrivateCloses,Flos +PrivateCloses,W&SR +PrivateCloses,TCC +PrivateCloses,Brdg +PrivateCloses,Tunn + +CompanyOperates,GT,Justin +LaysTileAt,GT,122,N11,NE +CompanyRevenue,GT,150 +CompanyMustPayLoanInterest,GT,20 +InterestPaidFromTreasury,GT,20 +CompanyPaysOutFull,GT,150 +Payout,Ron,15,1,10 +Payout,Justin,90,6,10 +Payout,Tyler,30,2,10 +Payout,GT,15,1,10 +PRICE_MOVES_LOG,GT,90,I6,100,I5 +BuysTrain,GT,5,IPO,550 + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,63,D17,S +CompanyRevenue,LPS,120 +CompanyPaysOutFull,LPS,120 +Payout,Lonny,72,6,10 +Payout,Ron,12,1,10 +Payout,Justin,24,2,10 +Payout,LPS,12,1,10 +PRICE_MOVES_LOG,LPS,80,H6,90,I6 +BuysTrain,LPS,5,IPO,550 +All 5-trains are sold out, 6-trains now available + +CompanyOperates,WR,Tyler +LaysTileAt,WR,64,L15,N +CompanyRevenue,WR,150 +CompanyMustPayLoanInterest,WR,50 +InterestPaidFromTreasury,WR,50 +CompanyPaysOutFull,WR,150 +Payout,Tyler,90,6,10 +Payout,WR,30,2,10 +PRICE_MOVES_LOG,WR,70,F6,75,G6 + +CompanyOperates,THB,Tyler +LaysTileAt,THB,5,J15,SE +CompanyRevenue,THB,310 +CompanyPaysOutFull,THB,310 +Payout,Ron,31,1,10 +Payout,Tyler,155,5,10 +Payout,THB,31,1,10 +PRICE_MOVES_LOG,THB,70,E5,75,F5 + +CompanyOperates,TGB,Justin +LaysTileAt,TGB,125,P9,S +CompanyRevenue,TGB,150 +CompanyMustPayLoanInterest,TGB,40 +InterestPaidFromRevenue,TGB,40,40 +CompanyWithholds,TGB,110 +PRICE_MOVES_LOG,TGB,60,A3,55,A4 +CompanyRepaysLoans,TGB,110,200,2,100 +CompanyRepaysLoansWithPresCash,TGB,90,200,2,100,Justin + +CompanyOperates,CA,Justin +LaysTileAt,CA,2,I14,N +CompanyTakesLoan,CA,100,100 +BuysBonusTokenFrom,CA,Tunnel,10,BANK,50 +CompanyRevenue,CA,260 +CompanyMustPayLoanInterest,CA,50 +InterestPaidFromTreasury,CA,50 +CompanyPaysOutFull,CA,260 +Payout,Lonny,52,2,10 +Payout,Justin,130,5,10 +PRICE_MOVES_LOG,CA,45,E10,50,E9 + +EndOfOperatingRound,6.1 +ORWorthIncrease,Lonny,6.1,114 +ORWorthIncrease,Tyler,6.1,350 +ORWorthIncrease,Ron,6.1,117 +ORWorthIncrease,Justin,6.1,239 +Has,GT,8 +Has,THB,31 +Has,LPS,253 +Has,WR,65 +Has,CV,56 +Has,CA,0 +Has,TGB,0 +Has,GW,10 +Has,Lonny,143 +Has,Tyler,279 +Has,Ron,172 +Has,Justin,204 +START_OR,6.2 + +CompanyOperates,CV,Ron +LaysTileAt,CV,14,J15,S +CompanyRevenue,CV,160 +CompanyPaysOutFull,CV,160 +Payout,Ron,96,6,10 +Payout,CV,32,2,10 +PRICE_MOVES_LOG,CV,110,H3,125,I3 +CompanyTakesLoan,CV,100,90 + +CompanyOperates,GT,Justin +LaysTileAt,GT,24,O10,SW +CompanyRevenue,GT,310 +CompanyMustPayLoanInterest,GT,20 +InterestPaidFromRevenue,GT,20,20 +CompanyPaysOutFull,GT,290 +Payout,Ron,29,1,10 +Payout,Tyler,58,2,10 +Payout,Justin,174,6,10 +Payout,GT,29,1,10 +PRICE_MOVES_LOG,GT,100,I5,110,J5 + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,126,F15,S +CompanyRevenue,LPS,330 +CompanyPaysOutFull,LPS,330 +Payout,Ron,33,1,10 +Payout,Lonny,198,6,10 +Payout,Justin,66,2,10 +Payout,LPS,33,1,10 +PRICE_MOVES_LOG,LPS,90,I6,100,I5 + +CompanyOperates,GW,Lonny +LaysTileAt,GW,63,H15,S +CompanyRevenue,GW,170 +CompanyPaysOutFull,GW,170 +Payout,Lonny,102,6,10 +PRICE_MOVES_LOG,GW,90,D1,100,E1 + +CompanyOperates,WR,Tyler +LaysTileAt,WR,66,N17,SW +CompanyRevenue,WR,150 +CompanyMustPayLoanInterest,WR,50 +InterestPaidFromTreasury,WR,50 +CompanyPaysOutFull,WR,150 +Payout,Tyler,90,6,10 +Payout,WR,30,2,10 +PRICE_MOVES_LOG,WR,75,G6,80,H6 + +CompanyOperates,THB,Tyler +LaysTileAt,THB,57,J13,S +CompanyRevenue,THB,310 +CompanyPaysOutFull,THB,310 +Payout,Ron,31,1,10 +Payout,Tyler,155,5,10 +Payout,THB,31,1,10 +PRICE_MOVES_LOG,THB,75,F5,80,G5 + +CompanyOperates,TGB,Justin +LaysTileAt,TGB,63,K8,S +CompanyRevenue,TGB,160 +CompanyMustPayLoanInterest,TGB,20 +InterestPaidFromRevenue,TGB,20,20 +CompanyPaysOutFull,TGB,140 +Payout,Justin,28,2,10 +Payout,TGB,28,2,10 +PRICE_MOVES_LOG,TGB,55,A4,60,B4 + +CompanyOperates,CA,Justin +CompanyTakesLoan,CA,100,100 +LaysTileAt,CA,7,I16,SW +CompanyRevenue,CA,270 +CompanyMustPayLoanInterest,CA,60 +InterestPaidFromTreasury,CA,60 +CompanyPaysOutFull,CA,270 +Payout,Lonny,54,2,10 +Payout,Justin,135,5,10 +PRICE_MOVES_LOG,CA,50,E9,55,E8 + +EndOfOperatingRound,6.2 +ORWorthIncrease,Lonny,6.2,474 +ORWorthIncrease,Tyler,6.2,378 +ORWorthIncrease,Ron,6.2,244 +ORWorthIncrease,Justin,6.2,493 +Has,GT,37 +Has,THB,62 +Has,LPS,286 +Has,WR,45 +Has,CV,178 +Has,CA,40 +Has,TGB,28 +Has,GW,10 +Has,Lonny,497 +Has,Tyler,582 +Has,Ron,361 +Has,Justin,607 +StartStockRound,7 +HasPriority,Tyler +START_COMPANY_LOG,Tyler,WGB,100,200,2,20,BANK +BUY_SHARE_LOG,Ron,10,WR,IPO,65 +PriceIsPaidTo,65,WR +START_COMPANY_LOG,Justin,CPR,100,200,2,20,BANK +HoldMoneyInEscrow,100,400,CV +BUY_SHARE_LOG,Lonny,10,CV,IPO,100 +BUY_SHARE_LOG,Tyler,10,WGB,IPO,100 +BUY_SHARE_LOG,Ron,10,GW,IPO,100 +PriceIsPaidTo,100,GW +HoldMoneyInEscrow,100,500,CV +BUY_SHARE_LOG,Justin,10,CV,IPO,100 +SELL_SHARE_LOG,Lonny,10,CV,125 +PRICE_MOVES_LOG,CV,125,I3,110,I4 +SELL_SHARES_LOG,Lonny,2,10,20,CA,110 +PRICE_MOVES_LOG,CA,55,E8,45,E10 +START_COMPANY_LOG,Lonny,BBG,100,200,2,20,BANK +BUY_SHARE_LOG,Tyler,10,WGB,IPO,100 +BUY_SHARE_LOG,Ron,10,CA,Pool,45 +SELL_SHARE_LOG,Justin,10,CV,110 +PRICE_MOVES_LOG,CV,110,I4,100,I5 +BUY_SHARE_LOG,Justin,10,WR,IPO,65 +PriceIsPaidTo,65,WR +BUY_SHARE_LOG,Lonny,10,BBG,IPO,100 +BUY_SHARE_LOG,Tyler,10,WGB,IPO,100 +BUY_SHARE_LOG,Ron,10,LPS,Pool,100 +SELL_SHARE_LOG,Justin,10,WR,80 +BUY_SHARE_LOG,Justin,10,CPR,IPO,100 +BUY_SHARE_LOG,Lonny,10,BBG,IPO,100 +SELL_SHARE_LOG,Tyler,10,WR,80 +BUY_SHARE_LOG,Tyler,10,WGB,IPO,100 +FloatsWithCash,WGB,1000 +PASSES,Ron +BUY_SHARE_LOG,Justin,10,CPR,IPO,100 +BUY_SHARE_LOG,Lonny,10,BBG,IPO,100 +BUY_SHARE_LOG,Tyler,10,CA,Pool,45 +PASSES,Ron +BUY_SHARE_LOG,Justin,10,CPR,IPO,100 +BUY_SHARE_LOG,Lonny,10,BBG,IPO,100 +FloatsWithCash,BBG,1000 +PASSES,Tyler +PASSES,Ron +BUY_SHARE_LOG,Justin,10,CPR,IPO,100 +FloatsWithCash,CPR,1000 +PASSES,Lonny +PASSES,Tyler +PASSES,Ron +PASSES,Justin + +END_SR,7 +PRICE_MOVES_LOG,LPS,100,I5,110,I4 +SoldOut,LPS,100,I5,110,I4 +Has,GT,37 +Has,THB,62 +Has,BBG,1000 +Has,LPS,286 +Has,WGB,1000 +Has,WR,175 +Has,CV,178 +Has,CPR,1000 +Has,CA,40 +Has,TGB,28 +Has,GW,110 +Has,Lonny,32 +Has,Tyler,17 +Has,Ron,51 +Has,Justin,32 +START_OR,7.1 + +CompanyOperates,GT,Justin +LaysTileAt,GT,8,K6,NE +CompanyRevenue,GT,310 +CompanyMustPayLoanInterest,GT,20 +InterestPaidFromTreasury,GT,20 +CompanyPaysOutFull,GT,310 +Payout,Justin,186,6,10 +Payout,Tyler,62,2,10 +Payout,Ron,31,1,10 +Payout,GT,31,1,10 +PRICE_MOVES_LOG,GT,110,J5,125,K5 + +CompanyOperates,LPS,Lonny +LaysTileAt,LPS,125,C14,N +CompanyRevenue,LPS,360 +CompanyPaysOutFull,LPS,360 +Payout,Lonny,216,6,10 +Payout,Justin,72,2,10 +Payout,Ron,72,2,10 +PRICE_MOVES_LOG,LPS,110,I4,125,J4 + +CompanyOperates,CV,Ron +LaysTileAt,CV,1,M10,SE +CompanyRevenue,CV,170 +CompanyMustPayLoanInterest,CV,10 +InterestPaidFromTreasury,CV,10 +CompanyPaysOutFull,CV,170 +Payout,Ron,102,6,10 +Payout,CV,68,4,10 +PRICE_MOVES_LOG,CV,100,I5,110,J5 +CompanyTakesLoan,CV,100,90 +BuysBonusTokenFrom,CV,Bridge,10,BANK,50 +BuysBonusTokenFrom,CV,Tunnel,10,BANK,50 + +CompanyOperates,GW,Lonny +LaysTileAt,GW,15,F17,SW +CompanyRevenue,GW,180 +CompanyPaysOutFull,GW,180 +Payout,Lonny,108,6,10 +Payout,Ron,18,1,10 +PRICE_MOVES_LOG,GW,100,E1,110,F1 + +CompanyOperates,WGB,Tyler +LaysTileAt,WGB,5,J11,NW +LAYS_TOKEN_ON,WGB,J15,40 +CompanyDoesNotPayDividend,WGB +PRICE_MOVES_LOG,WGB,100,E1,90,D1 +BuysTrain,WGB,6,IPO,700 +FirstTrainBought,6 +StartOfPhase,6 +TrainsRusted,3 +DestinationReached,THB,J11 +ReleasedFromEscrow,THB,180 +BuysTrain,WGB,4,THB,250 +StartFormationRound,CGR +StartingPlayer,Tyler + +CompanyHasLoans,WR,Tyler,5,100,500 +CompanyRepaysLoans,WR,100,500,1,100 +WillMergeInto,WR,CGR + +CompanyHasLoans,CV,Ron,2,100,200 +CompanyRepaysLoans,CV,200,200,2,100 + +CompanyHasLoans,GT,Justin,2,100,200 +CompanyRepaysLoans,GT,48,2,100 +CompanyRepaysLoansWithPresCash,GT,152,200,2,100,Justin + +CompanyHasLoans,TGB,Justin,2,100,200 +WillMergeInto,TGB,CGR + +CompanyHasLoans,CA,Justin,6,100,600 +WillMergeInto,CA,CGR +HasMergedShares,Tyler,6,3,CGR +HasMergedShares,Ron,2,1,CGR +HasMergedShares,Justin,7,3,CGR +HasPutShareInPool,Justin +HasMergedShares,POOL,7,3,CGR + +CompanyHasShares,CGR,10,10 +IS_NOW_PRES_OF,Tyler,CGR +Floats,CGR +ExchangesBaseToken,CGR,WR,O16/1 +ExchangesBaseToken,CGR,TGB,K8/1 +ExchangesBaseToken,CGR,CA,D17/1 +CompanyDiscardsTrain,CGR,4,Pool +Has,GT,0 +Has,THB,492 +Has,BBG,1000 +Has,LPS,286 +Has,WGB,10 +Has,CV,26 +Has,CPR,1000 +Has,CGR,143 +Has,GW,110 +Has,Lonny,356 +Has,Tyler,79 +Has,Ron,274 +Has,Justin,138 +EndOfFormationRound,CGR,OperatingRound 7.1 +CanOperate,CGR +CertificateLimit,18,4,9 + +CompanyOperates,CGR,Tyler From ef0fd8c59d1416e7369bdb50910191ee94cfcc4a Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sun, 21 Oct 2018 16:37:09 +0200 Subject: [PATCH 06/45] Changing Version Identifier --- src/main/resources/build/version.number | 2 +- src/main/resources/version.number | 4 ++-- .../data/bugs/1835_changePresidentAtStart.report | 16 ++++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/resources/build/version.number b/src/main/resources/build/version.number index ae5c23723..9ff57a5d1 100644 --- a/src/main/resources/build/version.number +++ b/src/main/resources/build/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC2 +version=2.0.RC4 # the following string "@DEVELOP@" is replaced by an empty string in the release version # this is done automatically by gradle develop=@DEVELOP@ diff --git a/src/main/resources/version.number b/src/main/resources/version.number index e0838456b..38116003b 100644 --- a/src/main/resources/version.number +++ b/src/main/resources/version.number @@ -1,8 +1,8 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC2 +version=2.0.RC4 # the following string "" is replaced by an empty string in the release version # this is done automatically by gradle develop= # the following string "@ BUILDDATE @" is replaced by the build date -buildDate=2017-07-07 +buildDate=2018-10-07 diff --git a/src/test/resources/data/bugs/1835_changePresidentAtStart.report b/src/test/resources/data/bugs/1835_changePresidentAtStart.report index af60a86e3..4c83fc832 100644 --- a/src/test/resources/data/bugs/1835_changePresidentAtStart.report +++ b/src/test/resources/data/bugs/1835_changePresidentAtStart.report @@ -1,5 +1,5 @@ GameIs,1835 -PlayerIs,1,Klaus-Jürgen +PlayerIs,1,Klaus-Jürgen PlayerIs,2,Jupp PlayerIs,3,Sven K. PlayerIs,4,Volker S. @@ -15,9 +15,9 @@ BuysItemFor,Sven K.,M2,170 FloatsWithCash,M2,170 BuysItemFor,Jupp,M5,80 FloatsWithCash,M5,80 -BuysItemFor,Klaus-Jürgen,M1,80 +BuysItemFor,Klaus-Jürgen,M1,80 FloatsWithCash,M1,80 -BuysItemFor,Klaus-Jürgen,M6,80 +BuysItemFor,Klaus-Jürgen,M6,80 FloatsWithCash,M6,80 BuysItemFor,Jupp,LD,190 ALSO_GETS,Jupp,PRES_CERT_NAME,SX,20 @@ -25,12 +25,12 @@ BuysItemFor,Sven K.,M4,160 FloatsWithCash,M4,160 BuysItemFor,Volker S.,NF,100 ALSO_GETS,Volker S.,CERT_NAME,BY,10 -BuysItemFor,Klaus-Jürgen,BB,130 +BuysItemFor,Klaus-Jürgen,BB,130 BuysItemFor,Jupp,HB,160 PASSES,Sven K. BuysItemFor,Volker S.,OBB,120 ALSO_GETS,Volker S.,CERT_NAME,BY,10 -BuysItemFor,Klaus-Jürgen,PRES_CERT_NAME,BY,20,184 +BuysItemFor,Klaus-Jürgen,PRES_CERT_NAME,BY,20,184 CannotBuyAnything,Jupp CannotBuyAnything,Sven K. BuysItemFor,Volker S.,PfB,150 @@ -44,11 +44,11 @@ Has,M4,160 Has,M5,80 Has,M6,80 Has,BY,460 -Has,Klaus-Jürgen,1 +Has,Klaus-Jürgen,1 Has,Jupp,45 Has,Sven K.,145 Has,Volker S.,25 StartStockRound,1 -HasPriority,Klaus-Jürgen -PASSES,Klaus-Jürgen +HasPriority,Klaus-Jürgen +PASSES,Klaus-Jürgen PASSES,Jupp From 1b740d98cee0cc13b6781fd84dda8e7c16093e3e Mon Sep 17 00:00:00 2001 From: Larry North Date: Thu, 25 Oct 2018 15:48:52 -0500 Subject: [PATCH 07/45] Fix Gradle build errors (#67) --- build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle b/build.gradle index 770798dd6..f261467fc 100644 --- a/build.gradle +++ b/build.gradle @@ -95,6 +95,14 @@ dependencies { testCompile fileTree(dir: 'libs/test', include: "**/*.jar") } +test { + // the expected test files have UTF-8 encoding + systemProperty 'file.encoding', 'UTF-8' + + // TestGame is not intended as a standalone test class + exclude 'net/sf/rails/test/TestGame.class' +} + jar { def manifestClasspath = configurations.runtime.collect{ './' + it.getName() }.join(' ') manifest { From 9f57573e3085235cf7d90fd9bdb1215be324cf8d Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 10 Nov 2018 12:15:27 +0100 Subject: [PATCH 08/45] Rails was not recognising a connection between an investor and the major company if the route was blocked by a token of another major company. This has been corrected --- .../net/sf/rails/algorithms/NetworkGraph.java | 16 +++++++++ .../game/specific/_1880/Investor_1880.java | 33 +++++++++++++++++-- .../specific/_1880/OperatingRound_1880.java | 17 +++------- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/sf/rails/algorithms/NetworkGraph.java b/src/main/java/net/sf/rails/algorithms/NetworkGraph.java index 1d4875fd1..69785d14d 100755 --- a/src/main/java/net/sf/rails/algorithms/NetworkGraph.java +++ b/src/main/java/net/sf/rails/algorithms/NetworkGraph.java @@ -473,4 +473,20 @@ public void visualize(String title) { } } + /** + * @return a map of all hexes and stations that cannot be run through + */ + public Multimap getNonPassableStations() { + + ImmutableMultimap.Builder hexStations = + ImmutableMultimap.builder(); + + for(NetworkVertex vertex:graph.vertexSet()) { + if (vertex.isStation() && vertex.isSink()) { + hexStations.put(vertex.getHex(), vertex.getStation()); + } + } + return hexStations.build(); + } + } diff --git a/src/main/java/net/sf/rails/game/specific/_1880/Investor_1880.java b/src/main/java/net/sf/rails/game/specific/_1880/Investor_1880.java index e2f6cf2bb..cefad74a8 100644 --- a/src/main/java/net/sf/rails/game/specific/_1880/Investor_1880.java +++ b/src/main/java/net/sf/rails/game/specific/_1880/Investor_1880.java @@ -12,18 +12,22 @@ import net.sf.rails.common.parser.ConfigurationException; import net.sf.rails.game.BaseToken; import net.sf.rails.game.CompanyManager; +import net.sf.rails.game.HexSidesSet; +import net.sf.rails.game.MapHex; import net.sf.rails.game.Player; import net.sf.rails.game.PublicCompany; import net.sf.rails.game.RailsItem; import net.sf.rails.game.RailsRoot; +import net.sf.rails.game.Station; import net.sf.rails.game.Stop; import net.sf.rails.game.Train; import net.sf.rails.game.TrainManager; import net.sf.rails.game.state.Owner; -import net.sf.rails.game.state.State; - import org.jgrapht.graph.SimpleGraph; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Multimap; + public class Investor_1880 extends PublicCompany implements RevenueStaticModifier { @@ -116,6 +120,8 @@ public int getCurrentTrainLimit() { } public boolean isConnectedToLinkedCompany() { + Multimap lStations; + Multimap iStations; NetworkGraph nwGraph = NetworkGraph.createMapGraph(getRoot()); NetworkGraph companyGraph = NetworkGraph.createRouteGraph(nwGraph, this, true); @@ -123,9 +129,20 @@ public boolean isConnectedToLinkedCompany() { companyGraph.getGraph(); Set verticies = graph.vertexSet(); + + PublicCompany_1880 linkedCompany = (PublicCompany_1880) ((Investor_1880) this).getLinkedCompany(); + if (linkedCompany != null) { + NetworkGraph linkedCompanyGraph=NetworkGraph.createRouteGraph(nwGraph, linkedCompany, true); + // Creating a list of stations blocked by tokens. + // The connection between investor and Linked Company is NOT blocked by any token of any company. + // A token that is counted as blocked can be reached by the company for which it blocks the route. + // Based on that logic a blocking token is reachable by both actors. + lStations = linkedCompanyGraph.getNonPassableStations(); + iStations = companyGraph.getNonPassableStations(); + //Case A) the token in Question from a linked Company is actually on the route of the Investor for (BaseToken token : linkedCompany.getLaidBaseTokens()) { Owner holder = token.getOwner(); if (!(holder instanceof Stop)) continue; @@ -139,6 +156,18 @@ public boolean isConnectedToLinkedCompany() { } } } + // Case B) the Blocking Token is not from the linked Company + // so we need to check if the MapHex of a blocking station is showing up in the + // List of non Passable Stations + for (MapHex blockedHex:lStations.keys()) { + if (iStations.containsKey(blockedHex)) { + //Make sure its not an Offboard Map Hex + if (blockedHex.getCurrentTile().getColour().toString() == "RED" ) continue; + if (blockedHex.getStopName().equals("Beijing")) continue; + return true; + } + } + } return false; } diff --git a/src/main/java/net/sf/rails/game/specific/_1880/OperatingRound_1880.java b/src/main/java/net/sf/rails/game/specific/_1880/OperatingRound_1880.java index b41476d72..566ba5c95 100644 --- a/src/main/java/net/sf/rails/game/specific/_1880/OperatingRound_1880.java +++ b/src/main/java/net/sf/rails/game/specific/_1880/OperatingRound_1880.java @@ -107,7 +107,7 @@ public void processPhaseAction(String name, String value) { @Override protected void prepareRevenueAndDividendAction() { - int[] allowedRevenueActions = new int[] {}; + int[] allowedRevenueActions; // There is only revenue if there are any trains if (operatingCompany.value().canRunTrains()) { if (operatingCompany.value() instanceof PublicCompany_1880) { @@ -243,12 +243,12 @@ public boolean specialBuyTrain(BuyTrain action) { } } } - if (trainResults == false) { + if (!trainResults) { return false; } if ((ipo.getTrainsPerType(action.getType()).length == 0) - && (trainTypeCanAffectOR(action.getType()) == true)) { + && (trainTypeCanAffectOR(action.getType()))) { orControl.orExitToStockRound(operatingCompany.value(), currentStep); setActionForPrivateExchange(action.getType()); if (manditoryNextAction == null) { @@ -293,7 +293,7 @@ public boolean buyTrain(BuyTrain action) { // If there are no more trains of this type, and this type causes an // OR end, end it. if ((ipo.getTrainsPerType(action.getType()).length == 0) - && (trainTypeCanAffectOR(action.getType()) == true)) { + && (trainTypeCanAffectOR(action.getType()))) { if (action.getType().getName().equals("8")) { orControl.setLastCompanyToOperate(((PublicCompany_1880) operatingCompany.value())); orControl.setFinalOperatingRoundSequence(true); @@ -695,15 +695,12 @@ public List setOperatingCompanies() { firstCompanyBeforePrivates = companyList.get(0); // Skip ahead if we have to - //if (!orControl.isFinalOperatingRoundSequence()) { PublicCompany firstCompany = orControl.getFirstCompanyToRun(); if (firstCompany != null) { while (companyList.get(0) != firstCompany) { Collections.rotate(companyList, 1); } } - //} - return new ArrayList(companyList); } @@ -717,8 +714,7 @@ public List setOperatingCompanies() { public List setOperatingCompanies( List oldOperatingCompanies, PublicCompany lastOperatingCompany) { - // TODO Auto-generated method stub - return setOperatingCompanies(); + return setOperatingCompanies(); } /* @@ -850,10 +846,8 @@ public boolean layTile(LayTile action) { // Was a special property used? if (stl != null) { stl.setExercised(); - // currentSpecialTileLays.remove(action); log.debug("This was a special tile lay, " + (extra ? "" : " not") + " extra"); - } if (!extra) { log.debug("This was a normal tile lay"); @@ -1195,7 +1189,6 @@ public void setBuyableTrains() { companiesPerPlayer.add(new ArrayList(4)); List companies; // Sort out which players preside over which companies. - //for (PublicCompanyI c : getOperatingCompanies()) { for (PublicCompany c : companyManager.getAllPublicCompanies()) { if (!c.hasFloated()) continue; if (c.isClosed() || c == operatingCompany.value()) continue; From f6688501850bb1b0b9911cdd8ce513612aae87f2 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 10 Nov 2018 16:04:34 +0100 Subject: [PATCH 09/45] Implementing the Swap of a Private for a Share in the Operating Round. 1830 & 1889 Fixes the Issue #37 --- .../net/sf/rails/game/OperatingRound.java | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/main/java/net/sf/rails/game/OperatingRound.java b/src/main/java/net/sf/rails/game/OperatingRound.java index 705ca322c..7f901a07d 100644 --- a/src/main/java/net/sf/rails/game/OperatingRound.java +++ b/src/main/java/net/sf/rails/game/OperatingRound.java @@ -309,6 +309,12 @@ public boolean process(PossibleAction action) { && ((UseSpecialProperty) selectedAction).getSpecialProperty() instanceof SpecialRight) { result = buyRight((UseSpecialProperty) selectedAction); + + } else if (selectedAction instanceof UseSpecialProperty + && ((UseSpecialProperty) selectedAction).getSpecialProperty() instanceof ExchangeForShare) { + + useSpecialProperty((UseSpecialProperty)selectedAction); + } else if (selectedAction instanceof NullAction) { @@ -341,6 +347,82 @@ public boolean process(PossibleAction action) { return result; } + + public boolean useSpecialProperty(UseSpecialProperty action) { + + SpecialProperty sp = action.getSpecialProperty(); + + if (sp instanceof ExchangeForShare) { + + return executeExchangeForShare(action, (ExchangeForShare) sp); + + } else { + return false; + } + } + + public boolean executeExchangeForShare (UseSpecialProperty action, ExchangeForShare sp) { + + PublicCompany publicCompany = + companyManager.getPublicCompany(sp.getPublicCompanyName()); + PrivateCompany privateCompany = (PrivateCompany)sp.getOriginalCompany(); + Owner owner= privateCompany.getOwner(); + Player player = null; + String errMsg = null; + boolean ipoHasShare = ipo.getShare(publicCompany) >= sp.getShare(); + boolean poolHasShare = pool.getShare(publicCompany) >= sp.getShare(); + + while (true) { + + /* Check if the private is owned by a player */ + if (!(owner instanceof Player)) { + errMsg = + LocalText.getText("PrivateIsNotOwnedByAPlayer", + privateCompany.getId()); + break; + } + + player = (Player) owner; + + /* Check if a share is available */ + if (!ipoHasShare && !poolHasShare) { + errMsg = + LocalText.getText("NoSharesAvailable", + publicCompany.getId()); + break; + } + + break; + } + if (errMsg != null) { + DisplayBuffer.add(this, LocalText.getText( + "CannotSwapPrivateForCertificate", + player.getId(), + privateCompany.getId(), + sp.getShare(), + publicCompany.getId(), + errMsg )); + return false; + } + + + + Certificate cert = + ipoHasShare ? ipo.findCertificate(publicCompany, + false) : pool.findCertificate(publicCompany, + false); + cert.moveTo(player); + ReportBuffer.add(this, LocalText.getText("SwapsPrivateForCertificate", + player.getId(), + privateCompany.getId(), + sp.getShare(), + publicCompany.getId())); + sp.setExercised(); + privateCompany.setClosed(); + + return true; + } + /** Stub, to be overridden in game-specific subclasses. */ public boolean processGameSpecificAction(PossibleAction action) { From 900370f4697941caa64404b5e6ce41ed19ea6fcf Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 17 Nov 2018 16:05:06 +0100 Subject: [PATCH 10/45] Startround Switch to next round was not triggered. --- .../rails/game/specific/_1837/StartRound_1837_Coal.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Coal.java b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Coal.java index 9cf2f6d20..730c0692a 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Coal.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Coal.java @@ -417,6 +417,15 @@ public boolean process(PossibleAction action) { LocalText.getText("UnexpectedAction", action.toString())); } } + if ((startPacket.areAllSold()) + && (pendingAction.value() == null)) { + /* + * If the complete start packet has been sold, start a Stock + * round, + */ + possibleActions.clear(); + finishRound(); + } return result; } From d18f91ebe6ebbc21c04651dbbcc43001e7ee63c2 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Mon, 3 Dec 2018 20:26:14 +0100 Subject: [PATCH 11/45] excludes local eclipse settings --- .settings/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .settings/.gitignore diff --git a/.settings/.gitignore b/.settings/.gitignore new file mode 100644 index 000000000..b012ade25 --- /dev/null +++ b/.settings/.gitignore @@ -0,0 +1 @@ +/org.eclipse.core.resources.prefs From c8f204196de6deb7008d61f034df5081945b3825 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sun, 11 Nov 2018 16:03:32 +0100 Subject: [PATCH 12/45] Replacing obsolete Code in 1837 Implementing the mapHex block for private companies and the phase 4 tile blocks for upper italy. --- .../game/specific/_1837/BzHTileModifier.java | 1 - .../_1837/FinalCoalExchangeRound.java | 5 +- .../specific/_1837/ItalyTileModifier.java | 1 - .../specific/_1837/OperatingRound_1837.java | 65 +++++++++---------- .../specific/_1837/StartRound_1837_Coal.java | 2 - .../game/specific/_1837/StockMarket_1837.java | 1 - .../game/specific/_1837/StockRound_1837.java | 1 - 7 files changed, 33 insertions(+), 43 deletions(-) diff --git a/src/main/java/net/sf/rails/game/specific/_1837/BzHTileModifier.java b/src/main/java/net/sf/rails/game/specific/_1837/BzHTileModifier.java index d242a2366..41eee97b7 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/BzHTileModifier.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/BzHTileModifier.java @@ -26,7 +26,6 @@ public class BzHTileModifier implements NetworkGraphModifier { @Override public void modifyMapGraph(NetworkGraph mapGraph) { - // TODO (Rails 2.0): Add root reference to modifiers SimpleGraph graph = mapGraph.getGraph(); RailsRoot root = RailsRoot.getInstance(); diff --git a/src/main/java/net/sf/rails/game/specific/_1837/FinalCoalExchangeRound.java b/src/main/java/net/sf/rails/game/specific/_1837/FinalCoalExchangeRound.java index d767a1c56..22eca5af4 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/FinalCoalExchangeRound.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/FinalCoalExchangeRound.java @@ -17,7 +17,6 @@ public class FinalCoalExchangeRound extends StockRound_1837 { public FinalCoalExchangeRound(GameManager parent, String id) { super(parent, id); - // TODO Auto-generated constructor stub guiHints.setVisibilityHint(GuiDef.Panel.MAP, true); guiHints.setActivePanel(GuiDef.Panel.STATUS); @@ -104,11 +103,9 @@ public boolean done(NullAction action, String playerName, boolean hasAutopassed) for (PublicCompany comp : companyManager.getAllPublicCompanies()) { - if (comp.getType().getId().equals("Coal")) { - if (!comp.isClosed()) { + if ((comp.getType().getId().equals("Coal")) && (!comp.isClosed())) { finishTurn(); return true; - } } } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/ItalyTileModifier.java b/src/main/java/net/sf/rails/game/specific/_1837/ItalyTileModifier.java index cb3c775ab..cfcd569fd 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/ItalyTileModifier.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/ItalyTileModifier.java @@ -26,7 +26,6 @@ public class ItalyTileModifier implements NetworkGraphModifier { @Override public void modifyMapGraph(NetworkGraph mapGraph) { - // TODO (Rails 2.0): Add root reference to modifiers SimpleGraph graph = mapGraph.getGraph(); RailsRoot root = RailsRoot.getInstance(); List italyMapHexes = new ArrayList (); diff --git a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java index 3a9747420..ef836a664 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java @@ -3,6 +3,8 @@ */ package net.sf.rails.game.specific._1837; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Set; @@ -19,6 +21,7 @@ import net.sf.rails.game.Player; import net.sf.rails.game.PrivateCompany; import net.sf.rails.game.PublicCompany; +import net.sf.rails.game.RailsRoot; import net.sf.rails.game.special.ExchangeForShare; import net.sf.rails.game.special.SpecialProperty; import net.sf.rails.game.state.BooleanState; @@ -423,38 +426,34 @@ protected void executeSetRevenueAndDividend(SetDividend action) { @Override protected boolean gameSpecificTileLayAllowed(PublicCompany company, MapHex hex, int orientation) { - boolean result = true; - // FIXME: Removed hex.isBlockedForTileLays removed in Rails 2.0 beta preparation, needs fix -// // Check if the Hex is blocked ? -// for (PrivateCompany privComp : gameManager.getAllPrivateCompanies()) { -// boolean isBlocked = hex.isBlockedForTileLays(privComp); -// if (isBlocked) { -// result = true; -// break; -// } -// } -// -// if (result == true) { -// // Check if the Owner of the PublicCompany is owner of the Private Company that blocks -// // the hex (1837) -// -// ImmutableSet compPrivatesOwned = -// company.getPresident().getPortfolioModel().getPrivateCompanies(); -// -// for (PrivateCompany privComp : compPrivatesOwned) { -// // Check if the Hex is blocked by any of the privates owned by -// // this PublicCompany -// if (hex.isBlockedForTileLays(privComp)) { -// result = false; -// } -// } -// -// } - - return result; + RailsRoot root = RailsRoot.getInstance(); + List italyMapHexes = new ArrayList (); + // 1. check Phase + + int phaseIndex = root.getPhaseManager().getCurrentPhase().getIndex(); + if (phaseIndex < 3) { + // Check if the Hex is blocked by a private ? + if (hex.isBlockedByPrivateCompany()) { + if (company.getPresident().getPortfolioModel().getPrivateCompanies().contains(hex.getBlockingPrivateCompany())) { + // Check if the Owner of the PublicCompany is owner of the Private Company that blocks + // the hex (1837) + return true; + } + return false; + } + } + if (phaseIndex >= 4 ) { + log.debug("Italy inactive, index of phase = " + phaseIndex); + + // 2. retrieve Italy vertices ... + String [] italyHexes = {"K2","K4","K8","K10","L3","L5","L7","L9","M4","M6","M8"}; + for (String italyHex:italyHexes){ + italyMapHexes.add(root.getMapManager().getHex(italyHex)); + } + if (italyMapHexes.contains(hex)) { + return false; + } + } + return true; } - - - - } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Coal.java b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Coal.java index 730c0692a..e9a88031e 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Coal.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Coal.java @@ -146,7 +146,6 @@ public boolean setPossibleActions() { possibleActions.clear(); } else { // Are all Sold possibleActions.clear(); - // finishRound(); return true; } @@ -351,7 +350,6 @@ protected void assignItem(Player player, StartItem item, int price, secondary.getCompany(), player, price)); pendingPlayer.set(player); pendingCertificate.set(secondary); - // item.setSold(player, price); } else { super.assignItem(player, item, price, sharePrice); } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StockMarket_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/StockMarket_1837.java index eb23c5f71..220ffda48 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/StockMarket_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/StockMarket_1837.java @@ -20,7 +20,6 @@ public class StockMarket_1837 extends StockMarket { */ public StockMarket_1837(RailsRoot parent, String id) { super(parent, id); - // TODO Auto-generated constructor stub } public void payOut(PublicCompany company, boolean split) { diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java index 98db69369..7990a15ca 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java @@ -49,7 +49,6 @@ public class StockRound_1837 extends StockRound { */ public StockRound_1837(GameManager parent, String id) { super(parent, id); - // TODO Auto-generated constructor stub } @Override From b99cfc6fd7fae5aeee1b0d50267e7667e49d1ff1 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 8 Dec 2018 12:37:29 +0100 Subject: [PATCH 13/45] Remving old Code - Fixing Startround Behaviour of KuK Startround --- .../_1837/StartRound_1837_Minors_KuK.java | 28 ++++++---- .../net/sf/rails/ui/swing/ORUIManager.java | 33 +++++++---- .../gamespecific/_1837/GameStatus_1837.java | 1 - .../_1837/GameUIManager_1837.java | 3 +- .../gamespecific/_1837/ORUIManager_1837.java | 31 +++++++++++ .../rails/ui/swing/hexmap/TileHexUpgrade.java | 55 +++++++++++++++---- src/main/resources/data/1837/Game.xml | 1 + src/main/resources/data/1837/GameOptions.xml | 1 + 8 files changed, 115 insertions(+), 38 deletions(-) create mode 100644 src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Minors_KuK.java b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Minors_KuK.java index b07d05021..57b03b341 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Minors_KuK.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Minors_KuK.java @@ -44,12 +44,19 @@ public boolean setPossibleActions() { possibleActions.clear(); return true; } +//TODO: Check in a game if this works as intended... + if (!fillPossibleActions(buyableItems)) { + /* we dont have a valid player action */ + possibleActions.add(new NullAction(NullAction.Mode.PASS)); + } else { + /* Pass is always allowed, we have a valid player action */ + possibleActions.add(new NullAction(NullAction.Mode.PASS)); + } + return true; + } - /* - * Repeat until we have found a player with enough money to buy some - * item - */ + private boolean fillPossibleActions(List buyableItems) { while (possibleActions.isEmpty()) { Player currentPlayer = playerManager.getCurrentPlayer(); @@ -63,13 +70,12 @@ public boolean setPossibleActions() { possibleActions.add(new BuyStartItem(item, item.getBasePrice(), false)); } - } /* Pass is always allowed */ - possibleActions.add(new NullAction(NullAction.Mode.PASS)); - -} - /* Pass is always allowed */ - possibleActions.add(new NullAction(NullAction.Mode.PASS)); - + } + break; + } + if (possibleActions.isEmpty()) { + return false; + } return true; } diff --git a/src/main/java/net/sf/rails/ui/swing/ORUIManager.java b/src/main/java/net/sf/rails/ui/swing/ORUIManager.java index d60b4d539..c94da22d7 100644 --- a/src/main/java/net/sf/rails/ui/swing/ORUIManager.java +++ b/src/main/java/net/sf/rails/ui/swing/ORUIManager.java @@ -185,9 +185,25 @@ public void setMapRelatedActions(PossibleActions actions) { // build and finalize hexUpgrades hexUpgrades.build(); - + // show selectable hexes if highlight is active if (gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.ROUTE_HIGHLIGHT)) { + checkHexVisibilityOnUI(actions); + } + + LocalSteps nextSubStep; + if (tileActions.isEmpty() && tokenActions.isEmpty()) { + nextSubStep = LocalSteps.Inactive; + } else { + nextSubStep = LocalSteps.SelectHex; + } + setLocalStep(nextSubStep); + } + + protected void checkHexVisibilityOnUI(PossibleActions actions) { + + // SpecialTileLay sp = (SpecialTileLay)layTile.getSpecialProperty(); + for (GUIHex hex:hexUpgrades.getHexes()) { boolean invalids = false; for (HexUpgrade upgrade:hexUpgrades.getUpgrades(hex)) { @@ -207,18 +223,10 @@ public void setMapRelatedActions(PossibleActions actions) { } } } - - LocalSteps nextSubStep; - if (tileActions.isEmpty() && tokenActions.isEmpty()) { - nextSubStep = LocalSteps.Inactive; - } else { - nextSubStep = LocalSteps.SelectHex; - } - setLocalStep(nextSubStep); - } - + private void defineTileUpgrades(List actions) { for (LayTile layTile:actions) { + switch (layTile.getType()) { case (LayTile.GENERIC): addConnectedTileLays(layTile); @@ -242,13 +250,14 @@ private void defineTileUpgrades(List actions) { } + private void addConnectedTileLays(LayTile layTile) { NetworkGraph graph = networkAdapter.getRouteGraph(layTile.getCompany(), true); Map mapHexSides = graph.getReachableSides(); Multimap mapHexStations = graph.getPassableStations(); boolean allLocations = (layTile.getLocations() == null || layTile.getLocations().isEmpty()); - + for (MapHex hex:Sets.union(mapHexSides.keySet(), mapHexStations.keySet())) { if (allLocations || layTile.getLocations().contains(hex)) { GUIHex guiHex = map.getHex(hex); diff --git a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameStatus_1837.java b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameStatus_1837.java index b8080899a..dda1cf790 100644 --- a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameStatus_1837.java +++ b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameStatus_1837.java @@ -24,7 +24,6 @@ public class GameStatus_1837 extends GameStatus { * */ public GameStatus_1837() { - // TODO Auto-generated constructor stub } private static final long serialVersionUID = 1L; diff --git a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java index 8b112bf06..6d52b52c2 100644 --- a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java +++ b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java @@ -30,14 +30,13 @@ public class GameUIManager_1837 extends GameUIManager { public GameUIManager_1837() { - // TODO Auto-generated constructor stub } + /* (non-Javadoc) * @see net.sf.rails.ui.swing.GameUIManager#updateUI() */ @Override public void updateUI() { - // TODO Auto-generated method stub super.updateUI(); } diff --git a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java new file mode 100644 index 000000000..5979f7700 --- /dev/null +++ b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java @@ -0,0 +1,31 @@ +/** + * + */ +package net.sf.rails.ui.swing.gamespecific._1837; + +import net.sf.rails.ui.swing.ORUIManager; +import rails.game.action.PossibleActions; + +/** + * @author Martin + * + */ +public class ORUIManager_1837 extends ORUIManager { + + /** + * + */ + public ORUIManager_1837() { + super(); + } + + /* (non-Javadoc) + * @see net.sf.rails.ui.swing.ORUIManager#setMapRelatedActions(rails.game.action.PossibleActions) + */ + @Override + public void setMapRelatedActions(PossibleActions actions) { + // TODO Auto-generated method stub + super.setMapRelatedActions(actions); + } + +} diff --git a/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java b/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java index 41690e3cf..650511090 100644 --- a/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java +++ b/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java @@ -17,6 +17,7 @@ import net.sf.rails.game.Tile; import net.sf.rails.game.TileColour; import net.sf.rails.game.TileUpgrade; +import net.sf.rails.game.special.SpecialTileLay; import rails.game.action.LayTile; import com.google.common.base.Objects; @@ -146,19 +147,51 @@ private void findValidRotations(HexSidesSet connectedSides, Collection private boolean validate(Phase phase) { invalids.clear(); - - if (hexIsBlocked()) { - invalids.add(Invalids.HEX_BLOCKED); - } - if (hexIsReserved()) { - invalids.add(Invalids.HEX_RESERVED); + + /*MBR 25.11.2018 + Check if the action causes this Validation is a Special Tile Lay + If that is the case the current support special action modifications need to be + excluded from the validation: + As of the time of this writing, the following actions are supported. + A private blocking hex might be unblocked by laying a tile + The tilelay might be free of cost, or carry a discount + Future Powers consist of Tile lays in a different Colour than the current Phase (1822) + */ + if (action.getType()== action.SPECIAL_PROPERTY) { + + SpecialTileLay sp = (SpecialTileLay)action.getSpecialProperty(); + if (!sp.isFree()) { + if (notEnoughCash(0)) { + invalids.add(Invalids.NOT_ENOUGH_CASH); + } + } + if (!(action.getSpecialProperty().getLocations().contains(hex.getHex()))) { + if (hexIsBlocked()) { + invalids.add(Invalids.HEX_BLOCKED); + } + if (hexIsReserved()) { + invalids.add(Invalids.HEX_RESERVED); + } + } + } else { + if (hexIsBlocked()) { + invalids.add(Invalids.HEX_BLOCKED); + } + if (hexIsReserved()) { + invalids.add(Invalids.HEX_RESERVED); + } + if (notEnoughCash(0)) { + invalids.add(Invalids.NOT_ENOUGH_CASH); + } } if (noTileAvailable()) { invalids.add(Invalids.NO_TILES_LEFT); - } + } + //TODO: Add 1822 Private Powers to remove a small station with a private power if (notAllowedForHex()) { invalids.add(Invalids.NOT_ALLOWED_FOR_HEX); } + //TODO: Add 1822 Private Powers to upgrade a Tile one phase ahead if (notAllowedForPhase(phase)) { invalids.add(Invalids.NOT_ALLOWED_FOR_PHASE); } @@ -173,9 +206,7 @@ private boolean validate(Phase phase) { } else if (noValidRotation()) { invalids.add(Invalids.NO_VALID_ORIENTATION); } - if (notEnoughCash()) { - invalids.add(Invalids.NOT_ENOUGH_CASH); - } + return invalids.isEmpty(); } @@ -219,12 +250,12 @@ public boolean noRouteToNewTrack() { return noValidRotation() && permissiveRoutePossible; } - public boolean notEnoughCash() { + public boolean notEnoughCash(int discount) { // correction action does not require cash if (action.getType() == LayTile.CORRECTION) { return false; } - return action.getCompany().getCash() < this.getCost(); + return action.getCompany().getCash() < (this.getCost()-discount); } public boolean requiresConnection() { diff --git a/src/main/resources/data/1837/Game.xml b/src/main/resources/data/1837/Game.xml index d9edc770b..e44b4baf2 100644 --- a/src/main/resources/data/1837/Game.xml +++ b/src/main/resources/data/1837/Game.xml @@ -19,6 +19,7 @@ + diff --git a/src/main/resources/data/1837/GameOptions.xml b/src/main/resources/data/1837/GameOptions.xml index db353de05..f5aef15fc 100644 --- a/src/main/resources/data/1837/GameOptions.xml +++ b/src/main/resources/data/1837/GameOptions.xml @@ -1,5 +1,6 @@ + From 9b1ceeb9a4c8760730c2d0f42c0cecb5da37848c Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 22 Dec 2018 10:55:43 +0100 Subject: [PATCH 14/45] Fixes typo in 1870 Description --- src/main/resources/data/GamesList.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/data/GamesList.xml b/src/main/resources/data/GamesList.xml index f00ae4007..62dc64f37 100644 --- a/src/main/resources/data/GamesList.xml +++ b/src/main/resources/data/GamesList.xml @@ -166,7 +166,7 @@ Not yet implemented: (c) 1992, 1995 Mayfair Games, Inc. Designed by Bill Dixon Limitations: -All aspects not present in 1830 have not been implemented yet. +All aspects not present in 1870 have not been implemented yet. From 09f3da3325d854ad6dd31e26173da7de709c6d45 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 22 Dec 2018 10:55:43 +0100 Subject: [PATCH 15/45] Fixes typo in 1870 Description From cfd97af27ee9aa4416d953485f90d68bd66b769b Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 22 Dec 2018 11:40:07 +0100 Subject: [PATCH 16/45] implementing Romoth Variant Fixing Map coordinates Implementing Change to Stockmarket --- .../game/specific/_1837/BzHTileModifier.java | 2 +- .../specific/_1837/ItalyTileModifier.java | 2 +- .../specific/_1837/OperatingRound_1837.java | 2 +- .../_1837/StartRound_1837_Minors_KuK.java | 1 - .../game/specific/_1837/StockMarket_1837.java | 6 +- .../resources/data/1837/CompanyManager.xml | 36 +- src/main/resources/data/1837/Game.xml | 16 +- src/main/resources/data/1837/GameOptions.xml | 1 + src/main/resources/data/1837/Map.xml | 367 +++++++++--------- 9 files changed, 237 insertions(+), 196 deletions(-) diff --git a/src/main/java/net/sf/rails/game/specific/_1837/BzHTileModifier.java b/src/main/java/net/sf/rails/game/specific/_1837/BzHTileModifier.java index 41eee97b7..d0ea7d657 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/BzHTileModifier.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/BzHTileModifier.java @@ -39,7 +39,7 @@ public void modifyMapGraph(NetworkGraph mapGraph) { } // 2. retrieve BzH vertices ... - String[] bzhHexes = {"L17","L19","L21","L23","M18","M20","M22","N19","N21"}; + String[] bzhHexes = {"L16","L18","L20","L22","M17","M19","M21","N18","N20"}; for(String bzhHex:bzhHexes){ bzhMapHexes.add(root.getMapManager().getHex(bzhHex)); } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/ItalyTileModifier.java b/src/main/java/net/sf/rails/game/specific/_1837/ItalyTileModifier.java index cfcd569fd..aa2e94132 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/ItalyTileModifier.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/ItalyTileModifier.java @@ -39,7 +39,7 @@ public void modifyMapGraph(NetworkGraph mapGraph) { } // 2. retrieve Italy vertices ... - String [] italyHexes = {"K2","K4","K8","K10","L3","L5","L7","L9","M4","M6","M8"}; + String [] italyHexes = {"K1","K3","K7","K9","L2","L4","L6","L8","M3","M5","M7"}; for (String italyHex:italyHexes){ italyMapHexes.add(root.getMapManager().getHex(italyHex)); } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java index ef836a664..3c34cfa7c 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java @@ -446,7 +446,7 @@ protected boolean gameSpecificTileLayAllowed(PublicCompany company, log.debug("Italy inactive, index of phase = " + phaseIndex); // 2. retrieve Italy vertices ... - String [] italyHexes = {"K2","K4","K8","K10","L3","L5","L7","L9","M4","M6","M8"}; + String [] italyHexes = {"K1","K3","K7","K9","L2","L4","L6","L8","M3","M5","M7"}; for (String italyHex:italyHexes){ italyMapHexes.add(root.getMapManager().getHex(italyHex)); } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Minors_KuK.java b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Minors_KuK.java index 57b03b341..615f850a4 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Minors_KuK.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_Minors_KuK.java @@ -44,7 +44,6 @@ public boolean setPossibleActions() { possibleActions.clear(); return true; } -//TODO: Check in a game if this works as intended... if (!fillPossibleActions(buyableItems)) { /* we dont have a valid player action */ possibleActions.add(new NullAction(NullAction.Mode.PASS)); diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StockMarket_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/StockMarket_1837.java index 220ffda48..2e3304249 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/StockMarket_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/StockMarket_1837.java @@ -3,6 +3,7 @@ */ package net.sf.rails.game.specific._1837; +import net.sf.rails.common.GameOption; import net.sf.rails.game.PublicCompany; import net.sf.rails.game.RailsRoot; import net.sf.rails.game.StockMarket; @@ -61,8 +62,11 @@ private void moveRightandDown(PublicCompany company) { @Override public void soldOut(PublicCompany company) { - if (company.getPresident().getPortfolioModel().getCertificates(company).size()>=4) { //President has 4 shares (50% or more) + + if (GameOption.getValue(this,GameOption.VARIANT).equalsIgnoreCase("Basegame")){ + if (company.getPresident().getPortfolioModel().getCertificates(company).size()>=4) { //President has 4 shares (50% or more) moveLeftAndUp(company); + } } else { moveUp(company); } diff --git a/src/main/resources/data/1837/CompanyManager.xml b/src/main/resources/data/1837/CompanyManager.xml index 14aec8d35..688bf093b 100644 --- a/src/main/resources/data/1837/CompanyManager.xml +++ b/src/main/resources/data/1837/CompanyManager.xml @@ -255,14 +255,26 @@ + - + + + + + + + + + + + + @@ -348,6 +360,7 @@ + @@ -355,19 +368,38 @@ + + + + + + + + + + + - + + + + + + + + + diff --git a/src/main/resources/data/1837/Game.xml b/src/main/resources/data/1837/Game.xml index e44b4baf2..117e7365f 100644 --- a/src/main/resources/data/1837/Game.xml +++ b/src/main/resources/data/1837/Game.xml @@ -138,14 +138,14 @@ - - - - - - - - + + + + + + + + diff --git a/src/main/resources/data/1837/GameOptions.xml b/src/main/resources/data/1837/GameOptions.xml index f5aef15fc..44cffd39c 100644 --- a/src/main/resources/data/1837/GameOptions.xml +++ b/src/main/resources/data/1837/GameOptions.xml @@ -8,4 +8,5 @@ + diff --git a/src/main/resources/data/1837/Map.xml b/src/main/resources/data/1837/Map.xml index dbdb3b4cd..1da72b043 100644 --- a/src/main/resources/data/1837/Map.xml +++ b/src/main/resources/data/1837/Map.xml @@ -1,182 +1,187 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From a1b73578869ad2b2902e919ca4703de13db5e8a6 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 22 Dec 2018 12:20:05 +0100 Subject: [PATCH 17/45] Implement Romoth Variant Dont Merge Minors if the Corresponding Major has been sold out. Final Oversight for K2 in Startpackage.. --- .../java/net/sf/rails/game/MapManager.java | 2 +- .../game/specific/_1837/StockRound_1837.java | 14 ++- .../_1837/StartRoundWindow_1837.java | 4 +- .../resources/data/1837/CompanyManager.xml | 109 +++++++++--------- src/main/resources/data/1837/Map.xml | 4 +- 5 files changed, 72 insertions(+), 61 deletions(-) diff --git a/src/main/java/net/sf/rails/game/MapManager.java b/src/main/java/net/sf/rails/game/MapManager.java index 6b31715ea..0ba61eb97 100644 --- a/src/main/java/net/sf/rails/game/MapManager.java +++ b/src/main/java/net/sf/rails/game/MapManager.java @@ -317,5 +317,5 @@ public void setMapScale(float mapScale) { public boolean isMapImageUsed() { return mapImageUsed; } - + } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java index 7990a15ca..2effc5f35 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java @@ -12,6 +12,7 @@ import rails.game.action.MergeCompanies; import rails.game.action.PossibleAction; import net.sf.rails.common.DisplayBuffer; +import net.sf.rails.common.GameOption; import net.sf.rails.common.LocalText; import net.sf.rails.common.ReportBuffer; import net.sf.rails.game.Bank; @@ -290,13 +291,16 @@ protected void finishRound() { // Check if a soldout Company has still Coal companies running // independently - // if thats the case the Coal companies need to be merged. - for (PublicCompany company : gameManager.getCompaniesInRunningOrder()) { - if ((company.hasStockPrice()) && (company.isSoldOut())) { - forcedMergeCompanyRoutine(company); + // if thats the case the Coal companies need to be merged in the basegame. + // If the Romoth Variant is played this rule will be ignored + if (GameOption.getValue(this,GameOption.VARIANT).equalsIgnoreCase("basegame")) { + for (PublicCompany company : gameManager.getCompaniesInRunningOrder()) { + if ((company.hasStockPrice()) && (company.isSoldOut())) { + forcedMergeCompanyRoutine(company); + } } } - + //TODO: Check correct order of next statements... if (discardingTrains.value()) { super.finishRound(); diff --git a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/StartRoundWindow_1837.java b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/StartRoundWindow_1837.java index 0e088356c..46c80172c 100644 --- a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/StartRoundWindow_1837.java +++ b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/StartRoundWindow_1837.java @@ -13,7 +13,7 @@ public class StartRoundWindow_1837 extends StartRoundWindow { /* Keys of dialogues owned by this class */ public static final String COMPANY_START_HEX_DIALOG = "CompanyStartHex"; - private static final String[] hexes = {"L3", "L9"}; + private static final String[] hexes = {"L2", "L8"}; protected JDialog currentDialog = null; protected PossibleAction currentDialogAction = null; @@ -42,6 +42,8 @@ public void dialogActionPerformed () { //-- Start Hex for S5 private boolean requestHomeHex(SetHomeHexLocation action) { + + RadioButtonDialog dialog = new RadioButtonDialog( COMPANY_START_HEX_DIALOG, this, this, LocalText.getText("PleaseSelect"), diff --git a/src/main/resources/data/1837/CompanyManager.xml b/src/main/resources/data/1837/CompanyManager.xml index 688bf093b..321ccfa6b 100644 --- a/src/main/resources/data/1837/CompanyManager.xml +++ b/src/main/resources/data/1837/CompanyManager.xml @@ -68,68 +68,68 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -137,7 +137,7 @@ - + @@ -145,7 +145,7 @@ - + @@ -153,7 +153,7 @@ - + @@ -161,7 +161,7 @@ - + @@ -169,7 +169,7 @@ - + @@ -177,7 +177,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -193,7 +193,7 @@ - + @@ -201,7 +201,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -217,7 +217,7 @@ - + @@ -225,7 +225,7 @@ - + @@ -233,7 +233,7 @@ - + @@ -248,7 +248,7 @@ - + @@ -257,7 +257,7 @@ - + @@ -267,7 +267,7 @@ - + @@ -276,7 +276,7 @@ - + @@ -285,7 +285,7 @@ - + @@ -294,7 +294,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -313,65 +313,65 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -379,22 +379,22 @@ - + - + - + - + - + @@ -431,7 +431,12 @@ - + + + + + + diff --git a/src/main/resources/data/1837/Map.xml b/src/main/resources/data/1837/Map.xml index 1da72b043..bebd83502 100644 --- a/src/main/resources/data/1837/Map.xml +++ b/src/main/resources/data/1837/Map.xml @@ -71,10 +71,10 @@ - + - + From 62fd011d819cfb9ce58006c4b8eee432329963b3 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Mon, 24 Dec 2018 12:57:02 +0100 Subject: [PATCH 18/45] Adding missing Text Locales Fixing Hungarian Private Certificates Count Fixing Hungarian U1 and U3 starting cash --- src/main/resources/LocalisedText.properties | 2 ++ .../resources/data/1837/CompanyManager.xml | 22 +++++++++++------- .../data/test/1837_StartroundCompleted.rails | Bin 0 -> 7978 bytes 3 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 src/test/resources/data/test/1837_StartroundCompleted.rails diff --git a/src/main/resources/LocalisedText.properties b/src/main/resources/LocalisedText.properties index 476ac532b..dfcebf5cc 100644 --- a/src/main/resources/LocalisedText.properties +++ b/src/main/resources/LocalisedText.properties @@ -41,6 +41,7 @@ BeginnerGame=Choose beginner game BID=Bid BID_ITEM_LOG={0} bids {1} on {2}. Remaining free cash {3}. BID_ITEM={0} bids {1} on {2}. +BidLow=Bidding by Reduction, Lowest reductions wins the bid. BidMustBeMultipleOf=Invalid bid {0}: must be multiple of {1} BROKEN=BROKEN BUY=Buy @@ -751,6 +752,7 @@ StartingPlayer=Starting player is {0} StartOfInitialRound=\n================\nStart of initial round\n================ StartOfParliamentRound=\n================\nStart of Parliament Round\n================ StartOfPhase=Start of phase {0}. +StartOfStartRound=Start of Starting Round {0}. StartPacketHasNoClass=Start packet {0} has no class defined. StartsPhase=Starts phase {0} StartStockRound=\n==================\nStart of Stock Round {0}\n================== diff --git a/src/main/resources/data/1837/CompanyManager.xml b/src/main/resources/data/1837/CompanyManager.xml index 321ccfa6b..20eb1fee7 100644 --- a/src/main/resources/data/1837/CompanyManager.xml +++ b/src/main/resources/data/1837/CompanyManager.xml @@ -27,7 +27,7 @@ - + @@ -283,10 +283,12 @@ - - + + + + + - @@ -302,10 +304,12 @@ - - + + + + + - @@ -441,9 +445,9 @@ - + - + diff --git a/src/test/resources/data/test/1837_StartroundCompleted.rails b/src/test/resources/data/test/1837_StartroundCompleted.rails new file mode 100644 index 0000000000000000000000000000000000000000..eba8c6a9e7766d66273a90c33f983bd22d8bcae7 GIT binary patch literal 7978 zcmeHMO>^5s7+%Xx^VKvd0S0D(Nok=lLzTv9Av6b?vLzYb_}$^|U5sz?yNS?AQD5^FGhJ+SP+U z(TG6fMf0Lry>{6w3N%~1xUh6#p?IOVIJa==%B7_%#bU_OsXKTNn-u#^(_(&e`Q9J* zfBxp|Lj&b*ppiXHBhuz*rq`$(dAo#v_29c#C%^suo`Fz1K%Hw`pu)n^;(IXYY1KXw zE;ToB*xJIu$mnlB{`BIfzvhv#jwUF>&N{XQ<0UjMTAYL}MxA!>!BsWX$^9|7&%kd& zpwXL{yVw^3ov1R8i55Jpx{k&61sc2VhIp3}N1#(x774Plk2/{c5)+-8fy4|+~_ zyxzWDq4v98R3-S;GvZQc)-llamNpr8MavUtqC&XmhM~Jhz*3n3WLwOE zXTxW0K=fUkd1jNbCM703dd!C#rNkCy$@3y1QLx-loU0K)i@Ki^XPt3R!3lpLoVU;z zp~NG;04HW|Su#ZPGVb%+yLVum<#rJ9xS~UdZpHmyKK@}Qe4EC>24WSq?Yk}nVheLS zg7FGBq9B0(Z!&t9@J@vQJUMy=aHXNy#2zsr;((-CjwoGGk6rf+0~sY$@L<9gnqq-$ zg{g&i358fBJgouBz)@i2+~Hv>4B!J8QbXqrly9IBuuPm1nhaF@OTI(e7Mke%R|eNU zLtmit?I0%|lFw)0o(n?x_@*q($*0#dg@!CVn<>o8!gHCzf-HO^Q~2LD#L;VqL$n$l z)CA_DBuGrnoPkD5=y@E5%yuzEsn!AsS3pgqghm2+Z=kUds4GL*K&L|@dQG-{deA`A zq3%;>H6kqZ5@;mA{y~`#2N=`qAOmsULX)9%qZVLWO7evc#bmykuQ4v2AfN}1&K#bC z_CG~4m<2F+9CC@*CD)X)ASc@6mo)xXicUzN{Mu$6m?5uq_yq~p4G9K-BxTr_WZstu z_n?yqS1M2>uPnktwE`$fg!@W#3SkXh0n&f=X03hx0c zt6hM8DJYs{1obTnaaxAx{Est31Z7ouR9SH;Mm@{c;X;=I`0ufVU4Fji#bAD!q3{sQ$AEd{3zuT6 zh7Jz5@@pG47)V}Ox<0c^*1!0UoTDn#b4+UYIA){})`rF;hbu9Mvk3Q Date: Tue, 25 Dec 2018 09:21:44 +0100 Subject: [PATCH 19/45] Preparation and implementation of Actions for introducing the Special Company Treasury Incomes. This is needed for a seperate income during the OR not tied to the private company income but stemming from the additional revenue coming from special trains (Coal Trains in 1837) or special powers like a Mail Contract. --- src/main/java/net/sf/rails/common/GuiDef.java | 4 +- .../net/sf/rails/game/OperatingRound.java | 2 +- .../java/net/sf/rails/game/PublicCompany.java | 36 ++++++ .../game/specific/_1837/GameManager_1837.java | 14 +++ .../specific/_1837/OperatingRound_1837.java | 14 +++ .../specific/_1837/PublicCompany_1837.java | 13 ++- .../net/sf/rails/ui/swing/GameUIManager.java | 5 - .../java/net/sf/rails/ui/swing/ORPanel.java | 105 ++++++++++++++++-- .../net/sf/rails/ui/swing/ORUIManager.java | 4 +- .../_1837/GameUIManager_1837.java | 11 ++ .../gamespecific/_1837/ORUIManager_1837.java | 45 +++++++- .../java/rails/game/action/SetDividend.java | 84 +++++++++++--- src/main/resources/data/1837/Game.xml | 6 +- src/main/resources/data/1837/GameOptions.xml | 2 +- 14 files changed, 299 insertions(+), 46 deletions(-) diff --git a/src/main/java/net/sf/rails/common/GuiDef.java b/src/main/java/net/sf/rails/common/GuiDef.java index 12778b113..51fc24c06 100644 --- a/src/main/java/net/sf/rails/common/GuiDef.java +++ b/src/main/java/net/sf/rails/common/GuiDef.java @@ -3,7 +3,6 @@ public class GuiDef { /** Identifiers and default names for configurable UI classes */ - // FIXME: Rails 2.0 move this to xml files public enum ClassName { GAME_UI_MANAGER ("net.sf.rails.ui.swing.GameUIManager"), @@ -42,7 +41,8 @@ public enum Parm { HAS_ANY_RIGHTS, NO_MAP_MODE, REVENUE_SUGGEST, - ROUTE_HIGHLIGHT, PLAYER_ORDER_VARIES + ROUTE_HIGHLIGHT, + PLAYER_ORDER_VARIES, HAS_SPECIAL_COMPANY_INCOME } /** diff --git a/src/main/java/net/sf/rails/game/OperatingRound.java b/src/main/java/net/sf/rails/game/OperatingRound.java index 7f901a07d..f599ab33d 100644 --- a/src/main/java/net/sf/rails/game/OperatingRound.java +++ b/src/main/java/net/sf/rails/game/OperatingRound.java @@ -2564,7 +2564,7 @@ public void payout(int amount) { recipient.getId(), partText, shares, operatingCompany.value().getShareUnit())); } - + // Move the token operatingCompany.value().payout(amount); diff --git a/src/main/java/net/sf/rails/game/PublicCompany.java b/src/main/java/net/sf/rails/game/PublicCompany.java index 501f4b4fd..d21a8f6ab 100644 --- a/src/main/java/net/sf/rails/game/PublicCompany.java +++ b/src/main/java/net/sf/rails/game/PublicCompany.java @@ -132,6 +132,11 @@ public class PublicCompany extends RailsAbstractItem implements Company, RailsMo /** Most recent revenue earned. */ protected final CountingMoneyModel lastRevenue = CountingMoneyModel.create(this, "lastRevenue", false); + public final CountingMoneyModel directIncomeRevenue = CountingMoneyModel.create(this, "directIncome", false); + + /** Most recent Direct Company Treasury income earned. */ + protected final CountingMoneyModel lastDirectIncome = CountingMoneyModel.create(this, "lastDirectIncome", false); + /** Most recent payout decision. */ protected final StringState lastRevenueAllocation = StringState.create(this, "lastRevenueAllocation"); @@ -303,6 +308,7 @@ public class PublicCompany extends RailsAbstractItem implements Company, RailsMo private String foundingStartCompany = null; + /** * Used by Configure (via reflection) only */ @@ -2038,6 +2044,36 @@ public String getFoundingStartCompany() { public void setStartingMinor(String foundingCompany) { this.foundingStartCompany = foundingCompany; } + + + public Model getLastDirectIncomeModel() { + return lastDirectIncome; + } + /** + * Store the last direct Income earned by this company. + * + * @param i The last revenue amount. + */ + public void setLastDirectIncome(int i) { + lastDirectIncome.set(i); + } + + /** + * Get the last directIncome earned by this company. + * + * @return The last revenue amount. + */ + public int getLastDirectIncome() { + return lastDirectIncome.value(); + } + + public void setDirectIncomeRevenue(int directIncome) { + this.directIncomeRevenue.set(directIncome); + } + public int getDirectIncomeRevenue() { + return directIncomeRevenue.value(); + } + } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java index 818e01a7b..c8ae59736 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java @@ -3,6 +3,8 @@ */ package net.sf.rails.game.specific._1837; +import net.sf.rails.common.GuiDef; +import net.sf.rails.common.GuiDef.Parm; import net.sf.rails.game.GameManager; import net.sf.rails.game.NationalFormationRound; import net.sf.rails.game.Phase; @@ -20,6 +22,7 @@ */ public class GameManager_1837 extends GameManager { + private Round previousRound = null; @@ -127,4 +130,15 @@ public void startKuKFormationRound(OperatingRound_1837 or) { createRound(NationalFormationRound.class, roundName).start(); } + /* (non-Javadoc) + * @see net.sf.rails.game.GameManager#setGuiParameter(net.sf.rails.common.GuiDef.Parm, boolean) + */ + @Override + public void setGuiParameters() { + super.setGuiParameters(); + //Flags the Game that a special Company income is needed... + guiParameters.put(GuiDef.Parm.HAS_SPECIAL_COMPANY_INCOME, true); + + } + } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java index 3c34cfa7c..1a33b3b61 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java @@ -357,7 +357,18 @@ public void payout(int amount, boolean roundUp, boolean b) { shares, operatingCompany.value().getShareUnit())); } + /** + * payout the direct Income from the Coal Mine if any + */ + String partText = Currency.fromBank( operatingCompany.value().getDirectIncomeRevenue(), operatingCompany.value()); + ReportBuffer.add(this, LocalText.getText("Payout", + operatingCompany.getId(), + partText, + " companies treasury." + )); + + // Move the token ((PublicCompany_1837) operatingCompany.value()).payout(amount, b); @@ -373,9 +384,12 @@ protected void executeSetRevenueAndDividend(SetDividend action) { int amount = action.getActualRevenue(); int revenueAllocation = action.getRevenueAllocation(); + int directIncome = action.getActualCompanyTreasuryRevenue(); operatingCompany.value().setLastRevenue(amount); operatingCompany.value().setLastRevenueAllocation(revenueAllocation); + operatingCompany.value().setLastDirectIncome(directIncome); + operatingCompany.value().setDirectIncomeRevenue(directIncome); // Pay any debts from treasury, revenue and/or president's cash // The remaining dividend may be less that the original income diff --git a/src/main/java/net/sf/rails/game/specific/_1837/PublicCompany_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/PublicCompany_1837.java index 632dc4888..e4f5f8e02 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/PublicCompany_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/PublicCompany_1837.java @@ -1,15 +1,18 @@ package net.sf.rails.game.specific._1837; +import net.sf.rails.common.LocalText; +import net.sf.rails.common.ReportBuffer; import net.sf.rails.game.BankPortfolio; import net.sf.rails.game.PublicCertificate; import net.sf.rails.game.PublicCompany; import net.sf.rails.game.RailsItem; import net.sf.rails.game.Train; +import net.sf.rails.game.state.Currency; +import net.sf.rails.game.state.IntegerState; import net.sf.rails.game.state.Owner; public class PublicCompany_1837 extends PublicCompany { - - + public PublicCompany_1837(RailsItem parent, String id) { super(parent, id); } @@ -59,4 +62,10 @@ public boolean isSoldOut() { } return true; } + + /** + * @param coalMineTreasuryBonus the coalMineTreasuryBonus to set + */ + + } diff --git a/src/main/java/net/sf/rails/ui/swing/GameUIManager.java b/src/main/java/net/sf/rails/ui/swing/GameUIManager.java index 4e59ddeec..f90d46a8b 100644 --- a/src/main/java/net/sf/rails/ui/swing/GameUIManager.java +++ b/src/main/java/net/sf/rails/ui/swing/GameUIManager.java @@ -1284,19 +1284,14 @@ public void update(Observable o, Object arg) { } public void deRegister() { - // TODO Auto-generated method stub - } @Override public void update(String text) { - // TODO Auto-generated method stub - } @Override public net.sf.rails.game.state.Observable getObservable() { - // TODO Auto-generated method stub return null; } } diff --git a/src/main/java/net/sf/rails/ui/swing/ORPanel.java b/src/main/java/net/sf/rails/ui/swing/ORPanel.java index 726ac49db..e92aa9b00 100644 --- a/src/main/java/net/sf/rails/ui/swing/ORPanel.java +++ b/src/main/java/net/sf/rails/ui/swing/ORPanel.java @@ -97,14 +97,21 @@ public class ORPanel extends GridPanel private Field newTrainCost[]; private int rightsXOffset, rightsYOffset; private Field rights[]; + /** + * For the direct Income to be entered during the OR Phase + */ + private Spinner directIncomeSelect[]; + private Field directIncomeRevenue[]; + private int bonusRevXOffset, bonusRevYOffset; private boolean privatesCanBeBought = false; private boolean bonusTokensExist = false; private boolean hasCompanyLoans = false; - private boolean hasRights; + private boolean hasRights = false; + private boolean hasDirectCompanyIncomeInOr = false; private Caption tileCaption, tokenCaption, revenueCaption, trainCaption, - privatesCaption, loansCaption; + privatesCaption, loansCaption, directIncomeCaption; private ActionButton buttonOC; // sfy: button for operating costs private ActionButton button1; @@ -148,6 +155,7 @@ public ORPanel(ORWindow parent, ORUIManager orUIManager) { 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); + hasDirectCompanyIncomeInOr= gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.HAS_SPECIAL_COMPANY_INCOME); initButtonPanel(); gbc = new GridBagConstraints(); @@ -421,6 +429,10 @@ private void initFields() { if (hasRights) rights = new Field[nc]; revenue = new Field[nc]; revenueSelect = new Spinner[nc]; + if (hasDirectCompanyIncomeInOr) { + directIncomeRevenue = new Field[nc]; + directIncomeSelect = new Spinner[nc]; + } decision = new Field[nc]; newTrainCost = new Field[nc]; newPrivatesCost = new Field[nc]; @@ -505,6 +517,14 @@ private void initFields() { addField(new Caption("earned"), revXOffset, 1, 1, 1, WIDE_BOTTOM); addField(new Caption("payout"), revXOffset + 1, 1, 1, 1, WIDE_BOTTOM + WIDE_RIGHT); + + if (hasDirectCompanyIncomeInOr) { + bonusRevXOffset = currentXOffset += lastXWidth; + bonusRevYOffset =leftCompNameYOffset; + addField(directIncomeCaption = new Caption("CompanyIncome"), bonusRevXOffset, 0, + lastXWidth = 3, 1, WIDE_RIGHT); + addField(new Caption("income"), revXOffset, 1, 1, 1, WIDE_BOTTOM + WIDE_RIGHT); + } trainsXOffset = currentXOffset += lastXWidth; trainsYOffset = leftCompNameYOffset; @@ -622,6 +642,16 @@ private void initFields() { f = decision[i] = new Field(c.getLastRevenueAllocationModel()); addField(f, revXOffset + 1, revYOffset + i, 1, 1, WIDE_RIGHT, visible); + if(hasDirectCompanyIncomeInOr) { + f = directIncomeRevenue[i] = new Field(c.getLastDirectIncomeModel()); + addField(f, bonusRevXOffset, bonusRevYOffset + i, 1, 1, 0, visible); + + f = directIncomeSelect[i] = new Spinner(0, 0, 0, GameManager.getRevenueSpinnerIncrement()); + + f.setPreferredSize(directIncomeRevenue[i].getPreferredSize()); + addField(f, bonusRevXOffset, bonusRevYOffset + i, 1, 1, 0, false); +} + f = trains[i] = new Field(c.getPortfolioModel().getTrainsModel()); addField(f, trainsXOffset, trainsYOffset + i, 1, 1, 0, visible); @@ -809,7 +839,16 @@ protected void executeNetworkInfo(String companyName) { //convertRcRun might erroneously raise exceptions try {ra.drawOptimalRunAsPath(orUIManager.getMap());} catch (Exception e) {} - + /** + * TODO: Here the automatic calculation of the Special Company Income needs to be implemented + * 1837: Coal Mines + * 1853: Mail Contract + * 1822: Mail Contract + * 1822CA: Mail Contract + * 1854 old/new : Mail Contract ? + */ + + if (!Config.getDevelop()) { //parent component is ORPanel so that dialog won't hide the routes painted on the map JOptionPane.showMessageDialog(this, @@ -899,8 +938,13 @@ public void actionPerformed(ActionEvent actor) { if (executedAction instanceof SetDividend) { // Hide the spinner here, because we might not return // via InitPayoutStep, where this would otherwise be done. + if(hasDirectCompanyIncomeInOr) { + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], + directIncomeSelect[orCompIndex], directIncomeRevenue[orCompIndex], false); + } else { setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], false); + } } orUIManager.processAction(command, executedActions); @@ -962,6 +1006,8 @@ public void actionPerformed(ActionEvent actor) { } } + + public int getRevenue(int orCompIndex) { return ((Integer) revenueSelect[orCompIndex].getValue()).intValue(); @@ -976,6 +1022,9 @@ public void resetActions() { tileCaption.setHighlight(false); tokenCaption.setHighlight(false); revenueCaption.setHighlight(false); + if(hasDirectCompanyIncomeInOr) { + directIncomeCaption.setHighlight(false); + } trainCaption.setHighlight(false); if (privatesCanBeBought) privatesCaption.setHighlight(false); for (int i = 0; i < president.length; i++) { @@ -1001,12 +1050,21 @@ public void resetActions() { public void resetORCompanyTurn(int orCompIndex) { for (int i = 0; i < nc; i++) { + if (hasDirectCompanyIncomeInOr) { + setSelect(revenue[i], revenueSelect[i], directIncomeSelect[i], directIncomeRevenue[i], false); + } else { setSelect(revenue[i], revenueSelect[i], false); + } } } public void resetCurrentRevenueDisplay() { + if (hasDirectCompanyIncomeInOr) { + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], + directIncomeSelect[orCompIndex], directIncomeRevenue[orCompIndex], false); + } else { setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], false); + } } /** @@ -1127,9 +1185,12 @@ public void initRevenueEntryStep(int orCompIndex, SetDividend action) { revenueCaption.setHighlight(true); setHighlight(revenueSelect[orCompIndex],true); revenueSelect[orCompIndex].setValue(action.getPresetRevenue()); - - setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], true); - + if ( hasDirectCompanyIncomeInOr) { + directIncomeSelect[orCompIndex].setValue(action.getPresetCompanyTreasuryRevenue()); + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], directIncomeSelect[orCompIndex], directIncomeRevenue[orCompIndex], true); + } else { + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex],true); + } button1.setRailsIcon(RailsIcon.SET_REVENUE); button1.setActionCommand(SET_REVENUE_CMD); button1.setPossibleAction(action); @@ -1147,6 +1208,12 @@ public void initRevenueEntryStep(int orCompIndex, SetDividend action) { public void revenueUpdate(int bestRevenue, boolean finalResult) { if (isRevenueValueToBeSet) { revenueSelect[orCompIndex].setValue(bestRevenue); + /** + * This needs to have another value for the automatic setting of a Direct Income for a Company + */ + if(hasDirectCompanyIncomeInOr) { + directIncomeSelect[orCompIndex].setValue(0); + } } if (finalResult) { orUIManager.getMap().setTrainPaths(null); @@ -1179,9 +1246,12 @@ public void initPayoutStep(int orCompIndex, SetDividend action, setHighlight(decision[orCompIndex],true); SetDividend clonedAction; - + if(hasDirectCompanyIncomeInOr) { + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], + directIncomeSelect[orCompIndex], directIncomeRevenue[orCompIndex], false); + } else { setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], false); - + } if (withhold) { button1.setRailsIcon(RailsIcon.WITHHOLD); button1.setActionCommand(WITHHOLD_CMD); @@ -1358,6 +1428,15 @@ private void setSelect(JComponent f, JComponent s, boolean active) { f.setVisible(!active); s.setVisible(active); } + + private void setSelect(JComponent f, JComponent s, JComponent s2, + JComponent f2, boolean active) { + f.setVisible(!active); + s.setVisible(active); + f2.setVisible(!active); + s2.setVisible(active); + + } public PublicCompany[] getOperatingCompanies() { return companies; @@ -1397,6 +1476,14 @@ private void setCompanyVisibility(boolean showAll) { setRowVisibility(i + leftCompNameYOffset, visible); } } - + + public int getCompanyTreasuryBonusRevenue(int orCompIndex) { + return ((Integer) directIncomeSelect[orCompIndex].getValue()).intValue(); + } + + public void setTreasuryBonusRevenue(int orCompIndex2, int bonusAmount) { + directIncomeRevenue[orCompIndex2].setText(orUIManager.getGameUIManager().format(bonusAmount)); + + } } diff --git a/src/main/java/net/sf/rails/ui/swing/ORUIManager.java b/src/main/java/net/sf/rails/ui/swing/ORUIManager.java index c94da22d7..82ae90a9a 100644 --- a/src/main/java/net/sf/rails/ui/swing/ORUIManager.java +++ b/src/main/java/net/sf/rails/ui/swing/ORUIManager.java @@ -81,7 +81,7 @@ // Rails 2.0, Even better add a new mechanism that allows to use the standard mechanism for corrections public class ORUIManager implements DialogOwner { - private static Logger log = + protected static Logger log = LoggerFactory.getLogger(ORUIManager.class); protected GameUIManager gameUIManager; @@ -529,7 +529,7 @@ protected boolean processGameSpecificActions(List actions) { } - private void setDividend(String command, SetDividend action) { + protected void setDividend(String command, SetDividend action) { int amount; diff --git a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java index 6d52b52c2..ea49893d1 100644 --- a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java +++ b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java @@ -5,6 +5,7 @@ import javax.swing.JOptionPane; +import rails.game.action.DiscardTrain; import rails.game.action.MergeCompanies; import rails.game.specific._1837.FoldIntoHungary; import rails.game.specific._1837.FoldIntoKuK; @@ -142,5 +143,15 @@ else if (SELECT_MERGING_MAJOR.equals(key)) { // Dialog action found and processed, let the superclass initiate processing. super.dialogActionPerformed(true); } + + /* (non-Javadoc) + * @see net.sf.rails.ui.swing.GameUIManager#discardTrains(rails.game.action.DiscardTrain) + */ + @Override + public void discardTrains(DiscardTrain dt) { + // TODO Auto-generated method stub + super.discardTrains(dt); + } + } diff --git a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java index 5979f7700..5ad6d484f 100644 --- a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java +++ b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java @@ -3,8 +3,11 @@ */ package net.sf.rails.ui.swing.gamespecific._1837; +import net.sf.rails.sound.SoundManager; +import net.sf.rails.ui.swing.ORPanel; import net.sf.rails.ui.swing.ORUIManager; -import rails.game.action.PossibleActions; +import net.sf.rails.ui.swing.ORWindow; +import rails.game.action.SetDividend; /** * @author Martin @@ -20,12 +23,42 @@ public ORUIManager_1837() { } /* (non-Javadoc) - * @see net.sf.rails.ui.swing.ORUIManager#setMapRelatedActions(rails.game.action.PossibleActions) + * @see net.sf.rails.ui.swing.ORUIManager#setDividend(java.lang.String, rails.game.action.SetDividend) */ - @Override - public void setMapRelatedActions(PossibleActions actions) { - // TODO Auto-generated method stub - super.setMapRelatedActions(actions); + protected void setDividend(String command, SetDividend action) { + int amount, bonusAmount; + + if (command.equals(ORPanel.SET_REVENUE_CMD)) { + amount = orPanel.getRevenue(orCompIndex); + bonusAmount = orPanel.getCompanyTreasuryBonusRevenue(orCompIndex); + orPanel.stopRevenueUpdate(); + log.debug("Set revenue amount is " + amount); + log.debug("The Bonus for the company treasury is " + bonusAmount); + action.setActualRevenue(amount); + action.setActualCompanyTreasuryRevenue(bonusAmount); + + // 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()); + orWindow.process(action); + } else { + log.debug("Allocation is unknown, asking for it"); + setLocalStep(LocalSteps.SelectPayout); + updateStatus(action, true); + + // Locally update revenue if we don't inform the server yet. + orPanel.setRevenue(orCompIndex, amount); + orPanel.setTreasuryBonusRevenue(orCompIndex, bonusAmount); + } + } else { + // The revenue allocation has been selected + orWindow.process(action); + } } } diff --git a/src/main/java/rails/game/action/SetDividend.java b/src/main/java/rails/game/action/SetDividend.java index 5708e037f..6c96118d7 100644 --- a/src/main/java/rails/game/action/SetDividend.java +++ b/src/main/java/rails/game/action/SetDividend.java @@ -43,14 +43,14 @@ public class SetDividend extends PossibleORAction implements Cloneable { * future, it will only be true if the user has some influence on it (e.g., * in 1844, the user may opt for less that maximum revenue is some cases). */ - protected boolean mayUserSetRevenue; + private boolean mayUserSetRevenue; /** * The revenue allocations that the user may select from. If only one value * is provided, the user has no option (e.g. minor companies always split in * most games). */ - protected int[] allowedRevenueAllocations; + private int[] allowedRevenueAllocations; /** Cash that should be minimally raised as revenue * (for instance, to pay loan interest as in 1856). @@ -66,23 +66,36 @@ public class SetDividend extends PossibleORAction implements Cloneable { /** The revenue destination selected by the user (if he has a choice at all). */ protected int revenueAllocation; + + /**The + * The direct revenue for the company treasury (not as dividend) as proposed by the back-end. Currently this is always the + * previous revenue. In the future, this could be the calculated revenue. + */ + private int presetCompanyTreasuryRevenue; + private int actualCompanyTreasuryRevenue; public static final long serialVersionUID = 1L; public SetDividend(int presetRevenue, boolean mayUserSetRevenue, int[] allowedAllocations) { - this (presetRevenue, mayUserSetRevenue, allowedAllocations, 0); + this (presetRevenue, 0, mayUserSetRevenue, allowedAllocations, 0); } public SetDividend(int presetRevenue, boolean mayUserSetRevenue, int[] allowedAllocations, int requiredCash) { + this (presetRevenue, 0, mayUserSetRevenue, allowedAllocations, requiredCash); + } + + public SetDividend(int presetRevenue, int presetCompanyTreasuryRevenue, boolean mayUserSetRevenue, + int[] allowedAllocations, int requiredCash) { super(); this.presetRevenue = presetRevenue; - this.mayUserSetRevenue = mayUserSetRevenue; - this.allowedRevenueAllocations = allowedAllocations.clone(); + this.presetCompanyTreasuryRevenue = presetCompanyTreasuryRevenue; + this.setMayUserSetRevenue(mayUserSetRevenue); + this.setAllowedRevenueAllocations(allowedAllocations.clone()); this.requiredCash = requiredCash; - if (allowedRevenueAllocations.length == 1) { - revenueAllocation = allowedRevenueAllocations[0]; + if (getAllowedRevenueAllocations().length == 1) { + revenueAllocation = getAllowedRevenueAllocations()[0]; } else { revenueAllocation = UNKNOWN; } @@ -90,8 +103,8 @@ public SetDividend(int presetRevenue, boolean mayUserSetRevenue, /** Clone an instance (used by clone) */ protected SetDividend(SetDividend action) { - this(action.presetRevenue, action.mayUserSetRevenue, - action.allowedRevenueAllocations, + this(action.presetRevenue, action.getMayUserSetRevenue(), + action.getAllowedRevenueAllocations(), action.requiredCash); } @@ -107,12 +120,25 @@ public int getActualRevenue() { return actualRevenue; } + public void setActualCompanyTreasuryRevenue( + int actualCompanyTreasuryRevenue2) { + this.actualCompanyTreasuryRevenue = actualCompanyTreasuryRevenue2; + } + + public int getActualCompanyTreasuryRevenue() { + return actualCompanyTreasuryRevenue; + } + + public int getPresetCompanyTreasuryRevenue() { + return presetCompanyTreasuryRevenue; + } + public int[] getAllowedAllocations() { - return allowedRevenueAllocations; + return getAllowedRevenueAllocations(); } public boolean isAllocationAllowed(int allocationType) { - for (int at : allowedRevenueAllocations) { + for (int at : getAllowedRevenueAllocations()) { if (at == allocationType) return true; } return false; @@ -143,6 +169,7 @@ public Object clone() { SetDividend result = new SetDividend(this); result.setActualRevenue(actualRevenue); + result.setActualCompanyTreasuryRevenue(actualCompanyTreasuryRevenue); result.setRevenueAllocation(revenueAllocation); return result; } @@ -158,8 +185,9 @@ protected boolean equalsAs(PossibleAction pa, boolean asOption) { SetDividend action = (SetDividend)pa; boolean options = Objects.equal(this.presetRevenue, action.presetRevenue) - && Objects.equal(this.mayUserSetRevenue, action.mayUserSetRevenue) - && Arrays.equals(this.allowedRevenueAllocations, action.allowedRevenueAllocations) + && Objects.equal(this.presetCompanyTreasuryRevenue, action.presetCompanyTreasuryRevenue) + && Objects.equal(this.getMayUserSetRevenue(), action.getMayUserSetRevenue()) + && Arrays.equals(this.getAllowedRevenueAllocations(), action.getAllowedRevenueAllocations()) && Objects.equal(this.requiredCash, action.requiredCash) ; @@ -169,6 +197,7 @@ protected boolean equalsAs(PossibleAction pa, boolean asOption) { // check asAction attributes return options && Objects.equal(this.actualRevenue, action.actualRevenue) + && Objects.equal(this.actualCompanyTreasuryRevenue, action.actualCompanyTreasuryRevenue) && Objects.equal(this.revenueAllocation, action.revenueAllocation) ; } @@ -178,10 +207,12 @@ public String toString() { return super.toString() + RailsObjects.stringHelper(this) .addToString("presetRevenue", presetRevenue) - .addToString("mayUserSetRevenue", mayUserSetRevenue) - .addToString("allowedRevenueAllocations", allowedRevenueAllocations) + .addToString("PresetTreasuryBonusRevenue",presetCompanyTreasuryRevenue) + .addToString("mayUserSetRevenue", getMayUserSetRevenue()) + .addToString("allowedRevenueAllocations", getAllowedRevenueAllocations()) .addToString("requiredCash", requiredCash) .addToStringOnlyActed("actualRevenue", actualRevenue) + .addToStringOnlyActed("actualCompanyTreasuryRevenue", actualCompanyTreasuryRevenue) .addToStringOnlyActed("revenueAllocation", revenueAllocation) .toString() ; @@ -194,10 +225,12 @@ private void readObject(ObjectInputStream in) throws IOException, // Custom deserialization for backwards compatibility ObjectInputStream.GetField fields = in.readFields(); presetRevenue = fields.get("presetRevenue", presetRevenue); - mayUserSetRevenue = fields.get("mayUserSetRevenue", mayUserSetRevenue); - allowedRevenueAllocations = (int[]) fields.get("allowedRevenueAllocations", allowedRevenueAllocations); + presetCompanyTreasuryRevenue = fields.get("PresetTreasuryBonusRevenue",presetCompanyTreasuryRevenue); + setMayUserSetRevenue(fields.get("mayUserSetRevenue", getMayUserSetRevenue())); + setAllowedRevenueAllocations((int[]) fields.get("allowedRevenueAllocations", getAllowedRevenueAllocations())); requiredCash = fields.get("requiredCash", 0); actualRevenue = fields.get("actualRevenue", actualRevenue); + actualCompanyTreasuryRevenue = fields.get("actualCompanyTreasuryRevenue", actualCompanyTreasuryRevenue); revenueAllocation = fields.get("revenueAllocation", revenueAllocation); if (Util.hasValue(companyName)) { @@ -205,4 +238,21 @@ private void readObject(ObjectInputStream in) throws IOException, } } + public boolean getMayUserSetRevenue() { + return mayUserSetRevenue; + } + + public void setMayUserSetRevenue(boolean mayUserSetRevenue) { + this.mayUserSetRevenue = mayUserSetRevenue; + } + + public int[] getAllowedRevenueAllocations() { + return allowedRevenueAllocations; + } + + public void setAllowedRevenueAllocations( + int[] allowedRevenueAllocations) { + this.allowedRevenueAllocations = allowedRevenueAllocations; + } + } diff --git a/src/main/resources/data/1837/Game.xml b/src/main/resources/data/1837/Game.xml index 117e7365f..69d15e19c 100644 --- a/src/main/resources/data/1837/Game.xml +++ b/src/main/resources/data/1837/Game.xml @@ -16,6 +16,7 @@ + @@ -207,7 +208,7 @@ haven't already. --> - + @@ -220,5 +221,8 @@ + diff --git a/src/main/resources/data/1837/GameOptions.xml b/src/main/resources/data/1837/GameOptions.xml index 44cffd39c..a303bc1b8 100644 --- a/src/main/resources/data/1837/GameOptions.xml +++ b/src/main/resources/data/1837/GameOptions.xml @@ -3,7 +3,7 @@ - + From d60f21ad62f273fb3f1b2ce3aa1dc242f9fdd89f Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Tue, 25 Dec 2018 09:21:44 +0100 Subject: [PATCH 20/45] Preparation and implementation of Actions for introducing the Special Company Treasury Incomes. This is needed for a seperate income during the OR not tied to the private company income but stemming from the additional revenue coming from special trains (Coal Trains in 1837) or special powers like a Mail Contract. --- src/main/java/net/sf/rails/common/GuiDef.java | 4 +- .../net/sf/rails/game/OperatingRound.java | 2 +- .../java/net/sf/rails/game/PublicCompany.java | 36 ++++++ .../game/specific/_1837/GameManager_1837.java | 14 +++ .../specific/_1837/OperatingRound_1837.java | 35 ++++++ .../specific/_1837/PublicCompany_1837.java | 13 ++- .../_1837/StartAtCoalMineModifier.java | 67 +++++++++++ .../net/sf/rails/ui/swing/GameUIManager.java | 5 - .../java/net/sf/rails/ui/swing/ORPanel.java | 105 ++++++++++++++++-- .../net/sf/rails/ui/swing/ORUIManager.java | 4 +- .../_1837/GameUIManager_1837.java | 11 ++ .../gamespecific/_1837/ORUIManager_1837.java | 45 +++++++- .../java/rails/game/action/SetDividend.java | 101 +++++++++++++---- src/main/resources/data/1837/Game.xml | 6 +- src/main/resources/data/1837/GameOptions.xml | 2 +- 15 files changed, 397 insertions(+), 53 deletions(-) create mode 100644 src/main/java/net/sf/rails/game/specific/_1837/StartAtCoalMineModifier.java diff --git a/src/main/java/net/sf/rails/common/GuiDef.java b/src/main/java/net/sf/rails/common/GuiDef.java index 12778b113..51fc24c06 100644 --- a/src/main/java/net/sf/rails/common/GuiDef.java +++ b/src/main/java/net/sf/rails/common/GuiDef.java @@ -3,7 +3,6 @@ public class GuiDef { /** Identifiers and default names for configurable UI classes */ - // FIXME: Rails 2.0 move this to xml files public enum ClassName { GAME_UI_MANAGER ("net.sf.rails.ui.swing.GameUIManager"), @@ -42,7 +41,8 @@ public enum Parm { HAS_ANY_RIGHTS, NO_MAP_MODE, REVENUE_SUGGEST, - ROUTE_HIGHLIGHT, PLAYER_ORDER_VARIES + ROUTE_HIGHLIGHT, + PLAYER_ORDER_VARIES, HAS_SPECIAL_COMPANY_INCOME } /** diff --git a/src/main/java/net/sf/rails/game/OperatingRound.java b/src/main/java/net/sf/rails/game/OperatingRound.java index 7f901a07d..f599ab33d 100644 --- a/src/main/java/net/sf/rails/game/OperatingRound.java +++ b/src/main/java/net/sf/rails/game/OperatingRound.java @@ -2564,7 +2564,7 @@ public void payout(int amount) { recipient.getId(), partText, shares, operatingCompany.value().getShareUnit())); } - + // Move the token operatingCompany.value().payout(amount); diff --git a/src/main/java/net/sf/rails/game/PublicCompany.java b/src/main/java/net/sf/rails/game/PublicCompany.java index 501f4b4fd..d21a8f6ab 100644 --- a/src/main/java/net/sf/rails/game/PublicCompany.java +++ b/src/main/java/net/sf/rails/game/PublicCompany.java @@ -132,6 +132,11 @@ public class PublicCompany extends RailsAbstractItem implements Company, RailsMo /** Most recent revenue earned. */ protected final CountingMoneyModel lastRevenue = CountingMoneyModel.create(this, "lastRevenue", false); + public final CountingMoneyModel directIncomeRevenue = CountingMoneyModel.create(this, "directIncome", false); + + /** Most recent Direct Company Treasury income earned. */ + protected final CountingMoneyModel lastDirectIncome = CountingMoneyModel.create(this, "lastDirectIncome", false); + /** Most recent payout decision. */ protected final StringState lastRevenueAllocation = StringState.create(this, "lastRevenueAllocation"); @@ -303,6 +308,7 @@ public class PublicCompany extends RailsAbstractItem implements Company, RailsMo private String foundingStartCompany = null; + /** * Used by Configure (via reflection) only */ @@ -2038,6 +2044,36 @@ public String getFoundingStartCompany() { public void setStartingMinor(String foundingCompany) { this.foundingStartCompany = foundingCompany; } + + + public Model getLastDirectIncomeModel() { + return lastDirectIncome; + } + /** + * Store the last direct Income earned by this company. + * + * @param i The last revenue amount. + */ + public void setLastDirectIncome(int i) { + lastDirectIncome.set(i); + } + + /** + * Get the last directIncome earned by this company. + * + * @return The last revenue amount. + */ + public int getLastDirectIncome() { + return lastDirectIncome.value(); + } + + public void setDirectIncomeRevenue(int directIncome) { + this.directIncomeRevenue.set(directIncome); + } + public int getDirectIncomeRevenue() { + return directIncomeRevenue.value(); + } + } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java index 818e01a7b..c8ae59736 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java @@ -3,6 +3,8 @@ */ package net.sf.rails.game.specific._1837; +import net.sf.rails.common.GuiDef; +import net.sf.rails.common.GuiDef.Parm; import net.sf.rails.game.GameManager; import net.sf.rails.game.NationalFormationRound; import net.sf.rails.game.Phase; @@ -20,6 +22,7 @@ */ public class GameManager_1837 extends GameManager { + private Round previousRound = null; @@ -127,4 +130,15 @@ public void startKuKFormationRound(OperatingRound_1837 or) { createRound(NationalFormationRound.class, roundName).start(); } + /* (non-Javadoc) + * @see net.sf.rails.game.GameManager#setGuiParameter(net.sf.rails.common.GuiDef.Parm, boolean) + */ + @Override + public void setGuiParameters() { + super.setGuiParameters(); + //Flags the Game that a special Company income is needed... + guiParameters.put(GuiDef.Parm.HAS_SPECIAL_COMPANY_INCOME, true); + + } + } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java index 3c34cfa7c..ad5ac196e 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java @@ -357,7 +357,18 @@ public void payout(int amount, boolean roundUp, boolean b) { shares, operatingCompany.value().getShareUnit())); } + /** + * payout the direct Income from the Coal Mine if any + */ + String partText = Currency.fromBank( operatingCompany.value().getDirectIncomeRevenue(), operatingCompany.value()); + ReportBuffer.add(this, LocalText.getText("Payout", + operatingCompany.getId(), + partText, + " companies treasury." + )); + + // Move the token ((PublicCompany_1837) operatingCompany.value()).payout(amount, b); @@ -373,9 +384,12 @@ protected void executeSetRevenueAndDividend(SetDividend action) { int amount = action.getActualRevenue(); int revenueAllocation = action.getRevenueAllocation(); + int directIncome = action.getActualCompanyTreasuryRevenue(); operatingCompany.value().setLastRevenue(amount); operatingCompany.value().setLastRevenueAllocation(revenueAllocation); + operatingCompany.value().setLastDirectIncome(directIncome); + operatingCompany.value().setDirectIncomeRevenue(directIncome); // Pay any debts from treasury, revenue and/or president's cash // The remaining dividend may be less that the original income @@ -456,4 +470,25 @@ protected boolean gameSpecificTileLayAllowed(PublicCompany company, } return true; } + + + protected void prepareRevenueAndDividendAction() { + + // There is only revenue if there are any trains + if (operatingCompany.value().canRunTrains()) { + int[] allowedRevenueActions = + operatingCompany.value().isSplitAlways() + ? new int[] { SetDividend.SPLIT } + : operatingCompany.value().isSplitAllowed() + ? new int[] { SetDividend.PAYOUT, + SetDividend.SPLIT, + SetDividend.WITHHOLD } : new int[] { + SetDividend.PAYOUT, + SetDividend.WITHHOLD }; + + possibleActions.add(new SetDividend( + operatingCompany.value().getLastRevenue(), operatingCompany.value().getLastDirectIncome(), true, + allowedRevenueActions,0)); + } + } } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/PublicCompany_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/PublicCompany_1837.java index 632dc4888..e4f5f8e02 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/PublicCompany_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/PublicCompany_1837.java @@ -1,15 +1,18 @@ package net.sf.rails.game.specific._1837; +import net.sf.rails.common.LocalText; +import net.sf.rails.common.ReportBuffer; import net.sf.rails.game.BankPortfolio; import net.sf.rails.game.PublicCertificate; import net.sf.rails.game.PublicCompany; import net.sf.rails.game.RailsItem; import net.sf.rails.game.Train; +import net.sf.rails.game.state.Currency; +import net.sf.rails.game.state.IntegerState; import net.sf.rails.game.state.Owner; public class PublicCompany_1837 extends PublicCompany { - - + public PublicCompany_1837(RailsItem parent, String id) { super(parent, id); } @@ -59,4 +62,10 @@ public boolean isSoldOut() { } return true; } + + /** + * @param coalMineTreasuryBonus the coalMineTreasuryBonus to set + */ + + } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StartAtCoalMineModifier.java b/src/main/java/net/sf/rails/game/specific/_1837/StartAtCoalMineModifier.java new file mode 100644 index 000000000..25ac2bd7f --- /dev/null +++ b/src/main/java/net/sf/rails/game/specific/_1837/StartAtCoalMineModifier.java @@ -0,0 +1,67 @@ +package net.sf.rails.game.specific._1837; + +import java.util.ArrayList; +import java.util.List; + +import net.sf.rails.algorithms.RevenueAdapter; +import net.sf.rails.algorithms.RevenueDynamicModifier; +import net.sf.rails.algorithms.RevenueTrainRun; + + +public class StartAtCoalMineModifier implements RevenueDynamicModifier { + + public boolean prepareModifier(RevenueAdapter revenueAdapter) { + // always active + return true; + } + + public int predictionValue(List runs) { + // cannot be predicted + return 0; + } + + private List identifyInvalidRuns(List runs) { + // check if runs end and start at major stations + List invalidRuns = new ArrayList(); + for (RevenueTrainRun run:runs) { + if (!run.hasAValidRun()) continue; + if (!run.getFirstVertex().isMajor() || !run.getLastVertex().isMajor()) { + invalidRuns.add(run); + } + } + return invalidRuns; + } + + public int evaluationValue(List runs, boolean optimalRuns) { + // optimal runs is already adjusted + if (optimalRuns) return 0; + // otherwise check invalid runs + int changeRevenues = 0; + for (RevenueTrainRun run:identifyInvalidRuns(runs)) { + changeRevenues -= run.getRunValue(); + } + return changeRevenues; + } + + public void adjustOptimalRun(List optimalRuns) { + // set invalid runs to be empty + for (RevenueTrainRun run:identifyInvalidRuns(optimalRuns)) { + run.getRunVertices().clear(); + } + } + public boolean providesOwnCalculateRevenue() { + // does not + return false; + } + + public int calculateRevenue(RevenueAdapter revenueAdpater) { + // zero does no change + return 0; + } + + public String prettyPrint(RevenueAdapter adapter) { + // nothing to do + return null; + } + +} diff --git a/src/main/java/net/sf/rails/ui/swing/GameUIManager.java b/src/main/java/net/sf/rails/ui/swing/GameUIManager.java index 4e59ddeec..f90d46a8b 100644 --- a/src/main/java/net/sf/rails/ui/swing/GameUIManager.java +++ b/src/main/java/net/sf/rails/ui/swing/GameUIManager.java @@ -1284,19 +1284,14 @@ public void update(Observable o, Object arg) { } public void deRegister() { - // TODO Auto-generated method stub - } @Override public void update(String text) { - // TODO Auto-generated method stub - } @Override public net.sf.rails.game.state.Observable getObservable() { - // TODO Auto-generated method stub return null; } } diff --git a/src/main/java/net/sf/rails/ui/swing/ORPanel.java b/src/main/java/net/sf/rails/ui/swing/ORPanel.java index 726ac49db..e92aa9b00 100644 --- a/src/main/java/net/sf/rails/ui/swing/ORPanel.java +++ b/src/main/java/net/sf/rails/ui/swing/ORPanel.java @@ -97,14 +97,21 @@ public class ORPanel extends GridPanel private Field newTrainCost[]; private int rightsXOffset, rightsYOffset; private Field rights[]; + /** + * For the direct Income to be entered during the OR Phase + */ + private Spinner directIncomeSelect[]; + private Field directIncomeRevenue[]; + private int bonusRevXOffset, bonusRevYOffset; private boolean privatesCanBeBought = false; private boolean bonusTokensExist = false; private boolean hasCompanyLoans = false; - private boolean hasRights; + private boolean hasRights = false; + private boolean hasDirectCompanyIncomeInOr = false; private Caption tileCaption, tokenCaption, revenueCaption, trainCaption, - privatesCaption, loansCaption; + privatesCaption, loansCaption, directIncomeCaption; private ActionButton buttonOC; // sfy: button for operating costs private ActionButton button1; @@ -148,6 +155,7 @@ public ORPanel(ORWindow parent, ORUIManager orUIManager) { 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); + hasDirectCompanyIncomeInOr= gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.HAS_SPECIAL_COMPANY_INCOME); initButtonPanel(); gbc = new GridBagConstraints(); @@ -421,6 +429,10 @@ private void initFields() { if (hasRights) rights = new Field[nc]; revenue = new Field[nc]; revenueSelect = new Spinner[nc]; + if (hasDirectCompanyIncomeInOr) { + directIncomeRevenue = new Field[nc]; + directIncomeSelect = new Spinner[nc]; + } decision = new Field[nc]; newTrainCost = new Field[nc]; newPrivatesCost = new Field[nc]; @@ -505,6 +517,14 @@ private void initFields() { addField(new Caption("earned"), revXOffset, 1, 1, 1, WIDE_BOTTOM); addField(new Caption("payout"), revXOffset + 1, 1, 1, 1, WIDE_BOTTOM + WIDE_RIGHT); + + if (hasDirectCompanyIncomeInOr) { + bonusRevXOffset = currentXOffset += lastXWidth; + bonusRevYOffset =leftCompNameYOffset; + addField(directIncomeCaption = new Caption("CompanyIncome"), bonusRevXOffset, 0, + lastXWidth = 3, 1, WIDE_RIGHT); + addField(new Caption("income"), revXOffset, 1, 1, 1, WIDE_BOTTOM + WIDE_RIGHT); + } trainsXOffset = currentXOffset += lastXWidth; trainsYOffset = leftCompNameYOffset; @@ -622,6 +642,16 @@ private void initFields() { f = decision[i] = new Field(c.getLastRevenueAllocationModel()); addField(f, revXOffset + 1, revYOffset + i, 1, 1, WIDE_RIGHT, visible); + if(hasDirectCompanyIncomeInOr) { + f = directIncomeRevenue[i] = new Field(c.getLastDirectIncomeModel()); + addField(f, bonusRevXOffset, bonusRevYOffset + i, 1, 1, 0, visible); + + f = directIncomeSelect[i] = new Spinner(0, 0, 0, GameManager.getRevenueSpinnerIncrement()); + + f.setPreferredSize(directIncomeRevenue[i].getPreferredSize()); + addField(f, bonusRevXOffset, bonusRevYOffset + i, 1, 1, 0, false); +} + f = trains[i] = new Field(c.getPortfolioModel().getTrainsModel()); addField(f, trainsXOffset, trainsYOffset + i, 1, 1, 0, visible); @@ -809,7 +839,16 @@ protected void executeNetworkInfo(String companyName) { //convertRcRun might erroneously raise exceptions try {ra.drawOptimalRunAsPath(orUIManager.getMap());} catch (Exception e) {} - + /** + * TODO: Here the automatic calculation of the Special Company Income needs to be implemented + * 1837: Coal Mines + * 1853: Mail Contract + * 1822: Mail Contract + * 1822CA: Mail Contract + * 1854 old/new : Mail Contract ? + */ + + if (!Config.getDevelop()) { //parent component is ORPanel so that dialog won't hide the routes painted on the map JOptionPane.showMessageDialog(this, @@ -899,8 +938,13 @@ public void actionPerformed(ActionEvent actor) { if (executedAction instanceof SetDividend) { // Hide the spinner here, because we might not return // via InitPayoutStep, where this would otherwise be done. + if(hasDirectCompanyIncomeInOr) { + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], + directIncomeSelect[orCompIndex], directIncomeRevenue[orCompIndex], false); + } else { setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], false); + } } orUIManager.processAction(command, executedActions); @@ -962,6 +1006,8 @@ public void actionPerformed(ActionEvent actor) { } } + + public int getRevenue(int orCompIndex) { return ((Integer) revenueSelect[orCompIndex].getValue()).intValue(); @@ -976,6 +1022,9 @@ public void resetActions() { tileCaption.setHighlight(false); tokenCaption.setHighlight(false); revenueCaption.setHighlight(false); + if(hasDirectCompanyIncomeInOr) { + directIncomeCaption.setHighlight(false); + } trainCaption.setHighlight(false); if (privatesCanBeBought) privatesCaption.setHighlight(false); for (int i = 0; i < president.length; i++) { @@ -1001,12 +1050,21 @@ public void resetActions() { public void resetORCompanyTurn(int orCompIndex) { for (int i = 0; i < nc; i++) { + if (hasDirectCompanyIncomeInOr) { + setSelect(revenue[i], revenueSelect[i], directIncomeSelect[i], directIncomeRevenue[i], false); + } else { setSelect(revenue[i], revenueSelect[i], false); + } } } public void resetCurrentRevenueDisplay() { + if (hasDirectCompanyIncomeInOr) { + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], + directIncomeSelect[orCompIndex], directIncomeRevenue[orCompIndex], false); + } else { setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], false); + } } /** @@ -1127,9 +1185,12 @@ public void initRevenueEntryStep(int orCompIndex, SetDividend action) { revenueCaption.setHighlight(true); setHighlight(revenueSelect[orCompIndex],true); revenueSelect[orCompIndex].setValue(action.getPresetRevenue()); - - setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], true); - + if ( hasDirectCompanyIncomeInOr) { + directIncomeSelect[orCompIndex].setValue(action.getPresetCompanyTreasuryRevenue()); + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], directIncomeSelect[orCompIndex], directIncomeRevenue[orCompIndex], true); + } else { + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex],true); + } button1.setRailsIcon(RailsIcon.SET_REVENUE); button1.setActionCommand(SET_REVENUE_CMD); button1.setPossibleAction(action); @@ -1147,6 +1208,12 @@ public void initRevenueEntryStep(int orCompIndex, SetDividend action) { public void revenueUpdate(int bestRevenue, boolean finalResult) { if (isRevenueValueToBeSet) { revenueSelect[orCompIndex].setValue(bestRevenue); + /** + * This needs to have another value for the automatic setting of a Direct Income for a Company + */ + if(hasDirectCompanyIncomeInOr) { + directIncomeSelect[orCompIndex].setValue(0); + } } if (finalResult) { orUIManager.getMap().setTrainPaths(null); @@ -1179,9 +1246,12 @@ public void initPayoutStep(int orCompIndex, SetDividend action, setHighlight(decision[orCompIndex],true); SetDividend clonedAction; - + if(hasDirectCompanyIncomeInOr) { + setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], + directIncomeSelect[orCompIndex], directIncomeRevenue[orCompIndex], false); + } else { setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], false); - + } if (withhold) { button1.setRailsIcon(RailsIcon.WITHHOLD); button1.setActionCommand(WITHHOLD_CMD); @@ -1358,6 +1428,15 @@ private void setSelect(JComponent f, JComponent s, boolean active) { f.setVisible(!active); s.setVisible(active); } + + private void setSelect(JComponent f, JComponent s, JComponent s2, + JComponent f2, boolean active) { + f.setVisible(!active); + s.setVisible(active); + f2.setVisible(!active); + s2.setVisible(active); + + } public PublicCompany[] getOperatingCompanies() { return companies; @@ -1397,6 +1476,14 @@ private void setCompanyVisibility(boolean showAll) { setRowVisibility(i + leftCompNameYOffset, visible); } } - + + public int getCompanyTreasuryBonusRevenue(int orCompIndex) { + return ((Integer) directIncomeSelect[orCompIndex].getValue()).intValue(); + } + + public void setTreasuryBonusRevenue(int orCompIndex2, int bonusAmount) { + directIncomeRevenue[orCompIndex2].setText(orUIManager.getGameUIManager().format(bonusAmount)); + + } } diff --git a/src/main/java/net/sf/rails/ui/swing/ORUIManager.java b/src/main/java/net/sf/rails/ui/swing/ORUIManager.java index c94da22d7..82ae90a9a 100644 --- a/src/main/java/net/sf/rails/ui/swing/ORUIManager.java +++ b/src/main/java/net/sf/rails/ui/swing/ORUIManager.java @@ -81,7 +81,7 @@ // Rails 2.0, Even better add a new mechanism that allows to use the standard mechanism for corrections public class ORUIManager implements DialogOwner { - private static Logger log = + protected static Logger log = LoggerFactory.getLogger(ORUIManager.class); protected GameUIManager gameUIManager; @@ -529,7 +529,7 @@ protected boolean processGameSpecificActions(List actions) { } - private void setDividend(String command, SetDividend action) { + protected void setDividend(String command, SetDividend action) { int amount; diff --git a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java index 6d52b52c2..ea49893d1 100644 --- a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java +++ b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/GameUIManager_1837.java @@ -5,6 +5,7 @@ import javax.swing.JOptionPane; +import rails.game.action.DiscardTrain; import rails.game.action.MergeCompanies; import rails.game.specific._1837.FoldIntoHungary; import rails.game.specific._1837.FoldIntoKuK; @@ -142,5 +143,15 @@ else if (SELECT_MERGING_MAJOR.equals(key)) { // Dialog action found and processed, let the superclass initiate processing. super.dialogActionPerformed(true); } + + /* (non-Javadoc) + * @see net.sf.rails.ui.swing.GameUIManager#discardTrains(rails.game.action.DiscardTrain) + */ + @Override + public void discardTrains(DiscardTrain dt) { + // TODO Auto-generated method stub + super.discardTrains(dt); + } + } diff --git a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java index 5979f7700..5ad6d484f 100644 --- a/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java +++ b/src/main/java/net/sf/rails/ui/swing/gamespecific/_1837/ORUIManager_1837.java @@ -3,8 +3,11 @@ */ package net.sf.rails.ui.swing.gamespecific._1837; +import net.sf.rails.sound.SoundManager; +import net.sf.rails.ui.swing.ORPanel; import net.sf.rails.ui.swing.ORUIManager; -import rails.game.action.PossibleActions; +import net.sf.rails.ui.swing.ORWindow; +import rails.game.action.SetDividend; /** * @author Martin @@ -20,12 +23,42 @@ public ORUIManager_1837() { } /* (non-Javadoc) - * @see net.sf.rails.ui.swing.ORUIManager#setMapRelatedActions(rails.game.action.PossibleActions) + * @see net.sf.rails.ui.swing.ORUIManager#setDividend(java.lang.String, rails.game.action.SetDividend) */ - @Override - public void setMapRelatedActions(PossibleActions actions) { - // TODO Auto-generated method stub - super.setMapRelatedActions(actions); + protected void setDividend(String command, SetDividend action) { + int amount, bonusAmount; + + if (command.equals(ORPanel.SET_REVENUE_CMD)) { + amount = orPanel.getRevenue(orCompIndex); + bonusAmount = orPanel.getCompanyTreasuryBonusRevenue(orCompIndex); + orPanel.stopRevenueUpdate(); + log.debug("Set revenue amount is " + amount); + log.debug("The Bonus for the company treasury is " + bonusAmount); + action.setActualRevenue(amount); + action.setActualCompanyTreasuryRevenue(bonusAmount); + + // 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()); + orWindow.process(action); + } else { + log.debug("Allocation is unknown, asking for it"); + setLocalStep(LocalSteps.SelectPayout); + updateStatus(action, true); + + // Locally update revenue if we don't inform the server yet. + orPanel.setRevenue(orCompIndex, amount); + orPanel.setTreasuryBonusRevenue(orCompIndex, bonusAmount); + } + } else { + // The revenue allocation has been selected + orWindow.process(action); + } } } diff --git a/src/main/java/rails/game/action/SetDividend.java b/src/main/java/rails/game/action/SetDividend.java index 5708e037f..e1da11099 100644 --- a/src/main/java/rails/game/action/SetDividend.java +++ b/src/main/java/rails/game/action/SetDividend.java @@ -43,14 +43,14 @@ public class SetDividend extends PossibleORAction implements Cloneable { * future, it will only be true if the user has some influence on it (e.g., * in 1844, the user may opt for less that maximum revenue is some cases). */ - protected boolean mayUserSetRevenue; + private boolean mayUserSetRevenue = true; /** * The revenue allocations that the user may select from. If only one value * is provided, the user has no option (e.g. minor companies always split in * most games). */ - protected int[] allowedRevenueAllocations; + private int[] allowedRevenueAllocations; /** Cash that should be minimally raised as revenue * (for instance, to pay loan interest as in 1856). @@ -62,36 +62,52 @@ public class SetDividend extends PossibleORAction implements Cloneable { /*--- Client-side settings ---*/ /** The revenue as set (or accepted, or just seen) by the user. */ - protected int actualRevenue; + protected int actualRevenue = 0; /** The revenue destination selected by the user (if he has a choice at all). */ protected int revenueAllocation; + + /**The + * The direct revenue for the company treasury (not as dividend) as proposed by the back-end. Currently this is always the + * previous revenue. In the future, this could be the calculated revenue. + */ + private int presetCompanyTreasuryRevenue = 0; + private int actualCompanyTreasuryRevenue = 0; public static final long serialVersionUID = 1L; - public SetDividend(int presetRevenue, boolean mayUserSetRevenue, - int[] allowedAllocations) { - this (presetRevenue, mayUserSetRevenue, allowedAllocations, 0); - } - - public SetDividend(int presetRevenue, boolean mayUserSetRevenue, - int[] allowedAllocations, int requiredCash) { + + public SetDividend(int presetRevenue, int presetCompanyTreasuryRevenue, boolean mayUserSetRevenue, + int[] allowedAllocations, int requiredCash) { super(); this.presetRevenue = presetRevenue; - this.mayUserSetRevenue = mayUserSetRevenue; - this.allowedRevenueAllocations = allowedAllocations.clone(); + this.presetCompanyTreasuryRevenue = presetCompanyTreasuryRevenue; + this.setMayUserSetRevenue(mayUserSetRevenue); + this.setAllowedRevenueAllocations(allowedAllocations.clone()); this.requiredCash = requiredCash; - if (allowedRevenueAllocations.length == 1) { - revenueAllocation = allowedRevenueAllocations[0]; + if (getAllowedRevenueAllocations().length == 1) { + revenueAllocation = getAllowedRevenueAllocations()[0]; } else { revenueAllocation = UNKNOWN; } } + public SetDividend(int presetRevenue, boolean mayUserSetRevenue, + int[] allowedAllocations) { + this (presetRevenue, 0, mayUserSetRevenue, allowedAllocations, 0); + } + + public SetDividend(int presetRevenue, boolean mayUserSetRevenue, + int[] allowedAllocations, int requiredCash) { + this (presetRevenue, 0, mayUserSetRevenue, allowedAllocations, requiredCash); + } + /** Clone an instance (used by clone) */ protected SetDividend(SetDividend action) { - this(action.presetRevenue, action.mayUserSetRevenue, - action.allowedRevenueAllocations, + this(action.presetRevenue, + action.presetCompanyTreasuryRevenue, + action.getMayUserSetRevenue(), + action.getAllowedRevenueAllocations(), action.requiredCash); } @@ -107,12 +123,25 @@ public int getActualRevenue() { return actualRevenue; } + public void setActualCompanyTreasuryRevenue( + int actualCompanyTreasuryRevenue) { + this.actualCompanyTreasuryRevenue = actualCompanyTreasuryRevenue; + } + + public int getActualCompanyTreasuryRevenue() { + return actualCompanyTreasuryRevenue; + } + + public int getPresetCompanyTreasuryRevenue() { + return presetCompanyTreasuryRevenue; + } + public int[] getAllowedAllocations() { - return allowedRevenueAllocations; + return getAllowedRevenueAllocations(); } public boolean isAllocationAllowed(int allocationType) { - for (int at : allowedRevenueAllocations) { + for (int at : getAllowedRevenueAllocations()) { if (at == allocationType) return true; } return false; @@ -143,6 +172,7 @@ public Object clone() { SetDividend result = new SetDividend(this); result.setActualRevenue(actualRevenue); + result.setActualCompanyTreasuryRevenue(actualCompanyTreasuryRevenue); result.setRevenueAllocation(revenueAllocation); return result; } @@ -158,8 +188,9 @@ protected boolean equalsAs(PossibleAction pa, boolean asOption) { SetDividend action = (SetDividend)pa; boolean options = Objects.equal(this.presetRevenue, action.presetRevenue) - && Objects.equal(this.mayUserSetRevenue, action.mayUserSetRevenue) - && Arrays.equals(this.allowedRevenueAllocations, action.allowedRevenueAllocations) + && Objects.equal(this.presetCompanyTreasuryRevenue, action.presetCompanyTreasuryRevenue) + && Objects.equal(this.getMayUserSetRevenue(), action.getMayUserSetRevenue()) + && Arrays.equals(this.getAllowedRevenueAllocations(), action.getAllowedRevenueAllocations()) && Objects.equal(this.requiredCash, action.requiredCash) ; @@ -169,6 +200,7 @@ protected boolean equalsAs(PossibleAction pa, boolean asOption) { // check asAction attributes return options && Objects.equal(this.actualRevenue, action.actualRevenue) + && Objects.equal(this.actualCompanyTreasuryRevenue, action.actualCompanyTreasuryRevenue) && Objects.equal(this.revenueAllocation, action.revenueAllocation) ; } @@ -178,10 +210,12 @@ public String toString() { return super.toString() + RailsObjects.stringHelper(this) .addToString("presetRevenue", presetRevenue) - .addToString("mayUserSetRevenue", mayUserSetRevenue) - .addToString("allowedRevenueAllocations", allowedRevenueAllocations) + .addToString("PresetCompanyTreasuryRevenue",presetCompanyTreasuryRevenue) + .addToString("mayUserSetRevenue", getMayUserSetRevenue()) + .addToString("allowedRevenueAllocations", getAllowedRevenueAllocations()) .addToString("requiredCash", requiredCash) .addToStringOnlyActed("actualRevenue", actualRevenue) + .addToStringOnlyActed("actualCompanyTreasuryRevenue", actualCompanyTreasuryRevenue) .addToStringOnlyActed("revenueAllocation", revenueAllocation) .toString() ; @@ -194,10 +228,12 @@ private void readObject(ObjectInputStream in) throws IOException, // Custom deserialization for backwards compatibility ObjectInputStream.GetField fields = in.readFields(); presetRevenue = fields.get("presetRevenue", presetRevenue); - mayUserSetRevenue = fields.get("mayUserSetRevenue", mayUserSetRevenue); - allowedRevenueAllocations = (int[]) fields.get("allowedRevenueAllocations", allowedRevenueAllocations); + presetCompanyTreasuryRevenue = fields.get("presetCompanyTreasuryRevenue", presetCompanyTreasuryRevenue); + setMayUserSetRevenue(fields.get("mayUserSetRevenue", getMayUserSetRevenue())); + setAllowedRevenueAllocations((int[]) fields.get("allowedRevenueAllocations", getAllowedRevenueAllocations())); requiredCash = fields.get("requiredCash", 0); actualRevenue = fields.get("actualRevenue", actualRevenue); + actualCompanyTreasuryRevenue = fields.get("actualCompanyTreasuryRevenue", actualCompanyTreasuryRevenue); revenueAllocation = fields.get("revenueAllocation", revenueAllocation); if (Util.hasValue(companyName)) { @@ -205,4 +241,21 @@ private void readObject(ObjectInputStream in) throws IOException, } } + public boolean getMayUserSetRevenue() { + return mayUserSetRevenue; + } + + public void setMayUserSetRevenue(boolean mayUserSetRevenue) { + this.mayUserSetRevenue = mayUserSetRevenue; + } + + public int[] getAllowedRevenueAllocations() { + return allowedRevenueAllocations; + } + + public void setAllowedRevenueAllocations( + int[] allowedRevenueAllocations) { + this.allowedRevenueAllocations = allowedRevenueAllocations; + } + } diff --git a/src/main/resources/data/1837/Game.xml b/src/main/resources/data/1837/Game.xml index 117e7365f..69d15e19c 100644 --- a/src/main/resources/data/1837/Game.xml +++ b/src/main/resources/data/1837/Game.xml @@ -16,6 +16,7 @@ + @@ -207,7 +208,7 @@ haven't already. --> - + @@ -220,5 +221,8 @@ + diff --git a/src/main/resources/data/1837/GameOptions.xml b/src/main/resources/data/1837/GameOptions.xml index 44cffd39c..a303bc1b8 100644 --- a/src/main/resources/data/1837/GameOptions.xml +++ b/src/main/resources/data/1837/GameOptions.xml @@ -3,7 +3,7 @@ - + From 6ae0cd015f703ca248a6095d7e776e9bdb34c29e Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Tue, 25 Dec 2018 23:10:46 +0100 Subject: [PATCH 21/45] Fix error in Saving and loading the SetDividend Action for the new preset Company Treasury income. From a33ff3884dfb91f8f5d90c1a927c8ddc68f0417d Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Wed, 26 Dec 2018 19:02:16 +0100 Subject: [PATCH 22/45] Updating Gamestatus Class to show direct Income first work on revenue recognition for Coal Mines --- 1837_20181226_1653_a.rails | Bin 0 -> 8585 bytes 1837_20181226_1657_a.rails | Bin 0 -> 13241 bytes .../sf/rails/algorithms/NetworkVertex.java | 9 +- .../specific/_1837/CoalTrainModifier.java | 78 ++++++++++++++++++ .../net/sf/rails/ui/swing/GameStatus.java | 27 +++++- .../java/rails/game/action/SetDividend.java | 3 +- src/main/resources/LocalisedText.properties | 1 + src/main/resources/build/version.number | 2 +- src/main/resources/data/1837/Map.xml | 14 +++- src/main/resources/version.number | 4 +- 10 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 1837_20181226_1653_a.rails create mode 100644 1837_20181226_1657_a.rails create mode 100644 src/main/java/net/sf/rails/game/specific/_1837/CoalTrainModifier.java diff --git a/1837_20181226_1653_a.rails b/1837_20181226_1653_a.rails new file mode 100644 index 0000000000000000000000000000000000000000..e07ed05042bcd965ee520465552857d0b55b7473 GIT binary patch literal 8585 zcmeHM&2!sC6n~bJ=BxQA0S0D(Nok=lLzUVgZ6-ZHoDX86I3CLZ#y!Bs+S=-@v_e`Z z4hN20$_zcgi39&Y{|SaG!wgq0aNx@Sz}vMYOG-1OsdK=!X4YEouJ*n6+uy#Y)qDI8 zj0%{@>$mjE`m(+(U_O5z zes}Fp4Kg3Y=pkV(+V)|tH>lKd4ygal;~!q1`u?wn8bI5F&NU%mB)7732PeIv#e3)U+qdmTlVQOpXFFQ& z-7hn8OnvOlAR;g9yUccML9HtHsy?w@?9fUadn)vhx-Gg+SiQxFu(^whn5{;G1~}cT zTQ<&t0$t0bj8(AFx9gozQ>t%4b)r^15jMkNo$0%}vIh5U(R2h%mZ|U9L0}(JRJ_Cy zuw8CpU2}OG@w{EDP>K0_hFqXUx$2912M=(byKS%KhaDX{bUPmX_SsK!!MiM6YNS<$U@2f( z$FhNC6LowI0c3&RAP&`WX%RBL)M9K+RlAyK8fZlranLpcrnx6a5oVAB$`JIJQYHe5 zWJKyMoSe4I5h=7dF?CjhYz;=Eu;)|l7A>lF_j1}QU z5(K<%6I>9piQBS_dxREY)RXrbj0Z?axmq>25>U|_vgfkn8q5aKGgWR-K;yq66!FGLeo2xbNvolu!N6>+E9Xr)7!f6WkS+p`I z5*?@TKnYR^M;2uz!h0L1AUurz2uz#_eWpj!om|4T*f|RQ$+ts)5;>Xk^Dya8@JN>3 zH9~}k{-pPwfBw*&^e1>g&2Da+Lx0l8^N~V0+5#HBbQDgb@cEbVB7*tTBk1rz zpEaEj;daUmM=yUD7#0+610_fy99cAt2pg3U;j|m>bBrByFvlfb%ORNZm_0m&T*$Yp zWT2Zu*lRl>>}d{1-a76jA`cU9j5bBQakvGL#&JM~(4_#04sdal(yU9ywaduZf*&$A z?I?ykOd*^GQ^k?zl!uB)kyDz%H_&RxBP$hf&P2@T8B1k*gk^X8CS%Ji0{rP|01tVY z+NfzP6~Kc}Lq(a040A}C^xKFJ@5OREfk*51eY>uIE|bzaW`DN1L$@&>$m=Sji?GT| zrg<=V6egF#9H9a8VS=jrTr%ggn#dN;;isDnW`;Er^U9i$S05UZ;V2_D&Ua+Of1R?D z4hTOBYdg8_qcyz8-+0q2pTtR?o_Cf`dGt))J*kSEZ$Gr+=~R(c?4M@EnN)eAD|sUQ WlOW(nUv2-HKsdW(H8P@U#`_m@eVso5 literal 0 HcmV?d00001 diff --git a/1837_20181226_1657_a.rails b/1837_20181226_1657_a.rails new file mode 100644 index 0000000000000000000000000000000000000000..a3584a24aa630c565665b5f3656728ad2cb97926 GIT binary patch literal 13241 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 allTrains = revenueAdapter.getTrains(); + List coalTrains = new ArrayList(); + List otherTrains = new ArrayList(); + for (NetworkTrain train:allTrains) { + // checks name of train + if (train.getTrainName().contains("G") ) { + coalTrains.add(train); + } else { + otherTrains.add(train); + } + } + + // change list that tgv trains are the first ones, if there are tgvs ... + nbCOAL = coalTrains.size(); + if (nbCOAL != 0) { + allTrains.clear(); + allTrains.addAll(coalTrains); + allTrains.addAll(otherTrains); + return true; + } else { // ... otherwise deactivate modifier + return false; + } + } + + public int predictionValue(List runs) { + // nothing to do here + return 0; + } + + public int evaluationValue(List runs, boolean optimalRuns) { + // nothing to do here + return 0; + } + + public void adjustOptimalRun(List optimalRuns) { + // nothing to do + } + + public boolean providesOwnCalculateRevenue() { + return true; + } + + public int calculateRevenue(RevenueAdapter revenueAdapter) { + int value = 0; + value = revenueAdapter.calculateRevenue(0, revenueAdapter.getTrains().size()-1); + return value; + } + + public String prettyPrint(RevenueAdapter adapter) { + return LocalText.getText("CoalTrainModifier"); + } + + +} diff --git a/src/main/java/net/sf/rails/ui/swing/GameStatus.java b/src/main/java/net/sf/rails/ui/swing/GameStatus.java index 7dc234cd1..4a7886d36 100644 --- a/src/main/java/net/sf/rails/ui/swing/GameStatus.java +++ b/src/main/java/net/sf/rails/ui/swing/GameStatus.java @@ -112,6 +112,14 @@ public class GameStatus extends GridPanel implements ActionListener { protected Field futureTrains; protected int futureTrainsXOffset, futureTrainsYOffset, futureTrainsWidth; protected int rightCompCaptionXOffset; + + /** + * Next Field is needed for the direct payment of Income and display of sum + * during an OR for a Company, that is not linked to a share. + */ + private Field compDirectRevenue[]; + private int compDirectRevXOffset, compDirectRevYOffset; + protected Caption[] upperPlayerCaption; protected Caption[] lowerPlayerCaption; @@ -130,6 +138,8 @@ public class GameStatus extends GridPanel implements ActionListener { protected boolean compCanHoldForeignShares = false; // NOT YET USED protected boolean hasCompanyLoans = false; protected boolean hasRights; + private boolean hasDirectCompanyIncomeInOr = false; + // Current actor. // Players: 0, 1, 2, ... @@ -179,6 +189,7 @@ public void init(StatusWindow parent, GameUIManager gameUIManager) { 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); + hasDirectCompanyIncomeInOr= gameUIManager.getGameParameterAsBoolean(GuiDef.Parm.HAS_SPECIAL_COMPANY_INCOME); // TODO: Can this be done using ipo and pool directly? ipo = bank.getIpo().getPortfolioModel(); @@ -204,7 +215,8 @@ public void init(StatusWindow parent, GameUIManager gameUIManager) { compPrivates = new Field[nc]; compLoans = new Field[nc]; if (hasRights) rights = new Field[nc]; - + if (hasDirectCompanyIncomeInOr) compDirectRevenue= new Field[nc]; + playerCash = new Field[np]; playerCashButton = new ClickField[np]; playerPrivates = new Field[np]; @@ -236,6 +248,10 @@ public void init(StatusWindow parent, GameUIManager gameUIManager) { compCashYOffset = lastY; compRevenueXOffset = ++lastX; compRevenueYOffset = lastY; + if (hasDirectCompanyIncomeInOr) { + compDirectRevXOffset = ++lastX; + compDirectRevYOffset = lastY; + } compTrainsXOffset = ++lastX; compTrainsYOffset = lastY; compTokensXOffset = ++lastX; @@ -332,6 +348,10 @@ protected void initFields() { 1, WIDE_BOTTOM, true); addField(new Caption(LocalText.getText("REVENUE")), compRevenueXOffset, 1, 1, 1, WIDE_BOTTOM, true); + if (this.hasDirectCompanyIncomeInOr) { + addField(new Caption(LocalText.getText("DIRECT_INCOME")), + compDirectRevXOffset, 1, 1, 1, WIDE_BOTTOM, true); + } addField(new Caption(LocalText.getText("TRAINS")), compTrainsXOffset, 1, 1, 1, WIDE_BOTTOM, true); addField(new Caption(LocalText.getText("TOKENS")), compTokensXOffset, @@ -465,6 +485,11 @@ protected void initFields() { f = compRevenue[i] = new Field(c.getLastRevenueModel()); addField(f, compRevenueXOffset, compRevenueYOffset + i, 1, 1, 0, visible); + + if (hasDirectCompanyIncomeInOr) { + f = compDirectRevenue[i] = new Field(c.getLastDirectIncomeModel()); + addField(f, compDirectRevXOffset, compDirectRevYOffset + i, 1, 1, 0, visible); + } f = compTrains[i] = new Field(c.getPortfolioModel().getTrainsModel()); addField(f, compTrainsXOffset, compTrainsYOffset + i, 1, 1, 0, visible); diff --git a/src/main/java/rails/game/action/SetDividend.java b/src/main/java/rails/game/action/SetDividend.java index 8020afc50..63cd1d9cb 100644 --- a/src/main/java/rails/game/action/SetDividend.java +++ b/src/main/java/rails/game/action/SetDividend.java @@ -211,7 +211,7 @@ public String toString() { return super.toString() + RailsObjects.stringHelper(this) .addToString("presetRevenue", presetRevenue) - .addToString("PresetTreasuryBonusRevenue",presetCompanyTreasuryRevenue) + .addToString("presetTreasuryBonusRevenue",presetCompanyTreasuryRevenue) .addToString("mayUserSetRevenue", getMayUserSetRevenue()) .addToString("allowedRevenueAllocations", getAllowedRevenueAllocations()) .addToString("requiredCash", requiredCash) @@ -230,7 +230,6 @@ private void readObject(ObjectInputStream in) throws IOException, ObjectInputStream.GetField fields = in.readFields(); presetRevenue = fields.get("presetRevenue", presetRevenue); presetCompanyTreasuryRevenue = fields.get("presetCompanyTreasuryRevenue", presetCompanyTreasuryRevenue); - presetCompanyTreasuryRevenue = fields.get("PresetTreasuryBonusRevenue",presetCompanyTreasuryRevenue); setMayUserSetRevenue(fields.get("mayUserSetRevenue", getMayUserSetRevenue())); setAllowedRevenueAllocations((int[]) fields.get("allowedRevenueAllocations", getAllowedRevenueAllocations())); requiredCash = fields.get("requiredCash", 0); diff --git a/src/main/resources/LocalisedText.properties b/src/main/resources/LocalisedText.properties index dfcebf5cc..45507f65b 100644 --- a/src/main/resources/LocalisedText.properties +++ b/src/main/resources/LocalisedText.properties @@ -310,6 +310,7 @@ DestinationReachedByToken={0} gains {1} by laying a token on its destination {2} DestinationReached={0} has reached its destination hex {1} DestinationsReached=Destinations reached DestinationsReachedPrompt=Select companies that have reached their destinations +DIRECT_INCOME=Direct Rev. DiscardsBaseToken={0} discards a {1} base token on {2} discount=discount of {0} DoesNotExist=Item does not exist diff --git a/src/main/resources/build/version.number b/src/main/resources/build/version.number index 9ff57a5d1..409475165 100644 --- a/src/main/resources/build/version.number +++ b/src/main/resources/build/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC4 +version=2.0.RC5.6 # the following string "@DEVELOP@" is replaced by an empty string in the release version # this is done automatically by gradle develop=@DEVELOP@ diff --git a/src/main/resources/data/1837/Map.xml b/src/main/resources/data/1837/Map.xml index bebd83502..0726462fe 100644 --- a/src/main/resources/data/1837/Map.xml +++ b/src/main/resources/data/1837/Map.xml @@ -40,7 +40,12 @@ - + + + + + + @@ -153,7 +158,12 @@ - + + + + + + diff --git a/src/main/resources/version.number b/src/main/resources/version.number index 38116003b..6fdf35de8 100644 --- a/src/main/resources/version.number +++ b/src/main/resources/version.number @@ -1,8 +1,8 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC4 +version=2.0.RC5.6 # the following string "" is replaced by an empty string in the release version # this is done automatically by gradle develop= # the following string "@ BUILDDATE @" is replaced by the build date -buildDate=2018-10-07 +buildDate=2018-12-25 From aaa2ee03d53264eccce64c889574edbda468ae1f Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Tue, 1 Jan 2019 22:57:01 +0100 Subject: [PATCH 23/45] preparing 1837 2nd Edition Setup Variant --- .../net/sf/rails/game/CompanyManager.java | 1 - .../java/net/sf/rails/game/StartPacket.java | 2 +- .../specific/_1837/StartRound_1837_2ndEd.java | 347 ++++++++++++++++++ .../resources/data/1837/CompanyManager.xml | 144 +++++--- src/main/resources/data/1837/Game.xml | 5 + src/main/resources/data/1837/GameOptions.xml | 2 +- src/main/resources/data/1837/Map.xml | 6 +- src/main/resources/data/1837/StockMarket.xml | 145 ++++++++ 8 files changed, 598 insertions(+), 54 deletions(-) create mode 100644 src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_2ndEd.java diff --git a/src/main/java/net/sf/rails/game/CompanyManager.java b/src/main/java/net/sf/rails/game/CompanyManager.java index c68a4bc81..d641f596b 100644 --- a/src/main/java/net/sf/rails/game/CompanyManager.java +++ b/src/main/java/net/sf/rails/game/CompanyManager.java @@ -213,7 +213,6 @@ public void finishConfiguration (RailsRoot root) public void initStartPackets(GameManager gameManager) { // initialize startPackets - // TODO: Check if this still works in 2.0 for (StartPacket packet: startPackets) { packet.init(gameManager); } diff --git a/src/main/java/net/sf/rails/game/StartPacket.java b/src/main/java/net/sf/rails/game/StartPacket.java index 9b5b5e6c2..59e6b7ecc 100644 --- a/src/main/java/net/sf/rails/game/StartPacket.java +++ b/src/main/java/net/sf/rails/game/StartPacket.java @@ -205,7 +205,7 @@ public List getUnsoldItems() { } /** - * Check if all items have bene sold. + * Check if all items have been sold. * * @return True if all items have been sold. */ diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_2ndEd.java b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_2ndEd.java new file mode 100644 index 000000000..364ec45d8 --- /dev/null +++ b/src/main/java/net/sf/rails/game/specific/_1837/StartRound_1837_2ndEd.java @@ -0,0 +1,347 @@ +package net.sf.rails.game.specific._1837; + +import rails.game.action.*; +import net.sf.rails.common.DisplayBuffer; +import net.sf.rails.common.LocalText; +import net.sf.rails.common.ReportBuffer; +import net.sf.rails.game.*; +import net.sf.rails.game.state.GenericState; +import net.sf.rails.game.state.IntegerState; + +public class StartRound_1837_2ndEd extends StartRound { + + public final static int SELECT_STEP = 0; + public final static int OPEN_STEP = 1; + public final static int BUY_STEP = 2; + public final static int BID_STEP = 3; + + private final IntegerState currentStep = IntegerState.create(this, "currentStep", SELECT_STEP); + private final GenericState selectingPlayer = GenericState.create(this, "selectingPlayer"); + private final IntegerState currentBuyPrice = IntegerState.create(this, "currentBuyPrice"); + private final GenericState currentAuctionItem = GenericState.create(this, "currentAuctionItem"); + + /** + * Constructed via Configure + */ + public StartRound_1837_2ndEd(GameManager parent, String id) { + super(parent, id, true, true, false); + // bidding, with base prices + } + + @Override + public void start() { + super.start(); + + currentStep.set(SELECT_STEP); + + setPossibleActions(); + } + + @Override + public boolean setPossibleActions() { + + possibleActions.clear(); + + Player currentPlayer = playerManager.getCurrentPlayer(); + + switch (currentStep.value()) { + case SELECT_STEP: + // In the selection step, all not yet sold items are selectable. + // The current player MUST select an item, + // and may then bid for it or pass. + + selectingPlayer.set(currentPlayer); + currentBuyPrice.set(100); + + for (StartItem item : itemsToSell.view()) { + if (!item.isSold()) { + item.setStatus(StartItem.SELECTABLE); + item.setMinimumBid(item.getBasePrice()); + BidStartItem possibleAction = + new BidStartItem(item, item.getBasePrice(), + startPacket.getModulus(), false, true); + possibleActions.add(possibleAction); + } + } + break; + case BUY_STEP: + // only offer buy if enough money + if (currentBuyPrice.value() <= currentPlayer.getFreeCash()) { + possibleActions.add(new BuyStartItem( + (StartItem) currentAuctionItem.value(), + currentBuyPrice.value(), true)); + } + possibleActions.add(new NullAction(NullAction.Mode.PASS)); + break; + case OPEN_STEP: + case BID_STEP: + StartItem item = (StartItem) currentAuctionItem.value(); + // only offer if enough money + if (item.getMinimumBid() <= currentPlayer.getFreeCash()) { + BidStartItem possibleAction = + new BidStartItem(item, item.getMinimumBid(), + startPacket.getModulus(), true); + possibleActions.add(possibleAction); + } + if (currentStep.value() == OPEN_STEP) { + possibleActions.add(new NullAction(NullAction.Mode.PASS).setLabel("DeclineToBid")); + } else { + possibleActions.add(new NullAction(NullAction.Mode.PASS)); + } + break; + } + + return true; + } + + @Override + protected boolean buy(String playerName, BuyStartItem boughtItem) { + StartItem item = boughtItem.getStartItem(); + int status = boughtItem.getStatus(); + String errMsg = null; + Player player = playerManager.getCurrentPlayer(); + int price = 0; + + while (true) { + + // Is the item buyable? + if (status == StartItem.AUCTIONED && currentStep.value() == BUY_STEP) { + price = currentBuyPrice.value(); + } else { + errMsg = LocalText.getText("NotForSale"); + break; + } + + if (player.getFreeCash() < price) { + errMsg = LocalText.getText("NoMoney"); + break; + } + + break; + } + + if (errMsg != null) { + DisplayBuffer.add(this, LocalText.getText("CantBuyItem", + playerName, + item.getId(), + errMsg )); + return false; + } + + + + assignItem(player, item, price, 0); + ((PublicCertificate) item.getPrimary()).getCompany().start(); + setNextSelectingPlayer(); + currentStep.set(SELECT_STEP); + + return true; + + } + + /** + * The current player bids on a given start item. + * + * @param playerName The name of the current player (for checking purposes). + * @param itemName The name of the start item on which the bid is placed. + * @param amount The bid amount. + */ + @Override + protected boolean bid(String playerName, BidStartItem bidItem) { + + StartItem item = bidItem.getStartItem(); + StartItem auctionedItem = (StartItem) currentAuctionItem.value(); + String errMsg = null; + Player player = playerManager.getCurrentPlayer(); + int bidAmount = bidItem.getActualBid(); + + while (true) { + + // If the bidAmount is -1, this is just a selection for auctioning + if (bidAmount == -1) { + if (!bidItem.isSelectForAuction()) { + errMsg = LocalText.getText("NotBiddable"); + break; + } + } else { + + // If auctioning, must be the right item + if ((currentStep.value() == OPEN_STEP || currentStep.value() == BID_STEP) + && !item.equals(auctionedItem)) { + errMsg = + LocalText.getText("WrongStartItem", + item.getId(), + auctionedItem.getId() ); + break; + } + + // Bid must be at least the minimum bid + if (bidAmount < item.getMinimumBid()) { + errMsg = + LocalText.getText("BidTooLow", + Bank.format(this, item.getMinimumBid())); + break; + } + + // Bid must be a multiple of the modulus + if (bidAmount % startPacket.getModulus() != 0) { + errMsg = LocalText.getText( + "BidMustBeMultipleOf", + bidAmount, + startPacket.getMinimumIncrement() ); + break; + } + + // Player must have enough cash + if (bidAmount > player.getCash()) { + errMsg = + LocalText.getText("BidTooHigh", + Bank.format(this, bidAmount)); + break; + } + } + + break; + } + + if (errMsg != null) { + DisplayBuffer.add(this, LocalText.getText("InvalidBid", + playerName, + item.getId(), + errMsg )); + return false; + } + + + + if (currentStep.value() == SELECT_STEP) { + + currentAuctionItem.set(item); + item.setStatus(StartItem.AUCTIONED); + item.setAllActive(); + + for (StartItem item2 : itemsToSell.view()) { + if (item2 != item && !item2.isSold()) { + item2.setStatus(StartItem.UNAVAILABLE); + } + } + if (bidAmount == -1) { + currentStep.set(OPEN_STEP); + } + + ReportBuffer.add(this, " "); + ReportBuffer.add(this, LocalText.getText("SelectForAuctioning", + playerName, + item.getId() )); + } + + if (bidAmount > 0) { + item.setBid(bidAmount, player); + item.setMinimumBid(bidAmount + 5); + currentStep.set(BID_STEP); + + ReportBuffer.add(this, LocalText.getText("BID_ITEM", + playerName, + Bank.format(this, bidAmount), + item.getId() )); + } + + switch (currentStep.value()) { + case OPEN_STEP: + case BUY_STEP: + Player currentPlayer = playerManager.setCurrentToNextPlayer(); + if (currentPlayer == selectingPlayer.value()) { + // All have passed, now lower the buy price + currentBuyPrice.add(-10); + currentStep.set(BUY_STEP); + if (currentBuyPrice.value() == 0) { + // Forced buy + assignItem(currentPlayer, item, 0, 0); + } + } + break; + + case BID_STEP: + setNextBiddingPlayer(); + } + + return true; + + } + + /** + * Process a player's pass. + * @param playerName The name of the current player (for checking purposes). + */ + @Override + public boolean pass(NullAction action, String playerName) { + // All validations have already been done + + ReportBuffer.add(this, LocalText.getText("PASSES", playerName)); + + + + StartItem auctionedItem = (StartItem) currentAuctionItem.value(); + + switch (currentStep.value()) { + case OPEN_STEP: + case BUY_STEP: + Player currentPlayer = playerManager.setCurrentToNextPlayer(); + if (currentPlayer == selectingPlayer.value()) { + // All have passed, now lower the buy price + currentBuyPrice.add(-10); + auctionedItem.setMinimumBid(currentBuyPrice.value()); + ReportBuffer.add(this, LocalText.getText("ITEM_PRICE_REDUCED", + auctionedItem.getId(), + Bank.format(this, currentBuyPrice.value()) )); + currentStep.set(BUY_STEP); + + if (currentBuyPrice.value() == 0) { + // Forced buy + // Trick to make the zero buy price visible + auctionedItem.setBid(0, currentPlayer); + + assignItem(currentPlayer, auctionedItem, 0, 0); + currentStep.set(SELECT_STEP); + setNextSelectingPlayer(); + } + } + break; + + case BID_STEP: + + auctionedItem.setPass(playerManager.getCurrentPlayer()); + + // We are done if the next still bidding player + // is equal to the current highest bidder. + setNextBiddingPlayer(); + if (playerManager.getCurrentPlayer() == auctionedItem.getBidder()) { + // Finish bidding + assignItem(auctionedItem.getBidder(), auctionedItem, + auctionedItem.getBid(), 0); + currentStep.set(SELECT_STEP); + setNextSelectingPlayer(); + } + } + + return true; + } + + private void setNextBiddingPlayer() { + + Player currentPlayer; + do { + currentPlayer = playerManager.setCurrentToNextPlayer(); + } while (((StartItem) currentAuctionItem.value()).isActive(currentPlayer) == false); + } + + private void setNextSelectingPlayer() { + playerManager.setCurrentToNextPlayerAfter(selectingPlayer.value()); + } + + @Override + public String getHelp() { + return "1837 Start Round help text"; + } + +} diff --git a/src/main/resources/data/1837/CompanyManager.xml b/src/main/resources/data/1837/CompanyManager.xml index 20eb1fee7..c48b2ae4a 100644 --- a/src/main/resources/data/1837/CompanyManager.xml +++ b/src/main/resources/data/1837/CompanyManager.xml @@ -404,54 +404,102 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - diff --git a/src/main/resources/data/1837/Game.xml b/src/main/resources/data/1837/Game.xml index 69d15e19c..3aba17b70 100644 --- a/src/main/resources/data/1837/Game.xml +++ b/src/main/resources/data/1837/Game.xml @@ -17,7 +17,12 @@ + + + + + diff --git a/src/main/resources/data/1837/GameOptions.xml b/src/main/resources/data/1837/GameOptions.xml index a303bc1b8..dc153e794 100644 --- a/src/main/resources/data/1837/GameOptions.xml +++ b/src/main/resources/data/1837/GameOptions.xml @@ -8,5 +8,5 @@ - + diff --git a/src/main/resources/data/1837/Map.xml b/src/main/resources/data/1837/Map.xml index 0726462fe..ce133c70c 100644 --- a/src/main/resources/data/1837/Map.xml +++ b/src/main/resources/data/1837/Map.xml @@ -43,7 +43,7 @@ - + @@ -76,7 +76,7 @@ - + @@ -161,7 +161,7 @@ - + diff --git a/src/main/resources/data/1837/StockMarket.xml b/src/main/resources/data/1837/StockMarket.xml index 0050afd20..25023a738 100644 --- a/src/main/resources/data/1837/StockMarket.xml +++ b/src/main/resources/data/1837/StockMarket.xml @@ -7,6 +7,7 @@ + @@ -125,4 +126,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 7b6515fc8feaf19d2d5cc5e9a8fc98e912af1772 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 3 Jan 2019 14:16:41 +0100 Subject: [PATCH 24/45] Setup 1837 2nd Edition further changes. --- .../resources/data/1837/CompanyManager.xml | 74 +++++++++---------- src/main/resources/data/1837/Game.xml | 2 +- src/main/resources/data/1837/Map.xml | 6 +- src/main/resources/data/1837/StockMarket.xml | 8 +- 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/main/resources/data/1837/CompanyManager.xml b/src/main/resources/data/1837/CompanyManager.xml index c48b2ae4a..bfe8af2f2 100644 --- a/src/main/resources/data/1837/CompanyManager.xml +++ b/src/main/resources/data/1837/CompanyManager.xml @@ -255,7 +255,7 @@ - + @@ -321,21 +321,21 @@ - + - + - + @@ -348,60 +348,60 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -464,34 +464,34 @@ - + - + - + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + diff --git a/src/main/resources/data/1837/Game.xml b/src/main/resources/data/1837/Game.xml index 3aba17b70..2054bef83 100644 --- a/src/main/resources/data/1837/Game.xml +++ b/src/main/resources/data/1837/Game.xml @@ -21,7 +21,7 @@ - + diff --git a/src/main/resources/data/1837/Map.xml b/src/main/resources/data/1837/Map.xml index ce133c70c..94c1551ae 100644 --- a/src/main/resources/data/1837/Map.xml +++ b/src/main/resources/data/1837/Map.xml @@ -43,7 +43,7 @@ - + @@ -76,7 +76,7 @@ - + @@ -161,7 +161,7 @@ - + diff --git a/src/main/resources/data/1837/StockMarket.xml b/src/main/resources/data/1837/StockMarket.xml index 25023a738..639e5018c 100644 --- a/src/main/resources/data/1837/StockMarket.xml +++ b/src/main/resources/data/1837/StockMarket.xml @@ -127,7 +127,7 @@ - + @@ -202,8 +202,8 @@ - - + + @@ -269,5 +269,5 @@ - + From 54bfe9b6d5b6c85059e2410853016f6082f1c272 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Fri, 4 Jan 2019 11:12:12 +0100 Subject: [PATCH 25/45] =?UTF-8?q?Fixing=20S=C3=BCdbahn=20Floating=20Proble?= =?UTF-8?q?m?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/build/version.number | 2 +- src/main/resources/data/1837/CompanyManager.xml | 2 +- src/main/resources/data/1837/Game.xml | 10 +++++----- src/main/resources/version.number | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/resources/build/version.number b/src/main/resources/build/version.number index 409475165..2dc6843bf 100644 --- a/src/main/resources/build/version.number +++ b/src/main/resources/build/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.6 +version=2.0.RC5.8 # the following string "@DEVELOP@" is replaced by an empty string in the release version # this is done automatically by gradle develop=@DEVELOP@ diff --git a/src/main/resources/data/1837/CompanyManager.xml b/src/main/resources/data/1837/CompanyManager.xml index c48b2ae4a..c2f550f5e 100644 --- a/src/main/resources/data/1837/CompanyManager.xml +++ b/src/main/resources/data/1837/CompanyManager.xml @@ -59,7 +59,7 @@ - + diff --git a/src/main/resources/data/1837/Game.xml b/src/main/resources/data/1837/Game.xml index 3aba17b70..b041bb534 100644 --- a/src/main/resources/data/1837/Game.xml +++ b/src/main/resources/data/1837/Game.xml @@ -17,12 +17,12 @@ - + - - - - + + + + diff --git a/src/main/resources/version.number b/src/main/resources/version.number index 6fdf35de8..653415363 100644 --- a/src/main/resources/version.number +++ b/src/main/resources/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.6 +version=2.0.RC5.8 # the following string "" is replaced by an empty string in the release version # this is done automatically by gradle develop= From 1fe9bfcb5c488f6e4c05aee93891985214966fd3 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sun, 6 Jan 2019 20:31:46 +0100 Subject: [PATCH 26/45] Fixed a mistake with the variant introduced 2nd-ED Startround causing the Startpackets to not be choosen. Whitespace in Variant Options are dangerous --- .../resources/data/1837/CompanyManager.xml | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/resources/data/1837/CompanyManager.xml b/src/main/resources/data/1837/CompanyManager.xml index 708f36509..90fda65b1 100644 --- a/src/main/resources/data/1837/CompanyManager.xml +++ b/src/main/resources/data/1837/CompanyManager.xml @@ -321,21 +321,21 @@ - + - + - + @@ -348,63 +348,63 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -456,7 +456,7 @@ - + From c1818c0a8e6b9a051c53934eabee62e2ffefce9f Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sun, 10 Feb 2019 14:45:05 +0100 Subject: [PATCH 27/45] Work on the Major Coal Exchange Mechanismn --- .../sf/rails/game/NationalFormationRound.java | 3 +- .../specific/_1837/CoalExchangeRound.java | 202 ++++++++++++++++++ .../_1837/FinalCoalExchangeRound.java | 8 +- .../game/specific/_1837/GameManager_1837.java | 48 ++++- .../specific/_1837/OperatingRound_1837.java | 23 ++ .../game/specific/_1837/StockRound_1837.java | 49 +++++ 6 files changed, 325 insertions(+), 8 deletions(-) create mode 100644 src/main/java/net/sf/rails/game/specific/_1837/CoalExchangeRound.java diff --git a/src/main/java/net/sf/rails/game/NationalFormationRound.java b/src/main/java/net/sf/rails/game/NationalFormationRound.java index 8120c3dd2..f1592c821 100644 --- a/src/main/java/net/sf/rails/game/NationalFormationRound.java +++ b/src/main/java/net/sf/rails/game/NationalFormationRound.java @@ -21,7 +21,6 @@ public class NationalFormationRound extends StockRound { public NationalFormationRound(GameManager parent, String id) { super(parent, id); - // TODO Auto-generated constructor stub } @@ -473,7 +472,7 @@ protected void finishRound() { @Override public String toString() { - return "1837 KuKFormationRound"; + return "1837 NationalFormationRound"; } } \ No newline at end of file diff --git a/src/main/java/net/sf/rails/game/specific/_1837/CoalExchangeRound.java b/src/main/java/net/sf/rails/game/specific/_1837/CoalExchangeRound.java new file mode 100644 index 000000000..f443c31ff --- /dev/null +++ b/src/main/java/net/sf/rails/game/specific/_1837/CoalExchangeRound.java @@ -0,0 +1,202 @@ +/** + * + */ +package net.sf.rails.game.specific._1837; + +import java.util.ArrayList; +import java.util.List; + +import net.sf.rails.common.GameOption; +import net.sf.rails.common.GuiDef; +import net.sf.rails.common.LocalText; +import net.sf.rails.common.ReportBuffer; +import net.sf.rails.game.GameManager; +import net.sf.rails.game.Player; +import net.sf.rails.game.PublicCompany; +import net.sf.rails.game.StockRound; +import rails.game.action.MergeCompanies; +import rails.game.action.NullAction; + +/** + * @author Martin Brumm + * @date 2019-01-26 + */ +public class CoalExchangeRound extends StockRound_1837 { + + Player playerStartingCERound; + /** + * @param parent + * @param id + */ + public CoalExchangeRound(GameManager parent, String id) { + super(parent, id); + guiHints.setVisibilityHint(GuiDef.Panel.MAP, true); + guiHints.setActivePanel(GuiDef.Panel.STATUS); + + raiseIfSoldOut = false; + } + + public static CoalExchangeRound create(GameManager parent, String id){ + return new CoalExchangeRound(parent, id); + } + + public void start(Player playerToStartCERound) { + ReportBuffer.add(this, ""); + ReportBuffer.add(this, LocalText.getText("StartCoalExchangeRound")); + + playerManager.setCurrentPlayer(playerToStartCERound); + initPlayer(); + playerStartingCERound=playerToStartCERound; + ReportBuffer.add(this, LocalText.getText("HasFirstTurn", + playerToStartCERound.getId() )); + } + /*----- General methods -----*/ + + @Override + public boolean setPossibleActions() { + + if (discardingTrains.value()) { + return setTrainDiscardActions(); + } else { + return setMinorMergeActions(); + } + + } + + private boolean setMinorMergeActions() { + + if (hasActed.value()) { + possibleActions.add(new NullAction(NullAction.Mode.DONE)); + return true; + } + + List comps = + companyManager.getAllPublicCompanies(); + List minors = new ArrayList(); + PublicCompany targetCompany = null; + String type; +/** + * Minor Companies are merged on request until the final Exchange Round, Director goes first and then everyone else is asked each round + */ + for (PublicCompany comp : comps) { + type = comp.getType().getId(); + + + + if ((type.equals("Coal")) && (companyManager.getPublicCompany(comp.getRelatedNationalCompany()).hasFloated())) { + if (comp.isClosed()) continue; + if (comp.getPresident() == currentPlayer) { + minors.add(comp); + targetCompany = companyManager.getPublicCompany(comp.getRelatedNationalCompany()); + possibleActions.add(new MergeCompanies(comp, targetCompany, true)); + possibleActions.add(new NullAction(NullAction.Mode.DONE)); + } + } + } + +/** + * The current Player wasnt the director we are looking for the next one + */ + while (minors.isEmpty()) { + setNextPlayer(); + for (PublicCompany comp : comps) { + type = comp.getType().getId(); + if ((type.equals("Coal")) && (companyManager.getPublicCompany(comp.getRelatedNationalCompany()).hasFloated())) { + if (comp.isClosed()) continue; + if (comp.getPresident() == currentPlayer) { + targetCompany = companyManager.getPublicCompany(comp.getRelatedNationalCompany()); + possibleActions.add(new MergeCompanies(comp, targetCompany, true)); + possibleActions.add(new NullAction(NullAction.Mode.DONE)); + minors.add(comp); + } + } + } //Inner loop + if (currentPlayer == playerStartingCERound) { + finishRound(); + return true; + } + } //While Loop +/** + * we need to make sure that everyone is asked who has a share of a minor that is corresponding to the floated Major.. + */ + return true; + } + + + + @Override + // Autopassing does not apply here + public boolean done(NullAction action, String playerName, boolean hasAutopassed) { + + for (PublicCompany comp : companyManager.getAllPublicCompanies()) { + if ((comp.getType().getId().equals("Coal")) && (!comp.isClosed())) { + finishTurn(); + return true; + } + } + + finishRound(); + return true; + } + + @Override + protected void initPlayer() { + + currentPlayer = playerManager.getCurrentPlayer(); + hasActed.set(false); + + } + + /*----- METHODS TO BE CALLED TO SET UP THE NEXT TURN -----*/ + + @Override + protected void finishRound() { + ReportBuffer.add(this, " "); + ReportBuffer.add( + this, + LocalText.getText("END_CoalExchangeRound", + String.valueOf(getCoalExchangeRoundNumber()))); + + if (discardingTrains.value()) { + + return; + + } else if (!compWithExcessTrains.isEmpty()) { + + discardingTrains.set(true); + + // Make up a list of train discarding companies in operating + // sequence. + PublicCompany[] operatingCompanies = + setOperatingCompanies().toArray(new PublicCompany[0]); + discardingCompanies = + new PublicCompany[compWithExcessTrains.size()]; + for (int i = 0, j = 0; i < operatingCompanies.length; i++) { + if (compWithExcessTrains.contains(operatingCompanies[i])) { + discardingCompanies[j++] = operatingCompanies[i]; + } + } + + discardingCompanyIndex.set(0); + PublicCompany discardingCompany = + discardingCompanies[discardingCompanyIndex.value()]; + setCurrentPlayer(discardingCompany.getPresident()); + + } else { + + return; + + } + } + + + private int getCoalExchangeRoundNumber() { + return ((GameManager_1837) gameManager).getCERNumber(); + } + + @Override + public String toString() { + return "CoalExchangeRound"; + } + +} diff --git a/src/main/java/net/sf/rails/game/specific/_1837/FinalCoalExchangeRound.java b/src/main/java/net/sf/rails/game/specific/_1837/FinalCoalExchangeRound.java index 22eca5af4..6ee2f0fb6 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/FinalCoalExchangeRound.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/FinalCoalExchangeRound.java @@ -27,14 +27,14 @@ public static FinalCoalExchangeRound create(GameManager parent, String id){ return new FinalCoalExchangeRound(parent, id); } - public void start(Player playerToStartFMCRound) { + public void start(Player playerToStartFCERound) { ReportBuffer.add(this, ""); - ReportBuffer.add(this, LocalText.getText("StartFinalMinorExchangeRound")); + ReportBuffer.add(this, LocalText.getText("StartFinalCoalExchangeRound")); - playerManager.setCurrentPlayer(playerToStartFMCRound); + playerManager.setCurrentPlayer(playerToStartFCERound); initPlayer(); ReportBuffer.add(this, LocalText.getText("HasFirstTurn", - playerToStartFMCRound.getId() )); + playerToStartFCERound.getId() )); } /*----- General methods -----*/ diff --git a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java index c8ae59736..21f625c47 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java @@ -8,11 +8,15 @@ import net.sf.rails.game.GameManager; import net.sf.rails.game.NationalFormationRound; import net.sf.rails.game.Phase; +import net.sf.rails.game.Player; import net.sf.rails.game.RailsRoot; import net.sf.rails.game.Round; import net.sf.rails.game.StartPacket; import net.sf.rails.game.StartRound; import net.sf.rails.game.specific._1837.OperatingRound_1837; +import net.sf.rails.game.specific._18EU.FinalMinorExchangeRound; +import net.sf.rails.game.state.GenericState; +import net.sf.rails.game.state.IntegerState; @@ -22,9 +26,15 @@ */ public class GameManager_1837 extends GameManager { + protected final IntegerState cerNumber = IntegerState.create(this, "cerNumber"); + private Round previousRound = null; - + protected final GenericState playerToStartFCERound = + GenericState.create(this, "playerToStartFCERound"); + + protected final GenericState playerToStartCERound = + GenericState.create(this, "playerToStartCERound"); public GameManager_1837(RailsRoot parent, String id) { super(parent, id); @@ -41,6 +51,17 @@ public void nextRound(Round round) { startOperatingRound(runIfStartPacketIsNotCompletelySold()); } } + else if ((round instanceof StockRound_1837) ||(round instanceof OperatingRound_1837)) { + //Check if a Major is started and if so ask the Owner of the Coal Company to fold + if (playerToStartCERound.value() != null) { + cerNumber.add(1); + createRound (CoalExchangeRound.class, "CoalExchangeRound").start + ((Player)playerToStartCERound.value()); + playerToStartCERound.set(null); + } else { + super.nextRound(round); + } + } else if (round instanceof NationalFormationRound) { if (interruptedRound != null) { @@ -69,7 +90,7 @@ else if (round instanceof NationalFormationRound) } else { super.nextRound(round); } - } + } } @@ -141,4 +162,27 @@ public void setGuiParameters() { } + + public Player getPlayerToStartFCERound() { + return (Player) playerToStartFCERound.value(); + } + + + public void setPlayerToStartFCERound(Player president) { + this.playerToStartFCERound.set(president); + } + + public Player getPlayerToStartCERound() { + return (Player) playerToStartCERound.value(); + } + + + public void setPlayerToStartCERound(Player president) { + this.playerToStartCERound.set(president); + } + + public int getCERNumber () { + return cerNumber.value(); + } + } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java index ad5ac196e..35c52f953 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java @@ -24,10 +24,12 @@ import net.sf.rails.game.RailsRoot; import net.sf.rails.game.special.ExchangeForShare; import net.sf.rails.game.special.SpecialProperty; +import net.sf.rails.game.specific._18EU.GameManager_18EU; import net.sf.rails.game.state.BooleanState; import net.sf.rails.game.state.Currency; import net.sf.rails.game.state.MoneyOwner; import net.sf.rails.util.SequenceUtil; +import rails.game.action.BuyTrain; import rails.game.action.SetDividend; import com.google.common.collect.HashBasedTable; @@ -491,4 +493,25 @@ protected void prepareRevenueAndDividendAction() { allowedRevenueActions,0)); } } + + + /* (non-Javadoc) + * @see net.sf.rails.game.OperatingRound#buyTrain(rails.game.action.BuyTrain) + */ + @Override + public boolean buyTrain(BuyTrain action) { + boolean result = super.buyTrain(action); + // Check if we have just started Phase 5 and + // if we still have at least one Minor operating. + // If so, record the current player as the first + // one to act in the Final Minor Exchange Round. + if ((result) && getRoot().getPhaseManager().hasReachedPhase("5") + && operatingCompanies.get(0).getType().getId().equalsIgnoreCase("Minor") + && ((GameManager_1837)gameManager).getPlayerToStartFCERound() == null) { + ((GameManager_1837)gameManager).setPlayerToStartFCERound(operatingCompany.value().getPresident()); + } + return result; + } + + } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java index 2effc5f35..a98e70136 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/StockRound_1837.java @@ -41,6 +41,8 @@ public class StockRound_1837 extends StockRound { this, "discardingCompanyIndex"); protected final BooleanState discardingTrains = BooleanState.create(this, "discardingTrains"); + protected final BooleanState exchangedCoalCompanies = BooleanState.create(this, + "exchangdCoalCompanies"); protected PublicCompany[] discardingCompanies; @@ -58,6 +60,9 @@ public void start() { if (discardingTrains.value()) { discardingTrains.set(false); } + if (((GameManager_1837) gameManager).getPlayerToStartCERound()!= null) { + ((GameManager_1837) gameManager).setPlayerToStartCERound(null); + } } @Override @@ -299,7 +304,20 @@ protected void finishRound() { forcedMergeCompanyRoutine(company); } } + + } + else if (!exchangedCoalCompanies.value()){ + for (PublicCompany company : gameManager.getCompaniesInRunningOrder()) { + if ((company.hasStockPrice()) && (company.hasFloated())){ + if (findStartingPlayerForCoalExchange(company)) exchangedCoalCompanies.set(true); + } + } + } + else { + ((GameManager_1837) gameManager).setPlayerToStartCERound(null); } + + //TODO: Check correct order of next statements... if (discardingTrains.value()) { @@ -353,4 +371,35 @@ private void forcedMergeCompanyRoutine(PublicCompany company) { mergeCompanies(minor, targetCompany); } } + + private boolean findStartingPlayerForCoalExchange(PublicCompany company) { + List comps = companyManager.getAllPublicCompanies(); + List minors = new ArrayList(); + String type; + + for (PublicCompany comp : comps) { + type = comp.getType().getId(); + if (type.equals("Coal")) { + if (comp.isClosed()) continue; + if (comp.getRelatedNationalCompany().equals(company.getId())) { + minors.add(comp); + //The president of a Major Company is the first one to get the chance to exchange a share. + if (((GameManager_1837) gameManager).getPlayerToStartCERound()== null) { + ((GameManager_1837) gameManager).setPlayerToStartCERound(company.getPresident()); + return true; + //We found a victim lets move on. + } + } // Coal Company & Major Found + } //Coal Company Found + + } //Check if we have a minor that has a started Major + while (!minors.isEmpty()) { + //The first minors president will start the CoalExchangeRound + if (((GameManager_1837) gameManager).getPlayerToStartCERound()== null) { + ((GameManager_1837) gameManager).setPlayerToStartCERound(minors.get(0).getPresident()); + return true; + } + } + return false; + } } From 1daa1bb91399014932f757601aff680f3c9459f3 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 11 May 2019 14:16:39 +0200 Subject: [PATCH 28/45] Redoing the reservedHex Model for PublicCompanies --- src/main/java/net/sf/rails/game/MapHex.java | 14 +++++++++++-- .../java/net/sf/rails/game/PublicCompany.java | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/sf/rails/game/MapHex.java b/src/main/java/net/sf/rails/game/MapHex.java index e965e3bec..6f66e15c6 100644 --- a/src/main/java/net/sf/rails/game/MapHex.java +++ b/src/main/java/net/sf/rails/game/MapHex.java @@ -301,8 +301,8 @@ public void finishConfiguration(RailsRoot root) { currentTile.set(root.getTileManager().getTile(preprintedTileId)); currentTileRotation.set(preprintedTileRotation); - reservedForCompany = getRoot().getCompanyManager().getPublicCompany( - reservedForCompanyName); + setReservedForCompany(getRoot().getCompanyManager().getPublicCompany( + reservedForCompanyName)); // We need completely new objects, not just references to the Tile's // stations. @@ -940,6 +940,16 @@ public PublicCompany getReservedForCompany() { return reservedForCompany; } + /** + * @param reservedForCompany the reservedForCompany to set + */ + public void setReservedForCompany(PublicCompany reservedForCompany) { + this.reservedForCompany = reservedForCompany; + if (reservedForCompany != null) { + reservedForCompany.addReservedHex(this); + } + } + public boolean isReservedForCompany() { return reservedForCompany != null; } diff --git a/src/main/java/net/sf/rails/game/PublicCompany.java b/src/main/java/net/sf/rails/game/PublicCompany.java index d21a8f6ab..82e8d2334 100644 --- a/src/main/java/net/sf/rails/game/PublicCompany.java +++ b/src/main/java/net/sf/rails/game/PublicCompany.java @@ -308,6 +308,8 @@ public class PublicCompany extends RailsAbstractItem implements Company, RailsMo private String foundingStartCompany = null; + private List reservedHexes = null; + /** * Used by Configure (via reflection) only @@ -1981,9 +1983,21 @@ public void setClosed() { // close company on the stock market getRoot().getStockMarket().close(this); + + //make sure all reservations on the map are removed (18EU Hex Brussels for example + freeReservedHexes(); + + } + private void freeReservedHexes() { + if (reservedHexes != null) { + for (MapHex hex : reservedHexes) { + hex.setReservedForCompany(null); + } + } } + public String getLongName() { return longName; } @@ -2076,4 +2090,10 @@ public int getDirectIncomeRevenue() { return directIncomeRevenue.value(); } + + public void addReservedHex(MapHex mapHex) { + this.reservedHexes.add(mapHex); + + } + } From 159021d73c641f3c97759e28d79d80080c0ad8a3 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Mon, 20 May 2019 21:17:21 +0200 Subject: [PATCH 29/45] Revert "Redoing the reservedHex Model for PublicCompanies" This reverts commit 1daa1bb91399014932f757601aff680f3c9459f3. --- src/main/java/net/sf/rails/game/MapHex.java | 14 ++----------- .../java/net/sf/rails/game/PublicCompany.java | 20 ------------------- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/src/main/java/net/sf/rails/game/MapHex.java b/src/main/java/net/sf/rails/game/MapHex.java index 6f66e15c6..e965e3bec 100644 --- a/src/main/java/net/sf/rails/game/MapHex.java +++ b/src/main/java/net/sf/rails/game/MapHex.java @@ -301,8 +301,8 @@ public void finishConfiguration(RailsRoot root) { currentTile.set(root.getTileManager().getTile(preprintedTileId)); currentTileRotation.set(preprintedTileRotation); - setReservedForCompany(getRoot().getCompanyManager().getPublicCompany( - reservedForCompanyName)); + reservedForCompany = getRoot().getCompanyManager().getPublicCompany( + reservedForCompanyName); // We need completely new objects, not just references to the Tile's // stations. @@ -940,16 +940,6 @@ public PublicCompany getReservedForCompany() { return reservedForCompany; } - /** - * @param reservedForCompany the reservedForCompany to set - */ - public void setReservedForCompany(PublicCompany reservedForCompany) { - this.reservedForCompany = reservedForCompany; - if (reservedForCompany != null) { - reservedForCompany.addReservedHex(this); - } - } - public boolean isReservedForCompany() { return reservedForCompany != null; } diff --git a/src/main/java/net/sf/rails/game/PublicCompany.java b/src/main/java/net/sf/rails/game/PublicCompany.java index 82e8d2334..d21a8f6ab 100644 --- a/src/main/java/net/sf/rails/game/PublicCompany.java +++ b/src/main/java/net/sf/rails/game/PublicCompany.java @@ -308,8 +308,6 @@ public class PublicCompany extends RailsAbstractItem implements Company, RailsMo private String foundingStartCompany = null; - private List reservedHexes = null; - /** * Used by Configure (via reflection) only @@ -1983,21 +1981,9 @@ public void setClosed() { // close company on the stock market getRoot().getStockMarket().close(this); - - //make sure all reservations on the map are removed (18EU Hex Brussels for example - freeReservedHexes(); - - } - private void freeReservedHexes() { - if (reservedHexes != null) { - for (MapHex hex : reservedHexes) { - hex.setReservedForCompany(null); - } - } } - public String getLongName() { return longName; } @@ -2090,10 +2076,4 @@ public int getDirectIncomeRevenue() { return directIncomeRevenue.value(); } - - public void addReservedHex(MapHex mapHex) { - this.reservedHexes.add(mapHex); - - } - } From 7daf6ffe784fba4399a9b4ed56c0ec356238c4c7 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Tue, 28 May 2019 14:09:35 +0200 Subject: [PATCH 30/45] Fixing the problem with reserved hexes not being able to be upgraded if they have been upgraded already. Might need some additional work in the future if theres the rare case a company doesnt touch its reserved hex. --- .../net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java b/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java index 650511090..52e669db6 100644 --- a/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java +++ b/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java @@ -219,7 +219,14 @@ public boolean hexIsBlocked() { } public boolean hexIsReserved() { - return hex.getHex().isReservedForCompany() && hex.getHex().getReservedForCompany() != action.getCompany(); + if ( hex.getHex().isReservedForCompany() && hex.getHex().getReservedForCompany() != action.getCompany()) { + //check that the hex has not been upgraded already... + if (hex.getHex().isPreprintedTileCurrent()) { + return true; + } + } + return false; + } public boolean noTileAvailable() { From 9c890b0d689db5aa477c2710b7d75d413a5ea62b Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Tue, 28 May 2019 14:09:35 +0200 Subject: [PATCH 31/45] Working on Coal Exchange Round for 1837 --- .../game/specific/_1837/CoalExchangeRound.java | 17 +++++++++++++++-- .../game/specific/_1837/GameManager_1837.java | 9 ++++++++- .../rails/ui/swing/hexmap/TileHexUpgrade.java | 9 ++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/sf/rails/game/specific/_1837/CoalExchangeRound.java b/src/main/java/net/sf/rails/game/specific/_1837/CoalExchangeRound.java index f443c31ff..ecf887447 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/CoalExchangeRound.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/CoalExchangeRound.java @@ -10,6 +10,7 @@ import net.sf.rails.common.GuiDef; import net.sf.rails.common.LocalText; import net.sf.rails.common.ReportBuffer; +import net.sf.rails.game.Bank; import net.sf.rails.game.GameManager; import net.sf.rails.game.Player; import net.sf.rails.game.PublicCompany; @@ -184,8 +185,20 @@ protected void finishRound() { } else { - return; - + // Report financials + ReportBuffer.add(this, ""); + for (PublicCompany c : companyManager.getAllPublicCompanies()) { + if (c.hasFloated() && !c.isClosed()) { + ReportBuffer.add(this, LocalText.getText("Has", c.getId(), + Bank.format(this, c.getCash()))); + } + } + for (Player p : playerManager.getPlayers()) { + ReportBuffer.add(this, LocalText.getText("Has", p.getId(), + Bank.format(this, p.getCashValue()))); + } + // Inform GameManager + gameManager.nextRound(this); } } diff --git a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java index 21f625c47..92bc93d93 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java @@ -55,7 +55,8 @@ else if ((round instanceof StockRound_1837) ||(round instanceof OperatingRound_1 //Check if a Major is started and if so ask the Owner of the Coal Company to fold if (playerToStartCERound.value() != null) { cerNumber.add(1); - createRound (CoalExchangeRound.class, "CoalExchangeRound").start +// startMergingRound(false); + createRound (CoalExchangeRound.class, "CoalExchangeRound" + cerNumber.value()).start ((Player)playerToStartCERound.value()); playerToStartCERound.set(null); } else { @@ -96,6 +97,12 @@ else if (round instanceof NationalFormationRound) + private void startMergingRound(boolean b) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) * @see net.sf.rails.game.GameManager#runIfStartPacketIsNotCompletelySold() */ diff --git a/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java b/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java index 650511090..52e669db6 100644 --- a/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java +++ b/src/main/java/net/sf/rails/ui/swing/hexmap/TileHexUpgrade.java @@ -219,7 +219,14 @@ public boolean hexIsBlocked() { } public boolean hexIsReserved() { - return hex.getHex().isReservedForCompany() && hex.getHex().getReservedForCompany() != action.getCompany(); + if ( hex.getHex().isReservedForCompany() && hex.getHex().getReservedForCompany() != action.getCompany()) { + //check that the hex has not been upgraded already... + if (hex.getHex().isPreprintedTileCurrent()) { + return true; + } + } + return false; + } public boolean noTileAvailable() { From 12b1b55b1d1fcb8e927606dc4d0be541c09274c2 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sun, 23 Jun 2019 14:19:30 +0200 Subject: [PATCH 32/45] 1837-Working on Minor Coal Exchange Adding new mechanism to direct correct handling of OR and SR fter CoalexchangeRounds --- .../game/specific/_1837/GameManager_1837.java | 43 ++++++++++++++++++- .../net/sf/rails/ui/swing/GameUIManager.java | 6 ++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java index 1dddaff9b..932ddbda3 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/GameManager_1837.java @@ -7,6 +7,7 @@ import net.sf.rails.common.GuiDef.Parm; import net.sf.rails.game.GameManager; import net.sf.rails.game.NationalFormationRound; +import net.sf.rails.game.OperatingRound; import net.sf.rails.game.Phase; import net.sf.rails.game.Player; import net.sf.rails.game.RailsRoot; @@ -15,6 +16,7 @@ import net.sf.rails.game.StartRound; import net.sf.rails.game.specific._1837.OperatingRound_1837; import net.sf.rails.game.specific._18EU.FinalMinorExchangeRound; +import net.sf.rails.game.state.BooleanState; import net.sf.rails.game.state.GenericState; import net.sf.rails.game.state.IntegerState; @@ -35,6 +37,10 @@ public class GameManager_1837 extends GameManager { protected final GenericState playerToStartCERound = GenericState.create(this, "playerToStartCERound"); + + + protected final BooleanState CoalRoundFollowedByOR = + BooleanState.create(this, "CoalRoundFollowedByOr"); public GameManager_1837(RailsRoot parent, String id) { super(parent, id); @@ -52,7 +58,36 @@ public void nextRound(Round round) { } } else if (round instanceof CoalExchangeRound) { - super.nextRound(round); + //Since the CoalExchangeRound can happen after both types of rounds we need to move the + //round decision down to this class and cant call the superclass :( + + if (this.CoalRoundFollowedByOR.value()) { + Phase currentPhase = getRoot().getPhaseManager().getCurrentPhase(); + if (currentPhase == null) log.error ("Current Phase is null??", new Exception ("")); + numOfORs.set(currentPhase.getNumberOfOperatingRounds()); + log.info("Phase=" + currentPhase.toText() + " ORs=" + numOfORs); + + // Create a new OperatingRound (never more than one Stock Round) + // OperatingRound.resetRelativeORNumber(); + relativeORNumber.set(1); + startOperatingRound(true); + } + else { + if (relativeORNumber.add(1) <= numOfORs.value()) { + // There will be another OR + startOperatingRound(true); + } else { + if (gameOverPending.value() && gameEndsAfterSetOfORs) { + finishGame(); + } else { + ((OperatingRound)round).checkForeignSales(); + startStockRound(); + } + } + + } + + //super.nextRound(round); getCurrentRound().setPossibleActions(); } else if ((round instanceof StockRound_1837) ||(round instanceof OperatingRound_1837)) { @@ -188,4 +223,10 @@ public int getCERNumber () { return cerNumber.value(); } + + public void setCoalRoundFollowedByOR(boolean b) { + this.CoalRoundFollowedByOR.set(b); + + } + } diff --git a/src/main/java/net/sf/rails/ui/swing/GameUIManager.java b/src/main/java/net/sf/rails/ui/swing/GameUIManager.java index f90d46a8b..677034ede 100644 --- a/src/main/java/net/sf/rails/ui/swing/GameUIManager.java +++ b/src/main/java/net/sf/rails/ui/swing/GameUIManager.java @@ -526,8 +526,10 @@ public void updateUI() { } } - boolean correctionOverride = statusWindow.setupFor(currentRound); - correctionOverride = false; + //This was always false before ? Bug oversight ? + boolean correctionOverride = false; + + correctionOverride = statusWindow.setupFor(currentRound); if (correctionOverride) { log.debug("Correction overrides active window: status window active"); From 5a1947bdf91e7266fa1d988d39ad35119c752cbf Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Fri, 3 Jan 2020 22:54:42 +0100 Subject: [PATCH 33/45] Fixed a Bug in regard to shareselling while dumping the presidency. Previously it wasnt possible to dump x shares containing the presidency. Now it is. Befoire this fix you had to sell twice shares from the company with the president in your hand. Now the correct amount is available on the first sell. Bug reported by Peter De Boer, December 2019 --- .../net/sf/rails/game/PlayerShareUtils.java | 2 +- .../java/net/sf/rails/game/StockRound.java | 4 +- .../game/specific/_1835/StockRound_1835.java | 38 +++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/sf/rails/game/PlayerShareUtils.java b/src/main/java/net/sf/rails/game/PlayerShareUtils.java index 5f99167dd..e4f733a9b 100644 --- a/src/main/java/net/sf/rails/game/PlayerShareUtils.java +++ b/src/main/java/net/sf/rails/game/PlayerShareUtils.java @@ -124,7 +124,7 @@ private static SortedSet presidentSellMultiple(PublicCompany company, P // d is the amount sold in addition to standard shares, returned has the remaining part of the president share int remaining = presidentCert.getShares() - d; if (returnShareNumbers.contains(remaining)) { - sharesToSell.add(s); + sharesToSell.add(s+d); } } else { break; // pool is full diff --git a/src/main/java/net/sf/rails/game/StockRound.java b/src/main/java/net/sf/rails/game/StockRound.java index bb5efc746..1f4c33b86 100644 --- a/src/main/java/net/sf/rails/game/StockRound.java +++ b/src/main/java/net/sf/rails/game/StockRound.java @@ -422,7 +422,9 @@ public void setSellableShares() { Player potential = company.findPlayerToDump(); if (potential != null) { dumpThreshold = ownedShare - potential.getPortfolioModel().getShareNumber(company) + 1; - possibleSharesToSell = PlayerShareUtils.sharesToSell(company, currentPlayer); + possibleSharesToSell = PlayerShareUtils.sharesToSell(company, currentPlayer); + + dumpIsPossible = true; log.debug("dumpThreshold = " + dumpThreshold); log.debug("possibleSharesToSell = " + possibleSharesToSell); diff --git a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java index 6989fb280..72318d9da 100644 --- a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java +++ b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java @@ -5,6 +5,10 @@ package net.sf.rails.game.specific._1835; import java.util.Set; +import java.util.SortedSet; + +import com.google.common.collect.Sets; +import com.google.common.collect.SortedMultiset; import rails.game.action.BuyCertificate; import rails.game.action.NullAction; @@ -219,5 +223,39 @@ public boolean done(NullAction action, String playerName, } return super.done(action, playerName, hasAutopassed); } + + /* (non-Javadoc) + * @see net.sf.rails.game.StockRound#mayPlayerSellShareOfCompany(net.sf.rails.game.PublicCompany) + */ + @Override + public boolean mayPlayerSellShareOfCompany(PublicCompany company) { + PortfolioModel playerPortfolio = currentPlayer.getPortfolioModel(); + if (!super.mayPlayerSellShareOfCompany(company) ) + { + return false; + } + else { + /* + * Player is President and not allowed to sell his director share if thats the only share he got + * But if he has sold a share in this round he is allowed to sell dump the presidency... + * + * */ + if (company.getPresident() == currentPlayer) { + SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); + // Make sure that single shares are always considered (due to possible dumping) + SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); + certSizeElements.add(1); + for (int shareSize:certSizeElements) { + int number = certCount.count(shareSize); + if ((number == 0) && (shareSize == 1)) { + return false; //We found no normal share so the president cant sell the director + } + } + } + } + return true; + } + + } From b392b6dd690720c0af4c48da7c1ab24bf376ec28 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Mon, 2 Mar 2020 13:59:15 +0100 Subject: [PATCH 34/45] Working on multiple share selling problems in 1835. Its not allowed to split sell shares.. --- .../net/sf/rails/game/PlayerShareUtils.java | 24 ++++++-- .../java/net/sf/rails/game/StockRound.java | 57 ++++++++++++------- .../rails/game/model/CertificatesModel.java | 5 +- .../sf/rails/game/model/PortfolioModel.java | 2 +- .../game/specific/_1835/StockRound_1835.java | 38 ++++++++++--- src/main/resources/build/version.number | 2 +- src/main/resources/version.number | 2 +- 7 files changed, 91 insertions(+), 39 deletions(-) diff --git a/src/main/java/net/sf/rails/game/PlayerShareUtils.java b/src/main/java/net/sf/rails/game/PlayerShareUtils.java index e4f733a9b..3b7c90ab7 100644 --- a/src/main/java/net/sf/rails/game/PlayerShareUtils.java +++ b/src/main/java/net/sf/rails/game/PlayerShareUtils.java @@ -16,7 +16,7 @@ */ public class PlayerShareUtils { - public static SortedSet sharesToSell (PublicCompany company, Player player) { + public static SortedSet sharesToSell (PublicCompany company, Player player) { if (company.hasMultipleCertificates()) { if (player == company.getPresident()) { @@ -88,13 +88,18 @@ private static SortedSet presidentSellMultiple(PublicCompany company, P Player potential = company.findPlayerToDump(); int potentialShareNumber = potential.getPortfolioModel().getShare(company); int shareNumberDumpDifference = presidentShareNumber - potentialShareNumber; + boolean presidentShareOnly = false; - // ... if this is less than what the pool allows => goes back to non-president selling - int poolAllows = poolAllowsShareNumbers(company); - if (shareNumberDumpDifference <= poolAllows) { - return otherSellMultiple(company, president); + if (presidentCert.getShare() == presidentShareNumber) { // Only President Share to be sold... + presidentShareOnly = true; } + // ... if this is less than what the pool allows => goes back to non-president selling only if non president share... (1835 or other multipe director shares...) + int poolAllows = poolAllowsShareNumbers(company); + if ((shareNumberDumpDifference <= poolAllows) && (!presidentShareOnly)) { + return otherSellMultiple(company, president); + } + // second: separate the portfolio into other shares and president certificate ImmutableList.Builder otherCerts = ImmutableList.builder(); for (PublicCertificate c:president.getPortfolioModel().getCertificates(company)) { @@ -175,8 +180,15 @@ public static List findCertificatesToSell(PublicCompany compa break; } } + else if (cert.isPresidentShare() && cert.getShares()== shareUnits) { + certsToSell.add(cert); + nbCertsToSell--; + if (nbCertsToSell == 0) { + break; + } + } } - + return certsToSell.build(); } diff --git a/src/main/java/net/sf/rails/game/StockRound.java b/src/main/java/net/sf/rails/game/StockRound.java index 1f4c33b86..a99f79c92 100644 --- a/src/main/java/net/sf/rails/game/StockRound.java +++ b/src/main/java/net/sf/rails/game/StockRound.java @@ -422,8 +422,8 @@ public void setSellableShares() { Player potential = company.findPlayerToDump(); if (potential != null) { dumpThreshold = ownedShare - potential.getPortfolioModel().getShareNumber(company) + 1; - possibleSharesToSell = PlayerShareUtils.sharesToSell(company, currentPlayer); + possibleSharesToSell = checkForPossibleSharesToSell(company,currentPlayer); dumpIsPossible = true; log.debug("dumpThreshold = " + dumpThreshold); @@ -448,20 +448,21 @@ public void setSellableShares() { // Make sure that single shares are always considered (due to possible dumping) SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - certSizeElements.add(1); + // certSizeElements.add(1); for (int shareSize:certSizeElements) { int number = certCount.count(shareSize); - // If you can dump a presidency, you add the shareNumbers of the presidency - // to the single shares to be sold - if (dumpIsPossible && shareSize == 1 && number + company.getPresidentsShare().getShares() >= dumpThreshold) { - number += company.getPresidentsShare().getShares(); - // but limit this to the pool - number = Math.min(number, poolAllowsShares); - log.debug("Dump is possible increased single shares to " + number); - } + // If you can dump a presidency, you add the shareNumbers of the presidency + // to the single shares to be sold + if (dumpIsPossible && shareSize == 1 && number + + company.getPresidentsShare().getShares() >= dumpThreshold) { + number += company.getPresidentsShare().getShares(); // but limit this to the pool + number = Math.min(number, poolAllowsShares); + log.debug("Dump is possible increased single shares to " + number); + } + if (number == 0) { continue; } @@ -495,10 +496,12 @@ public void setSellableShares() { for (int i=1; i<=number; i++) { // check if selling would dump the company if (dumpIsPossible && i*shareSize >= dumpThreshold) { - // dumping requires that the total is in the possibleSharesToSell list and that shareSize == 1 - // multiple shares have to be sold separately + // dumping requires that the total is in the possibleSharesToSell list and that shareSize == 1 Comment: MBr-2020-03-02 why ? not true anymore from now on... + // multiple shares have to be sold separately Addition: Mbrumm 2020-03-01 (no not in all cases..... 1835 for example) if (shareSize == 1 && possibleSharesToSell.contains(i*shareSize)) { possibleActions.add(new SellShares(company, shareSize, i, price, 1)); + } else if ( shareSize >= 2 && possibleSharesToSell.contains(i*shareSize)) { + possibleActions.add(new SellShares(company, shareSize, i, price, 1)); } } else { // ... no dumping: standard sell @@ -506,6 +509,8 @@ public void setSellableShares() { } } } + // if we have multiple Sharesizes the combination of Sharesizes is also a viable sell option... + // but not possible in a single sell action due to the sharesize parameter handed over to sellShares... } // Is player over the total certificate hold limit? @@ -526,6 +531,11 @@ public void setSellableShares() { } } + protected SortedSet checkForPossibleSharesToSell( + PublicCompany company, Player currentPlayer) { + return PlayerShareUtils.sharesToSell(company, currentPlayer); + } + protected void setSpecialActions() { List sps = @@ -1046,17 +1056,21 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { // ... check if there is a dump required // Player is president => dump is possible - if (currentPlayer == company.getPresident() && shareUnits == 1) { + if (currentPlayer == company.getPresident() && ((shareUnits == 1) || (shareUnits == 2)) ) { dumpedPlayer = company.findPlayerToDump(); if (dumpedPlayer != null) { presidentShareNumbersToSell = PlayerShareUtils.presidentShareNumberToSell( company, currentPlayer, dumpedPlayer, numberToSell); - // reduce the numberToSell by the president (partial) sold certificate + numberToSell -= presidentShareNumbersToSell; } } - - certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); + if ((currentPlayer == company.getPresident()) && (currentPlayer.getPortfolioModel().getShareNumber(company)==2)) { + certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, 1, shareUnits); + } + else { + certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); + } // reduce numberToSell to double check for (PublicCertificate c:certsToSell) { @@ -1122,7 +1136,7 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { if (!company.isClosed()) { executeShareTransfer (company, certsToSell, - dumpedPlayer, presidentShareNumbersToSell); + dumpedPlayer, presidentShareNumbersToSell * shareUnits); } // Remember that the player has sold this company this round. @@ -1137,7 +1151,7 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { } // FIXME: Rails 2.x This has to be rewritten to give the new presidency a choice which shares to swap (if he has multiple share certificates) - protected final void executeShareTransferTo( PublicCompany company, + protected void executeShareTransferTo( PublicCompany company, List certsToSell, Player dumpedPlayer, int presSharesToSell, BankPortfolio bankTo) { @@ -1152,9 +1166,12 @@ protected final void executeShareTransferTo( PublicCompany company, } - // Transfer the sold certificates + // Transfer the sold certificates (but not the presidents Certificate... + if (certsToSell.get(0).isPresidentShare()) { //do nothing + return; + } else { Portfolio.moveAll(certsToSell, bankTo); - + } } protected void executeShareTransfer( PublicCompany company, diff --git a/src/main/java/net/sf/rails/game/model/CertificatesModel.java b/src/main/java/net/sf/rails/game/model/CertificatesModel.java index f299cf9ff..680127cd8 100644 --- a/src/main/java/net/sf/rails/game/model/CertificatesModel.java +++ b/src/main/java/net/sf/rails/game/model/CertificatesModel.java @@ -104,7 +104,10 @@ ImmutableMultimap getCertificatesByType(PublicCompany SortedMultiset getCertificateTypeCounts(PublicCompany company) { ImmutableSortedMultiset.Builder certCount = ImmutableSortedMultiset.naturalOrder(); for (PublicCertificate cert : getCertificates(company)) { - if (!cert.isPresidentShare()) { + if (!cert.isPresidentShare()) { // Acounting for director shares of different sizes + certCount.add(cert.getShares()); + } + else if ((cert.isPresidentShare()) && (cert.getShares() ==2)) { certCount.add(cert.getShares()); } } diff --git a/src/main/java/net/sf/rails/game/model/PortfolioModel.java b/src/main/java/net/sf/rails/game/model/PortfolioModel.java index ef1a3e596..e63cdb866 100644 --- a/src/main/java/net/sf/rails/game/model/PortfolioModel.java +++ b/src/main/java/net/sf/rails/game/model/PortfolioModel.java @@ -229,7 +229,7 @@ public ImmutableList getCertsOfType(String certTypeId) { /** * @return a sorted Multiset of shareNumbers of the certificates - * Remark: excludes the presdident share + * Remark: excludes the presdident share if not of a different size as the standard share... */ // FIXME: Integers could be replaced later by CerficateTypes public SortedMultiset getCertificateTypeCounts(PublicCompany company) { diff --git a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java index 72318d9da..ff11cf31f 100644 --- a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java +++ b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java @@ -4,9 +4,11 @@ */ package net.sf.rails.game.specific._1835; +import java.util.List; import java.util.Set; import java.util.SortedSet; +import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Sets; import com.google.common.collect.SortedMultiset; @@ -16,6 +18,7 @@ import net.sf.rails.common.ReportBuffer; import net.sf.rails.game.*; import net.sf.rails.game.model.PortfolioModel; +import net.sf.rails.game.state.Portfolio; public class StockRound_1835 extends StockRound { @@ -236,7 +239,7 @@ public boolean mayPlayerSellShareOfCompany(PublicCompany company) { } else { /* - * Player is President and not allowed to sell his director share if thats the only share he got + * Player is President and ia allowed to sell his director share if there is enough space in the pool in 1835 * But if he has sold a share in this round he is allowed to sell dump the presidency... * * */ @@ -244,18 +247,35 @@ public boolean mayPlayerSellShareOfCompany(PublicCompany company) { SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); // Make sure that single shares are always considered (due to possible dumping) SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - certSizeElements.add(1); - for (int shareSize:certSizeElements) { - int number = certCount.count(shareSize); - if ((number == 0) && (shareSize == 1)) { - return false; //We found no normal share so the president cant sell the director - } + if (certSizeElements.first()==2) { //President Share only, check if there is room in pool, President Share is 2 normal shares so space to sell must be 2 + if (PlayerShareUtils.poolAllowsShareNumbers(company) >1) return true; + } + if (certSizeElements.isEmpty()) return false; + } - } } return true; } - + + @Override protected SortedSet checkForPossibleSharesToSell(PublicCompany company, Player currentPlayer) { + PortfolioModel playerPortfolio = currentPlayer.getPortfolioModel(); + if (currentPlayer == company.getPresident()) { + ImmutableSortedSet.Builder presidentShareSet = ImmutableSortedSet.naturalOrder(); + SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); + // Make sure that single shares are always considered (due to possible dumping) + SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); + if (certSizeElements.first()==2) { //President Share only, check if there is room in pool, President Share is 2 normal shares so space to sell must be 2 + presidentShareSet.add(2); + return presidentShareSet.build(); + } else { + return PlayerShareUtils.sharesToSell(company, currentPlayer); + } + + } + return PlayerShareUtils.sharesToSell(company, currentPlayer); + + } + } diff --git a/src/main/resources/build/version.number b/src/main/resources/build/version.number index 2dc6843bf..d6acf829a 100644 --- a/src/main/resources/build/version.number +++ b/src/main/resources/build/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.8 +version=2.0.RC5.9 # the following string "@DEVELOP@" is replaced by an empty string in the release version # this is done automatically by gradle develop=@DEVELOP@ diff --git a/src/main/resources/version.number b/src/main/resources/version.number index 653415363..5b322eabc 100644 --- a/src/main/resources/version.number +++ b/src/main/resources/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.8 +version=2.0.RC5.9 # the following string "" is replaced by an empty string in the release version # this is done automatically by gradle develop= From 32eeea81b155037df8578ab06bb41fe993c47ad0 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Mon, 2 Mar 2020 20:58:03 +0100 Subject: [PATCH 35/45] Revert "Working on multiple share selling problems in 1835. Its not allowed to split sell shares.." This reverts commit b392b6dd690720c0af4c48da7c1ab24bf376ec28. --- .../net/sf/rails/game/PlayerShareUtils.java | 24 ++------ .../java/net/sf/rails/game/StockRound.java | 57 +++++++------------ .../rails/game/model/CertificatesModel.java | 5 +- .../sf/rails/game/model/PortfolioModel.java | 2 +- .../game/specific/_1835/StockRound_1835.java | 38 +++---------- src/main/resources/build/version.number | 2 +- src/main/resources/version.number | 2 +- 7 files changed, 39 insertions(+), 91 deletions(-) diff --git a/src/main/java/net/sf/rails/game/PlayerShareUtils.java b/src/main/java/net/sf/rails/game/PlayerShareUtils.java index 3b7c90ab7..e4f733a9b 100644 --- a/src/main/java/net/sf/rails/game/PlayerShareUtils.java +++ b/src/main/java/net/sf/rails/game/PlayerShareUtils.java @@ -16,7 +16,7 @@ */ public class PlayerShareUtils { - public static SortedSet sharesToSell (PublicCompany company, Player player) { + public static SortedSet sharesToSell (PublicCompany company, Player player) { if (company.hasMultipleCertificates()) { if (player == company.getPresident()) { @@ -88,18 +88,13 @@ private static SortedSet presidentSellMultiple(PublicCompany company, P Player potential = company.findPlayerToDump(); int potentialShareNumber = potential.getPortfolioModel().getShare(company); int shareNumberDumpDifference = presidentShareNumber - potentialShareNumber; - boolean presidentShareOnly = false; - if (presidentCert.getShare() == presidentShareNumber) { // Only President Share to be sold... - presidentShareOnly = true; - } - - // ... if this is less than what the pool allows => goes back to non-president selling only if non president share... (1835 or other multipe director shares...) + // ... if this is less than what the pool allows => goes back to non-president selling int poolAllows = poolAllowsShareNumbers(company); - if ((shareNumberDumpDifference <= poolAllows) && (!presidentShareOnly)) { + if (shareNumberDumpDifference <= poolAllows) { return otherSellMultiple(company, president); - } - + } + // second: separate the portfolio into other shares and president certificate ImmutableList.Builder otherCerts = ImmutableList.builder(); for (PublicCertificate c:president.getPortfolioModel().getCertificates(company)) { @@ -180,15 +175,8 @@ public static List findCertificatesToSell(PublicCompany compa break; } } - else if (cert.isPresidentShare() && cert.getShares()== shareUnits) { - certsToSell.add(cert); - nbCertsToSell--; - if (nbCertsToSell == 0) { - break; - } - } } - + return certsToSell.build(); } diff --git a/src/main/java/net/sf/rails/game/StockRound.java b/src/main/java/net/sf/rails/game/StockRound.java index a99f79c92..1f4c33b86 100644 --- a/src/main/java/net/sf/rails/game/StockRound.java +++ b/src/main/java/net/sf/rails/game/StockRound.java @@ -422,8 +422,8 @@ public void setSellableShares() { Player potential = company.findPlayerToDump(); if (potential != null) { dumpThreshold = ownedShare - potential.getPortfolioModel().getShareNumber(company) + 1; + possibleSharesToSell = PlayerShareUtils.sharesToSell(company, currentPlayer); - possibleSharesToSell = checkForPossibleSharesToSell(company,currentPlayer); dumpIsPossible = true; log.debug("dumpThreshold = " + dumpThreshold); @@ -448,21 +448,20 @@ public void setSellableShares() { // Make sure that single shares are always considered (due to possible dumping) SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - // certSizeElements.add(1); + certSizeElements.add(1); for (int shareSize:certSizeElements) { int number = certCount.count(shareSize); + // If you can dump a presidency, you add the shareNumbers of the presidency + // to the single shares to be sold + if (dumpIsPossible && shareSize == 1 && number + company.getPresidentsShare().getShares() >= dumpThreshold) { + number += company.getPresidentsShare().getShares(); + // but limit this to the pool + number = Math.min(number, poolAllowsShares); + log.debug("Dump is possible increased single shares to " + number); + } - // If you can dump a presidency, you add the shareNumbers of the presidency - // to the single shares to be sold - if (dumpIsPossible && shareSize == 1 && number + - company.getPresidentsShare().getShares() >= dumpThreshold) { - number += company.getPresidentsShare().getShares(); // but limit this to the pool - number = Math.min(number, poolAllowsShares); - log.debug("Dump is possible increased single shares to " + number); - } - if (number == 0) { continue; } @@ -496,12 +495,10 @@ public void setSellableShares() { for (int i=1; i<=number; i++) { // check if selling would dump the company if (dumpIsPossible && i*shareSize >= dumpThreshold) { - // dumping requires that the total is in the possibleSharesToSell list and that shareSize == 1 Comment: MBr-2020-03-02 why ? not true anymore from now on... - // multiple shares have to be sold separately Addition: Mbrumm 2020-03-01 (no not in all cases..... 1835 for example) + // dumping requires that the total is in the possibleSharesToSell list and that shareSize == 1 + // multiple shares have to be sold separately if (shareSize == 1 && possibleSharesToSell.contains(i*shareSize)) { possibleActions.add(new SellShares(company, shareSize, i, price, 1)); - } else if ( shareSize >= 2 && possibleSharesToSell.contains(i*shareSize)) { - possibleActions.add(new SellShares(company, shareSize, i, price, 1)); } } else { // ... no dumping: standard sell @@ -509,8 +506,6 @@ public void setSellableShares() { } } } - // if we have multiple Sharesizes the combination of Sharesizes is also a viable sell option... - // but not possible in a single sell action due to the sharesize parameter handed over to sellShares... } // Is player over the total certificate hold limit? @@ -531,11 +526,6 @@ public void setSellableShares() { } } - protected SortedSet checkForPossibleSharesToSell( - PublicCompany company, Player currentPlayer) { - return PlayerShareUtils.sharesToSell(company, currentPlayer); - } - protected void setSpecialActions() { List sps = @@ -1056,21 +1046,17 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { // ... check if there is a dump required // Player is president => dump is possible - if (currentPlayer == company.getPresident() && ((shareUnits == 1) || (shareUnits == 2)) ) { + if (currentPlayer == company.getPresident() && shareUnits == 1) { dumpedPlayer = company.findPlayerToDump(); if (dumpedPlayer != null) { presidentShareNumbersToSell = PlayerShareUtils.presidentShareNumberToSell( company, currentPlayer, dumpedPlayer, numberToSell); - + // reduce the numberToSell by the president (partial) sold certificate numberToSell -= presidentShareNumbersToSell; } } - if ((currentPlayer == company.getPresident()) && (currentPlayer.getPortfolioModel().getShareNumber(company)==2)) { - certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, 1, shareUnits); - } - else { - certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); - } + + certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); // reduce numberToSell to double check for (PublicCertificate c:certsToSell) { @@ -1136,7 +1122,7 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { if (!company.isClosed()) { executeShareTransfer (company, certsToSell, - dumpedPlayer, presidentShareNumbersToSell * shareUnits); + dumpedPlayer, presidentShareNumbersToSell); } // Remember that the player has sold this company this round. @@ -1151,7 +1137,7 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { } // FIXME: Rails 2.x This has to be rewritten to give the new presidency a choice which shares to swap (if he has multiple share certificates) - protected void executeShareTransferTo( PublicCompany company, + protected final void executeShareTransferTo( PublicCompany company, List certsToSell, Player dumpedPlayer, int presSharesToSell, BankPortfolio bankTo) { @@ -1166,12 +1152,9 @@ protected void executeShareTransferTo( PublicCompany company, } - // Transfer the sold certificates (but not the presidents Certificate... - if (certsToSell.get(0).isPresidentShare()) { //do nothing - return; - } else { + // Transfer the sold certificates Portfolio.moveAll(certsToSell, bankTo); - } + } protected void executeShareTransfer( PublicCompany company, diff --git a/src/main/java/net/sf/rails/game/model/CertificatesModel.java b/src/main/java/net/sf/rails/game/model/CertificatesModel.java index 680127cd8..f299cf9ff 100644 --- a/src/main/java/net/sf/rails/game/model/CertificatesModel.java +++ b/src/main/java/net/sf/rails/game/model/CertificatesModel.java @@ -104,10 +104,7 @@ ImmutableMultimap getCertificatesByType(PublicCompany SortedMultiset getCertificateTypeCounts(PublicCompany company) { ImmutableSortedMultiset.Builder certCount = ImmutableSortedMultiset.naturalOrder(); for (PublicCertificate cert : getCertificates(company)) { - if (!cert.isPresidentShare()) { // Acounting for director shares of different sizes - certCount.add(cert.getShares()); - } - else if ((cert.isPresidentShare()) && (cert.getShares() ==2)) { + if (!cert.isPresidentShare()) { certCount.add(cert.getShares()); } } diff --git a/src/main/java/net/sf/rails/game/model/PortfolioModel.java b/src/main/java/net/sf/rails/game/model/PortfolioModel.java index e63cdb866..ef1a3e596 100644 --- a/src/main/java/net/sf/rails/game/model/PortfolioModel.java +++ b/src/main/java/net/sf/rails/game/model/PortfolioModel.java @@ -229,7 +229,7 @@ public ImmutableList getCertsOfType(String certTypeId) { /** * @return a sorted Multiset of shareNumbers of the certificates - * Remark: excludes the presdident share if not of a different size as the standard share... + * Remark: excludes the presdident share */ // FIXME: Integers could be replaced later by CerficateTypes public SortedMultiset getCertificateTypeCounts(PublicCompany company) { diff --git a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java index ff11cf31f..72318d9da 100644 --- a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java +++ b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java @@ -4,11 +4,9 @@ */ package net.sf.rails.game.specific._1835; -import java.util.List; import java.util.Set; import java.util.SortedSet; -import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Sets; import com.google.common.collect.SortedMultiset; @@ -18,7 +16,6 @@ import net.sf.rails.common.ReportBuffer; import net.sf.rails.game.*; import net.sf.rails.game.model.PortfolioModel; -import net.sf.rails.game.state.Portfolio; public class StockRound_1835 extends StockRound { @@ -239,7 +236,7 @@ public boolean mayPlayerSellShareOfCompany(PublicCompany company) { } else { /* - * Player is President and ia allowed to sell his director share if there is enough space in the pool in 1835 + * Player is President and not allowed to sell his director share if thats the only share he got * But if he has sold a share in this round he is allowed to sell dump the presidency... * * */ @@ -247,35 +244,18 @@ public boolean mayPlayerSellShareOfCompany(PublicCompany company) { SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); // Make sure that single shares are always considered (due to possible dumping) SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - if (certSizeElements.first()==2) { //President Share only, check if there is room in pool, President Share is 2 normal shares so space to sell must be 2 - if (PlayerShareUtils.poolAllowsShareNumbers(company) >1) return true; - } - if (certSizeElements.isEmpty()) return false; - + certSizeElements.add(1); + for (int shareSize:certSizeElements) { + int number = certCount.count(shareSize); + if ((number == 0) && (shareSize == 1)) { + return false; //We found no normal share so the president cant sell the director + } } + } } return true; } + - - @Override protected SortedSet checkForPossibleSharesToSell(PublicCompany company, Player currentPlayer) { - PortfolioModel playerPortfolio = currentPlayer.getPortfolioModel(); - if (currentPlayer == company.getPresident()) { - ImmutableSortedSet.Builder presidentShareSet = ImmutableSortedSet.naturalOrder(); - SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); - // Make sure that single shares are always considered (due to possible dumping) - SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - if (certSizeElements.first()==2) { //President Share only, check if there is room in pool, President Share is 2 normal shares so space to sell must be 2 - presidentShareSet.add(2); - return presidentShareSet.build(); - } else { - return PlayerShareUtils.sharesToSell(company, currentPlayer); - } - - } - return PlayerShareUtils.sharesToSell(company, currentPlayer); - - } - } diff --git a/src/main/resources/build/version.number b/src/main/resources/build/version.number index d6acf829a..2dc6843bf 100644 --- a/src/main/resources/build/version.number +++ b/src/main/resources/build/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.9 +version=2.0.RC5.8 # the following string "@DEVELOP@" is replaced by an empty string in the release version # this is done automatically by gradle develop=@DEVELOP@ diff --git a/src/main/resources/version.number b/src/main/resources/version.number index 5b322eabc..653415363 100644 --- a/src/main/resources/version.number +++ b/src/main/resources/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.9 +version=2.0.RC5.8 # the following string "" is replaced by an empty string in the release version # this is done automatically by gradle develop= From 0d3e5dca2633d4ee2f8378a131727226a17858dc Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Mon, 2 Mar 2020 13:59:15 +0100 Subject: [PATCH 36/45] Working on multiple share selling problems in 1835. Its not allowed to split sell shares.. --- .../net/sf/rails/game/PlayerShareUtils.java | 24 ++++++-- .../java/net/sf/rails/game/StockRound.java | 57 ++++++++++++------- .../rails/game/model/CertificatesModel.java | 5 +- .../sf/rails/game/model/PortfolioModel.java | 2 +- .../game/specific/_1835/StockRound_1835.java | 38 ++++++++++--- src/main/resources/build/version.number | 2 +- src/main/resources/version.number | 2 +- 7 files changed, 91 insertions(+), 39 deletions(-) diff --git a/src/main/java/net/sf/rails/game/PlayerShareUtils.java b/src/main/java/net/sf/rails/game/PlayerShareUtils.java index e4f733a9b..3b7c90ab7 100644 --- a/src/main/java/net/sf/rails/game/PlayerShareUtils.java +++ b/src/main/java/net/sf/rails/game/PlayerShareUtils.java @@ -16,7 +16,7 @@ */ public class PlayerShareUtils { - public static SortedSet sharesToSell (PublicCompany company, Player player) { + public static SortedSet sharesToSell (PublicCompany company, Player player) { if (company.hasMultipleCertificates()) { if (player == company.getPresident()) { @@ -88,13 +88,18 @@ private static SortedSet presidentSellMultiple(PublicCompany company, P Player potential = company.findPlayerToDump(); int potentialShareNumber = potential.getPortfolioModel().getShare(company); int shareNumberDumpDifference = presidentShareNumber - potentialShareNumber; + boolean presidentShareOnly = false; - // ... if this is less than what the pool allows => goes back to non-president selling - int poolAllows = poolAllowsShareNumbers(company); - if (shareNumberDumpDifference <= poolAllows) { - return otherSellMultiple(company, president); + if (presidentCert.getShare() == presidentShareNumber) { // Only President Share to be sold... + presidentShareOnly = true; } + // ... if this is less than what the pool allows => goes back to non-president selling only if non president share... (1835 or other multipe director shares...) + int poolAllows = poolAllowsShareNumbers(company); + if ((shareNumberDumpDifference <= poolAllows) && (!presidentShareOnly)) { + return otherSellMultiple(company, president); + } + // second: separate the portfolio into other shares and president certificate ImmutableList.Builder otherCerts = ImmutableList.builder(); for (PublicCertificate c:president.getPortfolioModel().getCertificates(company)) { @@ -175,8 +180,15 @@ public static List findCertificatesToSell(PublicCompany compa break; } } + else if (cert.isPresidentShare() && cert.getShares()== shareUnits) { + certsToSell.add(cert); + nbCertsToSell--; + if (nbCertsToSell == 0) { + break; + } + } } - + return certsToSell.build(); } diff --git a/src/main/java/net/sf/rails/game/StockRound.java b/src/main/java/net/sf/rails/game/StockRound.java index 1f4c33b86..a99f79c92 100644 --- a/src/main/java/net/sf/rails/game/StockRound.java +++ b/src/main/java/net/sf/rails/game/StockRound.java @@ -422,8 +422,8 @@ public void setSellableShares() { Player potential = company.findPlayerToDump(); if (potential != null) { dumpThreshold = ownedShare - potential.getPortfolioModel().getShareNumber(company) + 1; - possibleSharesToSell = PlayerShareUtils.sharesToSell(company, currentPlayer); + possibleSharesToSell = checkForPossibleSharesToSell(company,currentPlayer); dumpIsPossible = true; log.debug("dumpThreshold = " + dumpThreshold); @@ -448,20 +448,21 @@ public void setSellableShares() { // Make sure that single shares are always considered (due to possible dumping) SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - certSizeElements.add(1); + // certSizeElements.add(1); for (int shareSize:certSizeElements) { int number = certCount.count(shareSize); - // If you can dump a presidency, you add the shareNumbers of the presidency - // to the single shares to be sold - if (dumpIsPossible && shareSize == 1 && number + company.getPresidentsShare().getShares() >= dumpThreshold) { - number += company.getPresidentsShare().getShares(); - // but limit this to the pool - number = Math.min(number, poolAllowsShares); - log.debug("Dump is possible increased single shares to " + number); - } + // If you can dump a presidency, you add the shareNumbers of the presidency + // to the single shares to be sold + if (dumpIsPossible && shareSize == 1 && number + + company.getPresidentsShare().getShares() >= dumpThreshold) { + number += company.getPresidentsShare().getShares(); // but limit this to the pool + number = Math.min(number, poolAllowsShares); + log.debug("Dump is possible increased single shares to " + number); + } + if (number == 0) { continue; } @@ -495,10 +496,12 @@ public void setSellableShares() { for (int i=1; i<=number; i++) { // check if selling would dump the company if (dumpIsPossible && i*shareSize >= dumpThreshold) { - // dumping requires that the total is in the possibleSharesToSell list and that shareSize == 1 - // multiple shares have to be sold separately + // dumping requires that the total is in the possibleSharesToSell list and that shareSize == 1 Comment: MBr-2020-03-02 why ? not true anymore from now on... + // multiple shares have to be sold separately Addition: Mbrumm 2020-03-01 (no not in all cases..... 1835 for example) if (shareSize == 1 && possibleSharesToSell.contains(i*shareSize)) { possibleActions.add(new SellShares(company, shareSize, i, price, 1)); + } else if ( shareSize >= 2 && possibleSharesToSell.contains(i*shareSize)) { + possibleActions.add(new SellShares(company, shareSize, i, price, 1)); } } else { // ... no dumping: standard sell @@ -506,6 +509,8 @@ public void setSellableShares() { } } } + // if we have multiple Sharesizes the combination of Sharesizes is also a viable sell option... + // but not possible in a single sell action due to the sharesize parameter handed over to sellShares... } // Is player over the total certificate hold limit? @@ -526,6 +531,11 @@ public void setSellableShares() { } } + protected SortedSet checkForPossibleSharesToSell( + PublicCompany company, Player currentPlayer) { + return PlayerShareUtils.sharesToSell(company, currentPlayer); + } + protected void setSpecialActions() { List sps = @@ -1046,17 +1056,21 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { // ... check if there is a dump required // Player is president => dump is possible - if (currentPlayer == company.getPresident() && shareUnits == 1) { + if (currentPlayer == company.getPresident() && ((shareUnits == 1) || (shareUnits == 2)) ) { dumpedPlayer = company.findPlayerToDump(); if (dumpedPlayer != null) { presidentShareNumbersToSell = PlayerShareUtils.presidentShareNumberToSell( company, currentPlayer, dumpedPlayer, numberToSell); - // reduce the numberToSell by the president (partial) sold certificate + numberToSell -= presidentShareNumbersToSell; } } - - certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); + if ((currentPlayer == company.getPresident()) && (currentPlayer.getPortfolioModel().getShareNumber(company)==2)) { + certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, 1, shareUnits); + } + else { + certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); + } // reduce numberToSell to double check for (PublicCertificate c:certsToSell) { @@ -1122,7 +1136,7 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { if (!company.isClosed()) { executeShareTransfer (company, certsToSell, - dumpedPlayer, presidentShareNumbersToSell); + dumpedPlayer, presidentShareNumbersToSell * shareUnits); } // Remember that the player has sold this company this round. @@ -1137,7 +1151,7 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { } // FIXME: Rails 2.x This has to be rewritten to give the new presidency a choice which shares to swap (if he has multiple share certificates) - protected final void executeShareTransferTo( PublicCompany company, + protected void executeShareTransferTo( PublicCompany company, List certsToSell, Player dumpedPlayer, int presSharesToSell, BankPortfolio bankTo) { @@ -1152,9 +1166,12 @@ protected final void executeShareTransferTo( PublicCompany company, } - // Transfer the sold certificates + // Transfer the sold certificates (but not the presidents Certificate... + if (certsToSell.get(0).isPresidentShare()) { //do nothing + return; + } else { Portfolio.moveAll(certsToSell, bankTo); - + } } protected void executeShareTransfer( PublicCompany company, diff --git a/src/main/java/net/sf/rails/game/model/CertificatesModel.java b/src/main/java/net/sf/rails/game/model/CertificatesModel.java index f299cf9ff..680127cd8 100644 --- a/src/main/java/net/sf/rails/game/model/CertificatesModel.java +++ b/src/main/java/net/sf/rails/game/model/CertificatesModel.java @@ -104,7 +104,10 @@ ImmutableMultimap getCertificatesByType(PublicCompany SortedMultiset getCertificateTypeCounts(PublicCompany company) { ImmutableSortedMultiset.Builder certCount = ImmutableSortedMultiset.naturalOrder(); for (PublicCertificate cert : getCertificates(company)) { - if (!cert.isPresidentShare()) { + if (!cert.isPresidentShare()) { // Acounting for director shares of different sizes + certCount.add(cert.getShares()); + } + else if ((cert.isPresidentShare()) && (cert.getShares() ==2)) { certCount.add(cert.getShares()); } } diff --git a/src/main/java/net/sf/rails/game/model/PortfolioModel.java b/src/main/java/net/sf/rails/game/model/PortfolioModel.java index ef1a3e596..e63cdb866 100644 --- a/src/main/java/net/sf/rails/game/model/PortfolioModel.java +++ b/src/main/java/net/sf/rails/game/model/PortfolioModel.java @@ -229,7 +229,7 @@ public ImmutableList getCertsOfType(String certTypeId) { /** * @return a sorted Multiset of shareNumbers of the certificates - * Remark: excludes the presdident share + * Remark: excludes the presdident share if not of a different size as the standard share... */ // FIXME: Integers could be replaced later by CerficateTypes public SortedMultiset getCertificateTypeCounts(PublicCompany company) { diff --git a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java index 72318d9da..ff11cf31f 100644 --- a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java +++ b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java @@ -4,9 +4,11 @@ */ package net.sf.rails.game.specific._1835; +import java.util.List; import java.util.Set; import java.util.SortedSet; +import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Sets; import com.google.common.collect.SortedMultiset; @@ -16,6 +18,7 @@ import net.sf.rails.common.ReportBuffer; import net.sf.rails.game.*; import net.sf.rails.game.model.PortfolioModel; +import net.sf.rails.game.state.Portfolio; public class StockRound_1835 extends StockRound { @@ -236,7 +239,7 @@ public boolean mayPlayerSellShareOfCompany(PublicCompany company) { } else { /* - * Player is President and not allowed to sell his director share if thats the only share he got + * Player is President and ia allowed to sell his director share if there is enough space in the pool in 1835 * But if he has sold a share in this round he is allowed to sell dump the presidency... * * */ @@ -244,18 +247,35 @@ public boolean mayPlayerSellShareOfCompany(PublicCompany company) { SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); // Make sure that single shares are always considered (due to possible dumping) SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - certSizeElements.add(1); - for (int shareSize:certSizeElements) { - int number = certCount.count(shareSize); - if ((number == 0) && (shareSize == 1)) { - return false; //We found no normal share so the president cant sell the director - } + if (certSizeElements.first()==2) { //President Share only, check if there is room in pool, President Share is 2 normal shares so space to sell must be 2 + if (PlayerShareUtils.poolAllowsShareNumbers(company) >1) return true; + } + if (certSizeElements.isEmpty()) return false; + } - } } return true; } - + + @Override protected SortedSet checkForPossibleSharesToSell(PublicCompany company, Player currentPlayer) { + PortfolioModel playerPortfolio = currentPlayer.getPortfolioModel(); + if (currentPlayer == company.getPresident()) { + ImmutableSortedSet.Builder presidentShareSet = ImmutableSortedSet.naturalOrder(); + SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); + // Make sure that single shares are always considered (due to possible dumping) + SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); + if (certSizeElements.first()==2) { //President Share only, check if there is room in pool, President Share is 2 normal shares so space to sell must be 2 + presidentShareSet.add(2); + return presidentShareSet.build(); + } else { + return PlayerShareUtils.sharesToSell(company, currentPlayer); + } + + } + return PlayerShareUtils.sharesToSell(company, currentPlayer); + + } + } diff --git a/src/main/resources/build/version.number b/src/main/resources/build/version.number index 2dc6843bf..d6acf829a 100644 --- a/src/main/resources/build/version.number +++ b/src/main/resources/build/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.8 +version=2.0.RC5.9 # the following string "@DEVELOP@" is replaced by an empty string in the release version # this is done automatically by gradle develop=@DEVELOP@ diff --git a/src/main/resources/version.number b/src/main/resources/version.number index 653415363..5b322eabc 100644 --- a/src/main/resources/version.number +++ b/src/main/resources/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.8 +version=2.0.RC5.9 # the following string "" is replaced by an empty string in the release version # this is done automatically by gradle develop= From 1910d6895561ad89612354af7289b444c95246ce Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Wed, 4 Mar 2020 23:42:59 +0100 Subject: [PATCH 37/45] Fixing the SellShares problem stemming from the newly introduced handling for the President Share Selling --- .../java/net/sf/rails/game/StockRound.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/sf/rails/game/StockRound.java b/src/main/java/net/sf/rails/game/StockRound.java index a99f79c92..d9180746d 100644 --- a/src/main/java/net/sf/rails/game/StockRound.java +++ b/src/main/java/net/sf/rails/game/StockRound.java @@ -1007,6 +1007,7 @@ public boolean sellShares(SellShares action) int presidentShareNumbersToSell = 0; int numberToSell = action.getNumber(); int shareUnits = action.getShareUnits(); + int presidentExchange = action.getPresidentExchange(); // Dummy loop to allow a quick jump out while (true) { @@ -1056,13 +1057,18 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { // ... check if there is a dump required // Player is president => dump is possible - if (currentPlayer == company.getPresident() && ((shareUnits == 1) || (shareUnits == 2)) ) { + if (presidentExchange >0) { // we have found in the Original Routine that a President will change... dumpedPlayer = company.findPlayerToDump(); if (dumpedPlayer != null) { presidentShareNumbersToSell = PlayerShareUtils.presidentShareNumberToSell( company, currentPlayer, dumpedPlayer, numberToSell); - - numberToSell -= presidentShareNumbersToSell; + + numberToSell -= presidentShareNumbersToSell; // Besides the President Share which normal counts at least 2 shareunits. + + } + else { + errMsg = "President Exchange but no suitable target found!"; + break; } } if ((currentPlayer == company.getPresident()) && (currentPlayer.getPortfolioModel().getShareNumber(company)==2)) { @@ -1090,7 +1096,7 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { break; } - int numberSold = action.getNumber(); + int numberSold = action.getNumber(); //Beware that the number sold is the number of shareunits, not the certs. if (errMsg != null) { DisplayBuffer.add(this, LocalText.getText("CantSell", playerName, @@ -1136,7 +1142,7 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { if (!company.isClosed()) { executeShareTransfer (company, certsToSell, - dumpedPlayer, presidentShareNumbersToSell * shareUnits); + dumpedPlayer, presidentShareNumbersToSell); } // Remember that the player has sold this company this round. @@ -1167,11 +1173,9 @@ protected void executeShareTransferTo( PublicCompany company, } // Transfer the sold certificates (but not the presidents Certificate... - if (certsToSell.get(0).isPresidentShare()) { //do nothing - return; - } else { + Portfolio.moveAll(certsToSell, bankTo); - } + } protected void executeShareTransfer( PublicCompany company, From 1017cde796fc20e14b7f1b9ff26e14c252f6b1d0 Mon Sep 17 00:00:00 2001 From: "Dr. Maritn Brumm" Date: Sat, 7 Mar 2020 21:06:26 +0100 Subject: [PATCH 38/45] Fixing Share selling problematic arising from 1835 share problem of not being allowed to split director shares. --- .../net/sf/rails/game/ShareSellingRound.java | 2 +- .../java/net/sf/rails/game/StockRound.java | 19 ++++++++++++++++--- .../game/specific/_1835/StockRound_1835.java | 8 +++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/sf/rails/game/ShareSellingRound.java b/src/main/java/net/sf/rails/game/ShareSellingRound.java index 56371a9d1..b4b46010f 100644 --- a/src/main/java/net/sf/rails/game/ShareSellingRound.java +++ b/src/main/java/net/sf/rails/game/ShareSellingRound.java @@ -237,7 +237,7 @@ public boolean sellShares(SellShares action) { int presSharesToSell = 0; int numberToSell = action.getNumber(); int shareUnits = action.getShareUnits(); - + int presidentExchange = action.getPresidentExchange(); // Dummy loop to allow a quick jump out while (true) { diff --git a/src/main/java/net/sf/rails/game/StockRound.java b/src/main/java/net/sf/rails/game/StockRound.java index d9180746d..0ef279040 100644 --- a/src/main/java/net/sf/rails/game/StockRound.java +++ b/src/main/java/net/sf/rails/game/StockRound.java @@ -448,7 +448,7 @@ public void setSellableShares() { // Make sure that single shares are always considered (due to possible dumping) SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - // certSizeElements.add(1); + certSizeElements.add(1); for (int shareSize:certSizeElements) { int number = certCount.count(shareSize); @@ -1071,8 +1071,14 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { break; } } - if ((currentPlayer == company.getPresident()) && (currentPlayer.getPortfolioModel().getShareNumber(company)==2)) { - certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, 1, shareUnits); + if (presidentExchange >0) { + //is it allowed to split a presidency Certificate on sale ? + if (checkIfPresidentCertifcateSplitSaleAllowed()) { + certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); + } + else { + certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, 1, shareUnits); + } } else { certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); @@ -1156,6 +1162,8 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { return true; } + + // FIXME: Rails 2.x This has to be rewritten to give the new presidency a choice which shares to swap (if he has multiple share certificates) protected void executeShareTransferTo( PublicCompany company, List certsToSell, Player dumpedPlayer, int presSharesToSell, @@ -1648,5 +1656,10 @@ public void setSellObligationLifted (PublicCompany company) { } sellObligationLifted.add(company); } + + private boolean checkIfPresidentCertifcateSplitSaleAllowed() { + // Standard Games its true + return true; + } } diff --git a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java index ff11cf31f..b34ea11ce 100644 --- a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java +++ b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java @@ -247,10 +247,11 @@ public boolean mayPlayerSellShareOfCompany(PublicCompany company) { SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); // Make sure that single shares are always considered (due to possible dumping) SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); + if (certSizeElements.isEmpty()) return false; if (certSizeElements.first()==2) { //President Share only, check if there is room in pool, President Share is 2 normal shares so space to sell must be 2 if (PlayerShareUtils.poolAllowsShareNumbers(company) >1) return true; } - if (certSizeElements.isEmpty()) return false; + } } @@ -277,5 +278,10 @@ public boolean mayPlayerSellShareOfCompany(PublicCompany company) { return PlayerShareUtils.sharesToSell(company, currentPlayer); } + + private boolean checkIfPresidentCertifcateSplitSaleAllowed() { + // in 1835 its not allowed to Split the President Certificate on sale + return false; + } } From 2f60f23555b3575bb6c8045624bd57e7ffbab96c Mon Sep 17 00:00:00 2001 From: "Dr. Martin Brumm" Date: Sat, 7 Mar 2020 21:11:10 +0100 Subject: [PATCH 39/45] Savegames adjusted for various problems including missing coal rights... --- .../rails/game/model/CertificatesModel.java | 5 +---- .../data/bugs/1830_sellPresidency.rails | Bin 11828 -> 0 bytes src/test/resources/data/real/1830_A.rails | Bin 41313 -> 0 bytes src/test/resources/data/real/1830_B.rails | Bin 0 -> 11566 bytes src/test/resources/data/real/1889_B.rails | Bin 26253 -> 27611 bytes src/test/resources/data/real/1889_B.report | 4 ++-- .../data/test/1830_SellFullPresCert.rails | Bin 8451 -> 8719 bytes .../data/test/1830_SellHalfPresCert.rails | Bin 8451 -> 8719 bytes .../data/test/1835_SellDoubleShare.rails | Bin 30335 -> 31358 bytes .../data/test/1835_ShareSelling_Test.rails | Bin 22309 -> 22789 bytes 10 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 src/test/resources/data/bugs/1830_sellPresidency.rails delete mode 100644 src/test/resources/data/real/1830_A.rails create mode 100644 src/test/resources/data/real/1830_B.rails diff --git a/src/main/java/net/sf/rails/game/model/CertificatesModel.java b/src/main/java/net/sf/rails/game/model/CertificatesModel.java index 680127cd8..131aa74ea 100644 --- a/src/main/java/net/sf/rails/game/model/CertificatesModel.java +++ b/src/main/java/net/sf/rails/game/model/CertificatesModel.java @@ -104,10 +104,7 @@ ImmutableMultimap getCertificatesByType(PublicCompany SortedMultiset getCertificateTypeCounts(PublicCompany company) { ImmutableSortedMultiset.Builder certCount = ImmutableSortedMultiset.naturalOrder(); for (PublicCertificate cert : getCertificates(company)) { - if (!cert.isPresidentShare()) { // Acounting for director shares of different sizes - certCount.add(cert.getShares()); - } - else if ((cert.isPresidentShare()) && (cert.getShares() ==2)) { + if (!cert.isPresidentShare()) { certCount.add(cert.getShares()); } } diff --git a/src/test/resources/data/bugs/1830_sellPresidency.rails b/src/test/resources/data/bugs/1830_sellPresidency.rails deleted file mode 100644 index c3fd78ca3a74335f99a6065440428bf18bce961a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11828 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 diff --git a/src/test/resources/data/real/1830_A.rails b/src/test/resources/data/real/1830_A.rails deleted file mode 100644 index af64f9c5bf9805ce7c5cf2aeba324418bd660d59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41313 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 pYb2>mCl}4NPc1b%jc&WsO%{l8XN3%&pV diff --git a/src/test/resources/data/real/1830_B.rails b/src/test/resources/data/real/1830_B.rails new file mode 100644 index 0000000000000000000000000000000000000000..c1bb51e483d34c13d1dc3530d3e16a9ce2c56f02 GIT binary patch literal 11566 zcmd5?dyHIF89y_-+xNQ_DYm3q*cOmwA8l!Y1b3(1?!fHBooySonsPgHx_jl$+~M9k z+g(jWVnh=#YC=tnG2stM6d@!8jU`GXkcf#S!k@+jH5kD}qkrjt`1`(d?m6eq%s!x! zc#}JG=iKl6&i6X!dz^Xp@1iFW8wdOP`=$#=`%WZc_hA2E|Ly%lxAz}AFgS46(GzzK z48@Vy_62Xj>kGX4Twf`y&)xm_JKz58w+_CY7rFaH&w>{;3udgX&`A-p??p>o0G>_W|776S3=@pUh7-5SugUvIuLgiLNB=F%b*(fPD`)q*XI(kWkk;T^}38s zd$km0S4nyca=2NcsVD1GUK~FxzASbo;uD45;ew13|B_$v5_wpYnXCs(w?L@rlcy80 z=S)5DYknfDGhu_pjW3+k_?q|2UL@->hP)fc{JHr6H~8B(b2-$CpgBrJ1={*d%chrX(p`m)UEQ4Sg8pB(q!p;2d0KbG9Et@__ zG5tlDez!IKa1?ngN646tbkNlYE-U!17ao-#m?t|w*vwb6ewVZfSQcPqGgy_oUMGssG08KBz z`=Z!#5uf!+Bx}$@QEaODb-&iE;oYp*5z9bUlF=~I#+nry)R3&g>p$5(rI~M-Sx}SG zta;1|o7IZ-s$49It#QiO1pCFV5~<}5T4r~Yp;9a~OmLumf~gRWcrlO}`dxX^H7j}` zm4rl_8|>|RrcLS>O+z-gb+M5nuITw7zPsR7IJ*<*zS_Jy>L6#fN8C%kx+s?9@fk(;(+|%sMM}#xk)WwDe}h_SoRegk=d{ zuCIi(hF4#jkdhX0SZ&J0V~1iMChCqcc6`wy5z z4KzA016~6K<)MJ53(FvPUb`hbKW(Syi=B6wk>-*Uh7x78%6i8VNtaN%HI>AMOHo*}TNMGaX{>I+3vvok zz`dsd9ZWn>NW_K_ul~@5;?!g_BALctda!rlZ!bKZCLilG!fAZdE<%fI7I&4`3!B+Y zAe5axOWL=_!w;I32&h?m&k=8DoAh}OqidMLP;;lSuFx_?_rwDeW3FT$U?xLU&s5Gj zGG?LyQsJg{6gk*YV%u(YvBthH(QtAKPhgTSV)2}^+2Ig$>fj~MJy>ztQ{@vN-Xh~6Xg@fFLJ z0d-|FE|uc1O+|++Z_I}As8%vYJy$Fv2H0g}MfW2~t{`0OZx5Q&68mzT%rv7q@q~+_ zMM><5)C(jys&MGAHLE#^_|29(!-&hBanw{kWjsRtzG99(m6@0xG2(}^+V$y=I1{X?SQf?Btt#t1yWN~1-})=_4n^58NQ ziDo2`ypMRXoCzP2^|*+1v>}nV22)YkKnz_XobF_)LD@`YK8$63OfDL`U@!<#I->lc zF}4V@(H%tAuUfjOjh&Pf746+6aa}8rDnv+&oY0mG*F1C{wU815nZ)k%?F9@XJn~&x z2!pU0F(*GhFV@pgQAOTqBp;t@S6N!(Oirsr?!EkTuif^K4ZmZTY)cw!{-$g}IYBRl z zQ$PIoqhCJ`Mv&;J-Uq3oi%=IGPc>eVC$G4nT}0$pT)8XW1aj2vRFzh%vRXht1kacJ zMLdUbGAnjn3Q?k0fm6IR5ps88R%}y)rxq*os2OEZ>}sG(;#c8HL}4ZzuA+e5Z3f4^ zC5+IkS)?#2=s1dMJ&ZZI7Mg;UJ9!=aL+Z(@%zH~Vw?!@{kvER6gEyxt&DL}dz6l7w zoZs5TfMRqDo3cx<|49JkX8y9DT|AZ{7)Jzt5PAhWC8eB}#7}>iEi6K4*FZ7e~ z2kkCp%%nGjA2Bx3JE-#+P&lDUt1r+Q9qeZ}${)RR4Sqz_UI1>!Kg^~B{~&;$+KK7s zFZ7fvOEb_Q*sE3?L)8^0Ex5rrQe_Y(dB|bah2c{JC$3c<-kGU_bLCNk#N%)DWGl-v z=*Ytg=|DgeqAzV;qW>macjy}Nk6a`EQ3v1F6r`0*yvgK2&YodY8#Tx&fk{`$LFi61 zi{eHLEB+lzf~7$NNHyDt6Nm3?V&}YQ703or;?5;u z=F@|`4%-}e17Q(Ue9=N2IL?lnJFaG3aX%*!+twjZ{7=y1eY!(pgf7iVe}Q&Y${FcG z1m92;`_O7b15sDlGm-S-X0)XH%0;nNz1F|cQmT1NXJQ$FoPpU#o3KolC81s$@GX>z z`B54lc1Eg)J&a(b!u@%%*Q3ZKs~X3?V#`k3eN%}|8u^zJ%2li$F_kUVy>zSAoONtc zo4e8QX8JA>{R>`n2)={LSZfKs9gU?X0BttbAt$I-!YD$Uwy&VRk^4}8KGOxFe0El> zgI&C z@39xfsKJ5NyoYdqMIW!YnV5-*Ix?{Y*~w_4d+f%d=3P#LWg<28R?~~08ypN?1M5R7 z?HID#tKms2fOlxt3RQ%}3EgU^XN_EQAA_mjBX`3pT$s8o%LT+xQNkr)VBPR$Ydj|s z@P6~Z>x?>S8Vd$x9m8!euzT7hHAj{U4v4KibCHyFBJzsK{Q1|1a3Pc2+@l#;&V_gj zZS?_`N%??MHi*zF;GLHVV)*`nqpPd}BNN-1aXEKws6q0T0WF8(7e7Yz zz;c4|+Gxk`ur?rz%E^Z=a2A{Uxb;iJ72K+0haYti`qv9M$>LhB)PYZ{7|M%8!Kf_t3x?SO$KTgD0IT_>RiID zwPVn#j#Nxq$+?qCFk%#Uo>jv8s#@nMEHQJKbwW@2TF!TDUP1drCNh|W+16xx0b(gL zJ1P~-4<220xi7Oc&bUj1mS>JmTim6g2I&pg9(emy%0xP_qIia=E1pTKA%*H&kSk@D z{e8M`u|mPQ+Pc5!3P&p}_qi6~)F8e2Jl@c?mS7cPW{DK|M&2@x6c0cz5QQ0 zjXae9iAjjLH|(xzjG>$$_f7I4wIvYbckpWyL$h~eUyyK_{C0dmH+PPIXy-7yk#-JV agRO(Mdvz#fl6d(p@lMyG`VykOd-Y$Fqi9M1 literal 0 HcmV?d00001 diff --git a/src/test/resources/data/real/1889_B.rails b/src/test/resources/data/real/1889_B.rails index c118a189a5c7afa1c9660f3cd0581887588e1516..6d0aff53414bb072107d27db3c4b10c9ae5a99ab 100644 GIT binary patch literal 27611 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 diff --git a/src/test/resources/data/real/1889_B.report b/src/test/resources/data/real/1889_B.report index 24086298b..54eb910f5 100644 --- a/src/test/resources/data/real/1889_B.report +++ b/src/test/resources/data/real/1889_B.report @@ -1051,7 +1051,7 @@ PresidentAddsCash,IR,klaus,322 BuysTrain,IR,D,IPO,1100 CompanyOperates,SR,stefan -LaysTileAt,SR,42,I8,NW +LaysTileAt,SR,58,J9,NW CompanyRevenue,SR,450 CompanyPaysOutFull,SR,450 Payout,stefan,225,5,10 @@ -1061,7 +1061,7 @@ Payout,SR,45,1,10 PRICE_MOVES_LOG,SR,80,G6,90,G5 CompanyOperates,AR,Josha -LaysTileAt,AR,58,J9,NW +LaysTileAt,AR,42,I8,NW CompanyRevenue,AR,440 CompanyPaysOutFull,AR,440 Payout,stefan,132,3,10 diff --git a/src/test/resources/data/test/1830_SellFullPresCert.rails b/src/test/resources/data/test/1830_SellFullPresCert.rails index c2be9f1bc47a9a1aa980c8b1e4674b95392b9ae1..d5e2a353e4a757d9d3cebcb9720dce00ef6d051f 100644 GIT binary patch literal 8719 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 W{aP0a3IB5nzouE7N>I!I;r|~JHR|O6 literal 8451 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 W4@A09Ncf*q_|?tgbb_J>2=D(h^XlaQ literal 8451 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 Qxs~VfnU>@5Z_T3hf8t=WW&i*H diff --git a/src/test/resources/data/test/1835_SellDoubleShare.rails b/src/test/resources/data/test/1835_SellDoubleShare.rails index e0f0c1799828eb089327ecaaac1d1ab9014f9cad..2cf33e39c7de0197a80b2ae7b7d9dc88db6c9214 100644 GIT binary patch literal 31358 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 From ef5c1bfc15da820ace9edef084b5cf9c3e2054cf Mon Sep 17 00:00:00 2001 From: "Dr. Martin Brumm" Date: Mon, 9 Mar 2020 22:24:13 +0100 Subject: [PATCH 40/45] Fixing the shareselling mechanismn in 1835 and adding a specific testcase. All other testcases report clear handling sofar. --- 1835_20200301_2250_Hakko.rails | Bin 0 -> 26681 bytes .../java/net/sf/rails/game/StockRound.java | 128 +++++++++--------- .../game/specific/_1835/StockRound_1835.java | 35 +---- 3 files changed, 67 insertions(+), 96 deletions(-) create mode 100644 1835_20200301_2250_Hakko.rails diff --git a/1835_20200301_2250_Hakko.rails b/1835_20200301_2250_Hakko.rails new file mode 100644 index 0000000000000000000000000000000000000000..a0128587098882851f1fd2921809b784791205ec GIT binary patch literal 26681 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 dumpThreshold) { - number += company.getPresidentsShare().getShares(); // but limit this to the pool - number = Math.min(number, poolAllowsShares); - log.debug("Dump is possible increased single shares to " + number); - } - if (number == 0) { continue; } @@ -492,25 +491,39 @@ public void setSellableShares() { if (number <= 0) { continue; } + - for (int i=1; i<=number; i++) { - // check if selling would dump the company - if (dumpIsPossible && i*shareSize >= dumpThreshold) { - // dumping requires that the total is in the possibleSharesToSell list and that shareSize == 1 Comment: MBr-2020-03-02 why ? not true anymore from now on... - // multiple shares have to be sold separately Addition: Mbrumm 2020-03-01 (no not in all cases..... 1835 for example) - if (shareSize == 1 && possibleSharesToSell.contains(i*shareSize)) { - possibleActions.add(new SellShares(company, shareSize, i, price, 1)); - } else if ( shareSize >= 2 && possibleSharesToSell.contains(i*shareSize)) { - possibleActions.add(new SellShares(company, shareSize, i, price, 1)); + for (int i=1; i<=number; i++) { //For a president certificate only the number is 2.. but it may also be 2 if the player has more than just the president certificate.. + if(checkIfSplitSaleOfPresidentAllowed()) { + // check if selling would dump the company + if (dumpIsPossible && i*shareSize >= dumpThreshold) { + // dumping requires that the total is in the possibleSharesToSell list + if (shareSize == 1 && possibleSharesToSell.contains(i*shareSize)) { + possibleActions.add(new SellShares(company, shareSize, i, price, 1)); + } + } else { + // ... no dumping: standard sell + possibleActions.add(new SellShares(company, shareSize, i, price, 0)); } - } else { - // ... no dumping: standard sell - possibleActions.add(new SellShares(company, shareSize, i, price, 0)); + } + else { + if (dumpIsPossible && i*shareSize >= dumpThreshold) { + if ( certCount.isEmpty() && number == 2) { + + possibleActions.add(new SellShares(company, 2, 1, price, 1)); + } + else { + if (((!certCount.isEmpty()) && (number ==1) ) || number >2) { + possibleActions.add(new SellShares(company, shareSize, i, price, 1)); + } + } + } + else { + possibleActions.add(new SellShares(company, shareSize, i, price, 0)); + } } } } - // if we have multiple Sharesizes the combination of Sharesizes is also a viable sell option... - // but not possible in a single sell action due to the sharesize parameter handed over to sellShares... } // Is player over the total certificate hold limit? @@ -531,9 +544,9 @@ public void setSellableShares() { } } - protected SortedSet checkForPossibleSharesToSell( - PublicCompany company, Player currentPlayer) { - return PlayerShareUtils.sharesToSell(company, currentPlayer); + protected boolean checkIfSplitSaleOfPresidentAllowed() { + // To be overwritten in Stockround Classes for games where that is not allowed e.g. 1835 + return true; } protected void setSpecialActions() { @@ -1007,7 +1020,6 @@ public boolean sellShares(SellShares action) int presidentShareNumbersToSell = 0; int numberToSell = action.getNumber(); int shareUnits = action.getShareUnits(); - int presidentExchange = action.getPresidentExchange(); // Dummy loop to allow a quick jump out while (true) { @@ -1057,32 +1069,28 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { // ... check if there is a dump required // Player is president => dump is possible - if (presidentExchange >0) { // we have found in the Original Routine that a President will change... + if (currentPlayer == company.getPresident() && shareUnits == 1) { dumpedPlayer = company.findPlayerToDump(); if (dumpedPlayer != null) { presidentShareNumbersToSell = PlayerShareUtils.presidentShareNumberToSell( company, currentPlayer, dumpedPlayer, numberToSell); - - numberToSell -= presidentShareNumbersToSell; // Besides the President Share which normal counts at least 2 shareunits. - - } - else { - errMsg = "President Exchange but no suitable target found!"; - break; + // reduce the numberToSell by the president (partial) sold certificate + numberToSell -= presidentShareNumbersToSell; } } - if (presidentExchange >0) { - //is it allowed to split a presidency Certificate on sale ? - if (checkIfPresidentCertifcateSplitSaleAllowed()) { - certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); - } - else { - certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, 1, shareUnits); - } + else { + if (currentPlayer == company.getPresident() && shareUnits == 2) { + dumpedPlayer = company.findPlayerToDump(); + if (dumpedPlayer != null) { + presidentShareNumbersToSell = PlayerShareUtils.presidentShareNumberToSell( + company, currentPlayer, dumpedPlayer, numberToSell+1); + // reduce the numberToSell by the president (partial) sold certificate + numberToSell -= presidentShareNumbersToSell; + } + } } - else { - certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); - } + + certsToSell = PlayerShareUtils.findCertificatesToSell(company, currentPlayer, numberToSell, shareUnits); // reduce numberToSell to double check for (PublicCertificate c:certsToSell) { @@ -1102,7 +1110,7 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { break; } - int numberSold = action.getNumber(); //Beware that the number sold is the number of shareunits, not the certs. + int numberSold = action.getNumber(); if (errMsg != null) { DisplayBuffer.add(this, LocalText.getText("CantSell", playerName, @@ -1162,10 +1170,8 @@ > getGameParameterAsInt(GameDef.Parm.POOL_SHARE_LIMIT)) { return true; } - - // FIXME: Rails 2.x This has to be rewritten to give the new presidency a choice which shares to swap (if he has multiple share certificates) - protected void executeShareTransferTo( PublicCompany company, + protected final void executeShareTransferTo( PublicCompany company, List certsToSell, Player dumpedPlayer, int presSharesToSell, BankPortfolio bankTo) { @@ -1180,8 +1186,7 @@ protected void executeShareTransferTo( PublicCompany company, } - // Transfer the sold certificates (but not the presidents Certificate... - + // Transfer the sold certificates Portfolio.moveAll(certsToSell, bankTo); } @@ -1437,7 +1442,7 @@ protected void finishTurn() { setAutopass (currentPlayer, false); } else { // Process a pass for a player that has set Autopass - done (null, currentPlayer.getId(), true); + done (null, currentPlayer.getId(), true); } } } @@ -1645,21 +1650,16 @@ public String getRoundName() { return "StockRound " + getStockRoundNumber(); } - public boolean isSellObligationLifted(PublicCompany company) { + public boolean isSellObligationLifted(PublicCompany company) { return sellObligationLifted != null && sellObligationLifted.contains(company); } - public void setSellObligationLifted (PublicCompany company) { + public void setSellObligationLifted (PublicCompany company) { if (sellObligationLifted == null) { - sellObligationLifted = HashSetState.create(this, "sellObligationLifted"); + sellObligationLifted = HashSetState.create(this, "sellObligationLifted"); } sellObligationLifted.add(company); } - - private boolean checkIfPresidentCertifcateSplitSaleAllowed() { - // Standard Games its true - return true; - } } diff --git a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java index b34ea11ce..ee55f1c0a 100644 --- a/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java +++ b/src/main/java/net/sf/rails/game/specific/_1835/StockRound_1835.java @@ -232,7 +232,6 @@ public boolean done(NullAction action, String playerName, */ @Override public boolean mayPlayerSellShareOfCompany(PublicCompany company) { - PortfolioModel playerPortfolio = currentPlayer.getPortfolioModel(); if (!super.mayPlayerSellShareOfCompany(company) ) { return false; @@ -244,42 +243,14 @@ public boolean mayPlayerSellShareOfCompany(PublicCompany company) { * * */ if (company.getPresident() == currentPlayer) { - SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); - // Make sure that single shares are always considered (due to possible dumping) - SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - if (certSizeElements.isEmpty()) return false; - if (certSizeElements.first()==2) { //President Share only, check if there is room in pool, President Share is 2 normal shares so space to sell must be 2 - if (PlayerShareUtils.poolAllowsShareNumbers(company) >1) return true; - } - - + if (PlayerShareUtils.poolAllowsShareNumbers(company) >1) return true; } } return true; } - - - @Override protected SortedSet checkForPossibleSharesToSell(PublicCompany company, Player currentPlayer) { - PortfolioModel playerPortfolio = currentPlayer.getPortfolioModel(); - if (currentPlayer == company.getPresident()) { - ImmutableSortedSet.Builder presidentShareSet = ImmutableSortedSet.naturalOrder(); - SortedMultiset certCount = playerPortfolio.getCertificateTypeCounts(company); - // Make sure that single shares are always considered (due to possible dumping) - SortedSet certSizeElements =Sets.newTreeSet(certCount.elementSet()); - if (certSizeElements.first()==2) { //President Share only, check if there is room in pool, President Share is 2 normal shares so space to sell must be 2 - presidentShareSet.add(2); - return presidentShareSet.build(); - } else { - return PlayerShareUtils.sharesToSell(company, currentPlayer); - } - - } - return PlayerShareUtils.sharesToSell(company, currentPlayer); - - } - - private boolean checkIfPresidentCertifcateSplitSaleAllowed() { + @Override + protected boolean checkIfSplitSaleOfPresidentAllowed() { // in 1835 its not allowed to Split the President Certificate on sale return false; } From 8e5a0ea33049167cd7a702886973f9295263ff42 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Fri, 13 Mar 2020 17:40:22 +0100 Subject: [PATCH 41/45] test case for shareselling corrected --- .../data/test/1835_Correct_Sell_Pass.rails | Bin 22309 -> 22789 bytes .../data/test/1835_ShareSelling_Test.rails | Bin 22789 -> 22789 bytes src/test/resources/data/test/1851_Late.rails | Bin 14136 -> 14709 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/test/resources/data/test/1835_Correct_Sell_Pass.rails b/src/test/resources/data/test/1835_Correct_Sell_Pass.rails index 3e5cbdba8eeee647b7f3a6a49fc70dfd20b7938b..d7c998733e9e83b009da4e4a24ae78ef7df0be8f 100644 GIT binary patch delta 2495 zcmZWrT})eL7(S%@{`Tcmcpd%X;U!j1=i6;4Ybf6=9oID zx-7=U0q?e}iJ0hx42|({XX3(@n0cd#8g(WTjofIQdaKU!o$vJgl#`t1eCK<<=Y8Ji zeZTMYy${LDACn#1zY}VP(D>XQcPbQc4=_Z%&*SsBJiRV&uhrW>=nD=8f@}77AJL9H zF*=*iFvZghLmUZsPB4T%zBuna)8|H}AI}z< zY+){w%Q1v1mxmx}g-=L}wPqqbo;#bL%W`Z!PmB{0&&M+JvHT481_4P`BfLyf@EzH; z_E!UIQl-^LYhS1#2*SWF9A#AH0g#Or&}t_Y{IQB1Fxsu~D(fw)BMAUf`{VBTdt1rvrf5&Vn6 zq2#f{>Zl3c3f2H^bc-;u(FPnRY#X&ae7MYJXYU!eRdR|1H2^<&G_V{~!nq7~Q`6E;Cmvuc`GOrN5(y823%K_NFa zl$yE}aNe^MTxilPEE0HkBM$hcP?6BU@yGYgQv%Ztg9=WA8MF$nt>eH4{)R z;qsV$zU5+tReoqOJLR?{{dSl&E7SbdtVk0%(PBxIS-B{vHtPCINc!?&>31z>6xdUg zqID9~qGB3R0iwEon5x4%A;Y5V#pK|7>jOTK8C+jFZCmeA!;yAri`;B~nn&D}A#`k~ zZK+x$HTrGvMQ1Ay6WmWw6u4Y^XzIG6fbDf*7>(JGahmS90#fS65TWIEBX$^S(7>IC zYQaitVZYm@fCrrl#&X$T3e>|bXSV|Sr?V9vbyZah!LdeZhoUrob5#U)fY&`PvXtCU z@>%X-`9Hcp5U199#2#Zm>!IcSWPxGtNfB7`W^|}Xn>+{iFayRZJJkAOA_OUU)rXZ} z7$6%~M;paWdf<~bDS{97%57Nhqu_k+bs6DFUboe2$y_%2GE6BfP9FZ0B^aC{iHGe}W!< z`U0M&(++sCRl`mX+}23A5YB7|W0E16s*nxthp=Wmz20XBZ&=!=Mh z(oad?VLS7e31v=M1& zxom$vBg`{v@L38OBHoJs zP%*}c3pb@DDnM6mmx9G=YY4UqW1A7^+_vR@9efqeh0n@)3JsVaf~tzTj4g~-w4sav zR}YL8rneW9Ai{PO#w$wUep@bZA-(Xhp(Wjcdib=;K`Kr)SYb=QAIgm(%0o8hf>DEe zhI?g&FO6YoXt_+0cbag&K$XHvrXDE-{xPL{HZOIPOdy#n*~~w!d-vt8L6n|q$Vw-qm5m0{ z_dw&i3~lfk*iGU#!B+bLxU1H{IiE`g`Pugtwa*;(>_ZL&w+=r;eT047-@&dTxbB~m zxkF7nyMPbsh)q~)+Q_A`-A)TEwj0G<90&V;2D{YzX!9oOvg|F@3nAg$dN6b zQ2a9NAw$WHBx&m9kuH2^;H$&~Rii2DCg{&cD@lkO@qzVt+{j{O2we$!%Mg|A~(Y`>;1;ngC%v8d_6c9A|p{?-b U2bS!UGiCTD%Zsp0z8Rqd06r2A+5i9m delta 75 zcmZqO#Mrutae_3rfw_W_ft9JTm7&Q-we$!%CI$##1X8|0%nHSfB@9dfL6aZa3QvAu S$v!z#hHtXG2;1bF5jp@ooe$9f diff --git a/src/test/resources/data/test/1851_Late.rails b/src/test/resources/data/test/1851_Late.rails index 1d35fe5cfa0208f26dc2238ff5c3885cfb7ca3ae..175ba72238e89285d60e9e17e3afcce4781d5da3 100644 GIT binary patch literal 14709 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 b(BHK@KNPnb`=a^Z9^8Ji-E8uor9}IG@U75J From 4b1b1c77c9033e53541d8ac3debc869a3f313fe9 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 14 Mar 2020 00:49:44 +0100 Subject: [PATCH 42/45] Fixing Bug reported by Peter De Boer: Player cant sell any shares in emergency buy and wasnt declared bancrupt. Now the player is declared bancrupt and the game endswith bancruptcy if it should end. --- src/main/java/net/sf/rails/game/ShareSellingRound.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/net/sf/rails/game/ShareSellingRound.java b/src/main/java/net/sf/rails/game/ShareSellingRound.java index b4b46010f..965a756ae 100644 --- a/src/main/java/net/sf/rails/game/ShareSellingRound.java +++ b/src/main/java/net/sf/rails/game/ShareSellingRound.java @@ -47,6 +47,12 @@ public void start(Round parentRound, Player sellingPlayer, int cashToRaise, log.debug("Forced selling, dumpOtherCompaniesAllowed = " + dumpOtherCompaniesAllowed); getRoot().getPlayerManager().setCurrentPlayer(sellingPlayer); getSellableShares(); + if (getSellableShares().isEmpty()) { + DisplayBuffer.add(this, LocalText.getText("YouMustRaiseCashButCannot", + Bank.format(this, cashToRaise))); + currentPlayer.setBankrupt(); + gameManager.registerBankruptcy(); + } } @Override From 8698f485173dece0ce786bb958d20891a11c258e Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Sat, 14 Mar 2020 14:35:38 +0100 Subject: [PATCH 43/45] 1837 relict in maintenance code --- .classpath | 12 +- .project | 19 +- .settings/org.eclipse.jdt.core.prefs | 263 +---- build.gradle | 2 +- pom.xml | 2 +- settings.gradle | 6 +- .../specific/_1837/OperatingRound_1837.java | 9 +- src/main/resources/build/version.number | 2 +- src/main/resources/version.number | 8 +- .../data/test/1837_StartRoundCompleted.rails | Bin 9331 -> 0 bytes .../data/test/1837_StartRoundCompleted.report | 931 ++++++++---------- 11 files changed, 457 insertions(+), 797 deletions(-) delete mode 100644 src/test/resources/data/test/1837_StartRoundCompleted.rails diff --git a/.classpath b/.classpath index 49b418df5..c8a5339eb 100644 --- a/.classpath +++ b/.classpath @@ -6,18 +6,18 @@ - - - - - - + + + + + + diff --git a/.project b/.project index b08b8511c..b986d8f7a 100644 --- a/.project +++ b/.project @@ -1,7 +1,7 @@ rails - @key 32303037303533312D31303030205261696C732F6672657973746566 + rails @@ -15,26 +15,9 @@ - - org.eclipse.m2e.core.maven2Builder - - - - org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature org.eclipse.buildship.core.gradleprojectnature - - - 0 - - 26 - - org.eclipse.ui.ide.multiFilter - 1.0-projectRelativePath-matches-false-false-build - - - diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 7fae57d64..05d6f2110 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,260 +1,13 @@ -eclipse.preferences.version=1 +# +#Sat Mar 14 00:30:15 CET 2020 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.compliance=1.6 org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.6 -org.eclipse.jdt.core.formatter.align_type_members_on_columns=false -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_assignment=16 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18 -org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 -org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 -org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -org.eclipse.jdt.core.formatter.blank_lines_before_field=0 -org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 -org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false -org.eclipse.jdt.core.formatter.comment.format_comments=true -org.eclipse.jdt.core.formatter.comment.format_header=false -org.eclipse.jdt.core.formatter.comment.format_html=false -org.eclipse.jdt.core.formatter.comment.format_source_code=true -org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false -org.eclipse.jdt.core.formatter.comment.indent_root_tags=false -org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert -org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert -org.eclipse.jdt.core.formatter.comment.line_length=80 -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true -org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_empty_lines=false -org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true -org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert -org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false -org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false -org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=true -org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false -org.eclipse.jdt.core.formatter.lineSplit=80 -org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 -org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false diff --git a/build.gradle b/build.gradle index fd8db78ed..2add2d7c4 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ plugins { // Addition of macAppBundle // https://github.com/crotwell/gradle-macappbundle plugins { - id "edu.sc.seis.macAppBundle" version "2.1.6" + id "edu.sc.seis.macAppBundle" version "2.3.0" } diff --git a/pom.xml b/pom.xml index a376fafba..c938f003e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ net.sf rails jar - 2.0-RC4 + 2.1beta2 rails A Java playing aid for playing 18xx based games via email or in Hotseat mode. diff --git a/settings.gradle b/settings.gradle index ac500e899..5e210db08 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,5 @@ -rootProject.name = "rails" +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'rails' diff --git a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java index 883bb426e..c96effc26 100644 --- a/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java +++ b/src/main/java/net/sf/rails/game/specific/_1837/OperatingRound_1837.java @@ -524,17 +524,14 @@ protected void finishRound() { for (PublicCompany company : gameManager.getCompaniesInRunningOrder()) { if ((company.hasStockPrice()) && (company.hasFloated())){ - if (findStartingPlayerForCoalExchange(company)) exchangedCoalCompanies.set(true); - } + } else { ((GameManager_1837) gameManager).setPlayerToStartCERound(null); } - - } else { - - super.finishRound(); + } + super.finishRound(); } diff --git a/src/main/resources/build/version.number b/src/main/resources/build/version.number index d6acf829a..cf3a1f994 100644 --- a/src/main/resources/build/version.number +++ b/src/main/resources/build/version.number @@ -1,6 +1,6 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.9 +version=2.1beta1 # the following string "@DEVELOP@" is replaced by an empty string in the release version # this is done automatically by gradle develop=@DEVELOP@ diff --git a/src/main/resources/version.number b/src/main/resources/version.number index 5b322eabc..cf3a1f994 100644 --- a/src/main/resources/version.number +++ b/src/main/resources/version.number @@ -1,8 +1,8 @@ #Changes are only valid in the build subdirectory of src/main/resources #Property file that contains version number and the develop indicator -version=2.0.RC5.9 -# the following string "" is replaced by an empty string in the release version +version=2.1beta1 +# the following string "@DEVELOP@" is replaced by an empty string in the release version # this is done automatically by gradle -develop= +develop=@DEVELOP@ # the following string "@ BUILDDATE @" is replaced by the build date -buildDate=2018-12-25 +buildDate=@BUILDDATE@ diff --git a/src/test/resources/data/test/1837_StartRoundCompleted.rails b/src/test/resources/data/test/1837_StartRoundCompleted.rails deleted file mode 100644 index 0a000c32b05116e9049198e4ec3dd3aa6c3db74a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9331 zcmeHNO>g5w7=Gh4{oH=+79k{dmlimHV7>idmuhzrw9wK}CykmQQ1$@RWSYz}_85E8 zrW`nM;Iao63C{e175@QoMMzw^z+tca2i}?1Q`;?4PK{|}$+7c#JoC=;JnuVWkDvYn z1ql;N_JU2g-zIn8kTAQnu=v)kg_T>&3v-Lh_ZC*}EiQ!tOg$p|#OB0n*^cm9_a8rd z^4oW>{AEGzBPi?>-l5$9W=;x~JMJzGzJ2=Rjfo%rery4BeK^|2Bn&OCEWeGFUe)D0 zl5u;JgzXaX3nPF2^6T@T|B(l41ID=^%?;9!A}GR`YzH)K3*PMd@4lz2x^ggz#~Iv5 zBwYL0h_aX8K+T;V`YJTDTyXlVR`7n^bs7}dlgO&X@KQ& zce)6`-G*@OmJlsYZ9H{_hX>ASL)t~x?MSlAsl!6~YLy0zaP}2#Ziv9uy~iI!{~?T0 zPF?CrtaSFFqY%BVXu7?<`v~i~-}O5|bm54<;|ouI|MaJs@O2(>gGv}Kkw7x+;&4^c zJ%T4g>jC>h!bpiV+Jtfm1!UhlMAxq)#5}ZH#HBV;gvi+C4(F@-^w>em0;>o^E&}1e zr0`WK!X2`!YPuHlwJHOKqCyGHovyYbkPQSPQFY#ed>sndGHn)N!q>PKy(aBCFn;u} zjIMnNU&DOY&nbu0`HOhW`Jp&jUKmq-kgfA7OSrtgW9N zl!MuSDk%HLn%0bAEgqDHBYeiUR->5wJ{gnQN+$gcfHR@gMgwI$CNC6p$(a?t(a2Zb zNHWc&WYQzRfHd{wk(pN^$*I+-VzLr3nR?pER?@m8k*2%ZQ|?Gkt?=z{zU2G|lj#9q zfTfDb%)E3=POYvWlWRf5WGcH}{Gq1z0MI3~m83M2hNEemS$z@_Sx*j=J%xA%dw5Aw zhbGc+G>##;zF9>E)s`A22NNE|BtG*s`i~n8mT}{GK&P2B4NV}E^{pr-Q%q(nmt2xa z)7|Vz9hynQ(G(`vT12FW5*)lr>K#g5(m)vx$-z`HmCa1*h@+H-PD|53H;GBc*@?9I zT2hepg7>Hm7nbwU3bz9j(SmjKC4~dC(W3Y9{mIqlcM@xqGx+q9`x$Gk MpnKIj_~R`93oD=JvH$=8 diff --git a/src/test/resources/data/test/1837_StartRoundCompleted.report b/src/test/resources/data/test/1837_StartRoundCompleted.report index 43a5f585f..6c3be045a 100644 --- a/src/test/resources/data/test/1837_StartRoundCompleted.report +++ b/src/test/resources/data/test/1837_StartRoundCompleted.report @@ -1,669 +1,510 @@ GameIs,1837 -PlayerIs,1,Martin -PlayerIs,2,Stefan -PlayerIs,3,Erik -PlayerIs,4,Michael -PlayerIs,5,Lonny +PlayerIs,1,Ocki +PlayerIs,2,Marcus +PlayerIs,3,Jupp +PlayerIs,4,Volker +PlayerIs,5,Martin PlayerCash,450 BankHas,12018 StartOfPhase,2 BankSizeIs,12018 StartOfStartRound,Initial Minor StartRound (Coal and Privates including Suedbahn) -HasPriority,Martin +HasPriority,Ocki +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny ALL_PASSED ITEM_PRICE_REDUCED,EKT,90 ITEM_PRICE_REDUCED,EPP,90 ITEM_PRICE_REDUCED,BB,90 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny ALL_PASSED ITEM_PRICE_REDUCED,EKT,80 ITEM_PRICE_REDUCED,EPP,80 ITEM_PRICE_REDUCED,BB,80 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny ALL_PASSED ITEM_PRICE_REDUCED,EKT,70 ITEM_PRICE_REDUCED,EPP,70 ITEM_PRICE_REDUCED,BB,70 -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -ALL_PASSED -ITEM_PRICE_REDUCED,EKT,60 -ITEM_PRICE_REDUCED,EPP,60 -ITEM_PRICE_REDUCED,BB,60 -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -ALL_PASSED -ITEM_PRICE_REDUCED,EKT,50 -ITEM_PRICE_REDUCED,EPP,50 -ITEM_PRICE_REDUCED,BB,50 -BuysItemFor,Martin,EKT,50 +PASSES,Ocki +BuysItemFor,Marcus,EKT,70 FloatsWithCash,EKT,100 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Jupp +PASSES,Volker PASSES,Martin +PASSES,Ocki +PASSES,Marcus ALL_PASSED ITEM_PRICE_REDUCED,EPP,90 ITEM_PRICE_REDUCED,BB,90 ITEM_PRICE_REDUCED,EOD,90 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Jupp +PASSES,Volker PASSES,Martin +PASSES,Ocki +PASSES,Marcus ALL_PASSED ITEM_PRICE_REDUCED,EPP,80 ITEM_PRICE_REDUCED,BB,80 ITEM_PRICE_REDUCED,EOD,80 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Jupp +PASSES,Volker PASSES,Martin +PASSES,Ocki +PASSES,Marcus ALL_PASSED ITEM_PRICE_REDUCED,EPP,70 ITEM_PRICE_REDUCED,BB,70 ITEM_PRICE_REDUCED,EOD,70 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -PASSES,Martin -ALL_PASSED -ITEM_PRICE_REDUCED,EPP,60 -ITEM_PRICE_REDUCED,BB,60 -ITEM_PRICE_REDUCED,EOD,60 -BuysItemFor,Stefan,EPP,60 +BuysItemFor,Jupp,EPP,70 FloatsWithCash,EPP,100 -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Volker PASSES,Martin -PASSES,Stefan +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp ALL_PASSED ITEM_PRICE_REDUCED,BB,90 ITEM_PRICE_REDUCED,EOD,90 ITEM_PRICE_REDUCED,RGTE,90 -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Volker PASSES,Martin -PASSES,Stefan +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp ALL_PASSED ITEM_PRICE_REDUCED,BB,80 ITEM_PRICE_REDUCED,EOD,80 ITEM_PRICE_REDUCED,RGTE,80 -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Volker PASSES,Martin -PASSES,Stefan +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp ALL_PASSED ITEM_PRICE_REDUCED,BB,70 ITEM_PRICE_REDUCED,EOD,70 ITEM_PRICE_REDUCED,RGTE,70 -PASSES,Erik -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -ALL_PASSED -ITEM_PRICE_REDUCED,BB,60 -ITEM_PRICE_REDUCED,EOD,60 -ITEM_PRICE_REDUCED,RGTE,60 -BuysItemFor,Erik,BB,60 -FloatsWithCash,BB,100 -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -ALL_PASSED -ITEM_PRICE_REDUCED,EOD,90 -ITEM_PRICE_REDUCED,RGTE,90 -ITEM_PRICE_REDUCED,SmB,140 -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -ALL_PASSED -ITEM_PRICE_REDUCED,EOD,80 -ITEM_PRICE_REDUCED,RGTE,80 -ITEM_PRICE_REDUCED,SmB,130 -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -ALL_PASSED -ITEM_PRICE_REDUCED,EOD,70 -ITEM_PRICE_REDUCED,RGTE,70 -ITEM_PRICE_REDUCED,SmB,120 -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -ALL_PASSED -ITEM_PRICE_REDUCED,EOD,60 -ITEM_PRICE_REDUCED,RGTE,60 -ITEM_PRICE_REDUCED,SmB,110 -BuysItemFor,Michael,EOD,60 -FloatsWithCash,EOD,100 -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -ALL_PASSED -ITEM_PRICE_REDUCED,RGTE,90 -ITEM_PRICE_REDUCED,SmB,140 -ITEM_PRICE_REDUCED,KwB,160 -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -ALL_PASSED -ITEM_PRICE_REDUCED,RGTE,80 -ITEM_PRICE_REDUCED,SmB,130 -ITEM_PRICE_REDUCED,KwB,150 -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -ALL_PASSED -ITEM_PRICE_REDUCED,RGTE,70 -ITEM_PRICE_REDUCED,SmB,120 -ITEM_PRICE_REDUCED,KwB,140 -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -ALL_PASSED -ITEM_PRICE_REDUCED,RGTE,60 -ITEM_PRICE_REDUCED,SmB,110 -ITEM_PRICE_REDUCED,KwB,130 -BuysItemFor,Lonny,KwB,130 -ALSO_GETS,Lonny,S2 -FloatsWithCash,S2,90 -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -ALL_PASSED -ITEM_PRICE_REDUCED,RGTE,90 -ITEM_PRICE_REDUCED,SmB,140 -ITEM_PRICE_REDUCED,MLB,90 -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -ALL_PASSED -ITEM_PRICE_REDUCED,RGTE,80 -ITEM_PRICE_REDUCED,SmB,130 -ITEM_PRICE_REDUCED,MLB,80 -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -ALL_PASSED -ITEM_PRICE_REDUCED,RGTE,70 -ITEM_PRICE_REDUCED,SmB,120 -ITEM_PRICE_REDUCED,MLB,70 -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -ALL_PASSED -ITEM_PRICE_REDUCED,RGTE,60 -ITEM_PRICE_REDUCED,SmB,110 -ITEM_PRICE_REDUCED,MLB,60 -BuysItemFor,Martin,RGTE,60 +BuysItemFor,Volker,RGTE,70 FloatsWithCash,RGTE,100 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker ALL_PASSED -ITEM_PRICE_REDUCED,SmB,140 +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,EOD,90 ITEM_PRICE_REDUCED,AB,175 -ITEM_PRICE_REDUCED,MLB,90 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker ALL_PASSED -ITEM_PRICE_REDUCED,SmB,130 +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,EOD,80 ITEM_PRICE_REDUCED,AB,165 -ITEM_PRICE_REDUCED,MLB,80 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker ALL_PASSED -ITEM_PRICE_REDUCED,SmB,120 +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,EOD,70 ITEM_PRICE_REDUCED,AB,155 -ITEM_PRICE_REDUCED,MLB,70 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -PASSES,Martin -ALL_PASSED -ITEM_PRICE_REDUCED,SmB,110 -ITEM_PRICE_REDUCED,AB,145 -ITEM_PRICE_REDUCED,MLB,60 -BuysItemFor,Stefan,AB,145 -ALSO_GETS,Stefan,S3 +BuysItemFor,Martin,AB,155 +ALSO_GETS,Martin,S3 FloatsWithCash,S3,90 -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan ALL_PASSED -ITEM_PRICE_REDUCED,SmB,140 -ITEM_PRICE_REDUCED,MLB,90 +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,EOD,90 ITEM_PRICE_REDUCED,EHS,90 -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan ALL_PASSED -ITEM_PRICE_REDUCED,SmB,130 -ITEM_PRICE_REDUCED,MLB,80 +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,EOD,80 ITEM_PRICE_REDUCED,EHS,80 -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan ALL_PASSED -ITEM_PRICE_REDUCED,SmB,120 -ITEM_PRICE_REDUCED,MLB,70 +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,EOD,70 ITEM_PRICE_REDUCED,EHS,70 -PASSES,Erik -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -ALL_PASSED -ITEM_PRICE_REDUCED,SmB,110 -ITEM_PRICE_REDUCED,MLB,60 -ITEM_PRICE_REDUCED,EHS,60 -PASSES,Erik -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -ALL_PASSED -ITEM_PRICE_REDUCED,SmB,100 -ITEM_PRICE_REDUCED,MLB,50 -ITEM_PRICE_REDUCED,EHS,50 -BuysItemFor,Erik,SmB,100 -ALSO_GETS,Erik,S1 -FloatsWithCash,S1,90 -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +BuysItemFor,Volker,EOD,70 +FloatsWithCash,EOD,100 PASSES,Martin -PASSES,Stefan -PASSES,Erik +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker ALL_PASSED -ITEM_PRICE_REDUCED,SPB,90 -ITEM_PRICE_REDUCED,MLB,90 +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,KwB,160 ITEM_PRICE_REDUCED,EHS,90 -PASSES,Michael -PASSES,Lonny PASSES,Martin -PASSES,Stefan -PASSES,Erik +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker ALL_PASSED -ITEM_PRICE_REDUCED,SPB,80 -ITEM_PRICE_REDUCED,MLB,80 +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,KwB,150 ITEM_PRICE_REDUCED,EHS,80 -PASSES,Michael -PASSES,Lonny PASSES,Martin -PASSES,Stefan -PASSES,Erik +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker ALL_PASSED -ITEM_PRICE_REDUCED,SPB,70 -ITEM_PRICE_REDUCED,MLB,70 +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,KwB,140 ITEM_PRICE_REDUCED,EHS,70 -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -ALL_PASSED -ITEM_PRICE_REDUCED,SPB,60 -ITEM_PRICE_REDUCED,MLB,60 -ITEM_PRICE_REDUCED,EHS,60 -BuysItemFor,Michael,SPB,60 -FloatsWithCash,SPB,100 -PASSES,Lonny +BuysItemFor,Martin,KwB,140 +ALSO_GETS,Martin,S2 +FloatsWithCash,S2,90 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 ITEM_PRICE_REDUCED,MLB,90 ITEM_PRICE_REDUCED,EHS,90 -ITEM_PRICE_REDUCED,ZKB,90 -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 ITEM_PRICE_REDUCED,MLB,80 ITEM_PRICE_REDUCED,EHS,80 -ITEM_PRICE_REDUCED,ZKB,80 -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael ALL_PASSED +ITEM_PRICE_REDUCED,BB,70 ITEM_PRICE_REDUCED,MLB,70 ITEM_PRICE_REDUCED,EHS,70 -ITEM_PRICE_REDUCED,ZKB,70 -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -ALL_PASSED -ITEM_PRICE_REDUCED,MLB,60 -ITEM_PRICE_REDUCED,EHS,60 -ITEM_PRICE_REDUCED,ZKB,60 -BuysItemFor,Lonny,MLB,60 +PASSES,Ocki +BuysItemFor,Marcus,MLB,70 FloatsWithCash,MLB,100 +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 ITEM_PRICE_REDUCED,EHS,90 -ITEM_PRICE_REDUCED,ZKB,90 ITEM_PRICE_REDUCED,BrB,130 +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 ITEM_PRICE_REDUCED,EHS,80 -ITEM_PRICE_REDUCED,ZKB,80 ITEM_PRICE_REDUCED,BrB,120 +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -ALL_PASSED -ITEM_PRICE_REDUCED,EHS,70 -ITEM_PRICE_REDUCED,ZKB,70 -ITEM_PRICE_REDUCED,BrB,110 -PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny -ALL_PASSED -ITEM_PRICE_REDUCED,EHS,60 -ITEM_PRICE_REDUCED,ZKB,60 -ITEM_PRICE_REDUCED,BrB,100 -BuysItemFor,Martin,BrB,100 -ALSO_GETS,Martin,S4 +BuysItemFor,Ocki,BrB,120 +ALSO_GETS,Ocki,S4 FloatsWithCash,S4,90 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin +PASSES,Ocki ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 ITEM_PRICE_REDUCED,EHS,90 -ITEM_PRICE_REDUCED,ZKB,90 ITEM_PRICE_REDUCED,WB,120 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin +PASSES,Ocki ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 ITEM_PRICE_REDUCED,EHS,80 -ITEM_PRICE_REDUCED,ZKB,80 ITEM_PRICE_REDUCED,WB,110 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin +PASSES,Ocki ALL_PASSED +ITEM_PRICE_REDUCED,BB,70 ITEM_PRICE_REDUCED,EHS,70 -ITEM_PRICE_REDUCED,ZKB,70 ITEM_PRICE_REDUCED,WB,100 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Marcus +BuysItemFor,Jupp,BB,70 +FloatsWithCash,BB,100 +PASSES,Volker PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp ALL_PASSED -ITEM_PRICE_REDUCED,EHS,60 -ITEM_PRICE_REDUCED,ZKB,60 -ITEM_PRICE_REDUCED,WB,90 -BuysItemFor,Stefan,WB,90 -PASSES,Erik -PASSES,Michael -PASSES,Lonny +ITEM_PRICE_REDUCED,SmB,140 +ITEM_PRICE_REDUCED,EHS,90 +ITEM_PRICE_REDUCED,WB,120 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +ALL_PASSED +ITEM_PRICE_REDUCED,SmB,130 +ITEM_PRICE_REDUCED,EHS,80 +ITEM_PRICE_REDUCED,WB,110 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +BuysItemFor,Jupp,SmB,130 +ALSO_GETS,Jupp,S1 +FloatsWithCash,S1,90 +PASSES,Volker PASSES,Martin -PASSES,Stefan +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp ALL_PASSED +ITEM_PRICE_REDUCED,SPB,90 ITEM_PRICE_REDUCED,EHS,90 -ITEM_PRICE_REDUCED,ZKB,90 -PASSES,Erik -PASSES,Michael -PASSES,Lonny +ITEM_PRICE_REDUCED,WB,120 +PASSES,Volker PASSES,Martin -PASSES,Stefan +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp ALL_PASSED +ITEM_PRICE_REDUCED,SPB,80 ITEM_PRICE_REDUCED,EHS,80 -ITEM_PRICE_REDUCED,ZKB,80 -PASSES,Erik -PASSES,Michael -PASSES,Lonny +ITEM_PRICE_REDUCED,WB,110 +PASSES,Volker PASSES,Martin -PASSES,Stefan +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp ALL_PASSED +ITEM_PRICE_REDUCED,SPB,70 ITEM_PRICE_REDUCED,EHS,70 -ITEM_PRICE_REDUCED,ZKB,70 -PASSES,Erik -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -ALL_PASSED -ITEM_PRICE_REDUCED,EHS,60 -ITEM_PRICE_REDUCED,ZKB,60 -BuysItemFor,Erik,EHS,60 +ITEM_PRICE_REDUCED,WB,100 +BuysItemFor,Volker,EHS,70 FloatsWithCash,EHS,100 -PASSES,Michael -PASSES,Lonny PASSES,Martin -PASSES,Stefan -PASSES,Erik +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker ALL_PASSED -ITEM_PRICE_REDUCED,ZKB,90 +ITEM_PRICE_REDUCED,SPB,90 ITEM_PRICE_REDUCED,LRB,90 -PASSES,Michael -PASSES,Lonny +ITEM_PRICE_REDUCED,WB,120 PASSES,Martin -PASSES,Stefan -PASSES,Erik +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker ALL_PASSED -ITEM_PRICE_REDUCED,ZKB,80 +ITEM_PRICE_REDUCED,SPB,80 ITEM_PRICE_REDUCED,LRB,80 -PASSES,Michael -PASSES,Lonny +ITEM_PRICE_REDUCED,WB,110 PASSES,Martin -PASSES,Stefan -PASSES,Erik +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker ALL_PASSED -ITEM_PRICE_REDUCED,ZKB,70 +ITEM_PRICE_REDUCED,SPB,70 ITEM_PRICE_REDUCED,LRB,70 -PASSES,Michael -PASSES,Lonny -PASSES,Martin -PASSES,Stefan -PASSES,Erik -ALL_PASSED -ITEM_PRICE_REDUCED,ZKB,60 -ITEM_PRICE_REDUCED,LRB,60 -BuysItemFor,Michael,ZKB,60 -FloatsWithCash,ZKB,100 -PASSES,Lonny +ITEM_PRICE_REDUCED,WB,100 +BuysItemFor,Martin,SPB,70 +FloatsWithCash,SPB,100 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael ALL_PASSED +ITEM_PRICE_REDUCED,ZKB,90 ITEM_PRICE_REDUCED,LRB,90 -ITEM_PRICE_REDUCED,TB,140 -PASSES,Lonny +ITEM_PRICE_REDUCED,WB,120 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael ALL_PASSED +ITEM_PRICE_REDUCED,ZKB,80 ITEM_PRICE_REDUCED,LRB,80 -ITEM_PRICE_REDUCED,TB,130 -PASSES,Lonny +ITEM_PRICE_REDUCED,WB,110 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +BuysItemFor,Martin,LRB,80 +FloatsWithCash,LRB,100 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael ALL_PASSED -ITEM_PRICE_REDUCED,LRB,70 -ITEM_PRICE_REDUCED,TB,120 -PASSES,Lonny +ITEM_PRICE_REDUCED,ZKB,90 +ITEM_PRICE_REDUCED,WB,120 +ITEM_PRICE_REDUCED,KB,110 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael ALL_PASSED -ITEM_PRICE_REDUCED,LRB,60 -ITEM_PRICE_REDUCED,TB,110 -BuysItemFor,Lonny,TB,110 +ITEM_PRICE_REDUCED,ZKB,80 +ITEM_PRICE_REDUCED,WB,110 +ITEM_PRICE_REDUCED,KB,100 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny ALL_PASSED -ITEM_PRICE_REDUCED,LRB,90 +ITEM_PRICE_REDUCED,ZKB,70 +ITEM_PRICE_REDUCED,WB,100 +ITEM_PRICE_REDUCED,KB,90 +PASSES,Ocki +BuysItemFor,Marcus,ZKB,70 +FloatsWithCash,ZKB,100 +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus ALL_PASSED -ITEM_PRICE_REDUCED,LRB,80 +ITEM_PRICE_REDUCED,TB,140 +ITEM_PRICE_REDUCED,WB,120 +ITEM_PRICE_REDUCED,KB,110 +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus ALL_PASSED -ITEM_PRICE_REDUCED,LRB,70 +ITEM_PRICE_REDUCED,TB,130 +ITEM_PRICE_REDUCED,WB,110 +ITEM_PRICE_REDUCED,KB,100 +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus ALL_PASSED -ITEM_PRICE_REDUCED,LRB,60 +ITEM_PRICE_REDUCED,TB,120 +ITEM_PRICE_REDUCED,WB,100 +ITEM_PRICE_REDUCED,KB,90 +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +PASSES,Ocki +PASSES,Marcus ALL_PASSED -ITEM_PRICE_REDUCED,LRB,50 +ITEM_PRICE_REDUCED,TB,110 +ITEM_PRICE_REDUCED,WB,90 +ITEM_PRICE_REDUCED,KB,80 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,TB,100 +ITEM_PRICE_REDUCED,WB,80 +ITEM_PRICE_REDUCED,KB,70 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +BuysItemFor,Marcus,WB,80 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +BuysItemFor,Ocki,KB,120 +ALSO_GETS,Ocki,S5 +SetsHomeHexS5,S5,L2 +FloatsWithCash,S5,90 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny ALL_PASSED -ITEM_PRICE_REDUCED,LRB,40 -BuysItemFor,Martin,LRB,40 -FloatsWithCash,LRB,100 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +ITEM_PRICE_REDUCED,TB,140 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin ALL_PASSED -ITEM_PRICE_REDUCED,KB,110 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +ITEM_PRICE_REDUCED,TB,130 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin ALL_PASSED -ITEM_PRICE_REDUCED,KB,100 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +ITEM_PRICE_REDUCED,TB,120 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin ALL_PASSED -ITEM_PRICE_REDUCED,KB,90 -PASSES,Stefan -PASSES,Erik -PASSES,Michael -PASSES,Lonny +ITEM_PRICE_REDUCED,TB,110 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker PASSES,Martin ALL_PASSED -ITEM_PRICE_REDUCED,KB,80 -BuysItemFor,Stefan,KB,80 -ALSO_GETS,Stefan,S5 -SetsHomeHexS5,S5,L3 -FloatsWithCash,S5,90 +ITEM_PRICE_REDUCED,TB,100 +PASSES,Ocki +BuysItemFor,Marcus,TB,100 Has,EPP,100 Has,RGTE,100 Has,EOD,100 @@ -679,10 +520,92 @@ Has,S2,90 Has,S3,90 Has,S4,90 Has,S5,90 -Has,Martin,200 -Has,Stefan,75 -Has,Erik,230 -Has,Michael,270 -Has,Lonny,150 +Has,Ocki,210 +Has,Marcus,60 +Has,Jupp,180 +Has,Volker,240 +Has,Martin,5 StartOfStartRound,Minor KuK StartRound -HasPriority,Erik +HasPriority,Jupp +BuysItemFor,Jupp,K1,90 +FloatsWithCash,K1,90 +BuysItemFor,Volker,K3,90 +FloatsWithCash,K3,90 +PASSES,Martin +BuysItemFor,Ocki,K2,120 +FloatsWithCash,K2,120 +Has,EPP,100 +Has,RGTE,100 +Has,EOD,100 +Has,EKT,100 +Has,MLB,100 +Has,ZKB,100 +Has,SPB,100 +Has,LRB,100 +Has,BB,100 +Has,EHS,100 +Has,S1,90 +Has,S2,90 +Has,S3,90 +Has,S4,90 +Has,S5,90 +Has,K1,90 +Has,K2,120 +Has,K3,90 +Has,Ocki,90 +Has,Marcus,60 +Has,Jupp,90 +Has,Volker,150 +Has,Martin,5 +StartOfStartRound,Minor Hungary StartRound +HasPriority,Marcus +PASSES,Marcus +BuysItemFor,Jupp,U2,90 +FloatsWithCash,U2,90 +BuysItemFor,Volker,PRES_CERT_NAME,U1,50,90 +FloatsWithCash,U1,180 +PASSES,Martin +BuysItemFor,Ocki,PRES_CERT_NAME,U3,50,90 +FloatsWithCash,U3,180 +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +ALL_PASSED +Has,EPP,100 +Has,RGTE,100 +Has,EOD,100 +Has,EKT,100 +Has,MLB,100 +Has,ZKB,100 +Has,SPB,100 +Has,LRB,100 +Has,BB,100 +Has,EHS,100 +Has,S1,90 +Has,S2,90 +Has,S3,90 +Has,S4,90 +Has,S5,90 +Has,K1,90 +Has,K2,120 +Has,K3,90 +Has,U1,180 +Has,U2,90 +Has,U3,180 +Has,Ocki,0 +Has,Marcus,60 +Has,Jupp,0 +Has,Volker,60 +Has,Martin,5 +START_OR,0.0 +ReceivesFor,Martin,25,KwB +ReceivesFor,Ocki,15,BrB +ReceivesFor,Marcus,30,WB +ReceivesFor,Martin,20,AB +ReceivesFor,Ocki,10,KB +ReceivesFor,Jupp,5,SmB +ReceivesFor,Marcus,35,TB + +CompanyOperates,EPP,Jupp From 3464de455313e8a7df585f97432d3a82f58308e8 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Wed, 18 Mar 2020 21:42:32 +0100 Subject: [PATCH 44/45] Fix for Issue #90 --- src/main/java/net/sf/rails/game/StartRound_1830.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/sf/rails/game/StartRound_1830.java b/src/main/java/net/sf/rails/game/StartRound_1830.java index c2a2c6ab5..5c43fb3ee 100644 --- a/src/main/java/net/sf/rails/game/StartRound_1830.java +++ b/src/main/java/net/sf/rails/game/StartRound_1830.java @@ -100,8 +100,8 @@ public boolean setPossibleActions() { playerManager.setCurrentPlayer(item.getBidder()); item.setStatus(StartItem.NEEDS_SHARE_PRICE); BuyStartItem newItem = - new BuyStartItem(item, item.getBasePrice(), - true, true); + new BuyStartItem(item, item.getBid(), + false, true); possibleActions.add(newItem); break; // No more actions possible! } else { From ebf5ed63ef3cc45569214709ac075537f3c0a779 Mon Sep 17 00:00:00 2001 From: Martin Brumm Date: Wed, 18 Mar 2020 21:45:31 +0100 Subject: [PATCH 45/45] Recreated Test game reports, all games pass ... --- .../bugs/1835_changePresidentAtStart.report | 16 +- src/test/resources/data/real/1830_B.report | 438 +++++++++++++ .../data/test/1835_Correct_Sell_Pass.report | 2 +- .../data/test/1835_SellDoubleShare.report | 1 + .../data/test/1835_ShareSelling_Test.report | 2 +- .../data/test/1837_StartroundCompleted.report | 611 ++++++++++++++++++ 6 files changed, 1060 insertions(+), 10 deletions(-) create mode 100644 src/test/resources/data/real/1830_B.report create mode 100644 src/test/resources/data/test/1837_StartroundCompleted.report diff --git a/src/test/resources/data/bugs/1835_changePresidentAtStart.report b/src/test/resources/data/bugs/1835_changePresidentAtStart.report index 4c83fc832..af60a86e3 100644 --- a/src/test/resources/data/bugs/1835_changePresidentAtStart.report +++ b/src/test/resources/data/bugs/1835_changePresidentAtStart.report @@ -1,5 +1,5 @@ GameIs,1835 -PlayerIs,1,Klaus-Jürgen +PlayerIs,1,Klaus-Jürgen PlayerIs,2,Jupp PlayerIs,3,Sven K. PlayerIs,4,Volker S. @@ -15,9 +15,9 @@ BuysItemFor,Sven K.,M2,170 FloatsWithCash,M2,170 BuysItemFor,Jupp,M5,80 FloatsWithCash,M5,80 -BuysItemFor,Klaus-Jürgen,M1,80 +BuysItemFor,Klaus-Jürgen,M1,80 FloatsWithCash,M1,80 -BuysItemFor,Klaus-Jürgen,M6,80 +BuysItemFor,Klaus-Jürgen,M6,80 FloatsWithCash,M6,80 BuysItemFor,Jupp,LD,190 ALSO_GETS,Jupp,PRES_CERT_NAME,SX,20 @@ -25,12 +25,12 @@ BuysItemFor,Sven K.,M4,160 FloatsWithCash,M4,160 BuysItemFor,Volker S.,NF,100 ALSO_GETS,Volker S.,CERT_NAME,BY,10 -BuysItemFor,Klaus-Jürgen,BB,130 +BuysItemFor,Klaus-Jürgen,BB,130 BuysItemFor,Jupp,HB,160 PASSES,Sven K. BuysItemFor,Volker S.,OBB,120 ALSO_GETS,Volker S.,CERT_NAME,BY,10 -BuysItemFor,Klaus-Jürgen,PRES_CERT_NAME,BY,20,184 +BuysItemFor,Klaus-Jürgen,PRES_CERT_NAME,BY,20,184 CannotBuyAnything,Jupp CannotBuyAnything,Sven K. BuysItemFor,Volker S.,PfB,150 @@ -44,11 +44,11 @@ Has,M4,160 Has,M5,80 Has,M6,80 Has,BY,460 -Has,Klaus-Jürgen,1 +Has,Klaus-Jürgen,1 Has,Jupp,45 Has,Sven K.,145 Has,Volker S.,25 StartStockRound,1 -HasPriority,Klaus-Jürgen -PASSES,Klaus-Jürgen +HasPriority,Klaus-Jürgen +PASSES,Klaus-Jürgen PASSES,Jupp diff --git a/src/test/resources/data/real/1830_B.report b/src/test/resources/data/real/1830_B.report new file mode 100644 index 000000000..0329f90c8 --- /dev/null +++ b/src/test/resources/data/real/1830_B.report @@ -0,0 +1,438 @@ +GameIs,1830 +PlayerIs,1,Marcus +PlayerIs,2,Si +PlayerIs,3,Ed +PlayerIs,4,Phil +PlayerIs,5,Chris +PlayerCash,480 +BankHas,17600 +StartOfPhase,2 +BankSizeIs,17600 +StartOfInitialRound +HasPriority,Marcus +BID_ITEM_LOG,Marcus,115,M&H,365 +BID_ITEM_LOG,Si,165,C&A,315 +BID_ITEM_LOG,Ed,170,C&A,310 +BID_ITEM_LOG,Phil,75,D&H,405 +BID_ITEM_LOG,Chris,45,C&StL,435 +BuysItemFor,Marcus,SVNRR,20 +BuysItemFor,Chris,C&StL,45 +BuysItemFor,Phil,D&H,75 +BuysItemFor,Marcus,M&H,115 +TO_AUCTION,C&A +BID_ITEM_LOG,Si,175,C&A,305 +BID_ITEM_LOG,Ed,180,C&A,300 +BID_ITEM_LOG,Si,185,C&A,295 +BID_ITEM_LOG,Ed,190,C&A,290 +BID_ITEM_LOG,Si,195,C&A,285 +BID_ITEM_LOG,Ed,200,C&A,280 +BID_ITEM_LOG,Si,210,C&A,270 +PASSES,Ed +BuysItemFor,Si,C&A,210 +ALSO_GETS,Si,CERT_NAME,RDG,10 +PASSES,Si +PASSES,Ed +PASSES,Phil +PASSES,Chris +PASSES,Marcus +ALL_PASSED +Has,Marcus,345 +Has,Si,270 +Has,Ed,480 +Has,Phil,405 +Has,Chris,435 +START_OR,0.0 +ReceivesFor,Marcus,5,SVNRR +ReceivesFor,Chris,10,C&StL +ReceivesFor,Phil,15,D&H +ReceivesFor,Marcus,20,M&H +ReceivesFor,Si,25,C&A +ShortORExecuted +Has,Marcus,370 +Has,Si,295 +Has,Ed,480 +Has,Phil,420 +Has,Chris,445 +StartOfInitialRound +HasPriority,Si +PASSES,Si +BuysItemFor,Ed,B&O,220 +ALSO_GETS,Ed,PRES_CERT_NAME,B&O,20 +Has,Marcus,370 +Has,Si,295 +Has,Ed,260 +Has,Phil,420 +Has,Chris,445 +StartStockRound,1 +HasPriority,Phil +START_COMPANY_LOG,Phil,NYC,67,134,2,20,BANK +START_COMPANY_LOG,Chris,N&W,71,142,2,20,BANK +START_COMPANY_LOG,Marcus,NYNH,71,142,2,20,BANK +BUY_SHARE_LOG,Si,10,NYC,IPO,67 +BUY_SHARE_LOG,Ed,10,NYNH,IPO,71 +BUY_SHARE_LOG,Phil,10,NYC,IPO,67 +BUY_SHARE_LOG,Chris,10,N&W,IPO,71 +BUY_SHARE_LOG,Marcus,10,NYNH,IPO,71 +BUY_SHARE_LOG,Si,10,NYC,IPO,67 +BUY_SHARE_LOG,Ed,10,NYNH,IPO,71 +BUY_SHARE_LOG,Phil,10,NYC,IPO,67 +FloatsWithCash,NYC,670 +BUY_SHARE_LOG,Chris,10,N&W,IPO,71 +BUY_SHARE_LOG,Marcus,10,NYNH,IPO,71 +FloatsWithCash,NYNH,710 +BUY_SHARE_LOG,Si,10,NYC,IPO,67 +Autopasses,Ed +BUY_SHARE_LOG,Phil,10,NYC,IPO,67 +BUY_SHARE_LOG,Chris,10,N&W,IPO,71 +BUY_SHARE_LOG,Marcus,10,NYNH,IPO,71 +BUY_SHARE_LOG,Si,10,NYC,IPO,67 +BUY_SHARE_LOG,Ed,10,NYC,IPO,67 +Autopasses,Phil +BUY_SHARE_LOG,Chris,10,N&W,IPO,71 +FloatsWithCash,N&W,710 +PASSES,Marcus +PASSES,Si +PASSES,Ed +Autopasses,Phil +PASSES,Chris + +END_SR,1 +PRICE_MOVES_LOG,NYC,67,G6,71,G5 +SoldOut,NYC,67,G6,71,G5 +Has,N&W,710 +Has,NYC,670 +Has,NYNH,710 +Has,Marcus,15 +Has,Si,27 +Has,Ed,51 +Has,Phil,85 +Has,Chris,19 +START_OR,1.1 +ReceivesFor,Marcus,5,SVNRR +ReceivesFor,Chris,10,C&StL +ReceivesFor,Phil,15,D&H +ReceivesFor,Marcus,20,M&H +ReceivesFor,Si,25,C&A +ReceivesFor,Ed,30,B&O + +CompanyOperates,N&W,Chris +LaysTileAt,N&W,9,L14,W +CompanyDoesNotPayDividend,N&W +PRICE_MOVES_LOG,N&W,71,G5,67,F5 +BuysTrain,N&W,2,IPO,80 +FirstTrainBought,2 + +CompanyOperates,NYNH,Marcus +LaysTileAt,NYNH,57,F20,SW +CompanyDoesNotPayDividend,NYNH +PRICE_MOVES_LOG,NYNH,71,G5,67,F5 +BuysTrain,NYNH,2,IPO,80 + +CompanyOperates,NYC,Phil +LaysTileAt,NYC,57,E19,NE +CompanyDoesNotPayDividend,NYC +PRICE_MOVES_LOG,NYC,71,G5,67,F5 +BuysTrain,NYC,2,IPO,80 +BuysTrain,NYC,2,IPO,80 +BuysTrain,NYC,2,IPO,80 +BuysTrain,NYC,2,IPO,80 +All 2-trains are sold out, 3-trains now available + +EndOfOperatingRound,1.1 +ORWorthIncrease,Marcus,1.1,5 +ORWorthIncrease,Si,1.1,9 +ORWorthIncrease,Ed,1.1,18 +ORWorthIncrease,Phil,1.1,-5 +ORWorthIncrease,Chris,1.1,-14 +Has,N&W,630 +Has,NYC,350 +Has,NYNH,630 +Has,Marcus,40 +Has,Si,52 +Has,Ed,81 +Has,Phil,100 +Has,Chris,29 +StartStockRound,2 +HasPriority,Marcus +PASSES,Marcus +PASSES,Si +BUY_SHARE_LOG,Ed,10,NYNH,IPO,71 +BUY_SHARE_LOG,Phil,10,N&W,IPO,71 +PASSES,Chris +PASSES,Marcus +PASSES,Si +PASSES,Ed +PASSES,Phil + +END_SR,2 +PRICE_MOVES_LOG,NYC,67,F5,71,F4 +SoldOut,NYC,67,F5,71,F4 +Has,N&W,630 +Has,NYC,350 +Has,NYNH,630 +Has,Marcus,40 +Has,Si,52 +Has,Ed,10 +Has,Phil,29 +Has,Chris,29 +START_OR,2.1 +ReceivesFor,Marcus,5,SVNRR +ReceivesFor,Chris,10,C&StL +ReceivesFor,Phil,15,D&H +ReceivesFor,Marcus,20,M&H +ReceivesFor,Si,25,C&A +ReceivesFor,Ed,30,B&O + +CompanyOperates,NYC,Phil +LaysTileAt,NYC,8,F18,W +CompanyRevenue,NYC,0 +CompanyDoesNotPayDividend,NYC +PRICE_MOVES_LOG,NYC,71,F4,66,E4 + +CompanyOperates,N&W,Chris +LaysTileAt,N&W,9,L12,W +CorrectionModeActivate,Chris,CORRECT_CASH +CorrectCashSubstractMoney,N&W,140 +CorrectionModeDeactivate,Chris,CORRECT_CASH +CompanyRevenue,N&W,70 +CompanyPaysOutFull,N&W,70 +Payout,Phil,7,1,10 +Payout,Chris,42,6,10 +PRICE_MOVES_LOG,N&W,67,F5,71,G5 + +CompanyOperates,NYNH,Marcus +LaysTileAtFor,NYNH,9,E21,SW,120 +CompanyRevenue,NYNH,60 +CompanyPaysOutFull,NYNH,60 +Payout,Ed,18,3,10 +Payout,Marcus,30,5,10 +PRICE_MOVES_LOG,NYNH,67,F5,71,G5 +BuysTrain,NYNH,3,IPO,180 +FirstTrainBought,3 +StartOfPhase,3 + +EndOfOperatingRound,2.1 +ORWorthIncrease,Marcus,2.1,75 +ORWorthIncrease,Si,2.1,5 +ORWorthIncrease,Ed,2.1,55 +ORWorthIncrease,Phil,2.1,1 +ORWorthIncrease,Chris,2.1,76 +Has,N&W,490 +Has,NYC,350 +Has,NYNH,330 +Has,Marcus,95 +Has,Si,77 +Has,Ed,58 +Has,Phil,51 +Has,Chris,81 +StartStockRound,3 +HasPriority,Chris +BUY_SHARE_LOG,Chris,10,NYNH,IPO,71 +BUY_SHARE_LOG,Marcus,10,NYNH,IPO,71 +BUY_SHARE_LOG,Si,10,N&W,IPO,71 +PASSES,Ed +PASSES,Phil +PASSES,Chris +PASSES,Marcus +PASSES,Si + +END_SR,3 +PRICE_MOVES_LOG,NYNH,71,G5,76,G4 +SoldOut,NYNH,71,G5,76,G4 +PRICE_MOVES_LOG,NYC,66,E4,70,E3 +SoldOut,NYC,66,E4,70,E3 +Has,N&W,490 +Has,NYC,350 +Has,NYNH,330 +Has,Marcus,24 +Has,Si,6 +Has,Ed,58 +Has,Phil,51 +Has,Chris,10 +START_OR,3.1 +ReceivesFor,Marcus,5,SVNRR +ReceivesFor,Chris,10,C&StL +ReceivesFor,Phil,15,D&H +ReceivesFor,Marcus,20,M&H +ReceivesFor,Si,25,C&A +ReceivesFor,Ed,30,B&O + +CompanyOperates,NYNH,Marcus +LaysTileAtFor,NYNH,54,G19,SW,80 +CompanyRevenue,NYNH,80 +CompanyPaysOutFull,NYNH,80 +Payout,Ed,24,3,10 +Payout,Marcus,48,6,10 +Payout,Chris,8,1,10 +PRICE_MOVES_LOG,NYNH,76,G4,82,H4 + +CompanyOperates,N&W,Chris +LaysTileAtFor,N&W,9,K15,NW,40 +CompanyRevenue,N&W,70 +CompanyPaysOutFull,N&W,70 +Payout,Chris,42,6,10 +Payout,Phil,7,1,10 +Payout,Si,7,1,10 +PRICE_MOVES_LOG,N&W,71,G5,76,H5 +BuysTrain,N&W,3,IPO,180 + +CompanyOperates,NYC,Phil +BuysPrivateFromFor,NYC,D&H,Phil,140 +LaysTileAtFor,NYC,57,F16,W,120 +LAYS_FREE_TOKEN_ON,NYC,F16 +CompanyRevenue,NYC,40 +CompanyPaysOutFull,NYC,40 +Payout,Ed,4,1,10 +Payout,Phil,20,5,10 +Payout,Si,16,4,10 +PRICE_MOVES_LOG,NYC,70,E3,76,F3 + +EndOfOperatingRound,3.1 +ORWorthIncrease,Marcus,3.1,109 +ORWorthIncrease,Si,3.1,77 +ORWorthIncrease,Ed,3.1,82 +ORWorthIncrease,Phil,3.1,147 +ORWorthIncrease,Chris,3.1,96 +Has,N&W,270 +Has,NYC,90 +Has,NYNH,250 +Has,Marcus,97 +Has,Si,54 +Has,Ed,116 +Has,Phil,233 +Has,Chris,70 +START_OR,3.2 +ReceivesFor,Marcus,5,SVNRR +ReceivesFor,Chris,10,C&StL +ReceivesFor,NYC,15,D&H +ReceivesFor,Marcus,20,M&H +ReceivesFor,Si,25,C&A +ReceivesFor,Ed,30,B&O + +CompanyOperates,NYNH,Marcus +LaysTileAt,NYNH,25,F18,W +CompanyRevenue,NYNH,160 +CompanyPaysOutFull,NYNH,160 +Payout,Ed,48,3,10 +Payout,Marcus,96,6,10 +Payout,Chris,16,1,10 +PRICE_MOVES_LOG,NYNH,82,H4,90,I4 + +CompanyOperates,N&W,Chris +LaysTileAtFor,N&W,57,J14,NW,80 +CompanyRevenue,N&W,120 +CompanyPaysOutFull,N&W,120 +Payout,Phil,12,1,10 +Payout,Chris,72,6,10 +Payout,Si,12,1,10 +PRICE_MOVES_LOG,N&W,76,H5,82,I5 +BuysPrivateFromFor,N&W,C&StL,Chris,20 + +CompanyOperates,NYC,Phil +LaysTileAt,NYC,14,F16,W +CompanyRevenue,NYC,90 +CompanyPaysOutFull,NYC,90 +Payout,Ed,9,1,10 +Payout,Phil,45,5,10 +Payout,Si,36,4,10 +PRICE_MOVES_LOG,NYC,76,F3,82,G3 + +EndOfOperatingRound,3.2 +ORWorthIncrease,Marcus,3.2,169 +ORWorthIncrease,Si,3.2,103 +ORWorthIncrease,Ed,3.2,117 +ORWorthIncrease,Phil,3.2,93 +ORWorthIncrease,Chris,3.2,122 +Has,N&W,170 +Has,NYC,105 +Has,NYNH,250 +Has,Marcus,218 +Has,Si,127 +Has,Ed,203 +Has,Phil,290 +Has,Chris,188 +StartStockRound,4 +HasPriority,Ed +SELL_SHARE_LOG,Ed,10,NYC,82 +PRICE_MOVES_LOG,NYC,82,G3,76,G4 +SELL_SHARES_LOG,Ed,3,10,30,NYNH,270 +PRICE_MOVES_LOG,NYNH,90,I4,70,I7 +START_COMPANY_LOG,Ed,RDG,100,300,3,30,BANK +SELL_SHARES_LOG,Phil,4,10,40,NYC,304 +PRICE_MOVES_LOG,NYC,76,G4,67,G8 +IS_NOW_PRES_OF,Si,NYC +START_COMPANY_LOG,Phil,C&O,90,180,2,20,BANK +BUY_SHARE_LOG,Chris,10,NYNH,Pool,70 +START_COMPANY_LOG,Marcus,Erie,90,180,2,20,BANK +SwapsPrivateForCertificate,Marcus,M&H,10,NYC +PrivateCloses,M&H +BUY_SHARE_LOG,Si,10,N&W,IPO,71 +BUY_SHARE_LOG,Ed,10,RDG,IPO,100 +BUY_SHARE_LOG,Phil,10,C&O,IPO,90 +BUY_SHARE_LOG,Chris,10,NYNH,Pool,70 +Autopasses,Marcus +PASSES,Si +BUY_SHARE_LOG,Ed,10,RDG,IPO,100 +FloatsWithCash,RDG,1000 +BUY_SHARE_LOG,Phil,10,C&O,IPO,90 +Autopasses,Chris +Autopasses,Marcus +PASSES,Si +PASSES,Ed +BUY_SHARE_LOG,Phil,10,C&O,IPO,90 +Autopasses,Chris +Autopasses,Marcus +PASSES,Si +PASSES,Ed +BUY_SHARE_LOG,Phil,10,C&O,IPO,90 +FloatsWithCash,C&O,900 +Autopasses,Chris +Autopasses,Marcus +PASSES,Si +PASSES,Ed +PASSES,Phil + +END_SR,4 +Has,C&O,900 +Has,N&W,170 +Has,NYC,105 +Has,NYNH,250 +Has,RDG,1000 +Has,Marcus,38 +Has,Si,56 +Has,Ed,55 +Has,Phil,54 +Has,Chris,48 +START_OR,4.1 +ReceivesFor,Marcus,5,SVNRR +ReceivesFor,N&W,10,C&StL +ReceivesFor,NYC,15,D&H +ReceivesFor,Si,25,C&A +ReceivesFor,Ed,30,B&O + +CompanyOperates,RDG,Ed +LaysTileAt,RDG,57,H16,W +CompanyDoesNotPayDividend,RDG +PRICE_MOVES_LOG,RDG,100,G1,90,F1 +BuysTrain,RDG,3,IPO,180 + +CompanyOperates,C&O,Phil +LaysTileAt,C&O,57,K13,SW +CompanyDoesNotPayDividend,C&O +PRICE_MOVES_LOG,C&O,90,G2,82,F2 +BuysTrain,C&O,3,IPO,180 +BuysTrain,C&O,3,IPO,180 +All 3-trains are sold out, 4-trains now available +BuysTrain,C&O,4,IPO,300 +FirstTrainBought,4 +StartOfPhase,4 +TrainsObsolete.ALL,2 +CompanyDiscardsTrain,NYC,2,ScrapHeap + +CompanyOperates,N&W,Chris +BuysRight,N&W,Coalfields,140 +LaysTileAt,N&W,8,M11,NW +CompanyRevenue,N&W,150 +CompanyWithholds,N&W,150 +PRICE_MOVES_LOG,N&W,82,I5,76,H5 +TrainsObsoleteRusted,2,N&W diff --git a/src/test/resources/data/test/1835_Correct_Sell_Pass.report b/src/test/resources/data/test/1835_Correct_Sell_Pass.report index 827a33322..bdea028a0 100644 --- a/src/test/resources/data/test/1835_Correct_Sell_Pass.report +++ b/src/test/resources/data/test/1835_Correct_Sell_Pass.report @@ -1038,7 +1038,7 @@ StartStockRound,5 HasPriority,Lonny PASSES,Lonny PASSES,Stefan -SELL_SHARES_LOG,Ronnie,2,5,10,PR,154 +SELL_SHARE_LOG,Ronnie,10,PR,154 PRICE_MOVES_LOG,PR,154,I4,140,I5 IS_NOW_PRES_OF,Stefan,PR PASSES,Ronnie diff --git a/src/test/resources/data/test/1835_SellDoubleShare.report b/src/test/resources/data/test/1835_SellDoubleShare.report index 2774c2df6..f94451a44 100644 --- a/src/test/resources/data/test/1835_SellDoubleShare.report +++ b/src/test/resources/data/test/1835_SellDoubleShare.report @@ -1641,3 +1641,4 @@ HasPriority,m2 PASSES,m2 SELL_SHARE_LOG,m3,20,HE,200 PRICE_MOVES_LOG,HE,100,D3,94,D4 +PASSES,m3 diff --git a/src/test/resources/data/test/1835_ShareSelling_Test.report b/src/test/resources/data/test/1835_ShareSelling_Test.report index 827a33322..bdea028a0 100644 --- a/src/test/resources/data/test/1835_ShareSelling_Test.report +++ b/src/test/resources/data/test/1835_ShareSelling_Test.report @@ -1038,7 +1038,7 @@ StartStockRound,5 HasPriority,Lonny PASSES,Lonny PASSES,Stefan -SELL_SHARES_LOG,Ronnie,2,5,10,PR,154 +SELL_SHARE_LOG,Ronnie,10,PR,154 PRICE_MOVES_LOG,PR,154,I4,140,I5 IS_NOW_PRES_OF,Stefan,PR PASSES,Ronnie diff --git a/src/test/resources/data/test/1837_StartroundCompleted.report b/src/test/resources/data/test/1837_StartroundCompleted.report new file mode 100644 index 000000000..6c3be045a --- /dev/null +++ b/src/test/resources/data/test/1837_StartroundCompleted.report @@ -0,0 +1,611 @@ +GameIs,1837 +PlayerIs,1,Ocki +PlayerIs,2,Marcus +PlayerIs,3,Jupp +PlayerIs,4,Volker +PlayerIs,5,Martin +PlayerCash,450 +BankHas,12018 +StartOfPhase,2 +BankSizeIs,12018 +StartOfStartRound,Initial Minor StartRound (Coal and Privates including Suedbahn) +HasPriority,Ocki +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,EKT,90 +ITEM_PRICE_REDUCED,EPP,90 +ITEM_PRICE_REDUCED,BB,90 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,EKT,80 +ITEM_PRICE_REDUCED,EPP,80 +ITEM_PRICE_REDUCED,BB,80 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,EKT,70 +ITEM_PRICE_REDUCED,EPP,70 +ITEM_PRICE_REDUCED,BB,70 +PASSES,Ocki +BuysItemFor,Marcus,EKT,70 +FloatsWithCash,EKT,100 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,EPP,90 +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,EOD,90 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,EPP,80 +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,EOD,80 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,EPP,70 +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,EOD,70 +BuysItemFor,Jupp,EPP,70 +FloatsWithCash,EPP,100 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,EOD,90 +ITEM_PRICE_REDUCED,RGTE,90 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,EOD,80 +ITEM_PRICE_REDUCED,RGTE,80 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +ALL_PASSED +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,EOD,70 +ITEM_PRICE_REDUCED,RGTE,70 +BuysItemFor,Volker,RGTE,70 +FloatsWithCash,RGTE,100 +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,EOD,90 +ITEM_PRICE_REDUCED,AB,175 +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,EOD,80 +ITEM_PRICE_REDUCED,AB,165 +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +ALL_PASSED +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,EOD,70 +ITEM_PRICE_REDUCED,AB,155 +BuysItemFor,Martin,AB,155 +ALSO_GETS,Martin,S3 +FloatsWithCash,S3,90 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,EOD,90 +ITEM_PRICE_REDUCED,EHS,90 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,EOD,80 +ITEM_PRICE_REDUCED,EHS,80 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,EOD,70 +ITEM_PRICE_REDUCED,EHS,70 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +BuysItemFor,Volker,EOD,70 +FloatsWithCash,EOD,100 +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,KwB,160 +ITEM_PRICE_REDUCED,EHS,90 +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,KwB,150 +ITEM_PRICE_REDUCED,EHS,80 +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +ALL_PASSED +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,KwB,140 +ITEM_PRICE_REDUCED,EHS,70 +BuysItemFor,Martin,KwB,140 +ALSO_GETS,Martin,S2 +FloatsWithCash,S2,90 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,MLB,90 +ITEM_PRICE_REDUCED,EHS,90 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,MLB,80 +ITEM_PRICE_REDUCED,EHS,80 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,MLB,70 +ITEM_PRICE_REDUCED,EHS,70 +PASSES,Ocki +BuysItemFor,Marcus,MLB,70 +FloatsWithCash,MLB,100 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,EHS,90 +ITEM_PRICE_REDUCED,BrB,130 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,EHS,80 +ITEM_PRICE_REDUCED,BrB,120 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +BuysItemFor,Ocki,BrB,120 +ALSO_GETS,Ocki,S4 +FloatsWithCash,S4,90 +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +ALL_PASSED +ITEM_PRICE_REDUCED,BB,90 +ITEM_PRICE_REDUCED,EHS,90 +ITEM_PRICE_REDUCED,WB,120 +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +ALL_PASSED +ITEM_PRICE_REDUCED,BB,80 +ITEM_PRICE_REDUCED,EHS,80 +ITEM_PRICE_REDUCED,WB,110 +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +ALL_PASSED +ITEM_PRICE_REDUCED,BB,70 +ITEM_PRICE_REDUCED,EHS,70 +ITEM_PRICE_REDUCED,WB,100 +PASSES,Marcus +BuysItemFor,Jupp,BB,70 +FloatsWithCash,BB,100 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +ALL_PASSED +ITEM_PRICE_REDUCED,SmB,140 +ITEM_PRICE_REDUCED,EHS,90 +ITEM_PRICE_REDUCED,WB,120 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +ALL_PASSED +ITEM_PRICE_REDUCED,SmB,130 +ITEM_PRICE_REDUCED,EHS,80 +ITEM_PRICE_REDUCED,WB,110 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +BuysItemFor,Jupp,SmB,130 +ALSO_GETS,Jupp,S1 +FloatsWithCash,S1,90 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +ALL_PASSED +ITEM_PRICE_REDUCED,SPB,90 +ITEM_PRICE_REDUCED,EHS,90 +ITEM_PRICE_REDUCED,WB,120 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +ALL_PASSED +ITEM_PRICE_REDUCED,SPB,80 +ITEM_PRICE_REDUCED,EHS,80 +ITEM_PRICE_REDUCED,WB,110 +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +ALL_PASSED +ITEM_PRICE_REDUCED,SPB,70 +ITEM_PRICE_REDUCED,EHS,70 +ITEM_PRICE_REDUCED,WB,100 +BuysItemFor,Volker,EHS,70 +FloatsWithCash,EHS,100 +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +ALL_PASSED +ITEM_PRICE_REDUCED,SPB,90 +ITEM_PRICE_REDUCED,LRB,90 +ITEM_PRICE_REDUCED,WB,120 +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +ALL_PASSED +ITEM_PRICE_REDUCED,SPB,80 +ITEM_PRICE_REDUCED,LRB,80 +ITEM_PRICE_REDUCED,WB,110 +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +ALL_PASSED +ITEM_PRICE_REDUCED,SPB,70 +ITEM_PRICE_REDUCED,LRB,70 +ITEM_PRICE_REDUCED,WB,100 +BuysItemFor,Martin,SPB,70 +FloatsWithCash,SPB,100 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,ZKB,90 +ITEM_PRICE_REDUCED,LRB,90 +ITEM_PRICE_REDUCED,WB,120 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,ZKB,80 +ITEM_PRICE_REDUCED,LRB,80 +ITEM_PRICE_REDUCED,WB,110 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +BuysItemFor,Martin,LRB,80 +FloatsWithCash,LRB,100 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,ZKB,90 +ITEM_PRICE_REDUCED,WB,120 +ITEM_PRICE_REDUCED,KB,110 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,ZKB,80 +ITEM_PRICE_REDUCED,WB,110 +ITEM_PRICE_REDUCED,KB,100 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,ZKB,70 +ITEM_PRICE_REDUCED,WB,100 +ITEM_PRICE_REDUCED,KB,90 +PASSES,Ocki +BuysItemFor,Marcus,ZKB,70 +FloatsWithCash,ZKB,100 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,TB,140 +ITEM_PRICE_REDUCED,WB,120 +ITEM_PRICE_REDUCED,KB,110 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,TB,130 +ITEM_PRICE_REDUCED,WB,110 +ITEM_PRICE_REDUCED,KB,100 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,TB,120 +ITEM_PRICE_REDUCED,WB,100 +ITEM_PRICE_REDUCED,KB,90 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,TB,110 +ITEM_PRICE_REDUCED,WB,90 +ITEM_PRICE_REDUCED,KB,80 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +PASSES,Marcus +ALL_PASSED +ITEM_PRICE_REDUCED,TB,100 +ITEM_PRICE_REDUCED,WB,80 +ITEM_PRICE_REDUCED,KB,70 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +BuysItemFor,Marcus,WB,80 +PASSES,Jupp +PASSES,Volker +PASSES,Martin +BuysItemFor,Ocki,KB,120 +ALSO_GETS,Ocki,S5 +SetsHomeHexS5,S5,L2 +FloatsWithCash,S5,90 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,TB,140 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,TB,130 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,TB,120 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,TB,110 +PASSES,Ocki +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +ALL_PASSED +ITEM_PRICE_REDUCED,TB,100 +PASSES,Ocki +BuysItemFor,Marcus,TB,100 +Has,EPP,100 +Has,RGTE,100 +Has,EOD,100 +Has,EKT,100 +Has,MLB,100 +Has,ZKB,100 +Has,SPB,100 +Has,LRB,100 +Has,BB,100 +Has,EHS,100 +Has,S1,90 +Has,S2,90 +Has,S3,90 +Has,S4,90 +Has,S5,90 +Has,Ocki,210 +Has,Marcus,60 +Has,Jupp,180 +Has,Volker,240 +Has,Martin,5 +StartOfStartRound,Minor KuK StartRound +HasPriority,Jupp +BuysItemFor,Jupp,K1,90 +FloatsWithCash,K1,90 +BuysItemFor,Volker,K3,90 +FloatsWithCash,K3,90 +PASSES,Martin +BuysItemFor,Ocki,K2,120 +FloatsWithCash,K2,120 +Has,EPP,100 +Has,RGTE,100 +Has,EOD,100 +Has,EKT,100 +Has,MLB,100 +Has,ZKB,100 +Has,SPB,100 +Has,LRB,100 +Has,BB,100 +Has,EHS,100 +Has,S1,90 +Has,S2,90 +Has,S3,90 +Has,S4,90 +Has,S5,90 +Has,K1,90 +Has,K2,120 +Has,K3,90 +Has,Ocki,90 +Has,Marcus,60 +Has,Jupp,90 +Has,Volker,150 +Has,Martin,5 +StartOfStartRound,Minor Hungary StartRound +HasPriority,Marcus +PASSES,Marcus +BuysItemFor,Jupp,U2,90 +FloatsWithCash,U2,90 +BuysItemFor,Volker,PRES_CERT_NAME,U1,50,90 +FloatsWithCash,U1,180 +PASSES,Martin +BuysItemFor,Ocki,PRES_CERT_NAME,U3,50,90 +FloatsWithCash,U3,180 +PASSES,Marcus +PASSES,Jupp +PASSES,Volker +PASSES,Martin +PASSES,Ocki +ALL_PASSED +Has,EPP,100 +Has,RGTE,100 +Has,EOD,100 +Has,EKT,100 +Has,MLB,100 +Has,ZKB,100 +Has,SPB,100 +Has,LRB,100 +Has,BB,100 +Has,EHS,100 +Has,S1,90 +Has,S2,90 +Has,S3,90 +Has,S4,90 +Has,S5,90 +Has,K1,90 +Has,K2,120 +Has,K3,90 +Has,U1,180 +Has,U2,90 +Has,U3,180 +Has,Ocki,0 +Has,Marcus,60 +Has,Jupp,0 +Has,Volker,60 +Has,Martin,5 +START_OR,0.0 +ReceivesFor,Martin,25,KwB +ReceivesFor,Ocki,15,BrB +ReceivesFor,Marcus,30,WB +ReceivesFor,Martin,20,AB +ReceivesFor,Ocki,10,KB +ReceivesFor,Jupp,5,SmB +ReceivesFor,Marcus,35,TB + +CompanyOperates,EPP,Jupp