-- / --
--
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

03 / 06
Thu

Ziphil です。

ランダムダンジョンの生成アルゴリズム、 3 つ目になります。 今回は、 セルオートマトンを使ってみました。

774_製作過程A

前のアルゴリズムに比べて荒れが少ないですね。 しかし、 これが簡単なセルオートマトンのルールを何回か適用しただけの結果だというのは驚きです。

簡単にアルゴリズムを説明しましょう。 今回は Ruby のコードつきです。 ちなみに、 今回のアルゴリズムは、 主にこのサイトを参考にしています。

まず、 セルオートマトンのルールです。 あるマス p から n 回以内の移動 (斜め移動なし) で進める範囲を An(p) とし、 範囲 An(p) の内部にある壁のマスの個数を Rn(p) とします。 つまり、 An(p) は p を中心とする 1 辺が 2n + 1 の正方形になります。

セルオートマトンのルールは、 R1(p) ≧ C1 または R2(p) ≦ C2 のときは p を壁にし、 そうでないときは p を通路にする、 というものです。 これを、 初期条件として W% が壁であるマップに対し、 何度か適用します。 W, C1, C2 はパラメータです。

上のスクリーンショットでは、 W = 40 とし、 C1 = 5, C2 = 2 のルールを 2 回適用し、 その後 C1 = 5, C2 = -1 のルールを 1 回適用しています。 この繰り返し回数と W, C1, C2 の値は、 各自で調整してください。

では、 プログラムを見てみましょう。

class AutoTilemap
  def initialize(width, height)
    @width = width
    @height = height
    @tiles = Array.new(height){Array.new(width, 0)}
  end
  def generate_tilemap
    create_noise
    apply_automaton
  end
  def create_noise
    for x in 1...(@width - 1)
      for y in 1...(@height - 1)
        @tiles[y][x] = (rand(100) < 40)? 0 : 1
      end
    end
  end
  def apply_automaton
    parameters = [[2, 5, 2], [1, 5, -1]]
    new_tiles = Array.new(@height){Array.new(@width, 0)}
    parameters.each do |parameter|
      parameter[0].times do 
        for x in 1...(@width - 1)
          for y in 1...(@height - 1)
            area_in = [x - 1, x, x + 1].product([y - 1, y, y + 1])
            area_out = [x - 2, x - 1, x, x + 1, x + 2].select{|i| i.between?(0, @width - 1)}.
                       product([y - 2, y - 1, y, y + 1, y + 2].select{|i| i.between?(0, @height - 1)})
            number_in = 9 - area_in.count{|i| @tiles[i[1]][i[0]] != 0}
            number_out = 25 - area_out.count{|i| @tiles[i[1]][i[0]] != 0}
            new_tiles[y][x] = (number_in >= parameter[1] || number_out <= parameter[2])? 0 : 1
          end
        end
      end
    end
    @tiles = new_tiles
  end
end

create_noise メソッドは、 W% が壁であるマップをランダムに生成しています。 今回は W = 40 としたので、 (rand(100) < 40)? 0 : 1 としてあります。 なお、 0 が壁で 1 が通路を表します。

apply_automaton メソッドで、 セルオートマトンのルールを適用しています。 変数 parameters で、 簡単にパラメータを変更できるようにしておきました。 繰り返し回数, C1, C2 を格納した配列の配列を指定してください。

・・・にしても、 セルオートマトンってこんなこともできるんですね。 簡単なルールを適用するだけで、 自然物が模倣できる・・・。 自然とは結構単純なのでしょうか。

ちなみに、 上の参考にしたサイトを読んでるときに 「cellular automata」 って automaton と何が違うのかなー、 とか考えたことは内緒です。 どう見てもただの複数形です。 本当にありがとうございました。

スポンサーサイト

comment ×0
コメント
管理者にだけ表示を許可する
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。