View Javadoc
1   package org.woehlke.computer.kurzweil.tabs.cca;
2   
3   import lombok.Getter;
4   import lombok.extern.log4j.Log4j2;
5   import org.woehlke.computer.kurzweil.commons.model.LatticeNeighbourhoodType;
6   import org.woehlke.computer.kurzweil.commons.model.LatticePointNeighbourhoodPosition;
7   import org.woehlke.computer.kurzweil.commons.tabs.TabModel;
8   import org.woehlke.computer.kurzweil.tabs.cca.canvas.CyclicCellularAutomatonColorScheme;
9   
10  import java.util.Random;
11  import java.util.concurrent.ForkJoinTask;
12  
13  import static org.woehlke.computer.kurzweil.commons.model.LatticeNeighbourhoodType.*;
14  
15  @Log4j2
16  @Getter
17  public class CyclicCellularAutomatonModel extends ForkJoinTask<Void> implements TabModel {
18  
19      private final CyclicCellularAutomatonContext tabCtx;
20  
21      private volatile int[][][] lattice;
22      private volatile int source;
23      private volatile int target;
24      private volatile LatticeNeighbourhoodType neighbourhoodType;
25      private Boolean running;
26  
27      private final CyclicCellularAutomatonColorScheme colorScheme;
28      private final int versions;
29      private final static int startX = 0;
30      private final static int startY = 0;
31      private final int worldX;
32      private final int worldY;
33  
34      public CyclicCellularAutomatonModel(CyclicCellularAutomatonContext tabCtx) {
35          this.tabCtx = tabCtx;
36          this.worldX = this.tabCtx.getCtx().getWorldDimensions().getX();
37          this.worldY = this.tabCtx.getCtx().getWorldDimensions().getY();
38          this.colorScheme = new CyclicCellularAutomatonColorScheme();
39          this.versions = 2;
40          this.startWithNeighbourhoodVonNeumann();
41          this.resetLattice();
42          this.running = Boolean.FALSE;
43      }
44  
45      @Override
46      protected boolean exec() {
47          boolean doIt = false;
48          synchronized (running) {
49              doIt = running.booleanValue();
50          }
51          if(doIt){
52              //log.info("step");
53              int maxState = colorScheme.getMaxState();
54              int xx;
55              int yy;
56              int nextState;
57              int y;
58              int x;
59              int i;
60              for (y = 0; y < worldY; y++) {
61                  for (x = 0; x < worldX; x++) {
62                      lattice[target][x][y] = lattice[source][x][y];
63                      nextState = (lattice[source][x][y] + 1) % maxState;
64                      LatticePointNeighbourhoodPosition[] pos = LatticePointNeighbourhoodPosition.getNeighbourhoodFor(neighbourhoodType);
65                      for (i = 0; i < pos.length; i++) {
66                          xx = ((x + pos[i].getX() + worldX) % worldX);
67                          yy = ((y + pos[i].getY() + worldY) % worldY);
68                          if (nextState == lattice[source][xx][yy]) {
69                              lattice[target][x][y] = nextState;
70                              i = pos.length;
71                          }
72                      }
73                  }
74              }
75              this.source = (this.source + 1) % 2;
76              this.target = (this.target + 1) % 2;
77              //log.info("stepped");
78          }
79          return true;
80      }
81  
82  
83      private void initCreateLattice(){
84          log.info("initCreateLattice start: "+neighbourhoodType.name());
85          lattice = new int[versions][worldX][worldY];
86          source = 0;
87          target = 1;
88          log.info("initCreateLattice finished: "+neighbourhoodType.name());
89      }
90  
91      private void initFillLattice(){
92          log.info("initCreateLattice start: "+neighbourhoodType.name());
93          Random random = this.tabCtx.getCtx().getRandom();
94          int maxState = this.colorScheme.getMaxState();
95          int y;
96          int x;
97          for (y = 0; y < worldY; y++) {
98              for (x = 0; x < worldX; x++) {
99                  lattice[source][x][y] = random.nextInt(maxState);
100             }
101         }
102         log.info("initCreateLattice finished: "+neighbourhoodType.name());
103     }
104 
105     public void resetLattice(){
106         initCreateLattice();
107         initFillLattice();
108     }
109 
110     public void startWithNeighbourhoodVonNeumann() {
111         if( this.neighbourhoodType == null) {
112             log.info("startWithNeighbourhoodVonNeumann");
113         } else {
114             log.info("startWithNeighbourhoodVonNeumann: " + neighbourhoodType.name());
115         }
116         this.neighbourhoodType=VON_NEUMANN_NEIGHBORHOOD;
117         resetLattice();
118         log.info("startWithNeighbourhoodVonNeumann started: "+neighbourhoodType.name());
119     }
120 
121     public void startWithNeighbourhoodMoore() {
122         log.info("startWithNeighbourhoodVonNeumann: "+neighbourhoodType.name());
123         this.neighbourhoodType=MOORE_NEIGHBORHOOD;
124         resetLattice();
125         log.info("startWithNeighbourhoodVonNeumann started: "+neighbourhoodType.name());
126     }
127 
128     public void startWithNeighbourhoodWoehlke() {
129         //log.info("startWithNeighbourhoodVonNeumann: "+neighbourhoodType.name());
130         this.neighbourhoodType=WOEHLKE_NEIGHBORHOOD;
131         resetLattice();
132         log.info("startWithNeighbourhoodVonNeumann started: "+neighbourhoodType.name());
133     }
134 
135 
136     @Override
137     public Void getRawResult() {
138         return null;
139     }
140 
141     @Override
142     protected void setRawResult(Void value) {}
143 
144 
145     public void start() {
146         log.info("start");
147         synchronized (running) {
148             running = Boolean.TRUE;
149         }
150         log.info("started "+this.toString());
151     }
152 
153     public void stop() {
154         log.info("stop");
155         synchronized (running) {
156             running = Boolean.FALSE;
157         }
158         log.info("stopped "+this.toString());
159     }
160 
161     public int getState(int x, int y) {
162         return lattice[source][x][y];
163     }
164 }