package ch.zhaw.catan; import ch.zhaw.catan.games.ThreePlayerStandard; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import java.awt.*; import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.*; /** * This class contains some basic tests for the {@link SiedlerGame} class *

*

DO NOT MODIFY THIS CLASS

* * @author tebe */ public class SiedlerGameTestBasic { private final static int DEFAULT_WINPOINTS = 5; private final static int DEFAULT_NUMBER_OF_PLAYERS = 3; /** * Tests whether the functionality for switching to the next/previous player * works as expected for different numbers of players. * * @param numberOfPlayers the number of players */ @ParameterizedTest @ValueSource(ints = {2, 3, 4}) public void requirementPlayerSwitching(int numberOfPlayers) { SiedlerGame model = new SiedlerGame(DEFAULT_WINPOINTS, numberOfPlayers); assertTrue(numberOfPlayers == model.getPlayerFactions().size(), "Wrong number of players returned by getPlayers()"); //Switching forward for (int i = 0; i < numberOfPlayers; i++) { assertEquals(Config.Faction.values()[i], model.getCurrentPlayerFaction(), "Player order does not match order of Faction.values()"); model.switchToNextPlayer(); } assertEquals(Config.Faction.values()[0], model.getCurrentPlayerFaction(), "Player wrap-around from last player to first player did not work."); //Switching backward for (int i = numberOfPlayers - 1; i >= 0; i--) { model.switchToPreviousPlayer(); assertEquals(Config.Faction.values()[i], model.getCurrentPlayerFaction(), "Switching players in reverse order does not work as expected."); } } /** * Tests whether the game board meets the required layout/land placement. */ @Test public void requirementLandPlacementTest() { SiedlerGame model = new SiedlerGame(DEFAULT_WINPOINTS, DEFAULT_NUMBER_OF_PLAYERS); assertTrue(Config.getStandardLandPlacement().size() == model.getBoard().getFields().size(), "Check if explicit init must be done (violates spec): " + "modify initializeSiedlerGame accordingly."); for (Map.Entry e : Config.getStandardLandPlacement().entrySet()) { assertEquals(e.getValue(), model.getBoard().getField(e.getKey()), "Land placement does not match default placement."); } } /** * Tests whether the {@link ThreePlayerStandard#getAfterSetupPhase(int)}} game board is not empty (returns * an object) at positions where settlements and roads have been placed. */ @Test public void requirementSettlementAndRoadPositionsOccupiedThreePlayerStandard() { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhase(DEFAULT_WINPOINTS); assertEquals(DEFAULT_NUMBER_OF_PLAYERS, model.getPlayerFactions().size()); for (Config.Faction f : model.getPlayerFactions()) { assertTrue(model.getBoard().getCorner(ThreePlayerStandard.INITIAL_SETTLEMENT_POSITIONS.get(f).first) != null); assertTrue(model.getBoard().getCorner(ThreePlayerStandard.INITIAL_SETTLEMENT_POSITIONS.get(f).second) != null); assertTrue(model.getBoard().getEdge(ThreePlayerStandard.INITIAL_SETTLEMENT_POSITIONS.get(f).first, ThreePlayerStandard.INITIAL_ROAD_ENDPOINTS.get(f).first) != null); assertTrue(model.getBoard().getEdge(ThreePlayerStandard.INITIAL_SETTLEMENT_POSITIONS.get(f).second, ThreePlayerStandard.INITIAL_ROAD_ENDPOINTS.get(f).second) != null); } } /** * Checks that the resource card payout for different dice values matches * the expected payout for the game state {@link ThreePlayerStandard#getAfterSetupPhase(int)}}. * * Note, that for the test to work, the {@link Map} returned by {@link SiedlerGame#throwDice(int)} * must contain a {@link List} with resource cards (empty {@link List}, if the player gets none) * for each of the players. * * @param diceValue the dice value */ @ParameterizedTest @ValueSource(ints = {2, 3, 4, 5, 6, 8, 9, 10, 11, 12}) public void requirementDiceThrowResourcePayoutThreePlayerStandardTest(int diceValue) { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhase(DEFAULT_WINPOINTS); Map> expectd = ThreePlayerStandard.INITIAL_DICE_THROW_PAYOUT.get(diceValue); Map> actual = model.throwDice(diceValue); assertEquals(ThreePlayerStandard.INITIAL_DICE_THROW_PAYOUT.get(diceValue), model.throwDice(diceValue)); } /** * Tests whether the resource card stock of the players matches the expected stock * for the game state {@link ThreePlayerStandard#getAfterSetupPhase(int)}}. */ @Test public void requirementPlayerResourceCardStockAfterSetupPhase() { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhase(DEFAULT_WINPOINTS); assertPlayerResourceCardStockEquals(model, ThreePlayerStandard.INITIAL_PLAYER_CARD_STOCK); } /** * Tests whether the resource card stock of the players matches the expected stock * for the game state {@link ThreePlayerStandard#getAfterSetupPhaseAlmostEmptyBank(int)}}. */ @Test public void requirementPlayerResourceCardStockAfterSetupPhaseAlmostEmptyBank() { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhaseAlmostEmptyBank(DEFAULT_WINPOINTS); assertPlayerResourceCardStockEquals(model, ThreePlayerStandard.BANK_ALMOST_EMPTY_RESOURCE_CARD_STOCK); } /** * Tests whether the resource card stock of the players matches the expected stock * for the game state {@link ThreePlayerStandard#getAfterSetupPhaseAlmostEmptyBank(int)}}. */ @Test public void requirementPlayerResourceCardStockPlayerOneReadyToBuildFifthSettlement() { SiedlerGame model = ThreePlayerStandard.getPlayerOneReadyToBuildFifthSettlement(DEFAULT_WINPOINTS); assertPlayerResourceCardStockEquals(model, ThreePlayerStandard.PLAYER_ONE_READY_TO_BUILD_FIFTH_SETTLEMENT_RESOURCE_CARD_STOCK); } /** * Throws each dice value except 7 once and tests whether the resource * card stock of the players matches the expected stock. */ @Test public void requirementDiceThrowPlayerResourceCardStockUpdateTest() { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhase(DEFAULT_WINPOINTS); for(int i : List.of(2, 3, 4, 5, 6, 8, 9, 10, 11, 12)) { model.throwDice(i); } Map> expected = Map.of( Config.Faction.values()[0], Map.of(Config.Resource.GRAIN, 1, Config.Resource.WOOL, 2, Config.Resource.BRICK, 2, Config.Resource.ORE, 1, Config.Resource.LUMBER, 1), Config.Faction.values()[1], Map.of(Config.Resource.GRAIN, 1, Config.Resource.WOOL, 5, Config.Resource.BRICK, 0, Config.Resource.ORE, 0, Config.Resource.LUMBER, 0), Config.Faction.values()[2], Map.of(Config.Resource.GRAIN, 0, Config.Resource.WOOL, 0, Config.Resource.BRICK, 2, Config.Resource.ORE, 0, Config.Resource.LUMBER, 1)); assertPlayerResourceCardStockEquals(model, expected); } private void assertPlayerResourceCardStockEquals(SiedlerGame model, Map> expected) { for (int i = 0; i < expected.keySet().size(); i++) { Config.Faction f = model.getCurrentPlayerFaction(); for (Config.Resource r : Config.Resource.values()) { assertEquals(expected.get(f).get(r), model.getCurrentPlayerResourceStock(r), "Resource card stock of player " + i + " [faction " + f + "] for resource type " + r + " does not match."); } model.switchToNextPlayer(); } } /** * Tests whether player one can build two roads starting in game state * {@link ThreePlayerStandard#getAfterSetupPhaseAlmostEmptyBank(int)}. */ @Test public void requirementBuildRoad() { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhaseAlmostEmptyBank(DEFAULT_WINPOINTS); assertTrue(model.buildRoad(new Point(6, 6), new Point(6, 4))); assertTrue(model.buildRoad(new Point(6, 4), new Point(7, 3))); } /** * Tests whether player one can build a road and a settlement starting in game state * {@link ThreePlayerStandard#getAfterSetupPhaseAlmostEmptyBank(int)}. */ @Test public void requirementBuildSettlement() { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhaseAlmostEmptyBank(DEFAULT_WINPOINTS); assertTrue(model.buildRoad(new Point(9, 15), new Point(9, 13))); assertTrue(model.buildSettlement(new Point(9, 13))); } /** * Tests whether payout with multiple settlements of the same player at one field works * {@link ThreePlayerStandard#getAfterSetupPhaseAlmostEmptyBank(int)}. */ @Test public void requirementTwoSettlementsSamePlayerSameFieldResourceCardPayout() { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhase(DEFAULT_WINPOINTS); for(int diceValue : List.of(2, 6, 6, 11)){ model.throwDice(diceValue); } assertTrue(model.buildRoad(new Point(6, 6), new Point(7, 7))); assertTrue(model.buildSettlement(new Point(7, 7))); assertEquals(List.of(Config.Resource.ORE, Config.Resource.ORE), model.throwDice(4).get(model.getCurrentPlayerFaction())); } /** * Tests whether player one can build a city starting in game state * {@link ThreePlayerStandard#getAfterSetupPhaseAlmostEmptyBank(int)}. */ @Test public void requirementBuildCity() { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhaseAlmostEmptyBank(DEFAULT_WINPOINTS); assertTrue(model.buildCity(new Point(10, 16))); } /** * Tests whether player two can trade in resources with the bank and has the * correct number of resource cards afterwards. The test starts from game state * {@link ThreePlayerStandard#getAfterSetupPhaseAlmostEmptyBank(int)}. */ @Test public void requirementCanTradeFourToOneWithBank() { SiedlerGame model = ThreePlayerStandard.getAfterSetupPhaseAlmostEmptyBank(DEFAULT_WINPOINTS); model.switchToNextPlayer(); Map expectedResourceCards = ThreePlayerStandard.BANK_ALMOST_EMPTY_RESOURCE_CARD_STOCK.get(model.getCurrentPlayerFaction()); assertEquals(expectedResourceCards.get(Config.Resource.WOOL), model.getCurrentPlayerResourceStock(Config.Resource.WOOL)); assertEquals(expectedResourceCards.get(Config.Resource.LUMBER), model.getCurrentPlayerResourceStock(Config.Resource.LUMBER)); model.tradeWithBankFourToOne(Config.Resource.WOOL, Config.Resource.LUMBER); int cardsOffered = 4; int cardsReceived = 1; assertEquals(expectedResourceCards.get(Config.Resource.WOOL)-cardsOffered, model.getCurrentPlayerResourceStock(Config.Resource.WOOL)); assertEquals(expectedResourceCards.get(Config.Resource.LUMBER)+cardsReceived, model.getCurrentPlayerResourceStock(Config.Resource.LUMBER)); } /*** * This test is not actually a test and should be removed. However, * we leave it in for you to have a quick and easy way to look at the * game board produced by {@link ThreePlayerStandard#getAfterSetupPhase(int)}, * augmented by annotations, which you won't need since we do not ask for * more advanced trading functionality using harbours. */ @Disabled @Test public void print(){ SiedlerGame model = ThreePlayerStandard.getAfterSetupPhase(DEFAULT_WINPOINTS); model.getBoard().addFieldAnnotation(new Point(6, 8),new Point(6, 6), "N "); model.getBoard().addFieldAnnotation(new Point(6, 8),new Point(5, 7), "NE"); model.getBoard().addFieldAnnotation(new Point(6, 8),new Point(5, 9), "SE"); model.getBoard().addFieldAnnotation(new Point(6, 8),new Point(6, 10), "S "); model.getBoard().addFieldAnnotation(new Point(6, 8),new Point(7, 7), "NW"); model.getBoard().addFieldAnnotation(new Point(6, 8),new Point(7, 9), "SW"); System.out.println(new SiedlerBoardTextView(model.getBoard()).toString()); } }