ちょっと変わったセルオートマトンを実装してみた
今日は少しプログラミングをしてみました。セルオートマトンによる芸術作品を作れないかと考えていて、その一環で作ったものです。
セルオートマトンというのが何か、というのは説明を省きますが、宇宙の真理とも言える『単純なルールで複雑な現象が起こる』ことを実感できるモデルだと思ってもらえると良いと思います。
そこで、今日はそのルールをちょっと複雑にして(といっても少しだけですが)何か変わった現象が起きないかなーと調査をしてみました。先の動画はそのいくつかの例です。
例えば、こんな星型のような模様が浮かび上がるルールができました。
他にも静止画で面白く見せられるものだとこういうのも。大きなドットと小さなドットが共存しています。大きなドットの周りには小さなドットが生まれ、小さなドットがきっかけで大きなドットが生まれたりしています。
今回作った物は、だいたいが一般的な8近傍総和型ではなく特殊なものを使っています。これを説明するのはとても難しいのですが、8x8個のドットの状態を同時に1つの数(すう)として表現し、その数を演算して結果に反映することで実現しています。
どうやって作ったか
先も言ったとおりどうやって実現したかを説明するのは本当に難しいのですが、ソースコードを公開しているのでご興味があれば御覧ください。一対一で会話できる状態なら説明し切ることはできますが、解説文を書くのはちょっと大変なので・・・。
ただし、ソースコードを読んでもよくわからない、とは思います。熟読しなければなぜこうなったか理解することは難しいです。これはぼくが分かりやすいコーディングをサボったからではなく、説明し難いハックを用いて実行速度の効率を得ているからです。
例えばですが、https://github.com/tosik/ca-art/blob/master/src/bitcounter.cpp で説明しましょう。
int count_bits(BitboardCA::Bitboard n) {
n = ((n >> 1) & 0x5555555555555555ULL) + (n & 0x5555555555555555ULL);
n = ((n >> 2) & 0x3333333333333333ULL) + (n & 0x3333333333333333ULL);
n = ((n >> 4) & 0x0f0f0f0f0f0f0f0fULL) + (n & 0x0f0f0f0f0f0f0f0fULL);
n = ((n >> 8) & 0x00ff00ff00ff00ffULL) + (n & 0x00ff00ff00ff00ffULL);
n = ((n >> 16) & 0x0000ffff0000ffffULL) + (n & 0x0000ffff0000ffffULL);
n = (n >> 32) + (n & 0x00000000ffffffffULL);
return (int)n;
}
BitboardCA::Bitboard 型は unsigned long long int のエイリアスです。なので単純な64ビット配列だと思ってください。そして、この関数はそのビットの1の数を数えて返すものです。分岐や判定などがまったくなく、演算回数が極力少なくなるように作られています。シフト演算、アンド演算、加算を入力に対して6回施行しているだけですね。こういうハックの塊のようなものが今回作ったものなので、読んでもわからないコードだらけだったりします。
今日も日記がかけました!では。
応援してくださると嬉しいです。よろしくお願いいたします!