1 class L8onLife extends SCPattern {
2 // Controls the rate of life algorithm ticks, in milliseconds
3 private BasicParameter rateParameter = new BasicParameter("DELAY", 112.5, 0.0, 1000.0);
4 // Controls the probability of a mutation in the cycleOfLife
5 private BasicParameter mutationParameter = new BasicParameter("MUT", 0.000000011, 0.0, 0.1);
6 // Controls the saturation.
7 private BasicParameter saturationParameter = new BasicParameter("SAT", 90.0, 0.0, 100.0);
9 public final double MIN_ALIVE_PROBABILITY = 0.2;
10 public final double MAX_ALIVE_PROBABILITY = 0.9;
12 public final float MAX_ALIVE_BRIGHTNESS = 90.0;
14 private final SawLFO cubePos = new SawLFO(0, model.cubes.size(), 4000);
17 // Index of cube in glucose.model.cubes
19 // Boolean which describes if cube is alive.
21 // Boolean which describes if strip was just changed;
22 public boolean just_changed;
24 public float current_brightness;
25 // List of this cubes neighbors
26 public List<Integer> neighbors;
28 public CubeState(Integer index, boolean alive, float current_brightness, List<Integer> neighbors) {
31 this.current_brightness = current_brightness;
32 this.neighbors = neighbors;
36 // Contains the state of all cubes by index.
37 private List<CubeState> cube_states;
38 // Contains the amount of time since the last cycle of life.
39 private int time_since_last_run;
40 // Boolean describing if life changes were made during the current run.
41 private boolean any_changes_this_run;
43 private List<Boolean> new_lives;
45 public L8onLife(LX lx) {
48 //Print debug info about the cubes.
52 time_since_last_run = 0;
53 any_changes_this_run = false;
54 new_lives = new ArrayList<Boolean>();
56 addParameter(rateParameter);
57 addParameter(mutationParameter);
58 addParameter(saturationParameter);
59 addModulator(cubePos).trigger();
62 public void run(double deltaMs) {
66 any_changes_this_run = false;
68 time_since_last_run += deltaMs;
70 for (Cube cube : model.cubes) {
71 cube_state = this.cube_states.get(i);
73 if(shouldLightCube(cube_state)) {
74 lightLiveCube(cube, cube_state, deltaMs);
76 lightDeadCube(cube, cube_state, deltaMs);
82 if(!any_changes_this_run) {
83 randomizeCubeStates();
88 if(time_since_last_run >= rateParameter.getValuef()) {
89 time_since_last_run = 0;
93 public void lightLiveCube(Cube cube, CubeState cube_state, double deltaMs) {
94 float cube_dist = LXUtils.wrapdistf((float) cube_state.index, cubePos.getValuef(), model.cubes.size());
95 float hv = (cube_dist / model.cubes.size()) * 360;
96 float bv = cube_state.current_brightness;
98 if(!cube_state.just_changed || deltaMs >= rateParameter.getValuef()) {
99 float bright_prop = min(((float) time_since_last_run / rateParameter.getValuef()), 1.0);
100 bv = min(MAX_ALIVE_BRIGHTNESS, bright_prop * MAX_ALIVE_BRIGHTNESS);
102 if(cube_state.current_brightness < bv) {
103 cube_state.current_brightness = bv;
105 bv = cube_state.current_brightness;
109 for (LXPoint p : cube.points) {
110 colors[p.index] = lx.hsb(
112 saturationParameter.getValuef(),
118 public void lightDeadCube(Cube cube, CubeState cube_state, double deltaMs) {
119 float cube_dist = LXUtils.wrapdistf((float) cube_state.index, cubePos.getValuef(), model.cubes.size());
120 float hv = (cube_dist / (float) model.cubes.size()) * 360;
121 float bv = cube_state.current_brightness;
123 if(!cube_state.just_changed || deltaMs >= rateParameter.getValuef()) {
124 float bright_prop = 1.0 - min(((float) time_since_last_run / rateParameter.getValuef()), 1.0);
125 bv = max(0.0, bright_prop * MAX_ALIVE_BRIGHTNESS);
127 if(cube_state.current_brightness > bv) {
128 cube_state.current_brightness = bv;
130 bv = cube_state.current_brightness;
134 for (LXPoint p : cube.points) {
135 colors[p.index] = lx.hsb(
137 saturationParameter.getValuef(),
143 public void outputCubeInfo() {
145 for (Cube c : model.cubes) {
146 print("Cube " + i + ": " + c.x + "," + c.y + "," + c.z + "\n");
149 print("Edgeheight: " + Cube.EDGE_HEIGHT + "\n");
150 print("Edgewidth: " + Cube.EDGE_WIDTH + "\n");
151 print("Channelwidth: " + Cube.CHANNEL_WIDTH + "\n");
154 private void initCubeStates() {
155 List<Integer> neighbors;
156 boolean alive = false;
157 CubeState cube_state;
158 this.cube_states = new ArrayList<CubeState>();
159 float current_brightness = 0.0;
162 for (Cube c : model.cubes) {
163 neighbors = findCubeNeighbors(c, i);
165 cube_state = new CubeState(i, alive, current_brightness, neighbors);
166 this.cube_states.add(cube_state);
171 private void randomizeCubeStates() {
172 double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY);
173 double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random());
175 //print("Randomizing cubes! p = " + prob + "\n");
177 for (CubeState cube_state: this.cube_states) {
178 cube_state.alive = (Math.random() <= prob);
182 public List<Integer> findCubeNeighbors(Cube cube, Integer index) {
183 List<Integer> neighbors = new LinkedList<Integer>();
186 for (Cube c : model.cubes) {
188 if(abs(c.x - cube.x) < (Cube.EDGE_WIDTH * 2) && abs(c.y - cube.y) < (Cube.EDGE_HEIGHT * 2)) {
189 //print("Cube " + i + " is a neighbor of " + index + "\n");
200 public boolean shouldLightCube(CubeState cube_state) {
201 // Respect rate parameter.
202 if(time_since_last_run < rateParameter.getValuef()) {
203 any_changes_this_run = true;
204 cube_state.just_changed = false;
205 return cube_state.alive;
207 boolean new_life = cycleOfLife(cube_state);
208 new_lives.add(new_life);
213 public void applyNewLives() {
215 for(boolean liveliness: new_lives) {
216 CubeState cube_state = this.cube_states.get(index);
217 cube_state.alive = new_lives.get(index);
222 public boolean cycleOfLife(CubeState cube_state) {
223 Integer index = cube_state.index;
224 Integer alive_neighbor_count = countLiveNeighbors(cube_state);
225 boolean before_alive = cube_state.alive;
226 boolean after_alive = before_alive;
227 double mutation = Math.random();
229 if(cube_state.alive) {
230 if(alive_neighbor_count < 2 || alive_neighbor_count > 3) {
237 if(alive_neighbor_count == 2) {
244 if(mutation <= mutationParameter.getValuef()) {
245 after_alive = !after_alive;
248 if(before_alive != after_alive) {
249 cube_state.just_changed = true;
250 any_changes_this_run = true;
256 public Integer countLiveNeighbors(CubeState cube_state) {
258 CubeState neighbor_cube_state;
260 for(Integer neighbor_index: cube_state.neighbors) {
261 neighbor_cube_state = this.cube_states.get(neighbor_index);
262 if(neighbor_cube_state.alive) {
271 class L8onAutomata extends SCPattern {
272 // Controls the rate of life algorithm ticks, in milliseconds
273 private BasicParameter rateParameter = new BasicParameter("DELAY", 75.0, 0.0, 1000.0);
274 // Controls the probability of a mutation in the cycleOfStripperLife
275 private BasicParameter mutationParameter = new BasicParameter("MUT", 0.000000011, 0.0, 0.1);
276 // Controls the rate of life algorithm ticks, in milliseconds
277 private BasicParameter saturationParameter = new BasicParameter("SAT", 90.0, 0.0, 100.0);
279 private final SawLFO pointPos = new SawLFO(0, model.points.size(), 8000);
281 public final double MIN_ALIVE_PROBABILITY = 0.2;
282 public final double MAX_ALIVE_PROBABILITY = 0.9;
284 public final float MAX_ALIVE_BRIGHTNESS = 90.0;
287 // Index of cube in glucose.model.cubes
288 public Integer index;
289 // Boolean which describes if cube is alive.
290 public boolean alive;
291 // Boolean which describes if strip was just changed;
292 public boolean just_changed;
293 // Current brightness
294 public float current_brightness;
296 public PointState(Integer index, boolean alive, float current_brightness) {
299 this.current_brightness = current_brightness;
300 this.just_changed = false;
304 // Contains the state of all cubes by index.
305 private List<PointState> point_states;
306 // Contains the amount of time since the last cycle of life.
307 private int time_since_last_run;
308 // Boolean describing if life changes were made during the current run.
309 private boolean any_changes_this_run;
310 // Hold the new lives
311 private List<Boolean> new_states;
313 public L8onAutomata(LX lx) {
316 //Print debug info about the cubes.
320 randomizePointStates();
321 time_since_last_run = 0;
322 any_changes_this_run = false;
323 new_states = new ArrayList<Boolean>();
325 addParameter(mutationParameter);
326 addParameter(rateParameter);
327 addParameter(saturationParameter);
328 addModulator(pointPos).trigger();
331 private void initPointStates() {
332 boolean alive = true;
333 PointState point_state;
334 this.point_states = new ArrayList<PointState>();
336 float current_brightness = 0.0;
338 for (LXPoint p : model.points) {
339 point_state = new PointState(i, alive, current_brightness);
340 this.point_states.add(point_state);
345 public void run(double deltaMs) {
347 PointState point_state;
349 any_changes_this_run = false;
351 time_since_last_run += deltaMs;
353 for (LXPoint p : model.points) {
354 point_state = this.point_states.get(i);
356 if(shouldLightPoint(point_state)) {
357 lightLivePoint(p, point_state, deltaMs);
359 lightDeadPoint(p, point_state, deltaMs);
364 if(!any_changes_this_run) {
365 randomizePointStates();
370 if(time_since_last_run >= rateParameter.getValuef()) {
371 time_since_last_run = 0;
375 public void lightLivePoint(LXPoint p, PointState point_state, double deltaMs) {
376 float point_dist = LXUtils.wrapdistf((float) point_state.index, pointPos.getValuef(), model.points.size());
377 float hv = (point_dist / model.points.size()) * 360;
378 float bv = point_state.current_brightness;
380 if(deltaMs >= rateParameter.getValuef() || !point_state.just_changed) {
381 float bright_prop = min(((float) time_since_last_run / rateParameter.getValuef()), 1.0);
382 bv = min(MAX_ALIVE_BRIGHTNESS, bright_prop * MAX_ALIVE_BRIGHTNESS);
384 if(point_state.current_brightness < bv) {
385 point_state.current_brightness = bv;
387 bv = point_state.current_brightness;
391 colors[p.index] = lx.hsb(
393 saturationParameter.getValuef(),
398 public void lightDeadPoint(LXPoint p, PointState point_state, double deltaMs) {
399 float point_dist = LXUtils.wrapdistf((float) point_state.index, pointPos.getValuef(), model.points.size());
400 float hv = (point_dist / model.points.size()) * 360;
401 float bv = point_state.current_brightness;
403 if(!point_state.just_changed || deltaMs >= rateParameter.getValuef()) {
404 float bright_prop = 1.0 - min(((float) time_since_last_run / rateParameter.getValuef()), 1.0);
405 bv = max(0.0, bright_prop * MAX_ALIVE_BRIGHTNESS);
407 if(point_state.current_brightness > bv) {
408 point_state.current_brightness = bv;
410 bv = point_state.current_brightness;
414 colors[p.index] = lx.hsb(
416 saturationParameter.getValuef(),
421 public boolean shouldLightPoint(PointState point_state) {
422 // Respect rate parameter.
423 if(time_since_last_run < rateParameter.getValuef()) {
424 any_changes_this_run = true;
425 point_state.just_changed = false;
426 return point_state.alive;
428 boolean new_state = cycleOfAutomata(point_state);
429 new_states.add(new_state);
434 public boolean cycleOfAutomata(PointState point_state) {
435 Integer index = point_state.index;
436 Integer alive_neighbor_count = countLiveNeighbors(point_state);
437 boolean before_alive = point_state.alive;
438 boolean after_alive = before_alive;
439 double mutation = Math.random();
441 if(point_state.alive) {
442 if(alive_neighbor_count == 1) {
449 if(alive_neighbor_count == 1) {
456 if(mutation < mutationParameter.getValuef()) {
457 after_alive = !after_alive;
460 if(before_alive != after_alive) {
461 any_changes_this_run = true;
462 point_state.just_changed = true;
468 public int countLiveNeighbors(PointState point_state) {
471 if (point_state.index > 0) {
472 PointState before_neighbor = point_states.get(point_state.index - 1);
473 if(before_neighbor.alive) {
478 if (point_state.index < (point_states.size() - 1)) {
479 PointState after_neighbor = point_states.get(point_state.index + 1);
480 if(after_neighbor.alive) {
488 private void applyNewStates() {
490 for(boolean new_state: new_states) {
491 PointState point_state = this.point_states.get(index);
492 point_state.alive = new_states.get(index);
497 private void randomizePointStates() {
498 double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY);
499 double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random());
501 //print("Randomizing points! p = " + prob + "\n");
503 for (PointState point_state: this.point_states) {
504 point_state.alive = (Math.random() <= prob);
505 point_state.just_changed = true;
510 class L8onStripLife extends SCPattern {
511 // Controls the rate of life algorithm ticks, in milliseconds
512 private BasicParameter rateParameter = new BasicParameter("DELAY", 112.5, 1.0, 1000.0);
513 // Controls the probability of a mutation in the cycleOfStripperLife
514 private BasicParameter mutationParameter = new BasicParameter("MUT", 0.000000011, 0.0, 0.1);
515 // Controls the saturation.
516 private BasicParameter saturationParameter = new BasicParameter("SAT", 90.0, 0.0, 100.0);
518 public final double MIN_ALIVE_PROBABILITY = 0.4;
519 public final double MAX_ALIVE_PROBABILITY = 0.9;
521 public final float MAX_ALIVE_BRIGHTNESS = 90.0;
523 private final SawLFO stripPos = new SawLFO(0, model.strips.size(), 8000);
526 // Index of strip in glucose.model.strips
527 public Integer index;
528 // Boolean which describes if strip is alive.
529 public boolean alive;
530 // Boolean which describes if strip was just changed;
531 public boolean just_changed;
532 // Current brightness
533 public float current_brightness;
534 // List of this cubes neighbors
535 public List<Integer> neighbors;
537 public StripState(Integer index, boolean alive, float current_brightness, List<Integer> neighbors) {
540 this.current_brightness = current_brightness;
541 this.neighbors = neighbors;
542 this.just_changed = false;
546 // Contains the state of all cubes by index.
547 private List<StripState> strip_states;
548 // Contains the amount of time since the last cycle of life.
549 private int time_since_last_run;
550 // Boolean describing if life changes were made during the current run.
551 private boolean any_changes_this_run;
552 // Hold the new lives
553 private List<Boolean> new_lives;
555 public L8onStripLife(LX lx) {
558 //Print debug info about the strips.
562 randomizeStripStates();
563 time_since_last_run = 0;
564 any_changes_this_run = false;
565 new_lives = new ArrayList<Boolean>();
567 addParameter(rateParameter);
568 addParameter(mutationParameter);
569 addParameter(saturationParameter);
571 addModulator(stripPos).trigger();
574 public void run(double deltaMs) {
576 StripState strip_state;
578 any_changes_this_run = false;
580 time_since_last_run += deltaMs;
582 for (Strip strip : model.strips) {
583 strip_state = this.strip_states.get(i);
585 if(shouldLightStrip(strip_state)) {
586 lightLiveStrip(strip, strip_state, deltaMs);
588 lightDeadStrip(strip, strip_state, deltaMs);
593 if(!any_changes_this_run) {
594 randomizeStripStates();
599 if(time_since_last_run >= rateParameter.getValuef()) {
600 time_since_last_run = 0;
604 public void lightLiveStrip(Strip strip, StripState strip_state, double deltaMs) {
605 float strip_dist = LXUtils.wrapdistf((float) strip_state.index, stripPos.getValuef(), model.strips.size());
606 float hv = (strip_dist / model.strips.size()) * 360;
607 float bv = strip_state.current_brightness;
609 if(deltaMs >= rateParameter.getValuef() || !strip_state.just_changed) {
610 float bright_prop = min(((float) time_since_last_run / rateParameter.getValuef()), 1.0);
611 bv = min(MAX_ALIVE_BRIGHTNESS, bright_prop * MAX_ALIVE_BRIGHTNESS);
613 if(strip_state.current_brightness < bv) {
614 strip_state.current_brightness = bv;
616 bv = strip_state.current_brightness;
620 for (LXPoint p : strip.points) {
621 colors[p.index] = lx.hsb(
623 saturationParameter.getValuef(),
629 public void lightDeadStrip(Strip strip, StripState strip_state, double deltaMs) {
630 float strip_dist = LXUtils.wrapdistf((float) strip_state.index, stripPos.getValuef(), model.strips.size());
631 float hv = (strip_dist / model.strips.size()) * 360;
632 float bv = strip_state.current_brightness;
634 if(!strip_state.just_changed || deltaMs >= rateParameter.getValuef()) {
635 float bright_prop = 1.0 - min(((float) time_since_last_run / rateParameter.getValuef()), 1.0);
636 bv = max(0.0, bright_prop * MAX_ALIVE_BRIGHTNESS);
638 if(strip_state.current_brightness > bv) {
639 strip_state.current_brightness = bv;
641 bv = strip_state.current_brightness;
645 for (LXPoint p : strip.points) {
646 colors[p.index] = lx.hsb(
648 saturationParameter.getValuef(),
654 public void outputStripInfo() {
656 for (Strip strip : model.strips) {
657 print("Strip " + i + ": " + strip.cx + "," + strip.cy + "," + strip.cz + "\n");
662 private void initStripStates() {
663 List<Integer> neighbors;
664 boolean alive = false;
665 float current_brightness = 0.0;
666 StripState strip_state;
667 this.strip_states = new ArrayList<StripState>();
670 int total_neighbors = 0;
672 for (Strip strip : model.strips) {
673 neighbors = findStripNeighbors(strip, i);
675 strip_state = new StripState(i, alive, current_brightness, neighbors);
676 this.strip_states.add(strip_state);
678 total_neighbors += neighbors.size();
682 float average_neighbor_count = (float) total_neighbors / (float) model.strips.size();
683 //print("Average neighbor count: " + average_neighbor_count + "\n");
686 private void randomizeStripStates() {
687 double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY);
688 double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random());
690 //print("Randomizing strips! p = " + prob + "\n");
692 for (StripState strip_state : this.strip_states) {
693 strip_state.alive = (Math.random() <= prob);
694 strip_state.just_changed = true;
698 public List<Integer> findStripNeighbors(Strip strip, Integer index) {
699 List<Integer> neighbors = new LinkedList<Integer>();
701 int neighbor_count = 0;
702 double distance = 0.0;
704 for (Strip s : model.strips) {
705 if( (int)index != (int)i ) {
706 distance = Math.sqrt( Math.pow((s.cx - strip.cx), 2) + Math.pow((s.cy - strip.cy), 2) + Math.pow((s.cz - strip.cz), 2) );
708 if(distance < ( (double) Cube.EDGE_WIDTH) ) {
709 //print("Strip " + i + " is a neighbor of " + index + "\n");
719 public boolean shouldLightStrip(StripState strip_state) {
720 // Respect rate parameter.
721 if(time_since_last_run < rateParameter.getValuef()) {
722 any_changes_this_run = true;
723 strip_state.just_changed = false;
724 return strip_state.alive;
726 boolean new_life = cycleOfStripperLife(strip_state);
727 new_lives.add(new_life);
732 public void applyNewLives() {
734 for(boolean liveliness: new_lives) {
735 StripState strip_state = this.strip_states.get(index);
736 strip_state.alive = new_lives.get(index);
741 public boolean cycleOfStripperLife(StripState strip_state) {
742 Integer alive_neighbor_count = countLiveNeighbors(strip_state);
743 boolean before_alive = strip_state.alive;
744 boolean after_alive = before_alive;
745 double mutation = Math.random();
747 if(strip_state.alive) {
748 if(alive_neighbor_count < 2 || alive_neighbor_count > 6) {
755 if(alive_neighbor_count == 5) {
762 if(mutation < mutationParameter.getValuef()) {
763 after_alive = !after_alive;
766 if(before_alive != after_alive) {
767 any_changes_this_run = true;
768 strip_state.just_changed = true;
774 public Integer countLiveNeighbors(StripState strip_state) {
776 StripState neighbor_strip_state;
778 for(Integer neighbor_index: strip_state.neighbors) {
779 neighbor_strip_state = this.strip_states.get(neighbor_index);
780 if(neighbor_strip_state.alive) {