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