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