animals are playing arround now

This commit is contained in:
Dorian VELOSO 2024-05-23 21:22:45 +02:00
parent be6e9da50d
commit 27d720dde9
6 changed files with 297 additions and 35 deletions

0
Readme Normal file
View File

View File

@ -4,6 +4,8 @@ public class Cell {
int posX;
int posY;
int state;
int timeOfLifeSinceCut = 0;
int GROWING_TIME = 50;
public Cell(int x, int y, int lifeState) {
posX = x;
@ -26,6 +28,16 @@ public class Cell {
state = lifeState;
}
public void updateCell() {
if (state == 0) {
timeOfLifeSinceCut++;
if (timeOfLifeSinceCut > GROWING_TIME) {
timeOfLifeSinceCut = 0;
state = 1;
}
}
}
public int getState() {
return state;
}

View File

@ -12,6 +12,11 @@ public class Sheep extends Agent {
int hunger;
Random rand;
int height;
int width;
private final int REPRODUCTION_RADIUS = 1; // Radius within which sheep can reproduce
private final double REPRODUCTION_PROBABILITY = 0.1; // Probability of reproduction per turn
Sheep(int x,int y){
//first we call the constructor of the superClass(Animal)
@ -34,24 +39,55 @@ public class Sheep extends Agent {
world.setCell(x, y, 0);
} else {
hunger++;
}
height = world.getHeight();
width = world.getHeight();
// Check for reproduction
for (Agent neighbor : neighbors) {
if (neighbor instanceof Sheep && this.isInArea(neighbor.getX(), neighbor.getY(), REPRODUCTION_RADIUS)) {
if (rand.nextDouble() < REPRODUCTION_PROBABILITY) {
reproduce(world);
break;
}
}
}
this.moveRandom();
return hunger>10;
}
private void reproduce(Simulator world) {
// Find a random adjacent cell
int newX = x + rand.nextInt(3) - 1;
int newY = y + rand.nextInt(3) - 1;
// Ensure the new position is within bounds and empty
if (newX >= 0 && newX < world.getWidth() && newY >= 0 && newY < world.getHeight() && !world.getOccupied(newX, newY)) {
world.setAgent(newX, newY, new Sheep(newX, newY));
}
}
private void moveRandom() {
int direction = rand.nextInt(4);
int nx = x;
int ny = y;
if(direction == 0) {
x+=1;
nx+=1;
}
if(direction == 1) {
y+=1;
ny+=1;
}
if(direction == 2) {
x-=1;
nx-=1;
}
if(direction == 3) {
y-=1;
ny-=1;
}
// Ensure the sheep does not move out of bounds
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
x = nx;
y = ny;
}
}

View File

@ -1,5 +1,6 @@
package backend;
import java.util.ArrayList;
import java.util.Iterator;
import windowInterface.MyInterface;
@ -7,13 +8,13 @@ public class Simulator extends Thread {
private MyInterface mjf;
private final int COL_NUM = 100;
private final int LINE_NUM = 100;
private final int COL_NUM = 50;
private final int LINE_NUM = 50;
private final int LIFE_TYPE_NUM = 4;
//Conway Radius : 1
private final int LIFE_AREA_RADIUS = 1;
//Animal Neighborhood Radius : 5
private final int ANIMAL_AREA_RADIUS = 2;
private final int ANIMAL_AREA_RADIUS = 3;
private ArrayList<Integer> fieldSurviveValues;
private ArrayList<Integer> fieldBirthValues;
@ -103,16 +104,14 @@ public class Simulator extends Thread {
// only modify if sure of what you do
// to modify agent behavior, see liveTurn method
// in agent classes
for(Agent agent : agents) {
ArrayList<Agent> neighbors =
this.getNeighboringAnimals(
agent.getX(),
agent.getY(),
ANIMAL_AREA_RADIUS);
if(!agent.liveTurn(
neighbors,
this)) {
agents.remove(agent);
//Modified because of cross-modifications to the arraylist and java doesn't like that much
for (int i = 0; i < agents.size(); i++) {
Agent agent = agents.get(i);
ArrayList<Agent> neighbors = this.getNeighboringAnimals(agent.getX(), agent.getY(), ANIMAL_AREA_RADIUS);
if (agent.liveTurn(neighbors, this)) {
agents.remove(i);
i--; // Adjust the index to account for the removed element
}
}
//then evolution of the field
@ -131,7 +130,9 @@ public class Simulator extends Thread {
* and the count is in the birth list,
* then the cell becomes alive
*/
if (!clickActionFlag)
world.makeStep();
else updateCells();
}
/*
@ -152,8 +153,53 @@ public class Simulator extends Thread {
* method called when clicking on a cell in the interface
*/
public void clickCell(int x, int y) {
if (clickActionFlag) {
setAgent(x, y);
} else {
world.clickCell(x, y);;
}
}
public void setAgent(int x, int y) {
int cellValue = getCell(x, y); // Assuming you have a method getCell(x, y) to retrieve the cell value
String agentType = null;
int indexOfAgent = 0;
for (int i = 0; i < agents.size(); i++) {
Agent agent = agents.get(i);
if (agent.getX() == x && agent.getY() == y) {
if (agent instanceof Sheep) {
agentType = "Sheep";
} else {
agentType = "Wolf";
}
indexOfAgent = i;
}
}
// If the cell is empty (0), set it to 1 (food)
if (cellValue == 0 && agentType == null) {
setCell(x, y, 1); // Set the cell to indicate food
} else if (cellValue == 1) { // If the cell has food (1), replace it with a sheep
agents.add(new Sheep(x, y)); // Add a new Sheep object to the agents list
setCell(x, y, 0);
} else if (agentType == "Sheep") {//If the cell is occupied by a sheep, turn it into a wolf
agents.remove(indexOfAgent);
agents.add(new Wolf(x, y));
} else if (agentType == "Wolf") {//If the cell is occupied by a wolf, loop back to cell = 0
agents.remove(indexOfAgent);
setCell(x, y, 0);
}
}
public void setAgent(int x, int y, Agent agent) {
agents.add(agent);
setCell(x, y, 0); // Clear the cell if it had food
}
public void removeAgent(Agent agent) {
agents.remove(agent);
}
/**
* get cell value in simulated world
@ -164,6 +210,15 @@ public class Simulator extends Thread {
public int getCell(int x, int y) {
return world.getCell(x, y);
}
private void updateCells() {
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
world.updateCell(x, y);
}
}
}
/**
*
* @return list of Animals in simulated world
@ -171,6 +226,15 @@ public class Simulator extends Thread {
public ArrayList<Agent> getAnimals(){
return agents;
}
public boolean getOccupied(int x, int y) {
for (Agent agent : agents) {
if (agent.getX() == x && agent.getY() == y) {
return true;
}
}
return false;
}
/**
* selects Animals in a circular area of simulated world
* @param x center
@ -205,8 +269,22 @@ public class Simulator extends Thread {
* the simulated world in its present state
*/
public ArrayList<String> getSaveState() {
//TODO : complete method with proper return
return null;
ArrayList<String> lines = new ArrayList<>();
// Iterate over the world and construct the lines
for (int y = 0; y < LINE_NUM; y++) {
StringBuilder lineBuilder = new StringBuilder();
for (int x = 0; x < COL_NUM; x++) {
lineBuilder.append(getCell(x, y)).append(";");
}
// Remove the last semicolon
if (lineBuilder.length() > 0) {
lineBuilder.deleteCharAt(lineBuilder.length() - 1);
}
lines.add(lineBuilder.toString());
}
return lines;
}
/**
*
@ -249,14 +327,6 @@ public class Simulator extends Thread {
* to be alive in new state
*/
public void generateRandom(float chanceOfLife) {
//TODO : complete method
/*
* Advice :
* as you should probably have a separate class
* representing the field of cells...
* maybe just make a constructor in there
* and use it here
*/
world.generateRandom(chanceOfLife);
}
@ -318,15 +388,57 @@ public class Simulator extends Thread {
}
public ArrayList<String> getAgentsSave() {
//TODO : Same idea as the other save method, but for agents
return null;
ArrayList<String> lines = new ArrayList<>();
StringBuilder sheepCoordinates = new StringBuilder();
StringBuilder wolfCoordinates = new StringBuilder();
for (Agent agent : agents) {
String coordinates = agent.getX() + "," + agent.getY();
if (agent instanceof Sheep) {
if (sheepCoordinates.length() > 0) {
sheepCoordinates.append(";");
}
sheepCoordinates.append(coordinates);
} else if (agent instanceof Wolf) {
if (wolfCoordinates.length() > 0) {
wolfCoordinates.append(";");
}
wolfCoordinates.append(coordinates);
}
}
lines.add(sheepCoordinates.toString());
lines.add(wolfCoordinates.toString());
return lines;
}
public void loadAgents(ArrayList<String> stringArray) {
//TODO : Same idea as other load methods, but for agent list
agents.clear();
// Load sheeps
String sheepLine = stringArray.get(0);
String[] sheepCoords = sheepLine.split(";");
for (String coord : sheepCoords) {
String[] xy = coord.split(",");
int x = Integer.parseInt(xy[0]);
int y = Integer.parseInt(xy[1]);
agents.add(new Sheep(x, y));
}
// Load wolves
String wolfLine = stringArray.get(1);
String[] wolfCoords = wolfLine.split(";");
for (String coord : wolfCoords) {
String[] xy = coord.split(",");
int x = Integer.parseInt(xy[0]);
int y = Integer.parseInt(xy[1]);
agents.add(new Wolf(x, y));
}
}
/**
* used by label in interface to show the active click action
* @return String representation of click action

98
src/backend/Wolf.java Normal file
View File

@ -0,0 +1,98 @@
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 Wolf extends Agent {
int hunger;
Random rand;
private final int REPRODUCTION_RADIUS = 1; // Radius within which sheep can reproduce
private final double REPRODUCTION_PROBABILITY = 0.2; // Probability of reproduction per turn
Wolf(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.red);
// 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<Agent> neighbors, Simulator world) {
boolean ateSheep = false;
// Check for neighboring sheep to eat
for (Agent neighbor : neighbors) {
if (neighbor instanceof Sheep) {
// Eat the sheep (remove from the list)
world.removeAgent(neighbor);
hunger = 0; // Reset hunger
ateSheep = true;
break;
}
}
// If no sheep were eaten, increase hunger
if (!ateSheep) {
hunger++;
}
// Check for reproduction
for (Agent neighbor : neighbors) {
if (neighbor instanceof Wolf && this.isInArea(neighbor.getX(), neighbor.getY(), REPRODUCTION_RADIUS)) {
if (rand.nextDouble() < REPRODUCTION_PROBABILITY) {
reproduce(world);
break;
}
}
}
// Move randomly
this.moveRandom();
return hunger>10;
}
private void reproduce(Simulator world) {
// Find a random adjacent cell
int newX = x + rand.nextInt(3) - 1;
int newY = y + rand.nextInt(3) - 1;
// Ensure the new position is within bounds and empty
if (newX >= 0 && newX < world.getWidth() && newY >= 0 && newY < world.getHeight() && world.getCell(newX, newY) == 0) {
world.setAgent(newX, newY, new Wolf(newX, newY));
}
}
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;
}
}
}

View File

@ -37,6 +37,10 @@ public class World {
}
}
public void updateCell(int x, int y) {
grid.getCell(x, y).updateCell();
}
public void makeStep() {
Grid nextGrid = new Grid(width,height);