View Javadoc
1   package org.woehlke.computer.kurzweil.cyclic.cellular.automaton.model;
2   
3   import org.woehlke.computer.kurzweil.cyclic.cellular.automaton.config.ObjectRegistry;
4   
5   import java.awt.*;
6   import java.io.Serializable;
7   import java.util.Date;
8   import java.util.Random;
9   
10  import static org.woehlke.computer.kurzweil.cyclic.cellular.automaton.model.LatticeNeighbourhood.*;
11  
12  /**
13   * Cyclic Cellular Automaton.
14   * <p>
15   * (C) 2006 - 2022 Thomas Woehlke.
16   * @see <a href="https://java.woehlke.org/cyclic-cellular-automaton">Maven Project Page</a>
17   * @author Thomas Woehlke
18   * <p>
19   * Created with IntelliJ IDEA.
20   * Date: 28.08.13
21   * Time: 12:39
22   */
23  public class CyclicCellularAutomatonLattice implements Serializable {
24  
25      private static final long serialVersionUID = -594681595882016258L;
26  
27      private Random random;
28  
29      private volatile int[][][] lattice;
30      private volatile int source;
31      private volatile int target;
32  
33      private final ObjectRegistry ctx;
34  
35      private volatile LatticeNeighbourhood neighbourhood;
36  
37      public CyclicCellularAutomatonLattice(ObjectRegistry ctx) {
38          this.ctx = ctx;
39          random = new Random(new Date().getTime());
40          startVonNeumann();
41      }
42  
43      private void initCreateLattice() {
44          lattice = new int[2]
45              [(int) this.ctx.getConfig().getLatticeDimensions().getX()]
46              [(int) this.ctx.getConfig().getLatticeDimensions().getY()];
47          source = 0;
48          target = 1;
49      }
50  
51      private void initFillLatticeByRandom() {
52          for (int y = 0; y < this.ctx.getConfig().getLatticeDimensions().getY(); y++) {
53              for (int x = 0; x < this.ctx.getConfig().getLatticeDimensions().getX(); x++) {
54                  lattice[source][x][y] = random.nextInt(ctx.getColorScheme().getMaxState());
55              }
56          }
57      }
58  
59      public synchronized void step() {
60          //System.out.print(".");
61          Point worldDimensions = this.ctx.getConfig().getLatticeDimensions();
62          for (int y = 0; y < worldDimensions.getY(); y++) {
63              for (int x = 0; x < worldDimensions.getX(); x++) {
64                  lattice[target][x][y] = lattice[source][x][y];
65                  int nextState = (lattice[source][x][y] + 1) % ctx.getColorScheme().getMaxState();
66                  int west = (int) ((x - 1 + worldDimensions.getX()) % worldDimensions.getX());
67                  int north = (int) ((y - 1 + worldDimensions.getY()) % worldDimensions.getY());
68                  int east = (int) ((x + 1 + worldDimensions.getX()) % worldDimensions.getX());
69                  int south = (int) ((y + 1 + worldDimensions.getY()) % worldDimensions.getY());
70                  if (neighbourhood == MOORE_NEIGHBORHOOD || neighbourhood == WOEHLKE_NEIGHBORHOOD) {
71                      //North-West
72                      if (nextState == lattice[source][west][north]) {
73                          lattice[target][x][y] = nextState;
74                          continue;
75                      }
76                      //North-East
77                      if (nextState == lattice[source][east][north]) {
78                          lattice[target][x][y] = nextState;
79                          continue;
80                      }
81                      if (neighbourhood == MOORE_NEIGHBORHOOD) {
82                          //South-East
83                          if (nextState == lattice[source][east][south]) {
84                              lattice[target][x][y] = nextState;
85                              continue;
86                          }
87                      }
88                      //SouthWest
89                      if (nextState == lattice[source][west][south]) {
90                          lattice[target][x][y] = nextState;
91                          continue;
92                      }
93                  }
94                  //North
95                  if (nextState == lattice[source][x][north]
96                  ) {
97                      lattice[target][x][y] = nextState;
98                      continue;
99                  }
100                 //East
101                 if (nextState == lattice[source][east][y]) {
102                     lattice[target][x][y] = nextState;
103                     continue;
104                 }
105                 if (neighbourhood == MOORE_NEIGHBORHOOD || neighbourhood == VON_NEUMANN_NEIGHBORHOOD) {
106                     //South
107                     if (nextState == lattice[source][x][south]) {
108                         lattice[target][x][y] = nextState;
109                         continue;
110                     }
111                 }
112                 //West
113                 if (nextState == lattice[source][west][y]) {
114                     lattice[target][x][y] = nextState;
115                 }
116             }
117         }
118         this.source = (this.source + 1) % 2;
119         this.target = (this.target + 1) % 2;
120     }
121 
122     public int getCellStatusFor(int x, int y) {
123         return this.lattice[source][x][y];
124     }
125 
126     public synchronized void startVonNeumann() {
127         initCreateLattice();
128         initFillLatticeByRandom();
129         this.neighbourhood = VON_NEUMANN_NEIGHBORHOOD;
130     }
131 
132     public synchronized void startMoore() {
133         initCreateLattice();
134         initFillLatticeByRandom();
135         this.neighbourhood = MOORE_NEIGHBORHOOD;
136     }
137 
138     public synchronized void startWoehlke() {
139         initCreateLattice();
140         initFillLatticeByRandom();
141         this.neighbourhood = WOEHLKE_NEIGHBORHOOD;
142     }
143 }