マインクラフト:メンガーのスポンジをコマンドで作成

最近、子供と一緒にマインクラフトで遊んでいる。
先日、メンガーのスポンジを作るコマンドを作ってみたので、備忘録がてら紹介。
ja.wikipedia.org

  • X軸(よこ軸)
  • Y軸(高さ軸)
  • Z軸(たて軸)

とするとき、まず起点となるブロックを一つ置いてみる。
↓ 3×3×3の立方体の一段目。

この000(相対座標)のブロックを、適切な箇所にコピーしていく。
白抜きの箇所が、コピーしてはいけない箇所。

↓二段目(白抜きの箇所はコピー不可)。

↓三段目(白抜きの箇所はコピー不可)。

結果、このような基本形が出来上がる。

これを一つのブロックと見立てて、どうようにコピーを繰り返すことでフラクタル図形ができていく。

ところでこの「コピーする/しない」、何か法則を見つけて自動化できないか。
試しに表にしてみた。

・・・法則が見つけられない。ということで、試しに全部1引いてみた。すると、0の数が2以上のときにコピー不可であることが分かった。
※恐らくは、すでに広く一般的に知られている法則と思われる。

ここまでわかれば、あとはコマンド化するだけだ。というわけで作ってみた。

count_zeros = 0
def check_zeros(a: number, b: number, c: number):
    global count_zeros
    count_zeros = 0
    if a == 0:
        count_zeros += 1
    if b == 0:
        count_zeros += 1
    if c == 0:
        count_zeros += 1
    return count_zeros <= 1

def on_on_chat(origin_x, origin_y, origin_z):
    blocks.place(PLANKS_ACACIA, world(origin_x, origin_y, origin_z))
    for n in range(5):
        for index_x in range(3):
            for index_y in range(3):
                for index_z in range(3):
                    if check_zeros(index_x - 1, index_y - 1, index_z - 1):
                        blocks.clone(world(origin_x, origin_y, origin_z),
                            world(origin_x + 3 ** n - 1,
                                origin_y + 3 ** n - 1,
                                origin_z + 3 ** n - 1),
                            world(origin_x + index_x * 3 ** n,
                                origin_y + index_y * 3 ** n,
                                origin_z + index_z * 3 ** n),
                            CloneMask.REPLACE,
                            CloneMode.NORMAL)
player.on_chat("Menger_sponge", on_on_chat)

結果がこちら。

参考まで。