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 124 /// 125 ref Vector3d opOpAssign(string op : "+")(const Vector3d v) { 126 x += v.x; 127 y += v.y; 128 z += v.z; 129 return this; 130 } 131 /// 132 ref Vector3d opOpAssign(string op : "-")(const Vector3d v) { 133 x -= v.x; 134 y -= v.y; 135 z -= v.z; 136 return this; 137 } 138 /// 139 ref Vector3d opOpAssign(string op : "*")(int n) { 140 x *= n; 141 y *= n; 142 z *= n; 143 return this; 144 } 145 Vector3d turnLeft() { 146 return Vector3d(z, y, -x); 147 } 148 Vector3d turnRight() { 149 return Vector3d(-z, y, x); 150 } 151 Vector3d turnUp() { 152 return Vector3d(x, -z, y); 153 } 154 Vector3d turnDown() { 155 return Vector3d(x, z, -y); 156 } 157 Vector3d move(Dir dir) { 158 Vector3d res = this; 159 switch (dir) with(Dir) { 160 case NORTH: 161 res.z--; 162 break; 163 case SOUTH: 164 res.z++; 165 break; 166 case WEST: 167 res.x--; 168 break; 169 case EAST: 170 res.x++; 171 break; 172 case UP: 173 res.y++; 174 break; 175 case DOWN: 176 res.y--; 177 break; 178 default: 179 break; 180 } 181 return res; 182 } 183 184 int dot(ref Vector3d v) { 185 return x * v.x + y * v.y + z * v.z; 186 } 187 188 int squaredLength() { 189 return x*x + y*y + z*z; 190 } 191 } 192 193 __gshared const Vector3d ZERO3 = Vector3d(0, 0, 0); 194 195 196 struct Array(T) { 197 private: 198 int _length; 199 T[] _data; 200 public: 201 T * ptr(int index = 0) { 202 return _data.ptr + index; 203 } 204 void swap(ref Array v) { 205 int tmp; 206 tmp = _length; _length = v._length; v._length = tmp; 207 T[] ptmp; 208 ptmp = _data; _data = v._data; v._data = ptmp; 209 } 210 /// ensure capacity is enough to fit sz items 211 void reserve(int sz) { 212 sz += _length; 213 if (_data.length < sz) { 214 int oldsize = cast(int)_data.length; 215 int newsize = 1024; 216 while (newsize < sz) 217 newsize <<= 1; 218 _data.length = newsize; 219 for (int i = oldsize; i < newsize; i++) 220 _data.ptr[i] = T.init; 221 _data.assumeSafeAppend(); 222 } 223 } 224 @property int length() { 225 return _length; 226 } 227 /// append single item by ref 228 void append(ref const T value) { 229 if (_length >= _data.length) 230 reserve(cast(int)(_data.length == 0 ? 64 : _data.length * 2 - _length)); 231 _data.ptr[_length++] = value; 232 } 233 /// append single item by value 234 void append(T value) { 235 if (_length >= _data.length) 236 reserve(cast(int)(_data.length == 0 ? 64 : _data.length * 2 - _length)); 237 _data.ptr[_length++] = value; 238 } 239 /// append single item w/o check 240 void appendNoCheck(ref const T value) { 241 _data.ptr[_length++] = value; 242 } 243 /// append single item w/o check 244 void appendNoCheck(T value) { 245 _data.ptr[_length++] = value; 246 } 247 /// appends same value several times, return pointer to appended items 248 T* append(ref const T value, int count) { 249 reserve(count); 250 int startLen = _length; 251 for (int i = 0; i < count; i++) 252 _data.ptr[_length++] = value; 253 return _data.ptr + startLen; 254 } 255 /// appends same value several times, return pointer to appended items 256 T* append(T value, int count) { 257 reserve(count); 258 int startLen = _length; 259 for (int i = 0; i < count; i++) 260 _data.ptr[_length++] = value; 261 return _data.ptr + startLen; 262 } 263 void clear() { 264 _length = 0; 265 } 266 T get(int index) { 267 return _data.ptr[index]; 268 } 269 void set(int index, T value) { 270 _data.ptr[index] = value; 271 } 272 ref T opIndex(int index) { 273 return _data.ptr[index]; 274 } 275 } 276 277 alias FloatArray = Array!(float); 278 alias IntArray = Array!(int); 279 alias CellArray = Array!(cell_t); 280 alias Vector2dArray = Array!(Vector2d); 281 alias Vector3dArray = Array!(Vector3d); 282 283 284 285 struct Position { 286 Vector3d pos; 287 Direction direction; 288 this(ref Position p) { 289 pos = p.pos; 290 direction = p.direction; 291 } 292 this(Vector3d position, Vector3d dir) { 293 pos = position; 294 direction = dir; 295 } 296 //Vector2d calcPlaneCoords(Vector3d v) { 297 // v = v - pos; 298 // switch (direction.dir) with(Dir) { 299 // default: 300 // case NORTH: 301 // return Vector2d(v.x, v.y); 302 // case SOUTH: 303 // return Vector2d(-v.x, v.y); 304 // case EAST: 305 // return Vector2d(v.z, v.y); 306 // case WEST: 307 // return Vector2d(-v.z, v.y); 308 // case UP: 309 // return Vector2d(-v.z, v.x); 310 // case DOWN: 311 // return Vector2d(v.z, v.x); 312 // } 313 //} 314 void turnLeft() { 315 direction.turnLeft(); 316 } 317 void turnRight() { 318 direction.turnRight(); 319 } 320 void shiftLeft(int step = 1) { 321 pos += direction.left * step; 322 } 323 void shiftRight(int step = 1) { 324 pos += direction.right * step; 325 } 326 void turnUp() { 327 direction.turnUp(); 328 } 329 void turnDown() { 330 direction.turnDown(); 331 } 332 void forward(int step = 1) { 333 pos += direction.forward * step; 334 } 335 void backward(int step = 1) { 336 pos -= direction.forward * step; 337 } 338 void moveUp(int step = 1) { 339 pos += direction.up * step; 340 } 341 void moveDown(int step = 1) { 342 pos += direction.down * step; 343 } 344 void moveLeft(int step = 1) { 345 pos += direction.left * step; 346 } 347 void moveRight(int step = 1) { 348 pos += direction.right * step; 349 } 350 } 351 352 353 /// returns opposite direction to specified direction 354 Dir opposite(Dir d) { 355 return cast(Dir)(d ^ 1); 356 } 357 358 Dir turnLeft(Dir d) { 359 switch (d) with (Dir) { 360 case WEST: 361 return SOUTH; 362 case EAST: 363 return NORTH; 364 default: 365 case NORTH: 366 return WEST; 367 case SOUTH: 368 return EAST; 369 case UP: 370 return SOUTH; 371 case DOWN: 372 return NORTH; 373 } 374 } 375 376 Dir turnRight(Dir d) { 377 switch (d) with (Dir) { 378 case WEST: 379 return NORTH; 380 case EAST: 381 return SOUTH; 382 default: 383 case NORTH: 384 return EAST; 385 case SOUTH: 386 return WEST; 387 case UP: 388 return NORTH; 389 case DOWN: 390 return SOUTH; 391 } 392 } 393 394 Dir turnUp(Dir d) { 395 switch (d) with (Dir) { 396 case WEST: 397 return UP; 398 case EAST: 399 return UP; 400 default: 401 case NORTH: 402 return UP; 403 case SOUTH: 404 return UP; 405 case UP: 406 return SOUTH; 407 case DOWN: 408 return NORTH; 409 } 410 } 411 412 Dir turnDown(Dir d) { 413 switch (d) with (Dir) { 414 case WEST: 415 return DOWN; 416 case EAST: 417 return DOWN; 418 default: 419 case NORTH: 420 return DOWN; 421 case SOUTH: 422 return DOWN; 423 case UP: 424 return NORTH; 425 case DOWN: 426 return SOUTH; 427 } 428 } 429 430 431 struct Direction { 432 this(int x, int y, int z) { 433 set(x, y, z); 434 } 435 this(Vector3d v) { 436 set(v); 437 } 438 this(Dir d) { 439 set(d); 440 } 441 /// returns Y axis rotation angle in degrees (0, 90, 180, 270) 442 @property float angle() { 443 switch (dir) with (Dir) { 444 default: 445 case NORTH: 446 return 0; 447 case SOUTH: 448 return 180; 449 case WEST: 450 return 90; 451 case EAST: 452 return 270; 453 case UP: 454 case DOWN: 455 return 0; 456 } 457 } 458 /// set by direction code 459 void set(Dir d) { 460 switch (d) with (Dir) { 461 default: 462 case NORTH: 463 set(0, 0, -1); 464 break; 465 case SOUTH: 466 set(0, 0, 1); 467 break; 468 case WEST: 469 set(-1, 0, 0); 470 break; 471 case EAST: 472 set(1, 0, 0); 473 break; 474 case UP: 475 set(0, 1, 0); 476 break; 477 case DOWN: 478 set(0, -1, 0); 479 break; 480 } 481 } 482 /// set by vector 483 void set(Vector3d v) { set(v.x, v.y, v.z); } 484 /// set by vector 485 void set(int x, int y, int z) { 486 forward = Vector3d(x, y, z); 487 if (x) { 488 dir = (x > 0) ? Dir.EAST : Dir.WEST; 489 } 490 else if (y) { 491 dir = (y > 0) ? Dir.UP : Dir.DOWN; 492 } 493 else { 494 dir = (z > 0) ? Dir.SOUTH : Dir.NORTH; 495 } 496 switch (dir) with (Dir) { 497 case UP: 498 up = Vector3d(1, 0, 0); 499 left = Vector3d(0, 0, 1); 500 break; 501 case DOWN: 502 up = Vector3d(1, 0, 0); 503 left = Vector3d(0, 0, -1); 504 break; 505 default: 506 case NORTH: 507 up = Vector3d(0, 1, 0); 508 left = Vector3d(-1, 0, 0); 509 break; 510 case SOUTH: 511 up = Vector3d(0, 1, 0); 512 left = Vector3d(1, 0, 0); 513 break; 514 case EAST: 515 up = Vector3d(0, 1, 0); 516 left = Vector3d(0, 0, -1); 517 break; 518 case WEST: 519 up = Vector3d(0, 1, 0); 520 left = Vector3d(0, 0, 1); 521 break; 522 } 523 down = -up; 524 right = -left; 525 forwardUp = forward + up; 526 forwardDown = forward + down; 527 forwardLeft = forward + left; 528 forwardLeftUp = forward + left + up; 529 forwardLeftDown = forward + left + down; 530 forwardRight = forward + right; 531 forwardRightUp = forward + right + up; 532 forwardRightDown = forward + right + down; 533 } 534 535 void turnLeft() { 536 set(.turnLeft(dir)); 537 } 538 void turnRight() { 539 set(.turnRight(dir)); 540 } 541 void turnUp() { 542 set(.turnUp(dir)); 543 } 544 void turnDown() { 545 set(.turnDown(dir)); 546 } 547 548 Dir dir; 549 Vector3d forward; 550 Vector3d up; 551 Vector3d right; 552 Vector3d left; 553 Vector3d down; 554 Vector3d forwardUp; 555 Vector3d forwardDown; 556 Vector3d forwardLeft; 557 Vector3d forwardLeftUp; 558 Vector3d forwardLeftDown; 559 Vector3d forwardRight; 560 Vector3d forwardRightUp; 561 Vector3d forwardRightDown; 562 } 563 564 /// returns number of bits to store integer 565 int bitsFor(int n) { 566 int res; 567 for (res = 0; n > 0; res++) 568 n >>= 1; 569 return res; 570 } 571 572 /// returns 0 for 0, 1 for negatives, 2 for positives 573 int mySign(int n) { 574 if (n > 0) 575 return 1; 576 else if (n < 0) 577 return -1; 578 else 579 return 0; 580 } 581 582 immutable ulong RANDOM_MULTIPLIER = 0x5DEECE66D; 583 immutable ulong RANDOM_MASK = ((cast(ulong)1 << 48) - 1); 584 immutable ulong RANDOM_ADDEND = cast(ulong)0xB; 585 586 struct Random { 587 ulong seed; 588 //Random(); 589 void setSeed(ulong value) { 590 seed = (value ^ RANDOM_MULTIPLIER) & RANDOM_MASK; 591 } 592 593 int next(int bits) { 594 seed = (seed * RANDOM_MULTIPLIER + RANDOM_ADDEND) & RANDOM_MASK; 595 return cast(int)(seed >> (48 - bits)); 596 } 597 598 int nextInt() { 599 return next(31); 600 } 601 int nextInt(int n) { 602 if ((n & -n) == n) // i.e., n is a power of 2 603 return cast(int)((n * cast(long)next(31)) >> 31); 604 int bits, val; 605 do { 606 bits = next(31); 607 val = bits % n; 608 } while (bits - val + (n - 1) < 0); 609 return val; 610 } 611 } 612 613 __gshared const Vector3d[6] DIRECTION_VECTORS = [ 614 Vector3d(0, 0, -1), 615 Vector3d(0, 0, 1), 616 Vector3d(-1, 0, 0), 617 Vector3d(1, 0, 0), 618 Vector3d(0, 1, 0), 619 Vector3d(0, -1, 0) 620 ]; 621 622 /// 3d array[+-size, +-size, +-size] of T 623 struct Array3d(T) { 624 int _size; 625 int _sizeBits; 626 T[] _cells; 627 void reset(int size) { 628 if (size == 0) { 629 // just clear storage 630 _cells = null; 631 _size = 0; 632 _sizeBits = 0; 633 return; 634 } 635 _size = size; 636 _sizeBits = bitsFor(size) + 1; 637 int arraySize = 1 << (_sizeBits * 3); 638 if (_cells.length < arraySize) 639 _cells.length = arraySize; 640 foreach(ref cell; _cells) 641 cell = T.init; 642 } 643 ref T opIndex(int x, int y, int z) { 644 int index = (x + _size) + ((y + _size) << _sizeBits) + ((z + _size) << (_sizeBits + _sizeBits)); 645 return _cells[index]; 646 } 647 T * ptr(int x, int y, int z) { 648 int index = (x + _size) + ((y + _size) << _sizeBits) + ((z + _size) << (_sizeBits + _sizeBits)); 649 return &_cells[index]; 650 } 651 } 652