New LX fixes FlashEffect bug
[SugarCubes.git] / L8onWallace.pde
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);
8
9 public final double MIN_ALIVE_PROBABILITY = 0.2;
10 public final double MAX_ALIVE_PROBABILITY = 0.9;
11
12 public final float MAX_ALIVE_BRIGHTNESS = 90.0;
13
14 private final SawLFO cubePos = new SawLFO(0, model.cubes.size(), 4000);
15
16 class CubeState {
17 // Index of cube in glucose.model.cubes
18 public Integer index;
19 // Boolean which describes if cube is alive.
20 public boolean alive;
21 // Boolean which describes if strip was just changed;
22 public boolean just_changed;
23 // Current brightness
24 public float current_brightness;
25 // List of this cubes neighbors
26 public List<Integer> neighbors;
27
28 public CubeState(Integer index, boolean alive, float current_brightness, List<Integer> neighbors) {
29 this.index = index;
30 this.alive = alive;
31 this.current_brightness = current_brightness;
32 this.neighbors = neighbors;
33 }
34 }
35
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;
42 // Hold the new lives
43 private List<Boolean> new_lives;
44
45 public L8onLife(LX lx) {
46 super(lx);
47
48 //Print debug info about the cubes.
49 //outputCubeInfo();
50
51 initCubeStates();
52 time_since_last_run = 0;
53 any_changes_this_run = false;
54 new_lives = new ArrayList<Boolean>();
55
56 addParameter(rateParameter);
57 addParameter(mutationParameter);
58 addParameter(saturationParameter);
59 addModulator(cubePos).trigger();
60 }
61
62 public void run(double deltaMs) {
63 Integer i = 0;
64 CubeState cube_state;
65
66 any_changes_this_run = false;
67 new_lives.clear();
68 time_since_last_run += deltaMs;
69
70 for (Cube cube : model.cubes) {
71 cube_state = this.cube_states.get(i);
72
73 if(shouldLightCube(cube_state)) {
74 lightLiveCube(cube, cube_state, deltaMs);
75 } else {
76 lightDeadCube(cube, cube_state, deltaMs);
77 }
78
79 i++;
80 }
81
82 if(!any_changes_this_run) {
83 randomizeCubeStates();
84 } else {
85 applyNewLives();
86 }
87
88 if(time_since_last_run >= rateParameter.getValuef()) {
89 time_since_last_run = 0;
90 }
91 }
92
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;
97
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);
101
102 if(cube_state.current_brightness < bv) {
103 cube_state.current_brightness = bv;
104 } else {
105 bv = cube_state.current_brightness;
106 }
107 }
108
109 for (LXPoint p : cube.points) {
110 colors[p.index] = lx.hsb(
111 hv,
112 saturationParameter.getValuef(),
113 bv
114 );
115 }
116 }
117
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;
122
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);
126
127 if(cube_state.current_brightness > bv) {
128 cube_state.current_brightness = bv;
129 } else {
130 bv = cube_state.current_brightness;
131 }
132 }
133
134 for (LXPoint p : cube.points) {
135 colors[p.index] = lx.hsb(
136 hv,
137 saturationParameter.getValuef(),
138 bv
139 );
140 }
141 }
142
143 public void outputCubeInfo() {
144 int i = 0;
145 for (Cube c : model.cubes) {
146 print("Cube " + i + ": " + c.x + "," + c.y + "," + c.z + "\n");
147 ++i;
148 }
149 print("Edgeheight: " + Cube.EDGE_HEIGHT + "\n");
150 print("Edgewidth: " + Cube.EDGE_WIDTH + "\n");
151 print("Channelwidth: " + Cube.CHANNEL_WIDTH + "\n");
152 }
153
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;
160 Integer i = 0;
161
162 for (Cube c : model.cubes) {
163 neighbors = findCubeNeighbors(c, i);
164 alive = true;
165 cube_state = new CubeState(i, alive, current_brightness, neighbors);
166 this.cube_states.add(cube_state);
167 ++i;
168 }
169 }
170
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());
174
175 //print("Randomizing cubes! p = " + prob + "\n");
176
177 for (CubeState cube_state: this.cube_states) {
178 cube_state.alive = (Math.random() <= prob);
179 }
180 }
181
182 public List<Integer> findCubeNeighbors(Cube cube, Integer index) {
183 List<Integer> neighbors = new LinkedList<Integer>();
184 Integer i = 0;
185
186 for (Cube c : model.cubes) {
187 if(index != i) {
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");
190 neighbors.add(i);
191 }
192 }
193
194 i++;
195 }
196
197 return neighbors;
198 }
199
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;
206 } else {
207 boolean new_life = cycleOfLife(cube_state);
208 new_lives.add(new_life);
209 return new_life;
210 }
211 }
212
213 public void applyNewLives() {
214 int index = 0;
215 for(boolean liveliness: new_lives) {
216 CubeState cube_state = this.cube_states.get(index);
217 cube_state.alive = new_lives.get(index);
218 index++;
219 }
220 }
221
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();
228
229 if(cube_state.alive) {
230 if(alive_neighbor_count < 2 || alive_neighbor_count > 3) {
231 after_alive = false;
232 } else {
233 after_alive = true;
234 }
235
236 } else {
237 if(alive_neighbor_count == 2) {
238 after_alive = true;
239 } else {
240 after_alive = false;
241 }
242 }
243
244 if(mutation <= mutationParameter.getValuef()) {
245 after_alive = !after_alive;
246 }
247
248 if(before_alive != after_alive) {
249 cube_state.just_changed = true;
250 any_changes_this_run = true;
251 }
252
253 return after_alive;
254 }
255
256 public Integer countLiveNeighbors(CubeState cube_state) {
257 Integer count = 0;
258 CubeState neighbor_cube_state;
259
260 for(Integer neighbor_index: cube_state.neighbors) {
261 neighbor_cube_state = this.cube_states.get(neighbor_index);
262 if(neighbor_cube_state.alive) {
263 count++;
264 }
265 }
266
267 return count;
268 }
269 }
270
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);
278
279 private final SawLFO pointPos = new SawLFO(0, model.points.size(), 8000);
280
281 public final double MIN_ALIVE_PROBABILITY = 0.2;
282 public final double MAX_ALIVE_PROBABILITY = 0.9;
283
284 public final float MAX_ALIVE_BRIGHTNESS = 90.0;
285
286 class PointState {
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;
295
296 public PointState(Integer index, boolean alive, float current_brightness) {
297 this.index = index;
298 this.alive = alive;
299 this.current_brightness = current_brightness;
300 this.just_changed = false;
301 }
302 }
303
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;
312
313 public L8onAutomata(LX lx) {
314 super(lx);
315
316 //Print debug info about the cubes.
317 //outputCubeInfo();
318
319 initPointStates();
320 randomizePointStates();
321 time_since_last_run = 0;
322 any_changes_this_run = false;
323 new_states = new ArrayList<Boolean>();
324
325 addParameter(mutationParameter);
326 addParameter(rateParameter);
327 addParameter(saturationParameter);
328 addModulator(pointPos).trigger();
329 }
330
331 private void initPointStates() {
332 boolean alive = true;
333 PointState point_state;
334 this.point_states = new ArrayList<PointState>();
335 Integer i = 0;
336 float current_brightness = 0.0;
337
338 for (LXPoint p : model.points) {
339 point_state = new PointState(i, alive, current_brightness);
340 this.point_states.add(point_state);
341 ++i;
342 }
343 }
344
345 public void run(double deltaMs) {
346 Integer i = 0;
347 PointState point_state;
348
349 any_changes_this_run = false;
350 new_states.clear();
351 time_since_last_run += deltaMs;
352
353 for (LXPoint p : model.points) {
354 point_state = this.point_states.get(i);
355
356 if(shouldLightPoint(point_state)) {
357 lightLivePoint(p, point_state, deltaMs);
358 } else {
359 lightDeadPoint(p, point_state, deltaMs);
360 }
361 i++;
362 }
363
364 if(!any_changes_this_run) {
365 randomizePointStates();
366 } else {
367 applyNewStates();
368 }
369
370 if(time_since_last_run >= rateParameter.getValuef()) {
371 time_since_last_run = 0;
372 }
373 }
374
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;
379
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);
383
384 if(point_state.current_brightness < bv) {
385 point_state.current_brightness = bv;
386 } else {
387 bv = point_state.current_brightness;
388 }
389 }
390
391 colors[p.index] = lx.hsb(
392 hv,
393 saturationParameter.getValuef(),
394 bv
395 );
396 }
397
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;
402
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);
406
407 if(point_state.current_brightness > bv) {
408 point_state.current_brightness = bv;
409 } else {
410 bv = point_state.current_brightness;
411 }
412 }
413
414 colors[p.index] = lx.hsb(
415 hv,
416 saturationParameter.getValuef(),
417 bv
418 );
419 }
420
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;
427 } else {
428 boolean new_state = cycleOfAutomata(point_state);
429 new_states.add(new_state);
430 return new_state;
431 }
432 }
433
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();
440
441 if(point_state.alive) {
442 if(alive_neighbor_count == 1) {
443 after_alive = true;
444 } else {
445 after_alive = false;
446 }
447
448 } else {
449 if(alive_neighbor_count == 1) {
450 after_alive = true;
451 } else {
452 after_alive = false;
453 }
454 }
455
456 if(mutation < mutationParameter.getValuef()) {
457 after_alive = !after_alive;
458 }
459
460 if(before_alive != after_alive) {
461 any_changes_this_run = true;
462 point_state.just_changed = true;
463 }
464
465 return after_alive;
466 }
467
468 public int countLiveNeighbors(PointState point_state) {
469 int count = 0;
470
471 if (point_state.index > 0) {
472 PointState before_neighbor = point_states.get(point_state.index - 1);
473 if(before_neighbor.alive) {
474 count++;
475 }
476 }
477
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) {
481 count++;
482 }
483 }
484
485 return count;
486 }
487
488 private void applyNewStates() {
489 int index = 0;
490 for(boolean new_state: new_states) {
491 PointState point_state = this.point_states.get(index);
492 point_state.alive = new_states.get(index);
493 index++;
494 }
495 }
496
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());
500
501 //print("Randomizing points! p = " + prob + "\n");
502
503 for (PointState point_state: this.point_states) {
504 point_state.alive = (Math.random() <= prob);
505 point_state.just_changed = true;
506 }
507 }
508 }
509
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);
517
518 public final double MIN_ALIVE_PROBABILITY = 0.4;
519 public final double MAX_ALIVE_PROBABILITY = 0.9;
520
521 public final float MAX_ALIVE_BRIGHTNESS = 90.0;
522
523 private final SawLFO stripPos = new SawLFO(0, model.strips.size(), 8000);
524
525 class StripState {
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;
536
537 public StripState(Integer index, boolean alive, float current_brightness, List<Integer> neighbors) {
538 this.index = index;
539 this.alive = alive;
540 this.current_brightness = current_brightness;
541 this.neighbors = neighbors;
542 this.just_changed = false;
543 }
544 }
545
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;
554
555 public L8onStripLife(LX lx) {
556 super(lx);
557
558 //Print debug info about the strips.
559 //outputStripInfo();
560
561 initStripStates();
562 randomizeStripStates();
563 time_since_last_run = 0;
564 any_changes_this_run = false;
565 new_lives = new ArrayList<Boolean>();
566
567 addParameter(rateParameter);
568 addParameter(mutationParameter);
569 addParameter(saturationParameter);
570
571 addModulator(stripPos).trigger();
572 }
573
574 public void run(double deltaMs) {
575 Integer i = 0;
576 StripState strip_state;
577
578 any_changes_this_run = false;
579 new_lives.clear();
580 time_since_last_run += deltaMs;
581
582 for (Strip strip : model.strips) {
583 strip_state = this.strip_states.get(i);
584
585 if(shouldLightStrip(strip_state)) {
586 lightLiveStrip(strip, strip_state, deltaMs);
587 } else {
588 lightDeadStrip(strip, strip_state, deltaMs);
589 }
590 i++;
591 }
592
593 if(!any_changes_this_run) {
594 randomizeStripStates();
595 } else {
596 applyNewLives();
597 }
598
599 if(time_since_last_run >= rateParameter.getValuef()) {
600 time_since_last_run = 0;
601 }
602 }
603
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;
608
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);
612
613 if(strip_state.current_brightness < bv) {
614 strip_state.current_brightness = bv;
615 } else {
616 bv = strip_state.current_brightness;
617 }
618 }
619
620 for (LXPoint p : strip.points) {
621 colors[p.index] = lx.hsb(
622 hv,
623 saturationParameter.getValuef(),
624 bv
625 );
626 }
627 }
628
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;
633
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);
637
638 if(strip_state.current_brightness > bv) {
639 strip_state.current_brightness = bv;
640 } else {
641 bv = strip_state.current_brightness;
642 }
643 }
644
645 for (LXPoint p : strip.points) {
646 colors[p.index] = lx.hsb(
647 hv,
648 saturationParameter.getValuef(),
649 bv
650 );
651 }
652 }
653
654 public void outputStripInfo() {
655 int i = 0;
656 for (Strip strip : model.strips) {
657 print("Strip " + i + ": " + strip.cx + "," + strip.cy + "," + strip.cz + "\n");
658 ++i;
659 }
660 }
661
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>();
668 Integer i = 0;
669
670 int total_neighbors = 0;
671
672 for (Strip strip : model.strips) {
673 neighbors = findStripNeighbors(strip, i);
674 alive = true;
675 strip_state = new StripState(i, alive, current_brightness, neighbors);
676 this.strip_states.add(strip_state);
677
678 total_neighbors += neighbors.size();
679 ++i;
680 }
681
682 float average_neighbor_count = (float) total_neighbors / (float) model.strips.size();
683 //print("Average neighbor count: " + average_neighbor_count + "\n");
684 }
685
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());
689
690 //print("Randomizing strips! p = " + prob + "\n");
691
692 for (StripState strip_state : this.strip_states) {
693 strip_state.alive = (Math.random() <= prob);
694 strip_state.just_changed = true;
695 }
696 }
697
698 public List<Integer> findStripNeighbors(Strip strip, Integer index) {
699 List<Integer> neighbors = new LinkedList<Integer>();
700 Integer i = 0;
701 int neighbor_count = 0;
702 double distance = 0.0;
703
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) );
707
708 if(distance < ( (double) Cube.EDGE_WIDTH) ) {
709 //print("Strip " + i + " is a neighbor of " + index + "\n");
710 neighbors.add(i);
711 }
712 }
713 i++;
714 }
715
716 return neighbors;
717 }
718
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;
725 } else {
726 boolean new_life = cycleOfStripperLife(strip_state);
727 new_lives.add(new_life);
728 return new_life;
729 }
730 }
731
732 public void applyNewLives() {
733 int index = 0;
734 for(boolean liveliness: new_lives) {
735 StripState strip_state = this.strip_states.get(index);
736 strip_state.alive = new_lives.get(index);
737 index++;
738 }
739 }
740
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();
746
747 if(strip_state.alive) {
748 if(alive_neighbor_count < 2 || alive_neighbor_count > 6) {
749 after_alive = false;
750 } else {
751 after_alive = true;
752 }
753
754 } else {
755 if(alive_neighbor_count == 5) {
756 after_alive = true;
757 } else {
758 after_alive = false;
759 }
760 }
761
762 if(mutation < mutationParameter.getValuef()) {
763 after_alive = !after_alive;
764 }
765
766 if(before_alive != after_alive) {
767 any_changes_this_run = true;
768 strip_state.just_changed = true;
769 }
770
771 return after_alive;
772 }
773
774 public Integer countLiveNeighbors(StripState strip_state) {
775 Integer count = 0;
776 StripState neighbor_strip_state;
777
778 for(Integer neighbor_index: strip_state.neighbors) {
779 neighbor_strip_state = this.strip_states.get(neighbor_index);
780 if(neighbor_strip_state.alive) {
781 count++;
782 }
783 }
784
785 return count;
786 }
787 }