- トップページ
- 書庫
- Context Free for beginners
- 再帰呼び出しでシェイプを描く

Context Freeでは、ルールを再帰呼び出しできます。 再帰呼び出しとは、あるルールの中でそのルール自身を呼び出す事です。 この例を見てください。
startshape Circles rule Circles { CIRCLE {} Circles { x 0.95 s 0.9 r 30 } }

startshapeがCirclesというルールを呼び出しており、Circlesの中では、円を描画した後で、Circles自身をx軸方向に0.95個分移動させ、スケールを0.9に縮小し、反時計回りに30度回転させて呼び出しています。 呼び出されたCirclesは、円を描画して、Circles自身をx軸方向に0.95個分移動させ、スケールを0.9に縮小し、反時計回りに30度回転させて呼び出し、呼び出されたCirclesは、円を描画して…
このように、自分自身を呼び出すことを再帰呼び出しと言います。 再帰呼び出しが無限ループに陥るのを防止するため、Context Freeはシェイプが描画できないスケールになった時点で処理を終了します。
この例では、Circlesを再帰呼び出しする際に、位置の移動と回転に加えてスケールも変更しました。 これにより、円の大きさがだんだんと小さくなって最後は描画できないスケールになり、Context Freeが再帰呼び出しを終了したのです。
再帰呼び出しを終了させる別の手段として、描画ルールと同じ名前の描画終了ルールを用意して、描画終了ルールがランダムに選ばれた時点で処理を終了させる方法があります。
startshape Circles rule Circles { 5 * { y -1 } CIRCLE {} Circles { x 1} } rule Circles 0.1 { }

このコードを実行すると、y軸方向に5つの円を描く処理が、x軸方向に移動しながら何回か繰り返されて終了します。
2番目のCirclesにはウエイトとして0.1が指定されているだけで、中カッコ内は空です。 中カッコ内が空ということは、再帰呼び出しをしないということですから、2番目のCirclesが終了ルールとなります。 最初のCirclesのウエイトは省略されているのでデフォルトの1となり、2番目のCirclesのウエイトが0.1ですので、1:0.1の比率で処理続行と終了が選択されます(処理終了確率が高いので、なにも描画されないこともあります)。
これらを応用して、木のようなイメージを描画してみましょう。
startshape Tree rule Tree 0.6 { SQUARE {} Tree { y 1 } } rule Tree 0.2 { CIRCLE { y -0.5 } Tree { y -0.5 r 30 s 0.75 } Tree { y -0.5 r -30 s 0.75 } } rule Tree 0.01 { CIRCLE { y -0.5 } }

見た目は複雑なイメージですが、コードの内容は単純です。 startshapeが呼び出すルールのTreeは3種類あり、それぞれにウエイトが設定されています。 最初のTreeは正方形で木の幹を描き、Treeをy軸方向に1個分移動して再帰呼び出しします。 幹はそれなりの長さが必要なので、ウエイトを3種類のうちで最も大きい0.6としています。 次のTreeは枝分かれです。分岐点の円を描き、左右に30度かたむけ、スケールを0.75に縮小して2つのTreeを再帰呼び出しします。 ときどき枝分かれすればいいので、ウエイトは0.2です。 最後のTreeは終了ルールで、再帰呼び出しせずに処理を終了します。 まれに終了すればいいのでウエイトは0.01にしています。 枝分かれのTreeでスケールを縮小していますから(描画できない大きさになれば終了するので)終了ルールがなくてもいいのですが、途中でぶっつり切れた枝ということで採用しました。 円を描いて描画を終了します。
ちなみに、終了ルールなしの場合はこんな感じになります。
startshape Tree rule Tree 0.6 { SQUARE {} Tree { y 1} } rule Tree 0.2 { CIRCLE {y -0.5} Tree { y -0.5 r 30 s 0.75 } Tree { y -0.5 r -30 s 0.75 } }

再帰呼び出しとウエイトによるルールの分岐制御はContext Freeの特徴のひとつです。 実行のたびに違ったイメージが現れるのが楽しいですね。
できるようになった(はずの)こと- 再帰呼び出しを使ってシェイプを描画できる
- 再帰呼び出し終了条件を設定できる