ImageMagick でライフゲームを動かすシェル芸ができたので、記録しておきます。
ImageMagick でライフゲームを動かすとは?
ライフゲームを動かすには、
- 初期状態の設定
- ライフゲームのルール記述
- 可視化
などの機能が必要ですが、これらをすべて ImageMagick で行いました。
シェル芸botでの実行例は以下のような感じになります(この実行例では初期状態設定はtextimgを利用)。
# 動作環境 以下の環境で動作確認しています。https://t.co/nrucj1Ifkj pic.twitter.com/s9vzxKuD2R
— シェル芸bot (@minyoruminyon) April 25, 2020
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic
$ $SHELL --version
GNU bash, バージョン 4.4.20(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ convert --version
Version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org
Copyright: © 1999-2017 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP
Delegates (built-in): bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png tiff wmf x xml zlib
コマンド
以下のコマンドを実行することで、ライフゲームが動きます。
$ eval "convert -delay 10 xc:[160x90\!] -gravity center -pointsize 50 -draw 'text 0,0 \"Life\"' -negate -threshold 10% `for i in {1..1399};do echo -n "\( +clone -fx 'aa=p[-1,-1]+p[-1,0]+p[-1,1]+p[0,-1]+p[0,1]+p[1,-1]+p[1,0]+p[1,1];aa==3&1-u?1:aa<2|aa>3&u?0:u' \) ";done`x.gif"
実行結果は、x.gif
というファイルに、以下の gif アニメーションが出力されます。
コマンド解説
コマンド全体は、bash の for 文で、長大な convert コマンドの 引数を生成して、それを eval しています。
eval される中身は大きく3つの部分に分けられます。
初期状態設定部分
convert -delay 10 xc:[160x90\!] -gravity center -pointsize 50 -draw 'text 0,0 \"Life\"' -negate -threshold 10%
この部分は、160x90のグリッドに黒地に白文字で Life と描いています。
ルール記述部分
`for i in {1..1399};do echo -n "\( +clone -fx 'aa=p[-1,-1]+p[-1,0]+p[-1,1]+p[0,-1]+p[0,1]+p[1,-1]+p[1,0]+p[1,1];aa==3&1-u?1:aa<2|aa>3&u?0:u' \) ";done`
この部分はライフゲームのルールを記述しています。
for 文で繰り返し echo している
\( +clone -fx 'aa=p[-1,-1]+p[-1,0]+p[-1,1]+p[0,-1]+p[0,1]+p[1,-1]+p[1,0]+p[1,1];aa==3&1-u?1:aa<2|aa>3&u?0:u' \)
は、直前(イメージシーケンスの最後)のイメージに対して、各ピクセルの近傍ピクセルの白ピクセルの個数に応じた更新を行います。
これを for 文で繰り返すたびにライフゲームが1tic進んだイメージが生成されます。
このコマンドでは1399回の更新を行っていることになります。
実行に時間がかかるので、試しにちょっと実行してみる場合、
この回数を減らすと短時間で結果が確かめられていいでしょう。
出力表示部分
最後に
x.gif
として、イメージシーケンスのイメージをx.gif
というファイルにgifアニメーションとして出力します。
所感
ImageMagick の fx expression が便利。
フラクタル図形なんかも描ける。
https://t.co/vgYhEnRTqB pic.twitter.com/kq7lVRrDnr
— シェル芸bot (@minyoruminyon) April 22, 2020
https://t.co/8i9FuLAGKv pic.twitter.com/rW6aHrA1OL
— シェル芸bot (@minyoruminyon) April 22, 2020
https://t.co/y7hgm6syk1 pic.twitter.com/CqOwAay8gM
— シェル芸bot (@minyoruminyon) May 6, 2020