Skip to content

Commit 705b0b3

Browse files
authored
Merge pull request #103 from aclonegeek/bonus_joker_rules
Bonus joker rules
2 parents e0deccf + 5292454 commit 705b0b3

File tree

6 files changed

+194
-41
lines changed

6 files changed

+194
-41
lines changed

src/main/java/core/GameController.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.Timer;
1010
import java.util.TimerTask;
1111

12+
import core.Globals.JokerRules;
1213
import javafx.application.Platform;
1314
import javafx.collections.FXCollections;
1415
import javafx.collections.ObservableList;
@@ -534,12 +535,13 @@ public void setPlayerStrategies(ArrayList<String> playerStrategies) {
534535
}
535536
}
536537

537-
public void setExtras(int highlightTimerLength, int optionalTimerLength, boolean showAIHands) {
538+
public void setExtras(int highlightTimerLength, int optionalTimerLength, boolean showAIHands, JokerRules jokerRules) {
538539
this.HIGHLIGHT_TIMER_LENGTH = highlightTimerLength;
539540
if (optionalTimerLength > 0) {
540541
this.enableTimer = true;
541542
this.OPTIONAL_TIMER_LENGTH = optionalTimerLength;
542543
}
543544
this.showAIHands = showAIHands;
545+
Globals.setJokerRules(jokerRules);
544546
}
545547
}

src/main/java/core/Globals.java

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
package core;
22

33
public class Globals {
4+
// Optional rules
5+
public static enum JokerRules {
6+
DEFAULT, LENIENT, NO_EXISTING_MELDS;
7+
}
8+
9+
private static JokerRules jokerRules = JokerRules.DEFAULT;
10+
11+
public static JokerRules getJokerRules() {
12+
return jokerRules;
13+
}
14+
15+
public static void setJokerRules(JokerRules rule) {
16+
jokerRules = rule;
17+
}
18+
419
public static enum Colour {
520
RED('R'), BLUE('B'), GREEN('G'), ORANGE('O');
621

src/main/java/core/Meld.java

+55-35
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.stream.IntStream;
1010

1111
import core.Globals.Colour;
12+
import core.Globals.JokerRules;
1213

1314
public class Meld {
1415
public enum MeldType {
@@ -60,7 +61,7 @@ public Tile addTile(Tile tile) {
6061
}
6162

6263
public Tile removeTile(int index) {
63-
if (this.isLocked) { return null; }
64+
if (!this.isInitialMeld && this.isLocked) { return null; }
6465
if (index < 0 || index >= this.meld.size()) {
6566
return null;
6667
}
@@ -97,7 +98,7 @@ public Tile removeTileObject(Tile tile) {
9798
}
9899

99100
public Meld splitMeld(int index) {
100-
if (this.isLocked || index <= 0 || index >= this.meld.size()) { return null; }
101+
if ((!this.isInitialMeld && this.isLocked) || index <= 0 || index >= this.meld.size()) { return null; }
101102

102103
Meld newMeld = new Meld();
103104
ArrayList<Tile> secondHalf = new ArrayList<>();
@@ -133,7 +134,13 @@ public Tile addTile(ArrayList<Tile> tiles) {
133134
if (tiles.size() > 1 && tiles.removeIf(t -> t.isJoker())) { return null; }
134135

135136
// Disallow two jokers in one meld
136-
if (this.containsJoker() && tiles.get(0).isJoker()) { return null; }
137+
if (this.containsJoker() && tiles.get(0).isJoker()) { return null; }
138+
139+
// Disallow adding a tile to a full meld with a joker if Lenient Jokers are allowed
140+
if (Globals.getJokerRules() == JokerRules.LENIENT) {
141+
if (this.meld.size() == 13 && this.meldType == MeldType.RUN) { return null; }
142+
if (this.meld.size() == 4 && this.meldType == MeldType.SET) { return null; }
143+
}
137144

138145
// Check if the tile being added is part of an initial meld (so the joker inside is not replaced by it right away)
139146
boolean meldIsFromHand = this.meld.stream().allMatch(t -> t.isOnTable() == false);
@@ -153,6 +160,10 @@ public Tile addTile(ArrayList<Tile> tiles) {
153160
if (this.meld.size() == 4 && this.meldType == MeldType.SET) { return null; }
154161

155162
if (tiles.get(0).isJoker()) {
163+
if (Globals.getJokerRules() == JokerRules.NO_EXISTING_MELDS && this.isInitialMeld == false) {
164+
return null;
165+
}
166+
156167
tempMeld.addAll(this.meld);
157168
Tile joker = this.determineJokerType(tiles.get(0), tempMeld);
158169
tempMeld.add(joker);
@@ -177,25 +188,26 @@ public Tile addTile(ArrayList<Tile> tiles) {
177188

178189
// Adding tile to a meld with a joker and one or more tiles
179190
if (this.meld.size() > 0) {
180-
// Check if the joker can be replaced as long as its not part of an initial move
181-
if (!this.isInitialMeld && joker.jokerEquals(tile)) {
182-
// If this tile is on the table but is being added to a meld that is locked
183-
if (tile.onTable && this.isLocked) {
184-
// Add the joker back
185-
joker = this.determineJokerType(joker, tempMeld);
186-
this.meld.add(joker);
187-
this.buildMeld(this.meld, releasedJoker);
188-
return null;
189-
}
190-
// Otherwise this meld is not locked or the tile being added is from the hand
191-
// In both cases, replace the joker
192-
releasedJoker = jokers.remove(0);
193-
tempMeld.add(tile);
194-
tempMeld.addAll(this.meld);
195-
return this.buildMeld(tempMeld, releasedJoker);
191+
if (Globals.getJokerRules() != JokerRules.LENIENT) {
192+
// Check if the joker can be replaced as long as its not part of an initial move
193+
if (!this.isInitialMeld && joker.jokerEquals(tile)) {
194+
// If this tile is on the table but is being added to a meld that is locked
195+
if (tile.onTable && this.isLocked) {
196+
// Add the joker back
197+
joker = this.determineJokerType(joker, tempMeld);
198+
this.meld.add(joker);
199+
this.buildMeld(this.meld, releasedJoker);
200+
return null;
201+
}
202+
// Otherwise this meld is not locked or the tile being added is from the hand
203+
// In both cases, replace the joker
204+
releasedJoker = jokers.remove(0);
205+
tempMeld.add(tile);
206+
tempMeld.addAll(this.meld);
207+
return this.buildMeld(tempMeld, releasedJoker);
208+
}
196209
}
197210

198-
199211
// Otherwise the joker can't be replaced. Check if the tile can still be added to the meld
200212
tempMeld.addAll(this.meld);
201213
tempMeld.add(tile);
@@ -234,8 +246,10 @@ private Tile buildMeld(ArrayList<Tile> tempMeld, Tile releasedJoker) {
234246
if (tempMeldType != MeldType.INVALID && tempMeld.size() < 3 || tempMeldType == MeldType.RUN || tempMeldType == MeldType.SET) {
235247
Collections.sort(tempMeld, Comparator.comparingInt(Tile::getValue)); // Sort numerically
236248

237-
// Lock the meld if a joker from the hand was added
238-
this.isLocked = this.determineLockedMeld(tempMeld);
249+
if (Globals.getJokerRules() != JokerRules.LENIENT) {
250+
// Lock the meld if a joker from the hand was added
251+
this.isLocked = this.determineLockedMeld(tempMeld);
252+
}
239253

240254
this.meld = tempMeld;
241255
this.meldType = tempMeldType;
@@ -410,28 +424,34 @@ private MeldType determineMeldType(ArrayList<Tile> tiles) {
410424

411425
// Locked meld = meld with a joker that has not been replaced yet
412426
private boolean determineLockedMeld(ArrayList<Tile> meld) {
413-
for (Tile tile : meld) {
414-
if (tile.isJoker() && tile.isReplaced() == false) {
415-
return true;
416-
}
427+
if (Globals.getJokerRules() != JokerRules.LENIENT) {
428+
for (Tile tile : meld) {
429+
if (tile.isJoker() && tile.isReplaced() == false) {
430+
return true;
431+
}
432+
}
417433
}
418434
return false;
419435
}
420436

421437
public boolean isLocked() {
422-
// This meld is locked if it has a joker which has not been replaced by a tile from the hand
423-
return this.meld.stream().anyMatch(t -> t.isJoker() && !t.isReplaced());
438+
if (Globals.getJokerRules() != JokerRules.LENIENT) {
439+
// This meld is locked if it has a joker which has not been replaced by a tile from the hand
440+
return this.meld.stream().anyMatch(t -> t.isJoker() && !t.isReplaced());
441+
}
442+
return false;
424443
}
425444

426445
public void setIsLocked(boolean isLocked) {
427-
// Lock this meld manually by looking for a joker and setting isReplaced
428-
for (Tile tile : this.meld) {
429-
if (tile.isJoker()) {
430-
tile.setIsReplaced(!isLocked);
431-
this.isLocked = isLocked;
432-
}
446+
if (Globals.getJokerRules() != JokerRules.LENIENT) {
447+
// Lock this meld manually by looking for a joker and setting isReplaced
448+
for (Tile tile : this.meld) {
449+
if (tile.isJoker()) {
450+
tile.setIsReplaced(!isLocked);
451+
this.isLocked = isLocked;
452+
}
453+
}
433454
}
434-
435455
}
436456

437457
public boolean isInitialMeld() {

src/main/java/core/Rummikub.png

449 KB
Loading

src/main/java/core/StartMenuController.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
import java.io.FileReader;
66
import java.io.IOException;
77
import java.nio.file.Paths;
8+
import java.sql.Array;
89
import java.util.ArrayList;
910

11+
import core.Globals.JokerRules;
1012
import javafx.beans.value.ChangeListener;
1113
import javafx.collections.FXCollections;
1214
import javafx.collections.ObservableList;
@@ -89,7 +91,8 @@ private void handlePlayButtonPressed(ActionEvent event) throws IOException {
8991
gameController.setPlayerStrategies(this.getPlayerStrategies());
9092
gameController.setExtras(this.getHighlightTimerLength(),
9193
this.getOptionalTimerLength(),
92-
this.showAIHandsCheckBox.isSelected());
94+
this.showAIHandsCheckBox.isSelected(),
95+
this.getSelectedJokerRule());
9396
if (this.enableRiggingCheckBox.isSelected()) {
9497
gameController.setRiggedAttributes(this.getRiggedStock(this.stockField.getText()),
9598
this.getRiggedStock(this.deciderStockField.getText()),
@@ -98,6 +101,17 @@ private void handlePlayButtonPressed(ActionEvent event) throws IOException {
98101

99102
gameController.play();
100103
}
104+
105+
private JokerRules getSelectedJokerRule() {
106+
if (this.jokerRules.getValue().equals("Default")) {
107+
return JokerRules.DEFAULT;
108+
} else if (this.jokerRules.getValue().equals("No Plays to Existing Melds")) {
109+
return JokerRules.NO_EXISTING_MELDS;
110+
} else if (this.jokerRules.getValue().equals("No Restrictions")) {
111+
return JokerRules.LENIENT;
112+
}
113+
return JokerRules.DEFAULT;
114+
}
101115

102116
private int getHighlightTimerLength() {
103117
try {

0 commit comments

Comments
 (0)