diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameUi.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameUi.js
index 7226d37c9..6747c533f 100644
--- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameUi.js
+++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameUi.js
@@ -258,7 +258,7 @@ var GempLotrGameUI = Class.extend({
this.layoutUI(false);
},
- initializeGameUI: function () {
+ initializeGameUI: function (discardPublic) {
this.advPathGroup = new AdvPathCardGroup($("#main"));
var that = this;
@@ -330,16 +330,18 @@ var GempLotrGameUI = Class.extend({
//TODO: This is where we will need to add support for public discard piles
if (!this.spectatorMode) {
- $("#discard" + this.getPlayerIndex(this.bottomPlayerId)).addClass("clickable").click(
- (function (index) {
- return function () {
- var dialog = that.discardPileDialogs[index];
- var group = that.discardPileGroups[index];
- openSizeDialog(dialog);
- that.dialogResize(dialog, group);
- group.layoutCards();
- };
- })(that.bottomPlayerId));
+ if(!discardPublic) {
+ $("#discard" + this.getPlayerIndex(this.bottomPlayerId)).addClass("clickable").click(
+ (function (index) {
+ return function () {
+ var dialog = that.discardPileDialogs[index];
+ var group = that.discardPileGroups[index];
+ openSizeDialog(dialog);
+ that.dialogResize(dialog, group);
+ group.layoutCards();
+ };
+ })(that.bottomPlayerId));
+ }
$("#adventureDeck" + this.getPlayerIndex(this.bottomPlayerId)).addClass("clickable").click(
(function (index) {
return function () {
@@ -363,6 +365,19 @@ var GempLotrGameUI = Class.extend({
group.layoutCards();
};
})(i));
+
+ if(discardPublic) {
+ $("#discard" + i).addClass("clickable").click(
+ (function (index) {
+ return function () {
+ var dialog = that.discardPileDialogs[that.allPlayerIds[index]];
+ var group = that.discardPileGroups[that.allPlayerIds[index]];
+ openSizeDialog(dialog);
+ that.dialogResize(dialog, group);
+ group.layoutCards();
+ };
+ })(i));
+ }
}
this.alertBox = $("
");
@@ -1359,6 +1374,7 @@ var GempLotrGameUI = Class.extend({
participant: function (element) {
var participantId = element.getAttribute("participantId");
this.allPlayerIds = element.getAttribute("allParticipantIds").split(",");
+ var discardPublic = element.getAttribute("discardPublic") === 'true';
this.bottomPlayerId = participantId;
@@ -1371,79 +1387,100 @@ var GempLotrGameUI = Class.extend({
} else {
this.spectatorMode = false;
- var discardPileDialog = $("").dialog({
- autoOpen: false,
- closeOnEscape: true,
- resizable: true,
- title: "Discard - " + participantId,
- minHeight: 80,
- minWidth: 200,
- width: 600,
- height: 300
- });
+ if(!discardPublic) {
+ this.createPile(participantId, "Discard Pile", "discardPileDialogs", "discardPileGroups");
+ }
- this.discardPileDialogs[participantId] = discardPileDialog;
- this.discardPileGroups[participantId] = new NormalCardGroup(discardPileDialog, function (card) {
- return true;
- }, false);
-
- this.discardPileGroups[participantId].setBounds(this.padding, this.padding, 580 - 2 * (this.padding), 250 - 2 * (this.padding));
-
- discardPileDialog.bind("dialogresize", function () {
- that.dialogResize(discardPileDialog, that.discardPileGroups[participantId]);
- });
-
- var adventureDeckDialog = $("").dialog({
- autoOpen: false,
- closeOnEscape: true,
- resizable: true,
- title: "Adventure deck - " + participantId,
- minHeight: 80,
- minWidth: 200,
- width: 600,
- height: 300
- });
-
- this.adventureDeckDialogs[participantId] = adventureDeckDialog;
- this.adventureDeckGroups[participantId] = new NormalCardGroup(adventureDeckDialog, function (card) {
- return true;
- }, false);
-
- this.adventureDeckGroups[participantId].setBounds(this.padding, this.padding, 580 - 2 * (this.padding), 250 - 2 * (this.padding));
-
- adventureDeckDialog.bind("dialogresize", function () {
- that.dialogResize(adventureDeckDialog, that.adventureDeckGroups[participantId]);
- });
+ this.createPile(participantId, "Adventure Deck", "adventureDeckDialogs", "adventureDeckGroups");
}
for (var i = 0; i < this.allPlayerIds.length; i++) {
- var deadPileDialog = $("").dialog({
- autoOpen: false,
- closeOnEscape: true,
- resizable: true,
- title: "Dead pile - " + this.allPlayerIds[i],
- minHeight: 80,
- minWidth: 200,
- width: 600,
- height: 300
- });
- this.deadPileDialogs[this.allPlayerIds[i]] = deadPileDialog;
- this.deadPileGroups[this.allPlayerIds[i]] = new NormalCardGroup(deadPileDialog, function (card) {
- return true;
- }, false);
+
+ participantId = this.allPlayerIds[i];
+
+ this.createPile(participantId, "Dead Pile", "deadPileDialogs", "deadPileGroups");
+
+ if(discardPublic) {
+ this.createPile(participantId, "Discard Pile", "discardPileDialogs", "discardPileGroups");
+ }
+
+ // var deadPileDialog = $("").dialog({
+ // autoOpen: false,
+ // closeOnEscape: true,
+ // resizable: true,
+ // title: "Dead pile - " + this.allPlayerIds[i],
+ // minHeight: 80,
+ // minWidth: 200,
+ // width: 600,
+ // height: 300
+ // });
+ // this.deadPileDialogs[this.allPlayerIds[i]] = deadPileDialog;
+ // this.deadPileGroups[this.allPlayerIds[i]] = new NormalCardGroup(deadPileDialog, function (card) {
+ // return true;
+ // }, false);
- this.deadPileGroups[this.allPlayerIds[i]].setBounds(this.padding, this.padding, 580 - 2 * (this.padding), 250 - 2 * (this.padding));
+ // this.deadPileGroups[this.allPlayerIds[i]].setBounds(this.padding, this.padding, 580 - 2 * (this.padding), 250 - 2 * (this.padding));
- deadPileDialog.bind("dialogresize", (function (dialog, index) {
- return function () {
- that.dialogResize(dialog, that.deadPileGroups[that.allPlayerIds[index]]);
- }
- })(deadPileDialog, i));
+ // deadPileDialog.bind("dialogresize", (function (dialog, index) {
+ // return function () {
+ // that.dialogResize(dialog, that.deadPileGroups[that.allPlayerIds[index]]);
+ // }
+ // })(deadPileDialog, i));
}
- this.initializeGameUI();
+ this.initializeGameUI(discardPublic);
this.layoutUI(true);
},
+
+ createAdventureDeckPiles: function(id) {
+ var adventureDeckDialog = $("").dialog({
+ autoOpen: false,
+ closeOnEscape: true,
+ resizable: true,
+ title: "Adventure deck - " + participantId,
+ minHeight: 80,
+ minWidth: 200,
+ width: 600,
+ height: 300
+ });
+
+ this.adventureDeckDialogs[participantId] = adventureDeckDialog;
+ this.adventureDeckGroups[participantId] = new NormalCardGroup(adventureDeckDialog, function (card) {
+ return true;
+ }, false);
+
+ this.adventureDeckGroups[participantId].setBounds(this.padding, this.padding, 580 - 2 * (this.padding), 250 - 2 * (this.padding));
+
+ adventureDeckDialog.bind("dialogresize", function () {
+ that.dialogResize(adventureDeckDialog, that.adventureDeckGroups[participantId]);
+ });
+ },
+
+ createPile: function(playerId, name, dialogsName, groupsName) {
+ var dialog = $("").dialog({
+ autoOpen: false,
+ closeOnEscape: true,
+ resizable: true,
+ title: name + " - " + playerId,
+ minHeight: 80,
+ minWidth: 200,
+ width: 600,
+ height: 300
+ });
+
+ this[dialogsName][playerId] = dialog;
+ this[groupsName][playerId] = new NormalCardGroup(dialog, function (card) {
+ return true;
+ }, false);
+
+ this[groupsName][playerId].setBounds(this.padding, this.padding, 580 - 2 * (this.padding), 250 - 2 * (this.padding));
+
+ var that = this;
+
+ dialog.bind("dialogresize", function () {
+ that.dialogResize(dialog, that[groupsName][playerId]);
+ });
+ },
getDecisionParameter: function (decision, name) {
var parameters = decision.getElementsByTagName("parameter");
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/lotrFormats.json b/gemp-lotr/gemp-lotr-cards/src/main/resources/lotrFormats.json
index c761c8f25..7d1bcbe75 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/lotrFormats.json
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/lotrFormats.json
@@ -23,6 +23,8 @@
"order": 2,
"sites":"FELLOWSHIP",
"cancelRingBearerSkirmish":true,
+ "winAtEndOfRegroup":true,
+ "discardPileIsPublic":true,
"set":[1, 2, 3, 101],
"erratasets": [
51,52,53
@@ -41,6 +43,8 @@
"code":"pc_movie",
"order": 4,
"sites":"KING",
+ "winAtEndOfRegroup":true,
+ "discardPileIsPublic":true,
"set":[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 101],
"erratasets": [
51,52,53,54,55,56,57,58,59,60
@@ -60,6 +64,8 @@
"code":"pc_expanded",
"order": 6,
"sites":"SHADOWS",
+ "winAtEndOfRegroup":true,
+ "discardPileIsPublic":true,
"set":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 100, 101],
"erratasets": [
51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69
diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/JSONDefs.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/JSONDefs.java
index 4efa31e0c..2a48f6866 100644
--- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/JSONDefs.java
+++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/JSONDefs.java
@@ -40,6 +40,7 @@ public class JSONDefs {
public boolean cancelRingBearerSkirmish = false;
public boolean ruleOfFour = true;
public boolean winAtEndOfRegroup = false;
+ public boolean discardPileIsPublic = false;
public boolean winOnControlling5Sites = false;
public boolean playtest = false;
public boolean validateShadowFPCount = true;
diff --git a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Zone.java b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Zone.java
index acaf70cec..d03b1fca5 100644
--- a/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Zone.java
+++ b/gemp-lotr/gemp-lotr-common/src/main/java/com/gempukku/lotro/common/Zone.java
@@ -7,13 +7,14 @@ public enum Zone implements Filterable {
// Public knowledge but not in play
STACKED("stacked", true, true, false), DEAD("dead pile", true, true, false),
+ REMOVED("removed", true, true, false),
// Private knowledge
HAND("hand", false, true, false), DISCARD("discard", false, true, false),
ADVENTURE_DECK("adventureDeck", false, true, false),
// Nobody sees
- VOID("void", false, false, false), VOID_FROM_HAND("voidFromHand", false, false, false), DECK("deck", false, false, false), REMOVED("removed", false, false, false);
+ VOID("void", false, false, false), VOID_FROM_HAND("voidFromHand", false, false, false), DECK("deck", false, false, false);
private final String _humanReadable;
private final boolean _public;
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/communication/GameStateListener.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/communication/GameStateListener.java
index f1ff85400..d5f2f92be 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/communication/GameStateListener.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/communication/GameStateListener.java
@@ -16,7 +16,7 @@ public interface GameStateListener {
public void cardsRemoved(String playerPerforming, Collection cards);
- public void setPlayerOrder(List playerIds);
+ public void initializeBoard(List playerIds, boolean discardIsPublic);
public void setPlayerPosition(String playerId, int i);
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroFormat.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroFormat.java
index f90c32ec7..883508cae 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroFormat.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/LotroFormat.java
@@ -18,6 +18,8 @@ public interface LotroFormat {
public boolean winWhenShadowReconciles();
+ public boolean discardPileIsPublic();
+
public boolean winOnControlling5Sites();
public boolean isPlaytest();
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/EventSerializer.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/EventSerializer.java
index ef4fde98e..7991048f1 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/EventSerializer.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/EventSerializer.java
@@ -46,6 +46,8 @@ public class EventSerializer {
eventElem.setAttribute("message", gameEvent.getMessage());
if (gameEvent.getVersion() != null)
eventElem.setAttribute("version", gameEvent.getVersion().toString());
+ if (gameEvent.getType() == GameEvent.Type.PARTICIPANTS)
+ eventElem.setAttribute("discardPublic", String.valueOf(gameEvent.isDiscardPublic()));
if (gameEvent.getGameStats() != null)
serializeGameStats(doc, eventElem, gameEvent.getGameStats());
if (gameEvent.getAwaitingDecision() != null)
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameCommunicationChannel.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameCommunicationChannel.java
index 4d7a4ae52..fd3e667d5 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameCommunicationChannel.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameCommunicationChannel.java
@@ -1,7 +1,9 @@
package com.gempukku.lotro.game.state;
import com.gempukku.lotro.common.Token;
+import com.gempukku.lotro.common.Zone;
import com.gempukku.lotro.communication.GameStateListener;
+import com.gempukku.lotro.game.LotroFormat;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.logic.decisions.AwaitingDecision;
import com.gempukku.lotro.logic.timing.GameStats;
@@ -19,9 +21,12 @@ public class GameCommunicationChannel implements GameStateListener, LongPollable
private final int _channelNumber;
private volatile WaitingRequest _waitingRequest;
- public GameCommunicationChannel(String self, int channelNumber) {
+ private final LotroFormat _format;
+
+ public GameCommunicationChannel(String self, int channelNumber, LotroFormat format) {
_self = self;
_channelNumber = channelNumber;
+ _format = format;
}
public int getChannelNumber() {
@@ -29,10 +34,14 @@ public class GameCommunicationChannel implements GameStateListener, LongPollable
}
@Override
- public void setPlayerOrder(List participants) {
+ public void initializeBoard(List participants, boolean discardIsPublic) {
List participantIds = new LinkedList<>();
participantIds.addAll(participants);
- appendEvent(new GameEvent(PARTICIPANTS).participantId(_self).allParticipantIds(participantIds));
+ appendEvent(new GameEvent(PARTICIPANTS)
+ .participantId(_self)
+ .allParticipantIds(participantIds)
+ .discardPublic(discardIsPublic)
+ );
}
@Override
@@ -107,7 +116,8 @@ public class GameCommunicationChannel implements GameStateListener, LongPollable
@Override
public void cardCreated(PhysicalCard card) {
- if (card.getZone().isPublic() || (card.getZone().isVisibleByOwner() && card.getOwner().equals(_self)))
+ boolean publicDiscard = card.getZone() == Zone.DISCARD && _format.discardPileIsPublic();
+ if (card.getZone().isPublic() || publicDiscard || (card.getZone().isVisibleByOwner() && card.getOwner().equals(_self)))
appendEvent(new GameEvent(PUT_CARD_INTO_PLAY).card(card));
}
@@ -120,7 +130,8 @@ public class GameCommunicationChannel implements GameStateListener, LongPollable
public void cardsRemoved(String playerPerforming, Collection cards) {
Set removedCardsVisibleByPlayer = new HashSet<>();
for (PhysicalCard card : cards) {
- if (card.getZone().isPublic() || (card.getZone().isVisibleByOwner() && card.getOwner().equals(_self)))
+ boolean publicDiscard = card.getZone() == Zone.DISCARD && _format.discardPileIsPublic();
+ if (card.getZone().isPublic() || publicDiscard || (card.getZone().isVisibleByOwner() && card.getOwner().equals(_self)))
removedCardsVisibleByPlayer.add(card);
}
if (removedCardsVisibleByPlayer.size() > 0)
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java
index d3db064f5..2bf1c412e 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameEvent.java
@@ -57,6 +57,7 @@ public class GameEvent {
private AwaitingDecision _awaitingDecision;
private ZonedDateTime _timestamp;
private Integer _version;
+ private boolean _discardIsPublic;
public GameEvent(Type type) {
_type = type;
@@ -241,4 +242,13 @@ public class GameEvent {
_phase = phase;
return this;
}
+
+ public boolean isDiscardPublic() {
+ return _discardIsPublic;
+ }
+
+ public GameEvent discardPublic(boolean discardPublic) {
+ _discardIsPublic = discardPublic;
+ return this;
+ }
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java
index 78c3a2762..82d3910f7 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java
@@ -18,6 +18,8 @@ public class GameState {
private static final int LAST_MESSAGE_STORED_COUNT = 15;
private PlayerOrder _playerOrder;
+ private LotroFormat _format;
+
private final Map> _adventureDecks = new HashMap<>();
private final Map> _decks = new HashMap<>();
private final Map> _hands = new HashMap<>();
@@ -67,9 +69,10 @@ public class GameState {
return _nextCardId++;
}
- public void init(PlayerOrder playerOrder, String firstPlayer, Map> cards, Map ringBearers, Map rings, LotroCardBlueprintLibrary library, GameStats gameStats) {
+ public void init(PlayerOrder playerOrder, String firstPlayer, Map> cards, Map ringBearers, Map rings, LotroCardBlueprintLibrary library, LotroFormat format) {
_playerOrder = playerOrder;
_currentPlayerId = firstPlayer;
+ _format = format;
for (Map.Entry> stringListEntry : cards.entrySet()) {
String playerId = stringListEntry.getKey();
@@ -101,7 +104,7 @@ public class GameState {
}
for (GameStateListener listener : getAllGameStateListeners()) {
- listener.setPlayerOrder(playerOrder.getAllPlayers());
+ listener.initializeBoard(playerOrder.getAllPlayers(), format.discardPileIsPublic());
}
//This needs done after the Player Order initialization has been issued, or else the player
@@ -198,7 +201,7 @@ public class GameState {
private void sendStateToPlayer(String playerId, GameStateListener listener, GameStats gameStats) {
if (_playerOrder != null) {
- listener.setPlayerOrder(_playerOrder.getAllPlayers());
+ listener.initializeBoard(_playerOrder.getAllPlayers(), _format.discardPileIsPublic());
if (_currentPlayerId != null)
listener.setCurrentPlayerId(_currentPlayerId);
if (_currentPhase != null)
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/actions/PlayerReconcilesAction.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/actions/PlayerReconcilesAction.java
index 8813b838f..f7953b163 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/actions/PlayerReconcilesAction.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/actions/PlayerReconcilesAction.java
@@ -80,45 +80,54 @@ public class PlayerReconcilesAction implements Action {
@Override
public Effect nextEffect(LotroGame game) {
if (_effectQueue == null) {
- game.getGameState().sendMessage(_playerId + " reconciles");
+
_effectQueue = new LinkedList<>();
final int handSize = game.getFormat().getHandSize();
GameState gameState = _game.getGameState();
final Set extends PhysicalCard> cardsInHand = new HashSet(gameState.getHand(_playerId));
- if (cardsInHand.size() > handSize) {
- _effectQueue.add(new PlayoutDecisionEffect(_playerId,
- new CardsSelectionDecision(1, "Choose cards to discard down to "+handSize, cardsInHand, cardsInHand.size() - handSize, cardsInHand.size() - handSize) {
- @Override
- public void decisionMade(String result) throws DecisionResultInvalidException {
- Set cards = getSelectedCardsByResponse(result);
- _effectQueue.add(new DiscardCardsFromHandEffect(null, _playerId, cards, false));
- _effectQueue.add(
- new TriggeringResultEffect(new ReconcileResult(_playerId), "Player reconciled"));
- }
- }));
- } else if (cardsInHand.size() > 0) {
- _effectQueue.add(new PlayoutDecisionEffect(_playerId,
- new CardsSelectionDecision(1, "Reconcile - choose card to discard or press DONE", cardsInHand, 0, 1) {
- @Override
- public void decisionMade(String result) throws DecisionResultInvalidException {
- Set selectedCards = getSelectedCardsByResponse(result);
- if (selectedCards.size() > 0) {
- _effectQueue.add(new DiscardCardsFromHandEffect(null, _playerId, selectedCards, false));
+
+ if(game.getFormat().winWhenShadowReconciles() && game.getGameState().getCurrentPhase() == Phase.REGROUP
+ && game.getGameState().getCurrentSiteNumber() == 9) {
+ game.getGameState().sendMessage("End of regroup phase reached.");
+ }
+ else {
+ game.getGameState().sendMessage(_playerId + " reconciles");
+
+ if (cardsInHand.size() > handSize) {
+ _effectQueue.add(new PlayoutDecisionEffect(_playerId,
+ new CardsSelectionDecision(1, "Choose cards to discard down to "+handSize, cardsInHand, cardsInHand.size() - handSize, cardsInHand.size() - handSize) {
+ @Override
+ public void decisionMade(String result) throws DecisionResultInvalidException {
+ Set cards = getSelectedCardsByResponse(result);
+ _effectQueue.add(new DiscardCardsFromHandEffect(null, _playerId, cards, false));
+ _effectQueue.add(
+ new TriggeringResultEffect(new ReconcileResult(_playerId), "Player reconciled"));
}
- int cardsInHandAfterDiscard = cardsInHand.size() - selectedCards.size();
- if (cardsInHandAfterDiscard < handSize) {
- _effectQueue.add(new DrawCardsEffect(PlayerReconcilesAction.this, _playerId, handSize - cardsInHandAfterDiscard));
+ }));
+ } else if (cardsInHand.size() > 0) {
+ _effectQueue.add(new PlayoutDecisionEffect(_playerId,
+ new CardsSelectionDecision(1, "Reconcile - choose card to discard or press DONE", cardsInHand, 0, 1) {
+ @Override
+ public void decisionMade(String result) throws DecisionResultInvalidException {
+ Set selectedCards = getSelectedCardsByResponse(result);
+ if (selectedCards.size() > 0) {
+ _effectQueue.add(new DiscardCardsFromHandEffect(null, _playerId, selectedCards, false));
+ }
+ int cardsInHandAfterDiscard = cardsInHand.size() - selectedCards.size();
+ if (cardsInHandAfterDiscard < handSize) {
+ _effectQueue.add(new DrawCardsEffect(PlayerReconcilesAction.this, _playerId, handSize - cardsInHandAfterDiscard));
+ }
+ _effectQueue.add(
+ new TriggeringResultEffect(new ReconcileResult(_playerId), "Player reconciled"));
}
- _effectQueue.add(
- new TriggeringResultEffect(new ReconcileResult(_playerId), "Player reconciled"));
- }
- }));
- } else {
- _effectQueue.add(new DrawCardsEffect(PlayerReconcilesAction.this, _playerId, handSize));
- _effectQueue.add(
- new TriggeringResultEffect(new ReconcileResult(_playerId), "Player reconciled"));
+ }));
+ } else {
+ _effectQueue.add(new DrawCardsEffect(PlayerReconcilesAction.this, _playerId, handSize));
+ _effectQueue.add(
+ new TriggeringResultEffect(new ReconcileResult(_playerId), "Player reconciled"));
+ }
}
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java
index 843e9b5a4..702516164 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/DefaultLotroGame.java
@@ -80,7 +80,7 @@ public class DefaultLotroGame implements LotroGame {
@Override
public void setPlayerOrder(PlayerOrder playerOrder, String firstPlayer) {
final GameStats gameStats = _turnProcedure.getGameStats();
- _gameState.init(playerOrder, firstPlayer, cards, ringBearers, rings, library, gameStats);
+ _gameState.init(playerOrder, firstPlayer, cards, ringBearers, rings, library, format);
}
}, characterDeathRule);
_userFeedback = userFeedback;
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/WinConditionRule.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/WinConditionRule.java
index 7c0951f28..2fc2317ae 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/WinConditionRule.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/rules/WinConditionRule.java
@@ -31,7 +31,7 @@ public class WinConditionRule {
if (isWinAtReconcile(game)) {
if (effectResults.getType() == EffectResult.Type.RECONCILE
&& !((ReconcileResult) effectResults).getPlayerId().equals(game.getGameState().getCurrentPlayerId())) {
- game.playerWon(game.getGameState().getCurrentPlayerId(), "Surviving till Shadow player reconciles on site 9");
+ game.playerWon(game.getGameState().getCurrentPlayerId(), "Surviving to end of Regroup phase on site 9");
}
} else if (effectResults.getType() == EffectResult.Type.START_OF_PHASE) {
game.playerWon(game.getGameState().getCurrentPlayerId(), "Surviving to Regroup phase on site 9");
diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java
index fa1330e1f..eb975a41a 100644
--- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java
+++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/GameRecorder.java
@@ -49,7 +49,7 @@ public class GameRecorder {
final ZonedDateTime startDate = ZonedDateTime.now(ZoneOffset.UTC);
final Map recordingChannels = new HashMap<>();
for (String playerId : lotroGame.getPlayersPlaying()) {
- var recordChannel = new GameCommunicationChannel(playerId, 0);
+ var recordChannel = new GameCommunicationChannel(playerId, 0, format);
lotroGame.addGameStateListener(playerId, recordChannel);
recordingChannels.put(playerId, recordChannel);
}
diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java
index 45ea334f5..d09181441 100644
--- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java
+++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/LotroGameMediator.java
@@ -403,7 +403,7 @@ public class LotroGameMediator {
int number = _channelNextIndex;
_channelNextIndex++;
- GameCommunicationChannel participantCommunicationChannel = new GameCommunicationChannel(playerName, number);
+ GameCommunicationChannel participantCommunicationChannel = new GameCommunicationChannel(playerName, number, _lotroGame.getFormat());
_communicationChannels.put(playerName, participantCommunicationChannel);
_lotroGame.addGameStateListener(playerName, participantCommunicationChannel);
diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/formats/DefaultLotroFormat.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/formats/DefaultLotroFormat.java
index ac05d32fc..609fb374a 100644
--- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/formats/DefaultLotroFormat.java
+++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/game/formats/DefaultLotroFormat.java
@@ -24,6 +24,7 @@ public class DefaultLotroFormat implements LotroFormat {
private final boolean _canCancelRingBearerSkirmish;
private final boolean _hasRuleOfFour;
private final boolean _winAtEndOfRegroup;
+ private final boolean _discardPileIsPublic;
private final boolean _winOnControlling5Sites;
private int _minimumDeckSize = 60;
private final List _bannedCards = new ArrayList<>();
@@ -42,7 +43,7 @@ public class DefaultLotroFormat implements LotroFormat {
public DefaultLotroFormat(AdventureLibrary adventureLibrary, LotroCardBlueprintLibrary library, JSONDefs.Format def) throws InvalidPropertiesFormatException{
this(library, adventureLibrary.getAdventure(def.adventure), def.name, def.code, def.order, def.surveyUrl, SitesBlock.valueOf(def.sites),
def.validateShadowFPCount, def.minimumDeckSize, def.maximumSameName, def.mulliganRule, def.cancelRingBearerSkirmish,
- def.ruleOfFour, def.winAtEndOfRegroup, def.winOnControlling5Sites, def.playtest, def.hall);
+ def.ruleOfFour, def.winAtEndOfRegroup, def.discardPileIsPublic, def.winOnControlling5Sites, def.playtest, def.hall);
if(def.set != null)
def.set.forEach(this::addValidSet);
@@ -71,8 +72,8 @@ public class DefaultLotroFormat implements LotroFormat {
Adventure adventure, String name, String code, int order, String surveyUrl,
SitesBlock siteBlock,
boolean validateShadowFPCount, int minimumDeckSize, int maximumSameName, boolean mulliganRule,
- boolean canCancelRingBearerSkirmish, boolean hasRuleOfFour, boolean winAtEndOfRegroup, boolean winOnControlling5Sites,
- boolean playtest, boolean hallVisible) {
+ boolean canCancelRingBearerSkirmish, boolean hasRuleOfFour, boolean winAtEndOfRegroup, boolean discardPileIsPublic,
+ boolean winOnControlling5Sites, boolean playtest, boolean hallVisible) {
_adventure = adventure;
_library = library;
_name = name;
@@ -87,6 +88,7 @@ public class DefaultLotroFormat implements LotroFormat {
_canCancelRingBearerSkirmish = canCancelRingBearerSkirmish;
_hasRuleOfFour = hasRuleOfFour;
_winAtEndOfRegroup = winAtEndOfRegroup;
+ _discardPileIsPublic = discardPileIsPublic;
_winOnControlling5Sites = winOnControlling5Sites;
_isPlaytest = playtest;
_hallVisible = hallVisible;
@@ -129,6 +131,9 @@ public class DefaultLotroFormat implements LotroFormat {
return _winAtEndOfRegroup;
}
+ @Override
+ public boolean discardPileIsPublic() { return _discardPileIsPublic; }
+
@Override
public boolean canCancelRingBearerSkirmish() {
return _canCancelRingBearerSkirmish;
@@ -717,6 +722,7 @@ public class DefaultLotroFormat implements LotroFormat {
cancelRingBearerSkirmish = _canCancelRingBearerSkirmish;
ruleOfFour = _hasRuleOfFour;
winAtEndOfRegroup = _winAtEndOfRegroup;
+ discardPileIsPublic = _discardPileIsPublic;
winOnControlling5Sites = _winOnControlling5Sites;
playtest = _isPlaytest;
validateShadowFPCount = _validateShadowFPCount;
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_055_ErrataTests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_055_ErrataTests.java
index 2296edb63..70df8ee18 100644
--- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_055_ErrataTests.java
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/errata/set01/Card_01_055_ErrataTests.java
@@ -94,6 +94,42 @@ public class Card_01_055_ErrataTests
scn.FreepsMoveCharToTable(galadriel);
scn.FreepsMoveCardToSupportArea(mirror);
+ PhysicalCardImpl card1 = scn.GetShadowCard("allyHome3_1");
+ PhysicalCardImpl card2 = scn.GetShadowCard("allyHome6_1");
+ PhysicalCardImpl card3 = scn.GetShadowCard("galadriel");
+ scn.ShadowMoveCardToHand(card1, card2, card3);
+ scn.ShadowMoveCharToTable("runner");
+
+ scn.StartGame();
+
+ scn.SkipToPhase(Phase.MANEUVER);
+ assertTrue(scn.FreepsActionAvailable(mirror));
+ assertEquals(0, scn.GetWoundsOn(galadriel));
+ assertEquals(3, scn.GetShadowHandCount());
+ assertEquals(1, scn.GetShadowDeckCount());
+ assertEquals(Zone.HAND, card1.getZone());
+
+ scn.FreepsUseCardAction(mirror);
+ assertEquals(3, scn.GetFreepsCardChoiceCount());
+ scn.FreepsDismissRevealedCards();
+ scn.ShadowDismissRevealedCards();
+ scn.FreepsChooseCardBPFromSelection(card1);
+ assertEquals(1, scn.GetWoundsOn(galadriel));
+ assertEquals(2, scn.GetShadowHandCount());
+ assertEquals(2, scn.GetShadowDeckCount());
+ assertEquals(Zone.DECK, card1.getZone());
+ }
+
+ @Test
+ public void ManeuverAbilityReveals3RandomCardsFromShadowHand() throws DecisionResultInvalidException, CardNotFoundException {
+ //Pre-game setup
+ GenericCardTestHelper scn = GetScenario();
+
+ PhysicalCardImpl mirror = scn.GetFreepsCard("mirror");
+ PhysicalCardImpl galadriel = scn.GetFreepsCard("galadriel");
+ scn.FreepsMoveCharToTable(galadriel);
+ scn.FreepsMoveCardToSupportArea(mirror);
+
PhysicalCardImpl card1 = scn.GetShadowCard("allyHome3_1");
PhysicalCardImpl card2 = scn.GetShadowCard("allyHome6_1");
PhysicalCardImpl card3 = scn.GetShadowCard("galadriel");
@@ -114,11 +150,6 @@ public class Card_01_055_ErrataTests
assertEquals(3, scn.GetFreepsCardChoiceCount());
scn.FreepsDismissRevealedCards();
scn.ShadowDismissRevealedCards();
- scn.FreepsChooseCardBPFromSelection(card1);
- assertEquals(1, scn.GetWoundsOn(galadriel));
- assertEquals(3, scn.GetShadowHandCount());
- assertEquals(1, scn.GetShadowDeckCount());
- assertEquals(Zone.DECK, card1.getZone());
}
}