From 5675c3486ece6cfc2e2e56189ffe145c3a8dcacf Mon Sep 17 00:00:00 2001 From: Florine Date: Fri, 31 May 2024 20:46:58 +0200 Subject: [PATCH] Final Version --- OOP_G6_Project/src/backend/Agent.java | 40 ++++ OOP_G6_Project/src/backend/Sheep.java | 59 +++++ OOP_G6_Project/src/backend/Simulator.java | 270 ++++++++++++++++++++++ 3 files changed, 369 insertions(+) create mode 100644 OOP_G6_Project/src/backend/Agent.java create mode 100644 OOP_G6_Project/src/backend/Sheep.java create mode 100644 OOP_G6_Project/src/backend/Simulator.java diff --git a/OOP_G6_Project/src/backend/Agent.java b/OOP_G6_Project/src/backend/Agent.java new file mode 100644 index 0000000..8b11e23 --- /dev/null +++ b/OOP_G6_Project/src/backend/Agent.java @@ -0,0 +1,40 @@ +package backend; + +import java.awt.Color; +import java.util.ArrayList; + +public abstract class Agent { + protected int x; + protected int y; + protected Color color; + + protected Agent(int x, int y, Color color) { + this.x = x; + this.y = y; + this.color = color; + } + + public Color getDisplayColor() { + return color; + } + public int getX() { + return x; + } + public int getY() { + return y; + } + public boolean isInArea(int x, int y, int radius) { + int diffX = this.x-x; + int diffY = this.y-y; + int dist = (int) Math.floor(Math.sqrt(diffX*diffX+diffY*diffY)); + return dist neighbors, Simulator world); + + +} diff --git a/OOP_G6_Project/src/backend/Sheep.java b/OOP_G6_Project/src/backend/Sheep.java new file mode 100644 index 0000000..ece8a18 --- /dev/null +++ b/OOP_G6_Project/src/backend/Sheep.java @@ -0,0 +1,59 @@ +package backend; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.Random; + +// example of basic animal. +// do not hesitate to make it more complex +// and DO add at least another species that interact with it +// for example wolves that eat Sheep +public class Sheep extends Agent { + + int hunger; + Random rand; + + Sheep(int x,int y){ + //first we call the constructor of the superClass(Animal) + //with the values we want. + // here we decide that a Sheep is initially white using this constructor + super(x,y,Color.white); + // we give our sheep a hunger value of zero at birth + hunger = 0; + //we initialize the random number generator we will use to move randomly + rand = new Random(); + } + + /** + * action of the animal + * it can interact with the cells or with other animals + * as you wish + */ + public boolean liveTurn(ArrayList neighbors, Simulator world) { + if(world.getCell(x, y)==1) { + world.setCell(x, y, 0); + } else { + hunger++; + } + this.moveRandom(); + return hunger>10; + } + + private void moveRandom() { + int direction = rand.nextInt(4); + if(direction == 0) { + x+=1; + } + if(direction == 1) { + y+=1; + } + if(direction == 2) { + x-=1; + } + if(direction == 3) { + y-=1; + } + } + + +} diff --git a/OOP_G6_Project/src/backend/Simulator.java b/OOP_G6_Project/src/backend/Simulator.java new file mode 100644 index 0000000..f8e5430 --- /dev/null +++ b/OOP_G6_Project/src/backend/Simulator.java @@ -0,0 +1,270 @@ +package backend; + +import java.util.ArrayList; +// Importing windowInterface for graphical user interface +import windowInterface.MyInterface; + +public class Simulator extends Thread { + + private MyInterface mjf; + + // Constants for the simulation grid dimensions and life types + private final int COL_NUM = 100; + private final int LINE_NUM = 100; + private final int LIFE_TYPE_NUM = 4; + private final int LIFE_AREA_RADIUS = 1; + private final int ANIMAL_AREA_RADIUS = 2; + + // Values for field survival and birth conditions + private ArrayList fieldSurviveValues; + private ArrayList fieldBirthValues; + + // List to store the agents (e.g., animals) in the simulation + private ArrayList agents; + + // Flags for controlling the simulation state + private boolean stopFlag; + private boolean pauseFlag; + private boolean loopingBorder; + private boolean clickActionFlag; + private int loopDelay = 150; // Delay in milliseconds between simulation steps + + // Random density slider value and dimensions of the grid + private double randomDansitySlider = 0.5; + private int width; + private int height; + private Gride gride; + + // Constructor to initialize the simulator with the interface + public Simulator(MyInterface mjfParam) { + mjf = mjfParam; + stopFlag = false; + pauseFlag = false; + loopingBorder = false; + clickActionFlag = false; + + agents = new ArrayList(); + fieldBirthValues = new ArrayList(); + fieldSurviveValues = new ArrayList(); + + this.width = COL_NUM; + this.height = LINE_NUM; + gride = new Gride(height, width, this); + + // Initializing survival values + for (int i = 0; i < 9; i++) { + fieldSurviveValues.add(i); + } + } + + // Get the width of the simulation grid + public int getWidth() { + return this.width; + } + + // Get the height of the simulation grid + public int getHeight() { + return this.height; + } + + // The main run method for the simulation thread + public void run() { + int stepCount = 0; + System.out.println("Step Count: " + stepCount); + while (!stopFlag) { + stepCount++; + makeStep(); + mjf.update(stepCount); + try { + Thread.sleep(loopDelay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // Pause handling + while (pauseFlag && !stopFlag) { + try { + Thread.sleep(loopDelay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + // Perform a single step in the simulation + public void makeStep() { + for (Agent agent : agents) { + ArrayList neighbors = this.getNeighboringAnimals(agent.getX(), agent.getY(), ANIMAL_AREA_RADIUS); + if (!agent.liveTurn(neighbors, this)) { + agents.remove(agent); + } + } + this.applyStep(); + } + + // Stop the simulation + public void stopSimu() { + stopFlag = true; + } + + // Toggle pause state of the simulation + public void togglePause() { + pauseFlag = !pauseFlag; + } + + // Handle cell click action + public void clickCell(int x, int y) { + if (clickActionFlag) { + int currentCellValue = getCell(x, y); + int newCellValue = currentCellValue == 0 ? 1 : 0; + this.setCell(x, y, newCellValue); + } + } + + // Get the value of a specific cell + public int getCell(int x, int y) { + return this.gride.getCell(x, y).getValue(); + } + + // Get the list of agents in the simulation + public ArrayList getAnimals() { + return agents; + } + + // Get neighboring agents within a certain radius + public ArrayList getNeighboringAnimals(int x, int y, int radius) { + ArrayList inArea = new ArrayList(); + for (Agent agent : agents) { + if (agent.isInArea(x, y, radius)) { + inArea.add(agent); + } + } + return inArea; + } + + // Set the value of a specific cell + public void setCell(int x, int y, int val) { + this.gride.getCell(x, y).setValue(val); + } + + // Count the number of live cells around a specific cell + public void countAround(int x, int y) { + this.gride.countAround(x, y); + System.out.println("countAround"); + } + + // Get the current state of the simulation for saving + public ArrayList getSaveState() { + return null; + } + + // Load a saved state into the simulation + public void loadSaveState(ArrayList lines) { + if (lines.size() <= 0) { + return; + } + String firstLine = lines.get(0); + String[] firstLineElements = firstLine.split(";"); + if (firstLineElements.length <= 0) { + return; + } + for (int y = 0; y < lines.size(); y++) { + String line = lines.get(y); + String[] lineElements = line.split(";"); + for (int x = 0; x < lineElements.length; x++) { + String elem = lineElements[x]; + int value = Integer.parseInt(elem); + setCell(x, y, value); + } + } + } + + // Generate a random board with a given chance of life + public void generateRandom(float chanceOfLife) { + this.gride.setRandom(chanceOfLife); + } + + // Check if the border is looping + public boolean isLoopingBorder() { + return loopingBorder; + } + + // Toggle the looping border state + public void toggleLoopingBorder() { + loopingBorder = !loopingBorder; + } + + // Set the delay between simulation steps + public void setLoopDelay(int delay) { + loopDelay = delay; + } + + // Toggle the click action state + public void toggleClickAction() { + clickActionFlag = !clickActionFlag; + } + + // Get the current rule for saving + public ArrayList getRule() { + return null; + } + + // Load a rule from a list of strings + public void loadRule(ArrayList lines) { + if (lines.size() <= 0) { + System.out.println("empty rule file"); + return; + } + String surviveLine = lines.get(0); + String birthLine = lines.get(1); + String[] surviveElements = surviveLine.split(";"); + for (String elem : surviveElements) { + int value = Integer.parseInt(elem); + } + String[] birthElements = birthLine.split(";"); + for (String elem : birthElements) { + int value = Integer.parseInt(elem); + } + } + + // Apply the step changes to the grid + public void applyStep() { + Gride newGrideUpdated = new Gride(this.height, this.width, this); + System.out.println("New Iteration :"); + for (int i = 0; i < this.height; i++) { + for (int j = 0; j < this.width; j++) { + int cellValue = this.gride.getCell(i, j).getValue(); + int newCellValue = cellValue; + int count = this.gride.countAround(i, j); + if (cellValue == 1) { + if (count == 2 || count == 3) { + newCellValue = 1; + } else { + newCellValue = 0; + } + } else { + if (count == 3) { + newCellValue = 1; + } + } + newGrideUpdated.setCell(i, j, new Cell(newCellValue)); + System.out.println("applyStep called : " + newGrideUpdated.getCell(i, j).getValue() + " at " + i + " " + j); + } + } + gride = newGrideUpdated; + } + + // Get the current agents' state for saving + public ArrayList getAgentsSave() { + return null; + } + + // Load agents from a list of strings + public void loadAgents(ArrayList stringArray) { + } + + // Used by label in interface to show the active click action + public String clickActionName() { + return ""; + } +}