final version in the right gitarero folder this time
This commit is contained in:
parent
2ed0bc55e8
commit
7b97b7861d
|
|
@ -0,0 +1,45 @@
|
||||||
|
package backend;
|
||||||
|
|
||||||
|
public class Cell {
|
||||||
|
int positionX; // X position
|
||||||
|
int positionY; // Y position
|
||||||
|
int state; // Current state of the cell
|
||||||
|
int timeOfLifeSinceCut = 0; // Time since the cell was last alive
|
||||||
|
int GROWING_TIME = 50; // Time it takes to grow back
|
||||||
|
|
||||||
|
// Constructor to initialize the cell
|
||||||
|
public Cell(int x, int y, int lifeState) {
|
||||||
|
positionX = x;
|
||||||
|
positionY = y;
|
||||||
|
state = lifeState;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the cell's state
|
||||||
|
public void toggleCell() {
|
||||||
|
state++;
|
||||||
|
if (state > 5) {
|
||||||
|
state = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the cell's state
|
||||||
|
public void setState(int lifeState) {
|
||||||
|
state = lifeState;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the cell's state based on time
|
||||||
|
public void updateCell() {
|
||||||
|
if (state == 0) { // If the cell is dead
|
||||||
|
timeOfLifeSinceCut++;
|
||||||
|
if (timeOfLifeSinceCut > GROWING_TIME) { // If enough time has passed
|
||||||
|
timeOfLifeSinceCut = 0;
|
||||||
|
state = 1; // Grow the cell back
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the cell's state
|
||||||
|
public int getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
package backend;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class GameScreen {
|
||||||
|
|
||||||
|
private Grid grid; // The grid representing the game world
|
||||||
|
private int width; // Width of the game screen
|
||||||
|
private int height; // Height of the game screen
|
||||||
|
private boolean loopingBorder; // Flag to determine if borders are looping
|
||||||
|
private ArrayList<ArrayList<Integer>> rule; // Rules for cell evolution
|
||||||
|
|
||||||
|
// Constructor to initialize the game screen with a given size and rules
|
||||||
|
public GameScreen(int sizeX, int sizeY, ArrayList<ArrayList<Integer>> _rule) {
|
||||||
|
width = sizeX;
|
||||||
|
height = sizeY;
|
||||||
|
rule = _rule;
|
||||||
|
grid = new Grid(sizeX, sizeY); // Initialize the grid with the given size
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to update the state of a specific cell
|
||||||
|
public void updateCell(int x, int y) {
|
||||||
|
grid.getCell(x, y).updateCell(); // Update the cell at (x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to check the number of neighbors of a cell that are in a specific state
|
||||||
|
private int checkNeighbors(int x, int y, int state) {
|
||||||
|
int numberNeighbors = 0; // Counter for neighbors
|
||||||
|
int width = getWidth(); // Get the width of the grid
|
||||||
|
int height = getHeight(); // Get the height of the grid
|
||||||
|
|
||||||
|
// Iterate over the 3x3 neighborhood around the cell at (x, y)
|
||||||
|
for (int i = -1; i <= 1; i++) {
|
||||||
|
for (int j = -1; j <= 1; j++) {
|
||||||
|
if (i == 0 && j == 0) continue; // Skip the cell itself
|
||||||
|
|
||||||
|
int NeighborX = x + i; // Calculate the x coordinate of the neighbor
|
||||||
|
int NeighborY = y + j; // Calculate the y coordinate of the neighbor
|
||||||
|
|
||||||
|
// Handle looping borders if enabled
|
||||||
|
if (loopingBorder) {
|
||||||
|
NeighborX = (NeighborX + width) % width;
|
||||||
|
NeighborY = (NeighborY + height) % height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the neighbor cell is within valid bounds
|
||||||
|
if (isValidCell(NeighborX, NeighborY, width, height)) {
|
||||||
|
// Increment the neighbor counter if the neighbor cell is in the desired state
|
||||||
|
if (grid.getCell(NeighborX, NeighborY).getState() == state) {
|
||||||
|
numberNeighbors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(numberNeighbors); // Print the number of neighbors (for debugging)
|
||||||
|
return numberNeighbors; // Return the number of neighbors
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to check if a cell coordinate is within the grid bounds
|
||||||
|
private boolean isValidCell(int x, int y, int width, int height) {
|
||||||
|
return x >= 0 && x < width && y >= 0 && y < height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to advance the game by one step
|
||||||
|
public void makeStep() {
|
||||||
|
int width = getWidth(); // Get the width of the grid
|
||||||
|
int height = getHeight(); // Get the height of the grid
|
||||||
|
Grid nextGrid = new Grid(width, height); // Create a new grid for the next state
|
||||||
|
|
||||||
|
// Iterate over all cells in the grid
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
int presentState = getCell(x, y); // Get the current state of the cell
|
||||||
|
int futureState = determineFutureState(x, y, presentState); // Determine the future state of the cell
|
||||||
|
nextGrid.setCell(x, y, futureState); // Set the future state in the new grid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grid = nextGrid; // Update the grid to the new state
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to determine the future state of a cell based on its current state
|
||||||
|
private int determineFutureState(int x, int y, int presentState) {
|
||||||
|
if (presentState == 0) {
|
||||||
|
return determineStateForDeadCell(x, y); // Determine state for a dead cell
|
||||||
|
} else {
|
||||||
|
return determineStateForLiveCell(x, y, presentState); // Determine state for a live cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to determine the future state of a dead cell based on neighbor states
|
||||||
|
private int determineStateForDeadCell(int x, int y) {
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
if (rule.get(0).contains(checkNeighbors(x, y, i))) {
|
||||||
|
return i; // Return the state if the rule matches the neighbor count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0; // Remain dead if no rules match
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to determine the future state of a live cell based on neighbor states
|
||||||
|
private int determineStateForLiveCell(int x, int y, int presentState) {
|
||||||
|
if (rule.get(1).contains(checkNeighbors(x, y, presentState))) {
|
||||||
|
return presentState; // Remain in the same state if the rule matches the neighbor count
|
||||||
|
}
|
||||||
|
return 0; // Die if no rules match
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to randomly generate the initial state of the grid
|
||||||
|
public void generateRandom(float chanceOfLife) {
|
||||||
|
int width = getWidth(); // Get the width of the grid
|
||||||
|
int height = getHeight(); // Get the height of the grid
|
||||||
|
Random random = new Random(); // Create a random number generator
|
||||||
|
|
||||||
|
// Iterate over all cells in the grid
|
||||||
|
IntStream.range(0, height).forEach(y ->
|
||||||
|
IntStream.range(0, width).forEach(x ->
|
||||||
|
// Set the cell state based on the chance of life
|
||||||
|
setCell(x, y, random.nextFloat() < chanceOfLife ? 1 : 0)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to toggle the state of a cell when clicked
|
||||||
|
public void clickCell(int x, int y) {
|
||||||
|
grid.getCell(x, y).toggleCell(); // Toggle the cell state at (x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to set the state of a specific cell
|
||||||
|
public void setCell(int x, int y, int val) {
|
||||||
|
grid.getCell(x, y).setState(val); // Set the state of the cell at (x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to set the rules for cell evolution
|
||||||
|
public void setRules(ArrayList<ArrayList<Integer>> _rule) {
|
||||||
|
rule = _rule; // Update the rules
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to enable or disable looping borders
|
||||||
|
public void setLoopingBorders(boolean loop) {
|
||||||
|
loopingBorder = loop; // Set the looping border flag
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to get the state of a specific cell
|
||||||
|
public int getCell(int x, int y) {
|
||||||
|
return grid.getCell(x, y).getState(); // Return the state of the cell at (x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to get the width of the grid
|
||||||
|
public int getWidth() {
|
||||||
|
return grid.getWidth(); // Return the width of the grid
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to get the height of the grid
|
||||||
|
public int getHeight() {
|
||||||
|
return grid.getHeight(); // Return the height of the grid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package backend;
|
||||||
|
|
||||||
|
public class Grid {
|
||||||
|
private Cell[][] playTable; // The grid of cells
|
||||||
|
private int width; // Grid width
|
||||||
|
private int height; // Grid height
|
||||||
|
|
||||||
|
// Constructor to initialize the grid
|
||||||
|
public Grid(int X, int Y) {
|
||||||
|
width = X;
|
||||||
|
height = Y;
|
||||||
|
playTable = new Cell[width][height];
|
||||||
|
|
||||||
|
// Initialize all cells in the grid
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
playTable[x][y] = new Cell(x, y, 0); // Set initial state to 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a cell from the grid
|
||||||
|
public Cell getCell(int x, int y) {
|
||||||
|
return playTable[x][y];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the state of a specific cell
|
||||||
|
public void setCell(int x, int y, int value) {
|
||||||
|
playTable[x][y].setState(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the grid width
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the grid height
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,9 +10,14 @@ import java.util.Random;
|
||||||
// for example wolves that eat Sheep
|
// for example wolves that eat Sheep
|
||||||
public class Sheep extends Agent {
|
public class Sheep extends Agent {
|
||||||
|
|
||||||
int hunger;
|
int hunger; // Hunger level
|
||||||
Random rand;
|
Random rand; // Random number generator
|
||||||
|
int height; // World height
|
||||||
|
int width; // World width
|
||||||
|
private final int REPRODUCTION_RADIUS = 1; // Radius within which sheep can reproduce
|
||||||
|
private final double REPRODUCTION_PROBABILITY = 0.05; // Probability of reproduction per turn
|
||||||
|
|
||||||
|
// Constructor to initialize the sheep
|
||||||
Sheep(int x,int y){
|
Sheep(int x,int y){
|
||||||
//first we call the constructor of the superClass(Animal)
|
//first we call the constructor of the superClass(Animal)
|
||||||
//with the values we want.
|
//with the values we want.
|
||||||
|
|
@ -31,29 +36,57 @@ public class Sheep extends Agent {
|
||||||
*/
|
*/
|
||||||
public boolean liveTurn(ArrayList<Agent> neighbors, Simulator world) {
|
public boolean liveTurn(ArrayList<Agent> neighbors, Simulator world) {
|
||||||
if(world.getCell(x, y)==1) {
|
if(world.getCell(x, y)==1) {
|
||||||
world.setCell(x, y, 0);
|
world.setCell(x, y, 0);// Eat if on food
|
||||||
} else {
|
} else {
|
||||||
hunger++;
|
hunger++;// Increase hunger if no food
|
||||||
|
}
|
||||||
|
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();
|
this.moveRandom();
|
||||||
return hunger>10;
|
return hunger>10;// Return true if the sheep is hungry over the limit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Move randomly
|
||||||
private void moveRandom() {
|
private void moveRandom() {
|
||||||
int direction = rand.nextInt(4);
|
int direction = rand.nextInt(4);
|
||||||
|
int nx = x;
|
||||||
|
int ny = y;
|
||||||
|
|
||||||
if(direction == 0) {
|
if(direction == 0) {
|
||||||
x+=1;
|
nx+=1;
|
||||||
}
|
}
|
||||||
if(direction == 1) {
|
if(direction == 1) {
|
||||||
y+=1;
|
ny+=1;
|
||||||
}
|
}
|
||||||
if(direction == 2) {
|
if(direction == 2) {
|
||||||
x-=1;
|
nx-=1;
|
||||||
}
|
}
|
||||||
if(direction == 3) {
|
if(direction == 3) {
|
||||||
y-=1;
|
ny-=1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package backend;
|
package backend;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import windowInterface.MyInterface;
|
import windowInterface.MyInterface;
|
||||||
|
|
||||||
|
|
@ -13,17 +14,19 @@ public class Simulator extends Thread {
|
||||||
//Conway Radius : 1
|
//Conway Radius : 1
|
||||||
private final int LIFE_AREA_RADIUS = 1;
|
private final int LIFE_AREA_RADIUS = 1;
|
||||||
//Animal Neighborhood Radius : 5
|
//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> surviveValues;
|
||||||
private ArrayList<Integer> fieldBirthValues;
|
private ArrayList<Integer> birthValues;
|
||||||
|
|
||||||
private ArrayList<Agent> agents;
|
private ArrayList<Agent> agents;
|
||||||
|
ArrayList<ArrayList<Integer>> rule = new ArrayList<>();
|
||||||
|
|
||||||
private boolean stopFlag;
|
private boolean stopFlag;
|
||||||
private boolean pauseFlag;
|
private boolean pauseFlag;
|
||||||
private boolean loopingBorder;
|
private boolean loopingBorder;
|
||||||
private boolean clickActionFlag;
|
private boolean clickActionFlag;
|
||||||
private int loopDelay = 150;
|
private int loopDelay = 150;
|
||||||
|
private GameScreen gameScreen;
|
||||||
|
|
||||||
//TODO : add missing attribute(s)
|
//TODO : add missing attribute(s)
|
||||||
|
|
||||||
|
|
@ -35,28 +38,28 @@ public class Simulator extends Thread {
|
||||||
clickActionFlag=false;
|
clickActionFlag=false;
|
||||||
|
|
||||||
agents = new ArrayList<Agent>();
|
agents = new ArrayList<Agent>();
|
||||||
fieldBirthValues = new ArrayList<Integer>();
|
birthValues = new ArrayList<Integer>();
|
||||||
fieldSurviveValues = new ArrayList<Integer>();
|
surviveValues = new ArrayList<Integer>();
|
||||||
|
|
||||||
//TODO : add missing attribute initialization
|
|
||||||
|
|
||||||
|
|
||||||
|
// Normal Game of Life rules
|
||||||
|
birthValues.add(3); // Birth condition
|
||||||
|
surviveValues.add(2); // Survival condition
|
||||||
|
surviveValues.add(3); // Survival condition
|
||||||
|
|
||||||
//Default rule : Survive always, birth never
|
rule.add(birthValues);
|
||||||
for(int i =0; i<9; i++) {
|
rule.add(surviveValues);
|
||||||
fieldSurviveValues.add(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
gameScreen = new GameScreen(COL_NUM, LINE_NUM, rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
//TODO : replace with proper return
|
return gameScreen.getWidth();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHeight() {
|
public int getHeight() {
|
||||||
//TODO : replace with proper return
|
//TODO : replace with proper return
|
||||||
return 0;
|
return gameScreen.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Should probably stay as is
|
//Should probably stay as is
|
||||||
|
|
@ -91,16 +94,14 @@ public class Simulator extends Thread {
|
||||||
// only modify if sure of what you do
|
// only modify if sure of what you do
|
||||||
// to modify agent behavior, see liveTurn method
|
// to modify agent behavior, see liveTurn method
|
||||||
// in agent classes
|
// in agent classes
|
||||||
for(Agent agent : agents) {
|
//Modified because of cross-modifications to the arraylist and java doesn't like that much
|
||||||
ArrayList<Agent> neighbors =
|
for (int i = 0; i < agents.size(); i++) {
|
||||||
this.getNeighboringAnimals(
|
Agent agent = agents.get(i);
|
||||||
agent.getX(),
|
ArrayList<Agent> neighbors = this.getNeighboringAnimals(agent.getX(), agent.getY(), ANIMAL_AREA_RADIUS);
|
||||||
agent.getY(),
|
|
||||||
ANIMAL_AREA_RADIUS);
|
if (agent.liveTurn(neighbors, this)) {
|
||||||
if(!agent.liveTurn(
|
agents.remove(i);
|
||||||
neighbors,
|
i--; // Adjust the index to account for the removed element
|
||||||
this)) {
|
|
||||||
agents.remove(agent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//then evolution of the field
|
//then evolution of the field
|
||||||
|
|
@ -119,10 +120,9 @@ public class Simulator extends Thread {
|
||||||
* and the count is in the birth list,
|
* and the count is in the birth list,
|
||||||
* then the cell becomes alive
|
* then the cell becomes alive
|
||||||
*/
|
*/
|
||||||
|
if (!clickActionFlag)
|
||||||
|
gameScreen.makeStep();
|
||||||
|
else updateCells();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -136,35 +136,99 @@ public class Simulator extends Thread {
|
||||||
* method called when clicking pause button
|
* method called when clicking pause button
|
||||||
*/
|
*/
|
||||||
public void togglePause() {
|
public void togglePause() {
|
||||||
// TODO : actually toggle the corresponding flag
|
pauseFlag = !pauseFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* method called when clicking on a cell in the interface
|
* method called when clicking on a cell in the interface
|
||||||
*/
|
*/
|
||||||
public void clickCell(int x, int y) {
|
public void clickCell(int x, int y) {
|
||||||
//TODO : complete method
|
if (clickActionFlag) {
|
||||||
|
setAgent(x, y);
|
||||||
|
} else {
|
||||||
|
gameScreen.clickCell(x, y);;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAgent(int x, int y) {
|
||||||
|
int cellValue = getCell(x, y);
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellValue == 0 && agentType == null) {
|
||||||
|
setCell(x, y, 1);
|
||||||
|
} else if (cellValue == 1) {
|
||||||
|
agents.add(new Sheep(x, y));
|
||||||
|
setCell(x, y, 0);
|
||||||
|
} else if ("Sheep".equals(agentType)) {
|
||||||
|
agents.remove(indexOfAgent);
|
||||||
|
agents.add(new Wolf(x, y));
|
||||||
|
} else if ("Wolf".equals(agentType)) {
|
||||||
|
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
|
* get cell value in simulated gameScreen
|
||||||
* @param x coordinate of cell
|
* @param x coordinate of cell
|
||||||
* @param y coordinate of cell
|
* @param y coordinate of cell
|
||||||
* @return value of cell
|
* @return value of cell
|
||||||
*/
|
*/
|
||||||
public int getCell(int x, int y) {
|
public int getCell(int x, int y) {
|
||||||
//TODO : complete method with proper return
|
return gameScreen.getCell(x, y);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateCells() {
|
||||||
|
for (int y = 0; y < getHeight(); y++) {
|
||||||
|
for (int x = 0; x < getWidth(); x++) {
|
||||||
|
gameScreen.updateCell(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return list of Animals in simulated world
|
* @return list of Animals in simulated gameScreen
|
||||||
*/
|
*/
|
||||||
public ArrayList<Agent> getAnimals(){
|
public ArrayList<Agent> getAnimals(){
|
||||||
return agents;
|
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
|
* selects Animals in a circular area of simulated gameScreen
|
||||||
* @param x center
|
* @param x center
|
||||||
* @param y center
|
* @param y center
|
||||||
* @param radius
|
* @param radius
|
||||||
|
|
@ -188,21 +252,35 @@ public class Simulator extends Thread {
|
||||||
* @param val to set in cell
|
* @param val to set in cell
|
||||||
*/
|
*/
|
||||||
public void setCell(int x, int y, int val) {
|
public void setCell(int x, int y, int val) {
|
||||||
//TODO : complete method
|
gameScreen.setCell(x, y, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return lines of file representing
|
* @return lines of file representing
|
||||||
* the simulated world in its present state
|
* the simulated gameScreen in its present state
|
||||||
*/
|
*/
|
||||||
public ArrayList<String> getSaveState() {
|
public ArrayList<String> getSaveState() {
|
||||||
//TODO : complete method with proper return
|
ArrayList<String> lines = new ArrayList<>();
|
||||||
return null;
|
|
||||||
|
// Iterate over the gameScreen 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;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param lines of file representing saved world state
|
* @param lines of file representing saved gameScreen state
|
||||||
*/
|
*/
|
||||||
public void loadSaveState(ArrayList<String> lines) {
|
public void loadSaveState(ArrayList<String> lines) {
|
||||||
/*
|
/*
|
||||||
|
|
@ -220,7 +298,7 @@ public class Simulator extends Thread {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* now we fill in the world
|
* now we fill in the gameScreen
|
||||||
* with the content of the file
|
* with the content of the file
|
||||||
*/
|
*/
|
||||||
for(int y =0; y<lines.size();y++) {
|
for(int y =0; y<lines.size();y++) {
|
||||||
|
|
@ -236,51 +314,45 @@ public class Simulator extends Thread {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called by button, with slider providing the argument
|
* called by button, with slider providing the argument
|
||||||
* makes a new world state with random cell states
|
* makes a new gameScreen state with random cell states
|
||||||
* @param chanceOfLife the chance for each cell
|
* @param chanceOfLife the chance for each cell
|
||||||
* to be alive in new state
|
* to be alive in new state
|
||||||
*/
|
*/
|
||||||
public void generateRandom(float chanceOfLife) {
|
public void generateRandom(float chanceOfLife) {
|
||||||
//TODO : complete method
|
gameScreen.generateRandom(chanceOfLife);
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLoopingBorder() {
|
public boolean isLoopingBorder() {
|
||||||
//TODO : complete method with proper return
|
return loopingBorder;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleLoopingBorder() {
|
public void toggleLoopingBorder() {
|
||||||
//TODO : complete method
|
loopingBorder = !loopingBorder;
|
||||||
|
gameScreen.setLoopingBorders(loopingBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLoopDelay(int delay) {
|
public void setLoopDelay(int delay) {
|
||||||
//TODO : complete method
|
loopDelay = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleClickAction() {
|
public void toggleClickAction() {
|
||||||
//TODO : complete method
|
clickActionFlag = !clickActionFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* prepare the content of a file saving present ruleSet
|
|
||||||
* as you might want to save a state,
|
|
||||||
* initialy written in this class constructor
|
|
||||||
* as a file for future use
|
|
||||||
* @return File content as an ArrayList of Lines (String)
|
|
||||||
* @see loadRule for inverse process
|
|
||||||
*/
|
|
||||||
public ArrayList<String> getRule() {
|
public ArrayList<String> getRule() {
|
||||||
//TODO : complete method with proper return
|
ArrayList<String> lines = new ArrayList<>();
|
||||||
|
|
||||||
return null;
|
// Add birth conditions
|
||||||
|
for (Integer birthCondition : rule.get(0)) {
|
||||||
|
lines.add(birthCondition.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add survival conditions
|
||||||
|
for (Integer survivalCondition : rule.get(1)) {
|
||||||
|
lines.add(survivalCondition.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadRule(ArrayList<String> lines) {
|
public void loadRule(ArrayList<String> lines) {
|
||||||
|
|
@ -288,8 +360,9 @@ public class Simulator extends Thread {
|
||||||
System.out.println("empty rule file");
|
System.out.println("empty rule file");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//TODO : remove previous rule (=emptying lists)
|
rule.clear();
|
||||||
|
birthValues.clear();
|
||||||
|
surviveValues.clear();
|
||||||
|
|
||||||
String surviveLine = lines.get(0);
|
String surviveLine = lines.get(0);
|
||||||
String birthLine = lines.get(1);
|
String birthLine = lines.get(1);
|
||||||
|
|
@ -297,36 +370,80 @@ public class Simulator extends Thread {
|
||||||
for(int x=0; x<surviveElements.length;x++) {
|
for(int x=0; x<surviveElements.length;x++) {
|
||||||
String elem = surviveElements[x];
|
String elem = surviveElements[x];
|
||||||
int value = Integer.parseInt(elem);
|
int value = Integer.parseInt(elem);
|
||||||
//TODO : add value to possible survive values
|
surviveValues.add(value);
|
||||||
|
|
||||||
}
|
}
|
||||||
String[] birthElements = birthLine.split(";");
|
String[] birthElements = birthLine.split(";");
|
||||||
for(int x=0; x<birthElements.length;x++) {
|
for(int x=0; x<birthElements.length;x++) {
|
||||||
String elem = birthElements[x];
|
String elem = birthElements[x];
|
||||||
int value = Integer.parseInt(elem);
|
int value = Integer.parseInt(elem);
|
||||||
//TODO : add value to possible birth values
|
birthValues.add(value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rule.add(birthValues);
|
||||||
|
rule.add(surviveValues);
|
||||||
|
gameScreen.setRules(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<String> getAgentsSave() {
|
public ArrayList<String> getAgentsSave() {
|
||||||
//TODO : Same idea as the other save method, but for agents
|
ArrayList<String> lines = new ArrayList<>();
|
||||||
return null;
|
|
||||||
|
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) {
|
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
|
* used by label in interface to show the active click action
|
||||||
* @return String representation of click action
|
* @return String representation of click action
|
||||||
*/
|
*/
|
||||||
public String clickActionName() {
|
public String clickActionName() {
|
||||||
// TODO : initially return "sheep" or "cell"
|
return clickActionFlag ? "Agents" : "Cells";
|
||||||
// depending on clickActionFlag
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
package backend;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Wolf extends Agent {
|
||||||
|
|
||||||
|
int hunger;
|
||||||
|
Random rand;
|
||||||
|
private final int REPRODUCTION_RADIUS = 1; // radius max of reproduction
|
||||||
|
private final double REPRODUCTION_PROBABILITY = 0.2; // proba of reproduction
|
||||||
|
|
||||||
|
Wolf(int x, int y) {
|
||||||
|
super(x, y, Color.red);
|
||||||
|
hunger = 0;
|
||||||
|
rand = new Random(); // generate random
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main behavior of the wolf each turn.
|
||||||
|
* @param neighbors List of neighboring agents
|
||||||
|
* @param world The simulation world
|
||||||
|
* @return true if the wolf is starving and should be removed
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean liveTurn(ArrayList<Agent> neighbors, Simulator world) {
|
||||||
|
boolean ateSheep = false;
|
||||||
|
|
||||||
|
// check to see if can eat a sheep
|
||||||
|
for (Agent neighbor : neighbors) {
|
||||||
|
if (neighbor instanceof Sheep) {
|
||||||
|
world.removeAgent(neighbor); // eat the sheep so removes it
|
||||||
|
hunger = 0; // rest hunger to 0
|
||||||
|
ateSheep = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not eating increase hunger
|
||||||
|
if (!ateSheep) {
|
||||||
|
hunger++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for reproduction with neighboring wolves
|
||||||
|
for (Agent neighbor : neighbors) {
|
||||||
|
if (neighbor instanceof Wolf && isInArea(neighbor.getX(), neighbor.getY(), REPRODUCTION_RADIUS)) {
|
||||||
|
if (rand.nextDouble() < REPRODUCTION_PROBABILITY) {
|
||||||
|
reproduce(world); // Reproduce a new wolf
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move randomly
|
||||||
|
moveRandom();
|
||||||
|
|
||||||
|
|
||||||
|
return hunger > 10; //cehck if the wolf is hungry above the limit
|
||||||
|
}
|
||||||
|
|
||||||
|
//reproduction makes a wolve appear on a adjacent cell
|
||||||
|
private void reproduce(Simulator world) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move randomly
|
||||||
|
private void moveRandom() {
|
||||||
|
int direction = rand.nextInt(4);
|
||||||
|
switch (direction) {
|
||||||
|
case 0 : x += 1;
|
||||||
|
case 1 : y += 1;
|
||||||
|
case 2 : x -= 1;
|
||||||
|
case 3 : y -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue