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 randomParameter = new BasicParameter("RAND", 0.000000011, 0.0, 0.1);
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);
11 public final double MIN_ALIVE_PROBABILITY = 0.2;
12 public final double MAX_ALIVE_PROBABILITY = 0.9;
14 private final SawLFO cubePos = new SawLFO(0, model.cubes.size(), 2500);
17 // Index of cube in glucose.model.cubes
19 // Boolean which describes if cube is alive.
21 // List of this cubes neighbors
22 public List<Integer> neighbors;
24 public CubeState(Integer index, boolean alive, List<Integer> neighbors) {
27 this.neighbors = neighbors;
31 // Contains the state of all cubes by index.
32 private List<CubeState> cube_states;
33 // Contains the amount of time since the last cycle of life.
34 private int time_since_last_run;
35 // Boolean describing if life changes were made during the current run.
36 private boolean any_changes_this_run;
38 private List<Boolean> new_lives;
40 public L8onLife(GLucose glucose) {
43 //Print debug info about the cubes.
47 time_since_last_run = 0;
48 any_changes_this_run = false;
49 new_lives = new ArrayList<Boolean>();
51 addParameter(rateParameter);
52 addParameter(randomParameter);
53 addParameter(deadParameter);
54 addParameter(saturationParameter);
55 addModulator(cubePos).trigger();
58 public void run(double deltaMs) {
62 any_changes_this_run = false;
64 time_since_last_run += deltaMs;
66 for (Cube cube : model.cubes) {
67 cube_state = this.cube_states.get(i);
69 if(shouldLightCube(cube_state)) {
70 lightLiveCube(cube, i);
72 lightDeadCube(cube, i);
78 if(!any_changes_this_run) {
79 randomizeCubeStates();
84 if(time_since_last_run >= rateParameter.getValuef()) {
85 time_since_last_run = 0;
89 public void lightLiveCube(Cube cube, Integer index) {
90 float cube_dist = LXUtils.wrapdistf((float) index, cubePos.getValuef(), model.cubes.size());
91 float hv = (cube_dist / model.cubes.size()) * 360;
93 for (LXPoint p : cube.points) {
94 colors[p.index] = lx.hsb(
96 saturationParameter.getValuef(),
102 public void lightDeadCube(Cube cube, Integer index) {
103 float cube_dist = LXUtils.wrapdistf((float) index, cubePos.getValuef(), model.cubes.size());
104 float dist_proportion = (cube_dist / (float) model.cubes.size());
105 float hv = dist_proportion * 360;
106 float dead_bright = deadParameter.getValuef() * dist_proportion;
108 for (LXPoint p : cube.points) {
109 colors[p.index] = lx.hsb(
111 saturationParameter.getValuef(),
117 public void outputCubeInfo() {
119 for (Cube c : model.cubes) {
120 print("Cube " + i + ": " + c.x + "," + c.y + "," + c.z + "\n");
123 print("Edgeheight: " + Cube.EDGE_HEIGHT + "\n");
124 print("Edgewidth: " + Cube.EDGE_WIDTH + "\n");
125 print("Channelwidth: " + Cube.CHANNEL_WIDTH + "\n");
128 private void initCubeStates() {
129 List<Integer> neighbors;
130 boolean alive = false;
131 CubeState cube_state;
132 this.cube_states = new ArrayList<CubeState>();
135 for (Cube c : model.cubes) {
136 neighbors = findCubeNeighbors(c, i);
138 cube_state = new CubeState(i, alive, neighbors);
139 this.cube_states.add(cube_state);
144 private void randomizeCubeStates() {
145 double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY);
146 double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random());
148 //print("Randomizing cubes! p = " + prob + "\n");
150 for (CubeState cube_state: this.cube_states) {
151 cube_state.alive = (Math.random() <= prob);
155 public List<Integer> findCubeNeighbors(Cube cube, Integer index) {
156 List<Integer> neighbors = new LinkedList<Integer>();
159 for (Cube c : model.cubes) {
161 if(abs(c.x - cube.x) < (Cube.EDGE_WIDTH * 2) && abs(c.y - cube.y) < (Cube.EDGE_HEIGHT * 2)) {
162 //print("Cube " + i + " is a neighbor of " + index + "\n");
173 public boolean shouldLightCube(CubeState cube_state) {
174 // Respect rate parameter.
175 if(time_since_last_run < rateParameter.getValuef()) {
176 any_changes_this_run = true;
177 return cube_state.alive;
179 boolean new_life = cycleOfLife(cube_state);
180 new_lives.add(new_life);
185 public void applyNewLives() {
187 for(boolean liveliness: new_lives) {
188 CubeState cube_state = this.cube_states.get(index);
189 cube_state.alive = new_lives.get(index);
194 public boolean cycleOfLife(CubeState cube_state) {
195 Integer index = cube_state.index;
196 Integer alive_neighbor_count = countLiveNeighbors(cube_state);
197 boolean before_alive = cube_state.alive;
198 boolean after_alive = before_alive;
199 double mutation = Math.random();
201 if(cube_state.alive) {
202 if(alive_neighbor_count < 2 || alive_neighbor_count > 3) {
209 if(alive_neighbor_count == 2) {
216 if(mutation <= randomParameter.getValuef()) {
217 after_alive = !after_alive;
220 if(before_alive != after_alive) {
221 any_changes_this_run = true;
227 public Integer countLiveNeighbors(CubeState cube_state) {
229 CubeState neighbor_cube_state;
231 for(Integer neighbor_index: cube_state.neighbors) {
232 neighbor_cube_state = this.cube_states.get(neighbor_index);
233 if(neighbor_cube_state.alive) {
242 class L8onAutomata extends SCPattern {
243 // Controls the probability of a mutation in the cycleOfStripperLife
244 private BasicParameter randomParameter = new BasicParameter("RAND", 0.000000011, 0.0, 0.1);
245 // Controls the rate of life algorithm ticks, in milliseconds
246 private BasicParameter rateParameter = new BasicParameter("DELAY", 75.0, 0.0, 1000.0);
248 private final SawLFO pointPos = new SawLFO(0, model.points.size(), 3000);
250 public final double MIN_ALIVE_PROBABILITY = 0.2;
251 public final double MAX_ALIVE_PROBABILITY = 0.9;
254 // Index of cube in glucose.model.cubes
255 public Integer index;
256 // Boolean which describes if cube is alive.
257 public boolean alive;
259 public PointState(Integer index, boolean alive) {
265 // Contains the state of all cubes by index.
266 private List<PointState> point_states;
267 // Contains the amount of time since the last cycle of life.
268 private int time_since_last_run;
269 // Boolean describing if life changes were made during the current run.
270 private boolean any_changes_this_run;
271 // Hold the new lives
272 private List<Boolean> new_states;
274 public L8onAutomata(GLucose glucose) {
277 //Print debug info about the cubes.
281 randomizePointStates();
282 time_since_last_run = 0;
283 any_changes_this_run = false;
284 new_states = new ArrayList<Boolean>();
286 addParameter(randomParameter);
287 addParameter(rateParameter);
288 addModulator(pointPos).trigger();
291 private void initPointStates() {
292 boolean alive = false;
293 PointState point_state;
294 this.point_states = new ArrayList<PointState>();
297 for (LXPoint p : model.points) {
299 point_state = new PointState(i, alive);
300 this.point_states.add(point_state);
305 public void run(double deltaMs) {
307 PointState point_state;
309 any_changes_this_run = false;
311 time_since_last_run += deltaMs;
313 for (LXPoint p : model.points) {
314 point_state = this.point_states.get(i);
316 if(shouldLightPoint(point_state)) {
317 lightLivePoint(p, i);
319 lightDeadPoint(p, i);
325 if(!any_changes_this_run) {
326 randomizePointStates();
331 if(time_since_last_run >= rateParameter.getValuef()) {
332 time_since_last_run = 0;
336 public void lightLivePoint(LXPoint p, Integer index) {
337 float point_dist = LXUtils.wrapdistf((float) index, pointPos.getValuef(), model.points.size());
338 float hv = (point_dist / model.points.size()) * 360;
340 colors[p.index] = lx.hsb(
347 public void lightDeadPoint(LXPoint p, Integer index) {
348 colors[p.index] = lx.hsb(
355 public boolean shouldLightPoint(PointState point_state) {
356 // Respect rate parameter.
357 if(time_since_last_run < rateParameter.getValuef()) {
358 any_changes_this_run = true;
359 return point_state.alive;
361 boolean new_state = cycleOfAutomata(point_state);
362 new_states.add(new_state);
367 public boolean cycleOfAutomata(PointState point_state) {
368 Integer index = point_state.index;
369 Integer alive_neighbor_count = countLiveNeighbors(point_state);
370 boolean before_alive = point_state.alive;
371 boolean after_alive = before_alive;
372 double mutation = Math.random();
374 if(point_state.alive) {
375 if(alive_neighbor_count == 1) {
382 if(alive_neighbor_count == 1) {
389 if(mutation < randomParameter.getValuef()) {
390 after_alive = !after_alive;
393 if(before_alive != after_alive) {
394 any_changes_this_run = true;
400 public int countLiveNeighbors(PointState point_state) {
401 Integer index = point_state.index;
402 PointState before_neighbor;
403 PointState after_neighbor;
407 before_neighbor = point_states.get(index - 1);
408 if(before_neighbor.alive) {
413 if (index < (point_states.size() - 1)) {
414 after_neighbor = point_states.get(index + 1);
415 if(after_neighbor.alive) {
423 private void applyNewStates() {
425 for(boolean new_state: new_states) {
426 PointState point_state = this.point_states.get(index);
427 point_state.alive = new_states.get(index);
432 private void randomizePointStates() {
433 double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY);
434 double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random());
436 //print("Randomizing points! p = " + prob + "\n");
438 for (PointState point_state: this.point_states) {
439 point_state.alive = (Math.random() <= prob);
444 class L8onStrips extends SCPattern {
445 // Controls the rate of life algorithm ticks, in milliseconds
446 private BasicParameter rateParameter = new BasicParameter("DELAY", 112.5, 1.0, 1000.0);
447 // Controls the probability of a mutation in the cycleOfStripperLife
448 private BasicParameter randomParameter = new BasicParameter("RAND", 0.000000011, 0.0, 0.1);
449 // Controls the saturation.
450 private BasicParameter saturationParameter = new BasicParameter("SAT", 90.0, 0.0, 100.0);
452 public final double MIN_ALIVE_PROBABILITY = 0.4;
453 public final double MAX_ALIVE_PROBABILITY = 0.9;
455 public final float MAX_ALIVE_BRIGHTNESS = 95.0;
457 private final SawLFO stripPos = new SawLFO(0, model.strips.size(), 3000);
460 // Index of strip in glucose.model.strips
461 public Integer index;
462 // Boolean which describes if strip is alive.
463 public boolean alive;
464 // Boolean which describes if strip was just changed;
465 public boolean just_changed;
466 // Current brightness
467 public float current_brightness;
468 // List of this cubes neighbors
469 public List<Integer> neighbors;
471 public StripState(Integer index, boolean alive, float current_brightness, List<Integer> neighbors) {
474 this.neighbors = neighbors;
478 // Contains the state of all cubes by index.
479 private List<StripState> strip_states;
480 // Contains the amount of time since the last cycle of life.
481 private int time_since_last_run;
482 // Boolean describing if life changes were made during the current run.
483 private boolean any_changes_this_run;
484 // Hold the new lives
485 private List<Boolean> new_lives;
487 public L8onStrips(GLucose glucose) {
490 //Print debug info about the strips.
494 randomizeStripStates();
495 time_since_last_run = 0;
496 any_changes_this_run = false;
497 new_lives = new ArrayList<Boolean>();
499 addParameter(rateParameter);
500 addParameter(randomParameter);
501 addParameter(saturationParameter);
503 addModulator(stripPos).trigger();
506 public void run(double deltaMs) {
508 StripState strip_state;
510 any_changes_this_run = false;
512 time_since_last_run += deltaMs;
514 for (Strip strip : model.strips) {
515 strip_state = this.strip_states.get(i);
517 if(shouldLightStrip(strip_state)) {
518 lightLiveStrip(strip, strip_state, deltaMs);
520 lightDeadStrip(strip, strip_state, deltaMs);
525 if(!any_changes_this_run) {
526 randomizeStripStates();
531 if(time_since_last_run >= rateParameter.getValuef()) {
532 time_since_last_run = 0;
536 public void lightLiveStrip(Strip strip, StripState strip_state, double deltaMs) {
537 Integer index = strip_state.index;
538 float strip_dist = LXUtils.wrapdistf((float) index, stripPos.getValuef(), model.strips.size());
539 float hv = (strip_dist / model.strips.size()) * 360;
540 float bv = strip_state.current_brightness;
542 if(!strip_state.just_changed || deltaMs >= rateParameter.getValuef()) {
543 float bright_prop = min(((float) time_since_last_run / rateParameter.getValuef()), 1.0);
544 bv = min(MAX_ALIVE_BRIGHTNESS, bright_prop * MAX_ALIVE_BRIGHTNESS);
547 print("live prop: " + bright_prop + " bv: " + bv + " current: " + strip_state.current_brightness + "\n");
550 if(strip_state.current_brightness < bv) {
551 strip_state.current_brightness = bv;
553 bv = strip_state.current_brightness;
557 print("live bv: " + bv + " current: " + strip_state.current_brightness + "\n");
561 for (LXPoint p : strip.points) {
562 colors[p.index] = lx.hsb(
564 saturationParameter.getValuef(),
570 public void lightDeadStrip(Strip strip, StripState strip_state, double deltaMs) {
571 Integer index = strip_state.index;
572 float strip_dist = LXUtils.wrapdistf((float) index, stripPos.getValuef(), model.strips.size());
573 float dist_proportion = (strip_dist / (float) model.strips.size());
574 float hv = dist_proportion * 360;
575 float bv = strip_state.current_brightness;
577 if(!strip_state.just_changed || deltaMs >= rateParameter.getValuef()) {
578 float bright_prop = 1.0 - min(((float) time_since_last_run / rateParameter.getValuef()), 1.0);
579 bv = max(0.0, bright_prop * MAX_ALIVE_BRIGHTNESS);
582 print("dead prop: " + bright_prop + " bv: " + bv + " current: " + strip_state.current_brightness + "\n");
585 if(strip_state.current_brightness > bv) {
586 strip_state.current_brightness = bv;
588 bv = strip_state.current_brightness;
592 print("dead bv: " + bv + " current: " + strip_state.current_brightness + "\n");
596 for (LXPoint p : strip.points) {
597 colors[p.index] = lx.hsb(
599 saturationParameter.getValuef(),
605 public void outputStripInfo() {
607 for (Strip strip : model.strips) {
608 print("Strip " + i + ": " + strip.cx + "," + strip.cy + "," + strip.cz + "\n");
613 private void initStripStates() {
614 List<Integer> neighbors;
615 boolean alive = false;
616 float current_brightness;
617 StripState strip_state;
618 this.strip_states = new ArrayList<StripState>();
621 int total_neighbors = 0;
623 for (Strip strip : model.strips) {
624 neighbors = findStripNeighbors(strip, i);
626 current_brightness = 0.0;
627 strip_state = new StripState(i, alive, current_brightness, neighbors);
628 this.strip_states.add(strip_state);
630 total_neighbors += neighbors.size();
634 float average_neighbor_count = (float) total_neighbors / (float) model.strips.size();
635 //print("Average neighbor count: " + average_neighbor_count + "\n");
638 private void randomizeStripStates() {
639 double prob_range = (1.0 - MIN_ALIVE_PROBABILITY) - (1.0 - MAX_ALIVE_PROBABILITY);
640 double prob = MIN_ALIVE_PROBABILITY + (prob_range * Math.random());
642 //print("Randomizing strips! p = " + prob + "\n");
644 for (StripState strip_state : this.strip_states) {
645 strip_state.alive = (Math.random() <= prob);
646 if(strip_state.alive) {
647 strip_state.current_brightness = 0;
649 strip_state.current_brightness = MAX_ALIVE_BRIGHTNESS;
654 public List<Integer> findStripNeighbors(Strip strip, Integer index) {
655 List<Integer> neighbors = new LinkedList<Integer>();
657 int neighbor_count = 0;
658 double distance = 0.0;
660 for (Strip s : model.strips) {
661 if( (int)index != (int)i ) {
662 distance = Math.sqrt( Math.pow((s.cx - strip.cx), 2) + Math.pow((s.cy - strip.cy), 2) + Math.pow((s.cz - strip.cz), 2) );
664 if(distance < ( (double) Cube.EDGE_WIDTH) ) {
665 //print("Strip " + i + " is a neighbor of " + index + "\n");
675 public boolean shouldLightStrip(StripState strip_state) {
676 // Respect rate parameter.
677 if(time_since_last_run < rateParameter.getValuef()) {
678 any_changes_this_run = true;
679 strip_state.just_changed = false;
680 return strip_state.alive;
682 boolean new_life = cycleOfStripperLife(strip_state);
683 new_lives.add(new_life);
688 public void applyNewLives() {
690 for(boolean liveliness: new_lives) {
691 StripState strip_state = this.strip_states.get(index);
692 strip_state.alive = new_lives.get(index);
697 public boolean cycleOfStripperLife(StripState strip_state) {
698 Integer index = strip_state.index;
699 Integer alive_neighbor_count = countLiveNeighbors(strip_state);
700 boolean before_alive = strip_state.alive;
701 boolean after_alive = before_alive;
702 double mutation = Math.random();
704 if(strip_state.alive) {
705 if(alive_neighbor_count < 2 || alive_neighbor_count > 6) {
712 if(alive_neighbor_count == 5) {
719 if(mutation < randomParameter.getValuef()) {
720 after_alive = !after_alive;
723 if(before_alive != after_alive) {
724 any_changes_this_run = true;
725 strip_state.just_changed = true;
731 public Integer countLiveNeighbors(StripState strip_state) {
733 StripState neighbor_strip_state;
735 for(Integer neighbor_index: strip_state.neighbors) {
736 neighbor_strip_state = this.strip_states.get(neighbor_index);
737 if(neighbor_strip_state.alive) {