1 module dminer.core.minetypes;
2
3 alias cell_t = ubyte;
4
5 immutable cell_t NO_CELL = 0;
6 immutable cell_t END_OF_WORLD = 253;
7 immutable cell_t VISITED_CELL = 255;
8 immutable cell_t VISITED_OCCUPIED = 254;
9
10 immutable cell_t BOUND_BOTTOM = 253;
11 immutable cell_t BOUND_SKY = 252;
12
13
14 /*
15 World coordinates
16
17 A UP
18 |
19 | / NORTH
20 | /
21 WEST |/
22 -----------|-----------> EAST
23 /|
24 / |
25 SOUTH/ |
26 L |
27 | DOWN
28 */
29
30 /// World direction
31 enum Dir : ubyte {
32 NORTH = 0, /// z--
33 SOUTH, /// z++
34 EAST, /// x++
35 WEST, /// x--
36 UP, /// y++
37 DOWN, /// y--
38 }
39
40 // 26 direction masks based on Dir
41 enum DirMask : ubyte {
42 MASK_NORTH = (1 << Dir.NORTH),
43 MASK_SOUTH = (1 << Dir.SOUTH),
44 MASK_EAST = (1 << Dir.EAST),
45 MASK_WEST = (1 << Dir.WEST),
46 MASK_UP = (1 << Dir.UP),
47 MASK_DOWN = (1 << Dir.DOWN),
48 MASK_ALL = 0x3F,
49 //MASK_WEST_UP = (1 << Dir.WEST) | MASK_UP,
50 //MASK_EAST_UP = (1 << Dir.EAST) | MASK_UP,
51 //MASK_WEST_DOWN = (1 << Dir.WEST) | MASK_DOWN,
52 //MASK_EAST_DOWN = (1 << Dir.EAST) | MASK_DOWN,
53 //MASK_NORTH_WEST = MASK_NORTH | MASK_WEST,
54 //MASK_NORTH_EAST = MASK_NORTH | MASK_EAST,
55 //MASK_NORTH_UP = MASK_NORTH | MASK_UP,
56 //MASK_NORTH_DOWN = MASK_NORTH | MASK_DOWN,
57 //MASK_NORTH_WEST_UP = MASK_NORTH | MASK_WEST | MASK_UP,
58 //MASK_NORTH_EAST_UP = MASK_NORTH | MASK_EAST | MASK_UP,
59 //MASK_NORTH_WEST_DOWN = MASK_NORTH | MASK_WEST | MASK_DOWN,
60 //MASK_NORTH_EAST_DOWN = MASK_NORTH | MASK_EAST | MASK_DOWN,
61 //MASK_SOUTH_WEST = MASK_SOUTH | MASK_WEST,
62 //MASK_SOUTH_EAST = MASK_SOUTH | MASK_EAST,
63 //MASK_SOUTH_UP = MASK_SOUTH | MASK_UP,
64 //MASK_SOUTH_DOWN = MASK_SOUTH | MASK_DOWN,
65 //MASK_SOUTH_WEST_UP = MASK_SOUTH | MASK_WEST | MASK_UP,
66 //MASK_SOUTH_EAST_UP = MASK_SOUTH | MASK_EAST | MASK_UP,
67 //MASK_SOUTH_WEST_DOWN = MASK_SOUTH | MASK_WEST | MASK_DOWN,
68 //MASK_SOUTH_EAST_DOWN = MASK_SOUTH | MASK_EAST | MASK_DOWN,
69 }
70
71 struct Vector2d {
72 int x;
73 int y;
74 this(int xx, int yy) {
75 x = xx;
76 y = yy;
77 }
78 //bool opEqual(Vector2d v) const {
79 // return x == v.x && y == v.y;
80 //}
81 }
82
83 immutable Vector2d ZERO2 = Vector2d(0, 0);
84
85 /// Integer 3d vector: x,y,z
86 struct Vector3d {
87 /// WEST-EAST
88 int x;
89 /// DOWN-UP
90 int y;
91 /// NORTH-SOUTH
92 int z;
93
94 this(int xx, int yy, int zz) {
95 x = xx;
96 y = yy;
97 z = zz;
98 }
99 //bool opEqual(const Vector3d v) const {
100 // return x == v.x && y == v.y && z == v.z;
101 //}
102
103 /// returns vector with all components which are negative of components for this vector
104 Vector3d opUnary(string op : "-")() const {
105 return Vector3d(-x, -y, -z);
106 }
107 /// subtract vectors
108 Vector3d opBinary(string op : "-")(const Vector3d v) const {
109 return Vector3d(x - v.x, y - v.y, z - v.z);
110 }
111 /// add vectors
112 Vector3d opBinary(string op : "+")(const Vector3d v) const {
113 return Vector3d(x + v.x, y + v.y, z + v.z);
114 }
115 ///
116 int opBinary(string op : "*")(const Vector3d v) const {
117 return x*v.x + y*v.y + z*v.z;
118 }
119 /// multiply vector elements by constant
120 Vector3d opBinary(string op : "*")(int n) const {
121 return Vector3d(x * n, y * n, z * n);
122 }
123 /// divide vector elements by constant
124 Vector3d opBinary(string op : "/")(int n) const {
125 return Vector3d(x / n, y / n, z / n);
126 }
127
128 ///
129 ref Vector3d opOpAssign(string op : "+")(const Vector3d v) {
130 x += v.x;
131 y += v.y;
132 z += v.z;
133 return this;
134 }
135 ///
136 ref Vector3d opOpAssign(string op : "-")(const Vector3d v) {
137 x -= v.x;
138 y -= v.y;
139 z -= v.z;
140 return this;
141 }
142 ///
143 ref Vector3d opOpAssign(string op : "*")(int n) {
144 x *= n;
145 y *= n;
146 z *= n;
147 return this;
148 }
149 Vector3d turnLeft() {
150 return Vector3d(z, y, -x);
151 }
152 Vector3d turnRight() {
153 return Vector3d(-z, y, x);
154 }
155 Vector3d turnUp() {
156 return Vector3d(x, -z, y);
157 }
158 Vector3d turnDown() {
159 return Vector3d(x, z, -y);
160 }
161 Vector3d move(Dir dir) {
162 Vector3d res = this;
163 switch (dir) with(Dir) {
164 case NORTH:
165 res.z--;
166 break;
167 case SOUTH:
168 res.z++;
169 break;
170 case WEST:
171 res.x--;
172 break;
173 case EAST:
174 res.x++;
175 break;
176 case UP:
177 res.y++;
178 break;
179 case DOWN:
180 res.y--;
181 break;
182 default:
183 break;
184 }
185 return res;
186 }
187
188 int dot(ref Vector3d v) {
189 return x * v.x + y * v.y + z * v.z;
190 }
191
192 int squaredLength() {
193 return x*x + y*y + z*z;
194 }
195 }
196
197 __gshared const Vector3d ZERO3 = Vector3d(0, 0, 0);
198
199
200 struct Array(T) {
201 private:
202 int _length;
203 T[] _data;
204 public:
205 T * ptr(int index = 0) {
206 return _data.ptr + index;
207 }
208 void swap(ref Array v) {
209 int tmp;
210 tmp = _length; _length = v._length; v._length = tmp;
211 T[] ptmp;
212 ptmp = _data; _data = v._data; v._data = ptmp;
213 }
214 /// ensure capacity is enough to fit sz items
215 void reserve(int sz) {
216 sz += _length;
217 if (_data.length < sz) {
218 int oldsize = cast(int)_data.length;
219 int newsize = 1024;
220 while (newsize < sz)
221 newsize <<= 1;
222 _data.length = newsize;
223 for (int i = oldsize; i < newsize; i++)
224 _data.ptr[i] = T.init;
225 _data.assumeSafeAppend();
226 }
227 }
228 @property int length() {
229 return _length;
230 }
231 /// append single item by ref
232 void append(ref const T value) {
233 if (_length >= _data.length)
234 reserve(cast(int)(_data.length == 0 ? 64 : _data.length * 2 - _length));
235 _data.ptr[_length++] = value;
236 }
237 /// append single item by value
238 void append(T value) {
239 if (_length >= _data.length)
240 reserve(cast(int)(_data.length == 0 ? 64 : _data.length * 2 - _length));
241 _data.ptr[_length++] = value;
242 }
243 /// append single item w/o check
244 void appendNoCheck(ref const T value) {
245 _data.ptr[_length++] = value;
246 }
247 /// append single item w/o check
248 void appendNoCheck(T value) {
249 _data.ptr[_length++] = value;
250 }
251 /// appends same value several times, return pointer to appended items
252 T* append(ref const T value, int count) {
253 reserve(count);
254 int startLen = _length;
255 for (int i = 0; i < count; i++)
256 _data.ptr[_length++] = value;
257 return _data.ptr + startLen;
258 }
259 /// appends same value several times, return pointer to appended items
260 T* append(T value, int count) {
261 reserve(count);
262 int startLen = _length;
263 for (int i = 0; i < count; i++)
264 _data.ptr[_length++] = value;
265 return _data.ptr + startLen;
266 }
267 void clear() {
268 _length = 0;
269 }
270 T get(int index) {
271 return _data.ptr[index];
272 }
273 void set(int index, T value) {
274 _data.ptr[index] = value;
275 }
276 ref T opIndex(int index) {
277 return _data.ptr[index];
278 }
279 }
280
281 alias FloatArray = Array!(float);
282 alias IntArray = Array!(int);
283 alias CellArray = Array!(cell_t);
284 alias Vector2dArray = Array!(Vector2d);
285 alias Vector3dArray = Array!(Vector3d);
286
287
288
289 struct Position {
290 Vector3d pos;
291 Direction direction;
292 this(ref Position p) {
293 pos = p.pos;
294 direction = p.direction;
295 }
296 this(Vector3d position, Vector3d dir) {
297 pos = position;
298 direction = dir;
299 }
300 //Vector2d calcPlaneCoords(Vector3d v) {
301 // v = v - pos;
302 // switch (direction.dir) with(Dir) {
303 // default:
304 // case NORTH:
305 // return Vector2d(v.x, v.y);
306 // case SOUTH:
307 // return Vector2d(-v.x, v.y);
308 // case EAST:
309 // return Vector2d(v.z, v.y);
310 // case WEST:
311 // return Vector2d(-v.z, v.y);
312 // case UP:
313 // return Vector2d(-v.z, v.x);
314 // case DOWN:
315 // return Vector2d(v.z, v.x);
316 // }
317 //}
318 void turnLeft() {
319 direction.turnLeft();
320 }
321 void turnRight() {
322 direction.turnRight();
323 }
324 void shiftLeft(int step = 1) {
325 pos += direction.left * step;
326 }
327 void shiftRight(int step = 1) {
328 pos += direction.right * step;
329 }
330 void turnUp() {
331 direction.turnUp();
332 }
333 void turnDown() {
334 direction.turnDown();
335 }
336 void forward(int step = 1) {
337 pos += direction.forward * step;
338 }
339 void backward(int step = 1) {
340 pos -= direction.forward * step;
341 }
342 void moveUp(int step = 1) {
343 pos += direction.up * step;
344 }
345 void moveDown(int step = 1) {
346 pos += direction.down * step;
347 }
348 void moveLeft(int step = 1) {
349 pos += direction.left * step;
350 }
351 void moveRight(int step = 1) {
352 pos += direction.right * step;
353 }
354 }
355
356
357 /// returns opposite direction to specified direction
358 Dir opposite(Dir d) {
359 return cast(Dir)(d ^ 1);
360 }
361
362 Dir turnLeft(Dir d) {
363 switch (d) with (Dir) {
364 case WEST:
365 return SOUTH;
366 case EAST:
367 return NORTH;
368 default:
369 case NORTH:
370 return WEST;
371 case SOUTH:
372 return EAST;
373 case UP:
374 return SOUTH;
375 case DOWN:
376 return NORTH;
377 }
378 }
379
380 Dir turnRight(Dir d) {
381 switch (d) with (Dir) {
382 case WEST:
383 return NORTH;
384 case EAST:
385 return SOUTH;
386 default:
387 case NORTH:
388 return EAST;
389 case SOUTH:
390 return WEST;
391 case UP:
392 return NORTH;
393 case DOWN:
394 return SOUTH;
395 }
396 }
397
398 Dir turnUp(Dir d) {
399 switch (d) with (Dir) {
400 case WEST:
401 return UP;
402 case EAST:
403 return UP;
404 default:
405 case NORTH:
406 return UP;
407 case SOUTH:
408 return UP;
409 case UP:
410 return SOUTH;
411 case DOWN:
412 return NORTH;
413 }
414 }
415
416 Dir turnDown(Dir d) {
417 switch (d) with (Dir) {
418 case WEST:
419 return DOWN;
420 case EAST:
421 return DOWN;
422 default:
423 case NORTH:
424 return DOWN;
425 case SOUTH:
426 return DOWN;
427 case UP:
428 return NORTH;
429 case DOWN:
430 return SOUTH;
431 }
432 }
433
434
435 struct Direction {
436 this(int x, int y, int z) {
437 set(x, y, z);
438 }
439 this(Vector3d v) {
440 set(v);
441 }
442 this(Dir d) {
443 set(d);
444 }
445 /// returns Y axis rotation angle in degrees (0, 90, 180, 270)
446 @property float angle() {
447 switch (dir) with (Dir) {
448 default:
449 case NORTH:
450 return 0;
451 case SOUTH:
452 return 180;
453 case WEST:
454 return 90;
455 case EAST:
456 return 270;
457 case UP:
458 case DOWN:
459 return 0;
460 }
461 }
462 /// set by direction code
463 void set(Dir d) {
464 switch (d) with (Dir) {
465 default:
466 case NORTH:
467 set(0, 0, -1);
468 break;
469 case SOUTH:
470 set(0, 0, 1);
471 break;
472 case WEST:
473 set(-1, 0, 0);
474 break;
475 case EAST:
476 set(1, 0, 0);
477 break;
478 case UP:
479 set(0, 1, 0);
480 break;
481 case DOWN:
482 set(0, -1, 0);
483 break;
484 }
485 }
486 /// set by vector
487 void set(Vector3d v) { set(v.x, v.y, v.z); }
488 /// set by vector
489 void set(int x, int y, int z) {
490 forward = Vector3d(x, y, z);
491 if (x) {
492 dir = (x > 0) ? Dir.EAST : Dir.WEST;
493 }
494 else if (y) {
495 dir = (y > 0) ? Dir.UP : Dir.DOWN;
496 }
497 else {
498 dir = (z > 0) ? Dir.SOUTH : Dir.NORTH;
499 }
500 switch (dir) with (Dir) {
501 case UP:
502 up = Vector3d(1, 0, 0);
503 left = Vector3d(0, 0, 1);
504 break;
505 case DOWN:
506 up = Vector3d(1, 0, 0);
507 left = Vector3d(0, 0, -1);
508 break;
509 default:
510 case NORTH:
511 up = Vector3d(0, 1, 0);
512 left = Vector3d(-1, 0, 0);
513 break;
514 case SOUTH:
515 up = Vector3d(0, 1, 0);
516 left = Vector3d(1, 0, 0);
517 break;
518 case EAST:
519 up = Vector3d(0, 1, 0);
520 left = Vector3d(0, 0, -1);
521 break;
522 case WEST:
523 up = Vector3d(0, 1, 0);
524 left = Vector3d(0, 0, 1);
525 break;
526 }
527 down = -up;
528 right = -left;
529 forwardUp = forward + up;
530 forwardDown = forward + down;
531 forwardLeft = forward + left;
532 forwardLeftUp = forward + left + up;
533 forwardLeftDown = forward + left + down;
534 forwardRight = forward + right;
535 forwardRightUp = forward + right + up;
536 forwardRightDown = forward + right + down;
537 }
538
539 void turnLeft() {
540 set(.turnLeft(dir));
541 }
542 void turnRight() {
543 set(.turnRight(dir));
544 }
545 void turnUp() {
546 set(.turnUp(dir));
547 }
548 void turnDown() {
549 set(.turnDown(dir));
550 }
551
552 Dir dir;
553 Vector3d forward;
554 Vector3d up;
555 Vector3d right;
556 Vector3d left;
557 Vector3d down;
558 Vector3d forwardUp;
559 Vector3d forwardDown;
560 Vector3d forwardLeft;
561 Vector3d forwardLeftUp;
562 Vector3d forwardLeftDown;
563 Vector3d forwardRight;
564 Vector3d forwardRightUp;
565 Vector3d forwardRightDown;
566 }
567
568 /// returns number of bits to store integer
569 int bitsFor(int n) {
570 int res;
571 for (res = 0; n > 0; res++)
572 n >>= 1;
573 return res;
574 }
575
576 /// returns 0 for 0, 1 for negatives, 2 for positives
577 int mySign(int n) {
578 if (n > 0)
579 return 1;
580 else if (n < 0)
581 return -1;
582 else
583 return 0;
584 }
585
586 immutable ulong RANDOM_MULTIPLIER = 0x5DEECE66D;
587 immutable ulong RANDOM_MASK = ((cast(ulong)1 << 48) - 1);
588 immutable ulong RANDOM_ADDEND = cast(ulong)0xB;
589
590 struct Random {
591 ulong seed;
592 //Random();
593 void setSeed(ulong value) {
594 seed = (value ^ RANDOM_MULTIPLIER) & RANDOM_MASK;
595 }
596
597 int next(int bits) {
598 seed = (seed * RANDOM_MULTIPLIER + RANDOM_ADDEND) & RANDOM_MASK;
599 return cast(int)(seed >> (48 - bits));
600 }
601
602 int nextInt() {
603 return next(31);
604 }
605 int nextInt(int n) {
606 if ((n & -n) == n) // i.e., n is a power of 2
607 return cast(int)((n * cast(long)next(31)) >> 31);
608 int bits, val;
609 do {
610 bits = next(31);
611 val = bits % n;
612 } while (bits - val + (n - 1) < 0);
613 return val;
614 }
615 }
616
617 __gshared const Vector3d[6] DIRECTION_VECTORS = [
618 Vector3d(0, 0, -1),
619 Vector3d(0, 0, 1),
620 Vector3d(-1, 0, 0),
621 Vector3d(1, 0, 0),
622 Vector3d(0, 1, 0),
623 Vector3d(0, -1, 0)
624 ];
625
626 /// 3d array[+-size, +-size, +-size] of T
627 struct Array3d(T) {
628 int _size;
629 int _sizeBits;
630 T[] _cells;
631 void reset(int size) {
632 if (size == 0) {
633 // just clear storage
634 _cells = null;
635 _size = 0;
636 _sizeBits = 0;
637 return;
638 }
639 _size = size;
640 _sizeBits = bitsFor(size) + 1;
641 int arraySize = 1 << (_sizeBits * 3);
642 if (_cells.length < arraySize)
643 _cells.length = arraySize;
644 foreach(ref cell; _cells)
645 cell = T.init;
646 }
647 ref T opIndex(int x, int y, int z) {
648 int index = (x + _size) + ((y + _size) << _sizeBits) + ((z + _size) << (_sizeBits + _sizeBits));
649 return _cells[index];
650 }
651 T * ptr(int x, int y, int z) {
652 int index = (x + _size) + ((y + _size) << _sizeBits) + ((z + _size) << (_sizeBits + _sizeBits));
653 return &_cells[index];
654 }
655 }
656