まずこのCASMという言葉の意味から説明しましょう。これは、タイトルに も有るように、Computer Aidad Scenario Makingの略です。つまり、RPGのシ ナリオを作る際に、コンピューターを利用しようということなのです。この CASMは、RPGを行う際にコンピューターを最大限利用するという意味の、 Computer Aided RPG(CAR‥‥なんかLISPみたい^_^;)という、より広い分野の 一部分と言えるでしょう。
Scena1は、テーブル・トーク・RPG用の大まかなシナリオを生成するこ とを目的として制作されました。また、Scena1は2つのプログラムからなって おり、その2つのプログラムはいずれもjgawk上で動作するスクリプトとなって います。Scena1としてのバージョンは、2つのAWKプログラムのバージョンを平 均したものとなっています。
さて、Scena1の動作に関して簡単に触れておきましょう。このScena1は、 特にPLOT.AWKの方は、いわばシナリオ・メイキング言語のインタプリタになっ ています。つまり、あなたの作ったシナリオ作成プログラムを実行する処理系 なのです。また、あなたの作ったシナリオ作成プログラムをPLOT.AWKが実行し た結果に含まれる(はずの)、変数に、実際の言葉を埋めこむのがWORD.AWKです。 つまり、処理の工程を図にすると次のようになる訳です。
シナリオ作成言語によるプログラム | | PLOT.AWK あなたの作ったプログラムに従って、 | シナリオのひな型を作成 ↓ シナリオのひな型 | | WORD.AWK 単語辞書を元に、変数を実際の言葉に置換 ↓ シナリオの概略
この圧縮ファイルには、以下のファイルが含まれています。
Scena1は、awkのスクリプトとして実現されています。ですから、Scena1を 動かすにはjgawkの実行系が必要です。
Scena1の起動は、scena1.bat, plot.awk, plot.dic, word.awk, word.dic のあるディレクトリで、次のように入力してください。これでscena1.batが起 動し、自動的に処理を開始します。
>scena1
実際には、jgawkに、スクリプト(jgawkに対するプログラム)として plot.awkを与えています。また、引数としてplot.awkに与えるプログラムを指 定します。その処理結果を、Scena1.batではScena1.tmpというファイルに出力 します。書式としては次のようになっています。
jgawk -f plot.awk プロット辞書名 > 中間ファイル名
次に、変数の置換を行うスクリプトとしてword.awkをjgawkに与えます。ま た、引数として単語辞書とScena1.tmpを指定します。そして、最終的な結果が Scena1.txtというファイルに出力されるのです。書式は次のようになっていま す。
jgawk -f word.awk 単語辞書名 中間ファイル名 > 処理結果ファイル名
Scena1は2つのプログラムから出来ていると書きましたが、それぞれの概略 について説明ます。
これは、キャンペーンの大まかなプロットを作成するためのプログラムで す。実際には、PLOT.DICというプロットの辞書を読み込み、それに書かれてい るコマンドにしたがってプロットを生成します。また出力として、SCENA1.TMP というファイルを出力します。
注:ここで示した『PLOT.DIC』『SCENA1.TMP』という2つのファイルの名前 は、固定的なものではありません。詳しくは、『Scena1.BAT』をご覧ください。
これは、PLOT.AWKが作り出したプロットデータ『PLOT.SAG』の中に含まれ る単語変数を、単語辞書『WORD.DIC』に書かれている単語データで置換するプ ログラムです。なお、このプログラムでは、PLOT.AWKの出力であるPLOT.SAGと、 WORD.DICを読み込み、使用します。ただ、Scena1の本来の目的からすれば、 WORD.AWKは使用しなくても構いません。それどころかWORD.AWKを使用すると、 お笑い文のプロットにしかならなくなるという話も……
注:ここで示した『WORD.DIC』『PLOT.SAG』という2つのファイルの名前は、 固定的なものではありません。詳しくは、『Scena1.BAT』をご覧ください。
まず、PLOT.DICに関しての説明を行います。先にも書きましたが、 PLOT.DICはプロットの構成等の辞書です。基本的な書式は以下に示すとおりで す。
paragraph paraname1 { コマンド コマンド コマンド : : : : } paragraph paraname2 { コマンド コマンド コマンド : : : : } : : : paragraph main { コマンド コマンド コマンド : : : : }
ここで、パラグラフの内容をかこむ"{""}"の内の"{"は、必ずパラグラフの 名前の宣言と同じ行に書いてください。また"}"はかならずそれだけで1行を構 成するようにしてください。そうでない場合の動作は保証しません。
また、パラグラフ名はスペースを含まない任意の文字列が使えます。
このような書式の辞書を読み込み、パラグラフ名が"main"であるパラグラ フから処理を開始します。
なお、PLOT.DICでは行の先頭に"#"を書くことによって、その行を注釈行と 見なして、処理の際は無視させることができます。
以下に、まずコマンドについて、次いで単語変数について説明していきま す。
現在、コマンドは「percent」「times」「radio」「exist」「notexist」 「set」「reset」「nul」「ifset」「ifnotset」「case」「'」「>>」「keyin」 「clrvar」の15個があります。それぞれの説明の前に、コマンドの記述のしか たについて説明しておきましょう。
なお、plot.dicの記述は、以下に示す各コマンドの記述法に従ってくださ い。そうでない場合の動作は保証いたしません。
では、それぞれの説明に移りましょう。
このコマンドは、引数として与えられた文字列を表示するコマンドです。 また、変数も引き数として指定できますが、「set」コマンドによってすでに その変数になんらかの内容が与えられている場合、その内容を出力します。内 容がまだ与えられていない場合には、変数名をそのまま出力します。
例 ' this is test この場合は、"this is test"という文字列を表示します。 ' { this is test do you understand? } この場合、"this is test""do you understand?"という2つの文字列を出力します。
このコマンドは、引数として与えられたパラグラフを呼び出すコマンドで す。
例 >> Paragraph1 これは、"Paragraph1"という名前のパラグラフを呼び出します。 >> { Paragraph1 Paragraph2 } これは、"Paragraph1"と"Paragraph2"とういパラグラフを続けて呼び出します。
このpercentコマンドは3つ以上の引数を取り、第2引数はコマンド名、第3 引数以降は第2引数として与えられているコマンドに対する引数となります。 第1の引数は、第2引数として与えられているコマンドが実行される確率です。 つまり、この第1引数に示された確率で、第2引数に示されたコマンドが実行さ れる訳です。
この第1引数は、0〜100の自然数を半角数字で与えてください。そうでない 場合の動作は保証しません。もっとも、第1引数として"100"とした場合、第2 引数で与えられているコマンドが必ず実行される事になるので、このpercent コマンドをわざわざ付けなくても動作としては同じ事になります。
例 percent 30 ' test これは、30%の確率で、"test"という文字列を出力します。 percent 30 { ' test1 ' test2 } これは30%の確率で、"test1"と"test2"という2つの文字列を出力します。
これは、第1引数で示された回数回、第2引数で示されたコマンドを実行す るコマンドです。ただし、第1引数で示された回数回とは言っても、何回繰り 返すかの数字を直接指定するわけでは有りません。第1引数として与えられる のは、ゲームにおいて見られるような、ダイスの種類とその個数を示す表記で す。つまり、"2d6"などという表記になる訳です(この例の場合、6面ダイスを2 個振ってその目の和の回数回のくり返しとなる。)。これは、その確率分布も ダイスを用いた場合などと同様になります。なお、この回数指定もかならず半 角文字で行ってください。
例 times 1d3 ' test これは、1回〜3回の間のいづれかの回数、"test"という文字列を出力します。 times 2d6 { ' test1 ' test2 } これは6面ダイスを2個振ったのと同じ確率分布で、その回数回、"test1" と"test2"という2つの文字列を出力します。
このコマンドは、次のような形で利用されます。の引数は、3個の組みで示 されます。
例 radio { 33 ' test1 33 ' test2 34 ' test3 }
これは、"test1""test2""test3"のいずれ1つのみが約1/3の確率で出力される ことになります。与えられたコマンドの内の1つだけが実行されるのです。い わゆる"ラジオ・ボタン"というものがありますが、その機能を実現したもので す。また、次のような文も可能です。
例 radio { 33 { ' test1.1 ' test1.2 } 33 { ' test2.1 ' test2.2 } 34 { ' test3.1 ' test3.2 } }
なお、それぞれの確率は、足しあわせると100以上になるようにしてくださ い。100より大きくても処理上問題とはなりませんが、逆に合計が100未満の場 合の動作は保証しません。
2つ以上の引数を取ります。このコマンドは、第1引数で指定したパラグラ フが、既に呼び出されている場合のみ、第2引数で与えられるコマンドを実行 します。
例 exist Paragraph1 ' Paragraph1-exist-already これは、"Paragraph1"という名前のパラグラフが既に呼び出されていた場合に のみ、"Paragraph1-exist-already"という文字列を表示します。 exist Paragraph1 { ' Paragraph1-exist-already ' do-you-understand? } この場合も同様に、"Paragraph1"という名前のパラグラフが既に呼び出さ れている場合にのみ、"Paragraph1-exist-already"と"do-you-understand?"と いう2つの文字列を出力します。
コマンド名が示すとおり、"exist"の逆の動作を行うコマンドです。つまり、 第1引数で指示されたパラグラフが未だ1度も呼び出されていない場合にのみ、 第2引数で与えられるコマンドを実行します。動作が逆である点を除けば、記 述の形式等はまったく同じです。
2つ以上の引数を取ります。第1引数で指定した変数に、第2引数以降で指定 した文字列あるいは変数を、半角スペースで連結したものを強制的に割り当て ます。第1引数は必ず変数名でなければなりませんが、第2引数以降は変数名で も、あるいは文字列でも構いません。もちろん、変数と文字列が混在しても構 いません。なお、指定する変数名にはかならず%を付けてください。
例 set %test %test2 この場合、%testは、処理上%test2として扱われます。 set %test テスト この場合は、%testは文字列"テスト"として扱われることになります。 set %test テスト だからテストなんだってば この場合は、%testは文字列"テスト だからテストなんだってば"として扱 われることになります。
setコマンドによる、引数に対する強制的な割り当てを解除します。なお、 指定する変数名にはかならず%を付けてください。なお、複数の引き数を指定 しても構いません。その場合、指定されたすべての変数に対し、割り当てを解 除します。
例 reset %test これで、%testに割り付けられていた変数、あるいは文字列が解除されま す。
「'」コマンドによって出力を行うさい、すでに内容が与えられている変数 はその内容に、また内容が与えられていない変数は後のWORD.AWKでの処理のた めに変数名がそのまま出力されます。しかし、この「nul」コマンドによって 指定された変数はそのいずれでもなく、空文字列を出力します。つまりその変 数が表示すべき文字列から削除されてしまうと思ってください。動作としては、 nulの引き数として与えられた変数の内容に"nul"という文字列を与えます。つ まり、動作の内容は「set %a nul」などとした場合とまったく同じなのです。
しかし、「set」コマンドと異なり、引き数は1個以上ならば何個でも構い ません。
例 nul %a %b %c
これで、%a %b %c のすべてに"nul"という内容が与えられます。なお引き 数の数は、場合にもよりますが、だいたい90個以下であれば問題なく動作する でしょう。
このコマンドは、2つ以上の引数を取ります。動作は、まず第1引数で指定 した変数に、「set」コマンドによって、第2引数に指定した文字列と同じ文字 列が設定されている場合、第3引数に指定したコマンドを実行します。
例 ifset %test テスト ' テストが設定されています。 この例だと、変数%testに"テスト"という文字列が設定されている場合、" テストが設定されています。"という文字列を表示します。 ifset %test テスト { ' 変数testには ' テストという文字列が ' 設定されています。 } この場合、変数%testに"テスト"という文字列が設定されている場合、"変 数testには""テストという文字列が""設定されています。"という3つの文字列 を表示します。
これは「ifset」コマンドとは逆の動作をします。つまり、第1引数に与え た変数に、第2引数に与えた文字列が割り付けられていない場合にのみ、第3引 数以降に指定したコマンドを実行するのです。
これは、次のような形で利用されます。
例1 case %x { a ' aがセットされています。 b ' bがセットされています。 }
つまり、ある変数と、それにセットされている文字列、およびその時に実 行するコマンドという3つ以上の組みを複数行に渡って記述できるのです。そ のような設定の組みの内、指定された変数に、指定された内容がセットされて いるという条件が最初に満足されて組みのみを実行します。また、次のような 記述も可能です。
例2 case %x { a { set %y a ' aがセットされています。 } b { set %y b ' bがセットされています。 } }
また条件、つまり「%xにaが入っている」等の条件の他に、「else」という 条件を付けられます。まずは例を見てください。
例3 case %x { a ' aがセットされています。 b ' bがセットされています。 else ' aでもbでもありません。 }
この場合、%xがaでもbでも無い場合、「else」という条件が満たされたも のとして、その行に書かれている内容を実行します。なお、この「else」とい う条件は、常に条件が満たされているものとして動作をしますので、例えば次 のような場合は、常に「else」の行の内容を実行してしまい、他の行は無視さ れます。
例4 case { else ' aでもbでもありません。 %x a ' aがセットされています。 %x b ' bがセットされています。 }
なお、次のようにcase文を入れ子には*できません *(known bug)。
例5 case %x { a { case %y { : } } : }
このコマンドは、キーボードからの入力を行います。
なお、plot.awk内では、入力を受け付けるのは半角の数字のみです。別段 一桁の数字には限りません。その他の文字が入力された場合の動作は保証しま せん。
例1 keyin %x 9
このような記述により、変数%xに、9までのいずれかの数字が入力される事 を表し、また入力を待ちます。
第1引数として与えられた変数の内容をクリアする命令です。気を付けて欲 しいのは、"set""reset"コマンドとはなんら関係が無いことです。もちろん、 "set"コマンドによって、%aという変数が%bと割り付けられている場合は、き ちんと%bをクリアするように動作しますが、それ以外にはなんの関連も有りま せん。
このコマンドは、正確には、PLOT.AWKに対する命令では有りません。 WORD.AWKにおいて、変数に割り付けられた内容をクリアし、次回その変数が現 れたときには新たに割り付け直すための命令です。
例 clrvar %test.a word.awkによって、%test.aに"テスト"という単語が割り付けられていた としましょう。その時、このコマンドを実行することによって、その割り付け をクリアすることができます。
先の「'」コマンドの引数となる文字列中には、WORD.AWKで置換する単語変 数が書き込めます。その単語変数とは「%」で始まる任意の文字列です。ただ し、"."は次に示すように特別な意味を持ちますので、不用意に使用してはい けません。
この単語変数には3つの形があり、それぞれは次のような意味を持っていま す。ここでは例として変数「%test」を例にとって説明していきましょう。
- 1回だけ変数: "%test"
- 局所変数: "%test.1"
- 大域変数: "%test.a"
i)の「1回だけ変数」とは、"%test"という変数が現れるごとに、別々の単 語に置き換えられる変数です。また、ii)の「局所変数」とは、"."の後に数字 列が付いた変数で、 各パラグラフ内で同一の単語と置換されます。もし、同 一のパラグラフが複数回実行される場合、呼び出される毎に別の単語に置換さ れます。最後の「大域変数」とは、"."の後に英字列が付いたもので、全パラ グラフを通して、同一の単語と置換されます。
なお、単語変数はその前後を半角スペースで囲んでおいてください。
単語変数を置換する単語データの辞書です。
この辞書は単語カテゴリというグループに各単語データを分割して記述し ます。単語カテゴリの名前は、単語変数の本体、つまり"%tes", "%tes.1", "%tes.a"の本体は、"%tes"、がそのまま単語カテゴリの名前になります。まず 基本的な記述方法を示しておきましょう。
%test テスト 試験 TEST %man 男の子 女の子 おじさん おばさん おじいさん おばあさん : : :
このようになります。単語カテゴリ名、およびそれぞれの単語データは、 ぞれぞれ別の行に書いてください。
また、単語データは、階層化することもできます。つまり、先の例の単語 データに、新たに"%test2"という単語カテゴリを付け加えるとしましょう。こ の"%test2"は内容として、"%test"と"%man"の単語データを含んでいるとしま す。この場合、もちろん"%test2"カテゴリとして、その全てを記述しても構わ ないのですが、次のように書くことで、記述量を少なくすることができます。
%test2 %test %man テスト2 TEST2
このように書くと、"%test2"の内容は、"%test"と"%man"の内容に加え、" テスト2"と"TEST2"という2つの単語データが合わさったものになります。 この単語データの階層化は、何段でも可能です(もっとも、AWKを使っているの で、その制約から来る限界は有りますが)。
いづれにせよ、単語変数を置換する単語は、各単語カテゴリの中に含まれ る単語から乱数によって決定されます。
また、このWORD.DICも行の先頭に"#"を書くことによって、その行を注釈行 と見なして、処理の際は無視させることができます。
という訳でScena1の解説を終了させていただきます。ところで、いかに Computer Aided Scenario Makerなどと言っても、しょせん大したことはやっ ていません。PLOT.DICにかかれているとおりの動作をしているにすぎないので す。ですから、このScena1が出力するシナリオはPLOT.DIC次第なのです。また、 Scena1によって作られたシナリオも、そのまま実用に耐えるようなものにはな らないでしょう(思いっきり根性を入れてPLOT.DICを作れば別ですが)。人間が しっかりと肉付けを行わなければ、とても使用に耐えられるようなシナリオに はならないでしょう。
そのような意味では、とても皆さんにお見せすることなどできないような プログラムです。しかし、そこはそれ"遊び"として見てやってください。ちな みに、私の周辺では、このScena1は単なる"お笑い文章生成プログラム"に成り 下がってしまっています。
なお、このScena1はMS-DOS上のjgawkで動作の確認をしておりますが、おそ らくUNIX上のjgawkでもそのまま動作するものと思われます。また、MS-DOS上 で使用する場合の辞書ファイルの大きさですが、動作環境にもよりますが、い ずれも数十Kbyte程度までならば、全く問題なく動作するはずです。
この、Scena1の第1バージョンは、非常に貧弱なものでした。可読性も最悪 でした。もちろん、非常に貧弱でしたから非常に単純なPLOT.DICしか作れませ んでした。しかし、今になって思うと、貧弱であったからこそ使い易かったの かもしれません。友人に配布し、しばらくしてから感想を聞いてみたところ、 全員が全員とも「ものすごく機能が拡張された事は充分にわかる。辞書データ を書きやすくなったのもわかる。でも、柔軟になりすぎてプロットの辞書を作 るときに、マジにプログラムを作るのと同じくらいの設計が必要だ。」と答え てきたのです。
事実、私自身もその事は実感しており、こまったもんだと思っています。 しかしこればっかりは私にも何ともできません。皆さんがこのScena1に慣れて、 すばらしいPLOT.DICを作れるようになること祈るのみです。
それはともかく、遊んでみてやってください。
では、最後にこのScena1の使用に関しての注意を書かせていただきます。
あと、使用上の注意ではありませんが、何か良いアイディアが有ったら、 ぜひとも原作者までお知らせ下さい。バージョン・アップの際(するかどうか は分かりません^_^;)、取り入れさせて頂きたいと思います。また、本来の使 用方(?)以外にも色々な活用が考えられないでもありません。何か面白い plot.dicができたなら、ぜひとも公開して頂けるようお願いいたします。
それでは、Scena1でお楽しみください。