> grids = mapfact.getGrids(EntityConstants.MAPWIDTH,
+ EntityConstants.MAPHEIGHT, cores);
+ final Maps gameMap = new Maps(grids);
+ // initialize player and their info.
+ final PlayerAttributes playerAttributes = new PlayerAttributes();
+ final PlayerInfo playerInfo = new PlayerInfo("Currentplayer");
+ final PlayerLocation playerLocation = new PlayerLocation();
+ final Inventory playerInventory = new Inventory();
+ final Location currentlocation = grids.get(playerLocation.getYcoordinate())
+ .get(playerLocation.getXcoordinate());
+ // initialize events and horde
+ final EventAmbush ambush = new EventAmbush();
+ final EventFlood flood = new EventFlood();
+ final EventBlizzard blizzard = new EventBlizzard();
+ final EventSurvivorJoins survivor = new EventSurvivorJoins();
+ final EventTraderEncounter traderEncounter = new EventTraderEncounter();
+ final Horde horde = new Horde();
+ // initialize ingame in memory database/dataaccess.
+ final InMemoryUnifiedDataAccess gamedatabase =
+ new InMemoryUnifiedDataAccess(playerAttributes, playerInventory, new ArrayList<>(), currentlocation,
+ horde, playerInfo, playerLocation, gameMap, ambush, blizzard, flood, survivor, traderEncounter);
+ // initialize each gameing view.
+ final CharacterCreationView attributeview = new CharacterCreationView();
+ final GameView gameView = new GameView();
+ final EventView eventView = new EventView();
+ final GameOverView gameOverView = new GameOverView();
+ final InformationView informationView = new InformationView("Daily log");
+ // initialize nevagation manager
+ final NavigationManager navigationManager =
+ new NavigationManager(mainView, attributeview, gameView, eventView, informationView, gameOverView);
+ // initialize each usecase.
+ // Nevagate to allowcate page usecase.
+ final NevagateAllowcatePresenter nevagateAllowcatePresenter = new NevagateAllowcatePresenter(navigationManager);
+ final NevagateAllowcateInteractor nevagateAllowcateInteractor = new NevagateAllowcateInteractor(
+ gamedatabase, nevagateAllowcatePresenter);
+ final NevagateAllowcateController nevagateAllowcateController = new NevagateAllowcateController(
+ nevagateAllowcateInteractor);
+
+ final ChatGptService chatGptService = new ChatGptService();
+ final ChatGptResponseParser responseParser = new ChatGptResponseParser();
+ // Allowcate points ussecase.
+ final AllowcatePresenter allowcatePresenter = new AllowcatePresenter(attributeview, navigationManager);
+ final AllowcateInteractor allowcateInteractor = new AllowcateInteractor(gamedatabase, allowcatePresenter);
+ final AllowcateController allowcateController = new AllowcateController(allowcateInteractor);
+ // Nevagate Main usecase.
+ final NevagateMainPresenter nevagateMainPresenter = new NevagateMainPresenter(navigationManager);
+ final NavigateMainInteractor nevagateMainInteractor =
+ new NavigateMainInteractor(gamedatabase, nevagateMainPresenter);
+ final NevagateMainController nevagateMainController = new NevagateMainController(nevagateMainInteractor);
+ // Fetch Usecase
+ final FetchPresenter fetchPresenter = new FetchPresenter(gameView);
+ final FetchInteractor fetchInteractor = new FetchInteractor(gamedatabase, fetchPresenter);
+ final FetchController fetchController = new FetchController(fetchInteractor);
+ // Broadcast Usecase
+ final BroadcastPresenter broadcastPresenter = new BroadcastPresenter(gameView);
+ final BroadcastInteractor broadcastInteractor = new BroadcastInteractor(gamedatabase, broadcastPresenter);
+ final BroadcastController broadcastController = new BroadcastController(broadcastInteractor);
+ // Place description usecase
+ final PlaceDescriptionPresenter placeDescriptionPresenter = new PlaceDescriptionPresenter(gameView);
+ final PlaceDescriptionInteractor placeDescriptionInteractor =
+ new PlaceDescriptionInteractor(gamedatabase, placeDescriptionPresenter);
+ final PlaceDescriptionController placeDescriptionController =
+ new PlaceDescriptionController(placeDescriptionInteractor);
+
+ // gather description usecase
+ final DailyGatherPresenter dailyGatherPresenter = new DailyGatherPresenter(gameView);
+ final GatherInteractor gatherInteractor = new GatherInteractor(gamedatabase, dailyGatherPresenter);
+ final DailyGatherController dailyGatherController = new DailyGatherController(gatherInteractor);
+
+ // Move usecase.
+ final DailyMovePresenter dailyMovePresenter = new DailyMovePresenter(gameView);
+ final MoveInteractor moveInteractor = new MoveInteractor(gamedatabase, dailyMovePresenter);
+ final DailyMoveController dailyMoveController = new DailyMoveController(moveInteractor);
+
+ // Nevagate Event usecase
+ final NevagateEventPresenter nevagateEventPresenter = new NevagateEventPresenter(navigationManager, gameView);
+ final NevagateEventInteractor nevagateEventInteractor =
+ new NevagateEventInteractor(gamedatabase, nevagateEventPresenter);
+ final NevagateEventController nevagateEventController = new NevagateEventController(nevagateEventInteractor);
+
+ // Event Initialize usecase
+ final EventInitializerPresenter eventInitializerPresenter = new EventInitializerPresenter(eventView);
+ final EventInitializeInteractor eventInitializeInteractor =
+ new EventInitializeInteractor(gamedatabase, eventInitializerPresenter);
+ final EventInitializerController eventInitializerController =
+ new EventInitializerController(eventInitializeInteractor);
+
+ // Event Decide usecase
+ final EventDecidePresenter eventDecidePresenter = new EventDecidePresenter(gameView);
+ final DecideEventInteractor decideEventInteractor =
+ new DecideEventInteractor(gamedatabase, eventDecidePresenter);
+ final EventDecideController eventDecideController = new EventDecideController(decideEventInteractor);
+
+ // Event Respond usecase ambush
+ final AmbushResponsePresenter ambushresponsePresenter = new AmbushResponsePresenter(eventView);
+ final AmbushEventInteractor ambushEventInteractor =
+ new AmbushEventInteractor(gamedatabase, ambushresponsePresenter, chatGptService);
+ final AmbushResponseController ambushResponseController = new AmbushResponseController(ambushEventInteractor);
+
+ // Event Respond usecase blizzard
+ final BlizzardResponsePresenter blizzardResponsePresenter = new BlizzardResponsePresenter(eventView);
+ final BlizzardEventInteractor blizzardEventInteractor =
+ new BlizzardEventInteractor(gamedatabase, blizzardResponsePresenter, chatGptService);
+ final BlizzardResponseController blizzardResponseController =
+ new BlizzardResponseController(blizzardEventInteractor);
+
+ // Event Respond usecase flood
+ final FloodResponsePresenter floodResponsePresenter = new FloodResponsePresenter(eventView);
+ final FloodEventInteractor floodEventInteractor =
+ new FloodEventInteractor(gamedatabase, floodResponsePresenter, chatGptService);
+ final FloodResponseController floodResponseController = new FloodResponseController(floodEventInteractor);
+
+ // Event Respond usecase survivor
+ final SurvivorResponsePresenter survivorResponsePresenter = new SurvivorResponsePresenter(eventView);
+ final SurvivorEventInteractor survivorEventInteractor =
+ new SurvivorEventInteractor(gamedatabase, survivorResponsePresenter, chatGptService);
+ final SurvivorResponseController survivorResponseController =
+ new SurvivorResponseController(survivorEventInteractor);
+
+ // Event Respond usecase trader
+ final TraderResponsePresenter traderResponsePresenter = new TraderResponsePresenter(eventView);
+ final TraderEventInteractor traderEventInteractor =
+ new TraderEventInteractor(gamedatabase, traderResponsePresenter, chatGptService);
+ final TraderResponseController traderResponseController = new TraderResponseController(traderEventInteractor);
+
+ // Initialize Event manager
+ final EventManager eventManager = new EventManager(ambushResponseController, blizzardResponseController,
+ floodResponseController, survivorResponseController, traderResponseController);
+
+ // Fetch Event usecase
+ final FetchEventPresenter fetchEventPresenter = new FetchEventPresenter(eventView);
+ final CurrentEventInteractor currentEventInteractor =
+ new CurrentEventInteractor(gamedatabase, fetchEventPresenter);
+ final FetchEventController fetchEventController = new FetchEventController(currentEventInteractor);
+
+ // Nevagate Game usecase
+ final NevagateGamePresenter nevagateGamePresenter = new NevagateGamePresenter(navigationManager);
+ final NevagateGameInteractor nevagateGameInteractor =
+ new NevagateGameInteractor(gamedatabase, nevagateGamePresenter);
+ final NevagateGameController nevagateGameController = new NevagateGameController(nevagateGameInteractor);
+
+ // Newday Game usecase
+ final NewdayPresenter newdayPresenter = new NewdayPresenter(gameView);
+ final NewdayInteractor newdayInteractor = new NewdayInteractor(gamedatabase, newdayPresenter);
+ final NewdayController newdayController = new NewdayController(newdayInteractor);
+
+ // Minimap update usecase
+ final MinimapPresenter minimapPresenter = new MinimapPresenter(gameView);
+ final MinimapInteractor minimapInteractor = new MinimapInteractor(gamedatabase, minimapPresenter);
+ final MinimapController minimapController = new MinimapController(minimapInteractor);
+
+ // Lose detect usecase
+ final LosePresenter losePresenter = new LosePresenter(gameOverView, navigationManager, gameView);
+ final LoseInteractor loseInteractor = new LoseInteractor(gamedatabase, losePresenter);
+ final LoseController loseController = new LoseController(loseInteractor);
+
+ // End process horde usecase
+ final HordePresenter hordePresenter = new HordePresenter(gameOverView, navigationManager, gameView);
+ final HordeInteractor hordeInteractor = new HordeInteractor(gamedatabase, hordePresenter);
+ final HordeController hordeController = new HordeController(hordeInteractor);
+
+ // Navigate Game Over view usecase
+ final NevagateGameOverPresenter nevagateGameOverPresenter =
+ new NevagateGameOverPresenter(navigationManager);
+ final NevagateGameOverInteractor nevagateGameOverInteractor =
+ new NevagateGameOverInteractor(gamedatabase, nevagateGameOverPresenter);
+ final NevagateGameOverController nevagateGameOverController =
+ new NevagateGameOverController(nevagateGameOverInteractor);
+
+
+ // Example of how to use the endGame method
+ // endGame("path/to/rankings.json", "Player1", score, daysSurvived, won);
+ gameView.setController(fetchController, broadcastController,
+ placeDescriptionController, dailyGatherController, dailyMoveController,
+ nevagateEventController, eventDecideController, newdayController, minimapController, loseController,
+ hordeController, nevagateGameOverController);
+ attributeview.setAllowcateController(allowcateController, nevagateMainController);
+ eventView.setController(eventInitializerController, fetchEventController, nevagateGameController);
+ eventView.setManager(eventManager);
+ gameOverView.setController(nevagateMainController);
+ gameOverView.setNavigationManager(navigationManagerJson);
+ gameOverView.setRestartGameController(this.restartGameController);
+ mainView.setNevagateAllowcateController(nevagateAllowcateController);
+ }
+
+ /**
+ * Entry point to initialize the application.
+ *
+ * @param args Command-line arguments.
+ */
+ public static void main(String[] args) {
+ try {
+ new JsonApplication("PlayerFile", "PlayerFile", "RankingFile");
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/app/MainNoteApplication.java b/src/main/java/app/MainNoteApplication.java
deleted file mode 100644
index c37860156..000000000
--- a/src/main/java/app/MainNoteApplication.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package app;
-
-import data_access.DBNoteDataAccessObject;
-import use_case.note.NoteDataAccessInterface;
-
-/**
- * An application where we can view and add to a note stored by a user.
- *
- * This is a minimal example of using the password-protected user API from lab 5,
- * but demonstrating the endpoint allowing you to store an arbitrary JSON object.
- * This functionality could be used in any project where your team wants to persist
- * data which is then accessible across devices.
- * The code is intentionally somewhat incomplete to leave work to be done if your
- * team were to choose to work on a project which would require similar functionality.
- * For example, we have intentionally not created a full "Note" entity here, but
- * rather just represented a note as a string.
- *
- * The ViewManager code has also been removed, since this minimal program only requires a single
- * view. Your team may wish to bring back the ViewManager or make your own implementation of supporting
- * switching between views depending on your project.
- */
-public class MainNoteApplication {
-
- /**
- * The main entry point of the application.
- *
- * The program will show you the note currently saved in the system.
- * You are able to edit it and then save it to the system. You can refresh
- * to update the note to reflect what was saved most recently. This
- * uses the API from lab, so there is one database storing the note,
- * which means that if anyone updates the note, that is what you will
- * see when you refresh.
- *
- * You can generalize the code to allow you to
- * specify which "user" to save the note for, which will allow your team
- * to store information specific to your team which is password-protected.
- * The username and password used in this application are currently for
- * user jonathan_calver2, but you can change that. As you did in lab 3,
- * you will likely want to store password information locally rather than
- * in your repo. Or you can require the user to enter their credentials
- * in your application; it just depends on what your program's main
- * functionality.
- *
- * @param args commandline arguments are ignored
- */
- public static void main(String[] args) {
-
- // create the data access and inject it into our builder!
- final NoteDataAccessInterface noteDataAccess = new DBNoteDataAccessObject();
-
- final NoteAppBuilder builder = new NoteAppBuilder();
- builder.addNoteDAO(noteDataAccess)
- .addNoteView()
- .addNoteUseCase().build().setVisible(true);
- }
-}
diff --git a/src/main/java/app/NoteAppBuilder.java b/src/main/java/app/NoteAppBuilder.java
deleted file mode 100644
index a68cb9ad6..000000000
--- a/src/main/java/app/NoteAppBuilder.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package app;
-
-import javax.swing.JFrame;
-import javax.swing.WindowConstants;
-
-import interface_adapter.note.NoteController;
-import interface_adapter.note.NotePresenter;
-import interface_adapter.note.NoteViewModel;
-import use_case.note.NoteDataAccessInterface;
-import use_case.note.NoteInteractor;
-import use_case.note.NoteOutputBoundary;
-import view.NoteView;
-
-/**
- * Builder for the Note Application.
- */
-public class NoteAppBuilder {
- public static final int HEIGHT = 300;
- public static final int WIDTH = 400;
- private NoteDataAccessInterface noteDAO;
- private NoteViewModel noteViewModel = new NoteViewModel();
- private NoteView noteView;
- private NoteInteractor noteInteractor;
-
- /**
- * Sets the NoteDAO to be used in this application.
- * @param noteDataAccess the DAO to use
- * @return this builder
- */
- public NoteAppBuilder addNoteDAO(NoteDataAccessInterface noteDataAccess) {
- noteDAO = noteDataAccess;
- return this;
- }
-
- /**
- * Creates the objects for the Note Use Case and connects the NoteView to its
- * controller.
- * This method must be called after addNoteView!
- * @return this builder
- * @throws RuntimeException if this method is called before addNoteView
- */
- public NoteAppBuilder addNoteUseCase() {
- final NoteOutputBoundary noteOutputBoundary = new NotePresenter(noteViewModel);
- noteInteractor = new NoteInteractor(
- noteDAO, noteOutputBoundary);
-
- final NoteController controller = new NoteController(noteInteractor);
- if (noteView == null) {
- throw new RuntimeException("addNoteView must be called before addNoteUseCase");
- }
- noteView.setNoteController(controller);
- return this;
- }
-
- /**
- * Creates the NoteView and underlying NoteViewModel.
- * @return this builder
- */
- public NoteAppBuilder addNoteView() {
- noteViewModel = new NoteViewModel();
- noteView = new NoteView(noteViewModel);
- return this;
- }
-
- /**
- * Builds the application.
- * @return the JFrame for the application
- */
- public JFrame build() {
- final JFrame frame = new JFrame();
- frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
- frame.setTitle("Note Application");
- frame.setSize(WIDTH, HEIGHT);
-
- frame.add(noteView);
-
- // refresh so that the note will be visible when we start the program
- noteInteractor.executeRefresh();
-
- return frame;
-
- }
-}
diff --git a/src/main/java/app/RankingApplication.java b/src/main/java/app/RankingApplication.java
new file mode 100644
index 000000000..b8321d63b
--- /dev/null
+++ b/src/main/java/app/RankingApplication.java
@@ -0,0 +1,43 @@
+package app;
+
+import java.io.IOException;
+
+import frameworks.database.JsonRankingDataAccess;
+import interface_adapters.rankinglist.RankingController;
+import interface_adapters.rankinglist.RankingInterface;
+import interface_adapters.rankinglist.RankingPresenter;
+import usecases.accountranking.RankingInputBoundary;
+import usecases.accountranking.RankingInteractor;
+import usecases.accountranking.RankingOutputBoundary;
+
+/**
+ * Application class for Ranking Use Case.
+ * Responsible for assembling and initializing the components for the ranking feature.
+ */
+public class RankingApplication {
+ private static String filePath = "RankingFile";
+
+ /**
+ * Initializes and assembles the components for the Ranking use case.
+ *
+ * @param rankingView The interface representing the view layer of the ranking feature.
+ * @return A RankingController instance that is connected to the use case.
+ * @throws IOException if there is an issue accessing ranking data files.
+ */
+ public static RankingController initializeRanking(RankingInterface rankingView) throws IOException {
+ // Data access layer
+ final JsonRankingDataAccess rankingDataAccess = new JsonRankingDataAccess(filePath);
+
+ // Presenter
+ final RankingPresenter rankingPresenter = new RankingPresenter(rankingView);
+
+ // Output boundary is the presenter
+ final RankingOutputBoundary outputBoundary = rankingPresenter;
+
+ // Use case interactor
+ final RankingInputBoundary rankingInteractor = new RankingInteractor(rankingDataAccess, outputBoundary);
+
+ // Controller
+ return new RankingController(rankingInteractor);
+ }
+}
diff --git a/src/main/java/app/RestartGameController.java b/src/main/java/app/RestartGameController.java
new file mode 100644
index 000000000..8ec747e86
--- /dev/null
+++ b/src/main/java/app/RestartGameController.java
@@ -0,0 +1,14 @@
+package app;
+
+public class RestartGameController {
+
+ private final JsonApplication jsonApplication;
+
+ public RestartGameController(JsonApplication jsonApplication) {
+ this.jsonApplication = jsonApplication;
+ }
+
+ public void resetGame() {
+ jsonApplication.startnewgame();
+ }
+}
diff --git a/src/main/java/data_access/DBNoteDataAccessObject.java b/src/main/java/data_access/DBNoteDataAccessObject.java
deleted file mode 100644
index dadb0cab0..000000000
--- a/src/main/java/data_access/DBNoteDataAccessObject.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package data_access;
-
-import java.io.IOException;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import entity.User;
-import okhttp3.MediaType;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.RequestBody;
-import okhttp3.Response;
-import use_case.note.DataAccessException;
-import use_case.note.NoteDataAccessInterface;
-
-/**
- * The DAO for accessing notes stored in the database.
- * This class demonstrates how your group can use the password-protected user
- * endpoints of the API used in lab 5 to store persistent data in your program.
- *
- * You can also refer to the lab 5 code for signing up a new user and other use cases.
- *
- * See
- *
- * the documentation
- * of the API for more details.
- */
-public class DBNoteDataAccessObject implements NoteDataAccessInterface {
- private static final int SUCCESS_CODE = 200;
- private static final int CREDENTIAL_ERROR = 401;
- private static final String CONTENT_TYPE_LABEL = "Content-Type";
- private static final String CONTENT_TYPE_JSON = "application/json";
- private static final String STATUS_CODE_LABEL = "status_code";
- private static final String USERNAME = "username";
- private static final String PASSWORD = "password";
- private static final String MESSAGE = "message";
-
- @Override
- public String saveNote(User user, String note) throws DataAccessException {
- final OkHttpClient client = new OkHttpClient().newBuilder()
- .build();
-
- // POST METHOD
- final MediaType mediaType = MediaType.parse(CONTENT_TYPE_JSON);
- final JSONObject requestBody = new JSONObject();
- requestBody.put(USERNAME, user.getName());
- requestBody.put(PASSWORD, user.getPassword());
- final JSONObject extra = new JSONObject();
- extra.put("note", note);
- requestBody.put("info", extra);
- final RequestBody body = RequestBody.create(requestBody.toString(), mediaType);
- final Request request = new Request.Builder()
- .url("http://vm003.teach.cs.toronto.edu:20112/modifyUserInfo")
- .method("PUT", body)
- .addHeader(CONTENT_TYPE_LABEL, CONTENT_TYPE_JSON)
- .build();
- try {
- final Response response = client.newCall(request).execute();
-
- final JSONObject responseBody = new JSONObject(response.body().string());
-
- if (responseBody.getInt(STATUS_CODE_LABEL) == SUCCESS_CODE) {
- return loadNote(user);
- }
- else if (responseBody.getInt(STATUS_CODE_LABEL) == CREDENTIAL_ERROR) {
- throw new DataAccessException("message could not be found or password was incorrect");
- }
- else {
- throw new DataAccessException("database error: " + responseBody.getString(MESSAGE));
- }
- }
- catch (IOException | JSONException ex) {
- throw new DataAccessException(ex.getMessage());
- }
- }
-
- @Override
- public String loadNote(User user) throws DataAccessException {
- // Make an API call to get the user object.
- final String username = user.getName();
- final OkHttpClient client = new OkHttpClient().newBuilder().build();
- final Request request = new Request.Builder()
- .url(String.format("http://vm003.teach.cs.toronto.edu:20112/user?username=%s", username))
- .addHeader("Content-Type", CONTENT_TYPE_JSON)
- .build();
- try {
- final Response response = client.newCall(request).execute();
-
- final JSONObject responseBody = new JSONObject(response.body().string());
-
- if (responseBody.getInt(STATUS_CODE_LABEL) == SUCCESS_CODE) {
- final JSONObject userJSONObject = responseBody.getJSONObject("user");
- final JSONObject data = userJSONObject.getJSONObject("info");
- return data.getString("note");
- }
- else {
- throw new DataAccessException(responseBody.getString(MESSAGE));
- }
- }
- catch (IOException | JSONException ex) {
- throw new RuntimeException(ex);
- }
- }
-}
diff --git a/src/main/java/entities/EntityConstants.java b/src/main/java/entities/EntityConstants.java
new file mode 100644
index 000000000..866da2ac7
--- /dev/null
+++ b/src/main/java/entities/EntityConstants.java
@@ -0,0 +1,154 @@
+package entities;
+
+/**
+ * Constants used in this program.
+ * Notice, by changing these constant, we can alter game dramatically.
+ * This could be used to achieve game balance as well as for difficulty setting implementation.
+ */
+public class EntityConstants {
+ public static final int NEWDAYSCORE = 100;
+ public static final int STARTERFOOD = 100;
+ public static final int STARTERWATER = 100;
+ public static final int STARTWEAPON = 5;
+ public static final int STARTERPEOPLE = 10;
+ public static final int STARTERACTIONPOINT = 3;
+ public static final int BROADCASTGAIN = 7;
+ public static final double SOCIALIMPACTBROADCAST = 0.05;
+ public static final int STARTERATRIBUTEPOINT = 20;
+ public static final double STARTERRESOURCESCALAR = 1;
+ public static final double RESOUCEDECREASERATIO = 0.7;
+ public static final double DEFAULTTEMP = 25;
+ public static final int CORERANGE = 16;
+ public static final double DEFAULTTHREAT = 1;
+ public static final double MAXTEMPDIFF = 50;
+ public static final double MAXTHREATDIFF = 0.5;
+
+ // Map information and calculation scalar settings.
+ public static final String ICELAND = "Iceland";
+ public static final int ICELANDCOLD = 0;
+ public static final int ICELANDEXTREMECOLD = -20;
+ public static final String DESERT = "Desert";
+ public static final int DESERTHOTDEGREE = 35;
+ public static final int DESERTUNBAREABLEDEGREE = 65;
+ public static final String FOREST = "Forest";
+ public static final double FORESTRICH = 1.25;
+ public static final double FORESTEXTREMERICH = 1.75;
+ public static final String CITY = "City";
+ public static final double CITYDANGER = 1.25;
+ public static final double CITYEXTREMEDANGER = 1.75;
+ public static final String PLAIN = "Plain";
+
+ // Name we gonna use.
+ public static final String SOCIAL = "Social";
+ public static final String LUCK = "Luck";
+ public static final String MOBILIZATION = "Mobilization";
+ public static final String THRIFT = "Thrift";
+ public static final String GENERALSHIP = "GeneralShip";
+
+ public static final int MAPHEIGHT = 100;
+ public static final int MAPWIDTH = 100;
+ public static final int SPAWNXCOOR = MAPWIDTH / 2;
+ public static final int SPAWNYCOOR = MAPHEIGHT / 2;
+ public static final int BIOMERADIUS = 16;
+ public static final int MINIMAPRADIUS = 4;
+ public static final int FIRSTCHOICE = 1;
+ public static final int SECONDCHOICE = 2;
+ public static final int THIRDCHOICE = 3;
+ public static final int FOURTHCHOICE = 4;
+
+ // Base event probability (probability at default at start).
+ public static final double COMMONEVENTBASEPROB = 0.1;
+ public static final double RAREEVENTBASEPROB = 0.05;
+
+ // Horde starter setting.
+ public static final int STARTERHORDEMAGNITUDE = 3000;
+ public static final int HORDEMAGNITUDELARGE = 4000;
+ public static final int HORDEMAGNITUDEEXTREME = 5000;
+ public static final int STARTERHORDEDURATION = 10;
+ public static final int HORDEDURATIONLONG = 8;
+ public static final int HORDEDURATIONSHORT = 6;
+ public static final double TEMPIMPACTHORDE = 0.5;
+
+ // Player attribute impacts.
+ public static final int MOBILIZATIONIMPACTSPEED = 10;
+ public static final double THRIFTIMPACTRESOURCELOSS = 0.03;
+
+ // Newday resource loss module
+ public static final double PEOPLELOSSPERFOOD = 1;
+ public static final double PEOPLELOSSPERWATER = 1;
+ public static final double PEOPLEBASEDEATHRATE = 0.05;
+
+ // Newday resource gain module
+ public static final double PEOPLEGAINPERFOOD = 0.4;
+ public static final double PEOPLEGAINPERWEAPON = 0.04;
+ public static final double PEOPLEGAINPERWATER = 0.4;
+ public static final double PEOPLEBASEJOINRATE = 0.04;
+ public static final double WEAPONBASELOSERATE = 0.04;
+
+ // Directions.
+ public static final String UP = "up";
+ public static final String DOWN = "down";
+ public static final String LEFT = "left";
+ public static final String RIGHT = "right";
+
+ // Firepower calculation settings.
+ public static final int UNARMPEOPLEPOWER = 1;
+ public static final int ARMEDPEOPLEPOWER = 5;
+
+ // Ambush constants.
+ public static final int AMBUSHPOWER = 35;
+ public static final int AMBUSHNEGOTIATE = 4;
+ public static final int AMBUSHFIGHTSUCCESSRESOURCEFOOD = 15;
+ public static final int AMBUSHFIGHTSUCCESSRESOURCEWATER = 15;
+ public static final int AMBUSHFIGHTSUCCESSRESOURCEPEOPLE = 0;
+ public static final int AMBUSHFIGHTSUCCESSRESOURCEWEAPON = 4;
+ public static final int AMBUSHFAILRESOURCEFOOD = -30;
+ public static final int AMBUSHFAILRESOURCEWATER = -30;
+ public static final int AMBUSHFAILRESOURCEPEOPLE = -5;
+ public static final int AMBUSHFAILRESOURCEWEAPON = -10;
+ // for event ambush, resource lost for failed.
+ // for any general escape choice, the distance move randomly at max.
+ public static final int LENGTHMESSAGECOMMA = 17;
+
+ // Flood event constants
+ public static final int FLOODRESOURCELOSSFOOD = -10;
+ public static final int FLOODRESOURCELOSSSECURE = -15;
+ public static final int FLOODRESOURCELOSSHIGH = -20;
+
+ public static final int FLOODPEOPLELOSSLOW = -1;
+ public static final int FLOODPEOPLELOSSMODERATE = -3;
+ public static final int FLOODPEOPLELOSSHIGH = -5;
+
+ // Blizzard constants.
+ public static final int BLIZZARDRESOURCELOSSFOOD = -15;
+ public static final int BLIZZARDRESOURCELOSSWATER = -15;
+
+ // Add these constants under the event-specific section
+ // TraderEncounter thresholds
+ public static final int TRADERNEGOTIATE = 5;
+ public static final int TRADERROBBERYPOWER = 30;
+
+ // TraderEncounter resource changes
+ public static final int TRADERTRADEGAINFOOD = 15;
+ public static final int TRADERTRADEGAINWATER = 10;
+ public static final int TRADERTRADEFAILLOSSFOOD = -5;
+ public static final int TRADERTRADEFAILLOSSWATER = -3;
+
+ public static final int TRADERROBBERYGAINFOOD = 20;
+ public static final int TRADERROBBERYGAINSUPPLIES = 5;
+ public static final int TRADERROBBERYFAILLOSSFOOD = -10;
+ public static final int TRADERROBBERYFAILLOSSPEOPLE = -2;
+
+ public static final int TRADERIGNORELOSS = 0;
+ public static final int MAXNUMDAY = 60;
+
+ // Survivor constants
+ public static final int SURVIVORACCEPTPEOPLEGAIN = 5;
+ public static final int SURVIVORROBBERYPOWER = 20;
+ public static final int SURVIVORROBBERYGAINFOOD = 10;
+ public static final int SURVIVORROBBERYGAINSUPPLIES = 5;
+ public static final int SURVIVORROBBERYFAILLOSSFOOD = -10;
+ public static final int SURVIVORROBBERYFAILLOSSPEOPLE = -2;
+
+ public static final String NEWLINE = "\n";
+}
diff --git a/src/main/java/entities/Event.java b/src/main/java/entities/Event.java
new file mode 100644
index 000000000..96a7e8065
--- /dev/null
+++ b/src/main/java/entities/Event.java
@@ -0,0 +1,48 @@
+package entities;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ * The random events of the game, this is an interface, all events should implement this.
+ */
+public interface Event {
+
+ /**
+ * Method for getting the probability.
+ * @return probability of this event occurring in the given location, time, etc.
+ */
+ double getprobability();
+
+ /**
+ * Method for setting the probability of this event.
+ * @param probability probability of this event,
+ */
+ void setprobability(double probability);
+
+ /**
+ * Getter method for the choices of the event, in map of int, string. String is the "facial" representation
+ * of the event, but actually for player's input, and response determine step, we use the int.
+ * @return Choices in map of int string.
+ */
+ Map getchoices();
+
+ /**
+ * Getter method for the brief description of the event.
+ * @return brief description of this event.
+ */
+ String getdescription();
+
+ /**
+ * Return of this is an positive event, we need this to determine how luck affect it's probability.
+ * @return Return positive or not.
+ */
+ boolean getispositive();
+
+ /**
+ * Return the only possible locations for this event to happen.
+ * @return return the occuring locations.
+ */
+ ArrayList getOccuringlocation();
+
+}
diff --git a/src/main/java/entities/EventAmbush.java b/src/main/java/entities/EventAmbush.java
new file mode 100644
index 000000000..15f7b5f93
--- /dev/null
+++ b/src/main/java/entities/EventAmbush.java
@@ -0,0 +1,106 @@
+package entities;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Event of ambush, player decide they want to fight back, pay, or negotiate. Different actions have different
+ * results as well as result descriptions. This entity is designed to remain simple, avoiding coupling and
+ * complex logic, which is handled in the use case interactor.
+ */
+public class EventAmbush implements Event {
+
+ private final Boolean isPositive;
+ private final ArrayList occuringlocation;
+ private final String description;
+ private final Map choices;
+ private double probability;
+ private final String fightoutcomesuccess;
+ private final String fightoutcomefailed;
+ private final String payoutcome;
+ private final String negotiatesuccessoutcome;
+ private final String negotiatefailedoutcome;
+
+ public EventAmbush() {
+ this.isPositive = false;
+ this.occuringlocation = new ArrayList<>();
+ occuringlocation.add(EntityConstants.PLAIN);
+ occuringlocation.add(EntityConstants.ICELAND);
+ occuringlocation.add(EntityConstants.DESERT);
+ occuringlocation.add(EntityConstants.CITY);
+ occuringlocation.add(EntityConstants.FOREST);
+ this.description = "Your group is ambushed by a small band of desperate bandits demanding your "
+ + "food supplies. Their ragged appearance suggests they're struggling to survive. What will you do?";
+ this.choices = new HashMap<>();
+ choices.put(EntityConstants.FIRSTCHOICE, "Fight back");
+ choices.put(EntityConstants.SECONDCHOICE, "Pay the bandits");
+ choices.put(EntityConstants.THIRDCHOICE, "Negotiate");
+ this.probability = EntityConstants.COMMONEVENTBASEPROB;
+ this.fightoutcomesuccess = "You successfully beat the bandits and secured their supplies.";
+ this.fightoutcomefailed = "You fought hard but were overpowered, losing some supplies.";
+ this.payoutcome = "You handed over some of your food to avoid conflict with the bandits.";
+ this.negotiatesuccessoutcome = "You successfully negotiated with the bandits, convincing"
+ + " them to leave peacefully.";
+ this.negotiatefailedoutcome = "Your negotiation failed, and the bandits"
+ + " took a portion of your supplies by force.";
+ }
+
+ @Override
+ public double getprobability() {
+ return this.probability;
+ }
+
+ @Override
+ public void setprobability(double prob) {
+ this.probability = prob;
+ }
+
+ @Override
+ public Map getchoices() {
+ return this.choices;
+ }
+
+ @Override
+ public String getdescription() {
+ return this.description;
+ }
+
+ @Override
+ public boolean getispositive() {
+ return isPositive;
+ }
+
+ @Override
+ public ArrayList getOccuringlocation() {
+ return occuringlocation;
+ }
+
+ public String getFightoutcomesuccess() {
+ return fightoutcomesuccess;
+ }
+
+ public String getFightoutcomefailed() {
+ return fightoutcomefailed;
+ }
+
+ public String getPayoutcome() {
+ return payoutcome;
+ }
+
+ public String getNegotiatesuccessoutcome() {
+ return negotiatesuccessoutcome;
+ }
+
+ public String getNegotiatefailedoutcome() {
+ return negotiatefailedoutcome;
+ }
+
+ /**
+ * Return the name of this event.
+ * @return the event name.
+ */
+ public String toString() {
+ return "Ambush";
+ }
+}
diff --git a/src/main/java/entities/EventBlizzard.java b/src/main/java/entities/EventBlizzard.java
new file mode 100644
index 000000000..03a6a094e
--- /dev/null
+++ b/src/main/java/entities/EventBlizzard.java
@@ -0,0 +1,94 @@
+package entities;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Event of a Blizzard. Represents a harsh blizzard that impacts resources and morale.
+ */
+public class EventBlizzard implements Event {
+
+ private final Boolean isPositive;
+ private final ArrayList occurringLocation;
+ private final String description;
+ private final Map choices;
+ private double probability;
+
+ private final String fightOutcome;
+ private final String negotiateOutcome;
+ private final String fleeOutcome;
+
+ public EventBlizzard() {
+ this.isPositive = false;
+ this.occurringLocation = new ArrayList<>();
+ occurringLocation.add(EntityConstants.ICELAND);
+
+ this.description = "A harsh blizzard strikes, blanketing the area in ice and snow. The biting cold "
+ + "and lack of visibility make survival challenging. What will you do?";
+ this.choices = new HashMap<>();
+ this.choices.put(EntityConstants.FIRSTCHOICE, "Secure shelter");
+ this.choices.put(EntityConstants.SECONDCHOICE, "Prepare supplies");
+ this.choices.put(EntityConstants.THIRDCHOICE, "Do nothing");
+
+ this.probability = EntityConstants.RAREEVENTBASEPROB;
+
+ this.fightOutcome = "You secured shelter from the blizzard, minimizing resource loss.";
+ this.negotiateOutcome = "You prepared supplies, but the blizzard still consumed some resources.";
+ this.fleeOutcome = "You did nothing, and the blizzard wreaked havoc on your group.";
+ }
+
+ @Override
+ public double getprobability() {
+ return this.probability;
+ }
+
+ @Override
+ public void setprobability(double prob) {
+ this.probability = prob;
+ }
+
+ @Override
+ public Map getchoices() {
+ return this.choices;
+ }
+
+ @Override
+ public String getdescription() {
+ return this.description;
+ }
+
+ @Override
+ public boolean getispositive() {
+ return isPositive;
+ }
+
+ @Override
+ public ArrayList getOccuringlocation() {
+ return occurringLocation;
+ }
+
+ public ArrayList getOccurringLocation() {
+ return occurringLocation;
+ }
+
+ public String getFightOutcome() {
+ return fightOutcome;
+ }
+
+ public String getNegotiateOutcome() {
+ return negotiateOutcome;
+ }
+
+ public String getFleeOutcome() {
+ return fleeOutcome;
+ }
+
+ /**
+ * Return the name of this event.
+ * @return the event name.
+ */
+ public String toString() {
+ return "Blizzard";
+ }
+}
diff --git a/src/main/java/entities/EventFlood.java b/src/main/java/entities/EventFlood.java
new file mode 100644
index 000000000..51d133fa0
--- /dev/null
+++ b/src/main/java/entities/EventFlood.java
@@ -0,0 +1,91 @@
+package entities;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Event of a flood. This is a negative event that occurs in Plains, Woods, or Cities.
+ * The flood causes a loss of resources or requires immediate action to mitigate damages.
+ */
+public class EventFlood implements Event {
+
+ private final Boolean isPositive;
+ private final ArrayList occuringlocation;
+ private final String description;
+ private final Map choices;
+ private double probability;
+ private final String evacuateOutcome;
+ private final String secureSuppliesOutcome;
+ private final String doNothingOutcome;
+
+ public EventFlood() {
+ this.isPositive = false;
+ this.occuringlocation = new ArrayList<>();
+ occuringlocation.add(EntityConstants.PLAIN);
+ occuringlocation.add(EntityConstants.FOREST);
+ occuringlocation.add(EntityConstants.CITY);
+
+ this.description = "Heavy rains have caused nearby rivers to overflow, threatening your group with a flood. "
+ + "You must act quickly to avoid losing supplies and people. What will you do?";
+ this.choices = new HashMap<>();
+ choices.put(EntityConstants.FIRSTCHOICE, "Evacuate");
+ choices.put(EntityConstants.SECONDCHOICE, "Secure supplies");
+ choices.put(EntityConstants.THIRDCHOICE, "hope subsides");
+
+ this.probability = EntityConstants.RAREEVENTBASEPROB;
+ this.evacuateOutcome = "You successfully evacuated, saving most of your group but losing some supplies.";
+ this.secureSuppliesOutcome = "You secured your supplies but lost time and some members to the flood.";
+ this.doNothingOutcome = "The flood devastated your group, causing heavy losses in supplies and morale.";
+ }
+
+ @Override
+ public double getprobability() {
+ return this.probability;
+ }
+
+ @Override
+ public void setprobability(double prob) {
+ this.probability = prob;
+ }
+
+ @Override
+ public Map getchoices() {
+ return this.choices;
+ }
+
+ @Override
+ public String getdescription() {
+ return this.description;
+ }
+
+ @Override
+ public boolean getispositive() {
+ return isPositive;
+ }
+
+ @Override
+ public ArrayList getOccuringlocation() {
+ return occuringlocation;
+ }
+
+ public String getEvacuateOutcome() {
+ return evacuateOutcome;
+ }
+
+ public String getSecureSuppliesOutcome() {
+ return secureSuppliesOutcome;
+ }
+
+ public String getDoNothingOutcome() {
+ return doNothingOutcome;
+ }
+
+ /**
+ * Return the name of this event.
+ * @return the event name.
+ */
+ public String toString() {
+ return "Flood";
+ }
+}
diff --git a/src/main/java/entities/EventSurvivorJoins.java b/src/main/java/entities/EventSurvivorJoins.java
new file mode 100644
index 000000000..cb92e8f15
--- /dev/null
+++ b/src/main/java/entities/EventSurvivorJoins.java
@@ -0,0 +1,99 @@
+package entities;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Event of a group of survivors wanting to join the player. The player can choose to accept, reject, or negotiate terms
+ * for joining. Different actions have different outcomes, and descriptions for each are provided. This class avoids
+ * coupling logic and leaves complex calculations to the use case interactor.
+ */
+
+public class EventSurvivorJoins implements Event {
+
+ private final Boolean isPositive;
+ private final ArrayList occuringlocation;
+ private final String description;
+ private final Map choices;
+ private double probability;
+ private final String acceptoutcome;
+ private final String rejectoutcome;
+ private final String roboutcomesuccess;
+ private final String roboutcomefail;
+
+ public EventSurvivorJoins() {
+ this.isPositive = true;
+ this.occuringlocation = new ArrayList<>();
+ occuringlocation.add(EntityConstants.PLAIN);
+ occuringlocation.add(EntityConstants.FOREST);
+ occuringlocation.add(EntityConstants.CITY);
+ this.description = "You encounter a small group of survivors who ask to join your group. They appear skilled "
+ + "but wary. What will you do?";
+ this.choices = new HashMap<>();
+ choices.put(EntityConstants.FIRSTCHOICE, "Accept them");
+ choices.put(EntityConstants.SECONDCHOICE, "reject them");
+ choices.put(EntityConstants.THIRDCHOICE, "rob them..?");
+ this.probability = EntityConstants.COMMONEVENTBASEPROB;
+ this.acceptoutcome = "You've accept them into the group";
+ this.rejectoutcome = "You've reject them into the group";
+ this.roboutcomesuccess = "You've robbed the survivor, they dear not to fight back as your group overpowered"
+ + "them, taking their supplies and leaving them helpless.";
+ this.roboutcomefail = "The robbery failed as they escaped.";
+
+ }
+
+ @Override
+ public double getprobability() {
+ return this.probability;
+ }
+
+ @Override
+ public void setprobability(double prob) {
+ this.probability = prob;
+ }
+
+ @Override
+ public Map getchoices() {
+ return this.choices;
+ }
+
+ @Override
+ public String getdescription() {
+ return this.description;
+ }
+
+ @Override
+ public boolean getispositive() {
+ return isPositive;
+ }
+
+ @Override
+ public ArrayList getOccuringlocation() {
+ return occuringlocation;
+ }
+
+ public String getAcceptoutcome() {
+ return acceptoutcome;
+ }
+
+ public String getRejectoutcome() {
+ return rejectoutcome;
+ }
+
+ public String getRoboutcomesuccess() {
+ return roboutcomesuccess;
+ }
+
+ public String getRoboutcomefail() {
+ return roboutcomefail;
+ }
+
+ /**
+ * Return the name of this event.
+ * @return the event name.
+ */
+ public String toString() {
+ return "SurvivorsJoins";
+ }
+}
diff --git a/src/main/java/entities/EventTraderEncounter.java b/src/main/java/entities/EventTraderEncounter.java
new file mode 100644
index 000000000..ecdd00bb7
--- /dev/null
+++ b/src/main/java/entities/EventTraderEncounter.java
@@ -0,0 +1,104 @@
+package entities;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Event of a trader encounter. The player can trade, ignore, or rob the trader,
+ * each leading to specific outcomes. This class is designed to store outcomes
+ * and allow interaction logic to remain in the use case layer.
+ */
+public class EventTraderEncounter implements Event {
+
+ private final Boolean isPositive;
+ private final ArrayList occuringLocation;
+ private final String description;
+ private final Map choices;
+ private double probability;
+ private final String tradeOutcomeSuccess;
+ private final String tradeOutcomeScam;
+ private final String ignoreOutcome;
+ private final String robOutcomeSuccess;
+ private final String robOutcomeFail;
+
+ public EventTraderEncounter() {
+ this.isPositive = true;
+ this.occuringLocation = new ArrayList<>();
+ occuringLocation.add(EntityConstants.PLAIN);
+ occuringLocation.add(EntityConstants.CITY);
+ occuringLocation.add(EntityConstants.DESERT);
+
+ this.description = "You encounter a wandering trader offering supplies in exchange for your resources. "
+ + "What will you do?";
+ this.choices = new HashMap<>();
+ choices.put(EntityConstants.FIRSTCHOICE, "Trade");
+ choices.put(EntityConstants.SECONDCHOICE, "Ignore");
+ choices.put(EntityConstants.THIRDCHOICE, "rob");
+
+ this.probability = EntityConstants.RAREEVENTBASEPROB;
+ this.tradeOutcomeSuccess = "You traded successfully and gained valuable supplies.";
+ this.tradeOutcomeScam = "The trader scammed you, taking your resources and leaving you with nothing.";
+ this.ignoreOutcome = "You ignored the trader and moved on.";
+ this.robOutcomeSuccess = "You successfully robbed the trader, taking their supplies.";
+ this.robOutcomeFail = "The robbery attempt failed, and you lost resources in the scuffle.";
+ }
+
+ @Override
+ public double getprobability() {
+ return this.probability;
+ }
+
+ @Override
+ public void setprobability(double prob) {
+ this.probability = prob;
+ }
+
+ @Override
+ public Map getchoices() {
+ return this.choices;
+ }
+
+ @Override
+ public String getdescription() {
+ return this.description;
+ }
+
+ @Override
+ public boolean getispositive() {
+ return isPositive;
+ }
+
+ @Override
+ public ArrayList getOccuringlocation() {
+ return occuringLocation;
+ }
+
+ public String getTradeOutcomeSuccess() {
+ return tradeOutcomeSuccess;
+ }
+
+ public String getTradeOutcomeScam() {
+ return tradeOutcomeScam;
+ }
+
+ public String getIgnoreOutcome() {
+ return ignoreOutcome;
+ }
+
+ public String getRobOutcomeSuccess() {
+ return robOutcomeSuccess;
+ }
+
+ public String getRobOutcomeFail() {
+ return robOutcomeFail;
+ }
+
+ /**
+ * Return the name of this event.
+ * @return the event name.
+ */
+ public String toString() {
+ return "TradeEncounter";
+ }
+}
diff --git a/src/main/java/entities/EventsDecided.java b/src/main/java/entities/EventsDecided.java
new file mode 100644
index 000000000..dca1cd6fe
--- /dev/null
+++ b/src/main/java/entities/EventsDecided.java
@@ -0,0 +1,22 @@
+package entities;
+
+import java.util.ArrayList;
+
+/**
+ * Events that has been decided and not yet processed by player.
+ */
+public class EventsDecided {
+ private ArrayList events;
+
+ public EventsDecided() {
+ events = new ArrayList<>();
+ }
+
+ public ArrayList getEvents() {
+ return events;
+ }
+
+ public void setEvents(ArrayList events) {
+ this.events = events;
+ }
+}
diff --git a/src/main/java/entities/Horde.java b/src/main/java/entities/Horde.java
new file mode 100644
index 000000000..b6386b1cf
--- /dev/null
+++ b/src/main/java/entities/Horde.java
@@ -0,0 +1,102 @@
+package entities;
+
+/**
+ * The class represent the horde by it's magnitude and duration. specific calculation involves other class info are for
+ * Use case interact.
+ */
+public class Horde {
+ private int magnitude;
+ // people and firepower requirement.
+ private double duration;
+ // food and water requirement.
+
+ public Horde() {
+ this.magnitude = EntityConstants.STARTERHORDEMAGNITUDE;
+ this.duration = EntityConstants.STARTERHORDEDURATION;
+ }
+
+ public Horde(int magnitude, double duration) {
+ this.magnitude = magnitude;
+ this.duration = duration;
+ }
+
+ public double getDuration() {
+ return duration;
+ }
+
+ public void setDuration(double duration) {
+ this.duration = duration;
+ }
+
+ public int getMagnitude() {
+ return magnitude;
+ }
+
+ public void setMagnitude(int magnitude) {
+ this.magnitude = magnitude;
+ }
+
+ /**
+ * Get the description for the horde, based on threatlevel and temperature of which player ended up on.
+ * @param threatLevel threat level, normal at 1, peak at 2
+ * @param temperature temperature, normal at 25, max diff at 50
+ * @return the description.
+ */
+ public String getDescription(double threatLevel, double temperature) {
+ // Adjust magnitude based on threat level
+ this.magnitude = (int) (magnitude * threatLevel);
+
+ // Adjust duration based on how far the temperature is from the ideal (25°C)
+ final double tempDifference = Math.abs(temperature - EntityConstants.DEFAULTTEMP);
+ this.duration = duration * (1 - ((EntityConstants.TEMPIMPACTHORDE * tempDifference)
+ / EntityConstants.MAXTEMPDIFF));
+
+ // Generate descriptions
+ final String magnitudeDescription;
+ if (this.magnitude < EntityConstants.HORDEMAGNITUDELARGE) {
+ magnitudeDescription = "around " + EntityConstants.HORDEMAGNITUDELARGE
+ + " zombies, scattered into smaller groups.";
+ }
+ else if (this.magnitude < EntityConstants.HORDEMAGNITUDEEXTREME) {
+ magnitudeDescription = "approximately " + EntityConstants.HORDEMAGNITUDEEXTREME
+ + " zombies, moving with relentless determination.";
+ }
+ else {
+ magnitudeDescription = "an overwhelming mass of about " + this.magnitude
+ + " zombies, consuming everything in their path.";
+ }
+
+ final String durationHint;
+ if (temperature < EntityConstants.ICELANDEXTREMECOLD) {
+ durationHint = "The bitter cold seems to sap their endurance, they won't last long out here.";
+ }
+ else if (temperature < EntityConstants.ICELANDCOLD) {
+ durationHint = "The cool air keeps them moving steadily, but they may tire eventually.";
+ }
+ else if (temperature > EntityConstants.DESERTUNBAREABLEDEGREE) {
+ durationHint = "The searing heat is taking its toll, they wont hold out for long under these conditions.";
+ }
+ else if (temperature > EntityConstants.DESERTHOTDEGREE) {
+ durationHint = "The heat made them active, but not for too long they'll dehydrate.";
+ }
+ else {
+ durationHint = "The perfect temperature not only make your group comfortable,"
+ + " but also made the horde lasting longer.";
+ }
+
+ final String durationDescription;
+ if (this.duration >= EntityConstants.HORDEDURATIONLONG) {
+ durationDescription = "It lingers for days, taking advantage of the weather.";
+ }
+ else if (this.duration >= EntityConstants.HORDEDURATIONSHORT) {
+ durationDescription = "It stays for a few days, but conditions will soon force it to dissipate.";
+ }
+ else {
+ durationDescription = "It is fleeting, scattered quickly by the harsh environment.";
+ }
+
+ // Combine descriptions
+ return "The horde consists of " + magnitudeDescription + " " + durationHint + " " + durationDescription;
+ }
+
+}
diff --git a/src/main/java/entities/Inventory.java b/src/main/java/entities/Inventory.java
new file mode 100644
index 000000000..f0626d0b1
--- /dev/null
+++ b/src/main/java/entities/Inventory.java
@@ -0,0 +1,141 @@
+package entities;
+
+/**
+ * Class reponsible for representing inventory and inventory only, provide initial resources, getter and change method.
+ */
+public class Inventory {
+
+ private int food;
+ private int water;
+ private int weapon;
+ private int people;
+
+ // Default constructor (no parameters)
+ public Inventory() {
+ this(EntityConstants.STARTERFOOD,
+ EntityConstants.STARTERWATER,
+ EntityConstants.STARTWEAPON,
+ EntityConstants.STARTERPEOPLE);
+ }
+
+ // Constructor with parameters
+ public Inventory(int food, int water, int weapon, int people) {
+ this.food = food;
+ this.water = water;
+ this.weapon = weapon;
+ this.people = people;
+ }
+
+ public int getFood() {
+ return food;
+ }
+
+ /**
+ * Changing food in inventory, can be pos or neg.
+ * @param foodChange the change which is happening.
+ */
+ public void changeFood(int foodChange) {
+ this.food = this.food + foodChange;
+ }
+
+ public int getWater() {
+ return water;
+ }
+
+ /**
+ * Changing water in inventory, can be pos or neg.
+ * @param waterChange the change which is happening.
+ */
+ public void changeWater(int waterChange) {
+ this.water = this.water + waterChange;
+ }
+
+ public int getWeapon() {
+ return weapon;
+ }
+
+ /**
+ * Changing firearm in inventory, can be pos or neg.
+ * @param weaponChange the change which is happening.
+ */
+ public void changeweapon(int weaponChange) {
+ this.weapon = this.weapon + weaponChange;
+ }
+
+ public int getPeople() {
+ return people;
+ }
+
+ /**
+ * Changing people in inventory, can be pos or neg.
+ * @param peopleChange the change which is happening.
+ */
+ public void changePeople(int peopleChange) {
+ this.people = this.people + peopleChange;
+ }
+
+ /**
+ * Calculatign the firepower of the group.
+ * @return firepower total.
+ */
+ public double getfirepower() {
+ // Calculate the number of people with weapon.
+ final int pairs = Math.min(people, weapon);
+ // Remaining people who are unarmed
+ final int unarmedPeople = people - pairs;
+
+ // Firepower: each pair contributes 5, and each unarmed person contributes 1
+ return (pairs * EntityConstants.ARMEDPEOPLEPOWER)
+ + unarmedPeople * EntityConstants.UNARMPEOPLEPOWER;
+ }
+
+ /**
+ * Method of generating string description on the change of inventory.
+ * @param foodChange change of food.
+ * @param waterChange change of water.
+ * @param peopleChange change of people.
+ * @param weaponChange change of weapon.
+ * @return String of the description.
+ */
+ public String generateResourceChangeMessage(final int foodChange, final int waterChange,
+ final int weaponChange, final int peopleChange) {
+ final StringBuilder message = new StringBuilder("Your group has ");
+ boolean hasChanges = false;
+
+ hasChanges |= appendChange(message, "food", foodChange);
+ hasChanges |= appendChange(message, "water", waterChange);
+ hasChanges |= appendChange(message, "people", peopleChange);
+ hasChanges |= appendChange(message, "weapons", weaponChange);
+
+ final String ans;
+ if (!hasChanges) {
+ ans = "Nothing has changed for your group.";
+ }
+ else {
+ message.append(".");
+ ans = message.toString();
+ }
+
+ return ans;
+ }
+
+ private boolean appendChange(final StringBuilder message, final String resourceName, final int change) {
+ boolean ans = false;
+
+ if (change != 0) {
+ if (message.length() > EntityConstants.LENGTHMESSAGECOMMA) {
+ message.append(", ");
+ }
+ if (change > 0) {
+ message.append("gained ").append(change).append(" units of ").append(resourceName);
+ }
+ else {
+ message.append("lost ").append(Math.abs(change)).append(" units of ").append(resourceName);
+ }
+ ans = true;
+ }
+
+ return ans;
+ }
+
+}
diff --git a/src/main/java/entities/Location.java b/src/main/java/entities/Location.java
new file mode 100644
index 000000000..f18a2e8a2
--- /dev/null
+++ b/src/main/java/entities/Location.java
@@ -0,0 +1,122 @@
+package entities;
+
+/**
+ * Interface for location (each specific xy coordinate), any environment should implement these.
+ * Notice, these are just basic and essential functions satisfying Interface segregation(no unnecessary implement)
+ * Notice as I said scalar closer to something increases is only for map construction step where each location
+ * starts with a higher or lower scalar. The only time resource scalar change is when player stay in same spot, decrease
+ * each day by some proportion.
+ */
+public interface Location {
+
+ /**
+ * Temperature is crucial for calculating food/water consumption. ideally, closer to core of iceland,
+ * Colder it is, as well as desert, specific calculation are for later.
+ * @param distance distance of location from its core.
+ * @return temperature.
+ */
+ Double getsettemperature(int distance);
+
+ /**
+ * Getter method of temperature.
+ * @return Temperature of that location.
+ */
+ Double gettemperature();
+
+ /**
+ * Crucial to the number people joins, in a double represent the number we'll use as scalar for people increase
+ * Method.
+ * Ideally, closer to core of city (center as more populated), it will be higher.
+ * And the longer they stay in same spot, the scalar decrease(people already joined or don't wanna join so decrease)
+ * @param distance distance from its core.
+ * @return people resource scalar.
+ */
+ Double getsetpeopleresourceavailable(int distance);
+
+ /**
+ * Getter method of people resource scalar.
+ * @return people resource scalar of that location.
+ */
+ Double getpeopleresourceavailable();
+
+ /**
+ * Crucial to the number of food gathers act as scalar. Ideally, make it high in city and woods, the scalar decrease
+ * as the longer they stayed.
+ * @param distance distance from its core.
+ * @return food resource scalar
+ */
+ Double getsetfoodresourceavailable(int distance);
+
+ /**
+ * Getter method of food resource scalar.
+ * @return food resource scalar of that location.
+ */
+ Double getfoodresourceavailable();
+
+ /**
+ * Crucial to the number of water gathers act as scalar. Ideally, make it high in iceland and wood
+ * the scalar decrease as the longer they stayed.
+ * @param distance distance from its core.
+ * @return water resource scalar
+ */
+ Double getsetwaterresourceavailable(int distance);
+
+ /**
+ * Getter method of water resource scalar.
+ * @return water resource scalar of that location.
+ */
+ Double getwaterresourceavailable();
+
+ /**
+ * Crucial to number of firearm gathered. Closer to city center, this scalar will be higher.
+ * Same spot, decrease this.
+ * @param distance distance from its core.
+ * @return firearm resource scalar
+ */
+ Double getsetweaponresourceavailable(int distance);
+
+ /**
+ * Getter method of firearm resource scalar.
+ * @return firearm resource scalar of that location.
+ */
+ Double getweaponresourceavailable();
+
+ /**
+ * The method responsible for decrease the scalar of the location if they stayed, by some proportion, determined
+ * by player's selected move ex: if player gathered, food weapon and water resource drop
+ * This is for food weapon and water drop.
+ */
+ void decreaseresourceavailable();
+
+ /**
+ * Decrease the scalar by some proportion, which is gonna happen if player broadcast, so what's left is less.
+ */
+ void decreaserepeopleavailable();
+
+
+ /**
+ * The threat level of this location, used for calculating power of the horde, and people decrease.
+ * Closer to city core, more threat level, Closer to iceland/desert,(as they are more isolated) lower threat.
+ * @param distance distance from its core.
+ * @return threat level.
+ */
+ Double getsetthreatlevel(int distance);
+
+ /**
+ * Getter method of threat scalar.
+ * @return people threat scalar of that location.
+ */
+ Double getthreatlevel();
+
+ /**
+ * String representing this place, Iceland, City etc.
+ * @return String representation.
+ */
+ String toString();
+
+ /**
+ * String for a description of the biome.
+ * @return brief description.
+ */
+ String getDescription();
+}
diff --git a/src/main/java/entities/LocationCity.java b/src/main/java/entities/LocationCity.java
new file mode 100644
index 000000000..0a43b32cf
--- /dev/null
+++ b/src/main/java/entities/LocationCity.java
@@ -0,0 +1,134 @@
+package entities;
+
+/**
+ * This is city subtype of location.
+ */
+public class LocationCity implements Location {
+ private double foodresource;
+ private double waterresource;
+ private double weaponresource;
+ private double peopleresource;
+ private double temperature;
+ private double threat;
+
+ public LocationCity(int dist) {
+ this.foodresource = EntityConstants.STARTERRESOURCESCALAR;
+ this.waterresource = EntityConstants.STARTERRESOURCESCALAR;
+ this.weaponresource = getsetweaponresourceavailable(dist);
+ this.peopleresource = getsetpeopleresourceavailable(dist);
+ this.temperature = EntityConstants.STARTERRESOURCESCALAR;
+ this.threat = getsetthreatlevel(dist);
+ }
+
+ @Override
+ public Double getsettemperature(int dist) {
+ return this.temperature;
+ }
+
+ @Override
+ public Double gettemperature() {
+ return this.temperature;
+ }
+
+ @Override
+ public Double getsetpeopleresourceavailable(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR + (1 / (dist + 1));
+ }
+
+ @Override
+ public Double getpeopleresourceavailable() {
+ return this.peopleresource;
+ }
+
+ @Override
+ public Double getsetfoodresourceavailable(int dist) {
+ return this.foodresource;
+ }
+
+ @Override
+ public Double getfoodresourceavailable() {
+ return this.foodresource;
+ }
+
+ @Override
+ public Double getsetwaterresourceavailable(int dist) {
+ return this.waterresource;
+ }
+
+ @Override
+ public Double getwaterresourceavailable() {
+ return this.waterresource;
+ }
+
+ @Override
+ public Double getsetweaponresourceavailable(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR + (1 / (dist + 1));
+ }
+
+ @Override
+ public Double getweaponresourceavailable() {
+ return this.weaponresource;
+ }
+
+ @Override
+ public void decreaseresourceavailable() {
+ this.foodresource = this.foodresource * EntityConstants.RESOUCEDECREASERATIO;
+ this.waterresource = this.waterresource * EntityConstants.RESOUCEDECREASERATIO;
+ this.weaponresource = this.weaponresource * EntityConstants.RESOUCEDECREASERATIO;
+
+ }
+
+ @Override
+ public void decreaserepeopleavailable() {
+ this.peopleresource = this.peopleresource * EntityConstants.RESOUCEDECREASERATIO;
+ }
+
+ @Override
+ public Double getsetthreatlevel(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR + (1 / (dist + 1));
+ }
+
+ @Override
+ public Double getthreatlevel() {
+ return this.threat;
+ }
+
+ @Override
+ public String toString() {
+ return EntityConstants.CITY;
+ }
+
+ @Override
+ public String getDescription() {
+ final String baseDescription =
+ "The city is a graveyard of skyscrapers, their windows shattered and facades crumbling. "
+ + "The streets are littered with rusting cars and decaying bodies, "
+ + "and the distant sound of groaning "
+ + "echoes down the alleyways.";
+
+ // Add threat-based phrasing
+ final String threatDescription;
+ if (this.threat <= EntityConstants.CITYDANGER) {
+ threatDescription =
+ "For now, the streets seem calm. Shadows shift in the distance, but it is quiet enough to risk "
+ + "searching for supplies. Your group moves cautiously, always watching for danger.";
+ }
+ else if (this.threat >= EntityConstants.CITYEXTREMEDANGER) {
+ threatDescription =
+ "The city is swarming with the infected. Groans and shuffling footsteps echo from every direction, "
+ + "and the danger is impossible to ignore. "
+ + "Every turn feels like an ambush waiting to happen, and your "
+ + "group knows it must escape quickly or risk being overwhelmed.";
+ }
+ else {
+ threatDescription =
+ "The city feels tense and unpredictable. While not overrun, signs of the infected are everywhere. "
+ + "Your group must tread carefully, "
+ + "as any sound or movement could draw unwanted attention.";
+ }
+
+ // Combine base and dynamic threat descriptions
+ return baseDescription + " " + threatDescription;
+ }
+
+}
diff --git a/src/main/java/entities/LocationDesert.java b/src/main/java/entities/LocationDesert.java
new file mode 100644
index 000000000..ea643404f
--- /dev/null
+++ b/src/main/java/entities/LocationDesert.java
@@ -0,0 +1,132 @@
+package entities;
+
+/**
+ * This is location form of Desert.
+ */
+public class LocationDesert implements Location {
+ private double foodresource;
+ private double waterresource;
+ private double weaponresource;
+ private double peopleresource;
+ private final double temperature;
+ private final double threat;
+
+ public LocationDesert(int dist) {
+ this.foodresource = EntityConstants.STARTERRESOURCESCALAR;
+ this.waterresource = getsetwaterresourceavailable(dist);
+ this.weaponresource = EntityConstants.STARTERRESOURCESCALAR;
+ this.peopleresource = getsetpeopleresourceavailable(dist);
+ this.temperature = getsettemperature(dist);
+ this.threat = EntityConstants.STARTERRESOURCESCALAR;
+ }
+
+ @Override
+ public Double getsettemperature(int dist) {
+ return EntityConstants.DEFAULTTEMP + (EntityConstants.MAXTEMPDIFF * (1 / (dist + 1)));
+ }
+
+ @Override
+ public Double gettemperature() {
+ return this.temperature;
+ }
+
+ @Override
+ public Double getsetpeopleresourceavailable(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR - (1 / (dist + 1));
+ }
+
+ @Override
+ public Double getpeopleresourceavailable() {
+ return this.peopleresource;
+ }
+
+ @Override
+ public Double getsetfoodresourceavailable(int dist) {
+ return this.foodresource;
+ }
+
+ @Override
+ public Double getfoodresourceavailable() {
+ return this.foodresource;
+ }
+
+ @Override
+ public Double getsetwaterresourceavailable(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR - (1 / (dist + 1));
+ }
+
+ @Override
+ public Double getwaterresourceavailable() {
+ return this.waterresource;
+ }
+
+ @Override
+ public Double getsetweaponresourceavailable(int dist) {
+ return this.weaponresource;
+ }
+
+ @Override
+ public Double getweaponresourceavailable() {
+ return this.weaponresource;
+ }
+
+ @Override
+ public void decreaseresourceavailable() {
+ this.foodresource = this.foodresource * EntityConstants.RESOUCEDECREASERATIO;
+ this.waterresource = this.waterresource * EntityConstants.RESOUCEDECREASERATIO;
+ this.weaponresource = this.weaponresource * EntityConstants.RESOUCEDECREASERATIO;
+ }
+
+ @Override
+ public void decreaserepeopleavailable() {
+ this.peopleresource = this.peopleresource * EntityConstants.RESOUCEDECREASERATIO;
+ }
+
+ @Override
+ public Double getsetthreatlevel(int dist) {
+ return this.threat;
+ }
+
+ @Override
+ public Double getthreatlevel() {
+ return this.threat;
+ }
+
+ @Override
+ public String toString() {
+ return EntityConstants.DESERT;
+ }
+
+ @Override
+ public String getDescription() {
+ final String baseDescription =
+ "The desert stretches endlessly, its golden dunes now marred by the occasional husk of a car "
+ + "or the skeletal remains of travelers who did not make it. The relentless sun beats down, "
+ + "offering no shelter from the horrors that might still wander here.";
+
+ // Add temperature-based phrasing
+ final String temperatureDescription;
+ if (this.temperature <= EntityConstants.DESERTHOTDEGREE) {
+ temperatureDescription =
+ "Your group finds some relief near the desert's edge. The air is warm but bearable, and "
+ + "a faint breeze carries a hint of moisture, suggesting you are not yet in the heart of "
+ + "this wasteland.";
+ }
+ else if (this.temperature >= EntityConstants.DESERTUNBAREABLEDEGREE) {
+ temperatureDescription =
+ "Your group struggles under the merciless heat, the sun blazing down like an open furnace. "
+ + "The ground is too hot to touch, and every step feels like it could be your last. "
+ + "Supplies will not last long in this heat.";
+ }
+ else {
+ temperatureDescription =
+ "The heat is punishing, but not unbearable yet. The deeper your group ventures into this "
+ + "wasteland, the more the sun saps your strength and the threat of "
+ + "dehydration looms ever larger.";
+ }
+
+ // Combine base and dynamic temperature descriptions
+ return baseDescription + " " + temperatureDescription;
+ }
+
+}
diff --git a/src/main/java/entities/LocationForest.java b/src/main/java/entities/LocationForest.java
new file mode 100644
index 000000000..1b7d478c5
--- /dev/null
+++ b/src/main/java/entities/LocationForest.java
@@ -0,0 +1,135 @@
+package entities;
+
+/**
+ * This is woods subtype of location.
+ */
+public class LocationForest implements Location {
+ private double foodresource;
+ private double waterresource;
+ private double weaponresource;
+ private double peopleresource;
+ private double temperature;
+ private double threat;
+
+ public LocationForest(int dist) {
+ this.foodresource = getsetfoodresourceavailable(dist);
+ this.waterresource = getsetwaterresourceavailable(dist);
+ this.weaponresource = EntityConstants.STARTERRESOURCESCALAR;
+ this.peopleresource = EntityConstants.STARTERRESOURCESCALAR;
+ this.temperature = EntityConstants.STARTERRESOURCESCALAR;
+ this.threat = EntityConstants.STARTERRESOURCESCALAR;
+ }
+
+ @Override
+ public Double getsettemperature(int dist) {
+ return this.temperature;
+ }
+
+ @Override
+ public Double gettemperature() {
+ return this.temperature;
+ }
+
+ @Override
+ public Double getsetpeopleresourceavailable(int dist) {
+ return this.peopleresource;
+ }
+
+ @Override
+ public Double getpeopleresourceavailable() {
+ return this.peopleresource;
+ }
+
+ @Override
+ public Double getsetfoodresourceavailable(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR + (1 / (dist + 1));
+ }
+
+ @Override
+ public Double getfoodresourceavailable() {
+ return this.foodresource;
+ }
+
+ @Override
+ public Double getsetwaterresourceavailable(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR + (1 / (dist + 1));
+ }
+
+ @Override
+ public Double getwaterresourceavailable() {
+ return this.waterresource;
+ }
+
+ @Override
+ public Double getsetweaponresourceavailable(int dist) {
+ return this.weaponresource;
+ }
+
+ @Override
+ public Double getweaponresourceavailable() {
+ return this.weaponresource;
+ }
+
+ @Override
+ public void decreaseresourceavailable() {
+ this.foodresource = this.foodresource * EntityConstants.RESOUCEDECREASERATIO;
+ this.waterresource = this.waterresource * EntityConstants.RESOUCEDECREASERATIO;
+ this.weaponresource = this.weaponresource * EntityConstants.RESOUCEDECREASERATIO;
+ }
+
+ @Override
+ public void decreaserepeopleavailable() {
+ this.peopleresource = this.peopleresource * EntityConstants.RESOUCEDECREASERATIO;
+ }
+
+ @Override
+ public Double getsetthreatlevel(int dist) {
+ return this.threat;
+ }
+
+ @Override
+ public Double getthreatlevel() {
+ return this.threat;
+ }
+
+ @Override
+ public String toString() {
+ return EntityConstants.FOREST;
+ }
+
+ @Override
+ public String getDescription() {
+ final String baseDescription =
+ "The forest feels alive yet foreboding, its towering trees "
+ + "stretching high above and casting long shadows. "
+ + "The air is rich with the scent of damp earth, and "
+ + "the undergrowth grows thick as your group ventures deeper.";
+
+ // Determine resource-based phrasing
+ final String resourceDescription;
+ if (this.foodresource <= EntityConstants.FORESTRICH
+ && this.waterresource <= EntityConstants.FORESTEXTREMERICH) {
+ resourceDescription =
+ "At the forest's edge, food and water are scarce. The sparse undergrowth offers little sustenance, "
+ + "and your group must decide carefully whether to move deeper in search of resources.";
+ }
+ else if (this.foodresource >= EntityConstants.FORESTEXTREMERICH
+ && this.waterresource >= EntityConstants.FORESTEXTREMERICH) {
+ resourceDescription =
+ "Deep within the heart of the forest, resources are plentiful. "
+ + "Your group finds wild fruits, clear streams, "
+ + "and signs of abundant wildlife. Yet the dense trees "
+ + "and eerie quiet suggest danger might not be far away.";
+ }
+ else {
+ resourceDescription =
+ "The forest offers a mix of hope and caution. While food and water are becoming easier to find, "
+ + "the growing density of the undergrowth hints at "
+ + "the challenges and risks that lie ahead.";
+ }
+
+ // Combine base and dynamic resource descriptions
+ return baseDescription + " " + resourceDescription;
+ }
+
+}
diff --git a/src/main/java/entities/LocationIceland.java b/src/main/java/entities/LocationIceland.java
new file mode 100644
index 000000000..b252a5efd
--- /dev/null
+++ b/src/main/java/entities/LocationIceland.java
@@ -0,0 +1,130 @@
+package entities;
+
+/**
+ * This is location form of Iceland.
+ */
+public class LocationIceland implements Location {
+ private double foodresource;
+ private double waterresource;
+ private double weaponresource;
+ private double peopleresource;
+ private final double temperature;
+ private final double threat;
+
+ public LocationIceland(int dist) {
+ this.foodresource = EntityConstants.STARTERRESOURCESCALAR;
+ this.waterresource = getsetwaterresourceavailable(dist);
+ this.weaponresource = EntityConstants.STARTERRESOURCESCALAR;
+ this.peopleresource = getsetpeopleresourceavailable(dist);
+ this.temperature = getsettemperature(dist);
+ this.threat = getsetthreatlevel(dist);
+ }
+
+ @Override
+ public Double getsettemperature(int dist) {
+ return EntityConstants.DEFAULTTEMP - (EntityConstants.MAXTEMPDIFF * (1 / (dist + 1)));
+ }
+
+ @Override
+ public Double gettemperature() {
+ return this.temperature;
+ }
+
+ @Override
+ public Double getsetpeopleresourceavailable(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR - (1 / (dist + 1));
+ }
+
+ @Override
+ public Double getpeopleresourceavailable() {
+ return this.peopleresource;
+ }
+
+ @Override
+ public Double getsetfoodresourceavailable(int dist) {
+ return this.foodresource;
+ }
+
+ @Override
+ public Double getfoodresourceavailable() {
+ return this.foodresource;
+ }
+
+ @Override
+ public Double getsetwaterresourceavailable(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR + (1 / (dist + 1));
+ }
+
+ @Override
+ public Double getwaterresourceavailable() {
+ return this.waterresource;
+ }
+
+ @Override
+ public Double getsetweaponresourceavailable(int dist) {
+ return this.weaponresource;
+ }
+
+ @Override
+ public Double getweaponresourceavailable() {
+ return this.weaponresource;
+ }
+
+ @Override
+ public void decreaseresourceavailable() {
+ this.foodresource = this.foodresource * EntityConstants.RESOUCEDECREASERATIO;
+ this.waterresource = this.waterresource * EntityConstants.RESOUCEDECREASERATIO;
+ this.weaponresource = this.weaponresource * EntityConstants.RESOUCEDECREASERATIO;
+ }
+
+ @Override
+ public void decreaserepeopleavailable() {
+ this.peopleresource = this.peopleresource * EntityConstants.RESOUCEDECREASERATIO;
+ }
+
+ @Override
+ public Double getsetthreatlevel(int dist) {
+ return EntityConstants.STARTERRESOURCESCALAR - (EntityConstants.MAXTHREATDIFF / (dist + 1));
+ }
+
+ @Override
+ public Double getthreatlevel() {
+ return this.threat;
+ }
+
+ @Override
+ public String toString() {
+ return EntityConstants.ICELAND;
+ }
+
+ @Override
+ public String getDescription() {
+ final String baseDescription =
+ "The icy tundra stretches endlessly, a barren landscape of snow and frost. "
+ + "Jagged ice formations rise like silent sentinels, "
+ + "and the wind howls across the open plains.";
+
+ // Add temperature-based phrasing
+ final String temperatureDescription;
+ if (this.temperature >= EntityConstants.ICELANDCOLD) {
+ temperatureDescription =
+ "The cold is biting but manageable. Your group trudges carefully, keeping an eye out for shelter "
+ + "as frost begins to settle on your gear.";
+ }
+ else if (this.temperature <= EntityConstants.ICELANDEXTREMECOLD) {
+ temperatureDescription =
+ "The cold is deadly, cutting through even the thickest clothing. Frostbite threatens your group, "
+ + "and every breath feels like shards of ice tearing through your lungs.";
+ }
+ else {
+ temperatureDescription =
+ "The freezing air saps your strength as you march onward. "
+ + "The snow is deep, and every step feels heavier, "
+ + "but the group presses on, desperate to find refuge before the cold worsens.";
+ }
+
+ // Combine base and dynamic temperature descriptions
+ return baseDescription + " " + temperatureDescription;
+ }
+
+}
diff --git a/src/main/java/entities/LocationPlain.java b/src/main/java/entities/LocationPlain.java
new file mode 100644
index 000000000..4bde6dbc7
--- /dev/null
+++ b/src/main/java/entities/LocationPlain.java
@@ -0,0 +1,105 @@
+package entities;
+
+/**
+ * This is location form of plain, more like default, which is not any of special biome (iceland, desert etc).
+ */
+public class LocationPlain implements Location {
+ private double foodResource;
+ private double waterResource;
+ private double weaponResource;
+ private double peopleResource;
+ private final double temperature;
+ private final double threat;
+
+ public LocationPlain() {
+ this.foodResource = EntityConstants.STARTERRESOURCESCALAR;
+ this.waterResource = EntityConstants.STARTERRESOURCESCALAR;
+ this.weaponResource = EntityConstants.STARTERRESOURCESCALAR;
+ this.peopleResource = EntityConstants.STARTERRESOURCESCALAR;
+ this.temperature = EntityConstants.DEFAULTTEMP;
+ this.threat = EntityConstants.DEFAULTTHREAT;
+ }
+
+ @Override
+ public Double getsettemperature(int dist) {
+ return temperature;
+ }
+
+ @Override
+ public Double gettemperature() {
+ return temperature;
+ }
+
+ @Override
+ public Double getsetpeopleresourceavailable(int dist) {
+ return this.peopleResource;
+ }
+
+ @Override
+ public Double getpeopleresourceavailable() {
+ return this.peopleResource;
+ }
+
+ @Override
+ public Double getsetfoodresourceavailable(int dist) {
+ return this.foodResource;
+ }
+
+ @Override
+ public Double getfoodresourceavailable() {
+ return this.foodResource;
+ }
+
+ @Override
+ public Double getsetwaterresourceavailable(int dist) {
+ return this.waterResource;
+ }
+
+ @Override
+ public Double getwaterresourceavailable() {
+ return this.waterResource;
+ }
+
+ @Override
+ public Double getsetweaponresourceavailable(int dist) {
+ return this.weaponResource;
+ }
+
+ @Override
+ public Double getweaponresourceavailable() {
+ return this.weaponResource;
+ }
+
+ @Override
+ public void decreaseresourceavailable() {
+ this.foodResource = this.foodResource * EntityConstants.RESOUCEDECREASERATIO;
+ this.waterResource = this.waterResource * EntityConstants.RESOUCEDECREASERATIO;
+ this.weaponResource = this.weaponResource * EntityConstants.RESOUCEDECREASERATIO;
+ }
+
+ @Override
+ public void decreaserepeopleavailable() {
+ this.peopleResource = this.peopleResource * EntityConstants.RESOUCEDECREASERATIO;
+ }
+
+ @Override
+ public Double getsetthreatlevel(int dist) {
+ return this.threat;
+ }
+
+ @Override
+ public Double getthreatlevel() {
+ return this.threat;
+ }
+
+ @Override
+ public String toString() {
+ return EntityConstants.PLAIN;
+ }
+
+ @Override
+ public String getDescription() {
+ return "The plains stretch endlessly in every direction, a sea of swaying grass under a pale, open sky. "
+ + "The emptiness is both calming and unsettling, offering little cover should danger arise.";
+ }
+}
diff --git a/src/main/java/entities/Main.java b/src/main/java/entities/Main.java
new file mode 100644
index 000000000..b72d1da6a
--- /dev/null
+++ b/src/main/java/entities/Main.java
@@ -0,0 +1,16 @@
+package entities;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+
+public class Main {
+ public static void main(String[] args) {
+ ArrayList environments = new ArrayList<>(Arrays.asList("Iceland", "Desert", "Forest", "City", "Plain"));
+ MapFactory Mapfact =new MapFactory();
+ ArrayList