find_quadhuts.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /**
  2. * This is an example program that demonstrates how to find seeds with a
  3. * quad-witch-hut located around the specified region (512x512 area).
  4. *
  5. * It uses some optimisations that cause it miss a small number of seeds, in
  6. * exchange for a major speed upgrade. (~99% accuracy, ~1200% speed)
  7. */
  8. #include "finders.h"
  9. #include "generator.h"
  10. #include "layers.h"
  11. #include <unistd.h>
  12. #if defined(_WIN32)
  13. #include <direct.h>
  14. #else
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #endif
  18. int main(int argc, char *argv[])
  19. {
  20. // Always initialize the biome list before starting any seed finder or
  21. // biome generator.
  22. initBiomes();
  23. LayerStack g;
  24. // Translate the positions to the desired regions.
  25. int regPosX = 0;
  26. int regPosZ = 0;
  27. int mcversion = MC_1_16;
  28. StructureConfig featureConfig;
  29. char seedFileName[256] = {};
  30. enum LowBitSet lbitset = LBIT_ALL;
  31. int radius = 128;
  32. if (argc > 2)
  33. {
  34. if (sscanf(argv[1], "%d", &regPosX) != 1) regPosX = 0;
  35. if (sscanf(argv[2], "%d", &regPosZ) != 1) regPosZ = 0;
  36. if (argc > 3)
  37. {
  38. int mcarg1 = 0, mcarg2 = 0;
  39. int ac = sscanf(argv[3], "%d.%d", &mcarg1, &mcarg2);
  40. if (ac < 1)
  41. {
  42. printf("Bad version format\n");
  43. exit(1);
  44. }
  45. if (ac > 1)
  46. mcarg1 = 100 * mcarg1 + mcarg2;
  47. if (mcarg1 < 113)
  48. mcversion = MC_1_7;
  49. else if (mcarg1 < 116)
  50. mcversion = MC_1_13;
  51. else
  52. mcversion = MC_1_16;
  53. }
  54. else
  55. {
  56. printf("MC version not specified. Defaulting to 1.16\n");
  57. }
  58. }
  59. else
  60. {
  61. printf("Usage:\n"
  62. "find_quadhuts [regionX] [regionZ] [mcversion]\n"
  63. "Defaulting to origin.\n\n");
  64. }
  65. regPosX -= 1;
  66. regPosZ -= 1;
  67. if (mcversion >= MC_1_13)
  68. {
  69. featureConfig = SWAMP_HUT_CONFIG;
  70. }
  71. else
  72. {
  73. featureConfig = FEATURE_CONFIG;
  74. }
  75. setupGenerator(&g, mcversion);
  76. #if defined(_WIN32)
  77. _mkdir("./seeds");
  78. #else
  79. mkdir("./seeds", 0773);
  80. #endif
  81. #if 0
  82. sprintf(seedFileName, "./seeds/quadbase_ideal_%d.txt", featureConfig.salt);
  83. lbitset = LBIT_IDEAL;
  84. radius = 128;
  85. #elif 0
  86. sprintf(seedFileName, "./seeds/quadbase_classic_%d.txt", featureConfig.salt);
  87. lbitset = LBIT_CLASSIC;
  88. radius = 128;
  89. #elif 1
  90. sprintf(seedFileName, "./seeds/quadbase_normal_%d.txt", featureConfig.salt);
  91. lbitset = LBIT_HUT_NORMAL;
  92. radius = 128;
  93. #else
  94. sprintf(seedFileName, "./seeds/quadbase_barely_%d.txt", featureConfig.salt);
  95. lbitset = LBIT_HUT_BARELY;
  96. radius = 128;
  97. #endif
  98. if (access(seedFileName, F_OK))
  99. {
  100. printf("Seed base file does not exist: Creating new one.\n"
  101. "This can take a while...\n");
  102. int threads = 6;
  103. search4QuadBases(seedFileName, threads, featureConfig, radius, lbitset);
  104. }
  105. int64_t i, j, qhcnt;
  106. int64_t base, seed;
  107. int64_t *qhcandidates = loadSavedSeeds(seedFileName, &qhcnt);
  108. Layer *lFilterBiome = &g.layers[L_BIOME_256];
  109. int *biomeCache = allocCache(lFilterBiome, 3, 3);
  110. // Load the positions of the four structures that make up the quad-structure
  111. // so we can test the biome at these positions.
  112. Pos qpos[4];
  113. // layerSeed for Layer 19: Biome, to make preliminary seed tests.
  114. int64_t lsBiome = g.layers[L_BIOME_256].layerSeed;
  115. int areaX = (regPosX << 1) + 1;
  116. int areaZ = (regPosZ << 1) + 1;
  117. int check_swamp_hut_specifics = 1;
  118. int64_t ss, cs;
  119. // Search for a swamp at the structure positions
  120. for (i = 0; i < qhcnt; i++)
  121. {
  122. base = moveStructure(qhcandidates[i], regPosX, regPosZ);
  123. qpos[0] = getStructurePos(featureConfig, base, 0+regPosX, 0+regPosZ, NULL);
  124. qpos[1] = getStructurePos(featureConfig, base, 0+regPosX, 1+regPosZ, NULL);
  125. qpos[2] = getStructurePos(featureConfig, base, 1+regPosX, 0+regPosZ, NULL);
  126. qpos[3] = getStructurePos(featureConfig, base, 1+regPosX, 1+regPosZ, NULL);
  127. /*
  128. for (j = 0; j < 4; j++)
  129. {
  130. printf("(%d,%d) ", qpos[j].x, qpos[j].z);
  131. }
  132. printf("\n");
  133. */
  134. if (check_swamp_hut_specifics)
  135. {
  136. // This little magic code checks if there is a meaningful chance for
  137. // this seed base to generate swamps in the area.
  138. // The idea is, that the conversion from Lush temperature to swamp
  139. // is independent of surroundings, so we can test for this
  140. // conversion beforehand. Furthermore, biomes tend to leak into the
  141. // negative coordinates because of the Zoom layers, so the majority
  142. // of hits will occur when SouthEast corner (at a 1:256 scale) of
  143. // the quad-hut has a swamp. (This assumption misses about 1 in 500
  144. // quad-hut seeds.) Finally, here we also exploit that the minecraft
  145. // random number generator is quite bad, the "mcNextRand() mod 6"
  146. // check has a period pattern of ~3 on the high seed-bits, which
  147. // means we can avoid checking all 16 high-bit combinations.
  148. for (j = 0; j < 5; j++)
  149. {
  150. seed = base + ((j+0x53) << 48);
  151. ss = getStartSeed(seed, lsBiome);
  152. cs = getChunkSeed(ss, areaX+1, areaZ+1);
  153. if (mcFirstInt(cs, 6) == 5)
  154. break;
  155. }
  156. if (j >= 5)
  157. continue;
  158. }
  159. int64_t hits = 0, swpc;
  160. for (j = 0; j < 0x10000; j++)
  161. {
  162. seed = base + (j << 48);
  163. if (check_swamp_hut_specifics)
  164. {
  165. /** Pre-Generation Checks **/
  166. // We can check that at least one swamp could generate in this
  167. // area before doing the biome generator checks.
  168. ss = getStartSeed(seed, lsBiome);
  169. cs = getChunkSeed(ss, areaX+1, areaZ+1);
  170. if (mcFirstInt(cs, 6) != 5)
  171. continue;
  172. // This seed base does not seem to contain many quad huts, so
  173. // make a more detailed analysis of the surroundings and see if
  174. // there is enough potential for more swamps to justify
  175. // searching further.
  176. if (hits == 0 && (j & 0xfff) == 0xfff)
  177. {
  178. swpc = 0;
  179. cs = getChunkSeed(ss, areaX, areaZ+1);
  180. swpc += mcFirstInt(cs, 6) == 5;
  181. cs = getChunkSeed(ss, areaX+1, areaZ);
  182. swpc += mcFirstInt(cs, 6) == 5;
  183. cs = getChunkSeed(ss, areaX, areaZ);
  184. swpc += mcFirstInt(cs, 6) == 5;
  185. if (swpc < (j > 0x1000 ? 2 : 1))
  186. break;
  187. }
  188. // Dismiss seeds that don't have a swamp near the quad temple.
  189. setWorldSeed(lFilterBiome, seed);
  190. genArea(lFilterBiome, biomeCache, (regPosX<<1)+2, (regPosZ<<1)+2, 1, 1);
  191. if (biomeCache[0] != swamp)
  192. continue;
  193. }
  194. // we need to use config here for pre 1.13 as that would not
  195. // specify that we are only interested in swamp huts
  196. if (!isViableStructurePos(Swamp_Hut, mcversion, &g, seed, qpos[0].x, qpos[0].z)) continue;
  197. if (!isViableStructurePos(Swamp_Hut, mcversion, &g, seed, qpos[1].x, qpos[1].z)) continue;
  198. if (!isViableStructurePos(Swamp_Hut, mcversion, &g, seed, qpos[2].x, qpos[2].z)) continue;
  199. if (!isViableStructurePos(Swamp_Hut, mcversion, &g, seed, qpos[3].x, qpos[3].z)) continue;
  200. printf("%" PRId64 "\n", seed);
  201. hits++;
  202. }
  203. }
  204. free(biomeCache);
  205. return 0;
  206. }