finders.c 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125
  1. #include "finders.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6. //==============================================================================
  7. // Globals
  8. //==============================================================================
  9. Biome biomes[256];
  10. //==============================================================================
  11. // Saving & Loading Seeds
  12. //==============================================================================
  13. int64_t *loadSavedSeeds(const char *fnam, int64_t *scnt)
  14. {
  15. FILE *fp = fopen(fnam, "r");
  16. int64_t seed, i;
  17. int64_t *baseSeeds;
  18. if (fp == NULL)
  19. {
  20. perror("ERR loadSavedSeeds: ");
  21. return NULL;
  22. }
  23. *scnt = 0;
  24. while (!feof(fp))
  25. {
  26. if (fscanf(fp, "%" PRId64, &seed) == 1) (*scnt)++;
  27. else while (!feof(fp) && fgetc(fp) != '\n');
  28. }
  29. baseSeeds = (int64_t*) calloc(*scnt, sizeof(*baseSeeds));
  30. rewind(fp);
  31. for (i = 0; i < *scnt && !feof(fp);)
  32. {
  33. if (fscanf(fp, "%" PRId64, &baseSeeds[i]) == 1) i++;
  34. else while (!feof(fp) && fgetc(fp) != '\n');
  35. }
  36. fclose(fp);
  37. return baseSeeds;
  38. }
  39. //==============================================================================
  40. // Finding Structure Positions
  41. //==============================================================================
  42. static int testOutpostPos(int64_t s, int cx, int cz)
  43. {
  44. s ^= (cx >> 4) ^ ( (cz >> 4) << 4 );
  45. setSeed(&s);
  46. next(&s, 32);
  47. return nextInt(&s, 5) == 0;
  48. }
  49. Pos getStructurePos(StructureConfig config, int64_t seed, int regX, int regZ, int *valid)
  50. {
  51. Pos pos;
  52. if (valid) *valid = 0;
  53. if (config.properties == 0)
  54. {
  55. pos = getFeaturePos(config, seed, regX, regZ);
  56. if (valid)
  57. {
  58. if (config.structType == Outpost)
  59. {
  60. *valid = testOutpostPos(seed, pos.x >> 4, pos.z >> 4);
  61. // Outposts also require that there are no villages nearby.
  62. // However, before 1.16 this would include a biome check, so it
  63. // should be tested for in the position viability check.
  64. }
  65. else
  66. {
  67. *valid = 1;
  68. }
  69. }
  70. }
  71. else if (config.properties == LARGE_STRUCT)
  72. {
  73. if ((config.chunkRange & (config.chunkRange-1)))
  74. {
  75. pos = getLargeStructurePos(config, seed, regX, regZ);
  76. if (valid) *valid = 1;
  77. }
  78. }
  79. return pos;
  80. }
  81. int isMineshaftChunk(int64_t seed, int chunkX, int chunkZ)
  82. {
  83. int64_t s = seed;
  84. setSeed(&s);
  85. int64_t i = nextLong(&s);
  86. int64_t j = nextLong(&s);
  87. s = chunkX * i ^ chunkZ * j ^ seed;
  88. setSeed(&s);
  89. return nextDouble(&s) < 0.004;
  90. }
  91. int isTreasureChunk(int64_t seed, int chunkX, int chunkZ)
  92. {
  93. seed = chunkX*341873128712 + chunkZ*132897987541 + seed + TREASURE_CONFIG.salt;
  94. setSeed(&seed);
  95. return nextFloat(&seed) < 0.01;
  96. }
  97. //==============================================================================
  98. // Multi-Structure Checks
  99. //==============================================================================
  100. // TODO: accurate seed testers for two or three structures in range
  101. /* Searches for the optimal AFK position given four structures at positions 'p',
  102. * each of volume (ax,ay,az).
  103. *
  104. * Returned is the number of spawning spaces within reach.
  105. */
  106. int countBlocksInSpawnRange(Pos p[4], int ax, int ay, int az, Pos *afk)
  107. {
  108. int minX = 3e7, minZ = 3e7, maxX = -3e7, maxZ = -3e7;
  109. int bestr, bestn, i, x, z, px, pz;
  110. // Find corners
  111. for (i = 0; i < 4; i++)
  112. {
  113. if (p[i].x < minX) minX = p[i].x;
  114. if (p[i].z < minZ) minZ = p[i].z;
  115. if (p[i].x > maxX) maxX = p[i].x;
  116. if (p[i].z > maxZ) maxZ = p[i].z;
  117. }
  118. // assume that the search area is bound by the inner corners
  119. maxX += ax;
  120. maxZ += az;
  121. bestr = 0;
  122. bestn = 0;
  123. double thsq = 128.0*128.0 - ay*ay/4.0;
  124. for (x = minX; x < maxX; x++)
  125. {
  126. for (z = minZ; z < maxZ; z++)
  127. {
  128. int inrange = 0;
  129. for (i = 0; i < 4; i++)
  130. {
  131. double dx = p[i].x - (x);
  132. double dz = p[i].z - (z);
  133. for (px = 0; px < ax; px++)
  134. {
  135. for (pz = 0; pz < az; pz++)
  136. {
  137. double ddx = px + dx;
  138. double ddz = pz + dz;
  139. inrange += (ddx*ddx + ddz*ddz <= thsq);
  140. }
  141. }
  142. }
  143. if (inrange > bestr)
  144. {
  145. if (afk)
  146. {
  147. afk->x = x;
  148. afk->z = z;
  149. bestn = 1;
  150. }
  151. bestr = inrange;
  152. }
  153. else if (inrange == bestr)
  154. {
  155. if (afk)
  156. {
  157. afk->x += x;
  158. afk->z += z;
  159. bestn++;
  160. }
  161. }
  162. }
  163. }
  164. if (afk && bestn)
  165. {
  166. afk->x /= bestn;
  167. afk->z /= bestn;
  168. }
  169. return bestr;
  170. }
  171. STRUCT(quad_threadinfo_t)
  172. {
  173. int64_t start, end;
  174. StructureConfig sconf;
  175. int threadID;
  176. int radius;
  177. int lbitset;
  178. const char *fnam;
  179. };
  180. #ifdef USE_PTHREAD
  181. static void *search4QuadBasesThread(void *data)
  182. #else
  183. static DWORD WINAPI search4QuadBasesThread(LPVOID data)
  184. #endif
  185. {
  186. quad_threadinfo_t info = *(quad_threadinfo_t*)data;
  187. const int64_t start = info.start;
  188. const int64_t end = info.end;
  189. const int64_t salt = info.sconf.salt;
  190. int64_t seed;
  191. int64_t *lowerBits;
  192. int lowerBitsCnt;
  193. int lowerBitsIdx = 0;
  194. int i;
  195. lowerBits = (int64_t *) malloc(0x100000 * sizeof(int64_t));
  196. switch (info.lbitset)
  197. {
  198. case LBIT_IDEAL:
  199. lowerBitsCnt = sizeof(lowerBaseBitsIdeal) / sizeof(int64_t);
  200. for (i = 0; i < lowerBitsCnt; i++)
  201. lowerBits[i] = (lowerBaseBitsIdeal[i] - salt) & 0xfffff;
  202. break;
  203. case LBIT_CLASSIC:
  204. lowerBitsCnt = sizeof(lowerBaseBitsClassic) / sizeof(int64_t);
  205. for (i = 0; i < lowerBitsCnt; i++)
  206. lowerBits[i] = (lowerBaseBitsClassic[i] - salt) & 0xfffff;
  207. break;
  208. case LBIT_HUT_NORMAL:
  209. lowerBitsCnt = sizeof(lowerBaseBitsHutNormal) / sizeof(int64_t);
  210. for (i = 0; i < lowerBitsCnt; i++)
  211. lowerBits[i] = (lowerBaseBitsHutNormal[i] - salt) & 0xfffff;
  212. break;
  213. case LBIT_HUT_BARELY:
  214. lowerBitsCnt = sizeof(lowerBaseBitsHutBarely) / sizeof(int64_t);
  215. for (i = 0; i < lowerBitsCnt; i++)
  216. lowerBits[i] = (lowerBaseBitsHutBarely[i] - salt) & 0xfffff;
  217. break;
  218. default:
  219. lowerBitsCnt = 0x100000;
  220. for (i = 0; i < lowerBitsCnt; i++) lowerBits[i] = i;
  221. break;
  222. }
  223. char fnam[256];
  224. sprintf(fnam, "%s.part%d", info.fnam, info.threadID);
  225. FILE *fp = fopen(fnam, "a+");
  226. if (fp == NULL)
  227. {
  228. fprintf(stderr, "Could not open \"%s\" for writing.\n", fnam);
  229. free(lowerBits);
  230. exit(-1);
  231. }
  232. seed = start;
  233. // Check the last entry in the file and use it as a starting point if it
  234. // exists. (I.e. loading the saved progress.)
  235. int c, nnl = 0;
  236. char buf[32];
  237. for (i = 1; i < 32; i++)
  238. {
  239. if (fseek(fp, -i, SEEK_END)) break;
  240. c = fgetc(fp);
  241. if (c <= 0 || (nnl && c == '\n')) break;
  242. nnl |= (c != '\n');
  243. }
  244. if (i < 32 && !fseek(fp, 1-i, SEEK_END) && fread(buf, i-1, 1, fp) > 0)
  245. {
  246. if (sscanf(buf, "%" PRId64, &seed) == 1)
  247. {
  248. while (lowerBits[lowerBitsIdx] <= (seed & 0xfffff))
  249. lowerBitsIdx++;
  250. seed = (seed & 0x0000fffffff00000) + lowerBits[lowerBitsIdx];
  251. printf("Thread %d starting from: %" PRId64"\n", info.threadID, seed);
  252. }
  253. else
  254. {
  255. seed = start;
  256. }
  257. }
  258. fseek(fp, 0, SEEK_END);
  259. while (seed < end)
  260. {
  261. float r = isQuadBase(info.sconf, seed, info.radius);
  262. if (r)
  263. {
  264. fprintf(fp, "%" PRId64"\n", seed);
  265. fflush(fp);
  266. //FILE *ftmp = fopen("./seeds/hex", "a");
  267. //fprintf(ftmp, "0x%05lx %.6f\n", (seed + salt) & 0xfffff, r);
  268. //fflush(ftmp);
  269. //fclose(ftmp);
  270. }
  271. lowerBitsIdx++;
  272. if (lowerBitsIdx >= lowerBitsCnt)
  273. {
  274. lowerBitsIdx = 0;
  275. seed += 0x100000;
  276. }
  277. seed = (seed & 0x0000fffffff00000) + lowerBits[lowerBitsIdx];
  278. }
  279. fclose(fp);
  280. free(lowerBits);
  281. #ifdef USE_PTHREAD
  282. pthread_exit(NULL);
  283. #endif
  284. return 0;
  285. }
  286. void search4QuadBases(const char *fnam, int threads,
  287. const StructureConfig structureConfig, int radius, int lbitset)
  288. {
  289. thread_id_t threadID[threads];
  290. quad_threadinfo_t info[threads];
  291. int64_t t;
  292. for (t = 0; t < threads; t++)
  293. {
  294. info[t].threadID = t;
  295. info[t].start = (t * SEED_BASE_MAX / threads) & 0x0000fffffff00000;
  296. info[t].end = ((info[t].start + (SEED_BASE_MAX-1) / threads) & 0x0000fffffff00000) + 1;
  297. info[t].fnam = fnam;
  298. info[t].radius = radius;
  299. info[t].lbitset = lbitset;
  300. info[t].sconf = structureConfig;
  301. }
  302. #ifdef USE_PTHREAD
  303. for (t = 0; t < threads; t++)
  304. {
  305. pthread_create(&threadID[t], NULL, search4QuadBasesThread, (void*)&info[t]);
  306. }
  307. for (t = 0; t < threads; t++)
  308. {
  309. pthread_join(threadID[t], NULL);
  310. }
  311. #else
  312. for (t = 0; t < threads; t++)
  313. {
  314. threadID[t] = CreateThread(NULL, 0, search4QuadBasesThread, (LPVOID)&info[t], 0, NULL);
  315. }
  316. WaitForMultipleObjects(threads, threadID, TRUE, INFINITE);
  317. #endif
  318. // merge thread parts
  319. char fnamThread[256];
  320. char buffer[4097];
  321. FILE *fp = fopen(fnam, "w");
  322. if (fp == NULL) {
  323. fprintf(stderr, "Could not open \"%s\" for writing.\n", fnam);
  324. exit(-1);
  325. }
  326. FILE *fpart;
  327. int n;
  328. for (t = 0; t < threads; t++)
  329. {
  330. sprintf(fnamThread, "%s.part%d", info[t].fnam, info[t].threadID);
  331. fpart = fopen(fnamThread, "r");
  332. if (fpart == NULL)
  333. {
  334. perror("ERR search4QuadBases: ");
  335. break;
  336. }
  337. while ((n = fread(buffer, sizeof(char), 4096, fpart)))
  338. {
  339. if (!fwrite(buffer, sizeof(char), n, fp))
  340. {
  341. perror("ERR search4QuadBases: ");
  342. fclose(fp);
  343. fclose(fpart);
  344. return;
  345. }
  346. }
  347. fclose(fpart);
  348. remove(fnamThread);
  349. }
  350. fclose(fp);
  351. }
  352. //==============================================================================
  353. // Checking Biomes & Biome Helper Functions
  354. //==============================================================================
  355. int getBiomeAtPos(const LayerStack *g, const Pos pos)
  356. {
  357. int *map = allocCache(g->entry_1, 1, 1);
  358. genArea(g->entry_1, map, pos.x, pos.z, 1, 1);
  359. int biomeID = map[0];
  360. free(map);
  361. return biomeID;
  362. }
  363. Pos findBiomePosition(
  364. const int mcversion,
  365. const Layer *l,
  366. int *cache,
  367. const int centerX,
  368. const int centerZ,
  369. const int range,
  370. const char *isValid,
  371. int64_t *seed,
  372. int *passes
  373. )
  374. {
  375. int x1 = (centerX-range) >> 2;
  376. int z1 = (centerZ-range) >> 2;
  377. int x2 = (centerX+range) >> 2;
  378. int z2 = (centerZ+range) >> 2;
  379. int width = x2 - x1 + 1;
  380. int height = z2 - z1 + 1;
  381. int *map;
  382. int i, j, found;
  383. Pos out;
  384. if (l->scale != 4)
  385. {
  386. printf("WARN findBiomePosition: require scale = 4, but have %d.\n",
  387. l->scale);
  388. }
  389. map = cache ? cache : allocCache(l, width, height);
  390. genArea(l, map, x1, z1, width, height);
  391. out.x = centerX;
  392. out.z = centerZ;
  393. found = 0;
  394. if (mcversion >= MC_1_13)
  395. {
  396. for (i = 0, j = 2; i < width*height; i++)
  397. {
  398. if (!biomeExists(map[i]) || !isValid[map[i]]) continue;
  399. if ((found == 0 || nextInt(seed, j++) == 0))
  400. {
  401. out.x = (x1 + i%width) << 2;
  402. out.z = (z1 + i/width) << 2;
  403. found = 1;
  404. }
  405. }
  406. found = j - 2;
  407. }
  408. else
  409. {
  410. for (i = 0; i < width*height; i++)
  411. {
  412. if (biomeExists(map[i]) && isValid[map[i]] &&
  413. (found == 0 || nextInt(seed, found + 1) == 0))
  414. {
  415. out.x = (x1 + i%width) << 2;
  416. out.z = (z1 + i/width) << 2;
  417. ++found;
  418. }
  419. }
  420. }
  421. if (cache == NULL)
  422. {
  423. free(map);
  424. }
  425. if (passes != NULL)
  426. {
  427. *passes = found;
  428. }
  429. return out;
  430. }
  431. int areBiomesViable(
  432. const Layer * l,
  433. int * cache,
  434. const int posX,
  435. const int posZ,
  436. const int radius,
  437. const char * isValid
  438. )
  439. {
  440. int x1 = (posX - radius) >> 2;
  441. int z1 = (posZ - radius) >> 2;
  442. int x2 = (posX + radius) >> 2;
  443. int z2 = (posZ + radius) >> 2;
  444. int width = x2 - x1 + 1;
  445. int height = z2 - z1 + 1;
  446. int i;
  447. int *map;
  448. int viable;
  449. if (l->scale != 4)
  450. {
  451. printf("WARN areBiomesViable: require scale = 4, but have %d.\n",
  452. l->scale);
  453. }
  454. map = cache ? cache : allocCache(l, width, height);
  455. viable = !genArea(l, map, x1, z1, width, height);
  456. if (viable)
  457. {
  458. for (i = 0; i < width*height; i++)
  459. {
  460. if (!biomeExists(map[i]) || !isValid[ map[i] ])
  461. {
  462. viable = 0;
  463. break;
  464. }
  465. }
  466. }
  467. if (cache == NULL)
  468. free(map);
  469. return viable;
  470. }
  471. int getBiomeRadius(
  472. const int * map,
  473. const int mapSide,
  474. const int * biomes,
  475. const int bnum,
  476. const int ignoreMutations)
  477. {
  478. int r, i, b;
  479. int blist[0x100];
  480. int mask = ignoreMutations ? 0x7f : 0xff;
  481. int radiusMax = mapSide / 2;
  482. if ((mapSide & 1) == 0)
  483. {
  484. printf("WARN getBiomeRadius: Side length of the square map should be an odd integer.\n");
  485. }
  486. memset(blist, 0, sizeof(blist));
  487. for (r = 1; r < radiusMax; r++)
  488. {
  489. for (i = radiusMax-r; i <= radiusMax+r; i++)
  490. {
  491. blist[ map[(radiusMax-r) * mapSide+ i] & mask ] = 1;
  492. blist[ map[(radiusMax+r-1) * mapSide + i] & mask ] = 1;
  493. blist[ map[mapSide*i + (radiusMax-r)] & mask ] = 1;
  494. blist[ map[mapSide*i + (radiusMax+r-1)] & mask ] = 1;
  495. }
  496. for (b = 0; b < bnum && blist[biomes[b] & mask]; b++);
  497. if (b >= bnum)
  498. {
  499. break;
  500. }
  501. }
  502. return r != radiusMax ? r : -1;
  503. }
  504. //==============================================================================
  505. // Finding Strongholds and Spawn
  506. //==============================================================================
  507. void approxInnerStrongholdRing(Pos p[3], int mcversion, int64_t s48)
  508. {
  509. int64_t rnds = s48;
  510. setSeed(&rnds);
  511. double angle = 2.0 * PI * nextDouble(&rnds);
  512. double acos = cos(angle);
  513. double asin = sin(angle);
  514. double tmp, distance;
  515. const double r120c = cos(2.0 * PI / 3);
  516. const double r120s = sin(2.0 * PI / 3);
  517. if (mcversion >= MC_1_9)
  518. {
  519. distance = (4.0 * 32.0) + (nextDouble(&rnds) - 0.5) * 32 * 2.5;
  520. p[0].x = (int)round(acos * distance);
  521. p[0].z = (int)round(asin * distance);
  522. // rotate 120 degrees
  523. tmp = acos;
  524. acos = tmp * r120c - asin * r120s;
  525. asin = tmp * r120s + asin * r120c;
  526. distance = (4.0 * 32.0) + (nextDouble(&rnds) - 0.5) * 32 * 2.5;
  527. p[1].x = (int)round(acos * distance);
  528. p[1].z = (int)round(asin * distance);
  529. // rotate 120 degrees
  530. tmp = acos;
  531. acos = tmp * r120c - asin * r120s;
  532. asin = tmp * r120s + asin * r120c;
  533. distance = (4.0 * 32.0) + (nextDouble(&rnds) - 0.5) * 32 * 2.5;
  534. p[2].x = (int)round(acos * distance);
  535. p[2].z = (int)round(asin * distance);
  536. }
  537. else
  538. {
  539. distance = (1.25 + nextDouble(&rnds)) * 32.0;
  540. p[0].x = (int)round(acos * distance);
  541. p[0].z = (int)round(asin * distance);
  542. // rotate 120 degrees
  543. tmp = acos;
  544. acos = tmp * r120c - asin * r120s;
  545. asin = tmp * r120s + asin * r120c;
  546. distance = (1.25 + nextDouble(&rnds)) * 32.0;
  547. p[1].x = (int)round(acos * distance);
  548. p[1].z = (int)round(asin * distance);
  549. // rotate 120 degrees
  550. tmp = acos;
  551. acos = tmp * r120c - asin * r120s;
  552. asin = tmp * r120s + asin * r120c;
  553. distance = (1.25 + nextDouble(&rnds)) * 32.0;
  554. p[2].x = (int)round(acos * distance);
  555. p[2].z = (int)round(asin * distance);
  556. }
  557. }
  558. int findStrongholds(const int mcversion, const LayerStack *g, int *cache,
  559. Pos *locations, int64_t worldSeed, int maxSH, int maxRing)
  560. {
  561. const char *validStrongholdBiomes = getValidStrongholdBiomes();
  562. int i, x, z;
  563. double distance;
  564. int currentRing = 0;
  565. int currentCount = 0;
  566. int perRing = 3;
  567. setSeed(&worldSeed); // PRNG
  568. double angle = nextDouble(&worldSeed) * PI * 2.0;
  569. const Layer *l = &g->layers[L_RIVER_MIX_4];
  570. if (mcversion >= MC_1_9)
  571. {
  572. if (maxSH <= 0) maxSH = 128;
  573. for (i = 0; i < maxSH; i++)
  574. {
  575. distance = (4.0 * 32.0) + (6.0 * currentRing * 32.0) +
  576. (nextDouble(&worldSeed) - 0.5) * 32 * 2.5;
  577. x = (int)round(cos(angle) * distance);
  578. z = (int)round(sin(angle) * distance);
  579. locations[i] = findBiomePosition(mcversion, l, cache,
  580. (x << 4) + 8, (z << 4) + 8, 112, validStrongholdBiomes,
  581. &worldSeed, NULL);
  582. angle += 2 * PI / perRing;
  583. currentCount++;
  584. if (currentCount == perRing)
  585. {
  586. // Current ring is complete, move to next ring.
  587. currentRing++;
  588. if (currentRing == maxRing)
  589. {
  590. i++;
  591. break;
  592. }
  593. currentCount = 0;
  594. perRing = perRing + 2*perRing/(currentRing+1);
  595. if (perRing > 128-i)
  596. perRing = 128-i;
  597. angle = angle + nextDouble(&worldSeed) * PI * 2.0;
  598. }
  599. }
  600. }
  601. else
  602. {
  603. if (maxSH <= 0) maxSH = 3;
  604. for (i = 0; i < maxSH; i++)
  605. {
  606. distance = (1.25 + nextDouble(&worldSeed)) * 32.0;
  607. x = (int)round(cos(angle) * distance);
  608. z = (int)round(sin(angle) * distance);
  609. locations[i] = findBiomePosition(mcversion, l, cache,
  610. (x << 4) + 8, (z << 4) + 8, 112, validStrongholdBiomes,
  611. &worldSeed, NULL);
  612. angle += 2 * PI / 3.0;
  613. }
  614. }
  615. return i;
  616. }
  617. static double getGrassProbability(int64_t seed, int biome, int x, int z)
  618. {
  619. // TODO: Use ChunkGeneratorOverworld.generateHeightmap for better estimate.
  620. // TODO: Try to determine the actual probabilities and build a statistic.
  621. switch (biome)
  622. {
  623. case plains: return 1.0;
  624. case mountains: return 0.8; // height dependent
  625. case forest: return 1.0;
  626. case taiga: return 1.0;
  627. case swamp: return 0.6; // height dependent
  628. case river: return 0.5;
  629. case beach: return 0.1;
  630. case wooded_hills: return 1.0;
  631. case taiga_hills: return 1.0;
  632. case mountain_edge: return 1.0; // height dependent
  633. case jungle: return 1.0;
  634. case jungle_hills: return 1.0;
  635. case jungle_edge: return 1.0;
  636. case birch_forest: return 1.0;
  637. case birch_forest_hills: return 1.0;
  638. case dark_forest: return 0.9;
  639. case snowy_taiga: return 0.2; // below trees
  640. case snowy_taiga_hills: return 0.2; // below trees
  641. case giant_tree_taiga: return 0.6;
  642. case giant_tree_taiga_hills: return 0.6;
  643. case wooded_mountains: return 0.2; // height dependent
  644. case savanna: return 1.0;
  645. case savanna_plateau: return 1.0;
  646. case wooded_badlands_plateau: return 0.1; // height dependent
  647. case badlands_plateau: return 0.1; // height dependent
  648. case sunflower_plains: return 1.0;
  649. case gravelly_mountains: return 0.2;
  650. case flower_forest: return 1.0;
  651. case taiga_mountains: return 1.0;
  652. case swamp_hills: return 0.9;
  653. case modified_jungle: return 1.0;
  654. case modified_jungle_edge: return 1.0;
  655. case tall_birch_forest: return 1.0;
  656. case tall_birch_hills: return 1.0;
  657. case dark_forest_hills: return 0.9;
  658. case snowy_taiga_mountains: return 0.2;
  659. case giant_spruce_taiga: return 0.6;
  660. case giant_spruce_taiga_hills: return 0.6;
  661. case modified_gravelly_mountains: return 0.2;
  662. case shattered_savanna: return 1.0;
  663. case shattered_savanna_plateau: return 1.0;
  664. case bamboo_jungle: return 0.4;
  665. case bamboo_jungle_hills: return 0.4;
  666. // NOTE: in rare circumstances you can get also get grassy islands that are
  667. // completely in ocean variants...
  668. default: return 0;
  669. }
  670. }
  671. static int canCoordinateBeSpawn(const int64_t seed, const LayerStack *g, int *cache, Pos pos)
  672. {
  673. int biome = getBiomeAtPos(g, pos);
  674. return getGrassProbability(seed, biome, pos.x, pos.z) >= 0.5;
  675. }
  676. Pos getSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed)
  677. {
  678. const char *isSpawnBiome = getValidSpawnBiomes();
  679. Pos spawn;
  680. int found;
  681. int i;
  682. const Layer *l = &g->layers[L_RIVER_MIX_4];
  683. setSeed(&worldSeed);
  684. spawn = findBiomePosition(mcversion, l, cache, 0, 0, 256, isSpawnBiome,
  685. &worldSeed, &found);
  686. if (!found)
  687. {
  688. //printf("Unable to find spawn biome.\n");
  689. spawn.x = spawn.z = 8;
  690. }
  691. if (mcversion >= MC_1_13)
  692. {
  693. // TODO: The 1.13 section may need further checking!
  694. int n2 = 0;
  695. int n3 = 0;
  696. int n4 = 0;
  697. int n5 = -1;
  698. for (i = 0; i < 1024; i++)
  699. {
  700. if (n2 > -16 && n2 <= 16 && n3 > -16 && n3 <= 16)
  701. {
  702. int cx = ((spawn.x >> 4) + n2) << 4;
  703. int cz = ((spawn.z >> 4) + n3) << 4;
  704. int i2, i3;
  705. for (i2 = cx; i2 <= cx+15; i2++)
  706. {
  707. for (i3 = cz; i3 <= cz+15; i3++)
  708. {
  709. Pos pos = {i2, i3};
  710. if (canCoordinateBeSpawn(worldSeed, g, cache, pos))
  711. {
  712. return pos;
  713. }
  714. }
  715. }
  716. }
  717. if (n2 == n3 || (n2 < 0 && n2 == - n3) || (n2 > 0 && n2 == 1 - n3))
  718. {
  719. int n7 = n4;
  720. n4 = - n5;
  721. n5 = n7;
  722. }
  723. n2 += n4;
  724. n3 += n5;
  725. }
  726. }
  727. else
  728. {
  729. for (i = 0; i < 1000 && !canCoordinateBeSpawn(worldSeed, g, cache, spawn); i++)
  730. {
  731. spawn.x += nextInt(&worldSeed, 64) - nextInt(&worldSeed, 64);
  732. spawn.z += nextInt(&worldSeed, 64) - nextInt(&worldSeed, 64);
  733. }
  734. }
  735. return spawn;
  736. }
  737. Pos estimateSpawn(const int mcversion, const LayerStack *g, int *cache, int64_t worldSeed)
  738. {
  739. const char *isSpawnBiome = getValidSpawnBiomes();
  740. Pos spawn;
  741. int found;
  742. const Layer *l = &g->layers[L_RIVER_MIX_4];
  743. setSeed(&worldSeed);
  744. spawn = findBiomePosition(mcversion, l, cache, 0, 0, 256, isSpawnBiome,
  745. &worldSeed, &found);
  746. if (!found)
  747. {
  748. spawn.x = spawn.z = 8;
  749. }
  750. return spawn;
  751. }
  752. //==============================================================================
  753. // Validating Structure Positions
  754. //==============================================================================
  755. int isViableFeatureBiome(int structureType, int biomeID)
  756. {
  757. switch (structureType)
  758. {
  759. case Desert_Pyramid:
  760. return biomeID == desert || biomeID == desert_hills;
  761. case Jungle_Pyramid:
  762. return (biomeID == jungle || biomeID == jungle_hills ||
  763. biomeID == bamboo_jungle || biomeID == bamboo_jungle_hills);
  764. case Swamp_Hut:
  765. return biomeID == swamp;
  766. case Igloo:
  767. return biomeID == snowy_tundra || biomeID == snowy_taiga;
  768. case Ocean_Ruin:
  769. return isOceanic(biomeID);
  770. case Shipwreck:
  771. return isOceanic(biomeID) || biomeID == beach || biomeID == snowy_beach;
  772. case Ruined_Portal:
  773. return 1;
  774. case Treasure:
  775. return (biomeID == beach || biomeID == snowy_beach ||
  776. biomeID == stone_shore || biomeID == mushroom_field_shore);
  777. case Monument:
  778. return isOceanic(biomeID);
  779. case Village:
  780. case Outpost:
  781. // differs across MC versions
  782. return (biomeID == plains || biomeID == desert ||
  783. biomeID == savanna || biomeID == taiga ||
  784. biomeID == snowy_taiga || biomeID == snowy_tundra);
  785. case Mansion:
  786. return biomeID == dark_forest || biomeID == dark_forest_hills;
  787. default:
  788. fprintf(stderr, "ERR isViableFeatureBiome: not implemented for structure type.\n");
  789. exit(1);
  790. }
  791. return 0;
  792. }
  793. static const char *getValidMonumentBiomes1()
  794. {
  795. static const int oceanMonumentBiomeList1[] =
  796. {
  797. ocean, deep_ocean, river, frozen_river,
  798. frozen_ocean, deep_frozen_ocean, cold_ocean, deep_cold_ocean,
  799. lukewarm_ocean, deep_lukewarm_ocean, warm_ocean, deep_warm_ocean
  800. };
  801. static char isValid[256];
  802. unsigned int i;
  803. if (!isValid[oceanMonumentBiomeList1[0]])
  804. for (i = 0; i < sizeof(oceanMonumentBiomeList1) / sizeof(int); i++)
  805. isValid[ oceanMonumentBiomeList1[i] ] = 1;
  806. return isValid;
  807. }
  808. static const char *getValidMonumentBiomes2()
  809. {
  810. static const int oceanMonumentBiomeList2[] =
  811. {
  812. deep_frozen_ocean, deep_cold_ocean, deep_ocean,
  813. deep_lukewarm_ocean, deep_warm_ocean
  814. };
  815. static char isValid[256];
  816. unsigned int i;
  817. if (!isValid[oceanMonumentBiomeList2[0]])
  818. for (i = 0; i < sizeof(oceanMonumentBiomeList2) / sizeof(int); i++)
  819. isValid[ oceanMonumentBiomeList2[i] ] = 1;
  820. return isValid;
  821. }
  822. static const char *getValidMansionBiomes()
  823. {
  824. static const int mansionBiomeList[] = {dark_forest, dark_forest+128};
  825. static char isValid[256];
  826. unsigned int i;
  827. if (!isValid[mansionBiomeList[0]])
  828. for (i = 0; i < sizeof(mansionBiomeList) / sizeof(int); i++)
  829. isValid[ mansionBiomeList[i] ] = 1;
  830. return isValid;
  831. }
  832. static int mapViableBiome(const Layer * l, int * out, int x, int z, int w, int h)
  833. {
  834. int err = mapBiome(l, out, x, z, w, h);
  835. if U(err != 0)
  836. return err;
  837. int styp = * (const int*) l->data;
  838. int i, j;
  839. for (j = 0; j < h; j++)
  840. {
  841. for (i = 0; i < w; i++)
  842. {
  843. int biomeID = out[i + w*j];
  844. switch (styp)
  845. {
  846. case Desert_Pyramid:
  847. if (biomeID == desert || getBiomeType(biomeID) == Mesa)
  848. return 0;
  849. break;
  850. case Jungle_Pyramid:
  851. if (biomeID == jungle)
  852. return 0;
  853. break;
  854. case Swamp_Hut:
  855. if (biomeID == swamp)
  856. return 0;
  857. break;
  858. case Igloo:
  859. if (biomeID == snowy_tundra || biomeID == snowy_taiga)
  860. return 0;
  861. break;
  862. case Ocean_Ruin:
  863. case Shipwreck:
  864. case Monument:
  865. if (isOceanic(biomeID))
  866. return 0;
  867. break;
  868. case Mansion:
  869. if (biomeID == dark_forest)
  870. return 0;
  871. break;
  872. default:
  873. return 0;
  874. }
  875. }
  876. }
  877. return 1; // required biomes not found: set err status to stop generator
  878. }
  879. static int mapViableShore(const Layer * l, int * out, int x, int z, int w, int h)
  880. {
  881. int err = mapShore(l, out, x, z, w, h);
  882. if U(err != 0)
  883. return err;
  884. int styp = * (const int*) l->data;
  885. int i, j;
  886. for (j = 0; j < h; j++)
  887. {
  888. for (i = 0; i < w; i++)
  889. {
  890. int biomeID = out[i + w*j];
  891. switch (styp)
  892. {
  893. case Desert_Pyramid:
  894. case Jungle_Pyramid:
  895. case Swamp_Hut:
  896. case Igloo:
  897. case Ocean_Ruin:
  898. case Shipwreck:
  899. case Village:
  900. case Monument:
  901. case Mansion:
  902. if (isViableFeatureBiome(styp, biomeID))
  903. return 0;
  904. break;
  905. default:
  906. return 0;
  907. }
  908. }
  909. }
  910. return 1;
  911. }
  912. int isViableStructurePos(int structureType, int mcversion, LayerStack *g,
  913. int64_t seed, int blockX, int blockZ)
  914. {
  915. int *map = NULL;
  916. Layer *l;
  917. int biome;
  918. int viable;
  919. int64_t chunkX = blockX >> 4;
  920. int64_t chunkZ = blockZ >> 4;
  921. Layer lbiome = g->layers[L_BIOME_256];
  922. Layer lshore = g->layers[L_SHORE_16];
  923. g->layers[L_BIOME_256].data = (void*) &structureType;
  924. g->layers[L_BIOME_256].getMap = mapViableBiome;
  925. g->layers[L_SHORE_16].data = (void*) &structureType;
  926. g->layers[L_SHORE_16].getMap = mapViableShore;
  927. switch (structureType)
  928. {
  929. case Desert_Pyramid:
  930. case Jungle_Pyramid:
  931. case Swamp_Hut:
  932. case Igloo:
  933. case Ocean_Ruin:
  934. case Shipwreck:
  935. case Treasure:
  936. if (mcversion < MC_1_16)
  937. {
  938. l = &g->layers[L_VORONOI_ZOOM_1];
  939. }
  940. else
  941. { // In 1.16 the position and layer for the biome dependence changed
  942. // to the centre of a chunk at scale 4. Using L_RIVER_MIX_4
  943. // (without ocean type) should be fine for ruins and wrecks.
  944. l = &g->layers[L_RIVER_MIX_4];
  945. blockX = (chunkX << 2) + 2;
  946. blockZ = (chunkZ << 2) + 2;
  947. }
  948. setWorldSeed(l, seed);
  949. map = allocCache(l, 1, 1);
  950. if (genArea(l, map, blockX, blockZ, 1, 1))
  951. goto L_NOT_VIABLE;
  952. if (!isViableFeatureBiome(structureType, map[0]))
  953. goto L_NOT_VIABLE;
  954. goto L_VIABLE;
  955. case Village:
  956. if (mcversion < MC_1_16)
  957. { // TODO: check this (and if it makes a difference)
  958. blockX >>= 2;
  959. blockZ >>= 2;
  960. }
  961. else
  962. {
  963. blockX = (chunkX << 2) + 2;
  964. blockZ = (chunkZ << 2) + 2;
  965. }
  966. l = &g->layers[L_RIVER_MIX_4];
  967. setWorldSeed(l, seed);
  968. map = allocCache(l, 1, 1);
  969. if (genArea(l, map, blockX, blockZ, 1, 1))
  970. goto L_NOT_VIABLE;
  971. biome = map[0];
  972. if (biome == plains || biome == desert || biome == savanna || biome == taiga)
  973. goto L_VIABLE;
  974. else if (mcversion >= MC_1_14 && biome == snowy_tundra)
  975. goto L_VIABLE;
  976. else if (mcversion == MC_BE && biome == snowy_taiga)
  977. goto L_VIABLE;
  978. else
  979. goto L_NOT_VIABLE;
  980. case Outpost:
  981. {
  982. if (!testOutpostPos(seed, chunkX, chunkZ))
  983. goto L_NOT_VIABLE;
  984. if (mcversion < MC_1_16)
  985. {
  986. l = &g->layers[L_VORONOI_ZOOM_1];
  987. }
  988. else
  989. {
  990. l = &g->layers[L_RIVER_MIX_4];
  991. blockX = (chunkX << 2) + 2;
  992. blockZ = (chunkZ << 2) + 2;
  993. }
  994. setWorldSeed(l, seed);
  995. map = allocCache(l, 1, 1);
  996. if (genArea(l, map, blockX, blockZ, 1, 1))
  997. goto L_NOT_VIABLE;
  998. biome = map[0];
  999. // TODO: support for MC_BE
  1000. if (biome != plains && biome != desert && biome != taiga && biome != snowy_tundra && biome != savanna)
  1001. goto L_NOT_VIABLE;
  1002. // look for villages within 10 chunks
  1003. int cx0 = (chunkX-10), cx1 = (chunkX+10);
  1004. int cz0 = (chunkZ-10), cz1 = (chunkZ+10);
  1005. int rx, rz;
  1006. for (rz = cz0 >> 5; rz <= cz1 >> 5; rz++)
  1007. {
  1008. for (rx = cx0 >> 5; rx <= cx1 >> 5; rx++)
  1009. {
  1010. Pos p = getFeaturePos(VILLAGE_CONFIG, seed, rx, rz);
  1011. int cx = p.x >> 4, cz = p.z >> 4;
  1012. if (cx >= cx0 && cx <= cx1 && cz >= cz0 && cz <= cz1)
  1013. {
  1014. if (mcversion >= MC_1_16)
  1015. goto L_NOT_VIABLE;
  1016. if (isViableStructurePos(Village, mcversion, g, seed, p.x, p.z))
  1017. goto L_NOT_VIABLE;
  1018. goto L_VIABLE;
  1019. }
  1020. }
  1021. }
  1022. goto L_VIABLE;
  1023. }
  1024. case Monument:
  1025. if (mcversion >= MC_1_9)
  1026. {
  1027. // Monuments require two viability checks with the ocean layer
  1028. // branch => worth checking for potential deep ocean beforehand.
  1029. l = &g->layers[L_SHORE_16];
  1030. setWorldSeed(l, seed);
  1031. map = allocCache(l, 1, 1);
  1032. if (genArea(l, map, chunkX, chunkZ, 1, 1))
  1033. goto L_NOT_VIABLE;
  1034. }
  1035. else
  1036. {
  1037. // In 1.8 monuments require only a single deep ocean block.
  1038. l = g->entry_1;
  1039. setWorldSeed(l, seed);
  1040. map = allocCache(l, 1, 1);
  1041. if (genArea(l, map, blockX, blockZ, 1, 1))
  1042. goto L_NOT_VIABLE;
  1043. }
  1044. if (!isDeepOcean(map[0]))
  1045. goto L_NOT_VIABLE;
  1046. if (mcversion >= MC_1_13)
  1047. l = &g->layers[L13_OCEAN_MIX_4];
  1048. else
  1049. l = &g->layers[L_RIVER_MIX_4];
  1050. setWorldSeed(l, seed);
  1051. if (mcversion < MC_1_9 || areBiomesViable(l, NULL, blockX, blockZ, 16, getValidMonumentBiomes2()))
  1052. if (areBiomesViable(l, NULL, blockX, blockZ, 29, getValidMonumentBiomes1()))
  1053. goto L_VIABLE;
  1054. goto L_NOT_VIABLE;
  1055. case Mansion:
  1056. l = &g->layers[L_RIVER_MIX_4];
  1057. setWorldSeed(l, seed);
  1058. if (areBiomesViable(l, NULL, blockX, blockZ, 32, getValidMansionBiomes()))
  1059. goto L_VIABLE;
  1060. goto L_NOT_VIABLE;
  1061. case Ruined_Portal:
  1062. goto L_VIABLE;
  1063. default:
  1064. fprintf(stderr, "ERR isViableStructurePos: validation for structure type not implemented");
  1065. goto L_NOT_VIABLE;
  1066. }
  1067. L_NOT_VIABLE:
  1068. viable = 0;
  1069. if (0) {
  1070. L_VIABLE:
  1071. viable = 1;
  1072. }
  1073. g->layers[L_BIOME_256] = lbiome;
  1074. g->layers[L_SHORE_16] = lshore;
  1075. if (map)
  1076. free(map);
  1077. return viable;
  1078. }
  1079. //==============================================================================
  1080. // Finding Properties of Structures
  1081. //==============================================================================
  1082. int isZombieVillage(const int mcversion, const int64_t worldSeed,
  1083. const int regionX, const int regionZ)
  1084. {
  1085. Pos pos;
  1086. int64_t seed = worldSeed;
  1087. if (mcversion < MC_1_10)
  1088. {
  1089. printf("Warning: Zombie villages were only introduced in MC 1.10.\n");
  1090. }
  1091. // get the chunk position of the village
  1092. seed = regionX*341873128712 + regionZ*132897987541 + seed + VILLAGE_CONFIG.salt;
  1093. seed = (seed ^ 0x5deece66dLL);// & ((1LL << 48) - 1);
  1094. seed = (seed * 0x5deece66dLL + 0xbLL) & 0xffffffffffff;
  1095. pos.x = (seed >> 17) % VILLAGE_CONFIG.chunkRange;
  1096. seed = (seed * 0x5deece66dLL + 0xbLL) & 0xffffffffffff;
  1097. pos.z = (seed >> 17) % VILLAGE_CONFIG.chunkRange;
  1098. pos.x += regionX * VILLAGE_CONFIG.regionSize;
  1099. pos.z += regionZ * VILLAGE_CONFIG.regionSize;
  1100. // jump to the random number check that determines whether this is village
  1101. // is zombie infested
  1102. int64_t rnd = chunkGenerateRnd(worldSeed, pos.x , pos.z);
  1103. skipNextN(&rnd, mcversion == MC_1_13 ? 10 : 11);
  1104. return nextInt(&rnd, 50) == 0;
  1105. }
  1106. int64_t getHouseList(const int64_t worldSeed, const int chunkX, const int chunkZ,
  1107. int *out)
  1108. {
  1109. int64_t rnd = chunkGenerateRnd(worldSeed, chunkX, chunkZ);
  1110. skipNextN(&rnd, 1);
  1111. out[HouseSmall] = nextInt(&rnd, 4 - 2 + 1) + 2;
  1112. out[Church] = nextInt(&rnd, 1 - 0 + 1) + 0;
  1113. out[Library] = nextInt(&rnd, 2 - 0 + 1) + 0;
  1114. out[WoodHut] = nextInt(&rnd, 5 - 2 + 1) + 2;
  1115. out[Butcher] = nextInt(&rnd, 2 - 0 + 1) + 0;
  1116. out[FarmLarge] = nextInt(&rnd, 4 - 1 + 1) + 1;
  1117. out[FarmSmall] = nextInt(&rnd, 4 - 2 + 1) + 2;
  1118. out[Blacksmith] = nextInt(&rnd, 1 - 0 + 1) + 0;
  1119. out[HouseLarge] = nextInt(&rnd, 3 - 0 + 1) + 0;
  1120. return rnd;
  1121. }
  1122. //==============================================================================
  1123. // Seed Filters
  1124. //==============================================================================
  1125. BiomeFilter setupBiomeFilter(const int *biomeList, int listLen)
  1126. {
  1127. BiomeFilter bf;
  1128. int i, id;
  1129. memset(&bf, 0, sizeof(bf));
  1130. for (i = 0; i < listLen; i++)
  1131. {
  1132. id = biomeList[i];
  1133. if (id & ~0xbf) // i.e. not in ranges [0,64),[128,192)
  1134. {
  1135. fprintf(stderr, "ERR: biomeID=%d not supported by filter.\n", id);
  1136. exit(-1);
  1137. }
  1138. switch (id)
  1139. {
  1140. case mushroom_fields:
  1141. // mushroom shores can generate with hills and at rivers
  1142. bf.raresToFind |= (1ULL << mushroom_fields);
  1143. case mushroom_field_shore:
  1144. bf.tempsToFind |= (1ULL << Oceanic);
  1145. bf.majorToFind |= (1ULL << mushroom_fields);
  1146. bf.riverToFind |= (1ULL << id);
  1147. break;
  1148. case badlands_plateau:
  1149. case wooded_badlands_plateau:
  1150. case badlands:
  1151. case eroded_badlands:
  1152. case modified_badlands_plateau:
  1153. case modified_wooded_badlands_plateau:
  1154. bf.tempsToFind |= (1ULL << (Warm+Special));
  1155. if (id == badlands_plateau || id == modified_badlands_plateau)
  1156. bf.majorToFind |= (1ULL << badlands_plateau);
  1157. if (id == wooded_badlands_plateau || id == modified_wooded_badlands_plateau)
  1158. bf.majorToFind |= (1ULL << wooded_badlands_plateau);
  1159. if (id < 128) {
  1160. bf.raresToFind |= (1ULL << id);
  1161. bf.riverToFind |= (1ULL << id);
  1162. } else {
  1163. bf.raresToFindM |= (1ULL << (id-128));
  1164. bf.riverToFindM |= (1ULL << (id-128));
  1165. }
  1166. break;
  1167. case jungle:
  1168. case jungle_edge:
  1169. case jungle_hills:
  1170. case modified_jungle:
  1171. case modified_jungle_edge:
  1172. case bamboo_jungle:
  1173. case bamboo_jungle_hills:
  1174. bf.tempsToFind |= (1ULL << (Lush+Special));
  1175. bf.majorToFind |= (1ULL << jungle);
  1176. if (id == bamboo_jungle || id == bamboo_jungle_hills) {
  1177. // bamboo%64 are End biomes, so we can reuse the edgesToFind
  1178. bf.edgesToFind |= (1ULL << (bamboo_jungle & 0x3f));
  1179. } else if (id == jungle_edge) {
  1180. // un-modified jungle_edge can be created at shore layer
  1181. bf.riverToFind |= (1ULL << jungle_edge);
  1182. } else {
  1183. if (id == modified_jungle_edge)
  1184. bf.edgesToFind |= (1ULL << jungle_edge);
  1185. else
  1186. bf.edgesToFind |= (1ULL << jungle);
  1187. if (id < 128) {
  1188. bf.raresToFind |= (1ULL << id);
  1189. bf.riverToFind |= (1ULL << id);
  1190. } else {
  1191. bf.raresToFindM |= (1ULL << (id-128));
  1192. bf.riverToFindM |= (1ULL << (id-128));
  1193. }
  1194. }
  1195. break;
  1196. case giant_tree_taiga:
  1197. case giant_tree_taiga_hills:
  1198. case giant_spruce_taiga:
  1199. case giant_spruce_taiga_hills:
  1200. bf.tempsToFind |= (1ULL << (Cold+Special));
  1201. bf.majorToFind |= (1ULL << giant_tree_taiga);
  1202. bf.edgesToFind |= (1ULL << giant_tree_taiga);
  1203. if (id < 128) {
  1204. bf.raresToFind |= (1ULL << id);
  1205. bf.riverToFind |= (1ULL << id);
  1206. } else {
  1207. bf.raresToFindM |= (1ULL << (id-128));
  1208. bf.riverToFindM |= (1ULL << (id-128));
  1209. }
  1210. break;
  1211. case savanna:
  1212. case savanna_plateau:
  1213. case shattered_savanna:
  1214. case shattered_savanna_plateau:
  1215. case desert_hills:
  1216. case desert_lakes:
  1217. bf.tempsToFind |= (1ULL << Warm);
  1218. if (id == desert_hills || id == desert_lakes) {
  1219. bf.majorToFind |= (1ULL << desert);
  1220. bf.edgesToFind |= (1ULL << desert);
  1221. } else {
  1222. bf.majorToFind |= (1ULL << savanna);
  1223. bf.edgesToFind |= (1ULL << savanna);
  1224. }
  1225. if (id < 128) {
  1226. bf.raresToFind |= (1ULL << id);
  1227. bf.riverToFind |= (1ULL << id);
  1228. } else {
  1229. bf.raresToFindM |= (1ULL << (id-128));
  1230. bf.riverToFindM |= (1ULL << (id-128));
  1231. }
  1232. break;
  1233. case dark_forest:
  1234. case dark_forest_hills:
  1235. case birch_forest:
  1236. case birch_forest_hills:
  1237. case tall_birch_forest:
  1238. case tall_birch_hills:
  1239. case swamp:
  1240. case swamp_hills:
  1241. bf.tempsToFind |= (1ULL << Lush);
  1242. if (id == dark_forest || id == dark_forest_hills) {
  1243. bf.majorToFind |= (1ULL << dark_forest);
  1244. bf.edgesToFind |= (1ULL << dark_forest);
  1245. }
  1246. else if (id == birch_forest || id == birch_forest_hills ||
  1247. id == tall_birch_forest || id == tall_birch_hills) {
  1248. bf.majorToFind |= (1ULL << birch_forest);
  1249. bf.edgesToFind |= (1ULL << birch_forest);
  1250. }
  1251. else if (id == swamp || id == swamp_hills) {
  1252. bf.majorToFind |= (1ULL << swamp);
  1253. bf.edgesToFind |= (1ULL << swamp);
  1254. }
  1255. if (id < 128) {
  1256. bf.raresToFind |= (1ULL << id);
  1257. bf.riverToFind |= (1ULL << id);
  1258. } else {
  1259. bf.raresToFindM |= (1ULL << (id-128));
  1260. bf.riverToFindM |= (1ULL << (id-128));
  1261. }
  1262. break;
  1263. case snowy_taiga:
  1264. case snowy_taiga_hills:
  1265. case snowy_taiga_mountains:
  1266. case snowy_tundra:
  1267. case snowy_mountains:
  1268. case ice_spikes:
  1269. case frozen_river:
  1270. bf.tempsToFind |= (1ULL << Freezing);
  1271. if (id == snowy_taiga || id == snowy_taiga_hills ||
  1272. id == snowy_taiga_mountains)
  1273. bf.edgesToFind |= (1ULL << snowy_taiga);
  1274. else
  1275. bf.edgesToFind |= (1ULL << snowy_tundra);
  1276. if (id == frozen_river) {
  1277. bf.raresToFind |= (1ULL << snowy_tundra);
  1278. bf.riverToFind |= (1ULL << id);
  1279. } else if (id < 128) {
  1280. bf.raresToFind |= (1ULL << id);
  1281. bf.riverToFind |= (1ULL << id);
  1282. } else {
  1283. bf.raresToFindM |= (1ULL << (id-128));
  1284. bf.riverToFindM |= (1ULL << (id-128));
  1285. }
  1286. break;
  1287. case sunflower_plains:
  1288. bf.raresToFindM |= (1ULL << (id-128));
  1289. bf.riverToFindM |= (1ULL << (id-128));
  1290. break;
  1291. case snowy_beach:
  1292. bf.tempsToFind |= (1ULL << Freezing);
  1293. case beach:
  1294. case stone_shore:
  1295. bf.riverToFind |= (1ULL << id);
  1296. break;
  1297. case mountains:
  1298. bf.majorToFind |= (1ULL << mountains);
  1299. case wooded_mountains:
  1300. bf.raresToFind |= (1ULL << id);
  1301. bf.riverToFind |= (1ULL << id);
  1302. break;
  1303. case gravelly_mountains:
  1304. bf.majorToFind |= (1ULL << mountains);
  1305. case modified_gravelly_mountains:
  1306. bf.raresToFindM |= (1ULL << (id-128));
  1307. bf.riverToFindM |= (1ULL << (id-128));
  1308. break;
  1309. case taiga:
  1310. case taiga_hills:
  1311. bf.edgesToFind |= (1ULL << taiga);
  1312. bf.raresToFind |= (1ULL << id);
  1313. bf.riverToFind |= (1ULL << id);
  1314. break;
  1315. case taiga_mountains:
  1316. bf.edgesToFind |= (1ULL << taiga);
  1317. bf.raresToFindM |= (1ULL << (id-128));
  1318. bf.riverToFindM |= (1ULL << (id-128));
  1319. break;
  1320. case plains:
  1321. case forest:
  1322. case wooded_hills:
  1323. bf.raresToFind |= (1ULL << id);
  1324. bf.riverToFind |= (1ULL << id);
  1325. break;
  1326. case flower_forest:
  1327. bf.raresToFindM |= (1ULL << (id-128));
  1328. bf.riverToFindM |= (1ULL << (id-128));
  1329. break;
  1330. case desert: // can generate at shore layer
  1331. bf.riverToFind |= (1ULL << id);
  1332. break;
  1333. default:
  1334. if (isOceanic(id)) {
  1335. bf.tempsToFind |= (1ULL << Oceanic);
  1336. bf.oceanToFind |= (1ULL << id);
  1337. if (isShallowOcean(id)) {
  1338. bf.otempToFind |= (1ULL << id);
  1339. } else {
  1340. bf.raresToFind |= (1ULL << deep_ocean);
  1341. bf.riverToFind |= (1ULL << deep_ocean);
  1342. if (id == deep_warm_ocean)
  1343. bf.otempToFind |= (1ULL << warm_ocean);
  1344. else if (id == deep_lukewarm_ocean)
  1345. bf.otempToFind |= (1ULL << lukewarm_ocean);
  1346. else if (id == deep_ocean)
  1347. bf.otempToFind |= (1ULL << ocean);
  1348. else if (id == deep_cold_ocean)
  1349. bf.otempToFind |= (1ULL << cold_ocean);
  1350. else if (id == deep_frozen_ocean)
  1351. bf.otempToFind |= (1ULL << frozen_ocean);
  1352. }
  1353. } else {
  1354. if (id < 64)
  1355. bf.riverToFind |= (1ULL << id);
  1356. else
  1357. bf.riverToFindM |= (1ULL << (id-128));
  1358. }
  1359. break;
  1360. }
  1361. }
  1362. bf.shoreToFind = bf.riverToFind;
  1363. bf.shoreToFind &= ~((1ULL << river) | (1ULL << frozen_river));
  1364. bf.shoreToFindM = bf.riverToFindM;
  1365. bf.specialCnt = 0;
  1366. bf.specialCnt += !!(bf.tempsToFind & (1ULL << (Warm+Special)));
  1367. bf.specialCnt += !!(bf.tempsToFind & (1ULL << (Lush+Special)));
  1368. bf.specialCnt += !!(bf.tempsToFind & (1ULL << (Cold+Special)));
  1369. return bf;
  1370. }
  1371. static int mapFilterSpecial(const Layer * l, int * out, int x, int z, int w, int h)
  1372. {
  1373. const BiomeFilter *bf = (const BiomeFilter*) l->data;
  1374. int i, j;
  1375. uint64_t temps;
  1376. /// pre-gen checks
  1377. int specialcnt = bf->specialCnt;
  1378. if (specialcnt > 0)
  1379. {
  1380. int64_t ss = l->startSeed;
  1381. int64_t cs;
  1382. for (j = 0; j < h; j++)
  1383. {
  1384. for (i = 0; i < w; i++)
  1385. {
  1386. cs = getChunkSeed(ss, x+i, z+j);
  1387. if (mcFirstIsZero(cs, 13))
  1388. specialcnt--;
  1389. }
  1390. }
  1391. if (specialcnt > 0)
  1392. return 1;
  1393. }
  1394. int err = mapSpecial(l, out, x, z, w, h);
  1395. if U(err != 0)
  1396. return err;
  1397. temps = 0;
  1398. for (j = 0; j < h; j++)
  1399. {
  1400. for (i = 0; i < w; i++)
  1401. {
  1402. int id = out[i + w*j];
  1403. int isspecial = id & 0xf00;
  1404. id &= ~0xf00;
  1405. if (isspecial && id != Freezing)
  1406. temps |= (1ULL << (id+Special));
  1407. else
  1408. temps |= (1ULL << id);
  1409. }
  1410. }
  1411. if ((temps & bf->tempsToFind) ^ bf->tempsToFind)
  1412. return 1;
  1413. return 0;
  1414. }
  1415. static int mapFilterMushroom(const Layer * l, int * out, int x, int z, int w, int h)
  1416. {
  1417. const BiomeFilter *bf = (const BiomeFilter*) l->data;
  1418. int i, j;
  1419. int err;
  1420. if (w*h < 100 && (bf->majorToFind & (1ULL << mushroom_fields)))
  1421. {
  1422. int64_t ss = l->startSeed;
  1423. int64_t cs;
  1424. for (j = 0; j < h; j++)
  1425. {
  1426. for (i = 0; i < w; i++)
  1427. {
  1428. cs = getChunkSeed(ss, i+x, j+z);
  1429. if (mcFirstIsZero(cs, 100))
  1430. goto L_GENERATE;
  1431. }
  1432. }
  1433. return 1;
  1434. }
  1435. L_GENERATE:
  1436. err = mapAddMushroomIsland(l, out, x, z, w, h);
  1437. if U(err != 0)
  1438. return err;
  1439. if (bf->majorToFind & (1ULL << mushroom_fields))
  1440. {
  1441. for (i = 0; i < w*h; i++)
  1442. if (out[i] == mushroom_fields)
  1443. return 0;
  1444. return 1;
  1445. }
  1446. return 0;
  1447. }
  1448. static int mapFilterBiome(const Layer * l, int * out, int x, int z, int w, int h)
  1449. {
  1450. const BiomeFilter *bf = (const BiomeFilter*) l->data;
  1451. int i, j;
  1452. uint64_t b;
  1453. int err = mapBiome(l, out, x, z, w, h);
  1454. if U(err != 0)
  1455. return err;
  1456. b = 0;
  1457. for (j = 0; j < h; j++)
  1458. {
  1459. for (i = 0; i < w; i++)
  1460. {
  1461. int id = out[i + w*j];
  1462. b |= (1ULL << id);
  1463. }
  1464. }
  1465. if ((b & bf->majorToFind) ^ bf->majorToFind)
  1466. return 1;
  1467. return 0;
  1468. }
  1469. static int mapFilterOceanTemp(const Layer * l, int * out, int x, int z, int w, int h)
  1470. {
  1471. const BiomeFilter *bf = (const BiomeFilter*) l->data;
  1472. int i, j;
  1473. uint64_t b;
  1474. int err = mapOceanTemp(l, out, x, z, w, h);
  1475. if U(err != 0)
  1476. return err;
  1477. b = 0;
  1478. for (j = 0; j < h; j++)
  1479. {
  1480. for (i = 0; i < w; i++)
  1481. {
  1482. int id = out[i + w*j];
  1483. b |= (1ULL << id);
  1484. }
  1485. }
  1486. if ((b & bf->otempToFind) ^ bf->otempToFind)
  1487. return 1;
  1488. return 0;
  1489. }
  1490. static int mapFilterBiomeEdge(const Layer * l, int * out, int x, int z, int w, int h)
  1491. {
  1492. const BiomeFilter *bf = (const BiomeFilter*) l->data;
  1493. uint64_t b;
  1494. int i;
  1495. int err;
  1496. err = mapBiomeEdge(l, out, x, z, w, h);
  1497. if U(err != 0)
  1498. return err;
  1499. b = 0;
  1500. for (i = 0; i < w*h; i++)
  1501. b |= (1ULL << (out[i] & 0x3f));
  1502. if ((b & bf->edgesToFind) ^ bf->edgesToFind)
  1503. return 1;
  1504. return 0;
  1505. }
  1506. static int mapFilterRareBiome(const Layer * l, int * out, int x, int z, int w, int h)
  1507. {
  1508. const BiomeFilter *bf = (const BiomeFilter*) l->data;
  1509. uint64_t b, bm;
  1510. int i;
  1511. int err;
  1512. err = mapRareBiome(l, out, x, z, w, h);
  1513. if U(err != 0)
  1514. return err;
  1515. b = 0; bm = 0;
  1516. for (i = 0; i < w*h; i++)
  1517. {
  1518. int id = out[i];
  1519. if (id < 128) b |= (1ULL << id);
  1520. else bm |= (1ULL << (id-128));
  1521. }
  1522. if ((b & bf->raresToFind) ^ bf->raresToFind)
  1523. return 1;
  1524. if ((bm & bf->raresToFindM) ^ bf->raresToFindM)
  1525. return 1;
  1526. return 0;
  1527. }
  1528. static int mapFilterShore(const Layer * l, int * out, int x, int z, int w, int h)
  1529. {
  1530. const BiomeFilter *bf = (const BiomeFilter*) l->data;
  1531. uint64_t b, bm;
  1532. int i;
  1533. int err = mapShore(l, out, x, z, w, h);
  1534. if U(err != 0) return err;
  1535. b = 0; bm = 0;
  1536. for (i = 0; i < w*h; i++)
  1537. {
  1538. int id = out[i];
  1539. if (id < 128) b |= (1ULL << id);
  1540. else bm |= (1ULL << (id-128));
  1541. }
  1542. if ((b & bf->shoreToFind) ^ bf->shoreToFind)
  1543. return 1;
  1544. if ((bm & bf->shoreToFindM) ^ bf->shoreToFindM)
  1545. return 1;
  1546. return 0;
  1547. }
  1548. static int mapFilterRiverMix(const Layer * l, int * out, int x, int z, int w, int h)
  1549. {
  1550. const BiomeFilter *bf = (const BiomeFilter*) l->data;
  1551. uint64_t b, bm;
  1552. int i;
  1553. int err = mapRiverMix(l, out, x, z, w, h);
  1554. if U(err != 0) return err;
  1555. b = 0; bm = 0;
  1556. for (i = 0; i < w*h; i++)
  1557. {
  1558. int id = out[i];
  1559. if (id < 128) b |= (1ULL << id);
  1560. else bm |= (1ULL << (id-128));
  1561. }
  1562. if ((b & bf->riverToFind) ^ bf->riverToFind)
  1563. return 1;
  1564. if ((bm & bf->riverToFindM) ^ bf->riverToFindM)
  1565. return 1;
  1566. return 0;
  1567. }
  1568. static int mapFilterOceanMix(const Layer * l, int * out, int x, int z, int w, int h)
  1569. {
  1570. const BiomeFilter *bf = (const BiomeFilter*) l->data;
  1571. uint64_t b;
  1572. int i;
  1573. int err;
  1574. if (bf->riverToFind)
  1575. {
  1576. err = mapRiverMix(l, out, x, z, w, h);
  1577. if (err) return err;
  1578. }
  1579. err = mapOceanMix(l, out, x, z, w, h);
  1580. if U(err != 0) return err;
  1581. b = 0;
  1582. for (i = 0; i < w*h; i++)
  1583. {
  1584. int id = out[i];
  1585. if (id < 128) b |= (1ULL << id);
  1586. }
  1587. if ((b & bf->oceanToFind) ^ bf->oceanToFind)
  1588. return 1;
  1589. return 0;
  1590. }
  1591. int checkForBiomes(
  1592. LayerStack * g,
  1593. int layerID,
  1594. int * cache,
  1595. int64_t seed,
  1596. int x,
  1597. int z,
  1598. unsigned int w,
  1599. unsigned int h,
  1600. BiomeFilter filter,
  1601. int protoCheck
  1602. )
  1603. {
  1604. Layer *l;
  1605. if (protoCheck)
  1606. {
  1607. l = &g->layers[layerID];
  1608. int i, j;
  1609. int bx = x * l->scale;
  1610. int bz = z * l->scale;
  1611. int bw = w * l->scale;
  1612. int bh = h * l->scale;
  1613. int x0, z0, x1, z1;
  1614. int64_t ss, cs;
  1615. uint64_t potential, required;
  1616. int specialcnt = filter.specialCnt;
  1617. if (specialcnt > 0)
  1618. {
  1619. l = &g->layers[L_SPECIAL_1024];
  1620. x0 = (bx) / l->scale; if (x < 0) x0--;
  1621. z0 = (bz) / l->scale; if (z < 0) z0--;
  1622. x1 = (bx + bw) / l->scale; if (x+w >= 0) x1++;
  1623. z1 = (bz + bh) / l->scale; if (z+h >= 0) z1++;
  1624. ss = getStartSeed(seed, l->layerSeed);
  1625. for (j = z0; j <= z1; j++)
  1626. {
  1627. for (i = x0; i <= x1; i++)
  1628. {
  1629. cs = getChunkSeed(ss, i, j);
  1630. if (mcFirstIsZero(cs, 13))
  1631. specialcnt--;
  1632. }
  1633. }
  1634. if (specialcnt > 0)
  1635. return 0;
  1636. }
  1637. l = &g->layers[L_BIOME_256];
  1638. x0 = bx / l->scale; if (x < 0) x0--;
  1639. z0 = bz / l->scale; if (z < 0) z0--;
  1640. x1 = (bx + bw) / l->scale; if (x+w >= 0) x1++;
  1641. z1 = (bz + bh) / l->scale; if (z+h >= 0) z1++;
  1642. if (filter.majorToFind & (1ULL << mushroom_fields))
  1643. {
  1644. ss = getStartSeed(seed, g->layers[L_ADD_MUSHROOM_256].layerSeed);
  1645. for (j = z0; j <= z1; j++)
  1646. {
  1647. for (i = x0; i <= x1; i++)
  1648. {
  1649. cs = getChunkSeed(ss, i, j);
  1650. if (mcFirstIsZero(cs, 100))
  1651. goto L_HAS_PROTO_MUSHROOM;
  1652. }
  1653. }
  1654. return 0;
  1655. }
  1656. L_HAS_PROTO_MUSHROOM:
  1657. potential = 0;
  1658. required = filter.majorToFind & (
  1659. (1ULL << badlands_plateau) | (1ULL << wooded_badlands_plateau) |
  1660. (1ULL << desert) | (1ULL << savanna) | (1ULL << plains) |
  1661. (1ULL << forest) | (1ULL << dark_forest) | (1ULL << mountains) |
  1662. (1ULL << birch_forest) | (1ULL << swamp));
  1663. ss = getStartSeed(seed, l->layerSeed);
  1664. for (j = z0; j <= z1; j++)
  1665. {
  1666. for (i = x0; i <= x1; i++)
  1667. {
  1668. cs = getChunkSeed(ss, i, j);
  1669. int cs6 = mcFirstInt(cs, 6);
  1670. int cs3 = mcFirstInt(cs, 3);
  1671. int cs4 = mcFirstInt(cs, 4);
  1672. if (cs3) potential |= (1ULL << badlands_plateau);
  1673. else potential |= (1ULL << wooded_badlands_plateau);
  1674. switch (cs6)
  1675. {
  1676. case 0: potential |= (1ULL << desert) | (1ULL << forest); break;
  1677. case 1: potential |= (1ULL << desert) | (1ULL << dark_forest); break;
  1678. case 2: potential |= (1ULL << desert) | (1ULL << mountains); break;
  1679. case 3: potential |= (1ULL << savanna) | (1ULL << plains); break;
  1680. case 4: potential |= (1ULL << savanna) | (1ULL << birch_forest); break;
  1681. case 5: potential |= (1ULL << plains) | (1ULL << swamp); break;
  1682. }
  1683. if (cs4 == 3) potential |= (1ULL << snowy_taiga);
  1684. else potential |= (1ULL << snowy_tundra);
  1685. }
  1686. }
  1687. if ((potential & required) ^ required)
  1688. return 0;
  1689. }
  1690. l = &g->layers[layerID];
  1691. int *map = cache ? cache : allocCache(l, w, h);
  1692. g->layers[L_SPECIAL_1024].data = (void*) &filter;
  1693. g->layers[L_SPECIAL_1024].getMap = mapFilterSpecial;
  1694. g->layers[L_ADD_MUSHROOM_256].data = (void*) &filter;
  1695. g->layers[L_ADD_MUSHROOM_256].getMap = mapFilterMushroom;
  1696. g->layers[L_BIOME_256].data = (void*) &filter;
  1697. g->layers[L_BIOME_256].getMap = mapFilterBiome;
  1698. g->layers[L13_OCEAN_TEMP_256].data = (void*) &filter;
  1699. g->layers[L13_OCEAN_TEMP_256].getMap = mapFilterOceanTemp;
  1700. g->layers[L_BIOME_EDGE_64].data = (void*) &filter;
  1701. g->layers[L_BIOME_EDGE_64].getMap = mapFilterBiomeEdge;
  1702. g->layers[L_RARE_BIOME_64].data = (void*) &filter;
  1703. g->layers[L_RARE_BIOME_64].getMap = mapFilterRareBiome;
  1704. g->layers[L_SHORE_16].data = (void*) &filter;
  1705. g->layers[L_SHORE_16].getMap = mapFilterShore;
  1706. g->layers[L_RIVER_MIX_4].data = (void*) &filter;
  1707. g->layers[L_RIVER_MIX_4].getMap = mapFilterRiverMix;
  1708. g->layers[L13_OCEAN_MIX_4].data = (void*) &filter;
  1709. g->layers[L13_OCEAN_MIX_4].getMap = mapFilterOceanMix;
  1710. setWorldSeed(l, seed);
  1711. int ret = !l->getMap(l, map, x, z, w, h);
  1712. if (ret)
  1713. {
  1714. uint64_t required, b = 0, bm = 0;
  1715. unsigned int i;
  1716. for (i = 0; i < w*h; i++)
  1717. {
  1718. int id = map[i];
  1719. if (id < 128) b |= (1ULL << id);
  1720. else bm |= (1ULL << (id-128));
  1721. }
  1722. required = filter.riverToFind;
  1723. required &= ~((1ULL << ocean) | (1ULL << deep_ocean));
  1724. required |= filter.oceanToFind;
  1725. if ((b & required) ^ required)
  1726. ret = -1;
  1727. required = filter.riverToFindM;
  1728. if ((bm & required) ^ required)
  1729. ret = -1;
  1730. }
  1731. g->layers[L_SPECIAL_1024].data = NULL;
  1732. g->layers[L_SPECIAL_1024].getMap = mapSpecial;
  1733. g->layers[L_ADD_MUSHROOM_256].data = NULL;
  1734. g->layers[L_ADD_MUSHROOM_256].getMap = mapAddMushroomIsland;
  1735. g->layers[L_BIOME_256].data = NULL;
  1736. g->layers[L_BIOME_256].getMap = mapBiome;
  1737. g->layers[L13_OCEAN_TEMP_256].data = NULL;
  1738. g->layers[L13_OCEAN_TEMP_256].getMap = mapOceanTemp;
  1739. g->layers[L_BIOME_EDGE_64].data = NULL;
  1740. g->layers[L_BIOME_EDGE_64].getMap = mapBiomeEdge;
  1741. g->layers[L_RARE_BIOME_64].data = NULL;
  1742. g->layers[L_RARE_BIOME_64].getMap = mapRareBiome;
  1743. g->layers[L_SHORE_16].data = NULL;
  1744. g->layers[L_SHORE_16].getMap = mapShore;
  1745. g->layers[L_RIVER_MIX_4].data = NULL;
  1746. g->layers[L_RIVER_MIX_4].getMap = mapRiverMix;
  1747. g->layers[L13_OCEAN_MIX_4].data = NULL;
  1748. g->layers[L13_OCEAN_MIX_4].getMap = mapOceanMix;
  1749. if (cache == NULL)
  1750. free(map);
  1751. return ret;
  1752. }
  1753. int hasAllTemps(LayerStack *g, int64_t seed, int x1024, int z1024)
  1754. {
  1755. int64_t ls;
  1756. ls = getLayerSeed(3); // L_SPECIAL_1024 layer seed
  1757. int64_t ss = getStartSeed(seed, ls);
  1758. int spbits = 0, spcnt = 0;
  1759. if (mcFirstIsZero(getChunkSeed(ss, x1024-1, z1024-1), 13))
  1760. { spbits |= (1<<0); spcnt++; }
  1761. if (mcFirstIsZero(getChunkSeed(ss, x1024 , z1024-1), 13))
  1762. { spbits |= (1<<1); spcnt++; }
  1763. if (mcFirstIsZero(getChunkSeed(ss, x1024+1, z1024-1), 13))
  1764. { spbits |= (1<<2); spcnt++; }
  1765. if (mcFirstIsZero(getChunkSeed(ss, x1024-1, z1024 ), 13))
  1766. { spbits |= (1<<3); spcnt++; }
  1767. if (mcFirstIsZero(getChunkSeed(ss, x1024 , z1024 ), 13))
  1768. { spbits |= (1<<4); spcnt++; }
  1769. if (mcFirstIsZero(getChunkSeed(ss, x1024+1, z1024 ), 13))
  1770. { spbits |= (1<<5); spcnt++; }
  1771. if (mcFirstIsZero(getChunkSeed(ss, x1024-1, z1024+1), 13))
  1772. { spbits |= (1<<6); spcnt++; }
  1773. if (mcFirstIsZero(getChunkSeed(ss, x1024 , z1024+1), 13))
  1774. { spbits |= (1<<7); spcnt++; }
  1775. if (mcFirstIsZero(getChunkSeed(ss, x1024+1, z1024+1), 13))
  1776. { spbits |= (1<<8); spcnt++; }
  1777. if (spcnt < 3)
  1778. return 0;
  1779. // approx. ~2.7% of seeds make it to here
  1780. int buf[20*20];
  1781. int i;
  1782. setWorldSeed(&g->layers[L_HEAT_ICE_1024], seed);
  1783. genArea(&g->layers[L_HEAT_ICE_1024], buf, x1024-1, z1024-1, 3, 3);
  1784. uint64_t bm = 0;
  1785. for (i = 0; i < 9; i++)
  1786. {
  1787. int id = buf[i];
  1788. if (id != 0 && id != Freezing && (spbits & (1<<i)))
  1789. bm |= (1ULL << (id+Special));
  1790. else
  1791. bm |= (1ULL << id);
  1792. }
  1793. // approx. 1 in 100000 seeds satisfy such an all-temperatures cluster
  1794. return ((bm & 0x1df) ^ 0x1df) == 0;
  1795. }