Created
June 10, 2021 21:22
-
-
Save reedacartwright/ae9bb75421aa715e28666822367cdeb7 to your computer and use it in GitHub Desktop.
Source code for finding natural wither killers in bedrock edition.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <random> | |
#include <array> | |
#include <iostream> | |
using namespace std; | |
using mat_t = array<array<unsigned int, 32>, 32>; | |
uint32_t get_seed(int d, int x, int z) { | |
if(d == 0) { | |
return x * 0x14609048 + z * 0x7ebe2d5; | |
} else if(d == 1) { | |
return x * -0x66c60af8 + z * -0xea9a42b; | |
} | |
return 0; | |
} | |
/* Wither Killer Pattern | |
011*k* | |
2**kkk | |
2***k* | |
where: | |
k: 4+ high bedrock | |
0: 2-high bedrock | |
1: 2-high bedrock | |
2: 2-high bedrock | |
0 must be true and either 1 or 2 must be true. | |
You also need room to complete placing the skulls | |
sss 011 ss0 | |
sss vs sss vs ss1 vs something with 4 openings | |
011 sss ss1 | |
*/ | |
void find_wither_killers(int dim, int chunk_x, int chunk_z, int extra) { | |
mat_t counts; | |
std::mt19937 gen; | |
auto f = [&](int a, int b) { | |
gen.seed(get_seed(dim, chunk_x+a, chunk_z+b)); | |
for(int x = 0; x < 16; ++x) { | |
for(int z = 0; z < 16; ++z) { | |
unsigned int h = 1 + (gen() % 4); | |
counts[x+a*16][z+b*16] = h+1; | |
for(int i=0; i < extra; ++i) { | |
gen(); | |
} | |
} | |
} | |
}; | |
auto g = [&](int x, int z, const char *p, int h) { | |
if(dim == 1) { | |
cout << "nether,"; | |
} else { | |
cout << "overworld,"; | |
} | |
cout << (chunk_x*16+x) << ",2," << (chunk_z*16+z); | |
if(dim == 0) { | |
cout << (extra != 2 ? ",grassy," : ",sandy,"); | |
} else { | |
cout << (extra != 3 ? ",regular," : ",delta/valley,"); | |
} | |
cout << p << "," << h; | |
cout << endl; | |
}; | |
// generate 4 chunks of bedrock height | |
f(0,0); | |
f(1,0); | |
f(0,1); | |
f(1,1); | |
// look for wither killers | |
for(int x=0; x < 18; ++x) { | |
for(int z=0; z < 18; ++z) { | |
// NW skull | |
bool b0 = counts[x][z] <= 2; | |
if(!b0) { | |
continue; | |
} | |
// Killer Cross | |
bool b4 = true; | |
b4 = b4 && counts[x+4][z+0] >= 4; | |
b4 = b4 && counts[x+3][z+1] >= 4 && counts[x+4][z+1] >= 4 && counts[x+5][z+1] >= 4; | |
b4 = b4 && counts[x+4][z+2] >= 4; | |
if(!b4) { | |
continue; | |
} | |
// NS skulls | |
bool b1 = counts[x][z+1] <= 2 && counts[x][z+2] <= 2; | |
// WE skulls | |
bool b2 = counts[x+1][z] <= 2 && counts[x+2][z] <= 2; | |
if(!(b1 || b2)) { | |
continue; | |
} | |
// Height of center | |
int center_height = counts[x+4][z+1]; | |
// Check for south/east soul sand | |
if(b1 && b2 && x < 16 && z < 16) { | |
bool b5 = true; | |
b5 = b5 && counts[x+1][z+1] <= 2 && counts[x+2][z+1] <= 2; | |
b5 = b5 && counts[x+1][z+2] <= 2 && counts[x+2][z+2] <= 2; | |
if(b5) { | |
g(x,z,"S",center_height); | |
g(x,z,"E",center_height); | |
} | |
} | |
// Check for west soul sand | |
if(b1 && z < 16 && x >= 2 && x < 18) { | |
bool b5 = true; | |
b5 = b5 && counts[x-2][z+0] <= 2 && counts[x-1][z+0] <= 2; | |
b5 = b5 && counts[x-2][z+1] <= 2 && counts[x-1][z+1] <= 2; | |
b5 = b5 && counts[x-2][z+2] <= 2 && counts[x-1][z+2] <= 2; | |
if(b5) { | |
g(x,z,"W",center_height); | |
} | |
} | |
// Check for north soul sand | |
if(b2 && x < 16 && z >= 2 && z < 18) { | |
bool b5 = true; | |
b5 = b5 && counts[x+0][z-2] <= 2 && counts[x+1][z-2] <= 2 && counts[x+2][z-2] <= 2; | |
b5 = b5 && counts[x+0][z-1] <= 2 && counts[x+1][z-1] <= 2 && counts[x+2][z-1] <= 2; | |
if(b5) { | |
g(x,z,"N",center_height); | |
} | |
} | |
} | |
} | |
} | |
int main(int argv, char* argc[]) { | |
const int sz = 256; | |
cout << "dim,x,y,z,biome,direction,center_height" << endl; | |
for(int x=-sz; x < sz; ++x) { | |
for(int z=-sz; z < sz; ++z) { | |
// overworld normal | |
find_wither_killers(0, x, z, 1); | |
// overworld rare (desert and beach biomes, mostly) | |
find_wither_killers(0, x, z, 2); | |
// nether 1.16+ (hell, warped, crimson) | |
// nether 1.16-1.16.40 (soulsand_valey, basalt_deltas) | |
find_wither_killers(1, x, z, 2); | |
// nether 1.16.100+ (soulsand_valley, basalt_deltas) | |
find_wither_killers(1, x, z, 3); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <random> | |
#include <array> | |
#include <iostream> | |
#include <algorithm> | |
using namespace std; | |
using mat_t = array<array<unsigned int, 32>, 32>; | |
uint32_t get_seed(int d, int x, int z) { | |
if(d == 0) { | |
return x * 0x14609048 + z * 0x7ebe2d5; | |
} else if(d == 1) { | |
return x * -0x66c60af8 + z * -0xea9a42b; | |
} | |
return 0; | |
} | |
/* Wither Killer Pattern | |
011*k* | |
2**kkk | |
2***k* | |
where: | |
k: 4+ high bedrock | |
0: 2-high bedrock | |
1: 2-high bedrock | |
2: 2-high bedrock | |
0 must be true and either 1 or 2 must be true. | |
You also need room to complete placing the skulls | |
sss 011 ss0 | |
sss vs sss vs ss1 vs something with 4 openings | |
011 sss ss1 | |
*/ | |
int offset_s[9][2] = { | |
{0,0}, {1,0}, {2,0}, | |
{0,1}, {1,1}, {2,1}, | |
{0,2}, {1,2}, {2,2} | |
}; | |
int offset_k[5][2] = { | |
{4,0},{3,1},{4,1},{5,1},{4,2} | |
}; | |
void find_wither_killers(int dim, int chunk_x, int chunk_z, int extra) { | |
mat_t counts; | |
std::mt19937 gen; | |
auto f = [&](int a, int b) { | |
gen.seed(get_seed(dim, chunk_x+a, chunk_z+b)); | |
for(int x = 0; x < 16; ++x) { | |
for(int z = 0; z < 16; ++z) { | |
unsigned int h = 1 + (gen() % 4); | |
counts[x+a*16][z+b*16] = h+1; | |
for(int i=0; i < extra; ++i) { | |
gen(); | |
} | |
} | |
} | |
}; | |
auto g = [&](int x, int z, const char *p, unsigned int h[3]) { | |
if(dim == 1) { | |
cout << "nether,"; | |
} else { | |
cout << "overworld,"; | |
} | |
cout << (chunk_x*16+x) << ",2," << (chunk_z*16+z); | |
if(dim == 0) { | |
cout << (extra != 2 ? ",grassy," : ",sandy,"); | |
} else { | |
cout << (extra != 3 ? ",regular," : ",delta/valley,"); | |
} | |
cout << p << "," << h[0] << "," << h[1] << "," << h[2]; | |
cout << endl; | |
}; | |
// generate 4 chunks of bedrock height | |
f(0,0); | |
f(1,0); | |
f(0,1); | |
f(1,1); | |
// look for wither killers | |
for(int x=0; x < 16; ++x) { | |
for(int z=0; z < 16; ++z) { | |
// Look for 3x3 space | |
bool has_space = std::all_of(offset_s, offset_s+9, [&](int *p) { | |
return counts[x+p[0]][z+p[1]] <= 2; | |
}); | |
if(!has_space) { | |
continue; | |
} | |
// Look for Killer 1 | |
bool k1 = std::all_of(offset_k, offset_k+5, [&](int *p) { | |
return counts[x+p[0]][z+p[1]] >= 4; | |
}); | |
if(!k1) { | |
continue; | |
} | |
// Look for Killer 2 | |
bool k2 = std::all_of(offset_k, offset_k+5, [&](int *p) { | |
return counts[x+2+p[0]][z+p[1]] >= 4; | |
}); | |
if(!k2) { | |
continue; | |
} | |
// Look for Killer 3 | |
bool k3 = std::all_of(offset_k, offset_k+5, [&](int *p) { | |
return counts[x+p[0]][z+2+p[1]] >= 4; | |
}); | |
if(!k3) { | |
continue; | |
} | |
unsigned int h[3] = { | |
counts[x+4][z+1], | |
counts[x+6][z+1], | |
counts[x+4][z+3] | |
}; | |
g(x,z,"safe", h); | |
} | |
} | |
} | |
int main(int argv, char* argc[]) { | |
const int sz = 1024; | |
cout << "dim,x,y,z,biome,direction,center_height1,center_height2,center_height3" << endl; | |
for(int x=-sz; x < sz; ++x) { | |
for(int z=-sz; z < sz; ++z) { | |
// overworld normal | |
find_wither_killers(0, x, z, 1); | |
// overworld rare (desert and beach biomes, mostly) | |
find_wither_killers(0, x, z, 2); | |
// nether 1.16+ (hell, warped, crimson) | |
// nether 1.16-1.16.40 (soulsand_valey, basalt_deltas) | |
find_wither_killers(1, x, z, 2); | |
// nether 1.16.100+ (soulsand_valley, basalt_deltas) | |
find_wither_killers(1, x, z, 3); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <random> | |
#include <array> | |
#include <iostream> | |
#include <algorithm> | |
using namespace std; | |
using mat_t = array<array<unsigned int, 32>, 32>; | |
uint32_t get_seed(int d, int x, int z) { | |
if(d == 0) { | |
return x * 0x14609048 + z * 0x7ebe2d5; | |
} else if(d == 1) { | |
return x * -0x66c60af8 + z * -0xea9a42b; | |
} | |
return 0; | |
} | |
/* Wither Killer Pattern | |
011*k* | |
2**kkk | |
2***k* | |
where: | |
k: 4+ high bedrock | |
0: 2-high bedrock | |
1: 2-high bedrock | |
2: 2-high bedrock | |
0 must be true and either 1 or 2 must be true. | |
You also need room to complete placing the skulls | |
sss 011 ss0 | |
sss vs sss vs ss1 vs something with 4 openings | |
011 sss ss1 | |
*/ | |
/* Wither Killer Pattern | |
22**44* | |
22*4554 | |
22**44* | |
where: | |
4: 4+ high bedrock | |
5: 5-high bedrock | |
2: 2-high bedrock | |
*/ | |
int offset_s[6][2] = { | |
{0,0}, {1,0}, | |
{0,1}, {1,1}, | |
{0,2}, {1,2}, | |
}; | |
int offset_k[8][2] = { | |
{4,0}, | |
{3,1},{4,1},{5,1}, | |
{4,2}, | |
}; | |
void find_wither_killers(int dim, int chunk_x, int chunk_z, int extra) { | |
mat_t counts; | |
std::mt19937 gen; | |
auto f = [&](int a, int b) { | |
gen.seed(get_seed(dim, chunk_x+a, chunk_z+b)); | |
for(int x = 0; x < 16; ++x) { | |
for(int z = 0; z < 16; ++z) { | |
unsigned int h = 1 + (gen() % 4); | |
counts[x+a*16][z+b*16] = h+1; | |
for(int i=0; i < extra; ++i) { | |
gen(); | |
} | |
} | |
} | |
}; | |
auto g = [&](int x, int z, const char *p) { | |
if(dim == 1) { | |
cout << "nether,"; | |
} else { | |
cout << "overworld,"; | |
} | |
cout << (chunk_x*16+x) << ",2," << (chunk_z*16+z); | |
if(dim == 0) { | |
cout << (extra != 2 ? ",grassy," : ",sandy,"); | |
} else { | |
cout << (extra != 3 ? ",regular," : ",delta/valley,"); | |
} | |
cout << p << endl; | |
}; | |
// generate 4 chunks of bedrock height | |
f(0,0); | |
f(1,0); | |
f(0,1); | |
f(1,1); | |
// look for wither killers | |
for(int x=0; x < 16; ++x) { | |
for(int z=0; z < 16; ++z) { | |
// Look for 2x3 space | |
bool has_space = std::all_of(offset_s, offset_s+6, [&](int *p) { | |
return counts[x+p[0]][z+p[1]] <= 2; | |
}); | |
if(has_space) { | |
// Look for Killer 1 | |
bool k1 = std::all_of(offset_k, offset_k+5, [&](int *p) { | |
return counts[x+p[0]][z+p[1]] >= 4; | |
}); | |
k1 = k1 && counts[x+4][z+1] >= 5; | |
// Look for Killer 2 | |
bool k2 = std::all_of(offset_k, offset_k+5, [&](int *p) { | |
return counts[x+p[0]+1][z+p[1]] >= 4; | |
}); | |
k2 = k2 && counts[x+5][z+1] >= 5; | |
if(k1 && k2) { | |
g(x,z,"AS"); | |
} | |
} | |
// Look for 3x2 space | |
has_space = std::all_of(offset_s, offset_s+6, [&](int *p) { | |
return counts[x+p[1]][z+p[0]] <= 2; | |
}); | |
if(has_space) { | |
// Look for Killer 1 | |
bool k1 = std::all_of(offset_k, offset_k+5, [&](int *p) { | |
return counts[x+p[0]][z+p[1]] >= 4; | |
}); | |
k1 = k1 && counts[x+4][z+1] >= 5; | |
// Look for Killer 2 | |
bool k2 = std::all_of(offset_k, offset_k+5, [&](int *p) { | |
return counts[x+p[0]][z+p[1]+1] >= 4; | |
}); | |
k2 = k2 && counts[x+4][z+2] >= 5; | |
if(k1 && k2) { | |
g(x,z,"AE"); | |
} | |
} | |
} | |
} | |
} | |
int main(int argv, char* argc[]) { | |
const int sz = 256; | |
cout << "dim,x,y,z,biome,direction" << endl; | |
for(int x=-sz; x < sz; ++x) { | |
for(int z=-sz; z < sz; ++z) { | |
// overworld normal | |
find_wither_killers(0, x, z, 1); | |
// overworld rare (desert and beach biomes, mostly) | |
find_wither_killers(0, x, z, 2); | |
// nether 1.16+ (hell, warped, crimson) | |
// nether 1.16-1.16.40 (soulsand_valey, basalt_deltas) | |
find_wither_killers(1, x, z, 2); | |
// nether 1.16.100+ (soulsand_valley, basalt_deltas) | |
find_wither_killers(1, x, z, 3); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment