Fibonacci structures


In [ ]:
# generate a list of Fibonacci series starting with 1
import itertools
import math
import numpy as np
def fib_function():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

def fib_list(n):
    fib = fib_function()
    return list(itertools.islice(fib,n+2))[2:]

In [ ]:
# return a range if the numbers are different
def ordered_range(a,b):
    if (a == b):
        return [a]
    elif (a < b):
        return range(a,b+1)
    else:
        return range(a,b-1,-1)

# replace None with previous value of coordinate
def replace_null(acc,p):
    null_replacer = lambda (a,b): b if (a is None) else a
    if not acc:
        return [p]
    else:
        previous_point = acc[-1]
        next_point = map(null_replacer, zip(p,previous_point))
        return acc + [next_point]

# a point p has (x,y,z) coordinates
def line_coordinates(p1,p2):
    x1,y1,z1 = p1[0],p1[1],p1[2]
    x2,y2,z2 = p2[0],p2[1],p2[2]
    points = reduce(replace_null,itertools.izip_longest(ordered_range(x1,x2),ordered_range(y1,y2),ordered_range(z1,z2)),[])
    return points

In [ ]:
# generate the sequence [(1,0),(0,1),(-1,0),(0,-1),(1,0),...]
def next_mult((m,n)):
    return (-1*n,m)

# return a new sequence = previous sequence + new segment
# and new start position for next segment new_start
def fib_segment((prev_sequence,(xm,zm)),segment_length):
    start = prev_sequence[-1]
    x1,y1,z1 = start[0],start[1],start[2]
    x2,y2,z2 = x1 + (xm * segment_length), y1, z1 + (zm * segment_length)
    new_segment = line_coordinates((x1,y1,z1),(x2,y2,z2))[1:]
    new_sequence = prev_sequence + new_segment
    return (new_sequence,next_mult((xm,zm)))
    
# fibonacci coordinates
# alternating x,z using next_mult
def fib_coords(start, n):
    fib_series = fib_list(n)
    fib_series.reverse()
    fib_points = reduce(fib_segment,fib_series,([start],(1,0)))
    return fib_points[0]

#logarithmic spiral functions
def log_spiral_xy(theta):
    a = 1
    b = 0.3
    x = a*math.exp(b*theta)*math.cos(theta)
    z = a*math.exp(b*theta)*math.sin(theta)
    return (x,z)

def theta_to_xyz((x,y,z),t):
    x1,z1 = log_spiral_xy(t)
    return (x1,y,z1)

# log spiral coordinates
def log_sequence((x,y,z),n):
    rads = np.arange(0,2*math.pi*n,0.1)
    logseq = map(lambda t: tuple(map(lambda x, y: int(round(x + y)), (x,y,z), theta_to_xyz((x,y,z),t))) ,rads)
    loglines = reduce(lambda acc,s: acc + line_coordinates(s[0],s[1]), zip(logseq,logseq[1:]),[])
    return logseq

In [ ]:
# Minecraft initialization
# import sys
# sys.path.append('/Users/esumitra/workspaces/mc/mcpipy')
import mcpi.minecraft as minecraft
import mcpi.block as block
import time
mc = minecraft.Minecraft.create()

In [ ]:
# build in Minecraft
def build_fib(n,blockid):
    pos = mc.player.getTilePos()
    mc.postToChat("building in 5 seconds ...")
    time.sleep(5)
    x,y,z = pos.x,pos.y,pos.z
    fclist = fib_coords((x,y,z),n)
    for p in fclist:
        mc.setBlock(p[0], p[1], p[2], blockid)

def build_log_spiral(n,blockid):
    pos = mc.player.getTilePos()
    mc.postToChat("building in 5 seconds ...")
    time.sleep(5)
    x,y,z = pos.x,pos.y,pos.z
    fclist = log_sequence((x,y,z),n)
    for p in fclist:
        mc.setBlock(p[0], p[1], p[2], blockid)

In [ ]:
# build_fib(5, block.TNT.id)
# build_log_spiral(2, block.STONE.id)