diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 6111a9a..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index f9dd416..e33e7b6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,5 +13,5 @@
22
UTF-8
-
+
\ No newline at end of file
diff --git a/src/main/java/com/island/Main.java b/src/main/java/com/island/Main.java
new file mode 100644
index 0000000..519b393
--- /dev/null
+++ b/src/main/java/com/island/Main.java
@@ -0,0 +1,14 @@
+package com.island;
+
+import com.island.config.Island;
+import com.island.config.IslandInitializer;
+
+public class Main {
+ public static void main(String[] args) {
+ Island island = new Island();
+ IslandInitializer initializer = new IslandInitializer(island);
+ Simulation simulation = new Simulation(island, 10);
+
+ simulation.start(initializer);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/island/Simulation.java b/src/main/java/com/island/Simulation.java
new file mode 100644
index 0000000..06b240c
--- /dev/null
+++ b/src/main/java/com/island/Simulation.java
@@ -0,0 +1,238 @@
+package com.island;
+
+import com.island.config.Island;
+import com.island.config.IslandInitializer;
+import com.island.config.Location;
+import com.island.entities.Animal;
+import com.island.entities.Plant;
+import com.island.entities.Predator;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.*;
+import java.util.function.BiConsumer;
+
+public class Simulation {
+ private final Island island;
+
+ private static final int CHUNK_COUNT = 4;
+
+ private final int numberOfTicks;
+
+ private int tickCounter = 0;
+
+ private int movedThisTick = 0;
+ private int diedThisTick = 0;
+ private int eatenThisTick = 0;
+ private int totalEaten = 0;
+ private int bornThisTick = 0;
+ private int ateThisTick = 0;
+ private int plantsGrewThisTick = 0;
+
+ private int totalDied = 0;
+ private int totalBorn = 0;
+ private int aliveAnimals = 0;
+ private boolean allAnimalsDead = true;
+
+ private final Set locationsWithDead = new HashSet<>();
+
+ private final ScheduledExecutorService executor;
+ private final ExecutorService workerPool = Executors.newFixedThreadPool(CHUNK_COUNT);
+
+ public Simulation(Island island, int numberOfTicks) {
+ this.island = island;
+ this.numberOfTicks = numberOfTicks;
+ this.executor = Executors.newScheduledThreadPool(1);
+ }
+
+ public void start(IslandInitializer initializer) {
+ initializer.initializeAll();
+ executor.scheduleAtFixedRate(
+ this::runCycle,
+ 0,
+ 1,
+ TimeUnit.SECONDS
+ );
+ }
+
+ public void stop() {
+ executor.shutdownNow();
+ workerPool.shutdownNow();
+ }
+
+ private void runCycle() {
+ try {
+ tickCounter++;
+
+ movedThisTick = 0;
+ diedThisTick = 0;
+ bornThisTick = 0;
+ ateThisTick = 0;
+ aliveAnimals = 0;
+ plantsGrewThisTick = 0;
+
+ processInChunks(this::processMoveAndDecreaseSatiety);
+ processInChunks(this::processEatAndMultiply);
+ processInChunks(this::processAliveAnimals);
+ processInChunks(this::processDiedThisTick);
+ growPlants();
+
+ totalDied+=diedThisTick;
+ totalBorn+=bornThisTick;
+ totalEaten+=eatenThisTick;
+ printTickStatistics();
+
+ if (numberOfTicks<=tickCounter){
+ System.out.println("\nВиконано " + tickCounter + " тактів. Зупиняємо симуляцію.");
+ printFinalStatistics();
+ stop();
+ }
+
+ if (allAnimalsDead) {
+ System.out.println("\nУсі тварини померли. Зупиняємо симуляцію.");
+ printFinalStatistics();
+ stop();
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ stop();
+ }
+ }
+
+ private void processInChunks(BiConsumer chunkAction) {
+ int width = island.getWIDTH();
+ int chunkSize = (int) Math.ceil((double) width / CHUNK_COUNT);
+
+ List> futures = new ArrayList<>(CHUNK_COUNT);
+
+ for (int i = 0; i < CHUNK_COUNT; i++) {
+ final int startX = i * chunkSize;
+ final int endX = Math.min((i + 1) * chunkSize, width);
+
+ // Передаємо лямбду chunkAction у пул
+ Future> future = workerPool.submit(() -> chunkAction.accept(startX, endX));
+ futures.add(future);
+ }
+ // Чекаємо на завершення всіх задач
+ waitForAllFutures(futures);
+ }
+
+ private void processMoveAndDecreaseSatiety(int startX, int endX) {
+ for (int x = startX; x < endX; x++) {
+ for (int y = 0; y < island.getHEIGHT(); y++) {
+ Location location = island.getLocation(x, y);
+ List animals = new ArrayList<>(location.getAnimals());
+ for (Animal animal : animals) {
+ if (animal.move(island)) {
+ synchronized (this) {
+ movedThisTick++;
+ }
+ }
+ animal.decreaseSatiety();
+ }
+ }
+ }
+ }
+
+ private void processDiedThisTick(int startX, int endX) {
+ for (int x = startX; x < endX; x++) {
+ for (int y = 0; y < island.getHEIGHT(); y++) {
+ Location location = island.getLocation(x, y);
+ List animals = new ArrayList<>(location.getAnimals());
+ for (Animal animal : animals) {
+ if (!animal.isAlive()){
+ synchronized (this){
+ diedThisTick++;
+ locationsWithDead.add(location);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void processEatAndMultiply(int startX, int endX) {
+ for (int x = startX; x < endX; x++) {
+ for (int y = 0; y < island.getHEIGHT(); y++) {
+ Location location = island.getLocation(x, y);
+ List animals = new ArrayList<>(location.getAnimals());
+ for (Animal animal : animals) {
+ if (animal.eat()){
+ synchronized (this){
+ ateThisTick++;
+ }
+ if (animal instanceof Predator){
+ synchronized (this){
+ eatenThisTick++;
+ }
+ }
+ }
+ if (animal.multiply()){
+ synchronized (this){
+ bornThisTick++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void growPlants(){
+ for (Location location : locationsWithDead){
+ plantsGrewThisTick += Plant.grow(location);
+ }
+ locationsWithDead.clear();
+ }
+
+ private void processAliveAnimals(int startX, int endX) {
+ for (int x = startX; x < endX; x++) {
+ for (int y = 0; y < island.getHEIGHT(); y++) {
+ Location location = island.getLocation(x, y);
+ List animals = new ArrayList<>(location.getAnimals());
+ for (Animal animal : animals) {
+ if (animal.isAlive()){
+ synchronized (this){
+ allAnimalsDead=false;
+ aliveAnimals++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void waitForAllFutures(List> futures) {
+ for (Future> future : futures) {
+ try {
+ future.get();
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void printTickStatistics() {
+ System.out.println(
+ "\n=== Такт #" + tickCounter + " ===" +
+ "\n Живих тварин: " + aliveAnimals +
+ "\n Походило тварин: " + movedThisTick +
+ "\n Померло тварин з голоду: " + diedThisTick +
+ "\n З'їдено тварин: " + eatenThisTick +
+ "\n Народилося тварин: " + bornThisTick +
+ "\n Поїло тварин: " + ateThisTick +
+ "\n Виросло рослин: " + plantsGrewThisTick
+ );
+ }
+
+ private void printFinalStatistics(){
+ System.out.println(
+ "\n Живих тварин: " + aliveAnimals +
+ "\n Померло тварин з голоду за час симуляції: " + totalDied +
+ "\n З'їдено тварин за час симуляції: " + totalEaten +
+ "\n Народилося тварин за час симуляції: " + totalBorn
+ );
+ }
+}
diff --git a/src/main/java/com/island/config/AnimalType.java b/src/main/java/com/island/config/AnimalType.java
new file mode 100644
index 0000000..80831e2
--- /dev/null
+++ b/src/main/java/com/island/config/AnimalType.java
@@ -0,0 +1,20 @@
+package com.island.config;
+
+public enum AnimalType {
+ BEAR,
+ BOA,
+ BOAR,
+ BUFFALO,
+ CATERPILLAR,
+ DEER,
+ DUCK,
+ EAGLE,
+ FOX,
+ GOAT,
+ HORSE,
+ MOUSE,
+ RABBIT,
+ SHEEP,
+ WOLF,
+ PLANT
+}
\ No newline at end of file
diff --git a/src/main/java/com/island/config/EatingChances.java b/src/main/java/com/island/config/EatingChances.java
new file mode 100644
index 0000000..4e15f20
--- /dev/null
+++ b/src/main/java/com/island/config/EatingChances.java
@@ -0,0 +1,122 @@
+package com.island.config;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class EatingChances {
+ public static final Map> CHANCE_MAP = new HashMap<>();
+
+ static {
+ // === Вовк (WOLF) ===
+ Map wolfMap = new HashMap<>();
+ wolfMap.put(AnimalType.HORSE, 10);
+ wolfMap.put(AnimalType.DEER, 15);
+ wolfMap.put(AnimalType.RABBIT, 60);
+ wolfMap.put(AnimalType.MOUSE, 80);
+ wolfMap.put(AnimalType.GOAT, 60);
+ wolfMap.put(AnimalType.SHEEP, 70);
+ wolfMap.put(AnimalType.BOAR, 15);
+ wolfMap.put(AnimalType.BUFFALO, 10);
+ wolfMap.put(AnimalType.DUCK, 40);
+ CHANCE_MAP.put(AnimalType.WOLF, wolfMap);
+
+ // === Удав (BOA) ===
+ Map boaMap = new HashMap<>();
+ boaMap.put(AnimalType.FOX, 15);
+ boaMap.put(AnimalType.RABBIT, 20);
+ boaMap.put(AnimalType.MOUSE, 40);
+ boaMap.put(AnimalType.DUCK, 10);
+ CHANCE_MAP.put(AnimalType.BOA, boaMap);
+
+ // === Лисиця (FOX) ===
+ Map foxMap = new HashMap<>();
+ foxMap.put(AnimalType.RABBIT, 70);
+ foxMap.put(AnimalType.MOUSE, 90);
+ foxMap.put(AnimalType.DUCK, 60);
+ foxMap.put(AnimalType.CATERPILLAR, 40);
+ CHANCE_MAP.put(AnimalType.FOX, foxMap);
+
+ // === Ведмідь (BEAR) ===
+ Map bearMap = new HashMap<>();
+ bearMap.put(AnimalType.BOA, 80);
+ bearMap.put(AnimalType.HORSE, 40);
+ bearMap.put(AnimalType.DEER, 80);
+ bearMap.put(AnimalType.RABBIT, 80);
+ bearMap.put(AnimalType.MOUSE, 90);
+ bearMap.put(AnimalType.GOAT, 70);
+ bearMap.put(AnimalType.SHEEP, 70);
+ bearMap.put(AnimalType.BOAR, 50);
+ bearMap.put(AnimalType.BUFFALO, 20);
+ bearMap.put(AnimalType.DUCK, 10);
+ CHANCE_MAP.put(AnimalType.BEAR, bearMap);
+
+ // === Орел (EAGLE) ===
+ Map eagleMap = new HashMap<>();
+ eagleMap.put(AnimalType.FOX, 10);
+ eagleMap.put(AnimalType.RABBIT, 90);
+ eagleMap.put(AnimalType.MOUSE, 90);
+ eagleMap.put(AnimalType.DUCK, 80);
+ CHANCE_MAP.put(AnimalType.EAGLE, eagleMap);
+
+ // === Кінь (HORSE) ===
+ Map horseMap = new HashMap<>();
+ horseMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.HORSE, horseMap);
+
+ // === Олень (DEER) ===
+ Map deerMap = new HashMap<>();
+ deerMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.DEER, deerMap);
+
+ // === Кролик (RABBIT) ===
+ Map rabbitMap = new HashMap<>();
+ rabbitMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.RABBIT, rabbitMap);
+
+ // === Миша (MOUSE) ===
+ Map mouseMap = new HashMap<>();
+ mouseMap.put(AnimalType.CATERPILLAR, 90);
+ mouseMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.MOUSE, mouseMap);
+
+ // === Коза (GOAT) ===
+ Map goatMap = new HashMap<>();
+ goatMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.GOAT, goatMap);
+
+ // === Вівця (SHEEP) ===
+ Map sheepMap = new HashMap<>();
+ sheepMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.SHEEP, sheepMap);
+
+ // === Кабан (BOAR) ===
+ Map boarMap = new HashMap<>();
+ boarMap.put(AnimalType.MOUSE, 50);
+ boarMap.put(AnimalType.CATERPILLAR, 90);
+ boarMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.BOAR, boarMap);
+
+ // === Буйвол (BUFFALO) ===
+ Map buffaloMap = new HashMap<>();
+ buffaloMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.BUFFALO, buffaloMap);
+
+ // === Качка (DUCK) ===
+ Map duckMap = new HashMap<>();
+ duckMap.put(AnimalType.CATERPILLAR, 90);
+ duckMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.DUCK, duckMap);
+
+ // === Гусінь (CATERPILLAR) ===
+ Map caterpillarMap = new HashMap<>();
+ caterpillarMap.put(AnimalType.PLANT, 100);
+ CHANCE_MAP.put(AnimalType.CATERPILLAR, caterpillarMap);
+ }
+
+ public static int getChance(AnimalType predator, AnimalType prey) {
+ return CHANCE_MAP
+ .getOrDefault(predator, Collections.emptyMap())
+ .getOrDefault(prey, 0);
+ }
+}
diff --git a/src/main/java/com/island/config/Island.java b/src/main/java/com/island/config/Island.java
new file mode 100644
index 0000000..1186953
--- /dev/null
+++ b/src/main/java/com/island/config/Island.java
@@ -0,0 +1,33 @@
+package com.island.config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Island {
+ private final List> map = new ArrayList<>();
+
+ private static final int WIDTH = 100;
+ private static final int HEIGHT = 20;
+
+ public Island() {
+ for (int x = 0; x < WIDTH; x++) {
+ List column = new ArrayList<>();
+ for (int y = 0; y < HEIGHT; y++) {
+ column.add(new Location(x, y));
+ }
+ map.add(column);
+ }
+ }
+
+ public Location getLocation(int x, int y) {
+ return map.get(x).get(y);
+ }
+
+ public int getHEIGHT() {
+ return HEIGHT;
+ }
+
+ public int getWIDTH() {
+ return WIDTH;
+ }
+}
diff --git a/src/main/java/com/island/config/IslandInitializer.java b/src/main/java/com/island/config/IslandInitializer.java
new file mode 100644
index 0000000..f046971
--- /dev/null
+++ b/src/main/java/com/island/config/IslandInitializer.java
@@ -0,0 +1,126 @@
+package com.island.config;
+
+import com.island.entities.*;
+
+import java.lang.reflect.Constructor;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class IslandInitializer {
+
+ private final Island island;
+ private static final double FILL_FACTOR = 0.001;
+
+ public IslandInitializer(Island island){
+ this.island = island;
+ }
+
+ public void initializeAll(){
+ spawnAnimals(Bear.class);
+ spawnAnimals(Boa.class);
+ spawnAnimals(Boar.class);
+ spawnAnimals(Buffalo.class);
+ spawnAnimals(Caterpillar.class);
+ spawnAnimals(Deer.class);
+ spawnAnimals(Duck.class);
+ spawnAnimals(Eagle.class);
+ spawnAnimals(Fox.class);
+ spawnAnimals(Goat.class);
+ spawnAnimals(Horse.class);
+ spawnAnimals(Mouse.class);
+ spawnAnimals(Rabbit.class);
+ spawnAnimals(Sheep.class);
+ spawnAnimals(Wolf.class);
+
+ spawnPlants(Plant.class);
+ }
+
+ private void spawnAnimals(Class animalClass) {
+ try {
+ // 1. Дістанемо конструктор (Location)
+ Constructor constructor = animalClass.getConstructor(Location.class);
+
+ // 2. Створимо "тимчасову" тварину
+ Location dummyLocation = island.getLocation(0, 0);
+ T dummy = constructor.newInstance(dummyLocation);
+
+ // 3. Через гетер дізнаємося максимальну кількість на локації
+ int maxNumberInLocation = dummy.getMaxNumberInLocation();
+
+ // 4. Обчислюємо, скільки екземплярів (всього на острів) створити
+ int totalCells = island.getWIDTH() * island.getHEIGHT();
+ int maxPossible = (int) (maxNumberInLocation * FILL_FACTOR * totalCells);
+
+ int totalCount = ThreadLocalRandom.current().nextInt(maxPossible + 1);
+
+ int created = 0;
+ while (created < totalCount) {
+ int x = ThreadLocalRandom.current().nextInt(island.getWIDTH());
+ int y = ThreadLocalRandom.current().nextInt(island.getHEIGHT());
+ Location location = island.getLocation(x, y);
+
+ long sameSpeciesCount = location.getAnimals().stream()
+ .filter(a -> a.getClass().equals(animalClass))
+ .count();
+
+ if (sameSpeciesCount < maxNumberInLocation) {
+ T animal = constructor.newInstance(location);
+ location.addAnimal(animal);
+ created++;
+ }
+ }
+
+ System.out.println("Створено " + animalClass.getSimpleName() + ": " + created);
+
+ } catch (NoSuchMethodException e) {
+ System.err.println("У класі " + animalClass.getSimpleName()
+ + " немає конструктора (Location): " + e.getMessage());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void spawnPlants(Class plantClass) {
+ try {
+ // 1. Дістанемо конструктор (Location)
+ Constructor constructor = plantClass.getConstructor(Location.class);
+
+ // 2. Створимо "тимчасову" рослину
+ Location dummyLocation = island.getLocation(0, 0);
+ Plant dummy = constructor.newInstance(dummyLocation);
+
+ // 3. Через гетер дізнаємося максимальну кількість на локації
+ int maxNumberInLocation = dummy.getMaxNumberInLocation();
+
+ // 4. Обчислюємо, скільки екземплярів (всього на острів) створити
+ int totalCells = island.getWIDTH() * island.getHEIGHT();
+ int maxPossible = (int) (maxNumberInLocation * FILL_FACTOR * totalCells);
+
+ int totalCount = ThreadLocalRandom.current().nextInt(maxPossible + 1);
+
+ int created = 0;
+ while (created < totalCount) {
+ int x = ThreadLocalRandom.current().nextInt(island.getWIDTH());
+ int y = ThreadLocalRandom.current().nextInt(island.getHEIGHT());
+ Location location = island.getLocation(x, y);
+
+ long sameSpeciesCount = location.getPlants().stream()
+ .filter(p -> p.getClass().equals(plantClass))
+ .count();
+
+ if (sameSpeciesCount < maxNumberInLocation) {
+ Plant plant = constructor.newInstance(location);
+ location.addPlant(plant);
+ created++;
+ }
+ }
+
+ System.out.println("Створено " + plantClass.getSimpleName() + ": " + created);
+
+ } catch (NoSuchMethodException e) {
+ System.err.println("У класі " + plantClass.getSimpleName()
+ + " немає конструктора (Location): " + e.getMessage());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/com/island/config/Location.java b/src/main/java/com/island/config/Location.java
new file mode 100644
index 0000000..c81c81b
--- /dev/null
+++ b/src/main/java/com/island/config/Location.java
@@ -0,0 +1,52 @@
+package com.island.config;
+
+import com.island.entities.Animal;
+import com.island.entities.Plant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Location {
+ private final int x;
+ private final int y;
+
+ private final List animals = new ArrayList<>();
+ private final List plants = new ArrayList<>();
+
+ public Location(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public List getAnimals() {
+ return animals;
+ }
+
+ public List getPlants() {
+ return plants;
+ }
+
+ public void addAnimal(Animal animal) {
+ animals.add(animal);
+ }
+
+ public void removeAnimal(Animal animal) {
+ animals.remove(animal);
+ }
+
+ public void addPlant(Plant plant) {
+ plants.add(plant);
+ }
+
+ public void removePlant(Plant plant) {
+ plants.remove(plant);
+ }
+}
diff --git a/src/main/java/com/island/entities/Animal.java b/src/main/java/com/island/entities/Animal.java
new file mode 100644
index 0000000..c2ec21d
--- /dev/null
+++ b/src/main/java/com/island/entities/Animal.java
@@ -0,0 +1,125 @@
+package com.island.entities;
+
+import com.island.config.AnimalType;
+import com.island.config.Island;
+import com.island.config.Location;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+public abstract class Animal {
+
+ private final double weight;
+ private final int maxNumberInLocation;
+ private final int movementSpeed;
+
+ private boolean isAlive = true;
+ private Location location;
+
+ protected Animal(double weight, int maxNumberInLocation, int movementSpeed, Location location) {
+ this.weight = weight;
+ this.maxNumberInLocation = maxNumberInLocation;
+ this.movementSpeed = movementSpeed;
+ this.location=location;
+ location.addAnimal(this);
+ }
+
+ public boolean move(Island island){
+ if (!this.isAlive || this.movementSpeed==0){
+ return false;
+ }
+
+ int direction = ThreadLocalRandom.current().nextInt(4);
+
+ int steps = ThreadLocalRandom.current().nextInt(1, this.movementSpeed+1);
+
+ int x = this.location.getX();
+ int y = this.location.getY();
+
+ int newX = x;
+ int newY = y;
+
+ switch (direction){
+ case 0 -> newY=Math.max(y-steps, 0); //UP
+ case 1 -> newY=Math.min(y+steps, island.getHEIGHT() - 1); //DOWN
+ case 2 -> newX=Math.max(x-steps, 0); //LEFT
+ case 3 -> newX=Math.min(x+steps, island.getWIDTH() - 1); //RIGHT
+ default -> {
+ return false;
+ }
+ }
+
+ if (newX == x && newY == y) {
+ return false;
+ }
+
+ this.location.removeAnimal(this);
+
+ Location newLocation = island.getLocation(newX, newY);
+ newLocation.addAnimal(this);
+
+ this.location=newLocation;
+
+ return true;
+ }
+
+ public boolean multiply(){
+ long sameSpecies = 0;
+ long potentialParents = 0;
+
+ for(Animal animal : this.getLocation().getAnimals()){
+ if (animal.getClass().equals(this.getClass())){
+ sameSpecies++;
+ if (animal.isAlive() && animal.getSatiety()>=100){
+ potentialParents++;
+ }
+ }
+ }
+
+ if (potentialParents>=2 || sameSpecies0){
+ double reduceSatiety = this.getWeight()* ThreadLocalRandom.current().nextDouble(0,0.8);
+ setSatiety(Math.max(0, this.getSatiety() - reduceSatiety));
+ } else {
+ this.setDead();
+ }
+ }
+
+ public abstract void reproduce();
+
+
+ public abstract double getSatiety();
+
+ public abstract void setSatiety(double satiety);
+
+ public abstract boolean eat();
+
+ public abstract AnimalType getType();
+
+ public double getWeight() {
+ return weight;
+ }
+
+ public boolean isAlive() {
+ return isAlive;
+ }
+
+ public void setDead(){
+ this.isAlive=false;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public int getMaxNumberInLocation() {
+ return maxNumberInLocation;
+ }
+}
diff --git a/src/main/java/com/island/entities/Bear.java b/src/main/java/com/island/entities/Bear.java
new file mode 100644
index 0000000..e7323fc
--- /dev/null
+++ b/src/main/java/com/island/entities/Bear.java
@@ -0,0 +1,20 @@
+package com.island.entities;
+
+import com.island.config.AnimalType;
+import com.island.config.Location;
+
+public class Bear extends Predator {
+ public Bear(Location location){
+ super(500,5,2,80, location);
+ }
+
+ @Override
+ public void reproduce() {
+ new Bear(this.getLocation());
+ }
+
+ @Override
+ public AnimalType getType() {
+ return AnimalType.BEAR;
+ }
+}
diff --git a/src/main/java/com/island/entities/Boa.java b/src/main/java/com/island/entities/Boa.java
new file mode 100644
index 0000000..fc7ceea
--- /dev/null
+++ b/src/main/java/com/island/entities/Boa.java
@@ -0,0 +1,20 @@
+package com.island.entities;
+
+import com.island.config.AnimalType;
+import com.island.config.Location;
+
+public class Boa extends Predator {
+ public Boa(Location location) {
+ super(15.0, 30, 1, 3, location);
+ }
+
+ @Override
+ public void reproduce() {
+ new Boa(this.getLocation());
+ }
+
+ @Override
+ public AnimalType getType() {
+ return AnimalType.BOA;
+ }
+}
diff --git a/src/main/java/com/island/entities/Boar.java b/src/main/java/com/island/entities/Boar.java
new file mode 100644
index 0000000..cc166d1
--- /dev/null
+++ b/src/main/java/com/island/entities/Boar.java
@@ -0,0 +1,62 @@
+package com.island.entities;
+
+import com.island.config.AnimalType;
+import com.island.config.EatingChances;
+import com.island.config.Location;
+
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class Boar extends Herbivore {
+ public Boar(Location location){
+ super(400, 50, 2, 50, location);
+ }
+
+ private boolean tryEatOther(){
+ if (!this.isAlive() || this.getSatiety()>=100){
+ return false;
+ }
+
+ List animalsHere = this.getLocation().getAnimals();
+
+ for (Animal victim : animalsHere){
+ int chance = EatingChances.getChance(this.getType(),victim.getType());
+
+ if (victim==this || !victim.isAlive() || chance<=0){
+ continue;
+ }
+
+ int roll = ThreadLocalRandom.current().nextInt(100);
+ if (roll=100){
+ return false;
+ }
+
+ List animalsHere = this.getLocation().getAnimals();
+
+ for (Animal victim : animalsHere){
+ int chance = EatingChances.getChance(this.getType(),victim.getType());
+
+ if (victim==this || !victim.isAlive() || chance<=0){
+ continue;
+ }
+
+ int roll = ThreadLocalRandom.current().nextInt(100);
+ if (roll100){
+ this.satiety=100;
+ }
+ }
+
+ @Override
+ public boolean eat() {
+ if (!this.isAlive() || this.getSatiety()>=100) {
+ return false;
+ }
+
+ List plantsHere = this.getLocation().getPlants();
+ for (Plant plant : plantsHere){
+ int chance = EatingChances.getChance(this.getType(),plant.getType());
+
+ if (chance<=0){
+ continue;
+ }
+
+ int roll = ThreadLocalRandom.current().nextInt(100);
+ if (roll=100){
+ return false;
+ }
+
+ List animalsHere = this.getLocation().getAnimals();
+
+ for (Animal victim : animalsHere){
+ int chance = EatingChances.getChance(this.getType(),victim.getType());
+
+ if (victim==this || !victim.isAlive() || chance<=0){
+ continue;
+ }
+
+ int roll = ThreadLocalRandom.current().nextInt(100);
+ if (roll deadAnimals = new ArrayList<>();
+
+ for (Animal animal : location.getAnimals()){
+ if (!animal.isAlive()) {
+ deadAnimalsWeight += animal.getWeight();
+ deadAnimals.add(animal);
+ }
+ }
+
+ for (Plant _ : location.getPlants()){
+ plantsInLocation++;
+ }
+
+ location.getAnimals().removeAll(deadAnimals);
+
+ int plantsFromDead = (int) Math.ceil(deadAnimalsWeight);
+ int canAdd = MAX_NUMBER_IN_LOCATION - plantsInLocation;
+
+ if (canAdd <= 0){
+ return 0;
+ }
+
+ int toAdd = Math.min(plantsFromDead, canAdd);
+
+ for (int i = 0; i < toAdd; i++){
+ new Plant(location);
+ }
+
+ return toAdd;
+ }
+
+ public double getWeight() {
+ return WEIGHT;
+ }
+
+ public int getMaxNumberInLocation() {
+ return MAX_NUMBER_IN_LOCATION;
+ }
+
+ public AnimalType getType(){
+ return AnimalType.PLANT;
+ }
+}
diff --git a/src/main/java/com/island/entities/Predator.java b/src/main/java/com/island/entities/Predator.java
new file mode 100644
index 0000000..7409016
--- /dev/null
+++ b/src/main/java/com/island/entities/Predator.java
@@ -0,0 +1,80 @@
+package com.island.entities;
+
+import com.island.config.AnimalType;
+import com.island.config.EatingChances;
+import com.island.config.Location;
+
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+public abstract class Predator extends Animal {
+
+ private final double foodNeeded;
+ private double satiety=50;
+
+ protected Predator(double weight, int maxNumberInLocation, int movementSpeed, double foodNeeded, Location location) {
+ super(weight, maxNumberInLocation, movementSpeed, location);
+ this.foodNeeded=foodNeeded;
+ }
+
+ public abstract void reproduce();
+
+ public abstract AnimalType getType();
+
+ protected void increaseSatiety(double eatenWeight){
+ double newSatiety = (eatenWeight / this.foodNeeded) * 100;
+
+ this.satiety += newSatiety;
+ if (this.satiety>100){
+ this.satiety=100;
+ }
+ }
+
+ public void decreaseSatiety(){
+ if (this.isAlive() && this.satiety>0){
+ double reduceSatiety = this.getWeight()*ThreadLocalRandom.current().nextDouble(0,0.3);
+ satiety = Math.max(0, this.satiety - reduceSatiety);
+ } else {
+ this.setDead();
+ }
+ }
+
+ @Override
+ public boolean eat() {
+ if (!this.isAlive() || this.getSatiety()>=100){
+ return false;
+ }
+
+ List animalsHere = this.getLocation().getAnimals();
+
+ for (Animal victim : animalsHere){
+ int chance = EatingChances.getChance(this.getType(),victim.getType());
+
+ if (victim==this || !victim.isAlive() || chance<=0){
+ continue;
+ }
+
+ int roll = ThreadLocalRandom.current().nextInt(100);
+ if (roll