Commit | Line | Data |
---|---|---|
4861d6c4 LW |
1 | class L8onLife extends SCPattern { |
2 | // Controls the rate of life algorithm ticks, in milliseconds | |
7782bf8e | 3 | private BasicParameter rateParameter = new BasicParameter("DELAY", 112.5, 0.0, 1000.0); |
4861d6c4 LW |
4 | // Controls if the cubes should be randomized even if something changes. Set above 0.5 to randomize cube aliveness. |
5 | private BasicParameter randomParameter = new BasicParameter("RAND", 0.0); | |
6 | // Controls the brightness of dead cubes. | |
7 | private BasicParameter deadParameter = new BasicParameter("DEAD", 25.0, 0.0, 100.0); | |
8 | // Controls the saturation. | |
9 | private BasicParameter saturationParameter = new BasicParameter("SAT", 90.0, 0.0, 100.0); | |
10 | ||
64ed63c7 LW |
11 | public final double MIN_ALIVE_PROBABILITY = 0.2; |
12 | public final double MAX_ALIVE_PROBABILITY = 0.9; | |
4861d6c4 | 13 | |
64ed63c7 | 14 | private final SinLFO xPos = new SinLFO(0, model.xMax, 4500); |
2815b690 LW |
15 | private final SinLFO zPos = new SinLFO(0, model.zMax, 2500); |
16 | ||
17 | class CubeState { | |
18 | // Index of cube in glucose.model.cubes | |
19 | public Integer index; | |
20 | // Boolean which describes if cube is alive. | |
21 | public boolean alive; | |
22 | // List of this cubes neighbors | |
23 | public List<Integer> neighbors; | |
24 | ||
25 | public CubeState(Integer index, boolean alive, List<Integer> neighbors) { | |
26 | this.index = index; | |
27 | this.alive = alive; | |
28 | this.neighbors = neighbors; | |
29 | } | |
30 | } | |
31 | ||
4861d6c4 LW |
32 | // Contains the state of all cubes by index. |
33 | private List<CubeState> cube_states; | |
34 | // Contains the amount of time since the last cycle of life. | |
35 | private int time_since_last_run; | |
36 | // Boolean describing if life changes were made during the current run. | |
37 | private boolean any_changes_this_run; | |
64ed63c7 LW |
38 | // Hold the new lives |
39 | private List<Boolean> new_lives; | |
f7f0bfe5 | 40 | |
4861d6c4 | 41 | public L8onLife(GLucose glucose) { |
f7f0bfe5 | 42 | super(glucose); |
4861d6c4 LW |
43 | |
44 | //Print debug info about the cubes. | |
45 | //outputCubeInfo(); | |
46 | ||
f7f0bfe5 LW |
47 | initCubeStates(); |
48 | time_since_last_run = 0; | |
49 | any_changes_this_run = false; | |
64ed63c7 | 50 | new_lives = new ArrayList<Boolean>(); |
4861d6c4 LW |
51 | |
52 | addParameter(rateParameter); | |
53 | addParameter(randomParameter); | |
54 | addParameter(deadParameter); | |
61f677b8 | 55 | addParameter(saturationParameter); |
f7f0bfe5 | 56 | addModulator(xPos).trigger(); |
2815b690 | 57 | addModulator(zPos).trigger(); |
f7f0bfe5 LW |
58 | } |
59 | ||
60 | public void run(double deltaMs) { | |
61 | Integer i = 0; | |
4861d6c4 | 62 | CubeState cube_state; |
f7f0bfe5 | 63 | |
4861d6c4 | 64 | any_changes_this_run = false; |
64ed63c7 | 65 | new_lives.clear(); |
f7f0bfe5 LW |
66 | time_since_last_run += deltaMs; |
67 | ||
4861d6c4 | 68 | for (Cube cube : model.cubes) { |
2815b690 | 69 | cube_state = this.cube_states.get(i); |
64ed63c7 | 70 | |
4861d6c4 | 71 | if(shouldLightCube(cube_state)) { |
f7f0bfe5 LW |
72 | lightLiveCube(cube); |
73 | } else { | |
74 | lightDeadCube(cube); | |
4861d6c4 LW |
75 | } |
76 | ||
77 | i++; | |
f7f0bfe5 LW |
78 | } |
79 | ||
4861d6c4 LW |
80 | boolean should_randomize_anyway = (randomParameter.getValuef() > 0.5); |
81 | if(should_randomize_anyway || !any_changes_this_run) { | |
f7f0bfe5 | 82 | randomizeCubeStates(); |
64ed63c7 LW |
83 | } else { |
84 | applyNewLives(); | |
f7f0bfe5 LW |
85 | } |
86 | ||
4861d6c4 LW |
87 | if(time_since_last_run >= rateParameter.getValuef()) { |
88 | time_since_last_run = 0; | |
89 | } | |
f7f0bfe5 LW |
90 | } |
91 | ||
4861d6c4 LW |
92 | public void lightLiveCube(Cube cube) { |
93 | for (LXPoint p : cube.points) { | |
2815b690 | 94 | float hv = max(0, lx.getBaseHuef() - abs(p.z - zPos.getValuef())); |
4861d6c4 LW |
95 | colors[p.index] = lx.hsb( |
96 | hv, | |
97 | saturationParameter.getValuef(), | |
98 | 75 | |
99 | ); | |
100 | } | |
101 | } | |
102 | ||
103 | public void lightDeadCube(Cube cube) { | |
104 | for (LXPoint p : cube.points) { | |
105 | float hv = max(0, lx.getBaseHuef() - abs(p.x - xPos.getValuef())); | |
106 | double dead_bright = deadParameter.getValuef() * Math.random(); | |
107 | ||
108 | colors[p.index] = lx.hsb( | |
109 | hv, | |
110 | saturationParameter.getValuef(), | |
111 | dead_bright | |
112 | ); | |
113 | } | |
114 | } | |
115 | ||
f7f0bfe5 LW |
116 | public void outputCubeInfo() { |
117 | int i = 0; | |
118 | for (Cube c : model.cubes) { | |
119 | print("Cube " + i + ": " + c.x + "," + c.y + "," + c.z + "\n"); | |
120 | ++i; | |
121 | } | |
122 | print("Edgeheight: " + Cube.EDGE_HEIGHT + "\n"); | |
123 | print("Edgewidth: " + Cube.EDGE_WIDTH + "\n"); | |
124 | print("Channelwidth: " + Cube.CHANNEL_WIDTH + "\n"); | |
125 | } | |
126 | ||
127 | private void initCubeStates() { | |
128 | List<Integer> neighbors; | |
129 | boolean alive = false; | |
130 | CubeState cube_state; | |
2815b690 | 131 | this.cube_states = new ArrayList<CubeState>(); |
f7f0bfe5 LW |
132 | Integer i = 0; |
133 | ||
134 | for (Cube c : model.cubes) { | |
135 | neighbors = findCubeNeighbors(c, i); | |
1c56d2f1 | 136 | alive = true; |
f7f0bfe5 LW |
137 | cube_state = new CubeState(i, alive, neighbors); |
138 | this.cube_states.add(cube_state); | |
139 | ++i; | |
140 | } | |
141 | } | |
142 | ||
4861d6c4 LW |
143 | private void randomizeCubeStates() { |
144 | double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY); | |
145 | double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random()); | |
1c56d2f1 | 146 | |
4861d6c4 LW |
147 | //print("Randomizing cubes! p = " + prob + "\n"); |
148 | ||
149 | for (CubeState cube_state: this.cube_states) { | |
150 | cube_state.alive = (Math.random() <= prob); | |
f7f0bfe5 LW |
151 | } |
152 | } | |
153 | ||
154 | public List<Integer> findCubeNeighbors(Cube cube, Integer index) { | |
155 | List<Integer> neighbors = new LinkedList<Integer>(); | |
156 | Integer i = 0; | |
157 | ||
158 | for (Cube c : model.cubes) { | |
4861d6c4 LW |
159 | if(index != i) { |
160 | if(abs(c.x - cube.x) < (Cube.EDGE_WIDTH * 2) && abs(c.y - cube.y) < (Cube.EDGE_HEIGHT * 2)) { | |
161 | //print("Cube " + i + " is a neighbor of " + index + "\n"); | |
162 | neighbors.add(i); | |
163 | } | |
f7f0bfe5 LW |
164 | } |
165 | ||
166 | i++; | |
167 | } | |
168 | ||
169 | return neighbors; | |
170 | } | |
171 | ||
4861d6c4 LW |
172 | public boolean shouldLightCube(CubeState cube_state) { |
173 | // Respect rate parameter. | |
174 | if(time_since_last_run < rateParameter.getValuef()) { | |
175 | any_changes_this_run = true; | |
64ed63c7 | 176 | return cube_state.alive; |
4861d6c4 | 177 | } else { |
64ed63c7 LW |
178 | boolean new_life = cycleOfLife(cube_state); |
179 | new_lives.add(new_life); | |
180 | return new_life; | |
181 | } | |
182 | } | |
183 | ||
184 | public void applyNewLives() { | |
185 | int index = 0; | |
186 | for(boolean liveliness: new_lives) { | |
187 | CubeState cube_state = this.cube_states.get(index); | |
188 | cube_state.alive = new_lives.get(index); | |
189 | index++; | |
190 | } | |
4861d6c4 LW |
191 | } |
192 | ||
193 | public boolean cycleOfLife(CubeState cube_state) { | |
194 | Integer index = cube_state.index; | |
195 | Integer alive_neighbor_count = countLiveNeighbors(cube_state); | |
f7f0bfe5 | 196 | boolean before_alive = cube_state.alive; |
64ed63c7 | 197 | boolean after_alive = before_alive; |
4861d6c4 | 198 | |
f7f0bfe5 LW |
199 | if(cube_state.alive) { |
200 | if(alive_neighbor_count < 2 || alive_neighbor_count > 3) { | |
64ed63c7 | 201 | after_alive = false; |
f7f0bfe5 | 202 | } else { |
64ed63c7 | 203 | after_alive = true; |
f7f0bfe5 LW |
204 | } |
205 | ||
206 | } else { | |
2815b690 | 207 | if(alive_neighbor_count == 2) { |
64ed63c7 | 208 | after_alive = true; |
f7f0bfe5 | 209 | } else { |
64ed63c7 | 210 | after_alive = false; |
f7f0bfe5 | 211 | } |
64ed63c7 LW |
212 | } |
213 | ||
214 | if(before_alive != after_alive) { | |
4861d6c4 | 215 | any_changes_this_run = true; |
64ed63c7 LW |
216 | } |
217 | ||
218 | return after_alive; | |
f7f0bfe5 LW |
219 | } |
220 | ||
221 | public Integer countLiveNeighbors(CubeState cube_state) { | |
222 | Integer count = 0; | |
223 | CubeState neighbor_cube_state; | |
224 | ||
225 | for(Integer neighbor_index: cube_state.neighbors) { | |
226 | neighbor_cube_state = this.cube_states.get(neighbor_index); | |
227 | if(neighbor_cube_state.alive) { | |
228 | count++; | |
229 | } | |
230 | } | |
231 | ||
232 | return count; | |
4861d6c4 | 233 | } |
f7f0bfe5 | 234 | } |
2815b690 LW |
235 | |
236 | class L8onAutomata extends SCPattern { | |
237 | // Controls if the points should be randomized even if something changes. Set above 0.5 to randomize cube aliveness. | |
238 | private BasicParameter randomParameter = new BasicParameter("RAND", 0.0); | |
239 | // Controls the rate of life algorithm ticks, in milliseconds | |
7782bf8e | 240 | private BasicParameter rateParameter = new BasicParameter("DELAY", 75.0, 0.0, 1000.0); |
2815b690 LW |
241 | |
242 | private final SinLFO zPos = new SinLFO(0, model.zMax, 2500); | |
243 | ||
244 | public final double MIN_ALIVE_PROBABILITY = 0.2; | |
245 | public final double MAX_ALIVE_PROBABILITY = 0.9; | |
246 | ||
247 | class PointState { | |
248 | // Index of cube in glucose.model.cubes | |
249 | public Integer index; | |
250 | // Boolean which describes if cube is alive. | |
251 | public boolean alive; | |
252 | ||
253 | public PointState(Integer index, boolean alive) { | |
254 | this.index = index; | |
255 | this.alive = alive; | |
256 | } | |
257 | } | |
258 | ||
259 | // Contains the state of all cubes by index. | |
260 | private List<PointState> point_states; | |
261 | // Contains the amount of time since the last cycle of life. | |
262 | private int time_since_last_run; | |
263 | // Boolean describing if life changes were made during the current run. | |
264 | private boolean any_changes_this_run; | |
265 | // Hold the new lives | |
266 | private List<Boolean> new_states; | |
267 | ||
268 | public L8onAutomata(GLucose glucose) { | |
269 | super(glucose); | |
270 | ||
271 | //Print debug info about the cubes. | |
272 | //outputCubeInfo(); | |
273 | ||
274 | initPointStates(); | |
275 | randomizePointStates(); | |
276 | time_since_last_run = 0; | |
277 | any_changes_this_run = false; | |
278 | new_states = new ArrayList<Boolean>(); | |
279 | ||
280 | addParameter(randomParameter); | |
281 | addParameter(rateParameter); | |
282 | addModulator(zPos).trigger(); | |
283 | } | |
284 | ||
285 | private void initPointStates() { | |
286 | boolean alive = false; | |
287 | PointState point_state; | |
288 | this.point_states = new ArrayList<PointState>(); | |
289 | Integer i = 0; | |
290 | ||
291 | for (LXPoint p : model.points) { | |
292 | alive = true; | |
293 | point_state = new PointState(i, alive); | |
294 | this.point_states.add(point_state); | |
295 | ++i; | |
296 | } | |
297 | } | |
298 | ||
299 | public void run(double deltaMs) { | |
300 | Integer i = 0; | |
301 | PointState point_state; | |
302 | ||
303 | any_changes_this_run = false; | |
304 | new_states.clear(); | |
305 | time_since_last_run += deltaMs; | |
306 | ||
307 | for (LXPoint p : model.points) { | |
308 | point_state = this.point_states.get(i); | |
309 | ||
310 | if(shouldLightPoint(point_state)) { | |
311 | lightLivePoint(p); | |
312 | } else { | |
313 | lightDeadPoint(p); | |
314 | } | |
315 | ||
316 | i++; | |
317 | } | |
318 | ||
319 | boolean should_randomize_anyway = (randomParameter.getValuef() > 0.5); | |
320 | if(should_randomize_anyway || !any_changes_this_run) { | |
321 | randomizePointStates(); | |
322 | } else { | |
323 | applyNewStates(); | |
324 | } | |
325 | ||
326 | if(time_since_last_run >= rateParameter.getValuef()) { | |
327 | time_since_last_run = 0; | |
328 | } | |
329 | } | |
330 | ||
331 | public void lightLivePoint(LXPoint p) { | |
332 | float hv = max(0, lx.getBaseHuef() - abs(p.z - zPos.getValuef())); | |
333 | colors[p.index] = lx.hsb( | |
334 | hv, | |
335 | 90, | |
336 | 80 | |
337 | ); | |
338 | } | |
339 | ||
340 | public void lightDeadPoint(LXPoint p) { | |
341 | colors[p.index] = lx.hsb( | |
342 | lx.getBaseHuef(), | |
343 | 0, | |
344 | 0 | |
345 | ); | |
346 | } | |
347 | ||
348 | public boolean shouldLightPoint(PointState point_state) { | |
349 | // Respect rate parameter. | |
350 | if(time_since_last_run < rateParameter.getValuef()) { | |
351 | any_changes_this_run = true; | |
352 | return point_state.alive; | |
353 | } else { | |
354 | boolean new_state = cycleOfAutomata(point_state); | |
355 | new_states.add(new_state); | |
356 | return new_state; | |
357 | } | |
358 | } | |
359 | ||
360 | public boolean cycleOfAutomata(PointState point_state) { | |
361 | Integer index = point_state.index; | |
362 | Integer alive_neighbor_count = countLiveNeighbors(point_state); | |
363 | boolean before_alive = point_state.alive; | |
364 | boolean after_alive = before_alive; | |
365 | ||
366 | if(point_state.alive) { | |
367 | if(alive_neighbor_count == 1) { | |
368 | after_alive = true; | |
369 | } else { | |
370 | after_alive = false; | |
371 | } | |
372 | ||
373 | } else { | |
374 | if(alive_neighbor_count == 1) { | |
375 | after_alive = true; | |
376 | } else { | |
377 | after_alive = false; | |
378 | } | |
379 | } | |
380 | ||
381 | if(before_alive != after_alive) { | |
382 | any_changes_this_run = true; | |
383 | } | |
384 | ||
385 | return after_alive; | |
386 | } | |
387 | ||
388 | public int countLiveNeighbors(PointState point_state) { | |
389 | Integer index = point_state.index; | |
390 | PointState before_neighbor; | |
391 | PointState after_neighbor; | |
392 | ||
393 | int count = 0; | |
394 | if (index > 0) { | |
395 | before_neighbor = point_states.get(index - 1); | |
396 | if(before_neighbor.alive) { | |
397 | count++; | |
398 | } | |
399 | } | |
400 | ||
401 | if (index < (point_states.size() - 1)) { | |
402 | after_neighbor = point_states.get(index + 1); | |
403 | if(after_neighbor.alive) { | |
404 | count++; | |
405 | } | |
406 | } | |
407 | ||
408 | return count; | |
409 | } | |
410 | ||
411 | private void applyNewStates() { | |
412 | int index = 0; | |
413 | for(boolean new_state: new_states) { | |
414 | PointState point_state = this.point_states.get(index); | |
415 | point_state.alive = new_states.get(index); | |
416 | index++; | |
417 | } | |
418 | } | |
419 | ||
420 | private void randomizePointStates() { | |
421 | double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY); | |
422 | double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random()); | |
423 | ||
424 | print("Randomizing points! p = " + prob + "\n"); | |
425 | ||
426 | for (PointState point_state: this.point_states) { | |
427 | point_state.alive = (Math.random() <= prob); | |
428 | } | |
429 | } | |
7782bf8e LW |
430 | } |
431 | ||
432 | class L8onStrips extends SCPattern { | |
433 | // Controls the rate of life algorithm ticks, in milliseconds | |
434 | private BasicParameter rateParameter = new BasicParameter("DELAY", 112.5, 0.0, 1000.0); | |
435 | // Controls if the cubes should be randomized even if something changes. Set above 0.5 to randomize cube aliveness. | |
436 | private BasicParameter randomParameter = new BasicParameter("RAND", 0.0); | |
437 | // Controls the brightness of dead cubes. | |
438 | private BasicParameter deadParameter = new BasicParameter("DEAD", 25.0, 0.0, 100.0); | |
439 | // Controls the saturation. | |
440 | private BasicParameter saturationParameter = new BasicParameter("SAT", 90.0, 0.0, 100.0); | |
441 | ||
442 | public final double MIN_ALIVE_PROBABILITY = 0.2; | |
443 | public final double MAX_ALIVE_PROBABILITY = 0.9; | |
444 | ||
445 | private final SinLFO xPos = new SinLFO(0, model.xMax, 4500); | |
446 | private final SinLFO zPos = new SinLFO(0, model.zMax, 2500); | |
447 | ||
448 | class StripState { | |
449 | // Index of strip in glucose.model.strips | |
450 | public Integer index; | |
451 | // Boolean which describes if strip is alive. | |
452 | public boolean alive; | |
453 | // List of this cubes neighbors | |
454 | public List<Integer> neighbors; | |
455 | ||
456 | public StripState(Integer index, boolean alive, List<Integer> neighbors) { | |
457 | this.index = index; | |
458 | this.alive = alive; | |
459 | this.neighbors = neighbors; | |
460 | } | |
461 | } | |
462 | ||
463 | // Contains the state of all cubes by index. | |
464 | private List<StripState> strip_states; | |
465 | // Contains the amount of time since the last cycle of life. | |
466 | private int time_since_last_run; | |
467 | // Boolean describing if life changes were made during the current run. | |
468 | private boolean any_changes_this_run; | |
469 | // Hold the new lives | |
470 | private List<Boolean> new_lives; | |
471 | ||
472 | public L8onStrips(GLucose glucose) { | |
473 | super(glucose); | |
474 | ||
475 | //Print debug info about the strips. | |
476 | //outputStripInfo(); | |
477 | ||
478 | initStripStates(); | |
479 | randomizeStripStates(); | |
480 | time_since_last_run = 0; | |
481 | any_changes_this_run = false; | |
482 | new_lives = new ArrayList<Boolean>(); | |
483 | ||
484 | addParameter(rateParameter); | |
485 | addParameter(randomParameter); | |
486 | addParameter(deadParameter); | |
487 | addParameter(saturationParameter); | |
488 | ||
489 | addModulator(xPos).trigger(); | |
490 | addModulator(zPos).trigger(); | |
491 | } | |
492 | ||
493 | public void run(double deltaMs) { | |
494 | Integer i = 0; | |
495 | StripState strip_state; | |
496 | ||
497 | any_changes_this_run = false; | |
498 | new_lives.clear(); | |
499 | time_since_last_run += deltaMs; | |
500 | ||
501 | for (Strip strip : model.strips) { | |
502 | strip_state = this.strip_states.get(i); | |
503 | ||
504 | if(shouldLightStrip(strip_state)) { | |
505 | lightLiveStrip(strip); | |
506 | } else { | |
507 | lightDeadStrip(strip); | |
508 | } | |
509 | ||
510 | i++; | |
511 | } | |
512 | ||
513 | boolean should_randomize_anyway = (randomParameter.getValuef() > 0.5); | |
514 | if(should_randomize_anyway || !any_changes_this_run) { | |
515 | randomizeStripStates(); | |
516 | } else { | |
517 | applyNewLives(); | |
518 | } | |
519 | ||
520 | if(time_since_last_run >= rateParameter.getValuef()) { | |
521 | time_since_last_run = 0; | |
522 | } | |
523 | } | |
524 | ||
525 | public void lightLiveStrip(Strip strip) { | |
526 | for (LXPoint p : strip.points) { | |
527 | float hv = max(0, lx.getBaseHuef() - abs(p.z - zPos.getValuef())); | |
528 | colors[p.index] = lx.hsb( | |
529 | hv, | |
530 | saturationParameter.getValuef(), | |
531 | 75 | |
532 | ); | |
533 | } | |
534 | } | |
535 | ||
536 | public void lightDeadStrip(Strip strip) { | |
537 | for (LXPoint p : strip.points) { | |
538 | float hv = max(0, lx.getBaseHuef() - abs(p.x - xPos.getValuef())); | |
539 | double dead_bright = deadParameter.getValuef() * Math.random(); | |
2815b690 | 540 | |
7782bf8e LW |
541 | colors[p.index] = lx.hsb( |
542 | hv, | |
543 | saturationParameter.getValuef(), | |
544 | dead_bright | |
545 | ); | |
546 | } | |
547 | } | |
548 | ||
549 | public void outputStripInfo() { | |
550 | int i = 0; | |
551 | for (Strip strip : model.strips) { | |
552 | print("Strip " + i + ": " + strip.cx + "," + strip.cy + "," + strip.cz + "\n"); | |
553 | ++i; | |
554 | } | |
555 | } | |
556 | ||
557 | private void initStripStates() { | |
558 | List<Integer> neighbors; | |
559 | boolean alive = false; | |
560 | StripState strip_state; | |
561 | this.strip_states = new ArrayList<StripState>(); | |
562 | Integer i = 0; | |
563 | ||
564 | int total_neighbors = 0; | |
565 | ||
566 | for (Strip strip : model.strips) { | |
567 | neighbors = findStripNeighbors(strip, i); | |
568 | alive = true; | |
569 | strip_state = new StripState(i, alive, neighbors); | |
570 | this.strip_states.add(strip_state); | |
571 | ||
572 | total_neighbors += neighbors.size(); | |
573 | ++i; | |
574 | } | |
575 | ||
576 | float average_neighbor_count = (float) total_neighbors / (float) model.strips.size(); | |
577 | //print("Average neighbor count: " + average_neighbor_count + "\n"); | |
578 | } | |
579 | ||
580 | private void randomizeStripStates() { | |
581 | double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY); | |
582 | double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random()); | |
583 | ||
584 | //print("Randomizing strips! p = " + prob + "\n"); | |
585 | ||
586 | for (StripState strip_state : this.strip_states) { | |
587 | strip_state.alive = (Math.random() <= prob); | |
588 | } | |
589 | } | |
590 | ||
591 | public List<Integer> findStripNeighbors(Strip strip, Integer index) { | |
592 | List<Integer> neighbors = new LinkedList<Integer>(); | |
593 | Integer i = 0; | |
594 | int neighbor_count = 0; | |
595 | double distance = 0.0; | |
596 | ||
597 | for (Strip s : model.strips) { | |
598 | if( (int)index != (int)i ) { | |
599 | distance = Math.sqrt( Math.pow((s.cx - strip.cx), 2) + Math.pow((s.cy - strip.cy), 2) + Math.pow((s.cz - strip.cz), 2) ); | |
600 | ||
601 | if(distance < ( (double) Cube.EDGE_WIDTH) ) { | |
602 | //print("Strip " + i + " is a neighbor of " + index + "\n"); | |
603 | neighbors.add(i); | |
604 | } | |
605 | } | |
606 | i++; | |
607 | } | |
608 | ||
609 | return neighbors; | |
610 | } | |
611 | ||
612 | public boolean shouldLightStrip(StripState strip_state) { | |
613 | // Respect rate parameter. | |
614 | if(time_since_last_run < rateParameter.getValuef()) { | |
615 | any_changes_this_run = true; | |
616 | return strip_state.alive; | |
617 | } else { | |
618 | boolean new_life = cycleOfStripperLife(strip_state); | |
619 | new_lives.add(new_life); | |
620 | return new_life; | |
621 | } | |
622 | } | |
623 | ||
624 | public void applyNewLives() { | |
625 | int index = 0; | |
626 | for(boolean liveliness: new_lives) { | |
627 | StripState strip_state = this.strip_states.get(index); | |
628 | strip_state.alive = new_lives.get(index); | |
629 | index++; | |
630 | } | |
631 | } | |
632 | ||
633 | public boolean cycleOfStripperLife(StripState strip_state) { | |
634 | Integer index = strip_state.index; | |
635 | Integer alive_neighbor_count = countLiveNeighbors(strip_state); | |
636 | boolean before_alive = strip_state.alive; | |
637 | boolean after_alive = before_alive; | |
638 | ||
639 | if(strip_state.alive) { | |
640 | if(alive_neighbor_count < 2 || alive_neighbor_count > 6) { | |
641 | after_alive = false; | |
642 | } else { | |
643 | after_alive = true; | |
644 | } | |
645 | ||
646 | } else { | |
647 | if(alive_neighbor_count == 5) { | |
648 | after_alive = true; | |
649 | } else { | |
650 | after_alive = false; | |
651 | } | |
652 | } | |
653 | ||
654 | if(before_alive != after_alive) { | |
655 | any_changes_this_run = true; | |
656 | } | |
657 | ||
658 | return after_alive; | |
659 | } | |
660 | ||
661 | public Integer countLiveNeighbors(StripState strip_state) { | |
662 | Integer count = 0; | |
663 | StripState neighbor_strip_state; | |
664 | ||
665 | for(Integer neighbor_index: strip_state.neighbors) { | |
666 | neighbor_strip_state = this.strip_states.get(neighbor_index); | |
667 | if(neighbor_strip_state.alive) { | |
668 | count++; | |
669 | } | |
670 | } | |
671 | ||
672 | return count; | |
673 | } | |
2815b690 | 674 | } |