kaktwoos.cl 4.0 KB

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