Created
August 8, 2012 19:46
-
-
Save eddyb/3298010 to your computer and use it in GitHub Desktop.
SethBling's BanSlimes filter, with two of my fixes.
This file contains 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
# Feel free to modify and use this filter however you wish. If you do, | |
# please give credit to SethBling. | |
# http://youtube.com/SethBling | |
#from pymclevel import TAG_Long | |
# Performs signed overflow and underflow for Java's long. | |
# NOTE apparently not required. | |
def jlong(x): | |
# Signed overflow. | |
if x >= (1 << 64): | |
return -(1 << 63) + (x & ((1 << 64)-1)) | |
# Signed underflow. | |
if x < -(1 << 64): | |
return (1 << 63) - 1 + (-x-1 & ((1 << 64)-1)) | |
return x | |
# This mimics some of the functionality from the Java Random class. | |
# Java Random source code can be found here: http://developer.classpath.org/doc/java/util/Random-source.html | |
# NOTE not used directly, inlined below. | |
class Random: | |
def __init__(self, randseed): | |
self.setSeed(randseed) | |
def setSeed(self, randseed): | |
self.randseed = (randseed ^ 0x5DEECE66DL) & ((1L << 48) - 1); | |
def next(self, bits): | |
self.randseed = long(self.randseed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1) | |
return int(self.randseed >> (48 - bits)) | |
def nextInt(self, n): | |
while True: | |
bits = self.next(31) | |
val = bits % n | |
if int(bits - val + (n-1)) >= 0: | |
break | |
return val | |
# Algorithm found here: http://www.minecraftforum.net/topic/397835-find-slime-spawning-chunks-125/ | |
def goodSeed(minx, minz, maxx, maxz, seed): | |
for x in xrange(minx, maxx): | |
# Partial seed for the current x. | |
partial = seed + (x * x * 0x4c1906) + (x * 0x5ac0db) | |
for z in xrange(minz, maxz): | |
# Compute the seed passed to the Java Random class. | |
randSeed = (partial + (z * z * 0x4307a7) + (z * 0x5f24f)) ^ 0x3ad8025f | |
# Random.setSeed(randSeed) | |
randSeed = (randSeed ^ 0x5DEECE66D) & ((1 << 48) - 1) | |
# Random.nextInt(10) | |
while True: | |
# bits = Random.next(31) | |
randSeed = (randSeed * 0x5DEECE66D + 0xB) & ((1 << 48) - 1) | |
bits = randSeed >> 17 # 17 == (48 - bits) with bits == 31 | |
val = bits % 10 | |
if (bits - val + 9) >= 0: # 9 == (n-1) with n == 10 | |
break | |
slimeChunk = val == 0 | |
if slimeChunk: | |
return False | |
return True | |
inputs = ( | |
("Max Seed", 100000), | |
) | |
def perform(level, box, options): | |
# Convert block coords to chunk coords | |
minx = int(box.minx/16) | |
minz = int(box.minz/16) | |
maxx = int((box.maxx-1)/16)+1 | |
maxz = int((box.maxz-1)/16)+1 | |
for seed in xrange(options["Max Seed"]): | |
if goodSeed(minx, minz, maxx, maxz, seed): | |
#level.root_tag["Data"]["RandomSeed"] = TAG_Long(seed) | |
print "Found good seed: " + str(seed) | |
return | |
print "Didn't find good seed." | |
# Code for testing the speed of the brute-force. | |
class TestBox: | |
minx = 0 | |
minz = 0 | |
maxx = 10*16 | |
maxz = 11*16 | |
perform(False, TestBox(), {'Max Seed': inputs[0][1]}) |
This file contains 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
# Feel free to modify and use this filter however you wish. If you do, | |
# please give credit to SethBling. | |
# http://youtube.com/SethBling | |
#from pymclevel import TAG_Long | |
# Performs signed overflow and underflow for Java's long. | |
# NOTE apparently not required. | |
def jlong(x): | |
# Signed overflow. | |
if x >= (1 << 64): | |
return -(1 << 63) + (x & ((1 << 64)-1)) | |
# Signed underflow. | |
if x < -(1 << 64): | |
return (1 << 63) - 1 + (-x-1 & ((1 << 64)-1)) | |
return x | |
# This mimics some of the functionality from the Java Random class. | |
# Java Random source code can be found here: http://developer.classpath.org/doc/java/util/Random-source.html | |
# NOTE not used directly, inlined below. | |
class Random: | |
def __init__(self, randseed): | |
self.setSeed(randseed) | |
def setSeed(self, randseed): | |
self.randseed = (randseed ^ 0x5DEECE66DL) & ((1L << 48) - 1); | |
def next(self, bits): | |
self.randseed = long(self.randseed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1) | |
return int(self.randseed >> (48 - bits)) | |
def nextInt(self, n): | |
while True: | |
bits = self.next(31) | |
val = bits % n | |
if int(bits - val + (n-1)) >= 0: | |
break | |
return val | |
# Algorithm found here: http://www.minecraftforum.net/topic/397835-find-slime-spawning-chunks-125/ | |
def initChunks(chunks, minx, minz, maxx, maxz): | |
for x in xrange(minx, maxx): | |
# Partial seed for the current x. | |
partial = (x * x * 0x4c1906) + (x * 0x5ac0db) | |
for z in xrange(minz, maxz): | |
# Compute per-chunk position-dependent partial seeds. | |
chunks.append(partial + (z * z * 0x4307a7) + (z * 0x5f24f)) | |
return chunks | |
def goodSeed(chunks, seed): | |
for i in chunks: | |
# Compute the seed passed to the Java Random class. | |
randSeed = (i + seed) ^ 0x3ad8025f | |
# Random.setSeed(randSeed) | |
randSeed = (randSeed ^ 0x5DEECE66D) & ((1 << 48) - 1) | |
# Random.nextInt(10) | |
while True: | |
# bits = Random.next(31) | |
randSeed = (randSeed * 0x5DEECE66D + 0xB) & ((1 << 48) - 1) | |
bits = randSeed >> 17 # 17 == (48 - bits) with bits == 31 | |
val = bits % 10 | |
if (bits - val + 9) >= 0: # 9 == (n-1) with n == 10 | |
break | |
slimeChunk = val == 0 | |
if slimeChunk: | |
return False | |
return True | |
inputs = ( | |
("Max Seed", 100000), | |
) | |
def perform(level, box, options): | |
# Convert block coords to chunk coords | |
minx = int(box.minx/16) | |
minz = int(box.minz/16) | |
maxx = int((box.maxx-1)/16)+1 | |
maxz = int((box.maxz-1)/16)+1 | |
# Initialize per-chunk seeds. | |
chunks = initChunks([], minx, minz, maxx, maxz) | |
for seed in xrange(options["Max Seed"]): | |
if goodSeed(chunks, seed): | |
#level.root_tag["Data"]["RandomSeed"] = TAG_Long(seed) | |
print "Found good seed: " + str(seed) | |
return | |
print "Didn't find good seed." | |
# Code for testing the speed of the brute-force. | |
class TestBox: | |
minx = 0 | |
minz = 0 | |
maxx = 10*16 | |
maxz = 11*16 | |
perform(False, TestBox(), {'Max Seed': inputs[0][1]}) |
This file contains 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
# Feel free to modify and use this filter however you wish. If you do, | |
# please give credit to SethBling. | |
# http://youtube.com/SethBling | |
#from pymclevel import TAG_Long | |
# This mimics some of the functionality from the Java Random class. | |
# Java Random source code can be found here: http://developer.classpath.org/doc/java/util/Random-source.html | |
class Random: | |
def __init__(self, randseed): | |
self.setSeed(randseed) | |
def setSeed(self, randseed): | |
self.randseed = (randseed ^ 0x5DEECE66DL) & ((1L << 48) - 1); | |
def next(self, bits): | |
self.randseed = long(self.randseed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1) | |
return int(self.randseed >> (48 - bits)) | |
def nextInt(self, n): | |
while True: | |
bits = self.next(31) | |
val = bits % n | |
if int(bits - val + (n-1)) >= 0: | |
break | |
return val | |
# Algorithm found here: http://www.minecraftforum.net/topic/397835-find-slime-spawning-chunks-125/ | |
def slimeChunk(seed, x, z): | |
randseed = long(seed) + long(x * x * 0x4c1906) + long(x * 0x5ac0db) + long(z * z) * 0x4307a7L + long(z * 0x5f24f) ^ 0x3ad8025f | |
r = Random(randseed) | |
i = r.nextInt(10) | |
return i == 0 | |
def goodSeed(box, seed): | |
minx = int(box.minx/16)*16 | |
minz = int(box.minz/16)*16 | |
for x in xrange(minx, box.maxx, 16): | |
for z in xrange(minz, box.maxz, 16): | |
if slimeChunk(seed, x/16, z/16): | |
return False | |
return True | |
inputs = ( | |
("Max Seed", 100000), | |
) | |
def perform(level, box, options): | |
for seed in xrange(options["Max Seed"]): | |
if goodSeed(box, seed): | |
#level.root_tag["Data"]["RandomSeed"] = TAG_Long(seed) | |
print "Found good seed: " + str(seed) | |
return | |
print "Didn't find good seed." | |
# Code for testing the speed of the brute-force. | |
class TestBox: | |
minx = 0 | |
minz = 0 | |
maxx = 10*16 | |
maxz = 11*16 | |
perform(False, TestBox(), {'Max Seed': inputs[0][1]}) |
This file contains 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
$ time python BanSlimes.original.py; time python BanSlimes.fix1.py; time python BanSlimes.fix2.py | |
# BanSlimes.original.py | |
Found good seed: 12949 | |
real 0m1.639s | |
user 0m1.607s | |
sys 0m0.016s | |
# BanSlimes.fix1.py | |
Found good seed: 12949 | |
real 0m0.634s | |
user 0m0.608s | |
sys 0m0.013s | |
# BanSlimes.fix2.py | |
Found good seed: 12949 | |
real 0m0.520s | |
user 0m0.496s | |
sys 0m0.015s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment