1 module caLib.lattices.OneDimDenseLattice;
2 
3 import caLib_abstract.neighbourhood : isNeighbourhood;
4 import caLib_abstract.util : formatBehaviour;
5 
6 import caLib_util.misc : mod;
7 import std.algorithm.searching : canFind;
8 
9 
10 
11 auto create_OneDimDenseLattice(Ct, Nt)(int width, Nt* neighbourhood)
12 if(isNeighbourhood!(Nt, 1))
13 in
14 {
15     assert(width > 0);
16     assert(neighbourhood !is null);
17 }
18 body
19 {
20     return create_OneDimDenseLattice(width, neighbourhood, 0, 0);
21 }
22 
23 
24 
25 auto create_OneDimDenseLattice(Ct, Nt)(int width, Nt* neighbourhood,
26     Ct emptyCellState, Ct initialCondition)
27 if(isNeighbourhood!(Nt, 1))
28 in
29 {
30     assert(width > 0); 
31     assert(neighbourhood !is null);
32 }
33 body
34 {
35     return create_OneDimDenseLattice(width, neighbourhood, emptyCellState,
36     	(int x) { return initialCondition; });
37 }
38 
39 
40 
41 auto create_OneDimDenseLattice(Ct, Nt)(int width, Nt* neighbourhood,
42     Ct emptyCellState, Ct delegate(int x) initialCondition)
43 if(isNeighbourhood!(Nt, 1))
44 in
45 {
46     assert(width > 0);
47     assert(neighbourhood !is null);
48 }
49 body
50 {
51     return new OneDimDenseLattice!(Ct, Nt)(width, neighbourhood,
52         emptyCellState, initialCondition);
53 }
54 
55 
56 
57 struct OneDimDenseLattice(Ct, Nt) if(isNeighbourhood!(Nt, 1))
58 {
59 
60 private:
61 
62 	Nt* neighbourhood;
63 
64 	int width;
65 
66 	Ct[] a, b;
67 	Ct[]* lattice, latticeNextGen;
68 
69 	Ct emptyCellState;
70 
71 public:
72 
73 	alias CellStateType = Ct;
74 	alias NeighbourhoodType = Nt;
75 	enum uint Dimension = 1;
76 
77 	this(int width, Nt* neighbourhood, Ct emptyCellState,
78 		Ct delegate(int x) initialCondition)
79 	in
80 	{
81 		assert(width > 0);
82 		assert(neighbourhood !is null);
83 	}
84 	body
85 	{
86 		this.width = width;
87 
88         this.neighbourhood = neighbourhood;
89 
90         this.emptyCellState = emptyCellState;
91 
92         a.length = width;
93         b.length = width;
94         lattice = &a;
95         latticeNextGen = &b;
96 
97         foreach(col; 0 .. width)
98         {
99             lattice[0][col] = initialCondition(col);
100         }
101 	}
102 
103 
104 
105 	Ct get(string behaviour)(int x)
106     {
107         immutable string[] behaviour = formatBehaviour!behaviour;
108 
109         static if(behaviour[0] == "torus")
110         {
111             return lattice[0].ptr[mod(x, width)];
112         }
113         else static if(behaviour[0] == "bounded" 
114         	&& behaviour.canFind("assumeInBounds"))
115         {
116             return lattice[0].ptr[x];
117         }
118         else static if(behaviour[0] == "bounded")
119         {
120             if(x >= 0 && x < width)
121             {
122                 return lattice[0].ptr[x];
123             }
124             else
125             {
126                 return emptyCellState;
127             }
128         }
129         else static if(behaviour[0] == "_test")
130         {
131             return Ct.init;
132         }
133         else
134         {
135             static assert(0, "OneDimDenseLattice get method dosen't have a \""
136                 ~ behaviour ~"\" behaviour");
137         }
138     }
139 
140 
141 
142     Ct get(int x)
143     {
144         return get!"bounded"(x);
145     }
146 
147 
148 
149     void set(string behaviour)(int x, Ct newValue)
150     {
151         immutable string[] behaviour = formatBehaviour!behaviour;
152 
153         static if(behaviour.canFind("instant")) {
154             alias latticeToChange = lattice;
155         } else {
156             alias latticeToChange = latticeNextGen;
157         }
158 
159         static if(behaviour[0] == "torus")
160         {
161             latticeToChange[0].ptr[mod(x, width)] = newValue;
162         }
163         else static if(behaviour[0] == "bounded"
164             && behaviour.canFind("assumeInBounds"))
165         {
166             latticeToChange[0].ptr[x] = newValue;
167         }
168         else static if(behaviour[0] == "bounded")
169         {
170             if(x >= 0 && x < width)
171             {
172                 latticeToChange[0].ptr[x] = newValue;
173             }
174         }
175         else static if(behaviour[0] == "_test")
176         {
177 
178         }
179         else
180         {
181             static assert(0, "OneDimDenseLattice set method dosen't have a \""
182                 ~ behaviour ~"\" behaviour");
183         }
184     }
185 
186 
187 
188     void set(int x, Ct newValue)
189     {
190         set!"bounded"(x, newValue);
191     }
192 
193 
194 
195     Ct[] getNeighbours(string behaviour)(int x)
196     {
197         enum string behaviourString = behaviour;
198         immutable string[] behaviour = formatBehaviour!behaviour;
199 
200         static if(behaviour[0] == "torus"
201                || behaviour[0] == "bounded")
202         {
203             Ct[] neighbours;
204             foreach(coord ; neighbourhood.getNeighboursCoordinates(x))
205             {
206                 neighbours ~= [get!behaviourString(coord[0])];
207             }
208             return neighbours;
209         }
210         else static if(behaviour[0] == "_test")
211         {
212             return Ct[].init;
213         }
214         else
215         {
216             static assert(0, "OneDimDenseLattice getNeighbours method dosen't" 
217                 ~ "have a \"" ~ behaviour ~ "\" behaviour");
218         }
219     }
220 
221 
222 
223     Ct[] getNeighbours(int x)
224     {
225         return getNeighbours!"bounded"(x);
226     }
227 
228 
229 
230     void iterate(string behaviour)(Ct delegate(Ct cellState, Ct[] neighbours,
231         int x) rule)
232     {
233         immutable string[] behaviour = formatBehaviour!behaviour;
234 
235         static if(behaviour[0] == "all")
236         {
237             foreach(x; 0 .. width)
238             {
239                 set(x, rule(get(x), getNeighbours(x), x));
240             }
241         }
242         else static if(behaviour[0] == "_test")
243         {
244 
245         }
246         else
247         {
248             static assert(0, "OneDimDenseLattice iterate method dosen't have a"
249                 ~ "\"" ~ behaviour ~"\" behaviour");
250         }
251     }
252 
253 
254 
255     void iterate(Ct delegate(Ct cellState, Ct[] neighbours,
256         int x) rule)
257     {
258         iterate!"all"(rule);
259     }
260 
261 
262 
263     void nextGen(string behaviour)()
264     {
265         immutable string[] behaviour = formatBehaviour!behaviour;
266 
267         static if(behaviour[0] == "correct")
268         {
269             Ct[]* tmp = lattice;
270             lattice = latticeNextGen;
271             latticeNextGen = tmp;
272 
273             foreach(i; 0 .. width)
274             {
275                 latticeNextGen[0].ptr[i] = emptyCellState;
276             }
277         }
278         else static if(behaviour[0] == "toggle")
279         {
280             lattice[0] = latticeNextGen[0].dup;
281         }
282         else static if(behaviour[0] == "flipp")
283         {
284             Ct[]* tmp = lattice;
285             lattice = latticeNextGen;
286             latticeNextGen = tmp;
287         }
288         else static if(behaviour[0] == "nothing")
289         {}
290         else static if(behaviour[0] == "_test")
291         {}
292         else
293         {
294             static assert(0, "OneDimDenseLattice nextGen method dosen't have a"
295                 ~ "\"" ~ behaviour ~"\" behaviour");
296         }
297     }
298 
299     void nextGen()
300     {
301         nextGen!"correct"();
302     }
303 
304     int[1] getLatticeBounds()
305     out(result)
306     {
307         assert(result[0] > 0);
308     }
309     body
310     {
311         return [width];
312     }
313 }