-
Notifications
You must be signed in to change notification settings - Fork 1
/
Map.java
145 lines (135 loc) · 6.05 KB
/
Map.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
/**
* This is a map that conducts the simulation of fungi spreading model.
*/
public class Map {
public Fungus[][] map;
public Climate climate;
private Queue<int[]> spreadable = new LinkedList<>(); //A queue to implement the spreading
public LinkedList<double[]>[] boimeData; //Place to record all the time-serie data
public static Random random = new Random();
/**
* Initialize a map with a preset size.
* @param size the size of the map
* @param climate the climate of the test
*/
@SuppressWarnings("unchecked")
public Map(int size, Climate climate){
map = new Fungus[size][size];
this.climate = climate;
int i = 0;
int numOfFungi = random.nextInt(1) + 10; //Randomly determine how many fungi species(between 1-5) in this experiment
int xAxis, yAxis;
this.boimeData = new LinkedList[numOfFungi];
for(i=0; i < numOfFungi; i++) //Generate different fungi species
{
do{
xAxis = random.nextInt(size); //generate the initial location on x-Axis of a species of fungi(between 0 to size-1)
yAxis = random.nextInt(size); //generate the initial location on y-Axis of a species of fungi(between 0 to size-1)
}while(map[xAxis][yAxis] != null); //check if the location alreay be taken
map[xAxis][yAxis] = new Fungus();//Put in a type of fungi
boimeData[i] = new LinkedList<double[]>();
}
}
/**
* Initialize a map with a preset size with a seed
* @param size the size of the map
* @param climate the climate of the test
* @param randomSeed set a seed for all random in this test
*/
@SuppressWarnings("unchecked")
public Map(int size, Climate climate, long randomSeed){
random = new Random(randomSeed);
map = new Fungus[size][size];
this.climate = climate;
int i = 0;
int numOfFungi = random.nextInt(1) + 20; //Randomly determine how many fungi species(between 1-5) in this experiment
int xAxis, yAxis;
this.boimeData = new LinkedList[numOfFungi];
for(i=0; i < numOfFungi; i++) //Generate different fungi species
{
do{
xAxis = random.nextInt(size); //generate the initial location on x-Axis of a species of fungi(between 0 to size-1)
yAxis = random.nextInt(size); //generate the initial location on y-Axis of a species of fungi(between 0 to size-1)
}while(map[xAxis][yAxis] != null); //check if the location alreay be taken
map[xAxis][yAxis] = new Fungus();//Put in a type of fungi
boimeData[i] = new LinkedList<double[]>();
}
}
/**
* Spread and decomposition all the fungus biomes in this map.
*/
public void spread(){
double[] climate = this.climate.getClimate();
for (int i=0; i < Fungus.fungiCount; i++){
double[] pair = {0., 0.}; //Start a new time point
boimeData[i].offer(pair);
}
for (int i=0; i < map.length; i++){
for (int j=0; j < map[0].length; j++){
if(map[i][j] == null) continue;
map[i][j].grow(climate); // gain spread progress and decompositing
if(map[i][j].spreadProgress >= 1){ // if spreadable
int[] pos = {i, j};
spreadable.offer(pos); // Record the spreadable cells position
}
double[] pair = boimeData[map[i][j].fungusId].peekLast(); //Get the newly insert data
pair[0] += 1;
pair[1] += map[i][j].decomp;
}
}
while(!spreadable.isEmpty()){ //Spread all the cells which is spreadable, the queue may extend itself while spreading
int[] pos = spreadable.poll();
spreadCell(pos[0], pos[1]);
}
}
/**
* Spread a cell if possible.
* It may offer several new elements into the spreadable queue if the new cell is still spreadable (process > 1).
* @param i cell coordinate i
* @param j cell coordinate j
*/
private void spreadCell(int i, int j){
double savedProcess = (int)map[i][j].spreadProgress - 1;
map[i][j].spreadProgress = 0; map[i][j].spreaded = true; // Useful for optimization as no species can be removed or die out
//Test 6 spreading direction
if(i != 0 && this.map[i-1][j] == null){
this.fungiClone(i, j, i-1, j, savedProcess);
}
if(j != 0 && this.map[i][j-1] == null){
this.fungiClone(i, j, i, j-1, savedProcess);
}
if(i != 0 && j != 0 && this.map[i-1][j-1] == null){
this.fungiClone(i, j, i-1, j-1, savedProcess);
}
if(i != map.length-1 && this.map[i+1][j] == null){
this.fungiClone(i, j, i+1, j, savedProcess);
}
if(j != map[0].length-1 && this.map[i][j+1] == null){
this.fungiClone(i, j, i, j+1, savedProcess);
}
if(i != map.length-1 && j != map[0].length-1 && this.map[i+1][j+1] == null){
this.fungiClone(i, j, i+1, j+1, savedProcess);
}
}
/**
* A method called in spreadCell.
* Clone a fungi into another place, saved process can be introduced.
* It may offer several new elements into the spreadable queue if the new cell is still spreadable (process > 1).
* @param i coordinate i being cloned
* @param j coordinate j being cloned
* @param newI coordinate i to be cloned into
* @param newJ coordinate j to be cloned into
* @param savedProcess a saved
*/
private void fungiClone(int i, int j, int newI, int newJ, double savedProcess){
this.map[newI][newJ] = (Fungus)this.map[i][j].clone();
this.map[newI][newJ].spreadProgress = savedProcess;
if(savedProcess >= 1){ // If the cell is still spreadable
int[] pos = {newI, newJ};
spreadable.offer(pos); // Add new spreadable into the queue
}
}
}