Wishful Coding

Didn't you ever wish your
computer understood you?

Where to dig in Minecraft

I have been playing Minecraft a lot lately, and I was wondering where to dig for certain minerals. I knew Redstone was only found in lower layers of the level, but I knew nothing concrete.

I pulled together Gnuplot and a Python lib for reading NBT files and analyzed a level. Here is the result, the code and some notes.

Where to dig in Minecraft

I suspect the sea level is around 60, because of the clay there. Coals is rare and Iron very rare above sea level.

Both Diamond and Redstone stop at 20, while gold can be found a little higher. There is no noticeable decline in Coal and Iron near the bottom, so best is to dig below level 20.
Where to dig in MinecraftAs can be seen above, there is a lot of Lava, Water and Obsidian around and below level 10, so stay above level 10 for safe mining.

The code:

from nbt import nbt
from itertools import izip_longest, repeat
import glob
import Gnuplot

files = glob.glob("/Users/pepijndevos/Library/Application Support/minecraft/saves/World2/*/*/*.dat")
output = "minecraft.png"

col = []

for file in files:
    print file
    file = nbt.NBTFile(file,'rb')
    
    col.extend(izip_longest(*[iter(file["Level"]["Blocks"].value)]*128))

    file.file.close()

layers = zip(*col)

minerals = {
    #'Bedrock': '\x07',
    #'Water': '\x09',
    #'Lava': '\x0B',
    #'Sand': '\x0C',
    #'Gravel': '\x0D',
    'Gold': '\x0E',
    'Iron': '\x0F',
    'Coal': '\x10',
    'Obsedian': '\x31',
    'Diamond': '\x38',
    'Redstone': '\x49',
    'Clay': '\x52',
}

names = minerals.keys()
hexes = minerals.values()

def count_minerals(layer):
    def filter_mineral(mineral):
        count = len([block for block in layer if block == mineral])
        return count
    
    m = map(filter_mineral, hexes)
    return m

g = Gnuplot.Gnuplot(debug=1)
g('set term png')
g('set out "%s"' % output)
g('set style data lines')

data = zip(*(count_minerals(layer) for layer in layers))

data = (Gnuplot.PlotItems.Data(list(enumerate(mineral)), title=names[index]) for index, mineral in enumerate(data))

g.plot(*data)

I regret doing this thing in Python. My coding style is strongly influenced by Clojure, and I had to do a number of hacks that would be trivial to do in Clojure. I might do a comparison in a future post if I ever do a Clojure version.