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 }