Fixing problems with concurrency and decision timeouts during preparation of the game.

This commit is contained in:
marcins78@gmail.com
2011-09-18 11:39:56 +00:00
parent 531fe20b79
commit 3d6a8c6ff5
8 changed files with 78 additions and 85 deletions

View File

@@ -39,17 +39,13 @@ public class GameState {
private Map<String, GameStateListener> _gameStateListeners = new HashMap<String, GameStateListener>();
private String _winnerPlayerId;
private String _winReason;
private Map<String, String> _losers = new HashMap<String, String>();
private int _nextCardId = 0;
private int nextCardId() {
return _nextCardId++;
}
public GameState(PlayerOrder playerOrder, String firstPlayer, Map<String, List<String>> cards, LotroCardBlueprintLibrary library) {
public void init(PlayerOrder playerOrder, String firstPlayer, Map<String, List<String>> cards, LotroCardBlueprintLibrary library) {
_playerOrder = playerOrder;
_currentPlayerId = firstPlayer;
for (Map.Entry<String, List<String>> stringListEntry : cards.entrySet()) {
@@ -63,31 +59,9 @@ public class GameState {
addPlayerCards(stringListEntry.getKey(), stringListEntry.getValue(), library);
}
}
public void setWinnerPlayerId(String winnerPlayerId, String reason) {
_winnerPlayerId = winnerPlayerId;
_winReason = reason;
for (GameStateListener listener : getAllGameStateListeners())
listener.sendMessage(winnerPlayerId + " is the winner due to: " + reason);
}
public String setLoserPlayerId(String loserPlayerId, String reason) {
_losers.put(loserPlayerId, reason);
for (GameStateListener listener : getAllGameStateListeners())
listener.sendMessage(loserPlayerId + " lost due to: " + reason);
if (_losers.size() + 1 == _playerOrder.getAllPlayers().size()) {
List<String> allPlayers = new LinkedList<String>(_playerOrder.getAllPlayers());
allPlayers.removeAll(_losers.keySet());
setWinnerPlayerId(allPlayers.get(0), "Last remaining player in game");
return allPlayers.get(0);
}
return null;
}
public String getWinnerPlayerId() {
return _winnerPlayerId;
for (String playerId : _gameStateListeners.keySet())
sendStateToPlayer(playerId);
}
private void addPlayerCards(String playerId, List<String> cards, LotroCardBlueprintLibrary library) {
@@ -143,43 +117,39 @@ public class GameState {
}
private void sendStateToPlayer(String playerId) {
GameStateListener listener = _gameStateListeners.get(playerId);
listener.setPlayerOrder(_playerOrder.getAllPlayers());
if (_currentPlayerId != null)
listener.setCurrentPlayerId(_currentPlayerId);
if (_currentPhase != null)
listener.setCurrentPhase(_currentPhase);
listener.setTwilight(_twilightPool);
for (Map.Entry<String, Integer> stringIntegerEntry : _playerPosition.entrySet())
listener.setPlayerPosition(stringIntegerEntry.getKey(), stringIntegerEntry.getValue());
if (_playerOrder != null) {
GameStateListener listener = _gameStateListeners.get(playerId);
listener.setPlayerOrder(_playerOrder.getAllPlayers());
if (_currentPlayerId != null)
listener.setCurrentPlayerId(_currentPlayerId);
if (_currentPhase != null)
listener.setCurrentPhase(_currentPhase);
listener.setTwilight(_twilightPool);
for (Map.Entry<String, Integer> stringIntegerEntry : _playerPosition.entrySet())
listener.setPlayerPosition(stringIntegerEntry.getKey(), stringIntegerEntry.getValue());
for (List<PhysicalCardImpl> physicalCards : _inPlay.values())
for (PhysicalCardImpl physicalCard : physicalCards)
listener.cardCreated(physicalCard);
for (List<PhysicalCardImpl> physicalCards : _inPlay.values())
for (PhysicalCardImpl physicalCard : physicalCards)
listener.cardCreated(physicalCard);
List<PhysicalCardImpl> hand = _hands.get(playerId);
if (hand != null) {
for (PhysicalCardImpl physicalCard : hand)
listener.cardCreated(physicalCard);
List<PhysicalCardImpl> hand = _hands.get(playerId);
if (hand != null) {
for (PhysicalCardImpl physicalCard : hand)
listener.cardCreated(physicalCard);
}
for (Skirmish assignment : _assignments)
listener.addAssignment(assignment.getFellowshipCharacter(), assignment.getShadowCharacters());
if (_skirmish != null)
listener.startSkirmish(_skirmish.getFellowshipCharacter(), _skirmish.getShadowCharacters());
for (Map.Entry<PhysicalCard, Map<Token, Integer>> physicalCardMapEntry : _cardTokens.entrySet()) {
PhysicalCard card = physicalCardMapEntry.getKey();
for (Map.Entry<Token, Integer> tokenIntegerEntry : physicalCardMapEntry.getValue().entrySet())
listener.addTokens(card, tokenIntegerEntry.getKey(), tokenIntegerEntry.getValue());
}
}
for (Skirmish assignment : _assignments)
listener.addAssignment(assignment.getFellowshipCharacter(), assignment.getShadowCharacters());
if (_skirmish != null)
listener.startSkirmish(_skirmish.getFellowshipCharacter(), _skirmish.getShadowCharacters());
for (Map.Entry<PhysicalCard, Map<Token, Integer>> physicalCardMapEntry : _cardTokens.entrySet()) {
PhysicalCard card = physicalCardMapEntry.getKey();
for (Map.Entry<Token, Integer> tokenIntegerEntry : physicalCardMapEntry.getValue().entrySet())
listener.addTokens(card, tokenIntegerEntry.getKey(), tokenIntegerEntry.getValue());
}
for (Map.Entry<String, String> playerLoseReason : _losers.entrySet())
listener.sendMessage(playerLoseReason.getKey() + " lost due to: " + playerLoseReason.getValue());
if (_winnerPlayerId != null)
listener.sendMessage(_winnerPlayerId + " is the winner due to: " + _winReason);
}
private boolean isZonePublic(Zone zone) {

View File

@@ -21,4 +21,6 @@ public interface LotroGame {
public void playerWon(String currentPlayerId, String reason);
public void playerLost(String currentPlayerId, String reason);
public String getWinnerPlayerId();
}

View File

@@ -6,6 +6,6 @@ import com.gempukku.lotro.logic.timing.UnrespondableEffect;
public class CorruptRingBearerEffect extends UnrespondableEffect {
@Override
public void doPlayEffect(LotroGame game) {
game.getGameState().setLoserPlayerId(game.getGameState().getCurrentPlayerId(), "The Ring-Bearer is corrupted by a card effect");
game.playerLost(game.getGameState().getCurrentPlayerId(), "The Ring-Bearer is corrupted by a card effect");
}
}

View File

@@ -30,10 +30,18 @@ public class DefaultLotroGame implements LotroGame {
private Map<String, GameStateListener> _gameStateListeners = new HashMap<String, GameStateListener>();
private GameResultListener _gameResultListener;
private Set<String> _allPlayers;
private String _winnerPlayerId;
private String _winReason;
private Map<String, String> _losers = new HashMap<String, String>();
public DefaultLotroGame(Map<String, LotroDeck> decks, UserFeedback userFeedback, GameResultListener gameResultListener, final LotroCardBlueprintLibrary library) {
_gameResultListener = gameResultListener;
_actionStack = new ActionStack();
_allPlayers = decks.keySet();
_actionsEnvironment = new DefaultActionsEnvironment(this, _actionStack);
final Map<String, List<String>> cards = new HashMap<String, List<String>>();
@@ -49,11 +57,13 @@ public class DefaultLotroGame implements LotroGame {
cards.put(playerId, deck);
}
_gameState = new GameState();
_turnProcedure = new TurnProcedure(this, decks.keySet(), userFeedback, _actionStack,
new PlayerOrderFeedback() {
@Override
public void setPlayerOrder(PlayerOrder playerOrder, String firstPlayer) {
_gameState = new GameState(playerOrder, firstPlayer, cards, library);
_gameState.init(playerOrder, firstPlayer, cards, library);
for (Map.Entry<String, GameStateListener> stringGameStateListenerEntry : _gameStateListeners.entrySet())
_gameState.addGameStateListener(stringGameStateListenerEntry.getKey(), stringGameStateListenerEntry.getValue());
_gameStateListeners = null;
@@ -76,22 +86,33 @@ public class DefaultLotroGame implements LotroGame {
}
@Override
public void playerWon(String currentPlayerId, String reason) {
_gameState.setWinnerPlayerId(currentPlayerId, reason);
public String getWinnerPlayerId() {
return _winnerPlayerId;
}
@Override
public void playerWon(String playerId, String reason) {
_winnerPlayerId = playerId;
_winReason = reason;
if (_gameState != null)
_gameState.sendMessage(_winnerPlayerId + " is the winner due to: " + reason);
if (_gameResultListener != null) {
Set<String> losers = new HashSet<String>(_gameState.getPlayerOrder().getAllPlayers());
losers.remove(currentPlayerId);
_gameResultListener.gameFinished(currentPlayerId, losers);
Set<String> losers = new HashSet<String>(_allPlayers);
losers.remove(_winnerPlayerId);
_gameResultListener.gameFinished(_winnerPlayerId, losers, reason);
}
}
@Override
public void playerLost(String currentPlayerId, String reason) {
String winner = _gameState.setLoserPlayerId(currentPlayerId, reason);
if (winner != null && _gameResultListener != null) {
Set<String> losers = new HashSet<String>(_gameState.getPlayerOrder().getAllPlayers());
losers.remove(winner);
_gameResultListener.gameFinished(winner, losers);
public void playerLost(String playerId, String reason) {
_losers.put(playerId, reason);
if (_gameState != null)
_gameState.sendMessage(playerId + " lst due to: " + reason);
if (_losers.size() + 1 == _allPlayers.size()) {
List<String> allPlayers = new LinkedList<String>(_allPlayers);
allPlayers.removeAll(_losers.keySet());
playerWon(allPlayers.get(0), "Last remaining player in game");
}
}

View File

@@ -3,5 +3,5 @@ package com.gempukku.lotro.logic.timing;
import java.util.Set;
public interface GameResultListener {
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds);
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds, String reason);
}

View File

@@ -35,7 +35,7 @@ public class TurnProcedure {
}
public void carryOutPendingActionsUntilDecisionNeeded() {
while (!_userFeedback.hasPendingDecisions() && (_game.getGameState() == null || _game.getGameState().getWinnerPlayerId() == null)) {
while (!_userFeedback.hasPendingDecisions() && _game.getWinnerPlayerId() == null) {
if (_actionStack.isEmpty()) {
if (_playedGameProcess) {
_gameProcess = _gameProcess.getNextProcess();

View File

@@ -1,6 +1,7 @@
package com.gempukku.lotro.game;
import com.gempukku.lotro.common.CardType;
import com.gempukku.lotro.common.Phase;
import com.gempukku.lotro.game.formats.LotroFormat;
import com.gempukku.lotro.game.state.GameState;
import com.gempukku.lotro.game.state.Skirmish;
@@ -46,17 +47,16 @@ public class LotroGameMediator {
}
public String getGameStatus() {
if (_lotroGame.getGameState() == null)
return "Preparation";
if (_lotroGame.getGameState().getWinnerPlayerId() != null)
if (_lotroGame.getWinnerPlayerId() != null)
return "Finished";
if (_lotroGame.getGameState().getCurrentPhase() == Phase.GAME_SETUP)
return "Preparation";
return "Playing";
}
public synchronized String produceCardInfo(String participantId, int cardId) {
StringBuilder sb = new StringBuilder();
PhysicalCard card = _lotroGame.getGameState().findCardById(cardId);
if (card == null)
return null;
@@ -104,7 +104,7 @@ public class LotroGameMediator {
}
}
if (_lotroGame.getGameState() != null && _lotroGame.getGameState().getWinnerPlayerId() == null) {
if (_lotroGame.getGameState() != null && _lotroGame.getWinnerPlayerId() == null) {
for (Map.Entry<String, Long> playerDecision : _decisionQuerySentTimes.entrySet()) {
String playerId = playerDecision.getKey();
long decisionSent = playerDecision.getValue();

View File

@@ -111,8 +111,8 @@ public class LotroServer extends AbstractServer {
LotroGameMediator lotroGameMediator = new LotroGameMediator(lotroFormat, participants, _lotroCardBlueprintLibrary,
new GameResultListener() {
@Override
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds) {
log.debug("Game finished, winner is: " + winnerPlayerId);
public void gameFinished(String winnerPlayerId, Set<String> loserPlayerIds, String reason) {
log.debug("Game finished, winner is - " + winnerPlayerId + " due to: " + reason);
synchronized (_finishedGamesTime) {
_finishedGamesTime.put(gameId, new Date());
}