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