diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java index 4da7f49..c04e25b 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -157,8 +157,9 @@ public class Game implements Serializable { * @throws IllegalArgumentException if {@code nPlayers < 0} or {@code nPlayers > 5}. */ public Game(int nPlayers) throws IllegalArgumentException{ - if(nPlayers < 0||nPlayers > 5) + if(nPlayers !=0 && (nPlayers < 2 || nPlayers > 5)) { throw new IllegalArgumentException(); + } this.nPlayers = nPlayers; board=new Board(nPlayers); slotMap = new LinkedHashMap<>(); @@ -406,7 +407,7 @@ public class Game implements Serializable { { return false; } - + if(!player.equals(currentState.getCurrentPlayer())) { return false; @@ -497,8 +498,8 @@ public class Game implements Serializable { else { return false; } - nextPlayerSetup(); OptionalCardQueue.removeIf(x->x.equals(player)); + nextPlayerSetup(); return true; } @@ -588,7 +589,7 @@ public class Game implements Serializable { { OptionalCardQueue.add(e.getKey()); } - currentState.PlayerUpdate(OptionalCardQueue.remove(), null); + currentState.PlayerUpdate(OptionalCardQueue.poll(), null); if(currentState.getCurrentPlayer()==null) { currentState.GameStageUpdate(GameStages.RESOLVING_EVENT); @@ -605,14 +606,27 @@ public class Game implements Serializable { return; } + return; } } - if(GameStages.OPTIONAL_CARD_EFFECT==currentState.getGameStage()) { - currentState.PlayerUpdate(OptionalCardQueue.remove(), null); - if(currentState.getCurrentPlayer()==null) - { - currentState.GameStageUpdate(GameStages.RESOLVING_EVENT); + if (GameStages.OPTIONAL_CARD_EFFECT == currentState.getGameStage()) { + Player optionalPlayer = OptionalCardQueue.poll(); + + if (optionalPlayer != null) { + currentState.PlayerUpdate(optionalPlayer, null); + return; } + + currentState.GameStageUpdate(GameStages.RESOLVING_EVENT); + + if (currentState.getRound() < 10) { + nextRound(); + } else { + EventResolution(); + currentState.GameStageUpdate(GameStages.ENDING); + endGame(); + } + } } @@ -657,9 +671,13 @@ public class Game implements Serializable { { currentState.GameStageUpdate(GameStages.ENDING); endGame(); + return; } - if(currentState.getEra()!= board.nextRound()) + + if(currentState.getEra()!= board.nextRound()) { currentState.EraUpdate(); + } + currentState.RoundUpdate(); } @@ -683,11 +701,28 @@ public class Game implements Serializable { * @param nPlayers the new configured number of players. * @return {@code true} if the number of players is updated, {@code false} otherwise. */ - public boolean setNPlayer(int nPlayers) - { - if(this.nPlayers!=0) + public boolean setNPlayer(int nPlayers) { + if (this.nPlayers != 0) { return false; - this.nPlayers=nPlayers; + } + + if (nPlayers < 2 || nPlayers > 5) { + return false; + } + + this.nPlayers = nPlayers; + + board = new Board(nPlayers); + + slotMap = new LinkedHashMap<>(); + for (Slot s : board.getSlotList()) { + slotMap.put(s, null); + } + + currentState = new CurrentState(); + playersList = new ArrayList<>(); + OptionalCardQueue = new LinkedList<>(); + return true; } diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java b/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java index 6f6d5ec..4709a9b 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java @@ -141,6 +141,87 @@ class GameTest { } } + private int slotIndexById(Game game, char slotId) { + it.polimi.ingsw.gc14.Model.GamePackage.Board board = getBoard(game); + List slots = board.getSlotList(); + + for (int i = 0; i < slots.size(); i++) { + if (slots.get(i).getSlotId() == slotId) { + return i; + } + } + + fail("No slot found with id: " + slotId); + return -1; + } + + private Player completeSlotChoiceAndAdvanceToPlayerOnSlot(Game game, char slotId) { + Player targetPlayer = game.getCurrentState().getCurrentPlayer(); + int targetSlotIndex = slotIndexById(game, slotId); + + assertTrue(game.SlotChoiceByIndex(targetPlayer, targetSlotIndex)); + + Set usedSlots = new HashSet<>(); + usedSlots.add(targetSlotIndex); + + int nextSlotIndex = 0; + + while (game.getCurrentState().getGameStage() == GameStages.SLOT_CHOICE) { + while (usedSlots.contains(nextSlotIndex)) { + nextSlotIndex++; + } + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertTrue(game.SlotChoiceByIndex(current, nextSlotIndex)); + usedSlots.add(nextSlotIndex); + } + + assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); + + int guard = 0; + + while (game.getCurrentState().getGameStage() == GameStages.RESOLVING_ACTIONS + && !targetPlayer.equals(game.getCurrentState().getCurrentPlayer()) + && guard < 20) { + guard++; + resolveOneMandatoryAction(game); + } + + assertTrue(guard < 20, "Possible infinite loop while reaching target player's slot."); + assertEquals(targetPlayer, game.getCurrentState().getCurrentPlayer()); + + return targetPlayer; + } + + private void resolveOptionalPhaseIfPresent(Game game) { + int guard = 0; + + while (game.getCurrentState().getGameStage() == GameStages.OPTIONAL_CARD_EFFECT && guard < 10) { + guard++; + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertTrue(game.NoOptionalCard(current)); + } + + assertTrue(guard < 10, "Possible infinite loop during optional phase."); + } + + private void playOneFullRound(Game game) { + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + + completeSlotChoice(game); + + assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); + + resolveAllMandatoryActions(game); + + resolveOptionalPhaseIfPresent(game); + } + @Test void constructorShouldInitializeGameCorrectly() { int nPlayers = 3; @@ -290,6 +371,7 @@ class GameTest { temp_player = players.poll(); assertEquals(temp_player, game.getCurrentState().getCurrentPlayer()); + int nCards = game.getUpperListTribeCards().size(); int countCards = 0; HashMap nCardsByType = new HashMap(); @@ -327,6 +409,17 @@ class GameTest { assertFalse(game.DrawUpperTribeCardByIndex(temp_player, remainingTribeIndex)); } + Player thirdPlayer = players.poll(); + assertNotNull(thirdPlayer); + assertEquals(thirdPlayer, game.getCurrentState().getCurrentPlayer()); + + while (game.getCurrentState().getGameStage() == GameStages.RESOLVING_ACTIONS + && thirdPlayer.equals(game.getCurrentState().getCurrentPlayer())) { + resolveOneMandatoryAction(game); + } + + assertNotEquals(thirdPlayer, game.getCurrentState().getCurrentPlayer()); + } @@ -584,13 +677,10 @@ class GameTest { Game game = new Game(3); addPlayers(game, 3, "lower_building_"); - completeSlotChoice(game); - Player current = game.getCurrentState().getCurrentPlayer(); + Player current = completeSlotChoiceAndAdvanceToPlayerOnSlot(game, 'D'); assertNotNull(current); - game.getCurrentState().PlayerUpdate(current, new Slot('D')); - it.polimi.ingsw.gc14.Model.GamePackage.Board board = getBoard(game); assertNotNull(board); @@ -714,13 +804,10 @@ class GameTest { Game game = new Game(3); addPlayers(game, 3, "no_lower_"); - completeSlotChoice(game); - Player current = game.getCurrentState().getCurrentPlayer(); + Player current = completeSlotChoiceAndAdvanceToPlayerOnSlot(game, 'C'); assertNotNull(current); - game.getCurrentState().PlayerUpdate(current, new Slot('C')); - int index = firstNonEventIndex(game.getLowerListTribeCards()); assertEquals(0, game.getCurrentState().getNLower()); @@ -732,13 +819,10 @@ class GameTest { Game game = new Game(3); addPlayers(game, 3, "lower_event_"); - completeSlotChoice(game); - Player current = game.getCurrentState().getCurrentPlayer(); + Player current = completeSlotChoiceAndAdvanceToPlayerOnSlot(game, 'B'); assertNotNull(current); - game.getCurrentState().PlayerUpdate(current, new Slot('B')); - it.polimi.ingsw.gc14.Model.GamePackage.Board board = getBoard(game); assertNotNull(board); @@ -754,13 +838,10 @@ class GameTest { Game game = new Game(3); addPlayers(game, 3, "no_upper_building_"); - completeSlotChoice(game); - Player current = game.getCurrentState().getCurrentPlayer(); + Player current = completeSlotChoiceAndAdvanceToPlayerOnSlot(game, 'B'); assertNotNull(current); - game.getCurrentState().PlayerUpdate(current, new Slot('B')); - it.polimi.ingsw.gc14.Model.GamePackage.Board board = getBoard(game); assertNotNull(board); @@ -778,13 +859,10 @@ class GameTest { Game game = new Game(3); addPlayers(game, 3, "upper_buy_true_"); - completeSlotChoice(game); - Player current = game.getCurrentState().getCurrentPlayer(); + Player current = completeSlotChoiceAndAdvanceToPlayerOnSlot(game, 'F'); assertNotNull(current); - game.getCurrentState().PlayerUpdate(current, new Slot('F')); - it.polimi.ingsw.gc14.Model.GamePackage.Board board = getBoard(game); assertNotNull(board); @@ -803,30 +881,6 @@ class GameTest { assertEquals(1, game.getCurrentState().getNUpper()); } - @Test - void eventResolutionShouldNotCrashWithNormalAndSustenanceEvents() { - Game game = new Game(3); - - addPlayers(game, 3, "events_"); - - it.polimi.ingsw.gc14.Model.GamePackage.Board board = getBoard(game); - assertNotNull(board); - - board.lowerListTribe.clear(); - - board.lowerListTribe.add( - new it.polimi.ingsw.gc14.Model.Cards.TribeCards.Events.ShamanicRitual(1, 15, 7)); - - board.lowerListTribe.add( - new it.polimi.ingsw.gc14.Model.Cards.TribeCards.Events.Sustenance(1, 3)); - - game.getCurrentState().GameStageUpdate(GameStages.RESOLVING_EVENT); - - invokePrivateMethod(game, "EventResolution"); - - assertEquals(GameStages.RESOLVING_EVENT, game.getCurrentState().getGameStage()); - } - @Test void nextRoundShouldUpdateEraWhenBoardEraDiffersFromCurrentStateEra() { Game game = new Game(3); @@ -900,17 +954,30 @@ class GameTest { } @Test - void nextRoundAtRoundTenShouldNotIncreaseRoundAfterEndingGame() { + void fullGameShouldEndAfterTenRoundsUsingOnlyPublicGameFlow() { Game game = new Game(3); - for (int i = 0; i < 9; i++) { - game.getCurrentState().RoundUpdate(); + assertTrue(game.addPlayer(new Player("p1"))); + assertTrue(game.addPlayer(new Player("p2"))); + assertTrue(game.addPlayer(new Player("p3"))); + + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + + int guard = 0; + + while (game.getCurrentState().getGameStage() != GameStages.ENDED && guard < 20) { + guard++; + + playOneFullRound(game); + + assertTrue( + game.getCurrentState().getGameStage() == GameStages.SLOT_CHOICE + || game.getCurrentState().getGameStage() == GameStages.ENDED, + "After a full round, the game should either start the next slot choice phase or end." + ); } - assertEquals(10, game.getCurrentState().getRound()); - - invokePrivateMethod(game, "nextRound"); - + assertTrue(guard < 20, "Possible infinite loop while playing the full game."); assertEquals(GameStages.ENDED, game.getCurrentState().getGameStage()); assertEquals(10, game.getCurrentState().getRound()); } @@ -931,26 +998,30 @@ class GameTest { } @Test - void shouldNotCrashWhenOnlyOptionalPlayerSkipsOptionalCard() { + void roundShouldAdvanceAfterOnlyOptionalPlayerSkipsOptionalCard() { Game game = new Game(3); List players = addPlayers(game, 3, "single_optional_"); players.get(0).buildingCards.add(new BuildingCard(12, 1, 1, 0)); + int roundBefore = game.getCurrentState().getRound(); + completeSlotChoice(game); resolveActionsUntilOptionalCardEffect(game); Player current = game.getCurrentState().getCurrentPlayer(); assertNotNull(current); - assertDoesNotThrow(() -> assertTrue(game.NoOptionalCard(current))); + assertTrue(game.NoOptionalCard(current)); - assertNotEquals(GameStages.OPTIONAL_CARD_EFFECT, game.getCurrentState().getGameStage()); + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertEquals(roundBefore + 1, game.getCurrentState().getRound()); + assertNotNull(game.getCurrentState().getCurrentPlayer()); } @Test - void optionalPhaseShouldFinishAfterAllPlayersSkipOptionalCard() { + void roundShouldAdvanceAfterAllOptionalPlayersSkipOptionalCard() { Game game = new Game(3); Player p1 = new Player("p1"); @@ -963,24 +1034,27 @@ class GameTest { giveOptionalEffectToAllPlayers(p1, p2, p3); + int roundBefore = game.getCurrentState().getRound(); + completeSlotChoice(game); resolveActionsUntilOptionalCardEffect(game); - assertDoesNotThrow(() -> { - int guard = 0; + int guard = 0; - while (game.getCurrentState().getGameStage() == GameStages.OPTIONAL_CARD_EFFECT && guard < 10) { - guard++; + while (game.getCurrentState().getGameStage() == GameStages.OPTIONAL_CARD_EFFECT && guard < 10) { + guard++; - Player current = game.getCurrentState().getCurrentPlayer(); - assertNotNull(current); + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); - assertTrue(game.NoOptionalCard(current)); - } + assertTrue(game.NoOptionalCard(current)); + } - assertTrue(guard < 10, "Possible infinite loop during optional phase."); - assertNotEquals(GameStages.OPTIONAL_CARD_EFFECT, game.getCurrentState().getGameStage()); - }); + assertTrue(guard < 10, "Possible infinite loop during optional phase."); + + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertEquals(roundBefore + 1, game.getCurrentState().getRound()); + assertNotNull(game.getCurrentState().getCurrentPlayer()); }