+ * The class provides definitions such as for the type and number of resource + * cards or the number of available road elements per player. Furthermore, it + * provides a dice number to field and a field to land type mapping for the + * standard setup detailed here + *
+ * + * @author tebe + */ +public class Config { + // Minimum number of players + // Note: The max. number is equal to the number of factions (see Faction enum) + public static final int MIN_NUMBER_OF_PLAYERS = 2; + + // Initial thief position (on the desert field) + public static final Point INITIAL_THIEF_POSITION = new Point(7, 11); + + // Available factions + public enum Faction { + RED("rr"), BLUE("bb"), GREEN("gg"), YELLOW("yy"); + + private final String name; + + private Faction(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + } + + // RESOURCE CARD DECK + public static final Map+ * The enum provides information about the cost of a structure and how many of + * these structures are available per player. + *
+ */ + public enum Structure { + SETTLEMENT(List.of(Resource.LUMBER, Resource.BRICK, Resource.WOOL, Resource.GRAIN), + NUMBER_OF_SETTLEMENTS_PER_PLAYER), + CITY(List.of(Resource.ORE, Resource.ORE, Resource.ORE, Resource.GRAIN, Resource.GRAIN), + NUMBER_OF_CITIES_PER_PLAYER), + ROAD(List.of(Resource.LUMBER, Resource.BRICK), NUMBER_OF_ROADS_PER_PLAYER); + + private final List+ * Each list entry represents a resource card. The value of an entry (e.g., {@link Resource#LUMBER}) + * identifies the resource type of the card. + *
+ * + * @return the build costs + */ + public List
+ * The SiedlerGame class is responsible for maintaining the state of the game, including the {@link Player}s and their inventories,
+ * the {@link SiedlerBoard}, and the bank. It provides methods for performing actions such as rolling the dice, building {@link Structure}s,
+ * and trading {@link Resource}s.
+ */
+public class SiedlerGame {
+
+ static final int FOUR_TO_ONE_TRADE_OFFER = 4;
+ static final int FOUR_TO_ONE_TRADE_WANT = 1;
+ static final int THIEF_DICE_NUMBER = 7;
+
+ private static final List
+ * The order of the {@link Player}'s {@link Faction}s in the {@link List} must correspond to the order in which they play. Hence, the
+ * {@link Player} that sets the first {@link Settlement} must be at position 0 in the list etc. Important note: The {@link List} must contain the {@link Faction}s of active {@link Player}s only. The placement does not cost any {@link Resource} cards. If payout is set to true, for each adjacent resource-producing
+ * {@link Field}, a {@link Resource} card of the type of the {@link Resource} produced by the {@link Field} is taken from the {@link Bank} (if available)
+ * and added to the {@link Player}s' stock of {@link Resource} cards.
+ * A key action is the payout of the {@link Resource} cards to the {@link Player}s according to the payout rules of the game. This
+ * includes the"negative payout" in case a 7 is thrown and a player has more than
+ * {@link Config#MAX_CARDS_IN_HAND_NO_DROP} {@link Resource} cards.
+ *
+ * If a {@link Player} does not get {@link Resource} cards, the list for this {@link Player}s' {@link Faction} is an empty {@link List} (not
+ * {@code null})!.
+ *
+ * The payout rules of the game take into account factors such as, the number of {@link Resource} cards currently available
+ * in the {@link Bank}, {@link Settlement} types({@link Settlement} or {@link City}), and the number of {@link Player}s that should get {@link Resource} cards of a
+ * certain type (relevant if there are not enough left in the {@link Bank}).
+ * The {@link Settlement} can be built if:
+ * The {@link City} can be built if:
+ * The {@link Road} can be built if:
+ * Trades in {@link #FOUR_TO_ONE_TRADE_OFFER} {@link Resource} cards of the
+ * offered type for {@link #FOUR_TO_ONE_TRADE_WANT} {@link Resource} cards of the wanted type.
+ *
+ * The trade only works when {@link Bank} and {@link Player} possess the {@link Resource} cards for the trade before the trade is executed.
+ *
+ * Edges are non-directional and can be created by providing the two points that
+ * span an edge on the hex-grid defined by @see ch.zhaw.hexboard.HexBoard
+ *
+ * This class represents a simple generic hexagonal game board.
+ * The game board uses a fixed coordinate system which is structured as follows:
+ * Fields F and corners C can be retrieved
+ * using their coordinates ({@link java.awt.Point}) on the board. Edges can be
+ * retrieved using the coordinates of the two corners they connect.
+ *
+ * When created, the board is empty (no fields added). To add fields, the
+ * #{@link #addField(Point, Object)} function can be used. Edges and corners are
+ * automatically created when adding a field. They cannot be created/removed
+ * individually. When adding a field, edges and corners that were already
+ * created, e.g., because adding an adjacent field already created them, are
+ * left untouched.
+ *
+ * Fields, edges and corners can store an object of the type of the
+ * corresponding type parameter each.
+ *
+ * Furthermore, the hexagonal game board can store six additional objects, so
+ * called annotations, for each field. These objects are identified by the
+ * coordinates of the field and the corner. Hence, they can be thought of being
+ * located between the center and the respective corner. Or in other words,
+ * their positions correspond to the positions N, NW, SW, NE, NW, SE and NE in
+ * the below visualization of a field.
+ *
+ * If the specified corner is not a corner or none of the fields that touch this
+ * corner have a non-null data element, an empty list is returned.
+ *
+ * Each corner has three direct neighbors, except corners that are located at
+ * the border of the game board.
+ *
+ * Each corner has three edges connecting to it, except edges that are located
+ * at the border of the game board.
+ *
+ * It creates a textual representation of the {@link ch.zhaw.hexboard.HexBoard}
+ * that includes all defined fields, edges, corners and annotations.
+ *
+ * The textual representation does not contain the hex-grid as such but only the
+ * fields that actually exist on the hex-board. Note that if a field exists,
+ * also its corners and edges exist and are therefore shown in the textual
+ * representation.
+ *
+ * This class defines how edges, corners and fields look like (their "label").
+ * This is done as follows: In addition to edges, corners and field labels, the hex-board's field
+ * annotations are included too. If an annotation exists for one of the corners
+ * (N, NW, SW, S, SE, NE), which means that an associated data object exists, it
+ * is turned into a {@link ch.zhaw.hexboard.Label} with
+ * {@link #getAnnotationLabel(Object)}. Two examples of how that looks like are shown below. The first example shows
+ * a case with all edges, corners and the field with no data associated with
+ * them. The second one has all edges corner and the upper field label defined
+ * by calling the corresponding method for creating the Label for the associated
+ * data object. To override the default behavior, which creates a Label using the two first
+ * characters of the string returned by the toString() method of the
+ * edge/corner/field data object, you might override the respective methods.
+ *
+ * Finally, a field can be labeled with a lower label (LL) by providing a map of
+ * field coordinates and associated labels. An example of a representation with
+ * all field annotations, corner labels and field labels defined but default
+ * edges is the following:
+ * This method returns a single-line string with all corners and field
+ * annotations for a given y-coordinate. It produces the string by iterating
+ * over corner positions and appending per corner:
+ *
+ * "(CL) NE NW " for y%3==1 "(CL) SE SW " for y%3==0
+ *
+ * Corners/labels that do not exist are replaced by spaces.
+ * The main ideas for this setup were the following:
+ * The following resource cards should be in the stock of the bank:
+ * The stocks of the players should contain: Player 1: Player 2: Player 3: The game board should look as follows:
+ *
+ * And the player resource card stocks:
+ * Returns a siedler game after building four additional roads and two
+ * settlements after the setup phase with the resource cards and roads
+ * for player one ready to build a fifth settlement at {@link #PLAYER_ONE_READY_TO_BUILD_FIFTH_SETTLEMENT_FIFTH_SETTLEMENT_POSITION}
+ * The game board should look as follows: And the player resource card stocks:
+ * Additionally, the test creates a SiedlerGame instance with four players
+ * and tests that the methods correctly switch between all four players.
+ */
+ @Test
+ void switchMultiplePlayer() {
+ assertEquals(siedlerGame.getPlayerFactions().get(0), siedlerGame.getCurrentPlayerFaction());
+ siedlerGame.switchToNextPlayer();
+ assertEquals(siedlerGame.getPlayerFactions().get(1), siedlerGame.getCurrentPlayerFaction());
+ siedlerGame.switchToNextPlayer();
+ assertEquals(siedlerGame.getPlayerFactions().get(0), siedlerGame.getCurrentPlayerFaction());
+ siedlerGame.switchToPreviousPlayer();
+ siedlerGame.switchToPreviousPlayer();
+ assertEquals(siedlerGame.getPlayerFactions().get(0), siedlerGame.getCurrentPlayerFaction());
+
+ SiedlerGame siedlerGameFourPlayers = new SiedlerGame(REQUIRED_WINNING_SCORE, 4);
+
+ assertEquals(siedlerGameFourPlayers.getPlayerFactions().get(0), siedlerGameFourPlayers.getCurrentPlayerFaction());
+ siedlerGameFourPlayers.switchToNextPlayer();
+ siedlerGameFourPlayers.switchToNextPlayer();
+ siedlerGameFourPlayers.switchToNextPlayer();
+ siedlerGameFourPlayers.switchToNextPlayer();
+ assertEquals(siedlerGameFourPlayers.getPlayerFactions().get(0), siedlerGameFourPlayers.getCurrentPlayerFaction());
+ siedlerGameFourPlayers.switchToPreviousPlayer();
+ assertEquals(siedlerGameFourPlayers.getPlayerFactions().get(3), siedlerGameFourPlayers.getCurrentPlayerFaction());
+ }
+
+ /**
+ * This is a test method for the getPlayerFactions() method of the SiedlerGame class.
+ * It first calls the getPlayerFactions() method to retrieve the factions of the players in the game,
+ * then checks that the returned list is in the correct order and contains the expected factions.
+ * It also checks that the function returns an empty list when there are no players in the game.
+ */
+ @Test
+ void getPlayerFactions() {
+ List
+ * 1. Place invalid settlements
+ * 2. Place settlements on valid positions
+ * 3. Try to place settlements again
+ * 4. Check player Inventory after no payout
+ * 5. Compare player inventory with Player that got a payout
+ * 6. Check inventory of Player that got payout
+ */
+ @Test
+ void placeInitialSettlement() {
+ // Trying to place settlements on invalid positions
+ for (Point invalidSettlementPoint : invalidSettlementPoints) {
+ assertFalse(siedlerGame.placeInitialSettlement(invalidSettlementPoint, false));
+ }
+
+ // place settlements on valid positions
+ for (Point validSettlementPoint : validSettlementPoints) {
+ assertTrue(siedlerGame.placeInitialSettlement(validSettlementPoint, false));
+ }
+
+ // Trying to place settlements on same positions again.
+ for (Point validSettlementPoint : validSettlementPoints) {
+ assertFalse(siedlerGame.placeInitialSettlement(validSettlementPoint, false));
+ }
+
+ // Trying to place settlements next to previously placed settlement
+ assertFalse(siedlerGame.placeInitialSettlement(validRoadEndPoints.get(0), false));
+ assertFalse(siedlerGame.placeInitialSettlement(validRoadEndPoints.get(1), false));
+
+ assertFalse(siedlerGame.placeInitialSettlement(validRoadStartPoint, false));
+
+ Player playerBeforePlacement = siedlerGame.getCurrentPlayer();
+
+ assertEquals(0, playerBeforePlacement.getTotalAmountOfResources());
+
+ SiedlerGame siedlerGame2 = new SiedlerGame(REQUIRED_WINNING_SCORE, 2);
+
+ // place settlements on valid positions and payout resources
+ for (Point validSettlementPoint : validSettlementPoints) {
+ assertTrue(siedlerGame2.placeInitialSettlement(validSettlementPoint, true));
+ }
+
+ assertNotEquals(playerBeforePlacement.getTotalAmountOfResources(), siedlerGame2.getCurrentPlayer().getTotalAmountOfResources());
+ assertEquals(11, siedlerGame2.getCurrentPlayer().getTotalAmountOfResources());
+ }
+
+ /**
+ * This test first attempts to place a road without any settlements,
+ * then creates settlements and attempts to place roads at valid locations.
+ * It also attempts to place roads at invalid locations and from a different player's perspective.
+ */
+ @Test
+ void placeInitialRoad() {
+ // No settlements exist
+ assertFalse(siedlerGame.placeInitialRoad(validRoadStartPoint, validRoadEndPoints.get(0)));
+ assertFalse(siedlerGame.placeInitialRoad(waterEdge.get(0), waterEdge.get(1)));
+
+ // Create Settlements
+ for (Point settlementPoint : validSettlementPoints) {
+ siedlerGame.placeInitialSettlement(settlementPoint, false);
+ }
+
+ // Place roads at valid Points
+ assertTrue(siedlerGame.placeInitialRoad(validRoadStartPoint, validRoadEndPoints.get(0)));
+ assertTrue(siedlerGame.placeInitialRoad(validRoadStartPoint, validRoadEndPoints.get(1)));
+
+ //Place invalid roads
+ assertFalse(siedlerGame.placeInitialRoad(validRoadStartPoint, invalidRoadEndPoints.get(0)));
+ assertFalse(siedlerGame.placeInitialRoad(invalidSettlementPoints.get(0), validRoadEndPoints.get(0)));
+
+ //Place road of different Player
+ siedlerGame.switchToNextPlayer();
+ assertFalse(siedlerGame.placeInitialRoad(validRoadStartPoint, validRoadEndPoints.get(2)));
+ }
+
+ /**
+ * This method tests the buildSettlement() method of the SiedlerGame class. The test first adds some resources to
+ * the current player's inventory, and then attempts to build a settlement at an invalid location.
+ * It then places an initial settlement and connects it to two roads, and then attempts to build another settlement
+ * at an invalid location and a valid location. It uses the assertFalse() and assertTrue() methods to verify that
+ * the buildSettlement() method returns false when it is called with an invalid location,and true when it is called
+ * with a valid location.
+ */
+ @Test
+ void buildSettlement() {
+ // Adding non-critical Resources
+ siedlerGame.getCurrentPlayer().increaseInventory(Config.Structure.SETTLEMENT.getCostsAsIntegerMap());
+ siedlerGame.getCurrentPlayer().increaseInventory(Config.Structure.SETTLEMENT.getCostsAsIntegerMap());
+
+ // No Settlement / Roads exist yet to build a settlement
+ assertFalse(siedlerGame.buildSettlement(invalidSettlementPoints.get(0)));
+ assertFalse(siedlerGame.buildSettlement(validSettlementPoints.get(0)));
+
+ // Place Settlement with connecting Roads to new settlement position
+ siedlerGame.placeInitialSettlement(validSettlementPoints.get(0), false);
+ siedlerGame.placeInitialRoad(validRoadStartPoint, validRoadEndPoints.get(0));
+ siedlerGame.placeInitialRoad(validRoadStartPoint, validRoadEndPoints.get(1));
+
+ // No resources are available to build Settlement
+ assertFalse(siedlerGame.buildSettlement(invalidSettlementPoints.get(0)));
+ assertTrue(siedlerGame.buildSettlement(validSettlementPoints.get(1)));
+ }
+
+ /**
+ * This method tests the buildSettlement() method of the SiedlerGame class in the case where the player does not
+ * have enough resources to build a settlement. The test first adds some resources to the current player's inventory,
+ * but not enough to build a settlement. It then attempts to build a settlement at an invalid location and a valid
+ * location, and uses the assertFalse() method to verify that the buildSettlement() method returns false in both
+ * cases. This test ensures that the buildSettlement() method correctly checks the player's inventory to make sure
+ * that they have enough resources to build a settlement, and returns the correct value if they do not.
+ */
+ @Test
+ void buildSettlementWithInsufficientResources() {
+ // Adding non-critical Resources
+ siedlerGame.getCurrentPlayer().increaseInventory(Config.Structure.CITY.getCostsAsIntegerMap());
+ siedlerGame.getCurrentPlayer().increaseInventory(Config.Structure.CITY.getCostsAsIntegerMap());
+
+ // No Settlement / Roads exist yet to build a settlement
+ assertFalse(siedlerGame.buildSettlement(invalidSettlementPoints.get(0)));
+ assertFalse(siedlerGame.buildSettlement(validSettlementPoints.get(0)));
+
+ // Place Settlement with connecting Roads to new settlement position
+ siedlerGame.placeInitialSettlement(validSettlementPoints.get(0), false);
+ siedlerGame.placeInitialRoad(validRoadStartPoint, validRoadEndPoints.get(0));
+ siedlerGame.placeInitialRoad(validRoadStartPoint, validRoadEndPoints.get(1));
+
+ // No resources are available to build Settlement
+ assertFalse(siedlerGame.buildSettlement(invalidSettlementPoints.get(0)));
+ assertFalse(siedlerGame.buildSettlement(validSettlementPoints.get(1)));
+ }
+
+ /**
+ * This test first attempts to build a city without sufficient resources or at an invalid location,
+ * then adds resources to the player's inventory and attempts to build a city again at both valid and invalid locations.
+ * Finally, it builds a city at a valid location and checks that the function returns true to indicate success.
+ */
+ @Test
+ void buildCity() {
+ siedlerGame.placeInitialSettlement(validSettlementPoints.get(0), false);
+
+ // Try to build City without resources
+ assertFalse(siedlerGame.buildCity(validSettlementPoints.get(0)));
+
+ // Try to build City without resources at wrong position
+ assertFalse(siedlerGame.buildCity(validSettlementPoints.get(1)));
+ assertFalse(siedlerGame.buildCity(invalidSettlementPoints.get(0)));
+
+ siedlerGame.getCurrentPlayer().increaseInventory(Config.Structure.CITY.getCostsAsIntegerMap());
+
+ // Try to build City with resources at wrong position
+ assertFalse(siedlerGame.buildCity(validSettlementPoints.get(1)));
+ assertFalse(siedlerGame.buildCity(invalidSettlementPoints.get(0)));
+ // Build city at correct position
+ assertTrue(siedlerGame.buildCity(validSettlementPoints.get(0)));
+ }
+
+ /**
+ * This test first checks that a road cannot be built without sufficient resources or settlements,
+ * then adds resources to the player's inventory
+ * and attempts to build roads from a valid starting point to both valid and invalid endpoints.
+ */
+ @Test
+ void buildRoad() {
+ Player player = siedlerGame.getCurrentPlayer();
+ // Player doesn't have enough resources && no settlements exist
+ assertFalse(siedlerGame.buildRoad(validRoadStartPoint, validRoadEndPoints.get(0)));
+
+ buildInitialSettlements();
+
+ // Player doesn't have enough resources but settlements exist
+ assertFalse(siedlerGame.buildRoad(validRoadStartPoint, validRoadEndPoints.get(0)));
+ player.increaseInventoryItem(Config.Resource.LUMBER, 2);
+ player.increaseInventoryItem(Config.Resource.BRICK, 2);
+ // Player has enough Resources for Road placement
+ assertFalse(siedlerGame.buildRoad(validRoadStartPoint, invalidRoadEndPoints.get(0)));
+ assertTrue(siedlerGame.buildRoad(validRoadStartPoint, validRoadEndPoints.get(0)));
+ assertFalse(siedlerGame.buildRoad(validRoadStartPoint, invalidRoadEndPoints.get(1)));
+ assertTrue(siedlerGame.buildRoad(validRoadStartPoint, validRoadEndPoints.get(1)));
+ }
+
+ /**
+ * This test first asserts that trading with no resources will fail,
+ * then adds resources to the player's inventory and trades them for other resources from the bank
+ * until the bank runs out of the desired resource.
+ * Finally, it checks that the bank's and player's inventories have been updated as expected.
+ */
+ @Test
+ void tradeWithBankFourToOne() {
+ // Try trading with no resources
+ assertFalse(siedlerGame.tradeWithBankFourToOne(Config.Resource.WOOL, Config.Resource.LUMBER));
+
+ siedlerGame.getCurrentPlayer().increaseInventoryItem(Config.Resource.WOOL, INITIAL_RESOURCE_CARDS_BANK.get(Config.Resource.WOOL) * 4);
+
+ // Trade for all Bank resources
+ while (siedlerGame.getBank().getAmountOfResource(Config.Resource.LUMBER) > 0) {
+ assertTrue(siedlerGame.tradeWithBankFourToOne(Config.Resource.WOOL, Config.Resource.LUMBER));
+ }
+
+ // Bank has no Lumber but all Wool traded. And player has all Lumber but no Wool.
+ assertFalse(siedlerGame.tradeWithBankFourToOne(Config.Resource.WOOL, Config.Resource.LUMBER));
+ assertEquals(0, siedlerGame.getBank().getAmountOfResource(Config.Resource.LUMBER));
+ assertEquals(INITIAL_RESOURCE_CARDS_BANK.get(Config.Resource.WOOL) * 5, siedlerGame.getBank().getAmountOfResource(Config.Resource.WOOL));
+ assertEquals(0, siedlerGame.getCurrentPlayer().getAmountOfResource(Config.Resource.WOOL));
+ assertEquals(INITIAL_RESOURCE_CARDS_BANK.get(Config.Resource.LUMBER), siedlerGame.getCurrentPlayer().getAmountOfResource(Config.Resource.LUMBER));
+ }
+
+ /**
+ * This is a JUnit test for the getWinner method.
+ * It first asserts that getWinner returns null before any structures have been built,
+ * indicating that no winner has been determined yet.
+ *
+ * Next, it rolls the dice four times, which should distribute resources to the players based on the numbers rolled and the placement of their settlements on the map.
+ * It then checks that the players received the expected number of resources.
+ *
+ * Finally, it asserts that the sum of the resources in the bank and the resources of the two players is still equal to the initial bank inventory.
+ */
+ @Test
+ void processPayoutResource() {
+ buildInitialSettlements();
+
+ int initialBankInventory = getInitialBankInventory();
+
+ assertEquals(initialBankInventory, siedlerGame.getBank().getTotalAmountOfResources() +
+ siedlerGame.getCurrentPlayers().get(0).getTotalAmountOfResources() +
+ siedlerGame.getCurrentPlayers().get(1).getTotalAmountOfResources());
+
+ // Check starting values for Settlement placement
+ // Player 1 = 3 Resources
+ // Player 2 = 3 Resources
+
+ siedlerGame.processDiceRoll(4);
+ siedlerGame.processDiceRoll(9);
+ siedlerGame.processDiceRoll(11);
+ siedlerGame.processDiceRoll(11);
+
+ // Check if resources were paid out according to map Placement
+ assertEquals(8, siedlerGame.getCurrentPlayers().get(0).getTotalAmountOfResources());
+ assertEquals(5, siedlerGame.getCurrentPlayers().get(1).getTotalAmountOfResources());
+
+ assertEquals(initialBankInventory, siedlerGame.getBank().getTotalAmountOfResources() +
+ siedlerGame.getCurrentPlayers().get(0).getTotalAmountOfResources() +
+ siedlerGame.getCurrentPlayers().get(1).getTotalAmountOfResources());
+ }
+
+ /**
+ * This method tests that the processPayoutResources() method of the SiedlerGame class correctly handles the case
+ * where there are not enough resources in the bank to pay out the resources to the players.
+ * The test first creates a SiedlerGame object with three players, and then rolls the dice until the bank has only one wool resource left.
+ * It then rolls the dice again, which should trigger a payout of wool resources to the players.
+ * Finally, it uses the assertEquals() method to verify that the total number of resources in the bank and the players remains the same as it was before the last dice roll.
+ */
+ @Test
+ void processPayoutResourcesNotEnoughResources() {
+ SiedlerGame threePlayerGame = ThreePlayerStandard.getAfterSetupPhaseSomeRoads(REQUIRED_WINNING_SCORE);
+ int initialBankInventory = getInitialBankInventory();
+
+ // Reduce Bank Resource Wool until only one is left.
+ for (int i = 0; i < 7; i++) {
+ threePlayerGame.processDiceRoll(12);
+ }
+
+ Integer bankInventory = threePlayerGame.getBank().getTotalAmountOfResources();
+
+ // Roll Wool one more time
+ threePlayerGame.processDiceRoll(12);
+
+ assertEquals(bankInventory, threePlayerGame.getBank().getTotalAmountOfResources());
+ assertEquals(initialBankInventory, threePlayerGame.getBank().getTotalAmountOfResources() +
+ threePlayerGame.getCurrentPlayers().get(0).getTotalAmountOfResources() +
+ threePlayerGame.getCurrentPlayers().get(1).getTotalAmountOfResources() +
+ threePlayerGame.getCurrentPlayers().get(2).getTotalAmountOfResources());
+ }
+
+ /**
+ * This is a test method for the processDiceRoll() method when the thief is rolled of the SiedlerGame class.
+ * It first creates two players and builds their initial settlements using the buildInitialSettlements() method.
+ * Then it rolls the dice several times to simulate the game being played and resources being paid out,
+ * and finally it rolls the number for the executeThief() method
+ * which checks that the thief is executed and that the players' inventories are correctly modified as a result.
+ * It also checks that the total amount of resources in the game remains the same after the thief is executed.
+ */
+ @Test
+ void processThiefRolled() {
+ buildInitialSettlements();
+
+ siedlerGame.processDiceRoll(4);
+ siedlerGame.processDiceRoll(9);
+ siedlerGame.processDiceRoll(11);
+ siedlerGame.processDiceRoll(11);
+
+ int initialBankInventory = getInitialBankInventory();
+
+ // Check if thief is executed and cuts players inventory with more than 7
+ // Resources in half but doesn't touch the other players resource
+ assertTrue(siedlerGame.processDiceRoll(THIEF_DICE_NUMBER).isThiefExecuted());
+ assertEquals(4, siedlerGame.getCurrentPlayers().get(0).getTotalAmountOfResources());
+ assertEquals(5, siedlerGame.getCurrentPlayers().get(1).getTotalAmountOfResources());
+
+ assertEquals(initialBankInventory, siedlerGame.getBank().getTotalAmountOfResources() +
+ siedlerGame.getCurrentPlayers().get(0).getTotalAmountOfResources() +
+ siedlerGame.getCurrentPlayers().get(1).getTotalAmountOfResources());
+ }
+
+ /**
+ * Testing the placeThiefAndStealCard Method
+ *
+ * The test creates the initial settlements on the board and checks whether the first field is occupied by a thief.
+ * It then attempts to place the thief on the water field and on the empty field,
+ * and checks whether these attempts were successful.
+ * Finally, the test places the thief on the first field, checks whether it is occupied by the thief,
+ * and checks the total amount of resources for the current player and the next player.
+ */
+ @Test
+ void placeThiefAndStealCard() {
+ buildInitialSettlements();
+
+ assertFalse(siedlerGame.getBoard().getField(firstField).isOccupiedByThief());
+
+ assertFalse(siedlerGame.placeThiefAndStealCard(waterField));
+ assertTrue(siedlerGame.placeThiefAndStealCard(emptyField));
+ siedlerGame.placeThiefAndStealCard(firstField);
+
+ assertTrue(siedlerGame.getBoard().getField(firstField).isOccupiedByThief());
+ assertEquals(4, siedlerGame.getCurrentPlayer().getTotalAmountOfResources());
+ assertEquals(2, siedlerGame.getCurrentPlayers().get(1).getTotalAmountOfResources());
+ }
+
+ /**
+ * This test first checks that the number of players returned by the function matches the number of players in the game,
+ * then checks that the factions of the players in the game and the manually generated list of players match.
+ */
+ @Test
+ void getCurrentPlayers() {
+ assertEquals(siedlerGame.getPlayerFactions().size(), siedlerGame.getCurrentPlayers().size());
+ assertEquals(siedlerGame.getPlayerFactions().get(0), siedlerGame.getCurrentPlayers().get(0).getFaction());
+ }
+
+ /**
+ * This test first checks that the current player's faction matches the faction of the first player in the list of players in the game,
+ * then checks that the player's faction matches the returned value of the getCurrentPlayerFaction function.
+ */
+ @Test
+ void getCurrentPlayer() {
+ assertEquals(siedlerGame.getPlayerFactions().get(0), siedlerGame.getCurrentPlayer().getFaction());
+ assertEquals(siedlerGame.getCurrentPlayer().getFaction(), siedlerGame.getCurrentPlayerFaction());
+ }
+
+ /**
+ * This test checks if the inventory of the bank returned by the getBank() method
+ * matches the expected INITIAL_RESOURCE_CARDS_BANK value.
+ */
+ @Test
+ void getBank() {
+ assertEquals(INITIAL_RESOURCE_CARDS_BANK, siedlerGame.getBank().getInventory());
+ }
+
+ private void buildInitialSettlements() {
+ siedlerGame.placeInitialSettlement(validSettlementPoints.get(0), true);
+ siedlerGame.placeInitialSettlement(validSettlementPoints.get(1), false);
+ siedlerGame.switchToNextPlayer();
+
+ siedlerGame.placeInitialSettlement(validSettlementPoints.get(2), true);
+ siedlerGame.placeInitialSettlement(validSettlementPoints.get(3), false);
+ siedlerGame.switchToNextPlayer();
+ }
+
+}
diff --git a/src/test/java/ch/zhaw/catan/game/SiedlerGameTestBasic.java b/src/test/java/ch/zhaw/catan/game/SiedlerGameTestBasic.java
new file mode 100644
index 0000000..9797380
--- /dev/null
+++ b/src/test/java/ch/zhaw/catan/game/SiedlerGameTestBasic.java
@@ -0,0 +1,304 @@
+package ch.zhaw.catan.game;
+
+import ch.zhaw.catan.ThreePlayerStandard;
+import ch.zhaw.catan.board.SiedlerBoardTextView;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.awt.Point;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static ch.zhaw.catan.game.App.REQUIRED_WINNING_SCORE;
+
+/**
+ * This class contains some basic tests for the {@link SiedlerGame} class
+ *
+ *
+ * DO NOT MODIFY THIS CLASS
+ *
+ * Note, that for the test to work, the {@link Map} returned by
+ * {@link SiedlerGame#processDiceRoll(int)}
+ * must contain a {@link List} with resource cards (empty {@link List}, if the
+ * player gets none)
+ * for each of the players.
+ *
+ * This class performs tests for the class {@link Edge}.
+ *
+ * Tests for the class {@link HexBoard}.
+ *
+ *
+ *
+ * @param position the position of the {@link Settlement}
+ * @return true, if the placement was successful, false otherwise
+ */
+ public boolean buildSettlement(final Point position) {
+ if (board.canPlaceSettlementOnPosition(position, false, getCurrentPlayerFaction())
+ && getCurrentPlayer().hasNotReachedMaxStockOf(SETTLEMENT)
+ && getCurrentPlayer().decreaseInventoryIfApplicable(SETTLEMENT.getCostsAsIntegerMap())) {
+ bank.increaseInventory(SETTLEMENT.getCostsAsIntegerMap());
+ final Structure settlement = new Settlement(getCurrentPlayerFaction());
+ getCurrentPlayer().addStructure(settlement);
+ board.setCorner(position, settlement);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Builds a {@link City} at the specified position on the board.
+ *
+ *
+ *
+ *
+ * @param position the position of the {@link City}
+ * @return true, if the placement was successful, false otherwise
+ */
+ public boolean buildCity(final Point position) {
+ if (board.canPlaceCityOnPosition(position, getCurrentPlayerFaction())
+ && getCurrentPlayer().hasNotReachedMaxStockOf(CITY)
+ && getCurrentPlayer().decreaseInventoryIfApplicable(CITY.getCostsAsIntegerMap())) {
+ bank.increaseInventory(CITY.getCostsAsIntegerMap());
+ final Structure city = new City(getCurrentPlayerFaction());
+ getCurrentPlayer().removeStructure(board.getCorner(position));
+ getCurrentPlayer().addStructure(city);
+ board.setCorner(position, city);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Builds a {@link Road} at the specified position on the board.
+ *
+ *
+ *
+ *
+ * @param roadStart the position of the start of the {@link Road}
+ * @param roadEnd the position of the end of the {@link Road}
+ * @return true, if the placement was successful, false otherwise
+ */
+ public boolean buildRoad(final Point roadStart, final Point roadEnd) {
+ if (board.canPlaceRoadOnPosition(roadStart, roadEnd, getCurrentPlayerFaction())
+ && getCurrentPlayer().hasNotReachedMaxStockOf(ROAD)
+ && getCurrentPlayer().decreaseInventoryIfApplicable(ROAD.getCostsAsIntegerMap())) {
+ bank.increaseInventory(ROAD.getCostsAsIntegerMap());
+ final Road road = new Road(getCurrentPlayerFaction());
+ getCurrentPlayer().addStructure(road);
+ board.setEdge(roadStart, roadEnd, road);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ *
+ * 0 1 2 3 4 5 6 7 8
+ * | | | | | | | | | ...
+ *
+ * 0---- C C C C C
+ * \ / \ / \ / \ / \
+ * 1---- C C C C C
+ *
+ * 2---- F | F | F | F | F | ...
+ *
+ * 3---- C C C C C
+ * / \ / \ / \ / \ /
+ * 4---- C C C C C
+ *
+ * 5---- | F | F | F | F | F ...
+ *
+ * 6---- C C C C C
+ * \ / \ / \ / \ / \
+ * 7---- C C C C C
+ *
+ * ...
+ *
+ *
+ *
+ * SW (C) SE
+ * / N \
+ * (C) NW NE (C)
+ * | F |
+ * | |
+ * (C) SW SE (C)
+ * \ S /
+ * NW (C) NE
+ *
+ *
+ * @param
+ *
+ *
+ *
+ *
+ *
+ * DEFAULT LABELS FROM DATA
+ *
+ * ( ) (CL)
+ * // \\ EL EL
+ * // \\ EL N EL
+ * ( ) ( ) (CL) NW NE (CL)
+ * || || EL UL EL
+ * || || EL EL
+ * ( ) ( ) (CL) SW SE (CL)
+ * \\ // EL S EL
+ * \\ // EL EL
+ * ( ) (CL)
+ *
+ *
+ *
+ *
+ * (CL)
+ * // N \\
+ * // \\
+ * (CL) NW NE (CL)
+ * || UL ||
+ * || LL ||
+ * (CL) SW SE (CL)
+ * \\ S //
+ * \\ //
+ * (CL)
+ *
+ *
+ * @param
+ * The basic game situations upon which all other situations that can be retrieved are based is
+ * the following:
+ *
+ * ( ) ( ) ( ) ( )
+ * // \\ // \\ // \\ // \\
+ * ( ) ( ) ( ) ( ) ( )
+ * || ~~ || ~~ || ~~ || ~~ ||
+ * || || || || ||
+ * ( ) ( ) ( ) ( ) ( )
+ * // \\ // \\ // \\ // \\ // \\
+ * ( ) ( ) ( ) (bb) ( ) ( )
+ * || ~~ || LU || WL bb WL || ~~ ||
+ * || || 06 || 03 bb 08 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( )
+ * // \\ // \\ rr \\ // \\ // \\ // \\
+ * ( ) ( ) (rr) ( ) ( ) ( ) ( )
+ * || ~~ || GR || OR || GR || LU || ~~ ||
+ * || || 02 || 04 || 05 || 10 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( ) ( )
+ * // \\ // \\ // \\ // \\ // \\ // \\ // \\
+ * ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
+ * || ~~ gg LU || BR || -- || OR || GR || ~~ ||
+ * || gg 05 || 09 || 07 || 06 || 09 || ||
+ * ( ) (gg) ( ) ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ // \\ // \\ // \\ bb \\ //
+ * ( ) ( ) ( ) ( ) ( ) (bb) ( )
+ * || ~~ || GR || OR || LU || WL || ~~ ||
+ * || || 10 || 11 || 03 || 12 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ // \\ // rr // \\ //
+ * ( ) ( ) ( ) ( ) (rr) ( )
+ * || ~~ || WL || BR || BR || ~~ ||
+ * || || 08 || 04 || 11 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ gg \\ // \\ //
+ * ( ) ( ) (gg) ( ) ( )
+ * || ~~ || ~~ || ~~ || ~~ ||
+ * || || || || ||
+ * ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ // \\ //
+ * ( ) ( ) ( ) ( )
+ *
+ * Resource cards after the setup phase:
+ *
+ *
+ *
+ *
+ *
+ * @author tebe
+ */
+public class ThreePlayerStandard {
+ public final static int NUMBER_OF_PLAYERS = 3;
+
+ public static final Map
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * @param winpoints the number of points required to win the game
+ * @return the siedler game
+ */
+ public static SiedlerGame getAfterSetupPhaseAlmostEmptyBank(int winpoints) {
+ SiedlerGame model = getAfterSetupPhase(winpoints);
+ throwDiceMultipleTimes(model, 6, 9);
+ throwDiceMultipleTimes(model, 11, 8);
+ throwDiceMultipleTimes(model, 2, 8);
+ throwDiceMultipleTimes(model, 4, 7);
+ throwDiceMultipleTimes(model, 12, 8);
+ throwDiceMultipleTimes(model, 5, 9);
+ throwDiceMultipleTimes(model, 9, 8);
+ return model;
+ }
+
+
+ /**
+ * Returns a {@link SiedlerGame} with several roads added but none longer than
+ * 4 elements. Hence, no player meets the longest road criteria yet. Furthermore,
+ * players one and three have enough resource cards to build additional roads and settlements.
+ *
+ *
+ *
+ * ( ) ( ) ( ) ( )
+ * // \\ // \\ // \\ // \\
+ * ( ) ( ) ( ) ( ) ( )
+ * || ~~ || ~~ || ~~ || ~~ ||
+ * || || || || ||
+ * ( ) ( ) ( ) ( ) ( )
+ * // \\ // \\ // \\ // \\ // \\
+ * ( ) ( ) ( ) (bb) ( ) ( )
+ * || ~~ || LU || WL bb WL || ~~ ||
+ * || || 06 || 03 bb 08 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( )
+ * // \\ // \\ rr \\ // \\ // \\ // \\
+ * ( ) ( ) (rr) ( ) ( ) ( ) ( )
+ * || ~~ gg GR rr OR || GR || LU || ~~ ||
+ * || gg 02 rr 04 || 05 || 10 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( ) ( )
+ * // \\ gg rr rr \\ // \\ // \\ // \\ // \\
+ * ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
+ * || ~~ gg LU || BR || -- || OR || GR || ~~ ||
+ * || gg 05 || 09 || 07 || 06 || 09 || ||
+ * ( ) (gg) ( ) ( ) ( ) ( ) ( ) ( )
+ * \\ // gg // \\ // \\ // \\ rr \\ bb \\ //
+ * ( ) ( ) ( ) ( ) ( ) (bb) ( )
+ * || ~~ || GR || OR || LU rr WL || ~~ ||
+ * || || 10 || 11 || 03 rr 12 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ // \\ // rr rr \\ //
+ * ( ) ( ) ( ) ( ) (rr) ( )
+ * || ~~ || WL gg BR gg BR rr ~~ ||
+ * || || 08 gg 04 gg 11 rr ||
+ * ( ) ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // gg gg \\ // \\ //
+ * ( ) ( ) (gg) ( ) ( )
+ * || ~~ || ~~ || ~~ || ~~ ||
+ * || || || || ||
+ * ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ // \\ //
+ * ( ) ( ) ( ) ( )
+ *
+ *
+ * Player 1:
+ *
+ *
+ * Player 2:
+ *
+ *
+ * Player 3:
+ *
+ *
+ *
+ * @param winpoints the number of points required to win the game
+ * @return the siedler game
+ */
+ public static SiedlerGame getAfterSetupPhaseSomeRoads(int winpoints) {
+ SiedlerGame model = getAfterSetupPhase(winpoints);
+ throwDiceMultipleTimes(model, 6, 7);
+ throwDiceMultipleTimes(model, 11, 6);
+ throwDiceMultipleTimes(model, 4, 5);
+ throwDiceMultipleTimes(model, 5, 6);
+ throwDiceMultipleTimes(model, 2, 1);
+
+ model.switchToNextPlayer();
+ model.switchToNextPlayer();
+ model.buildRoad(new Point(2, 12), new Point(3, 13));
+ buildRoad(model, List.of(new Point(2, 10), new Point(3, 9), new Point(3, 7)));
+ model.buildRoad(new Point(8, 18), new Point(8, 16));
+ buildRoad(model, List.of(new Point(7, 19), new Point(6, 18), new Point(6, 16)));
+ model.switchToNextPlayer();
+ model.buildRoad(new Point(10, 16), new Point(11, 15));
+ model.buildRoad(new Point(10, 16), new Point(10, 18));
+ buildRoad(model, List.of(new Point(9, 15), new Point(9, 13), new Point(10, 12)));
+ buildRoad(model, List.of(new Point(5, 7), new Point(5, 9), new Point(4, 10), new Point(3, 9)));
+
+ throwDiceMultipleTimes(model, 6, 6);
+ throwDiceMultipleTimes(model, 11, 6);
+ throwDiceMultipleTimes(model, 4, 6);
+ throwDiceMultipleTimes(model, 5, 6);
+
+ model.switchToNextPlayer();
+ model.switchToNextPlayer();
+ throwDiceMultipleTimes(model, 5, 4);
+ model.tradeWithBankFourToOne(Resource.LUMBER, Resource.GRAIN);
+ throwDiceMultipleTimes(model, 5, 4);
+ model.tradeWithBankFourToOne(Resource.LUMBER, Resource.WOOL);
+ model.switchToNextPlayer();
+ return model;
+ }
+
+
+ private static SiedlerGame throwDiceMultipleTimes(SiedlerGame model, int diceValue, int numberOfTimes) {
+ for (int i = 0; i < numberOfTimes; i++) {
+ model.processDiceRoll(diceValue);
+ }
+ return model;
+ }
+
+ /**
+ *
+ * ( ) ( ) ( ) ( )
+ * // \\ // \\ // \\ // \\
+ * ( ) ( ) ( ) ( ) ( )
+ * || ~~ || ~~ || ~~ || ~~ ||
+ * || || || || ||
+ * ( ) ( ) ( ) ( ) ( )
+ * // \\ // \\ // \\ // \\ // \\
+ * ( ) ( ) (rr) (bb) ( ) ( )
+ * || ~~ || LU rr WL bb WL || ~~ ||
+ * || || 06 rr 03 bb 08 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( )
+ * // \\ // \\ rr rr // \\ // \\ // \\
+ * ( ) ( ) (rr) (rr) ( ) ( ) ( )
+ * || ~~ || GR || OR || GR || LU || ~~ ||
+ * || || 02 || 04 || 05 || 10 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( ) ( )
+ * // \\ // \\ // \\ // \\ // \\ // \\ // \\
+ * ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
+ * || ~~ gg LU || BR || -- || OR || GR || ~~ ||
+ * || gg 05 || 09 || 07 || 06 || 09 || ||
+ * ( ) (gg) ( ) ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ // \\ // \\ // \\ bb \\ //
+ * ( ) ( ) ( ) ( ) ( ) (bb) ( )
+ * || ~~ || GR || OR || LU rr WL || ~~ ||
+ * || || 10 || 11 || 03 rr 12 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ // \\ // rr // \\ //
+ * ( ) ( ) ( ) ( ) (rr) ( )
+ * || ~~ || WL || BR || BR || ~~ ||
+ * || || 08 || 04 || 11 || ||
+ * ( ) ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ gg \\ // \\ //
+ * ( ) ( ) (gg) ( ) ( )
+ * || ~~ || ~~ || ~~ || ~~ ||
+ * || || || || ||
+ * ( ) ( ) ( ) ( ) ( )
+ * \\ // \\ // \\ // \\ //
+ * ( ) ( ) ( ) ( )
+ *
+ *
+ *
+ * Player 1:
+ *
+ *
+ * Player 2:
+ *
+ *
+ * Player 3:
+ *
+ *
+ *
+ * @param winpoints the number of points required to win the game
+ * @return the siedler game
+ */
+ public static SiedlerGame getPlayerOneReadyToBuildFifthSettlement(int winpoints) {
+ SiedlerGame model = getAfterSetupPhase(winpoints);
+ //generate resources to build four roads and four settlements.
+ throwDiceMultipleTimes(model, 6, 8);
+ throwDiceMultipleTimes(model, 11, 7);
+ throwDiceMultipleTimes(model, 2, 4);
+ throwDiceMultipleTimes(model, 12, 3);
+ model.buildRoad(new Point(6, 6), new Point(7, 7));
+ model.buildRoad(new Point(6, 6), new Point(6, 4));
+ model.buildRoad(new Point(9, 15), new Point(9, 13));
+ model.buildSettlement(playerOneReadyToBuildFifthSettlementAllSettlementPositions.get(2));
+ model.buildSettlement(playerOneReadyToBuildFifthSettlementAllSettlementPositions.get(3));
+ return model;
+ }
+
+ private static void buildSettlement(SiedlerGame model, Point position, List
+ * 0 1 2 3 4 5 6 7 8
+ * | | | | | | | | | ...
+ *
+ * 0----
+ *
+ * 1----
+ *
+ * 2----
+ *
+ * 3---- C
+ * / \
+ * 4---- C C
+ *
+ * 5---- | F | ...
+ *
+ * 6---- C C
+ * \ /
+ * 7---- C
+ *
+ */
+ @BeforeEach
+ public void setUp() {
+ board = new HexBoard<>();
+ board.addField(new Point(7, 5), "00");
+ Point[] singleField = {new Point(7, 3), new Point(8, 4), new Point(8, 6), new Point(7, 7),
+ new Point(6, 6), new Point(6, 4)};
+ this.corner = singleField;
+ }
+
+ // Edge retrieval
+ @Test
+ void edgeTest() {
+ for (int i = 0; i < corner.length - 1; i++) {
+ Assertions.assertNull(board.getEdge(corner[i], corner[i + 1]));
+ board.setEdge(corner[i], corner[i + 1], Integer.toString(i));
+ Assertions.assertEquals(board.getEdge(corner[i], corner[i + 1]), Integer.toString(i));
+ }
+ }
+
+ @Test
+ void noEdgeCoordinatesTest() {
+ Assertions.assertThrows(IllegalArgumentException.class,
+ () -> board.getEdge(new Point(2, 2), new Point(0, 2)));
+ }
+
+ @Test
+ void edgeDoesNotExistTest() {
+ Assertions.assertThrows(IllegalArgumentException.class,
+ () -> board.getEdge(new Point(0, 2), new Point(3, 1)));
+ }
+
+ // Corner retrieval
+ @Test
+ void cornerTest() {
+ for (Point p : corner) {
+ Assertions.assertNull(board.getCorner(p));
+ board.setCorner(p, p.toString());
+ Assertions.assertEquals(board.getCorner(p), p.toString());
+ }
+ }
+
+ @Test
+ void noCornerCoordinateTest() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> board.getCorner(new Point(2, 2)));
+ }
+
+ @Test
+ void cornerDoesNotExistTest() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> board.getCorner(new Point(2, 2)));
+ }
+
+ // Field addition/retrieval
+ @Test
+ void fieldAreadyExistsErrorTest() {
+ board.addField(new Point(2, 2), "22");
+ Assertions.assertThrows(IllegalArgumentException.class, () -> board.addField(new Point(2, 2), "22"));
+ }
+
+ @Test
+ void fieldRetrievalTest() {
+ Point field = new Point(2, 2);
+ board.addField(field, "22");
+ Assertions.assertTrue(board.hasField(field));
+ Assertions.assertEquals("22", board.getField(field));
+ }
+
+ @Test
+ void fieldRetrievalWrongCoordinatesOutsideTest() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> board.getField(new Point(10, 10)));
+ }
+
+ @Test
+ void fieldRetrievalWrongCoordinatesInsideTest() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> board.getField(new Point(2, 2)));
+ }
+}