diff --git a/.gitignore b/.gitignore
index 33732f06..8459cc8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
target
.Makefile.swp
+.idea/uiDesigner.xml
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..a7d75c89
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,4 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+/material_theme_project_new.xml
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 00000000..3500e153
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 00000000..aa00ffab
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 00000000..712ab9d9
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..9dc782bb
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 3214a650..61a0f80c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,5 @@
+all: check_and_test lint format
+
check_and_test: FORCE
mvn test
@@ -5,5 +7,5 @@ lint: FORCE
mvn checkstyle:check
format: FORCE
- mvn googleformatter:format
+ mvn formatter:format
FORCE: ;
diff --git a/README.md b/README.md
index 0a2144e5..890a7faf 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
# Stone Age
-This is the Java version of the semestral project from Principles of Software Design (1) course on FMFI UK, 2024/25.
+This is the Java version of the semestral project from Principles of Software Design (1) course on FMFI UK, 2024/25.
\ No newline at end of file
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/AllPlayersTakeReward.java b/src/main/java/sk/uniba/fmph/dcs/game_board/AllPlayersTakeReward.java
new file mode 100644
index 00000000..5283e8c1
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/AllPlayersTakeReward.java
@@ -0,0 +1,63 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.InterfaceGamePhaseController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AllPlayersTakeReward implements EvaluateCivilisationCardImmediateEffect {
+
+ private final RewardMenu menu;
+ private static final int WOODID = 1;
+ private static final int CLAYID = 2;
+ private static final int STONEID = 3;
+ private static final int GOLDID = 4;
+ private static final int TOOLID = 5;
+ private final InterfaceGamePhaseController controller;
+
+ /**
+ * @param menu
+ * RewardMenu that is already existing
+ * @param controller
+ * controller to call in performEffect
+ */
+ public AllPlayersTakeReward(final RewardMenu menu, final InterfaceGamePhaseController controller) {
+ this.menu = menu;
+ this.controller = controller;
+ int n = menu.getPlayersCount();
+ int[] t = Throw.hod(n);
+ List m = new ArrayList<>();
+ for (var i : t) {
+ if (i == WOODID) {
+ m.add(Effect.WOOD);
+ } else if (i == CLAYID) {
+ m.add(Effect.CLAY);
+ } else if (i == STONEID) {
+ m.add(Effect.STONE);
+ } else if (i == GOLDID) {
+ m.add(Effect.GOLD);
+ } else if (i == TOOLID) {
+ m.add(Effect.TOOL);
+ } else {
+ m.add(Effect.FIELD);
+ }
+ }
+ menu.initiate(m);
+ }
+
+ /**
+ * call controller.
+ *
+ * @param player
+ * player that takes from menu
+ * @param choice
+ * resource to take from menu
+ *
+ * @return true if resource was successfully taken
+ */
+ @Override
+ public boolean performEffect(final Player player, final Effect choice) {
+ return controller.makeAllPlayersTakeARewardChoice(player.playerOrder(), choice);
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/ArbitraryBuilding.java b/src/main/java/sk/uniba/fmph/dcs/game_board/ArbitraryBuilding.java
new file mode 100644
index 00000000..55239606
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/ArbitraryBuilding.java
@@ -0,0 +1,34 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import org.json.JSONObject;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.OptionalInt;
+
+public final class ArbitraryBuilding implements Building {
+ private final int numberOfResources;
+
+ public ArbitraryBuilding(final int numberOfResources) {
+ this.numberOfResources = numberOfResources;
+ }
+
+ @Override
+ public OptionalInt build(final Collection resources) {
+ if (resources.size() > numberOfResources) {
+ return OptionalInt.empty();
+ }
+ int sum = 0;
+ for (Effect resource : resources) {
+ sum += resource.points();
+ }
+ return OptionalInt.of(sum);
+ }
+
+ @Override
+ public String state() {
+ Map state = Map.of("numberOfResources", Integer.toString(numberOfResources));
+ return new JSONObject(state).toString();
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/Building.java b/src/main/java/sk/uniba/fmph/dcs/game_board/Building.java
index cf279418..b8176f7c 100644
--- a/src/main/java/sk/uniba/fmph/dcs/game_board/Building.java
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/Building.java
@@ -1,9 +1,12 @@
package sk.uniba.fmph.dcs.game_board;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
import java.util.Collection;
import java.util.OptionalInt;
-import sk.uniba.fmph.dcs.stone_age.Effect;
interface Building {
OptionalInt build(Collection resources);
+
+ String state();
}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/CivilizationCardDeck.java b/src/main/java/sk/uniba/fmph/dcs/game_board/CivilizationCardDeck.java
new file mode 100644
index 00000000..dba842da
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/CivilizationCardDeck.java
@@ -0,0 +1,15 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.CivilisationCard;
+
+import java.util.Optional;
+
+public final class CivilizationCardDeck {
+ public Optional getTop() {
+ return Optional.empty();
+ }
+
+ public String state() {
+ return "TODO";
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/CurrentThrow.java b/src/main/java/sk/uniba/fmph/dcs/game_board/CurrentThrow.java
new file mode 100644
index 00000000..e1503d0b
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/CurrentThrow.java
@@ -0,0 +1,30 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.InterfaceToolUse;
+
+public final class CurrentThrow implements InterfaceToolUse {
+
+ public CurrentThrow(final Effect throwsFor, final int throwResult) {
+ // todo
+ }
+
+ public void initiate(final Player player, final Effect effect, final int dices) {
+ return; // todo
+ }
+
+ @Override
+ public boolean useTool(final int idx) {
+ return false;
+ }
+
+ @Override
+ public boolean canUseTools() {
+ return false;
+ }
+
+ @Override
+ public boolean finishUsingTools() {
+ return false;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/EvaluateCivilisationCardImmediateEffect.java b/src/main/java/sk/uniba/fmph/dcs/game_board/EvaluateCivilisationCardImmediateEffect.java
new file mode 100644
index 00000000..8d5889ba
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/EvaluateCivilisationCardImmediateEffect.java
@@ -0,0 +1,7 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+public interface EvaluateCivilisationCardImmediateEffect {
+ boolean performEffect(Player player, Effect choice);
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/GetCard.java b/src/main/java/sk/uniba/fmph/dcs/game_board/GetCard.java
new file mode 100644
index 00000000..e16dd7e9
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/GetCard.java
@@ -0,0 +1,36 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.CivilisationCard;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.Optional;
+
+public class GetCard implements EvaluateCivilisationCardImmediateEffect {
+ private final CivilizationCardDeck deck;
+
+ /**
+ * @param deck
+ * to draw cards from
+ */
+ public GetCard(final CivilizationCardDeck deck) {
+ this.deck = deck;
+ }
+
+ /**
+ * @param player
+ * gives player top card of the deck
+ * @param choice
+ * ignored
+ *
+ * @return true if card exists
+ */
+ @Override
+ public boolean performEffect(final Player player, final Effect choice) {
+ Optional c = deck.getTop();
+ if (c.isEmpty()) {
+ return false;
+ }
+ player.playerBoard().giveEndOfGameEffect(c.get().endOfGameEffect());
+ return true;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/GetChoice.java b/src/main/java/sk/uniba/fmph/dcs/game_board/GetChoice.java
new file mode 100644
index 00000000..22532d1b
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/GetChoice.java
@@ -0,0 +1,38 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+public class GetChoice implements EvaluateCivilisationCardImmediateEffect {
+ private int numberOfResources;
+
+ /**
+ * @param numberOfResources
+ * number of resources available to choose.
+ */
+ public GetChoice(final int numberOfResources) {
+ this.numberOfResources = numberOfResources;
+ }
+
+ /**
+ * gives one resource of any type.
+ *
+ * @param player
+ * player to give resource to
+ * @param choice
+ * resource wanted
+ *
+ * @return true if player can take resource, false otherwise
+ */
+ @Override
+ public boolean performEffect(final Player player, final Effect choice) {
+ if (!choice.isResource()) {
+ return false;
+ }
+ if (numberOfResources == 0) {
+ return false;
+ }
+ numberOfResources--;
+ player.playerBoard().giveEffect(new Effect[] {choice});
+ return true;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/GetSomethingFixed.java b/src/main/java/sk/uniba/fmph/dcs/game_board/GetSomethingFixed.java
new file mode 100644
index 00000000..610408fa
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/GetSomethingFixed.java
@@ -0,0 +1,36 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GetSomethingFixed implements EvaluateCivilisationCardImmediateEffect {
+ private final List effects;
+
+ /**
+ * @param effect
+ * list of effects that can be chosen.
+ */
+ public GetSomethingFixed(final List effect) {
+ effects = new ArrayList<>();
+ effects.addAll(effect);
+ }
+
+ /**
+ * give all resources to player.
+ *
+ * @param player
+ * player to give choice to
+ * @param choice
+ * ignores
+ *
+ * @return true - it is always possible to give resources to player
+ */
+ @Override
+ public boolean performEffect(final Player player, final Effect choice) {
+ player.playerBoard().giveEffect(effects.toArray(new Effect[0]));
+ effects.clear();
+ return true;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/GetSomethingThrow.java b/src/main/java/sk/uniba/fmph/dcs/game_board/GetSomethingThrow.java
new file mode 100644
index 00000000..b28c54e8
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/GetSomethingThrow.java
@@ -0,0 +1,30 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.Arrays;
+
+public final class GetSomethingThrow implements EvaluateCivilisationCardImmediateEffect {
+ private final Effect resource;
+ private final CurrentThrow currentThrow;
+
+ public GetSomethingThrow(final Effect resource) {
+ this.resource = resource;
+
+ int something = 0; // todo
+ currentThrow = new CurrentThrow(resource, something);
+ }
+
+ @Override
+ public boolean performEffect(final Player player, final Effect choice) {
+ if (choice != this.resource) {
+ return false;
+ }
+ currentThrow.initiate(player, choice, 2);
+ int pocet = 0; // todo
+ Effect[] res = new Effect[pocet];
+ Arrays.fill(res, choice);
+ player.playerBoard().giveEffect(res);
+ return true;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/InterfaceFigureLocationInternal.java b/src/main/java/sk/uniba/fmph/dcs/game_board/InterfaceFigureLocationInternal.java
new file mode 100644
index 00000000..c5a0e6d7
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/InterfaceFigureLocationInternal.java
@@ -0,0 +1,20 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+
+public interface InterfaceFigureLocationInternal {
+ boolean placeFigures(Player player, int figureCount);
+
+ HasAction tryToPlaceFigures(Player player, int count);
+
+ ActionResult makeAction(Player player, Effect[] inputResources, Effect[] outputResources);
+
+ boolean skipAction(Player player);
+
+ HasAction tryToMakeAction(Player player);
+
+ boolean newTurn(); // Returns true if the end of the game is implied by the given location
+
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/PlaceOnFieldsAdaptor.java b/src/main/java/sk/uniba/fmph/dcs/game_board/PlaceOnFieldsAdaptor.java
new file mode 100644
index 00000000..aff673f5
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/PlaceOnFieldsAdaptor.java
@@ -0,0 +1,121 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+
+public class PlaceOnFieldsAdaptor implements InterfaceFigureLocationInternal {
+ private final ToolMakerHutsFields fields;
+
+ /**
+ * @param fields
+ * using methods from ToolMakerHutsFields
+ */
+ public PlaceOnFieldsAdaptor(final ToolMakerHutsFields fields) {
+ this.fields = fields;
+ }
+
+ /**
+ * @param player
+ * player that places figures
+ * @param figureCount
+ * number of figures to place
+ *
+ * @return true if move is possible
+ */
+ @Override
+ public boolean placeFigures(final Player player, final int figureCount) {
+ if (tryToPlaceFigures(player, figureCount) == HasAction.NO_ACTION_POSSIBLE) {
+ return false;
+ }
+ return fields.placeOnFields(player);
+ }
+
+ /**
+ * does field allow for player to place figures.
+ *
+ * @param player
+ * player that places figures
+ * @param count
+ * number of figures
+ *
+ * @return `NO_ACTION_POSSIBLE` when player cant place figures on field, `WAITING_FOR_PLAYER_ACTION` otherwise
+ */
+ @Override
+ public HasAction tryToPlaceFigures(final Player player, final int count) {
+ if (!player.playerBoard().hasFigures(count)) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (count != 1) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (!fields.canPlaceOnFields(player)) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ return HasAction.WAITING_FOR_PLAYER_ACTION;
+ }
+
+ /**
+ * resolve fields.
+ *
+ * @param player
+ * player that wants to resolve
+ * @param inputResources
+ * really don't know todo
+ * @param outputResources
+ * don't know either todo
+ *
+ * @return ACTION_DONE when player can resolve fields, FAILURE otherwise
+ */
+ @Override
+ public ActionResult makeAction(final Player player, final Effect[] inputResources, final Effect[] outputResources) {
+ boolean res = fields.actionFields(player);
+ if (res) {
+ return ActionResult.ACTION_DONE;
+ } else {
+ return ActionResult.FAILURE;
+ }
+ }
+
+ // todo
+
+ /**
+ * does exactly nothing.
+ *
+ * @param player
+ * player to do nothing with
+ *
+ * @return false
+ */
+ @Override
+ public boolean skipAction(final Player player) {
+ return false;
+ }
+
+ // todo
+
+ /**
+ * does exactly nothing.
+ *
+ * @param player
+ * player to do nothing with
+ *
+ * @return null
+ */
+ @Override
+ public HasAction tryToMakeAction(final Player player) {
+ return null;
+ }
+
+ // todo
+
+ /**
+ * does exactly nothing.
+ *
+ * @return false
+ */
+ @Override
+ public boolean newTurn() {
+ return false;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/PlaceOnHutAdaptor.java b/src/main/java/sk/uniba/fmph/dcs/game_board/PlaceOnHutAdaptor.java
new file mode 100644
index 00000000..11bb7428
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/PlaceOnHutAdaptor.java
@@ -0,0 +1,120 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+
+public class PlaceOnHutAdaptor implements InterfaceFigureLocationInternal {
+ private final ToolMakerHutsFields huts;
+
+ /**
+ * @param huts
+ * using methods from ToolMakerHutsFields
+ */
+ public PlaceOnHutAdaptor(final ToolMakerHutsFields huts) {
+ this.huts = huts;
+ }
+
+ /**
+ * @param player
+ * player that places figures
+ * @param figureCount
+ * number of figures to place
+ *
+ * @return true if move is possible
+ */
+ @Override
+ public boolean placeFigures(final Player player, final int figureCount) {
+ if (tryToPlaceFigures(player, figureCount) == HasAction.NO_ACTION_POSSIBLE) {
+ return false;
+ }
+ return huts.placeOnHut(player);
+ }
+
+ /**
+ * does field allow for player to place figures.
+ *
+ * @param player
+ * player that places figures
+ * @param count
+ * number of figures
+ *
+ * @return `NO_ACTION_POSSIBLE` when player cant place figures on field, `WAITING_FOR_PLAYER_ACTION` otherwise
+ */
+ @Override
+ public HasAction tryToPlaceFigures(final Player player, final int count) {
+ if (!player.playerBoard().hasFigures(count)) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (count != 2) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (!huts.canPlaceOnHut(player)) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ return HasAction.AUTOMATIC_ACTION_DONE;
+ }
+
+ /**
+ * resolve huts.
+ *
+ * @param player
+ * player that wants to resolve
+ * @param inputResources
+ * really don't know todo
+ * @param outputResources
+ * don't know either todo
+ *
+ * @return ACTION_DONE when player can resolve huts, FAILURE otherwise
+ */
+ @Override
+ public ActionResult makeAction(final Player player, final Effect[] inputResources, final Effect[] outputResources) {
+ boolean res = huts.actionHut(player);
+ if (res) {
+ return ActionResult.ACTION_DONE;
+ } else {
+ return ActionResult.FAILURE;
+ }
+ }
+ // todo
+
+ /**
+ * does exactly nothing.
+ *
+ * @param player
+ * player to do nothing with
+ *
+ * @return false
+ */
+ @Override
+ public boolean skipAction(final Player player) {
+ return false;
+ }
+
+ // todo
+
+ /**
+ * does exactly nothing.
+ *
+ * @param player
+ * player to do nothing with
+ *
+ * @return null
+ */
+ @Override
+ public HasAction tryToMakeAction(final Player player) {
+ return null;
+ }
+
+ // todo
+
+ /**
+ * does exactly nothing.
+ *
+ * @return false
+ */
+ @Override
+ public boolean newTurn() {
+ return false;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/PlaceOnToolMakerAdaptor.java b/src/main/java/sk/uniba/fmph/dcs/game_board/PlaceOnToolMakerAdaptor.java
new file mode 100644
index 00000000..5dbbcc51
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/PlaceOnToolMakerAdaptor.java
@@ -0,0 +1,121 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+
+public class PlaceOnToolMakerAdaptor implements InterfaceFigureLocationInternal {
+ private final ToolMakerHutsFields tools;
+
+ /**
+ * @param tools
+ * using methods from ToolMakerHutsFields
+ */
+ public PlaceOnToolMakerAdaptor(final ToolMakerHutsFields tools) {
+ this.tools = tools;
+ }
+
+ /**
+ * @param player
+ * player that places figures
+ * @param figureCount
+ * number of figures to place
+ *
+ * @return true if move is possible
+ */
+ @Override
+ public boolean placeFigures(final Player player, final int figureCount) {
+ if (tryToPlaceFigures(player, figureCount) == HasAction.NO_ACTION_POSSIBLE) {
+ return false;
+ }
+ return tools.placeOnToolMaker(player);
+ }
+
+ /**
+ * does field allow for player to place figures.
+ *
+ * @param player
+ * player that places figures
+ * @param count
+ * number of figures
+ *
+ * @return `NO_ACTION_POSSIBLE` when player cant place figures on field, `WAITING_FOR_PLAYER_ACTION` otherwise
+ */
+ @Override
+ public HasAction tryToPlaceFigures(final Player player, final int count) {
+ if (!player.playerBoard().hasFigures(count)) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (count != 1) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (!tools.canPlaceOnToolMaker(player)) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ return HasAction.AUTOMATIC_ACTION_DONE;
+ }
+
+ /**
+ * resolve tools.
+ *
+ * @param player
+ * player that wants to resolve
+ * @param inputResources
+ * really don't know todo
+ * @param outputResources
+ * don't know either todo
+ *
+ * @return ACTION_DONE when player can resolve tools, FAILURE otherwise
+ */
+ @Override
+ public ActionResult makeAction(final Player player, final Effect[] inputResources, final Effect[] outputResources) {
+ boolean res = tools.actionToolMaker(player);
+ if (res) {
+ return ActionResult.ACTION_DONE;
+ } else {
+ return ActionResult.FAILURE;
+ }
+ }
+
+ // todo
+
+ /**
+ * does exactly nothing.
+ *
+ * @param player
+ * player to do nothing with
+ *
+ * @return false
+ */
+ @Override
+ public boolean skipAction(final Player player) {
+ return false;
+ }
+
+ // todo
+
+ /**
+ * does exactly nothing.
+ *
+ * @param player
+ * player to do nothing with
+ *
+ * @return null
+ */
+ @Override
+ public HasAction tryToMakeAction(final Player player) {
+ return null;
+ }
+
+ // todo
+
+ /**
+ * does exactly nothing.
+ *
+ * @return false
+ */
+ @Override
+ public boolean newTurn() {
+ return false;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/Player.java b/src/main/java/sk/uniba/fmph/dcs/game_board/Player.java
new file mode 100644
index 00000000..b042f014
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/Player.java
@@ -0,0 +1,13 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.InterfacePlayerBoardGameBoard;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+
+/**
+ * @param playerOrder
+ * Player's order in the game
+ * @param playerBoard
+ * Interface for the player's board in the game
+ */
+public record Player(PlayerOrder playerOrder, InterfacePlayerBoardGameBoard playerBoard) {
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/RewardMenu.java b/src/main/java/sk/uniba/fmph/dcs/game_board/RewardMenu.java
new file mode 100644
index 00000000..fb3925dc
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/RewardMenu.java
@@ -0,0 +1,123 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+import sk.uniba.fmph.dcs.stone_age.InterfaceTakeReward;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class RewardMenu implements InterfaceTakeReward {
+ private final List menu;
+ private final List players;
+ private List playersLeft;
+
+ /**
+ * creates class.
+ *
+ * @param menu
+ * resources availible to take
+ * @param players
+ * list of all players
+ */
+ public RewardMenu(final List menu, final List players) {
+ this.menu = new ArrayList<>();
+ this.menu.addAll(menu);
+ this.players = new ArrayList<>();
+ this.players.addAll(players);
+ playersLeft = players.stream().map(Player::playerOrder).collect(Collectors.toList());
+ }
+
+ /**
+ * I mean who does not know what this does maven?.
+ *
+ * @return registered players count
+ */
+ public int getPlayersCount() {
+ return players.size();
+ }
+
+ /**
+ * don't really know why is this, I guess so that I can restart menu.
+ *
+ * @param menu
+ * new menu that replaces the old one
+ */
+ public void initiate(final List menu) {
+ menu.clear();
+ this.menu.addAll(menu);
+ playersLeft = players.stream().map(Player::playerOrder).collect(Collectors.toList());
+ }
+
+ /**
+ * @return items left to choose and players choosing.
+ */
+ public String state() {
+ return "Currently availible: " + menu.toString() + "\n" + "Players remaining: " + players.toString() + "\n";
+ }
+
+ private Player getPlayerFromPlayerOrder(final PlayerOrder player) {
+ Player p = null;
+ for (var i : players) {
+ if (i.playerOrder().equals(player)) {
+ p = i;
+ }
+ }
+ return p;
+ }
+
+ /**
+ * removes reward from menu and gives it to player.
+ *
+ * @param player
+ * gives reward to player with this order
+ * @param reward
+ * reward from menu
+ *
+ * @return `true` if found player with order `player` and reward is in menu, `false` otherwise
+ */
+ @Override
+ public boolean takeReward(final PlayerOrder player, final Effect reward) {
+ if (!menu.contains(reward)) {
+ return false;
+ }
+ Player p = getPlayerFromPlayerOrder(player);
+ if (p == null) {
+ return false;
+ }
+ if (!playersLeft.contains(player)) {
+ return false;
+ }
+ playersLeft.remove(player);
+ menu.remove(reward);
+ p.playerBoard().giveEffect(new Effect[] {reward});
+ return true;
+ }
+
+ /**
+ * don't really know either.
+ *
+ * @param player
+ * can this player take something
+ *
+ * @return NO_ACTION_POSSIBLE when either player is not allowed to choose or menu is empty
+ */
+ @Override
+ public HasAction tryMakeAction(final PlayerOrder player) {
+ if (menu.isEmpty()) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (!playersLeft.contains(player)) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (menu.size() == 1) {
+ Player p = getPlayerFromPlayerOrder(player);
+ p.playerBoard().giveEffect(menu.toArray(new Effect[0]));
+ playersLeft.remove(player);
+ return HasAction.AUTOMATIC_ACTION_DONE;
+ }
+ return HasAction.WAITING_FOR_PLAYER_ACTION;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/SimpleBuilding.java b/src/main/java/sk/uniba/fmph/dcs/game_board/SimpleBuilding.java
index 5d4c9d36..21769146 100644
--- a/src/main/java/sk/uniba/fmph/dcs/game_board/SimpleBuilding.java
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/SimpleBuilding.java
@@ -2,10 +2,12 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Map;
import java.util.OptionalInt;
import org.apache.commons.collections4.CollectionUtils;
+import org.json.JSONObject;
import sk.uniba.fmph.dcs.stone_age.Effect;
public final class SimpleBuilding implements Building {
@@ -32,4 +34,10 @@ public OptionalInt build(final Collection resources) {
}
return OptionalInt.of(sum);
}
+
+ @Override
+ public String state() {
+ Map state = Map.of("requiredResources", requiredResources.toString());
+ return new JSONObject(state).toString();
+ }
}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/Throw.java b/src/main/java/sk/uniba/fmph/dcs/game_board/Throw.java
new file mode 100644
index 00000000..2dc1b8e2
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/Throw.java
@@ -0,0 +1,29 @@
+package sk.uniba.fmph.dcs.game_board;
+
+public final class Throw {
+ private static final int DICESIDES = 6;
+
+ private Throw() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ private static int randomDice() {
+ return (int) (Math.random() * DICESIDES) + 1;
+ }
+
+ /**
+ * renamed to hod so that it won't conflict with compilers.
+ *
+ * @param dices
+ * number of dices to throw
+ *
+ * @return resulting throws
+ */
+ public static int[] hod(final int dices) {
+ int[] res = new int[dices];
+ for (int i = 0; i < dices; i++) {
+ res[i] = randomDice();
+ }
+ return res;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/ToolMakerHutsFields.java b/src/main/java/sk/uniba/fmph/dcs/game_board/ToolMakerHutsFields.java
new file mode 100644
index 00000000..951d520b
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/ToolMakerHutsFields.java
@@ -0,0 +1,193 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import org.json.JSONObject;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class ToolMakerHutsFields {
+ private static final int MAX_FILLED_RESTRICTION = 2;
+ private final List toolMakerFigures;
+ private final List hutFigures;
+ private final List fieldsFigures;
+ private final int restriction;
+ private static final int FOUR_PLAYERS = 4;
+
+ private boolean violatesRestriction() {
+ int result = (toolMakerFigures.isEmpty() ? 1 : 0) + (hutFigures.isEmpty() ? 1 : 0)
+ + (fieldsFigures.isEmpty() ? 1 : 0);
+ if (restriction == FOUR_PLAYERS) {
+ return false;
+ } else {
+ return result < MAX_FILLED_RESTRICTION;
+ }
+ }
+
+ /**
+ * @param playerCount
+ * needed for restrictions
+ */
+ public ToolMakerHutsFields(final int playerCount) {
+ toolMakerFigures = new ArrayList<>();
+ hutFigures = new ArrayList<>();
+ fieldsFigures = new ArrayList<>();
+ this.restriction = playerCount;
+ }
+
+ /**
+ * resolve action place on toolmaker.
+ *
+ * @param player
+ * player to place
+ *
+ * @return true if action can be completed
+ */
+ public boolean placeOnToolMaker(final Player player) {
+ if (!canPlaceOnToolMaker(player)) {
+ return false;
+ }
+ toolMakerFigures.add(player.playerOrder());
+ return true;
+ }
+
+ /**
+ * resolve action toolmaker.
+ *
+ * @param player
+ * player to give resource to
+ *
+ * @return true if action can be completed
+ */
+ public boolean actionToolMaker(final Player player) {
+ if (!toolMakerFigures.getFirst().equals(player.playerOrder())) {
+ return false;
+ }
+ player.playerBoard().giveEffect(new Effect[] {Effect.TOOL});
+ return true;
+ }
+
+ /**
+ * @param player
+ * irrelevant
+ *
+ * @return true if figure can be placed on toolmaker
+ */
+ public boolean canPlaceOnToolMaker(final Player player) {
+ if (violatesRestriction()) {
+ return false;
+ }
+ return toolMakerFigures.isEmpty();
+ }
+
+ /**
+ * resolve action place on hut.
+ *
+ * @param player
+ * player to place
+ *
+ * @return true if action can be completed
+ */
+ public boolean placeOnHut(final Player player) {
+ if (!canPlaceOnHut(player)) {
+ return false;
+ }
+ hutFigures.add(player.playerOrder());
+ hutFigures.add(player.playerOrder());
+ return true;
+ }
+
+ /**
+ * resolve action hut.
+ *
+ * @param player
+ * player to place
+ *
+ * @return true if action can be completed
+ */
+ public boolean actionHut(final Player player) {
+ if (!hutFigures.getFirst().equals(player.playerOrder())) {
+ return false;
+ }
+ player.playerBoard().giveFigure();
+ return false;
+ }
+
+ /**
+ * @param player
+ * irrelevant
+ *
+ * @return true figure can be placed on hut
+ */
+ public boolean canPlaceOnHut(final Player player) {
+ if (violatesRestriction()) {
+ return false;
+ }
+ return hutFigures.isEmpty();
+ }
+
+ /**
+ * resolve action place on fields.
+ *
+ * @param player
+ * player to place
+ *
+ * @return true if action can be completed
+ */
+ public boolean placeOnFields(final Player player) {
+ if (!canPlaceOnFields(player)) {
+ return false;
+ }
+ fieldsFigures.add(player.playerOrder());
+ return true;
+ }
+
+ /**
+ * resolve action fields.
+ *
+ * @param player
+ * player to give resource to
+ *
+ * @return true if action can be completed
+ */
+ public boolean actionFields(final Player player) {
+ if (!fieldsFigures.getFirst().equals(player.playerOrder())) {
+ return false;
+ }
+ player.playerBoard().giveEffect(new Effect[] {Effect.FIELD});
+ return false;
+ }
+
+ /**
+ * @param player
+ * irrelevant
+ *
+ * @return true if figure can be placed on fields
+ */
+ public boolean canPlaceOnFields(final Player player) {
+ if (violatesRestriction()) {
+ return false;
+ }
+ return fieldsFigures.isEmpty();
+ }
+
+ /**
+ * reset class so that it can work on new turn.
+ */
+ public void newTurn() {
+ toolMakerFigures.clear();
+ hutFigures.clear();
+ fieldsFigures.clear();
+ }
+
+ /**
+ * @return state of figure placment
+ */
+ public String state() {
+ Map state = Map.of("toolMakerFigures", toolMakerFigures.toString(), "hutFigures",
+ hutFigures.toString(), "fieldsFigures", fieldsFigures.toString());
+ return new JSONObject(state).toString();
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_board/VariableBuilding.java b/src/main/java/sk/uniba/fmph/dcs/game_board/VariableBuilding.java
new file mode 100644
index 00000000..dd75e6af
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_board/VariableBuilding.java
@@ -0,0 +1,40 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import org.json.JSONObject;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.Collection;
+import java.util.OptionalInt;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Map;
+
+public final class VariableBuilding implements Building {
+ private final int numberOfResources;
+ private final int numberOfResourcesTypes;
+
+ public VariableBuilding(final int numberOfResources, final int numberOfResourcesTypes) {
+ this.numberOfResources = numberOfResources;
+ this.numberOfResourcesTypes = numberOfResourcesTypes;
+ }
+
+ @Override
+ public OptionalInt build(final Collection resources) {
+ Set types = new TreeSet<>(resources);
+ if (resources.size() != numberOfResources || types.size() != numberOfResourcesTypes) {
+ return OptionalInt.empty();
+ }
+ int sum = 0;
+ for (Effect resource : resources) {
+ sum += resource.points();
+ }
+ return OptionalInt.of(sum);
+ }
+
+ @Override
+ public String state() {
+ Map state = Map.of("numberOfResources", Integer.toString(numberOfResources),
+ "numberOfResourcesTypes", Integer.toString(numberOfResourcesTypes));
+ return new JSONObject(state).toString();
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/AllPlayersTakeARewardState.java b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/AllPlayersTakeARewardState.java
new file mode 100644
index 00000000..ea4e928f
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/AllPlayersTakeARewardState.java
@@ -0,0 +1,70 @@
+package sk.uniba.fmph.dcs.game_phase_controller;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+import sk.uniba.fmph.dcs.stone_age.InterfaceTakeReward;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+import sk.uniba.fmph.dcs.stone_age.Location;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.Collection;
+
+public final class AllPlayersTakeARewardState implements InterfaceGamePhaseState {
+
+ private final InterfaceTakeReward interfaceTakeReward;
+
+ public AllPlayersTakeARewardState(final InterfaceTakeReward interfaceTakeReward) {
+ this.interfaceTakeReward = interfaceTakeReward;
+ }
+
+ @Override
+ public ActionResult placeFigures(final PlayerOrder player, final Location location, final int figuresCount) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAction(final PlayerOrder player, final Location location,
+ final Collection inputResources, final Collection outputResources) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult skipAction(final PlayerOrder player, final Location location) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult useTools(final PlayerOrder player, final int toolIndex) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult noMoreToolsThisThrow(final PlayerOrder player) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult feedTribe(final PlayerOrder player, final Collection resources) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult doNotFeedThisTurn(final PlayerOrder player) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAllPlayersTakeARewardChoice(final PlayerOrder player, final Effect reward) {
+ boolean success = interfaceTakeReward.takeReward(player, reward);
+ if (success) {
+ return ActionResult.ACTION_DONE;
+ } else {
+ return ActionResult.FAILURE;
+ }
+ }
+
+ @Override
+ public HasAction tryToMakeAutomaticAction(final PlayerOrder player) {
+ return interfaceTakeReward.tryMakeAction(player);
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/FeedTribeState.java b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/FeedTribeState.java
new file mode 100644
index 00000000..d3c2da90
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/FeedTribeState.java
@@ -0,0 +1,80 @@
+package sk.uniba.fmph.dcs.game_phase_controller;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+import sk.uniba.fmph.dcs.stone_age.Location;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+import sk.uniba.fmph.dcs.stone_age.InterfaceFeedTribe;
+
+import java.util.Collection;
+import java.util.Map;
+
+public final class FeedTribeState implements InterfaceGamePhaseState {
+
+ private final Map interfaceFeedTribeCollection;
+
+ public FeedTribeState(final Map interfaceFeedTribeCollection) {
+ this.interfaceFeedTribeCollection = interfaceFeedTribeCollection;
+ }
+
+ @Override
+ public ActionResult placeFigures(final PlayerOrder player, final Location location, final int figuresCount) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAction(final PlayerOrder player, final Location location,
+ final Collection inputResources, final Collection outputResources) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult skipAction(final PlayerOrder player, final Location location) {
+ return ActionResult.FAILURE;
+
+ }
+
+ @Override
+ public ActionResult useTools(final PlayerOrder player, final int toolIndex) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult noMoreToolsThisThrow(final PlayerOrder player) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult feedTribe(final PlayerOrder player, final Collection resources) {
+ if (interfaceFeedTribeCollection.get(player).feedTribe(resources)) {
+ return ActionResult.ACTION_DONE;
+ }
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult doNotFeedThisTurn(final PlayerOrder player) {
+ if (interfaceFeedTribeCollection.get(player).doNotFeedThisTurn()) {
+ return ActionResult.ACTION_DONE;
+ }
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAllPlayersTakeARewardChoice(final PlayerOrder player, final Effect reward) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public HasAction tryToMakeAutomaticAction(final PlayerOrder player) {
+ if (interfaceFeedTribeCollection.get(player).isTribeFed()) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (interfaceFeedTribeCollection.get(player).feedTribeIfEnoughFood()) {
+ return HasAction.AUTOMATIC_ACTION_DONE;
+ }
+
+ return HasAction.WAITING_FOR_PLAYER_ACTION;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/GameEndState.java b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/GameEndState.java
new file mode 100644
index 00000000..109e474d
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/GameEndState.java
@@ -0,0 +1,57 @@
+package sk.uniba.fmph.dcs.game_phase_controller;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+import sk.uniba.fmph.dcs.stone_age.Location;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+
+import java.util.Collection;
+
+public final class GameEndState implements InterfaceGamePhaseState {
+ @Override
+ public ActionResult placeFigures(final PlayerOrder player, final Location location, final int figuresCount) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAction(final PlayerOrder player, final Location location,
+ final Collection inputResources, final Collection outputResources) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult skipAction(final PlayerOrder player, final Location location) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult useTools(final PlayerOrder player, final int toolIndex) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult noMoreToolsThisThrow(final PlayerOrder player) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult feedTribe(final PlayerOrder player, final Collection resources) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult doNotFeedThisTurn(final PlayerOrder player) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAllPlayersTakeARewardChoice(final PlayerOrder player, final Effect reward) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public HasAction tryToMakeAutomaticAction(final PlayerOrder player) {
+ return HasAction.WAITING_FOR_PLAYER_ACTION;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/GamePhaseController.java b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/GamePhaseController.java
index cf94b721..b0c7f256 100644
--- a/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/GamePhaseController.java
+++ b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/GamePhaseController.java
@@ -1,17 +1,16 @@
package sk.uniba.fmph.dcs.game_phase_controller;
-import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
-import sk.uniba.fmph.dcs.stone_age.Location;
+import org.json.JSONObject;
import sk.uniba.fmph.dcs.stone_age.ActionResult;
-import sk.uniba.fmph.dcs.stone_age.HasAction;
import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
import sk.uniba.fmph.dcs.stone_age.InterfaceGamePhaseController;
-import java.util.Map;
-import java.util.Optional;
-
-import org.json.JSONObject;
+import sk.uniba.fmph.dcs.stone_age.Location;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
public final class GamePhaseController implements InterfaceGamePhaseController {
private Map dispatchers;
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/InterfaceGamePhaseState.java b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/InterfaceGamePhaseState.java
index 1612e5c6..c6a934c8 100644
--- a/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/InterfaceGamePhaseState.java
+++ b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/InterfaceGamePhaseState.java
@@ -1,11 +1,12 @@
package sk.uniba.fmph.dcs.game_phase_controller;
-import java.util.Collection;
-import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
-import sk.uniba.fmph.dcs.stone_age.Location;
import sk.uniba.fmph.dcs.stone_age.ActionResult;
-import sk.uniba.fmph.dcs.stone_age.HasAction;
import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+import sk.uniba.fmph.dcs.stone_age.Location;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+
+import java.util.Collection;
public interface InterfaceGamePhaseState {
ActionResult placeFigures(PlayerOrder player, Location location, int figuresCount);
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/PlaceFigureState.java b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/PlaceFigureState.java
new file mode 100644
index 00000000..67250b9a
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/PlaceFigureState.java
@@ -0,0 +1,74 @@
+package sk.uniba.fmph.dcs.game_phase_controller;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.InterfaceFigureLocation;
+import sk.uniba.fmph.dcs.stone_age.Location;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+
+import java.util.Collection;
+import java.util.Map;
+
+public final class PlaceFigureState implements InterfaceGamePhaseState {
+ private final Map places;
+
+ public PlaceFigureState(final Map places) {
+ this.places = places;
+ }
+
+ @Override
+ public ActionResult placeFigures(final PlayerOrder player, final Location location, final int figuresCount) {
+ if (places.containsKey(location) && places.get(location).placeFigures(player, figuresCount)) {
+ return ActionResult.ACTION_DONE;
+ }
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAction(final PlayerOrder player, final Location location,
+ final Collection inputResources, final Collection outputResources) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult skipAction(final PlayerOrder player, final Location location) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult useTools(final PlayerOrder player, final int toolIndex) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult noMoreToolsThisThrow(final PlayerOrder player) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult feedTribe(final PlayerOrder player, final Collection resources) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult doNotFeedThisTurn(final PlayerOrder player) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAllPlayersTakeARewardChoice(final PlayerOrder player, final Effect reward) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public HasAction tryToMakeAutomaticAction(final PlayerOrder player) {
+ for (Location location : places.keySet()) {
+ HasAction has = places.get(location).tryToPlaceFigures(player, 1);
+ if (has != HasAction.NO_ACTION_POSSIBLE) {
+ return has;
+ }
+ }
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/WaitingForToolUse.java b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/WaitingForToolUse.java
new file mode 100644
index 00000000..97d9e012
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/game_phase_controller/WaitingForToolUse.java
@@ -0,0 +1,80 @@
+package sk.uniba.fmph.dcs.game_phase_controller;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+import sk.uniba.fmph.dcs.stone_age.Location;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+import sk.uniba.fmph.dcs.stone_age.InterfaceToolUse;
+
+import java.util.Collection;
+import java.util.Map;
+
+public final class WaitingForToolUse implements InterfaceGamePhaseState {
+ private final Map interfaceToolUseCollection;
+
+ public WaitingForToolUse(final Map interfaceToolUseCollection) {
+ this.interfaceToolUseCollection = interfaceToolUseCollection;
+ }
+
+ @Override
+ public ActionResult placeFigures(final PlayerOrder player, final Location location, final int figuresCount) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAction(final PlayerOrder player, final Location location,
+ final Collection inputResources, final Collection outputResources) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult skipAction(final PlayerOrder player, final Location location) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult useTools(final PlayerOrder player, final int toolIndex) {
+ if (interfaceToolUseCollection.get(player).useTool(toolIndex)) {
+ return ActionResult.ACTION_DONE;
+ } else {
+ return ActionResult.FAILURE;
+ }
+ }
+
+ @Override
+ public ActionResult noMoreToolsThisThrow(final PlayerOrder player) {
+ if (interfaceToolUseCollection.get(player).finishUsingTools()) {
+ return ActionResult.ACTION_DONE;
+ } else {
+ return ActionResult.FAILURE;
+ }
+ }
+
+ @Override
+ public ActionResult feedTribe(final PlayerOrder player, final Collection resources) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult doNotFeedThisTurn(final PlayerOrder player) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public ActionResult makeAllPlayersTakeARewardChoice(final PlayerOrder player, final Effect reward) {
+ return ActionResult.FAILURE;
+ }
+
+ @Override
+ public HasAction tryToMakeAutomaticAction(final PlayerOrder player) {
+ if (interfaceToolUseCollection.get(player) == null || !interfaceToolUseCollection.get(player).canUseTools()) {
+ return HasAction.NO_ACTION_POSSIBLE;
+ }
+ if (interfaceToolUseCollection.get(player).finishUsingTools()) {
+ return HasAction.AUTOMATIC_ACTION_DONE;
+ }
+
+ return HasAction.WAITING_FOR_PLAYER_ACTION;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerCivilisationCards.java b/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerCivilisationCards.java
new file mode 100644
index 00000000..436d3f40
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerCivilisationCards.java
@@ -0,0 +1,90 @@
+package sk.uniba.fmph.dcs.player_board;
+
+import sk.uniba.fmph.dcs.stone_age.EndOfGameEffect;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class PlayerCivilisationCards {
+
+ private Map endOfGameEffects;
+ private final EndOfGameEffect[] greenBackGround = {EndOfGameEffect.MEDICINE, EndOfGameEffect.ART,
+ EndOfGameEffect.WRITING, EndOfGameEffect.POTTERY, EndOfGameEffect.SUNDIAL, EndOfGameEffect.TRANSPORT,
+ EndOfGameEffect.MUSIC, EndOfGameEffect.WEAVING};
+
+ /**
+ * Initialization.
+ */
+ public PlayerCivilisationCards() {
+ endOfGameEffects = new HashMap<>();
+ for (EndOfGameEffect effect : EndOfGameEffect.values()) {
+ endOfGameEffects.put(effect, 0);
+ }
+ }
+
+ /**
+ * @param effects
+ * - list of effects to be added
+ */
+ public void addEndOfGameEffects(final EndOfGameEffect[] effects) {
+ for (EndOfGameEffect effect : effects) {
+ endOfGameEffects.put(effect, endOfGameEffects.get(effect) + 1);
+ }
+ }
+
+ /**
+ * @param buildings
+ * - number of buildings
+ * @param tools
+ * - sum of values of multiple use tools (check rules)
+ * @param fields
+ * - number on agriculture track
+ * @param figures
+ * - number of player figures
+ *
+ * @return - score from green cards, tools, buildings, tools, agriculture track, figures as said it should be
+ * calculated in rules
+ */
+ public int calculateEndOfGameCivilisationCardsPoints(final int buildings, final int tools, final int fields,
+ final int figures) {
+ Map endOfGameEffectsCopy = new HashMap<>();
+ for (EndOfGameEffect effect : EndOfGameEffect.values()) {
+ endOfGameEffectsCopy.put(effect, endOfGameEffects.get(effect));
+ }
+
+ int ans = 0;
+ while (true) {
+ int points = 0;
+ for (EndOfGameEffect effect : greenBackGround) {
+ if (endOfGameEffectsCopy.get(effect) > 0) {
+ points += 1;
+ endOfGameEffectsCopy.put(effect, endOfGameEffectsCopy.get(effect) - 1);
+ }
+ }
+ ans += points * points;
+ if (points == 0) {
+ break;
+ }
+ }
+
+ ans += Math.max(buildings, 0) * endOfGameEffectsCopy.get(EndOfGameEffect.BUILDER);
+ ans += Math.max(tools, 0) * endOfGameEffectsCopy.get(EndOfGameEffect.TOOL_MAKER);
+ ans += Math.max(fields, 0) * endOfGameEffectsCopy.get(EndOfGameEffect.FARMER);
+ ans += Math.max(figures, 0) * endOfGameEffectsCopy.get(EndOfGameEffect.SHAMAN);
+
+ return ans;
+ }
+
+ /**
+ * @return inner state of this class
+ */
+ public String state() {
+ StringBuilder ans = new StringBuilder();
+ for (EndOfGameEffect egf : endOfGameEffects.keySet()) {
+ if (endOfGameEffects.get(egf) > 0) {
+ ans.append(egf).append(": ").append(endOfGameEffects.get(egf)).append("\n");
+ }
+ }
+ return ans.toString();
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerFigures.java b/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerFigures.java
new file mode 100644
index 00000000..bee0c748
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerFigures.java
@@ -0,0 +1,85 @@
+package sk.uniba.fmph.dcs.player_board;
+
+public class PlayerFigures {
+ private int totalFigures;
+ private int figures;
+ private boolean canAddFigure;
+
+ private final int startingFigures = 5;
+ private final int maxFigurines = 10;
+
+ /**
+ * Give player 5 starting figures.
+ */
+ public PlayerFigures() {
+ this.totalFigures = this.startingFigures;
+ this.figures = this.startingFigures;
+ this.canAddFigure = true;
+ }
+
+ /**
+ * Adds figure to players total figures. Has no effect when he has more than 10 figures. Can add only one figure per
+ * round.
+ */
+ public void addNewFigure() {
+ if (this.totalFigures >= this.maxFigurines) {
+ return;
+ }
+
+ if (!this.canAddFigure) {
+ return;
+ }
+
+ this.totalFigures++;
+ this.canAddFigure = false;
+ }
+
+ /**
+ * @param count
+ * number of figures to be checked
+ *
+ * @return true if player has at least count available figures
+ */
+ public boolean hasFigures(final int count) {
+ return count >= 0 && this.figures >= count;
+ }
+
+ /**
+ * @return number of total figures
+ */
+ public int getTotalFigures() {
+ return totalFigures;
+ }
+
+ /**
+ * Take count figures from player if available.
+ *
+ * @param count
+ * number of figures to be taken
+ *
+ * @return true if count figures available, otherwise returns false
+ */
+ public boolean takeFigures(final int count) {
+ if (!this.hasFigures(count)) {
+ return false;
+ }
+
+ this.figures -= count;
+ return true;
+ }
+
+ /**
+ * Resets the number of available figures.
+ */
+ public void newTurn() {
+ this.figures = this.totalFigures;
+ this.canAddFigure = true;
+ }
+
+ /**
+ * @return String with total figures and available figures.
+ */
+ public String state() {
+ return "Total figures: " + this.totalFigures + ", available: " + String.valueOf(this.figures);
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerResourcesAndFood.java b/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerResourcesAndFood.java
new file mode 100644
index 00000000..045adb4a
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerResourcesAndFood.java
@@ -0,0 +1,103 @@
+package sk.uniba.fmph.dcs.player_board;
+
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.lang.Math.max;
+
+public class PlayerResourcesAndFood {
+ private final Map resources;
+
+ /**
+ * Initialise resources such that every resource is zero.
+ */
+ public PlayerResourcesAndFood() {
+ resources = new HashMap<>();
+ for (Effect res : Effect.values()) {
+ resources.put(res, 0);
+ }
+ }
+
+ /**
+ * For each resource R: if this resource is x times in list resources, this function checks if player has at least x
+ * amount of resource R.
+ *
+ * @param resources
+ * list of resources
+ *
+ * @return true if player has at least x of each resource R listed in resources (x is number of occurrences of R in
+ * resources).
+ */
+ public boolean hasResources(final Effect[] resources) {
+ Map amountToCheck = new HashMap<>();
+ for (Effect resource : resources) {
+ if (!amountToCheck.containsKey(resource)) {
+ amountToCheck.put(resource, 0);
+ }
+ amountToCheck.put(resource, amountToCheck.get(resource) + 1);
+ if (this.resources.get(resource) < amountToCheck.get(resource)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * This function increases value of resource R by one for each occurrence of R in resources.
+ *
+ * @param resources
+ * list of resources to be taken from board.
+ *
+ * @return true - always. Something else should check if player can take resource.
+ */
+ public boolean takeResources(final Effect[] resources) {
+ for (Effect resource : resources) {
+ this.resources.put(resource, this.resources.get(resource) + 1);
+ }
+ return true;
+ }
+
+ /**
+ * .
+ *
+ * @param resources
+ * - list of resources listed in Effect.
+ *
+ * @return true if player has at least one resource of each resource listed in resources.
+ */
+ public boolean giveResources(final Effect[] resources) {
+ if (this.hasResources(resources)) {
+ for (Effect resource : resources) {
+ this.resources.put(resource, max(this.resources.get(resource) - 1, 0));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @return number of points player has from resources.
+ */
+ public int numberOfResourcesForFinalPoints() {
+ int ans = 0;
+ for (Effect res : resources.keySet()) {
+ ans += res.points() * resources.get(res);
+ }
+ return ans;
+ }
+
+ /**
+ * @return state of PlayerResourcesAndFood. Only lists resources which are greater than zero.
+ */
+ public String state() {
+ StringBuilder ans = new StringBuilder();
+ for (Effect res : resources.keySet()) {
+ if (resources.get(res) > 0) {
+ ans.append(res).append(": ").append(resources.get(res)).append("\n");
+ }
+ }
+ return ans.toString();
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerTools.java b/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerTools.java
new file mode 100644
index 00000000..5810103c
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/player_board/PlayerTools.java
@@ -0,0 +1,141 @@
+package sk.uniba.fmph.dcs.player_board;
+
+import java.util.Arrays;
+
+public class PlayerTools {
+ private final int maxMultipleUseTools = 3; // total number of tool slots
+ private final int maxSingleUseTools = 3; // total number of civilisation cards
+ private final int maxTools = maxMultipleUseTools + maxSingleUseTools;
+ private final int[] tools = new int[maxTools];
+ private final int maxStrength = 4;
+ // multiple use tools + single use tools,
+ // which can be max 36 - number of civilisation cards;
+ private final boolean[] usedTools = new boolean[maxMultipleUseTools];
+ // for one time tools does not need to remember if they were used
+ // usedTools[i] is true, if tools[i] was used this turn
+
+ /**
+ * Initialise.
+ */
+ public PlayerTools() {
+ Arrays.fill(usedTools, false);
+ Arrays.fill(tools, 0);
+ }
+
+ /**
+ * Resets tools such that all are unused.
+ */
+ public void newTurn() {
+ Arrays.fill(usedTools, false);
+ }
+
+ /**
+ * Upgrades first tool, which can be upgraded.
+ */
+ public void addTool() {
+ int min = maxStrength; // highest value multiple use tool can have is 4
+ int minIndex = -1;
+ for (int i = 0; i < maxMultipleUseTools; i++) {
+ if (tools[i] < min) {
+ min = tools[i];
+ minIndex = i;
+ }
+ }
+ // we find first tool, which is not upgraded, and we upgrade it
+ // this will find first tool, which is bellow level of other tools
+ // and it will upgrade it
+
+ if (minIndex == -1) {
+ return;
+ }
+ tools[minIndex]++;
+ }
+
+ /**
+ * Adds single use tool of value strength.
+ *
+ * @param strength
+ * - value of Single use tool.
+ */
+ public void addSingleUseTool(final int strength) {
+ if (strength <= 0 || this.maxStrength < strength) {
+ return;
+ }
+
+ for (int i = maxMultipleUseTools; i < maxTools; i++) {
+ if (tools[i] == 0) {
+ tools[i] = strength;
+ break;
+ }
+ }
+ }
+
+ /**
+ * @param index
+ * - tools, which is going to be used.
+ *
+ * @return value of tools[index] or null, if tools[index] cant be used.
+ */
+ public Integer useTool(final int index) {
+ if (index < 0 || index > maxTools) {
+ return null;
+ }
+ if (index < maxMultipleUseTools) {
+ if (usedTools[index]) {
+ return null;
+ }
+ usedTools[index] = true;
+ return tools[index];
+ }
+ if (tools[index] == 0) {
+ return null;
+ }
+
+ int ans = tools[index];
+ tools[index] = 0;
+ return ans;
+ }
+
+ /**
+ * @param goal
+ * - number we need to achieve.
+ *
+ * @return - returns true if sum of available tools is at least goal.
+ */
+ public boolean hasSufficientTools(final int goal) {
+ int totalToolValue = 0;
+ for (int i = 0; i < maxMultipleUseTools; i++) {
+ if (!usedTools[i]) {
+ totalToolValue += tools[i];
+ }
+ }
+ for (int i = maxMultipleUseTools; i < maxTools; i++) {
+ totalToolValue += tools[i];
+ }
+ return totalToolValue >= goal;
+ }
+
+ /**
+ * @return state of PlayerTools. Only includes Single use tools, if they are available.
+ */
+ public String state() {
+ StringBuilder ans = new StringBuilder();
+ ans.append("multiple use tools:");
+ for (int i = 0; i < maxMultipleUseTools; i++) {
+ ans.append(" tools[").append(i).append("] = ").append(tools[i]).append(", used = ").append(usedTools[i]);
+ if (i != maxMultipleUseTools - 1) {
+ ans.append(",");
+ }
+ }
+ ans.append("\nsingle use tools:");
+ for (int i = maxMultipleUseTools; i < maxTools; i++) {
+ if (tools[i] != 0) {
+ ans.append(" tools[").append(i).append("] = ").append(tools[i]);
+ if (i != maxTools - 1) {
+ ans.append(",");
+ }
+ }
+ }
+ return ans.toString();
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/player_board/TribeFedStatus.java b/src/main/java/sk/uniba/fmph/dcs/player_board/TribeFedStatus.java
new file mode 100644
index 00000000..d050e813
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/player_board/TribeFedStatus.java
@@ -0,0 +1,180 @@
+package sk.uniba.fmph.dcs.player_board;
+
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.Arrays;
+
+public class TribeFedStatus {
+ private boolean tribeFed;
+ private int fields;
+ private final PlayerResourcesAndFood playerResourcesAndFood;
+ private final PlayerFigures playerFigures;
+
+ private boolean fieldsHarvested;
+
+ private final int startingFields = 0;
+ private final int maxFields = 10;
+
+ public TribeFedStatus(final PlayerResourcesAndFood playerResourcesAndFood, final PlayerFigures playerFigures) {
+ this.tribeFed = false;
+ this.fields = this.startingFields;
+
+ this.playerResourcesAndFood = playerResourcesAndFood;
+ this.playerFigures = playerFigures;
+
+ this.fieldsHarvested = false;
+ }
+
+ /**
+ * Adds field if bellow 10 fields.
+ */
+ public void addField() {
+ if (this.fields >= this.maxFields) {
+ return;
+ }
+
+ this.fields++;
+ playerResourcesAndFood.takeResources(new Effect[] {Effect.FIELD});
+ }
+
+ /**
+ * Set tribe to unfed and give player food according to number of fields.
+ */
+ public void newTurn() {
+ this.harvestFields();
+
+ this.tribeFed = false;
+ this.fieldsHarvested = false;
+ }
+
+ private void harvestFields() {
+ if (!this.fieldsHarvested) {
+ Effect[] food = new Effect[this.fields];
+ Arrays.fill(food, Effect.FOOD);
+ this.playerResourcesAndFood.takeResources(food);
+ this.fieldsHarvested = true;
+ }
+ }
+
+ /**
+ * Attempts to feed the tribe with only food.
+ *
+ * @return true if tribe was successfully fed.
+ */
+ public boolean feedTribeIfEnoughFood() {
+ this.harvestFields();
+
+ if (this.tribeFed) {
+ return true;
+ }
+
+ Effect[] foodRequired = new Effect[this.playerFigures.getTotalFigures()];
+ Arrays.fill(foodRequired, Effect.FOOD);
+
+ if (!playerResourcesAndFood.hasResources(foodRequired)) {
+ return false;
+ }
+
+ this.playerResourcesAndFood.giveResources(foodRequired);
+ this.tribeFed = true;
+ return true;
+ }
+
+ /**
+ * Attempts to feed the tribe with those resources.
+ *
+ * @param resources
+ * resources
+ *
+ * @return true if tribe was successfully fed.
+ */
+ public boolean feedTribe(final Effect[] resources) {
+ this.harvestFields();
+
+ if (this.tribeFed) {
+ return true;
+ }
+
+ if (!this.playerResourcesAndFood.hasResources(resources)) {
+ return false;
+ }
+
+ int numberOfFood = 0;
+ int numberOfResources = 0;
+ for (Effect resource : resources) {
+ if (resource.isResource()) {
+ numberOfResources++;
+ } else if (resource == Effect.FOOD) {
+ numberOfFood++;
+ }
+ }
+
+ // checks if player has more food
+ Effect[] food = new Effect[numberOfFood + 1];
+ Arrays.fill(food, Effect.FOOD);
+ if (this.playerResourcesAndFood.hasResources(food)) {
+ return false;
+ }
+
+ // not right amount of food + resources
+ if (numberOfFood + numberOfResources != this.playerFigures.getTotalFigures()) {
+ return false;
+ }
+
+ // only using food or resource
+ for (Effect effect : resources) {
+ if (!effect.isResourceOrFood()) {
+ return false;
+ }
+ }
+
+ this.playerResourcesAndFood.giveResources(resources);
+ this.tribeFed = true;
+
+ return true;
+ }
+
+ /**
+ * Feeds the tribe if player does not have enough food. Should lose 10 victory points after this.
+ *
+ * @return true if tribe was fed.
+ */
+ public boolean setTribeFed() {
+ this.harvestFields();
+
+ if (this.tribeFed) {
+ return false;
+ }
+
+ Effect[] foodRequired = new Effect[this.playerFigures.getTotalFigures()];
+ Arrays.fill(foodRequired, Effect.FOOD);
+
+ if (this.playerResourcesAndFood.hasResources(foodRequired)) {
+ return false;
+ }
+
+ Effect[] oneFood = new Effect[1];
+ oneFood[0] = Effect.FOOD;
+ while (this.playerResourcesAndFood.hasResources(oneFood)) {
+ this.playerResourcesAndFood.giveResources(oneFood);
+ }
+
+ this.tribeFed = true;
+
+ return true;
+ }
+
+ /**
+ * @return true if tribe is fed
+ */
+ public boolean isTribeFed() {
+ return this.tribeFed;
+ }
+
+ /**
+ * @return string with fed status and number of fields.
+ */
+ public String state() {
+ return "Fed: " + this.tribeFed + ", # of fields: " + this.fields;
+ }
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/CivilisationCard.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/CivilisationCard.java
new file mode 100644
index 00000000..baf35870
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/CivilisationCard.java
@@ -0,0 +1,4 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public record CivilisationCard(ImmediateEffect[] immediateEffect, EndOfGameEffect[] endOfGameEffect) {
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/EndOfGameEffect.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/EndOfGameEffect.java
new file mode 100644
index 00000000..f48d844e
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/EndOfGameEffect.java
@@ -0,0 +1,5 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public enum EndOfGameEffect {
+ FARMER, TOOL_MAKER, BUILDER, SHAMAN, MEDICINE, ART, MUSIC, WRITING, SUNDIAL, POTTERY, TRANSPORT, WEAVING
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/HasAction.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/HasAction.java
index c7a0e130..b4f10ec5 100644
--- a/src/main/java/sk/uniba/fmph/dcs/stone_age/HasAction.java
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/HasAction.java
@@ -1,5 +1,5 @@
package sk.uniba.fmph.dcs.stone_age;
public enum HasAction {
- WAITING_FOR_PLAYER_ACTION, AUTOMATIC_ACTION_DONE, NO_ACTION_POSSIBLE,
+ WAITING_FOR_PLAYER_ACTION, AUTOMATIC_ACTION_DONE, NO_ACTION_POSSIBLE
}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/ImmediateEffect.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/ImmediateEffect.java
new file mode 100644
index 00000000..e94df9fa
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/ImmediateEffect.java
@@ -0,0 +1,6 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public enum ImmediateEffect {
+ THROW_WOOD, THROW_CLAY, THROW_STONE, THROW_GOLD, POINT, WOOD, CLAY, STONE, GOLD, CARD, ARBITRARY_RESOURCE, FOOD,
+ ALL_PLAYERS_TAKE_REWARD
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceFeedTribe.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceFeedTribe.java
new file mode 100644
index 00000000..55eff793
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceFeedTribe.java
@@ -0,0 +1,14 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+import java.util.Collection;
+
+public interface InterfaceFeedTribe {
+ boolean feedTribeIfEnoughFood();
+
+ boolean feedTribe(Collection resources);
+
+ boolean doNotFeedThisTurn();
+
+ boolean isTribeFed();
+
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceFigureLocation.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceFigureLocation.java
new file mode 100644
index 00000000..17fa5542
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceFigureLocation.java
@@ -0,0 +1,18 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+import java.util.Collection;
+
+public interface InterfaceFigureLocation {
+ boolean placeFigures(PlayerOrder player, int figureCount);
+
+ HasAction tryToPlaceFigures(PlayerOrder player, int count);
+
+ ActionResult makeAction(PlayerOrder player, Collection inputResources, Collection outputResources);
+
+ boolean skipAction(PlayerOrder player);
+
+ HasAction tryToMakeAction(PlayerOrder player);
+
+ boolean newTurn(); // Returns true if end of game is implied by the current state
+
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceGetState.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceGetState.java
new file mode 100644
index 00000000..5dc5b4f8
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceGetState.java
@@ -0,0 +1,5 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public interface InterfaceGetState {
+ String state();
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceNewTurn.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceNewTurn.java
new file mode 100644
index 00000000..f3d860ae
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceNewTurn.java
@@ -0,0 +1,5 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public interface InterfaceNewTurn {
+ void newTurn();
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfacePlayerBoardGameBoard.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfacePlayerBoardGameBoard.java
new file mode 100644
index 00000000..b399f76d
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfacePlayerBoardGameBoard.java
@@ -0,0 +1,22 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+import java.util.Optional;
+
+public interface InterfacePlayerBoardGameBoard {
+ void giveEffect(Effect[] stuff);
+
+ void giveEndOfGameEffect(EndOfGameEffect[] stuff);
+
+ boolean takeResources(Effect[] stuff);
+
+ void giveFigure();
+
+ boolean takeFigures(int count);
+
+ boolean hasFigures(int count);
+
+ boolean hasSufficientTools(int goal);
+
+ Optional useTool(int idx);
+
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceStoneAgeGame.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceStoneAgeGame.java
new file mode 100644
index 00000000..654f4426
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceStoneAgeGame.java
@@ -0,0 +1,21 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public interface InterfaceStoneAgeGame {
+ boolean placeFigures(int playerId, Location location, int figuresCount);
+
+ boolean makeAction(int playerId, Location location, Effect[] usedResources, Effect[] desiredResources);
+
+ boolean skipAction(int playerId, Location location); // : bool (only if resources are required) todo neviem co to
+ // znamena
+
+ boolean useTools(int playerId, int toolIndex); // : bool {affects last action} todo neviem co to znamena
+
+ boolean noMoreToolsThisThrow(int playerId);
+
+ boolean feedTribe(int playerId, Effect[] resources);
+
+ boolean doNotFeedThisTurn(int playerId);
+
+ boolean makeAllPlayersTakeARewardChoice(int playerId, Effect reward);
+
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceStoneAgeObservable.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceStoneAgeObservable.java
new file mode 100644
index 00000000..716f5b96
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceStoneAgeObservable.java
@@ -0,0 +1,5 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public interface InterfaceStoneAgeObservable {
+ void registerObserver(int playerId, InterfaceStoneAgeObservable observer);
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceStoneAgeObserver.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceStoneAgeObserver.java
new file mode 100644
index 00000000..cc058392
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceStoneAgeObserver.java
@@ -0,0 +1,5 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public interface InterfaceStoneAgeObserver {
+ void update(String gameState);
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceTakeReward.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceTakeReward.java
new file mode 100644
index 00000000..61e7ce3f
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceTakeReward.java
@@ -0,0 +1,8 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public interface InterfaceTakeReward {
+ boolean takeReward(PlayerOrder player, Effect reward);
+
+ HasAction tryMakeAction(PlayerOrder player);
+
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceToolUse.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceToolUse.java
new file mode 100644
index 00000000..bf2cc57a
--- /dev/null
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/InterfaceToolUse.java
@@ -0,0 +1,10 @@
+package sk.uniba.fmph.dcs.stone_age;
+
+public interface InterfaceToolUse {
+ boolean useTool(int idx);
+
+ boolean canUseTools();
+
+ boolean finishUsingTools();
+
+}
diff --git a/src/main/java/sk/uniba/fmph/dcs/stone_age/Location.java b/src/main/java/sk/uniba/fmph/dcs/stone_age/Location.java
index 583cae6a..2587b1f7 100644
--- a/src/main/java/sk/uniba/fmph/dcs/stone_age/Location.java
+++ b/src/main/java/sk/uniba/fmph/dcs/stone_age/Location.java
@@ -1,6 +1,6 @@
package sk.uniba.fmph.dcs.stone_age;
public enum Location {
- TOOL_MAKER, HUT, FIELD, HUNTING_GROUNDS, FOREST, CLAY_MOUND, QUARY, RIVER, CIVILISATION_CARD1, CIVILISATION_CARD2,
+ TOOL_MAKER, HUT, FIELD, HUNTING_GROUNDS, FOREST, CLAY_MOUND, QUARRY, RIVER, CIVILISATION_CARD1, CIVILISATION_CARD2,
CIVILISATION_CARD3, CIVILISATION_CARD4, BUILDING_TILE1, BUILDING_TILE2, BUILDING_TILE3, BUILDING_TILE4,
}
diff --git a/src/test/java/sk/uniba/fmph/dcs/game_board/ArbitraryBuildingTest.java b/src/test/java/sk/uniba/fmph/dcs/game_board/ArbitraryBuildingTest.java
new file mode 100644
index 00000000..e5786912
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/game_board/ArbitraryBuildingTest.java
@@ -0,0 +1,37 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import org.junit.Test;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.ArrayList;
+import java.util.OptionalInt;
+
+import static org.junit.Assert.assertEquals;
+
+public class ArbitraryBuildingTest {
+ @Test
+ public void test_calculation() {
+ // todo toto by mal spravit niekto iny ako ja zrejme
+
+ ArbitraryBuilding building = new ArbitraryBuilding(4);
+
+ ArrayList goodResources = new ArrayList();
+ goodResources.add(Effect.WOOD);
+ assertEquals(building.build(goodResources), OptionalInt.of(3));
+
+ goodResources.clear();
+ goodResources.add(Effect.GOLD);
+ goodResources.add(Effect.WOOD);
+ goodResources.add(Effect.STONE);
+ goodResources.add(Effect.CLAY);
+ assertEquals(building.build(goodResources), OptionalInt.of(3 + 4 + 5 + 6));
+
+ ArrayList wrongResources = new ArrayList();
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.WOOD);
+ assertEquals(building.build(wrongResources), OptionalInt.empty());
+ }
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/game_board/VariableBuildingTest.java b/src/test/java/sk/uniba/fmph/dcs/game_board/VariableBuildingTest.java
new file mode 100644
index 00000000..c5ae7380
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/game_board/VariableBuildingTest.java
@@ -0,0 +1,52 @@
+package sk.uniba.fmph.dcs.game_board;
+
+import org.junit.Test;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.ArrayList;
+import java.util.OptionalInt;
+
+import static org.junit.Assert.assertEquals;
+
+public class VariableBuildingTest {
+ @Test
+ public void test_calculation() {
+ // todo toto by mal spravit niekto iny ako ja zrejme
+
+ VariableBuilding building = new VariableBuilding(4, 2);
+
+ ArrayList wrongResources = new ArrayList();
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.CLAY);
+ assertEquals(building.build(wrongResources), OptionalInt.empty());
+
+ ArrayList goodResources = new ArrayList();
+ goodResources.add(Effect.GOLD);
+ goodResources.add(Effect.GOLD);
+ goodResources.add(Effect.STONE);
+ goodResources.add(Effect.STONE);
+ assertEquals(building.build(goodResources), OptionalInt.of(6 + 6 + 5 + 5));
+
+ wrongResources.clear();
+ wrongResources.add(Effect.STONE);
+ wrongResources.add(Effect.STONE);
+ wrongResources.add(Effect.STONE);
+ wrongResources.add(Effect.STONE);
+ assertEquals(building.build(wrongResources), OptionalInt.empty());
+
+ wrongResources.clear();
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.WOOD);
+ assertEquals(building.build(wrongResources), OptionalInt.empty());
+
+ wrongResources.clear();
+ wrongResources.add(Effect.WOOD);
+ wrongResources.add(Effect.CLAY);
+ wrongResources.add(Effect.GOLD);
+ wrongResources.add(Effect.WOOD);
+ assertEquals(building.build(wrongResources), OptionalInt.empty());
+ }
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/FeedTribeStateTest.java b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/FeedTribeStateTest.java
new file mode 100644
index 00000000..e0c34190
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/FeedTribeStateTest.java
@@ -0,0 +1,92 @@
+package sk.uniba.fmph.dcs.game_phase_controller;
+
+import org.junit.Test;
+import sk.uniba.fmph.dcs.stone_age.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+
+import static org.junit.Assert.assertEquals;
+
+public class FeedTribeStateTest {
+
+ private static class InterfaceFeedTribeMock implements InterfaceFeedTribe {
+ private final int figures;
+ private final int food;
+ private final boolean returnValue;
+
+ InterfaceFeedTribeMock(int figures, int food, boolean ret) {
+ this.figures = figures;
+ this.food = food;
+ returnValue = ret;
+ }
+
+ @Override
+ public boolean feedTribeIfEnoughFood() {
+ return food >= figures;
+ }
+
+ @Override
+ public boolean feedTribe(Collection resources) {
+ return returnValue;
+ }
+
+ @Override
+ public boolean doNotFeedThisTurn() {
+ return returnValue;
+ }
+
+ @Override
+ public boolean isTribeFed() {
+ return returnValue;
+ }
+ }
+
+ @Test
+ public void test_tryToMakeAutomaticAction() {
+ HashMap map = new HashMap<>();
+ PlayerOrder player1 = new PlayerOrder(1, 1);
+ PlayerOrder player2 = new PlayerOrder(2, 2);
+ PlayerOrder player3 = new PlayerOrder(3, 3);
+
+ map.put(player1, new InterfaceFeedTribeMock(2, 1, false));
+ map.put(player2, new InterfaceFeedTribeMock(2, 1, true));
+ map.put(player3, new InterfaceFeedTribeMock(1, 2, false));
+
+ FeedTribeState feedState = new FeedTribeState(map);
+ assertEquals(feedState.tryToMakeAutomaticAction(player1), HasAction.WAITING_FOR_PLAYER_ACTION);
+ assertEquals(feedState.tryToMakeAutomaticAction(player2), HasAction.NO_ACTION_POSSIBLE);
+ assertEquals(feedState.tryToMakeAutomaticAction(player3), HasAction.AUTOMATIC_ACTION_DONE);
+ }
+
+ @Test
+ public void test_feedTribe() {
+ HashMap map = new HashMap<>();
+ PlayerOrder player1 = new PlayerOrder(1, 1);
+ PlayerOrder player2 = new PlayerOrder(2, 2);
+
+ map.put(player1, new InterfaceFeedTribeMock(2, 2, false));
+ map.put(player2, new InterfaceFeedTribeMock(2, 2, true));
+ ArrayList resources = new ArrayList<>();
+
+ FeedTribeState feedState = new FeedTribeState(map);
+
+ assertEquals(feedState.feedTribe(player1, resources), ActionResult.FAILURE);
+ assertEquals(feedState.feedTribe(player2, resources), ActionResult.ACTION_DONE);
+ }
+
+ @Test
+ public void test_doNotFeedThisTurn() {
+ HashMap map = new HashMap<>();
+ PlayerOrder player1 = new PlayerOrder(1, 1);
+ PlayerOrder player2 = new PlayerOrder(2, 2);
+ FeedTribeState feedState = new FeedTribeState(map);
+
+ map.put(player1, new InterfaceFeedTribeMock(2, 2, false));
+ map.put(player2, new InterfaceFeedTribeMock(2, 2, true));
+
+ assertEquals(feedState.doNotFeedThisTurn(player1), ActionResult.FAILURE);
+ assertEquals(feedState.doNotFeedThisTurn(player2), ActionResult.ACTION_DONE);
+ }
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/GameEndStateTest.java b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/GameEndStateTest.java
new file mode 100644
index 00000000..ee7fff04
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/GameEndStateTest.java
@@ -0,0 +1,41 @@
+package sk.uniba.fmph.dcs.game_phase_controller;
+
+import org.junit.Test;
+import sk.uniba.fmph.dcs.stone_age.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+public class GameEndStateTest {
+ @Test
+ public void test_tryToMakeAutomaticAction() {
+ GameEndState gameEndState = new GameEndState();
+ int order = 1;
+ int players = 1;
+ PlayerOrder player = new PlayerOrder(order, players);
+ assertEquals(gameEndState.tryToMakeAutomaticAction(player), HasAction.WAITING_FOR_PLAYER_ACTION);
+ }
+
+ @Test
+ public void test_methodsReturnActionFailure() {
+ int order = 1;
+ int players = 1;
+ PlayerOrder player = new PlayerOrder(order, players);
+
+ Collection resources = new ArrayList<>();
+
+ GameEndState gameEndState = new GameEndState();
+
+ assertEquals(gameEndState.doNotFeedThisTurn(player), ActionResult.FAILURE);
+ assertEquals(gameEndState.feedTribe(player, resources), ActionResult.FAILURE);
+ assertEquals(gameEndState.makeAction(player, Location.BUILDING_TILE1, resources, resources),
+ ActionResult.FAILURE);
+ assertEquals(gameEndState.skipAction(player, Location.BUILDING_TILE1), ActionResult.FAILURE);
+ assertEquals(gameEndState.makeAllPlayersTakeARewardChoice(player, Effect.WOOD), ActionResult.FAILURE);
+ assertEquals(gameEndState.placeFigures(player, Location.BUILDING_TILE1, 1), ActionResult.FAILURE);
+ assertEquals(gameEndState.noMoreToolsThisThrow(player), ActionResult.FAILURE);
+ assertEquals(gameEndState.useTools(player, 0), ActionResult.FAILURE);
+ }
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/GamePhaseControllerTest.java b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/GamePhaseControllerTest.java
index e5b26fd9..c33a91be 100644
--- a/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/GamePhaseControllerTest.java
+++ b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/GamePhaseControllerTest.java
@@ -3,18 +3,16 @@
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
-import org.junit.Test.None;
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+import sk.uniba.fmph.dcs.stone_age.Location;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
-import java.util.Collection;
-
-import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
-import sk.uniba.fmph.dcs.stone_age.Location;
-import sk.uniba.fmph.dcs.stone_age.ActionResult;
-import sk.uniba.fmph.dcs.stone_age.HasAction;
-import sk.uniba.fmph.dcs.stone_age.Effect;
import static org.junit.Assert.*;
diff --git a/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/PlaceFigureStateTest.java b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/PlaceFigureStateTest.java
new file mode 100644
index 00000000..bf7f4f7c
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/PlaceFigureStateTest.java
@@ -0,0 +1,88 @@
+package sk.uniba.fmph.dcs.game_phase_controller;
+
+import org.junit.Test;
+
+import sk.uniba.fmph.dcs.stone_age.ActionResult;
+import sk.uniba.fmph.dcs.stone_age.InterfaceFigureLocation;
+import sk.uniba.fmph.dcs.stone_age.Location;
+import sk.uniba.fmph.dcs.stone_age.PlayerOrder;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+import sk.uniba.fmph.dcs.stone_age.HasAction;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static sk.uniba.fmph.dcs.stone_age.Location.FIELD;
+import static sk.uniba.fmph.dcs.stone_age.Location.FOREST;
+
+public class PlaceFigureStateTest {
+
+ private static class InterfaceFigureLocationMock implements InterfaceFigureLocation {
+ @Override
+ public boolean placeFigures(PlayerOrder player, int figureCount) {
+ return figureCount == 1;
+ }
+
+ @Override
+ public HasAction tryToPlaceFigures(PlayerOrder player, int count) {
+ HasAction result = switch (player.getPlayers()) {
+ case 1 -> HasAction.AUTOMATIC_ACTION_DONE;
+ case 2 -> HasAction.WAITING_FOR_PLAYER_ACTION;
+ default -> HasAction.NO_ACTION_POSSIBLE;
+ };
+ return result;
+ }
+
+ @Override
+ public ActionResult makeAction(PlayerOrder player, Collection inputResources,
+ Collection outputResources) {
+ return null;
+ }
+
+ @Override
+ public boolean skipAction(PlayerOrder player) {
+ return false;
+ }
+
+ @Override
+ public HasAction tryToMakeAction(PlayerOrder player) {
+ return null;
+ }
+
+ @Override
+ public boolean newTurn() {
+ return false;
+ }
+ }
+
+ @Test
+ public void test_placeFigures() {
+ Map places = new HashMap<>();
+ places.put(FIELD, new InterfaceFigureLocationMock());
+ PlaceFigureState placeFigureState = new PlaceFigureState(places);
+ assertEquals(placeFigureState.placeFigures(new PlayerOrder(1, 1), FIELD, 1), ActionResult.ACTION_DONE);
+ assertEquals(placeFigureState.placeFigures(new PlayerOrder(1, 1), FOREST, 1), ActionResult.FAILURE);
+ assertEquals(placeFigureState.placeFigures(new PlayerOrder(1, 1), FIELD, 2), ActionResult.FAILURE);
+ }
+
+ @Test
+ public void test_tryToMakeAutomaticAction() {
+ Map places = new HashMap<>();
+ places.put(Location.FIELD, new InterfaceFigureLocationMock());
+ places.put(Location.HUT, new InterfaceFigureLocationMock());
+ places.put(FOREST, new InterfaceFigureLocationMock());
+
+ PlaceFigureState placeFigureState = new PlaceFigureState(places);
+
+ PlayerOrder failPlayer = new PlayerOrder(1, 3);
+ PlayerOrder actionDonePLayer = new PlayerOrder(1, 1);
+ PlayerOrder waitingPlayer = new PlayerOrder(1, 2);
+
+ assertEquals(placeFigureState.tryToMakeAutomaticAction(failPlayer), HasAction.NO_ACTION_POSSIBLE);
+ assertEquals(placeFigureState.tryToMakeAutomaticAction(actionDonePLayer), HasAction.AUTOMATIC_ACTION_DONE);
+ assertEquals(placeFigureState.tryToMakeAutomaticAction(waitingPlayer), HasAction.WAITING_FOR_PLAYER_ACTION);
+ }
+
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/WaitingForToolUseTest.java b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/WaitingForToolUseTest.java
new file mode 100644
index 00000000..4292f214
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/game_phase_controller/WaitingForToolUseTest.java
@@ -0,0 +1,67 @@
+package sk.uniba.fmph.dcs.game_phase_controller;
+
+import org.junit.Test;
+import sk.uniba.fmph.dcs.stone_age.*;
+import java.util.HashMap;
+
+import static org.junit.Assert.assertEquals;
+
+public class WaitingForToolUseTest {
+ private static class InterfaceToolUseMock implements InterfaceToolUse {
+
+ private final boolean finishedUsingTools;
+ private final boolean canUseTools;
+
+ InterfaceToolUseMock(boolean canUseTools, boolean finishedUsingTools) {
+ this.canUseTools = canUseTools;
+ this.finishedUsingTools = finishedUsingTools;
+ }
+
+ @Override
+ public boolean useTool(int idx) {
+ return canUseTools;
+ }
+
+ @Override
+ public boolean canUseTools() {
+ return canUseTools;
+ }
+
+ @Override
+ public boolean finishUsingTools() {
+ return finishedUsingTools;
+ }
+
+ }
+
+ @Test
+ public void test_tryToMakeAutomaticAction() {
+ HashMap map = new HashMap<>();
+ PlayerOrder player1 = new PlayerOrder(1, 1);
+ PlayerOrder player2 = new PlayerOrder(2, 2);
+ PlayerOrder player3 = new PlayerOrder(3, 3);
+
+ map.put(player1, new WaitingForToolUseTest.InterfaceToolUseMock(false, false));
+ map.put(player2, new WaitingForToolUseTest.InterfaceToolUseMock(false, true));
+ map.put(player3, new WaitingForToolUseTest.InterfaceToolUseMock(true, true));
+ WaitingForToolUse toolUse = new WaitingForToolUse(map);
+ assertEquals(toolUse.tryToMakeAutomaticAction(player1), HasAction.NO_ACTION_POSSIBLE);
+ assertEquals(toolUse.tryToMakeAutomaticAction(player2), HasAction.NO_ACTION_POSSIBLE);
+ assertEquals(toolUse.tryToMakeAutomaticAction(player3), HasAction.AUTOMATIC_ACTION_DONE);
+ }
+
+ @Test
+ public void test_useTool() {
+ HashMap map = new HashMap<>();
+ PlayerOrder player1 = new PlayerOrder(1, 1);
+ PlayerOrder player2 = new PlayerOrder(2, 2);
+
+ map.put(player1, new InterfaceToolUseMock(false, false));
+ map.put(player2, new InterfaceToolUseMock(true, false));
+
+ WaitingForToolUse toolUse = new WaitingForToolUse(map);
+
+ assertEquals(toolUse.useTools(player1, 1), ActionResult.FAILURE);
+ assertEquals(toolUse.useTools(player2, 1), ActionResult.ACTION_DONE);
+ }
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerCivilisationCardsTest.java b/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerCivilisationCardsTest.java
new file mode 100644
index 00000000..9b6bf22f
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerCivilisationCardsTest.java
@@ -0,0 +1,177 @@
+package sk.uniba.fmph.dcs.player_board;
+
+import org.junit.Test;
+import sk.uniba.fmph.dcs.stone_age.EndOfGameEffect;
+
+public class PlayerCivilisationCardsTest {
+ @Test
+ public void test_init() {
+ PlayerCivilisationCards pc = new PlayerCivilisationCards();
+ assert (pc.state().isEmpty());
+ }
+
+ @Test
+ public void test_farmerEffect() {
+ PlayerCivilisationCards pc = new PlayerCivilisationCards();
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 1, 0) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 1, 0, 1) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(-1, -1, -1, -1) == 0);
+
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.FARMER });
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 1, 0) == 1);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 2, 0) == 2);
+
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.FARMER });
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.FARMER });
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 2, 0) == 6);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 10, 0) == 30);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 1, 0, 1) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, -1, 0) == 0);
+ }
+
+ @Test
+ public void test_toolMakerEffect() {
+ PlayerCivilisationCards pc = new PlayerCivilisationCards();
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 1, 0, 0) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 0, 1, 1) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(-1, -1, -1, -1) == 0);
+
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.TOOL_MAKER });
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 1, 0, 0) == 1);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 2, 0, 0) == 2);
+
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.TOOL_MAKER });
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.TOOL_MAKER });
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 2, 0, 0) == 6);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 10, 0, 0) == 30);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 0, 1, 1) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, -1, 0, 0) == 0);
+ }
+
+ @Test
+ public void test_builderEffect() {
+ PlayerCivilisationCards pc = new PlayerCivilisationCards();
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 0, 0, 0) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 1, 1, 1) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(-1, -1, -1, -1) == 0);
+
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.BUILDER });
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 0, 0, 0) == 1);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(2, 0, 0, 0) == 2);
+
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.BUILDER });
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.BUILDER });
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(2, 0, 0, 0) == 6);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(10, 0, 0, 0) == 30);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 1, 1, 1) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(-1, 0, 0, 0) == 0);
+ }
+
+ @Test
+ public void test_shamanEffect() {
+ PlayerCivilisationCards pc = new PlayerCivilisationCards();
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 1) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 1, 1, 0) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(-1, -1, -1, -1) == 0);
+
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.SHAMAN });
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 1) == 1);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 2) == 2);
+
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.SHAMAN });
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.SHAMAN });
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 2) == 6);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 10) == 30);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 1, 1, 0) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, -1) == 0);
+ }
+
+ @Test
+ public void test_sandBackgroundCards() {
+ PlayerCivilisationCards pc = new PlayerCivilisationCards();
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.BUILDER, EndOfGameEffect.TOOL_MAKER,
+ EndOfGameEffect.TOOL_MAKER, EndOfGameEffect.FARMER, EndOfGameEffect.FARMER, EndOfGameEffect.FARMER,
+ EndOfGameEffect.SHAMAN, EndOfGameEffect.SHAMAN, EndOfGameEffect.SHAMAN, EndOfGameEffect.SHAMAN });
+
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(-1, -1, -1, -1) == 0);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 0, 0, 0) == 1);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 1, 0, 0) == 3);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 1, 1, 0) == 6);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 1, 1, 1) == 10);
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 2, 1, 2) == 16);
+ }
+
+ @Test
+ public void test_grassBackgroundCards1() {
+ PlayerCivilisationCards pc = new PlayerCivilisationCards();
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 0);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.MEDICINE });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 1);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.ART });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 4);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.WRITING });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 9);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.POTTERY });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 16);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.SUNDIAL });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 25);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.TRANSPORT });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 36);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.MUSIC });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 49);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.WEAVING });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 64);
+ }
+
+ @Test
+ public void test_grassBackgroundCards2() {
+ PlayerCivilisationCards pc = new PlayerCivilisationCards();
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.WEAVING, EndOfGameEffect.ART,
+ EndOfGameEffect.MEDICINE, EndOfGameEffect.MUSIC });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 16);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.WEAVING, EndOfGameEffect.ART,
+ EndOfGameEffect.MEDICINE, EndOfGameEffect.MUSIC });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 32);
+ pc.addEndOfGameEffects(
+ new EndOfGameEffect[] { EndOfGameEffect.WEAVING, EndOfGameEffect.ART, EndOfGameEffect.MUSIC });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 41);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.WEAVING });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 42);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.POTTERY });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 51);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.POTTERY });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(0, 0, 0, 0) == 60);
+ }
+
+ @Test
+ public void test_addEndOfGameEffects() {
+ PlayerCivilisationCards pc = new PlayerCivilisationCards();
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.WEAVING, EndOfGameEffect.ART,
+ EndOfGameEffect.MEDICINE, EndOfGameEffect.MUSIC });
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.WEAVING, EndOfGameEffect.ART,
+ EndOfGameEffect.MEDICINE, EndOfGameEffect.MUSIC });
+ pc.addEndOfGameEffects(
+ new EndOfGameEffect[] { EndOfGameEffect.WEAVING, EndOfGameEffect.ART, EndOfGameEffect.MUSIC });
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.WEAVING });
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.POTTERY });
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.POTTERY });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 2, 1, 2) == 60);
+ pc.addEndOfGameEffects(new EndOfGameEffect[] { EndOfGameEffect.BUILDER, EndOfGameEffect.TOOL_MAKER,
+ EndOfGameEffect.TOOL_MAKER, EndOfGameEffect.FARMER, EndOfGameEffect.FARMER, EndOfGameEffect.FARMER,
+ EndOfGameEffect.SHAMAN, EndOfGameEffect.SHAMAN, EndOfGameEffect.SHAMAN, EndOfGameEffect.SHAMAN });
+ assert (pc.calculateEndOfGameCivilisationCardsPoints(1, 2, 1, 2) == 76);
+ }
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerFiguresTest.java b/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerFiguresTest.java
new file mode 100644
index 00000000..1aee4914
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerFiguresTest.java
@@ -0,0 +1,76 @@
+package sk.uniba.fmph.dcs.player_board;
+
+import org.junit.Test;
+
+public class PlayerFiguresTest {
+ @Test
+ public void test_initialization() {
+ PlayerFigures pf = new PlayerFigures();
+ assert (pf.getTotalFigures() == 5);
+ assert (pf.hasFigures(5));
+ }
+
+ @Test
+ public void testAddNewFigure() {
+ PlayerFigures pf = new PlayerFigures();
+ for (int i = 0; i < 5; i++) {
+ pf.addNewFigure();
+ pf.newTurn();
+ }
+ assert (pf.getTotalFigures() == 10);
+ assert (pf.hasFigures(10));
+ assert !(pf.hasFigures(11));
+
+ for (int i = 0; i < 10; i++) {
+ pf.addNewFigure();
+ }
+
+ assert (pf.getTotalFigures() == 10);
+ assert (pf.hasFigures(10));
+ assert !(pf.hasFigures(11));
+
+ }
+
+ @Test
+ public void testTakeFigures() {
+ PlayerFigures pf = new PlayerFigures();
+ for (int i = 0; i < 5; i++) {
+ pf.addNewFigure();
+ pf.newTurn();
+ }
+ assert (pf.hasFigures(10));
+ assert (pf.takeFigures(5));
+ assert !(pf.takeFigures(6));
+ assert (pf.takeFigures(5));
+ assert (pf.hasFigures(0));
+
+ pf.newTurn();
+ assert (pf.hasFigures(10));
+ assert !(pf.takeFigures(-1));
+ assert !(pf.takeFigures(-111111111));
+ }
+
+ @Test
+ public void testState() {
+ PlayerFigures pf = new PlayerFigures();
+ String state = pf.state();
+ String desiredOutcome = "Total figures: 5, available: 5";
+ assert (state.equals(desiredOutcome));
+
+ for (int i = 0; i < 5; i++) {
+ pf.addNewFigure();
+ pf.newTurn();
+ }
+
+ pf.takeFigures(5);
+
+ state = pf.state();
+ desiredOutcome = "Total figures: 10, available: 5";
+ System.out.println(state);
+ assert (state.equals(desiredOutcome));
+ pf.newTurn();
+ state = pf.state();
+ desiredOutcome = "Total figures: 10, available: 10";
+ assert (state.equals(desiredOutcome));
+ }
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerResourcesAndFoodTest.java b/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerResourcesAndFoodTest.java
new file mode 100644
index 00000000..19c38e04
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerResourcesAndFoodTest.java
@@ -0,0 +1,77 @@
+package sk.uniba.fmph.dcs.player_board;
+
+import org.junit.Test;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+public class PlayerResourcesAndFoodTest {
+ @Test
+ public void test_takingResources() {
+ PlayerResourcesAndFood playerResourcesAndFood = new PlayerResourcesAndFood();
+ playerResourcesAndFood.takeResources(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.GOLD });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.FOOD });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.GOLD });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.GOLD, Effect.FOOD });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.FOOD, Effect.FOOD });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.GOLD });
+ assert !playerResourcesAndFood
+ .hasResources(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.FOOD, Effect.GOLD });
+ assert !playerResourcesAndFood.hasResources(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.FOOD });
+ assert !playerResourcesAndFood
+ .hasResources(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.GOLD, Effect.STONE });
+ }
+
+ @Test
+ public void test_givingResources() {
+ PlayerResourcesAndFood playerResourcesAndFood = new PlayerResourcesAndFood();
+ playerResourcesAndFood
+ .takeResources(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.FOOD, Effect.STONE, Effect.GOLD });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.FOOD });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.STONE });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.GOLD });
+
+ playerResourcesAndFood.giveResources(new Effect[] { Effect.FOOD });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.FOOD, Effect.FOOD });
+ assert !playerResourcesAndFood.hasResources(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.FOOD });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.STONE });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.GOLD });
+
+ playerResourcesAndFood.giveResources(new Effect[] { Effect.FOOD, Effect.STONE });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.FOOD });
+ assert !playerResourcesAndFood.hasResources(new Effect[] { Effect.FOOD, Effect.FOOD });
+ assert !playerResourcesAndFood.hasResources(new Effect[] { Effect.STONE });
+ assert playerResourcesAndFood.hasResources(new Effect[] { Effect.GOLD });
+
+ assert !playerResourcesAndFood.giveResources(new Effect[] { Effect.CLAY });
+ }
+
+ @Test
+ public void test_numberOfResourcesForFinalPoints() {
+ PlayerResourcesAndFood playerResourcesAndFood = new PlayerResourcesAndFood();
+ assert playerResourcesAndFood.numberOfResourcesForFinalPoints() == 0;
+ int sum = 0;
+
+ sum += 2;
+ playerResourcesAndFood.takeResources(new Effect[] { Effect.FOOD });
+ assert playerResourcesAndFood.numberOfResourcesForFinalPoints() == sum;
+
+ sum += 3;
+ playerResourcesAndFood.takeResources(new Effect[] { Effect.WOOD });
+ assert playerResourcesAndFood.numberOfResourcesForFinalPoints() == sum;
+
+ sum += 4;
+ playerResourcesAndFood.takeResources(new Effect[] { Effect.CLAY });
+ assert playerResourcesAndFood.numberOfResourcesForFinalPoints() == sum;
+
+ sum += 5;
+ playerResourcesAndFood.takeResources(new Effect[] { Effect.STONE });
+ assert playerResourcesAndFood.numberOfResourcesForFinalPoints() == sum;
+
+ sum += 6;
+ playerResourcesAndFood.takeResources(new Effect[] { Effect.GOLD });
+ assert playerResourcesAndFood.numberOfResourcesForFinalPoints() == sum;
+
+ playerResourcesAndFood.takeResources(new Effect[] { Effect.TOOL, Effect.FIELD, Effect.BUILDING,
+ Effect.ONE_TIME_TOOL2, Effect.ONE_TIME_TOOL3, Effect.ONE_TIME_TOOL4 });
+ assert playerResourcesAndFood.numberOfResourcesForFinalPoints() == sum;
+ }
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerToolsTest.java b/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerToolsTest.java
new file mode 100644
index 00000000..7691e27c
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/player_board/PlayerToolsTest.java
@@ -0,0 +1,100 @@
+package sk.uniba.fmph.dcs.player_board;
+
+import org.junit.Test;
+
+public class PlayerToolsTest {
+ @Test
+ public void test_noTools() {
+ PlayerTools tools = new PlayerTools();
+ assert tools.hasSufficientTools(0);
+ assert !tools.hasSufficientTools(1);
+ }
+
+ @Test
+ public void test_addingTools() {
+ PlayerTools tools = new PlayerTools();
+ assert tools.hasSufficientTools(0);
+ assert !tools.hasSufficientTools(1);
+
+ tools.addTool();
+ assert tools.hasSufficientTools(1);
+ assert !tools.hasSufficientTools(2);
+
+ tools.addTool();
+ assert tools.hasSufficientTools(2);
+ assert !tools.hasSufficientTools(3);
+ }
+
+ @Test
+ public void test_maxTools() {
+ PlayerTools tools = new PlayerTools();
+ for (int i = 0; i < 12; i++) {
+ tools.addTool();
+ }
+
+ assert tools.hasSufficientTools(12);
+ assert !tools.hasSufficientTools(13);
+
+ tools.addTool();
+ assert tools.hasSufficientTools(12);
+ assert !tools.hasSufficientTools(13);
+ }
+
+ @Test
+ public void test_newTurn() {
+ PlayerTools tools = new PlayerTools();
+ for (int i = 0; i < 4; i++) {
+ tools.addTool();
+ }
+ assert tools.hasSufficientTools(2);
+ assert tools.hasSufficientTools(1);
+
+ assert tools.useTool(0) == 2;
+ assert tools.useTool(1) == 1;
+
+ assert !tools.hasSufficientTools(2);
+ assert tools.hasSufficientTools(1);
+
+ assert tools.useTool(0) == null;
+
+ tools.newTurn();
+
+ assert tools.hasSufficientTools(2);
+ assert tools.hasSufficientTools(1);
+
+ assert tools.useTool(0) == 2;
+ assert tools.useTool(1) == 1;
+
+ assert !tools.hasSufficientTools(2);
+ assert tools.hasSufficientTools(1);
+ }
+
+ @Test
+ public void test_singleUseTool() {
+ PlayerTools tools = new PlayerTools();
+ assert !tools.hasSufficientTools(1);
+
+ tools.addSingleUseTool(4);
+ assert tools.hasSufficientTools(4);
+ assert tools.useTool(0) == 0;
+ assert tools.useTool(1) == 0;
+ assert tools.useTool(2) == 0;
+ assert tools.useTool(3) == 4;
+ assert tools.useTool(3) == null;
+ }
+
+ @Test
+ public void test_maxSingleUseTool() {
+ PlayerTools tools = new PlayerTools();
+ tools.addSingleUseTool(5);
+ assert !tools.hasSufficientTools(5);
+ tools.addSingleUseTool(4);
+ assert tools.hasSufficientTools(4);
+ tools.addSingleUseTool(4);
+ assert tools.hasSufficientTools(8);
+ tools.addSingleUseTool(4);
+ assert tools.hasSufficientTools(12);
+ tools.addSingleUseTool(4);
+ assert !tools.hasSufficientTools(13);
+ }
+}
diff --git a/src/test/java/sk/uniba/fmph/dcs/player_board/TribeFedStatusTest.java b/src/test/java/sk/uniba/fmph/dcs/player_board/TribeFedStatusTest.java
new file mode 100644
index 00000000..716d683e
--- /dev/null
+++ b/src/test/java/sk/uniba/fmph/dcs/player_board/TribeFedStatusTest.java
@@ -0,0 +1,205 @@
+package sk.uniba.fmph.dcs.player_board;
+
+import org.junit.Test;
+import sk.uniba.fmph.dcs.stone_age.Effect;
+
+import java.util.Arrays;
+
+public class TribeFedStatusTest {
+ @Test
+ public void testAddingFields() {
+ PlayerResourcesAndFood resourcesAndFood = new PlayerResourcesAndFood();
+ TribeFedStatus tfs = new TribeFedStatus(resourcesAndFood, null);
+ String state;
+ for (int i = 0; i < 10; i++) {
+ tfs.addField();
+ state = tfs.state();
+ assert (state.equals("Fed: false, # of fields: " + (i + 1)));
+ }
+ for (int i = 0; i < 10; i++) {
+ tfs.addField();
+ }
+ state = tfs.state();
+ assert (state.equals("Fed: false, # of fields: 10"));
+ }
+
+ @Test
+ public void testNewTurn() {
+ PlayerResourcesAndFood prf = new PlayerResourcesAndFood();
+ TribeFedStatus tfs = new TribeFedStatus(prf, new PlayerFigures());
+ for (int i = 0; i < 10; i++) {
+ tfs.newTurn();
+ }
+ assert !(prf.hasResources(new Effect[] { Effect.FOOD }));
+
+ tfs.addField();
+ for (int i = 0; i < 10; i++) {
+ tfs.newTurn();
+ }
+ Effect[] ef1 = new Effect[10];
+ Arrays.fill(ef1, Effect.FOOD);
+ assert (prf.hasResources(ef1));
+
+ Effect[] ef2 = new Effect[11];
+ Arrays.fill(ef2, Effect.FOOD);
+ assert !(prf.hasResources(ef2));
+
+ for (int i = 0; i < 9; i++) {
+ tfs.addField();
+ }
+
+ for (int i = 0; i < 10; i++) {
+ tfs.newTurn();
+ }
+
+ Effect[] ef3 = new Effect[110];
+ Arrays.fill(ef3, Effect.FOOD);
+ assert (prf.hasResources(ef3));
+
+ Effect[] ef4 = new Effect[111];
+ Arrays.fill(ef4, Effect.FOOD);
+ assert !(prf.hasResources(ef4));
+ }
+
+ @Test
+ public void testFeedTribeIfEnoughFood() {
+ PlayerResourcesAndFood prf = new PlayerResourcesAndFood();
+ PlayerFigures figures = new PlayerFigures();
+ TribeFedStatus tfs = new TribeFedStatus(prf, figures);
+
+ for (int i = 0; i < 5; i++) {
+ tfs.addField();
+ }
+ boolean ans = tfs.feedTribeIfEnoughFood();
+ assert (ans);
+ assert (tfs.isTribeFed());
+ assert (tfs.isTribeFed());
+
+ tfs.newTurn();
+ figures.addNewFigure();
+ ans = tfs.feedTribeIfEnoughFood();
+ assert (!ans);
+ assert (!tfs.isTribeFed());
+
+ tfs.newTurn();
+ tfs.addField();
+ ans = tfs.feedTribeIfEnoughFood();
+ assert (ans);
+ assert (tfs.isTribeFed());
+ }
+
+ @Test
+ public void testFeedTribe() {
+ PlayerResourcesAndFood resources = new PlayerResourcesAndFood();
+ PlayerFigures figures = new PlayerFigures();
+ TribeFedStatus tfs = new TribeFedStatus(resources, figures);
+ figures.addNewFigure();
+ figures.newTurn();
+ tfs.newTurn();// 6 figures
+ figures.addNewFigure();
+ tfs.newTurn();// 7 figures
+ figures.newTurn();
+ Effect[] allResources = { Effect.FOOD, Effect.FOOD, Effect.GOLD, Effect.STONE, Effect.WOOD, Effect.CLAY,
+ Effect.STONE, Effect.GOLD, Effect.GOLD, Effect.GOLD, Effect.BUILDING, Effect.ONE_TIME_TOOL2,
+ Effect.ONE_TIME_TOOL3 };
+ resources.takeResources(allResources);
+ boolean ans = tfs.feedTribeIfEnoughFood();
+ assert !ans;
+ ans = tfs.feedTribe(allResources);
+ assert !ans;
+ ans = tfs.feedTribe(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.GOLD, Effect.STONE, Effect.WOOD,
+ Effect.CLAY, Effect.STONE, Effect.ONE_TIME_TOOL2, Effect.ONE_TIME_TOOL3 });
+ assert !ans;
+
+ ans = tfs.feedTribe(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.GOLD, Effect.STONE, Effect.WOOD,
+ Effect.CLAY, Effect.STONE, Effect.GOLD, Effect.GOLD, Effect.GOLD });
+ assert !ans;
+
+ ans = tfs.feedTribe(new Effect[] { Effect.GOLD, Effect.STONE, Effect.WOOD, Effect.CLAY, Effect.STONE,
+ Effect.GOLD, Effect.GOLD });
+ assert !ans;
+
+ ans = tfs.feedTribe(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.GOLD, Effect.STONE, Effect.WOOD,
+ Effect.CLAY, Effect.STONE });
+ assert ans;
+
+ tfs.newTurn();
+ ans = tfs.feedTribe(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.GOLD, Effect.STONE, Effect.WOOD,
+ Effect.CLAY, Effect.STONE });
+ assert !ans;
+ }
+
+ @Test
+ public void testSetTribeFed() {
+ PlayerResourcesAndFood resourcesAndFood = new PlayerResourcesAndFood();
+ PlayerFigures figures = new PlayerFigures();
+ TribeFedStatus tfs = new TribeFedStatus(resourcesAndFood, figures);
+ resourcesAndFood.takeResources(new Effect[] {});
+
+ for (int i = 0; i < 3; i++) {
+ tfs.addField();
+ tfs.newTurn();
+ }
+ boolean ans = tfs.setTribeFed();
+ assert !ans;
+
+ ans = tfs.feedTribeIfEnoughFood();
+ assert ans;
+
+ tfs.newTurn();
+ assert !tfs.isTribeFed();
+
+ ans = tfs.feedTribeIfEnoughFood();
+ assert ans;
+
+ tfs.newTurn();
+ ans = tfs.feedTribeIfEnoughFood();
+ assert ans;
+
+ tfs.newTurn();
+ ans = tfs.feedTribeIfEnoughFood();
+ assert !ans;
+
+ ans = tfs.setTribeFed();
+ assert ans;
+
+ tfs.newTurn();
+ resourcesAndFood.takeResources(new Effect[] { Effect.FOOD, Effect.FOOD });
+ ans = tfs.setTribeFed();
+ assert !ans;
+
+ ans = tfs.feedTribeIfEnoughFood();
+ assert ans;
+ }
+
+ @Test
+ public void testIsTribeFed() {
+ PlayerFigures figures = new PlayerFigures();
+ PlayerResourcesAndFood resourcesAndFood = new PlayerResourcesAndFood();
+ TribeFedStatus tfs = new TribeFedStatus(resourcesAndFood, figures);
+ resourcesAndFood.takeResources(new Effect[] { Effect.FOOD, Effect.FOOD, Effect.FOOD, Effect.FOOD, Effect.FOOD,
+ Effect.GOLD, Effect.GOLD, Effect.STONE, Effect.CLAY, Effect.WOOD });
+
+ tfs.feedTribeIfEnoughFood();
+ assert tfs.isTribeFed();
+ tfs.feedTribeIfEnoughFood();
+ assert tfs.isTribeFed();
+
+ tfs.newTurn();
+ tfs.feedTribeIfEnoughFood();
+ assert !tfs.isTribeFed();
+ tfs.feedTribe(new Effect[] { Effect.GOLD, Effect.GOLD, Effect.STONE, Effect.CLAY, Effect.WOOD });
+ assert tfs.isTribeFed();
+ tfs.feedTribe(new Effect[] { Effect.GOLD, Effect.GOLD, Effect.STONE, Effect.CLAY, Effect.WOOD });
+ assert tfs.isTribeFed();
+
+ tfs.newTurn();
+ tfs.feedTribeIfEnoughFood();
+ assert !tfs.isTribeFed();
+ tfs.feedTribe(new Effect[] { Effect.GOLD, Effect.GOLD, Effect.STONE, Effect.CLAY, Effect.WOOD });
+ System.out.println(resourcesAndFood.state());
+ assert !tfs.isTribeFed();
+ tfs.setTribeFed();
+ assert tfs.isTribeFed();
+ }
+}
diff --git a/zadanie/assignment.md b/zadanie/assignment.md
new file mode 100644
index 00000000..33e4ac1f
--- /dev/null
+++ b/zadanie/assignment.md
@@ -0,0 +1,42 @@
+# Assignment - Stone Age game
+
+Your task is to construct a component implementing the logic of board game Stone Age. These are the [rules](https://images.zmangames.com/filer_public/ee/88/ee888bec-5000-4566-9fb0-8c6475e706a0/zm7260_stone_age_rules.pdf).
+
+## Design
+
+I prepared a [design](diagram.png) template for your implementation. Besides that I prepared [simple description of the classes](classes.md) with estimations
+
+Note that the design is by no means complete. Most notably
+- You have to add appropriate constructors. Chose your constructors in a way that enables good testing. E.g. card deck and building stacks do not need to be full.
+- You have to add interfaces that separate classes that need to be separated.
+- You probably want to do something with Bag class to handle the randomness involved better.
+Also, it is highly likely, that I overlooked something and there are some issues that need to be resolved. Feel free to do necessary changes and adjustments.
+
+I recommend to stick to the following timeline
+- 11. 11. create teams, understand game rules, understand the design (so we can have a meaningful discussion on the lecture).
+- 20. 11. the common part of the project is finished
+- 27. 11. you are done
+
+## Implementation remarks
+
+You should build your project either in Python or in Java. I started the projects for you, including several tools that might help you. See [pts24-python](https://github.com/relatko/pts1-23-python) and [pts24-java](https://github.com/relatko/pts1-23-java). Note that if you use Python, your code should be type annotated and mypy --strict should show no errors. Do not use any except for when handling json.
+
+This is a fairly large project and it would take too long to implement. Thus you will collaborate while implementing the project.
+
+* Create groups of, ideally, six to eight people. and fork the repository you agree to use. Green classes are provided in the project (Java GamePhaseController will be implemented soonish).
+* Collaboratively implement the elements marked white (trivial) and blue, including factories and integration tests for two components. For blue elements create a PR (typically one PR per element, but you may merge several very trivial ones into one PR), discuss it and merge it into the master (I recommend main branch protection requiring PR with at least 1 approval). Blue classes are not of particular interest to me. The amount of points given here is quite limited (up to 20 points including non-coding aspects of common work like like making and reviewing PRs), so do not overthink stuff, but make it sound enough so you actually can write working integration tests. This also implies that the test coverage does not have to be great in these classes. While collaborating create new features in own branches and merge it to main with a PR after code review is done. Turn on branch protection. Try to keep CI green (you can enforce this by branch protection rules). You may use github issues to your the progress. You may split large task into smaller tasks. You may want to meet one time before you start your work. Splitting L tasks is a good thing to do.
+It is expected that everybody prepares and reviews 3-5 PRs.
+* After this, you should add your own implementation of the red classes (including unit tests) and prepare two integration tests. To reduce the amount of work necessary, it is sufficient to create one end to end scenario for each of these integration test.
+
+Unit tests for Game should be solitary. Do a sociable unit test of CivilisationCardPlace that also uses CivilisationCardDeck. Tests of ResourceSource must be solitary. You can discuss technical aspects of the implementation, but everybody should implement the red classes and the red integration tests on his own. You can either work on local machine or use a private repository for your effort.
+
+You should use Git and produce a reasonable history of commits. Note that to work on the red classes you do not need the blue ones. You are also free to adjust the implementation of blue and green classes according to the needs of your project (but, the changes, hopefully should not be large, a good example is changing interface name, adding a new interface, ...).
+
+
+
+## Instructions for submitting your project
+
+Send your solution to [lukotka.pts@gmail.com](lukotka.pts at gmail.com). The deadline is 30.11.2022 23:59:59. The solutions sent later will be accepted, however the number of points awarded may be reduced.
+
+Send the solution to me either as compressed folders containing the whole repository (including the hidden .git files) or as a link to private repository with read access granted (GitHub handle `relatko`). Attach a link to the public repository for the team part of the project and link PRs you have made and PRs you have reviewed.
+
diff --git a/zadanie/classes.md b/zadanie/classes.md
new file mode 100644
index 00000000..49753ca0
--- /dev/null
+++ b/zadanie/classes.md
@@ -0,0 +1,326 @@
+# Stone Age
+
+The component responsible for running the game according to the rules.
+
+*Estimation for top level integration tests and factories:* 3h
+
+
+## Facade classes
+
+### StoneAgeGame class
+
+This is an adapter class that converts external representation to internal representation. Namely it converts system-wide player ids to PlayerOrder objects relevant to the game and is the root for converting game state representation to JSON.
+
+*Unit tests:* No. It is an adaptor/facade class with very simple to no responsibilities. Testing is best handled by an integration test
+
+*Estimation:* 0.5h
+
+### StoneAgeObservable class
+
+Implements observer pattern. According to the rules the civilisation cards should be visible only to player. First of all, this is not that important as the information is available, if players remember it. Second, this cannot be realised for terminal multiplayer client. Thus we ship this aspect.
+
+*Unit tests:* No. It is an adaptor/facade class with very simple to no responsibilities. Testing is best handled by an integration test
+
+*Estimation:* XS
+
+
+## PlayerBoard component
+
+The component implements functionality associated with information present on player board (+ player points and fields). Besides that by applying informatin expert principle, this component is also responsible for tracking tribe feeding.
+
+*Integration tests:* Focus on interactions involving multiple classes like tribe feeding and final points calculation.
+
+*Estimation for integration tests and factories:* M
+
+### PlayerBoard class
+
+Composes state and the final points calculation. Stores points and houses (as there is no significant behaviour associated to these attributes.)
+
+*Unit tests:* Yes.
+
+*Estimation:* S
+
+### PlayerBoardFacade
+
+Facade class for PlayerBoard component that makes it easier for other components to interact with PlayerBoard.
+
+*Unit tests:* No. It is an adaptor/facade class with very simple to no responsibilities. Testing is best handled by an integration test
+
+*Estimation:* XS
+
+### PlayerResourcesAndFood class
+
+Stores resources and food, calculates points for leftover resources.
+
+*Unit tests:* Yes.
+
+*Estimation:* S
+
+### PlayerFigures class
+
+Handles player figures that are on player board and are free to be used. Note that instead of moving figures back from game board we just reset the number of figures at the start of new turn.
+
+*Unit tests:* Yes. Very simple.
+
+*Estimation:* XS
+
+### PlayerCivilisationCards class
+
+Stores player civilisation card long term effects and calculates the final points associated with them.
+
+*Unit tests:* Yes. Makes sense to produce quite a few unit test to be sure that this functionality is implemented correctly.
+
+*Estimation:* S
+
+### PlayerTools class
+
+Handless player tools and one time use tools
+
+*Unit tests:* Yes. This is quite a complex class, and requires significatn unit tests
+
+*Estimation:* M
+
+### TribeFedStatus class
+
+Tracks number of fields and tribe feeding. SetTribeFed should be used in case of -10 point hit chosen.
+
+*Unit tests:* Yes. Tests may be sociable
+
+*Estimation:* L
+
+
+## GameBoard component
+
+Implements behaviours associated with game board (except for tracking points aand fields), related to player actions.
+
+*Integration tests:* Yes. Focus on interaction involving RewardMenu, CurrentThrow
+
+*Estimation for integration tests and factories:* L (you can split this task into more smaller tasks)
+
+## GameBoard class
+
+Puts game board state together.
+
+*Unit tests:* No. It is an adaptor/facade class with very simple to no responsibilities. Testing is best handled by an integration test
+
+*Estimation:* XXS
+
+### FigureLocationAdaptor
+
+Adaptor replacing PlayerOrder with Player structures.
+
+*Unit tests:* No. It is an adaptor/facade class with very simple to no responsibilities. Testing is best handled by an integration test
+
+*Estimation:* XXS
+
+### PlaceOnToolMakerAdaptor class
+
+Adaptor between InterfaceFigureLocationInternal and ToolMakerHutFields for tool maker action.
+
+*Unit tests:* No. It is an adaptor/facade class with very simple to no responsibilities. Testing is best handled by an integration test
+
+*Estimation:* XXS
+
+### PlaceOnHutAdaptor class
+
+Adaptor between InterfaceFigureLocationInternal and ToolMakerHutFields for hut action.
+
+*Unit tests:* No. It is an adaptor/facade class with very simple to no responsibilities. Testing is best handled by an integration test
+
+*Estimation:* XXS
+
+### PlaceOnFieldsAdaptor class
+
+Adaptor between InterfaceFigureLocationInternal and ToolMakerHutFields for fields action.
+
+*Unit tests:* No. It is an adaptor/facade class with very simple to no responsibilities. Testing is best handled by an integration test
+
+*Estimation:* XS
+
+### ToolMakerHutsFields class
+
+Implements these three actions and interaction among them (when the game has less players)
+
+*Unit tests:* Yes. Focus on the interaction.
+
+*Estimation:* M
+
+### ResourceSource class
+
+Implements actions Hunting, Forest, Clay mound, Quarry, River.
+
+*Unit tests:* Yes. Focus on interaction between players.
+
+*Estimation:* M
+
+### CurrectThrow class
+
+Handles die throws for resources (Food, Wood, Clay, Stone, Gold) and with improving the throws with tools.
+
+*Unit tests:* Yes.
+
+*Estimation:* M
+
+### Throw class
+
+Encapsulates the random effect.
+
+*Unit tests:* No. Class needs to be mocked in integration tests
+
+*Estimation:* XS
+
+### CivilisationCardPlace class
+
+Implements civilisation card actions
+
+*Unit tests:* Yes. May be sociable with CivilisationCardDeck. Things to focus include paying sufficint resources, validating that imediate effect evaluation was invoked, end of game effect was forwarded to player board, and that filling up the places on end of turn is handled properly. The instances may assume that newTurn is called in certain order. If so, do not forget to documment it and do not forget to test the behaviour in NewRoundState.
+
+*Estimation:* L (you can split it into smaller tasks)
+
+### CivilisationCardDeck class
+
+Implements civilisation card deck.
+
+*Unit tests:* Not necessary. Class is very simple. Sociable unit tests with CivilisationCardPlace is sufficient.
+
+*Estimation:* XS
+
+### RewardMenu class
+
+Represents the choices available in All Players Take A Reward imediate civilisation card effect.
+
+*Unit tests:* Yes.
+
+*Estimation:* M
+
+### AllPlayersTakeAReward class
+
+Represents corresponding immediate civilisation card effect. Throws dices and initializes reward menu.
+
+*Unit tests:* Yes.
+
+*Estimation:* M
+
+### GetSomethingThrow class
+
+Represents corresponding immediate civilisation card effect. Uses CurrentThrow to perform the effect
+
+*Unit tests:* Yes.
+
+*Estimation:* S
+
+### GetSomethingFixed class
+
+Represents corresponding immediate civilisation card effect. Uses CurrentThrow to perform the effect
+
+*Unit tests:* Yes.
+
+*Estimation:* XS
+
+### GetSomethingChoice class
+
+Represents corresponding immediate civilisation card effect. Uses CurrentThrow to perform the effect
+
+*Unit tests:* Yes.
+
+*Estimation:* XS
+
+### GetCard class
+
+Represents corresponding immediate civilisation card effect. Uses CurrentThrow to perform the effect
+
+*Unit tests:* Yes.
+
+*Estimation:* S
+
+### BouldingTile class
+
+Represents building tiles, including hidden buildings and associated actions
+
+*Unit tests:* Yes. May be sociable with e.g. SimpleBuilding
+
+*Estimation:* L
+
+### ArbiraryBuilding class
+
+Represents building that allows 1-7 resources of any kind to be spent
+
+*Unit tests:* Yes.
+
+*Estimation:* XS
+
+### VariableBuilding class
+
+Represents building that allows spending fixed number of resources of given number of resource type.
+
+*Unit tests:* Yes. Be careful
+
+*Estimation:* S
+
+### SimpleBuilding class
+
+Represents building that prescribes resources spent.
+
+*Unit tests:* Yes.
+
+*Estimation:* XS
+
+
+## GamePhaseController component
+
+This components track game phases.
+
+*Integration tests:* Focus on game ending scenatios and interactions not covered by GamePhaseController unit test
+
+*Estimation for integration tests and factories:* M
+
+### GamePhaseController class
+
+Represents state transitions in the game. Besides moving the state after each succesfull player action the class tries to continue with player actions that do not require input.
+
+*Unit tests:* Yes. Focus on transition
+
+*Estimation:* XL
+
+### PlaceFigure class
+
+*Unit tests:* Yes. Focus on tryToMakeAutomaticAction method.
+
+*Estimation:* S
+
+### MakeActionState class
+
+*Unit tests:* Yes. Focus on tryToMakeAutomaticAction method.
+
+*Estimation:* S
+
+### NewRoundState class
+
+*Unit tests:* Yes. Focus on game end test.
+
+*Estimation:* S
+
+### FeedTribe class
+
+*Unit tests:* Yes. Focus on tryToMakeAutomaticAction method.
+
+*Estimation:* S
+
+### WaiitingForToolUse class
+
+*Unit tests:* Yes. Focus on tryToMakeAutomaticAction method.
+
+*Estimation:* S
+
+### AllPlayesTakeAReward class
+
+*Unit tests:* Yes. Focus on tryToMakeAutomaticAction method.
+
+*Estimation:* S
+
+### GameEnd class
+
+*Unit tests:* Yes.
+
+*Estimation:* XS
+
diff --git a/zadanie/diagram.pdf b/zadanie/diagram.pdf
new file mode 100644
index 00000000..b20d2307
Binary files /dev/null and b/zadanie/diagram.pdf differ
diff --git a/zadanie/diagram.png b/zadanie/diagram.png
new file mode 100644
index 00000000..4a988fdf
Binary files /dev/null and b/zadanie/diagram.png differ
diff --git a/zadanie/diagram.uxf b/zadanie/diagram.uxf
new file mode 100644
index 00000000..9a645aa6
--- /dev/null
+++ b/zadanie/diagram.uxf
@@ -0,0 +1,490 @@
+10Space for diagram notesUMLClass114070500180<<Interface>>
+InterfaceStoneAgeGame
+--
+placeFigures(playerId: int, location:Location, figuresCount: int): bool
+makeAction(playerId: int, location: Location, usedResources: Effect[],
+ desiredResources: Effect[]): bool
+skipAction(playerId: int, location: Location): bool (only if resources are required)
+useTools(playerId: int, toolIndex: int): bool {affects last action}
+noMoreToolsThisThrow(playerId: int): bool
+feedTribe(playerId: int, resources: Effect[]): bool
+doNotFeedThisTurn(playerId: int): bool
+makeAllPlayersTakeARewardChoice(playerId: int, reward: Effect):boolUMLClass21309021080<<Interface>>
+InterfaceStoneAgeObserver
+--
+update(gameState: string)
+UMLClass7600140290<<Enumeration>>
+Location
+--
+ToolMaker
+Hut
+Field
+HuntingGrounds
+Forest
+ClayMound
+Quary
+River
+CivilizationCard1
+CivilizationCard2
+CivilizationCard3
+CivilizationCard4
+BuildingTile1
+BuildingTile2
+BuildingTile3
+BuildingTile4
+
+
+
+
+UMLClass9200170280<<Enumeration>>
+Effect
+--
+Food
+Wood
+Clay
+Stone
+Gold
+Tool
+Field
+Building
+OneTimeTool2
+OneTimeTool3
+OneTimeTool4
+--
+isResourceOrFood(): bool
+isResource(): bool
+points(): int {is 0 if not
+ ResourceOrFood}
+UMLClass2340640360180bg=green
+GamePhaseController
+--
+roundStartingPlayer: PlayerOrder
+gamePhase: GamePhase
+currentPlayer: PlayerOrder
+currentPlayerTakingReward: Optional[PlayerOrder]
+dispatchers: map<GamePhase, InterfaceGamePhaseState>
+--
+-checkPlayersTurn(player: PlayerOrder): bool
+-progressStateAfterSuccesfullAction()
+-progressStateAfterNoActionPossible()
+-progressStateAfterNoActionPossibleByAnyPlayer()
+-tryToDoFurtherActions()
+UMLClass1260380260100bg=blue
+StoneAgeGame
+--
+players: map<PlayerOrder, int>
+UMLClass1420177030060bg=blue
+BuildingTile
+--
+figures:PlayerOrder[]
+--
+state(): stringUMLClass168038045060bg=blue
+StoneAgeObservable
+--
+notify(gameState: string) {Also removes information that should be invisible,
+ but we ignore this}UMLClass16809040080<<Interface>>
+InterfaceStoneAgeObservable
+--
+registerObserver(playerId: int,observer: InterfaceStoneAgeObserver)
+Relation151041019030lt=<-170;10;10;10Relation23905703090lt=<<.10;10;10;70Relation187016030240lt=<<.10;10;10;220Relation2120160110250lt=.>
+<<requires>>
+
+
+10;230;30;230;30;10UMLClass22601450140150<<Enumeration>>
+GamePhase
+--
+PlaceFigures
+MakeAction
+FeedTribe
+NewRound
+WaitingForToolsUse
+AllPlayersTakeAReward
+GameEnd
+UMLClass2240840490200<<Interface>>
+InterfaceGamePhaseState
+--
+placeFigures(player: PlayerOrder, location:Location, figuresCount: int): ActionResult
+makeAction(player: PlayerOrder, location: Location, inputResources: Effect[],
+ outputResources: Effect[]): ActionResult
+skipAction(player: PlayerOrder, location: Location): ActionResult
+useTools(player: PlayerOrder, toolIndex: int):ActionResult
+noMoreToolsThisThrow(player: PlayerOrder): ActionResult
+feedTribe(player: PlayerOrder, resources: Effect[]): ActionResult
+doNotFeedThisTurn(player: PlayerOrder): ActionResult
+makeAllPlayersTakeARewardChoice(player: PlayerOrder, reward: Effect): ActionResult
+tryToMakeAutomaticAction(player: PlayerOrder): HasAction
+
+Relation24908103050lt=<.10;30;10;10UMLClass601900220100<<Enumeration>>
+ActionResult
+--
+Failure
+ActionDone
+ActionDoneWaitForToolsUse
+ActionDoneAllPlayersTakeReward
+UMLClass701750200100<<Enumeration>>
+HasAction
+--
+WaitingForPlayerAction
+AutomaticActionDone
+NoActionPossible
+
+UMLNote2900510430580*Player on turn*
+
+Class is responsible for checking if the player is on turn.
+PlaceFigures: player must match currentPlayer
+MakeAction: player must match currentPlayer
+FeedTribe: any player is fine
+NewRound: assertion failure (calls should not happen)
+WaitingForToolsUse: player must match currentPlayer
+WaitingForActionChice: player must match currentPlayer
+AllPlayersTakeAReward: player must match currentPlayerTakingReward
+
+*TryToMakeAutomaticAction*
+
+*PlaceFigures:*
+- has free figures -> WaitingForPlayerAction
+- otherwise -> NoActionPossible
+*MakeAction:*
+- figures on board -> WaitingForPlayerAction
+- otherwise -> NoActionPossible
+*FeedTribe:*
+- tribe already fed -> NoActionPossible
+- has enough food to feed tribe -> AutomaticActionDone (feed tribe)
+- otherwise -> WaitingForPlayerAction
+*NewRound:*
+- round not initialized -> AutomaticActionDone (initialize round)
+- game ended -> NoActionPossible
+*WaitingForToolsUse:*
+- not enough tools to improve roll outcome -> NoActionPossible
+- otherwise -> WaitingForPlayerAction
+*AllPlayersTakeAReward:*
+- all players have reward - NoActionPossible
+- last player gets reward - AutomaticActionDone (gets the last reward)
+- otherwise -> WaitingForPlayerAction
+*GameEnd:*
+- WaitingForPlayerAction
+
+If NoActionPossible for each player, next phase can start.UMLClass14501090270120bg=red
+ResourceSource
+--
+name: string
+Resource: Effect
+maxFigures: int
+maxFigureColours: int
+figures: PlayerOrder[]
+--
+state(): stringUMLClass103060036060GameBoard
+--
+state(): string
+bg=blue
+UMLClass580530310130bg=blue
+PlayerBoard
+--
+points: int
+houses: int
+--
+addPoints(points: int)
+addHouse()
+addEndOfGamePoints()
+state(): string
+UMLClass1090850290260bg=blue
+ToolMakerHutFields
+--
+toolMakerFigures: PlayerOrder[]
+hutFigures:PlayerOrder[]
+fieldsFigures: PlayerOrder[]
+restriction: int
+--
+placeOnToolMaker(player: Player): bool
+actionToolMaker(player: Player): bool
+canPlaceOnToolMaker(player: Player): bool
+placeOnHut(figures: Player): bool
+actionHut(player: Player): bool
+canPlaceOnHut(player: Player)
+placeOnFields(player: Player): bool
+actionFields(player: Player): bool
+canPlaceOnFields(player: Player)
+newTurn()
+state(): stringUMLClass1380186034070<<interface>>
+Building
+--
+build(resources: Effect[]): Optional[int] {returns points}
+state(): string
+UMLClass1420138030080bg=red
+CivilizationCardPlace
+--
+requiredResources: int
+figures:PlayerOrder[]
+--
+state(): stringUMLClass1100143021060bg=red
+CivilizationCardDeck
+--
+getTop(): Optional[CivilizationCard]
+state: string()UMLClass150520250120bg=blue
+PlayerResourcesAndFood
+--
+resources: map<Effect, int>
+--
+hasResources(resources: Effect[]): bool
+takeResources(resources: Effect[]): bool
+giveResources(resources: Effect[]): bool
+numberOfResourcesForFinalPoints(): int
+state: string()
+
+
+UMLClass570710220150bg=blue
+PlayerTools
+--
+tools: int[]
+usedTools bnool[]
+--
+newTurn()
+addTool()
+addSingleUseTool(strength: int)
+useTool(index: int): Optional[int]
+hasSufficientTools(goal: int): bool
+state(): stringUMLClass1630199013040bg=green
+SimpleBuilding
+--
+resources: Effect[]
+UMLClass1430199019060bg=blue
+VariableBuilding
+--
+numberOfResources: int
+numberOfResourceTypes: int
+UMLClass1230199019050bg=blue
+ArbitraryBuilding
+--
+maxNumberOfResources: int
+Relation151019203090lt=<<.10;10;10;70Relation1320195039060lt=.370;40;370;10;10;10;10;40Relation153018203060lt=<<<<<-10;10;10;40UMLClass660162026070<<Datatype>>
+CivilisationCard
+--
+immediateEffect:ImmediateEffectType[]
+endOfGameEffect: EndOfGameEffectType[]
+Relation10606503801160lt=<<<<<-10;10;10;1140;360;1140Relation106010305030lt=-30;10;10;10UMLClass13801240270100bg=red
+CurrentThrow
+--
+throwsFor: Effect
+throwResult: int
+--
+initiate(player: Player, effect: Effect, dices: int)
+state(): stringUMLClass1360162014030AllPlayersTakeReward
+bg=blue
+UMLClass8101720130230<<Enumeration>>
+EndOfGameEffect
+--
+Farmer
+ToolMaker
+Builder
+Shaman
+Medicine
+Art
+Music
+Writing
+Sundial
+Pottery
+Transport
+Weaving
+
+
+UMLClass6401720140240<<Enumeration>>
+ImmediateEffect
+--
+ThrowWood
+ThrowClay
+ThrowStone
+ThrowGold
+Point
+Wood
+Clay
+Stone
+Gold
+Card
+ArbitraryResource
+Food
+AllPlayersTakeReward
+UMLClass2440106029040bg=blue
+PlaceFiguresState
+--
+places: Map[Location, InterfaceFigureLocation]UMLClass2440113029040bg=blue
+MakeActionState
+--
+places: Map[Location, InterfaceFigureLocation]UMLClass2550127018030bg=blue
+FeedTribeState
+UMLClass2530120020040bg=blue
+NewRoundState
+--
+places: InterfaceFigureLocation[]UMLClass2550133018030bg=blue
+WaitingForToolUseStateUMLClass2520139021030bg=blue
+AllPlayersTakeARewardStateUMLClass2580144015030bg=blue
+GameEndStateRelation272089060590lt=<<.10;10;40;10;40;570;10;570UMLClass18401040370160<<Interface>>
+InterfaceFigureLocation
+--
+placeFigures(player: PlayerOrder, figureCount: int):bool
+tryToPlaceFigures(player: PlayerOrder, count: int): HasAction
+makeAction(player: PlayerOrder, inputResources: Effect[],
+ outputResources: Effect[]): ActionResult
+skipAction(player: PlayerOrder): bool
+tryToMakeAction(player: PlayerOrder): HasAction
+newTurn(): bool {returns true if end of game is implied
+ by given location}
+Relation272010706030lt=.40;10;10;10Relation1770700190360lt=<<.170;340;170;10;10;10UMLClass1540100018030bg=blue
+PlaceOnHutAdaptorUMLClass1540104018030bg=blue
+PlaceOnFieldsAdaptorUMLClass154096018030bg=blue
+PlaceOnToolMakerAdaptorRelation171011406030lt=.40;10;10;10Relation16707103070lt=.>10;10;10;50Relation171010006030lt=.40;10;10;10Relation103083043030lt=.410;10;10;10Relation2200114026030lt=<.10;10;240;10Relation272011406030lt=.40;10;10;10Relation1370104019030lt=<-10;10;170;10Relation1370100019030lt=<-10;10;170;10Relation137096019030lt=<-10;10;170;10Relation1060139038030lt=-10;10;360;10Relation12004008040lt=<.
+10;20;60;20UMLClass150890220190bg=blue
+PlayerFigures
+--
+totalFigures:int
+figures:int
+--
+addNewFigure()
+hasFigures(count: int): bool
+getTotalFigures(): int
+takeFigures(count: int): bool
+newTurn()
+state: string()
+--
+{Adding figures when you have more
+than 10 has no effect}
+
+
+
+Relation39056021030lt=<<<<<-190;10;10;10UMLClass1140131017060bg=blue
+Throw
+--
+throw(dices: int): int[]Relation1300132010030lt=->80;10;10;10UMLClass6301250280150<<Interface>>
+InterfacePlayerBoardGameBoard
+--
+giveEffect(stuff: Effect[])
+giveEndOfGameEfect(stuff: EndOfGameEffect[])
+takeResources(stuff: Effect[]): bool
+takeFigures(count: int): bool
+hasFigures(count: int): bool
+hasSufficientTools(goal: int): bool
+useTool(idx: int): Optional[int]
+Relation84065030420lt=<-10;10;10;400Relation10307005601140lt=.
+390;1120;10;1120;10;10;540;10UMLClass680105020030bg=blue
+PlayerBoardGameBoardFacadeRelation750107030200lt=.>>10;10;10;180Relation152012003060lt=<-10;40;10;10Relation900128050030lt=<.10;10;480;10UMLGeneric90500830620symbol=component
+PlayerBoardUMLGeneric22306005701020symbol=component
+GamePhaseConrollerUMLGeneric10105508001520symbol=component
+GameBoardUMLClass1440760350170<<Interface>>
+InterfaceFigureLocationInternal
+--
+placeFigures(player: Player, figureCount: int):bool
+tryToPlaceFigures(player: Player, count: int): HasAction
+makeAction(player: Player, inputResources: Effect[],
+ outputResources: Effect[]): ActionResult
+skipAction(player: Player): bool
+tryToMakeAction(player: Player): HasAction
+newTurn(): bool {returns true if end of game is implied by
+ given location}
+
+UMLClass157069021030bg=blue
+FigureLocationAdaptorUMLClass150059028070<<Datatype>>
+Player
+--
+playerOrder: PlayerOrder
+playerBoard: InterfacePlayerBoardGameBoardRelation1060116041030lt=-390;10;10;10Relation37012702200860lt=<.10;90;10;840;2120;840;2120;10;2180;10Relation54012102010900lt=<.10;100;10;880;1930;880;1930;10;1990;10Relation23901070160160lt=.50;10;10;10;10;140;140;140Relation272012006030lt=.40;10;10;10Relation272012706030lt=.40;10;10;10Relation1640129025030lt=.>>10;10;230;10UMLClass1380149030070<<Interface>>
+EvaluateCivilisationCardImmediateEffect
+--
+performEffect(player: Player, choice: Effect): boolUMLClass1360167014040bg=blue
+GetSomethingFixed
+--
+effect: Effect[]
+UMLClass1560162013040bg=blue
+GetSomethingThrow
+--
+resource: Effect[]
+UMLClass1560167018040bg=blue
+GetChoice
+--
+numberOfResources: Effect[]Relation1520155030190lt=<<.10;10;10;170Relation149016709030lt=.70;10;10;10Relation149016209030lt=.10;10;70;10Relation16401320170340lt=<-10;10;150;10;150;320;50;320Relation1300134080310lt=<-10;10;50;10;50;290;60;290Relation1030153037030lt=.10;10;350;10Relation171092060890lt=<<.40;10;40;870;10;870UMLClass105040016060<<Interface>>
+InterfaceGetState
+--
+state(): stringRelation106045030170lt=<<.10;10;10;150Relation670440400110lt=<<.380;10;10;10;10;90UMLClass2150400640180<<Interface>>
+InterfaceGamePhaseController
+--
+placeFigures(player: PlayerOrder, location:Location, figuresCount: int):bool
+makeAction(player: PlayerOrder, location: Location, inputResources: Effect[], outputResources: Effect[]): bool
+skipAction(player: PlayerOrder, location: Location): bool
+useTools(player: PlayerOrder, toolIndex: int): bool
+noMoreToolsThisThrow(player: PlayerOrder): bool
+feedTribe(player: PlayerOrder, resources: Effect[]): bool
+doNotFeedThisTurn(player: PlayerOrder): bool
+makeAllPlayersTakeARewardChoice(player: PlayerOrder, reward: Effect): bool
+state(): string
+Relation151046066030lt=<.640;10;10;10UMLClass1870128029080InterfaceToolUse
+--
+useTool(idx: int):bool
+canUseTools(): bool
+finishUsingTools(): bool
+
+
+Relation137024030160lt=<<.10;10;10;140UMLClass450920340110bg=blue
+PlayerCivilisationCards
+--
+endOfGameEffects: map<EndOfGameEffectType, int>
+--
+addEndOfGameEffects(effects: EndOfGameEffectType[])
+calculateEndOfGameCivilisationCardPoints(buildings: int,
+ tools: int, fields:int, figures:int): int
+state: string()
+
+Relation2150133042030lt=<.10;10;400;10Relation146014503060lt=.>10;10;10;40Relation1300144014030lt=<-10;10;120;10Relation106015809030lt=-10;10;70;10UMLClass11301570170120bg=blue
+RewardMenu
+--
+menu: Effect[]
+players: Player[]
+--
+initiate(menu: Effect[])
+state(): stringRelation129016309030lt=<-10;10;70;10UMLClass1860157031070<<Interface>>
+InterfaceTakeReward
+--
+takeReward(player: PlayerOrder, reward: Effect): bool
+tryMakeAction(player: PlayerOrder): HasAction
+Relation1030217012030lt=.10;10;100;10UMLClass70163020090<<Dataclass>>
+PlayerOrder
+--
+order: int
+players: int
+--
+next():PlayerOrder
+Relation21601400380210lt=<.10;190;50;190;50;10;360;10Relation1290159059030lt=<<.570;10;10;10Relation17109606030lt=.40;10;10;10Relation171010406030lt=.40;10;10;10Relation1060126034030lt=-320;10;10;10Relation106014406030lt=-10;10;40;10Relation171014306030lt=.40;10;10;10Relation36073023030lt=-210;10;10;10Relation36089013030lt=-110;10;10;10Relation46056030380lt=-10;10;10;360Relation103010708030lt=.10;10;60;10UMLClass2601250210110<<Interface>>
+InterfaceFeedTribe
+--
+feedTribeIfEnoughFood(): bool
+feedTribe(resources: Effect[]): bool
+doNotFeedThisTurn(): bool
+isTribeFed(): bool
+UMLClass490125012060<<Interface>>
+InterfaceNewTurn
+--
+newTurn()
+
+Relation3701130410140lt=<<.10;120;10;10;390;10Relation540113030140lt=<<.10;120;10;10UMLClass150670220200bg=blue
+TribeFedStatus
+--
+tribeFed: bool
+fields: int
+--
+addField()
+newTurn()
+feedTribeIfEnoughFood(): bool
+feedTribe(resources: Effect[]): bool
+setTribeFed(): bool
+isTribeFed(): bool
+state(): string
+--
+{Adding fields when you have more
+than 10 has no effect}
+Relation11055060230lt=<-40;10;10;10;10;210;40;210Relation16601330130120lt=<-
+
+< next 10;50;10;20;70;20;70;100;60;100Relation272013906030lt=.40;10;10;10Relation272013406030lt=.40;10;10;10UMLClass1460172013030bg=blue
+GetCard
+Relation11001480380280lt=<-10;10;10;260;360;260Relation11079060150lt=<-40;130;10;130;10;10;40;10UMLGeneric030028601880symbol=component
+StoneAgeRelation272085020030lt=.10;10;180;10UMLClass13903108020bg=red
+UMLClass13705608020bg=red
+UMLClass45051011020bg=blue
+UMLClass243061017020bg=blue
+Relation1030164012030lt=.10;10;100;10Relation1030118044030lt=.10;10;420;10Relation1030141041030lt=.10;10;390;10
\ No newline at end of file
diff --git a/zadanie/mail1 b/zadanie/mail1
new file mode 100644
index 00000000..2b02d09c
--- /dev/null
+++ b/zadanie/mail1
@@ -0,0 +1,29 @@
+Dobry den.
+
+Do javoveho repozitara som pridal slubenu implementaciu GamePhaseControllera. Gro prace urobil ChatGPT (preklad Python -> Java). Este som sa trochu pohral so strukturou projektu a vymenil som formatovac, kedze ten co tam bol mal problemy s prikazom switch.
+
+Zaroven som si vsimol prvu vec, na ktoru som v dizajne zabudol. Interface Building by malo obsahovat state. Predpokladam, ze takychto veci objavite pocas implementacie niekolko. Fix je samozrejme jednoduchy, pridat metodu do interfacu a implementovt ju v podtriedach. Moze to napr urobit ten, kto bude implementovat BuildingTile. Samozrjme, problem by sa dal vyriesit v BuildingTile, ale delegovat ho na implementaciu Building je rozhodne spravnejsie.
+
+Na zaver vas chcem upozrnit na rozsah projektu. Projekt je velky. Neda sa urobit za vecer, ani za dva. Pri rovnomernom rozdeleni uloh v ramci timu odhadujem narocnost projektu na 2-2.5md, t.j. 16-20 hodin, a to za predpokladu, ze viete co robite. V skutocnosti vam to bude trvat o cosi dlhsie. Taktiez, timova cast sa tyka viacerych a nie je optimalne to robit na poslednu chvilu, lebo niekto moze nebyt v kritickom case dostupny. Takze vam sil;no odporucam zacat pracovat uz teraz.
+
+Odporucany timeline na najblizsi tyzden:
+
+8.8. Nainstalovat si potrebne nastroje a overit, ze ste schopny pracovat s kodom.
+Vytvorte github konto. A overte, ze mate nainstalovane dostatocne nove verzie pythonu, mypy, autopep8, pylint / javy, mavena. Make nepotrebujete, staci sa inspirovat a pouzivat prikazy z neho. Forknite si repozitar, vytvorte si novu vetvu, kde urobite drobnu zmenu, napr. implementacia + test horeuvedenej chybajucej state() metody. Pushnite zmeny na svoj forknuty repozitar a overte, ze CI je zelena.
+
+11.8. Mate dohodnute timy, rozumiete hre a dizajnu.
+Dohodli ste sa ako budete na spolocnej casti projektu postupovat. To znamena, bud mat dohodnute kto co urobi, alebo mat dohodnuty system ako budete postupovat (samoorganizacia). Rozmyslajte aj nad tym ako budete kontrolovat, ci postupujete podla planu. Dohodite si sposob komunikacie.
+
+Aby som vam s pracou na projekte pomohol, budem pre ucely projektov dostupny v extra casoch. Mozete so mnou prist konzultovat lubovolne problemy suvisiace s projektom. Taktiez mozte tento cas vyuzit na to aby ste si v ramci timu dali updaty a upravili postup. Po vyucovani bude cas iba na zodpovedanie zopar vseobecnych otazok. Ale budem k dispozicii v pondelky a stvrtky. Vyuzite tieto terminy na vcasne vyriesenie problemov rozneho druhu.
+7.11. 13:10-14:50 F1-328
+11.11 14:00-15:30 F1-328
+14.11. 13:10-14:50 F1-328
+18.11 14:00-15:30 F1-328
+21.11. 13:10-14:50 F1-328
+25.11 14:00-15:30 F1-328
+28.11. 13:10-14:50 F1-328
+
+Robert Lukotka
+
+
+Správu z AiS2 odoslal: doc. RNDr. Robert Lukoťka, PhD.
diff --git a/zadanie/stoneAge-rules.pdf b/zadanie/stoneAge-rules.pdf
new file mode 100644
index 00000000..8f93f4c3
Binary files /dev/null and b/zadanie/stoneAge-rules.pdf differ
diff --git a/zadanie/stoneAge-summary.pdf b/zadanie/stoneAge-summary.pdf
new file mode 100644
index 00000000..977493de
Binary files /dev/null and b/zadanie/stoneAge-summary.pdf differ