From 100b26a23db47f231e319caa90272cd9d1f929a1 Mon Sep 17 00:00:00 2001 From: Alexandre LETOURNEUX Date: Fri, 31 May 2024 23:44:39 +0200 Subject: [PATCH] Upload files to "/" --- Agent.java | 47 ++++++ Grid.java | 5 + Sheep.java | 92 ++++++++++++ Simulator.java | 388 +++++++++++++++++++++++++++++++++++++++++++++++++ Wolf.java | 89 ++++++++++++ 5 files changed, 621 insertions(+) create mode 100644 Agent.java create mode 100644 Grid.java create mode 100644 Sheep.java create mode 100644 Simulator.java create mode 100644 Wolf.java diff --git a/Agent.java b/Agent.java new file mode 100644 index 0000000..2ff0d62 --- /dev/null +++ b/Agent.java @@ -0,0 +1,47 @@ +package backend; + +import java.awt.Color; +import java.util.ArrayList; + +public abstract class Agent { + protected int x; + protected int y; + protected Color color; + + public int triggerRadius; // adds a radius for the animal to detect nearby food/entities + public int intelligence; // adds the capacity for an animal to get straight to its goal + // | 1 ==> will get lost on its way + // | 3 ==> will lose time on its way + // | 5 ==> will get straight to the target + + + protected Agent(int x, int y, Color color, int triggerRadius, int intelligence) { + this.x = x; + this.y = y; + this.color = color; + this.triggerRadius = triggerRadius; + this.intelligence = intelligence; + } + + public Color getDisplayColor() { + return color; + } + public int getX() { + return x; + } + public int getY() { + return y; + } + public void changeColor(Color newColor) { + this.color = newColor; + } + 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/Grid.java b/Grid.java new file mode 100644 index 0000000..597594c --- /dev/null +++ b/Grid.java @@ -0,0 +1,5 @@ +package backend; + +public class Grid { + +} diff --git a/Sheep.java b/Sheep.java new file mode 100644 index 0000000..82f838b --- /dev/null +++ b/Sheep.java @@ -0,0 +1,92 @@ +package backend; +import java.awt.Color; +import java.util.ArrayList; +import java.util.Random; + +public class Sheep extends Agent { + + int hunger; + Random rand; + + Sheep(int x,int y){ + //first we call the constructor of the superClass(Animal) + super(x,y,Color.white, 20, 3); + hunger = 0; + rand = new Random(); + } + + public boolean liveTurn(ArrayList neighbors, Simulator world) { + + // color darken the more it is starved + if(hunger<=100 && hunger>0) { + Color color = new Color((int)(255-2.54*hunger), (int)(255-2.54*hunger), (int)(255-2.54*hunger)); + this.changeColor(color); + } + + if(this.searchFood(triggerRadius, world).isEmpty()) { // no food nearby ? + this.moveRandom(world); + hunger++; + } + else { // go to food ! + this.moveToFood(this.searchFood(triggerRadius, world).get(0), this.searchFood(triggerRadius, world).get(1), world); + if(world.getCell(x, y)==1) { + world.setCell(x, y, 0); + if(hunger > 30) {hunger = hunger - 30;} + } + } + return hunger>100; + } + + private ArrayList searchFood(int radius, Simulator world) { // targets the nearest food (= cell alive) + ArrayList coordinates = new ArrayList(); + for(int x = this.x - radius; x < this.x + radius; x++) { + for(int y = this.y - radius; y < this.y + radius; y++) { + if(x > 0 && x < world.getWidth() && y > 0 && y < world.getHeight() && isInArea(x, y, radius) && world.getCell(x, y) == 1) { + coordinates.add(x); + coordinates.add(y); + } + } + } + return coordinates; + } + + private void moveRandom(Simulator world) { + int direction = rand.nextInt(4); + if(direction == 0 && x < world.getWidth()-1) { + x+=1; + } + if(direction == 1 && y < world.getHeight()-1) { + y+=1; + } + if(direction == 2 && x > 0) { + x-=1; + } + if(direction == 3 && y > 0) { + y-=1; + } + } + + private void moveToFood(int x, int y, Simulator world) { + int clever = rand.nextInt(6 - this.intelligence); + if(this.intelligence == 0) { + this.moveRandom(world); + } + + if(clever == 0) { + if(this.x < x && x < world.getWidth()-1) { + this.x+=1; + } + if(this.y < y && y < world.getHeight()-1) { + this.y+=1; + } + if(this.x > x && x > 0) { + this.x-=1; + } + if(this.y > y && y > 0) { + this.y-=1; + } + } + else {this.moveRandom(world);} + + } +} diff --git a/Simulator.java b/Simulator.java new file mode 100644 index 0000000..812cc7b --- /dev/null +++ b/Simulator.java @@ -0,0 +1,388 @@ +package backend; +import java.util.ArrayList; +import java.util.Iterator; + +import windowInterface.MyInterface; + +public class Simulator extends Thread { + + private MyInterface mjf; + + private final int COL_NUM = 200; + private final int LINE_NUM = 100; + private int[][] simuGrid = new int[COL_NUM][LINE_NUM]; + private final int LIFE_TYPE_NUM = 4; + //Conway Radius : 1 + private final int LIFE_AREA_RADIUS = 1; + private ArrayList fieldSurviveValues; + private ArrayList fieldBirthValues; + + private ArrayList agents; + + private boolean stopFlag; + private boolean pauseFlag; + private boolean loopingBorder; + private int clickActionFlag; // bool --> int to have 3 different actions (cell, sheep, wolf) + private int loopDelay = 150; + + public Simulator(MyInterface mjfParam) { + mjf = mjfParam; + stopFlag=false; + pauseFlag=false; + loopingBorder=false; + clickActionFlag=0; + + agents = new ArrayList(); + fieldBirthValues = new ArrayList(); + fieldSurviveValues = new ArrayList(); + + for(int x=0; x=COL_NUM || j<0 || j>=LINE_NUM || (i == x && j == y)) { + continue; + } + if(this.getCell(i, j) == 1) { + aliveNumber ++; + } + } + } + } + if(loopingBorder == true) { + for(int i=x-LIFE_AREA_RADIUS; i<=x+LIFE_AREA_RADIUS; i++) { + for(int j=y-LIFE_AREA_RADIUS; j<=y+LIFE_AREA_RADIUS; j++) { + + if(i == x && j == y) { + continue; + } + + if(this.getCell((i+COL_NUM)%COL_NUM, (j+LINE_NUM)%LINE_NUM) == 1) { + aliveNumber ++; + } + } + } + System.out.println(""); + } + return aliveNumber; + } + + public void run() { + + int stepCount=0; + while(!stopFlag) { + stepCount++; + makeStep(); + mjf.update(stepCount); + try { + Thread.sleep(loopDelay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + while(pauseFlag && !stopFlag) { + try { + Thread.sleep(loopDelay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + } + + public void makeStep() { + + // evolution of the animals + ArrayList morgue = new ArrayList(); // temporary list containing all the dead entities :'( + + /*for(Agent agent : agents) { + ArrayList neighbors = + this.getNeighboringAnimals( + agent.getX(), + agent.getY(), + ANIMAL_AREA_RADIUS); + if(!agent.liveTurn( + neighbors, + this)) { + agents.remove(agent); + } + }*/ + + // ConcurrentModificationException ?? We cannot iterate a list's modification ? + // The following piece of code fixes this by directly using an iterator + + for (Iterator iterator = agents.iterator(); iterator.hasNext();) { + Agent agent = iterator.next(); + + ArrayList neighbors = + this.getNeighboringAnimals( + agent.getX(), + agent.getY(), + agent.triggerRadius); + + if(agent.liveTurn( + neighbors, + this)) { + morgue.add(agent); + } + } + // clean the morgue and modify the agents list OUTSIDE the iteration + agents.removeAll(morgue); + + // evolution of the field + int n; + int[][] stepGrid = new int[COL_NUM][LINE_NUM]; + + for(int x=0; x getAnimals(){ + return agents; + } + + public ArrayList getNeighboringAnimals(int x, int y, int radius){ + ArrayList inArea = new ArrayList(); + for(int i=0;i getSaveState() { + + ArrayList lines = new ArrayList(LINE_NUM); + for(int x=0; x lines) { + + if(lines.size()<=0) { + return; + } + String firstLine = lines.get(0); + String[] firstLineElements = firstLine.split(";"); + if(firstLineElements.length<=0) { + return; + } + /* + * now we fill in the world + * with the content of the file + */ + for(int y =0; y= 1) { + setCell(x, y, 1); + } + } + } + } + + public boolean isLoopingBorder() { + return loopingBorder; + } + + public void toggleLoopingBorder() { + loopingBorder = !loopingBorder; + } + + public void setLoopDelay(int delay) { + this.loopDelay = delay; + } + + public void toggleClickAction() { + clickActionFlag ++; + } + + public ArrayList getRule() { + + ArrayList lines = new ArrayList(2); + for(int elem : fieldSurviveValues) { + String line = ""; + line += String.valueOf(elem) + ";"; + lines.add(line); + } + for(int elem : fieldBirthValues) { + String line = ""; + line += String.valueOf(elem) + ";"; + lines.add(line); + } + return lines; + } + + public void loadRule(ArrayList lines) { + + // agent file empty? + if(lines.size()<=0) { + System.out.println("empty rule file"); + return; + } + // (1) remove previous rule (= emptying lists) + this.fieldSurviveValues.clear(); + this.fieldBirthValues.clear(); + + // (2) read the content of the selected rule file + String surviveLine = lines.get(0); + String birthLine = lines.get(1); + String[] surviveElements = surviveLine.split(";"); + for(int x=0; x getAgentsSave() { + //TODO : Same idea as the other save method, but for agents + return null; + } + + public void loadAgents(ArrayList stringArray) { + + // agent file empty? + if(stringArray.size()<=0) { + System.out.println("empty agent file"); + return; + } + // (1) remove previous agent(s) (= emptying lists) + this.agents.clear(); + + // (2) read the content of the selected agent file + String line = stringArray.get(0); + String[] agentCoord = line.split(";"); + + for(int i=0; i neighbors, Simulator world) { + + // color darken the more it is starved + if(hunger<=100 && hunger>0) { + Color color = new Color((int)(255-2.54*hunger), 0, 0); + this.changeColor(color); + } + + if(this.searchPrey(triggerRadius, world).isEmpty()) { // no prey nearby ? + this.lurk(world); + hunger++; + } + else { // hunt prey ! + this.hunt(this.searchPrey(triggerRadius, world).get(0), this.searchPrey(triggerRadius, world).get(1), world); + if(world.getCell(x, y)==1) { + world.setCell(x, y, 0); + if(hunger > 30) {hunger = hunger - 30;} + } + } + return hunger>100; + } + + private ArrayList searchPrey(int radius, Simulator world) { // targets the nearest prey (= sheep) + ArrayList coordinates = new ArrayList(); + ArrayList preys = new ArrayList(); + preys = world.getNeighboringAnimals(this.x, this.y, radius); + coordinates.add(preys.get(0).getX()); // start tracking down the first sheep in sight + coordinates.add(preys.get(0).getY()); + return coordinates; + } + + private void lurk(Simulator world) { + int direction = rand.nextInt(4); + if(direction == 0 && x < world.getWidth()-1) { + x+=1; + } + if(direction == 1 && y < world.getHeight()-1) { + y+=1; + } + if(direction == 2 && x > 0) { + x-=1; + } + if(direction == 3 && y > 0) { + y-=1; + } + } + + private void hunt(int x, int y, Simulator world) { + int clever = rand.nextInt(6 - this.intelligence); + System.out.println(this.intelligence); + if(this.intelligence == 0) { + this.lurk(world); + } + + if(clever == 0) { + if(this.x < x && x < world.getWidth()-1) { + this.x+=1; + } + if(this.y < y && y < world.getHeight()-1) { + this.y+=1; + } + if(this.x > x && x > 0) { + this.x-=1; + } + if(this.y > y && y > 0) { + this.y-=1; + } + } + else {this.lurk(world);} + } + +}