kaktwoos-nv.cl 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #define MASK ((1UL << 48UL) - 1UL)
  2. #define MUL 0x5DEECE66DUL
  3. #define ADD 0xBUL
  4. #define WANTED_CACTUS_HEIGHT 22
  5. int nextInt(ulong* seed);
  6. int next(ulong* seed, short bits);
  7. int nextIntUnknown(ulong* seed, short bound);
  8. uchar extract(const uint heightMap[], int id);
  9. void increase(uint heightMap[], int id, int val);
  10. kernel void crack(global int *data, global ulong* answer)
  11. {
  12. int id = get_global_id(0);
  13. ulong originalSeed = (((ulong)data[0] * (ulong)data[1] + (ulong)id) << 4) | data[8];
  14. ulong seed = originalSeed;
  15. short position = -1;
  16. short posMap;
  17. short posX, posY, posZ;
  18. short initialPosX, initialPosY, initialPosZ;
  19. uchar top = data[7] + FLOOR_LEVEL;
  20. uint heightMap[171];
  21. for (short i = 0; i < 171; i++) {
  22. heightMap[i] = 0;
  23. }
  24. for (short i = 0; i < 10; i++) {
  25. if (WANTED_CACTUS_HEIGHT - top > 9 * (10 - i))
  26. return;
  27. initialPosX = next(&seed, 4) + 8;
  28. initialPosZ = next(&seed, 4) + 8;
  29. initialPosY = nextIntUnknown(&seed, extract(heightMap, initialPosX + initialPosZ * 32) * 2 + 2);
  30. if (initialPosY + 3 <= FLOOR_LEVEL && initialPosY - 3 >= 0) {
  31. seed = (seed * 256682821044977UL + 233843537749372UL) & MASK;
  32. continue;
  33. }
  34. if (initialPosY - 3 > top + 1) {
  35. for (int j = 0; j < 10; j++) {
  36. seed = (seed * 76790647859193UL + 25707281917278UL) & MASK;
  37. nextIntUnknown(&seed, nextInt(&seed) + 1);
  38. }
  39. continue;
  40. }
  41. #pragma unroll (1)
  42. for (short a = 0; a < 10; a++) {
  43. posX = initialPosX + next(&seed, 3) - next(&seed, 3);
  44. posY = initialPosY + next(&seed, 2) - next(&seed, 2);
  45. posZ = initialPosZ + next(&seed, 3) - next(&seed, 3);
  46. posMap = posX + posZ * 32;
  47. if (position == -1 && posY > FLOOR_LEVEL && posY <= FLOOR_LEVEL + data[7] + 1) {
  48. if (posMap == data[3]) {
  49. position = 0;
  50. } else if (posMap == data[4]) {
  51. position = 1;
  52. } else if (posMap == data[5]) {
  53. position = 2;
  54. }
  55. if (position != -1) {
  56. int bit = (int)((originalSeed >> 4) & 1);
  57. if ((data[6] == position) ^ (bit == data[9]))
  58. return;
  59. increase(heightMap, posMap, data[7]);
  60. }
  61. }
  62. if (posY <= extract(heightMap, posMap))
  63. continue;
  64. short offset = 1 + nextIntUnknown(&seed, nextInt(&seed) + 1);
  65. for (uchar j = posY; j < posY + offset; j++) {
  66. if (posY < 0 ||
  67. j > extract(heightMap, posMap) + 1 ||
  68. j <= extract(heightMap, (posMap + 1 ) & 1023) ||
  69. j <= extract(heightMap, (posMap - 1 ) & 1023) ||
  70. j <= extract(heightMap, (posMap + 32) & 1023) ||
  71. j <= extract(heightMap, (posMap - 32) & 1023))
  72. continue;
  73. increase(heightMap, posMap, 1);
  74. }
  75. top = max(top, extract(heightMap, posMap));
  76. }
  77. }
  78. if (top - FLOOR_LEVEL >= WANTED_CACTUS_HEIGHT) {
  79. answer[atomic_add(&data[2], 1)] =
  80. ((ulong)top - FLOOR_LEVEL) << 58UL |
  81. (((ulong)data[position + 3]) << 48UL) |
  82. originalSeed;
  83. }
  84. }
  85. int next(ulong* seed, short bits)
  86. {
  87. *seed = (*seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
  88. return *seed >> (48 - bits);
  89. }
  90. int nextInt(ulong* seed)
  91. {
  92. int bits, value;
  93. do {
  94. *seed = (*seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
  95. bits = *seed >> 17;
  96. value = bits % 3;
  97. } while(bits - value + (3 - 1) < 0);
  98. return value;
  99. }
  100. int nextIntUnknown(ulong* seed, short bound)
  101. {
  102. if((bound & -bound) == bound) {
  103. *seed = (*seed * MUL + ADD) & MASK;
  104. return (int)((bound * (*seed >> 17)) >> 31);
  105. }
  106. int bits, value;
  107. do {
  108. *seed = (*seed * MUL + ADD) & MASK;
  109. bits = *seed >> 17;
  110. value = bits % bound;
  111. } while(bits - value + (bound - 1) < 0);
  112. return value;
  113. }
  114. uchar extract(const uint heightMap[], int id)
  115. {
  116. return FLOOR_LEVEL + ((heightMap[id / 6] >> ((id % 6) * 5)) & 0b11111U);
  117. }
  118. void increase(uint heightMap[], int id, int val)
  119. {
  120. heightMap[id / 6] += val << ((id % 6) * 5);
  121. }