ライフゲーム #26

せっかくだからもう少しだけset_gen0.gを便利にしてみよう。
座標リストと移動量の組み合わせを複数指定できるようにしてみる。

set_gen0.g
BEGIN {
  if (ARGC < 1) {
    printf(2, 'usage: gvpr -cf set_gen0.g -a filename [[-a x0,y0 -a filename]...] [-a x0,y0] [-o outfile] [infile]\n');
    exit(0);
  }

  string p[];
  int arg = 0, pn = 0, mpx = -1, mpy = -1, minusp = 0;
  while (arg < ARGC) {
    string filename = ARGV[arg++];
    int x0 = 0, y0 = 0;
    if (arg < ARGC) {
      x0 = xOf(ARGV[arg]);
      y0 = yOf(ARGV[arg++]);
    }

    int fd = openF(filename, 'r');
    string s;
    for (s = readL(fd); s != ""; s = readL(fd)) {
      s = substr(s, 0, length(s) - 1);
      int x = xOf(s) + x0, y = yOf(s) + y0;
      p[pn++] = sprintf('%d,%d', x, y);
      mpx = MAX(mpx, x);
      mpy = MAX(mpy, y);
      if (minusp == 0 && (x < 0 || y < 0)) minusp = 1;
    }
    closeF(fd);
  }
}

BEG_G {
...snip
N {
...snip
END_G {
...snip

BEGIN節の変更だけで済んだ。
最後の移動量の指定を省略すると、その直前の座標リストに対する移動量を0にする。

glider.txt
0,0
0,1
1,0
1,2
2,0

で定義したGliderを並べて編隊を組んでみる。

$ gvpr -f gen_mesh.g -a 30,20 |
> gvpr -cf set_gen0.g \
> -a "glider.txt 26,16" \
> -a glider.txt -a 21,16 \
> -a "glider.txt 16,16" \
> -a glider.txt -a 26,11 |
> gvpr -cf vis_alive.g -a .1 | neato -Nlabel="" -T png -o gliders_0.png

長くなると見づらいのでbashの継続行の機能を使って複数行に分割入力している。
cmdなら'\'でなく'^'を使って、

C:\foo> gvpr -f gen_mesh.g -a 30,20 | ^
More? gvpr -cf set_gen0.g ^
More? -a "glider.txt 26,16" ^
More? -a glider.txt -a 21,16 ^
More? -a "glider.txt 16,16" ^
More? -a glider.txt -a 26,11 | ^
More? gvpr -cf vis_alive.g -a .1 | neato -Nlabel="" -T png -o gliders_0_0.png

ひとつのaオプションで全ての引数を引き受けてもいいし、上のように分割してもいい。

以上の例では全部glider.txtだったが、それぞれ別のパターンでも当然構わない。
パターンを裏返しにするとか回転するとかの指定もできるようになればほぼ完璧だろうけど、
set_gen0.gの改変もそろそろ切り上げたくまたの機会に。
さもないとパターンエディタとかコマンド群を駆動するフロントエンドとかまで作り始めかねず際限が無い。