伺かアドベントカレンダー2010 12/13

[伺かアドベントカレンダー2010]

ネタは参加表明時点で決めていたのですが、実は意外と知っている人も多い?
と思いつつも、皆がやっている風でもなさそうだし、Tips として情報共有したいよねということで。
テーマは「AYA/YAYA でランダムトークを管理する時にちょっと便利になるかもしれない話」です*1

ランダムトークの基本的な管理

基本的な方法としては、ランダムトーク用の関数にトークを列挙して、関数名の後ろに nonoverlap をつけているのではないでしょうか。

RandomTalk : nonoverlap
{
  "\0\s[0]これは、\w5トークAです。\e"
  "\0\s[0]これは、\w5トークBです。\e"
  "\0\s[0]これは、\w5トークCです。\e"
}

RandomTalk 関数が出力する結果は、列挙されたトークA・トークB・トークCのいずれかとなり、さらに nonoverlap がついていることで、一巡するまで同じ結果は重複しないようになる訳です*2

ちょっとだけ変えてみる

最初の書き方でも、ランダムトークとしては何の問題もないのですが、これを次のように書き換えてみます。
この場合も、RandomTalk 関数が出力する結果は、先ほど紹介した基本的な方法と同じものが得られます。

RandomTalk : nonoverlap
{
  parallel RandomTalkArray
}

RandomTalkArray : array
{
  "\0\s[0]これは、\w5トークAです。\e"
  "\0\s[0]これは、\w5トークBです。\e"
  "\0\s[0]これは、\w5トークCです。\e"
}

先ほどの書き方には無かった parallel とか array といったものが出てきましたので、ここで説明します。

array

これは、関数に列挙されているトークを「配列」という、トークを規則正しく納めた塊にして、結果として出力するというものです。
この場合は、RandomTalkArray 関数が出力する結果は、3つのトークが納められた「配列」そのものとなるのです*3

parallel

これは、parallel の後ろに指定されている「配列」に納められたトークを列挙するというものです。
この場合は、RandomTalkArray 関数が出力する「配列」に納められたトーク(要は、トークA・トークB・トークC)が RandomTalk 関数に列挙されることになります。ですから、結果としては最初の書き方と同じになりますね。

何でわざわざ?

結果が同じなのにもかかわらず、どうして一度「配列」にしたものを戻してから出力するという、何とも面倒臭いことをしているかというと、主に管理面でメリットがあると考えるからです。
たとえば、最初の書き方では、「RandomTalk の 1個目」と指定して出力させようとしても、(人間なら見れば分かることでも)AYA/YAYA にはそんなことはできないのです。しかし、改良した書き方では、「RandomTalkArray の 1個目」と指定すれば、AYA/YAYA は『トークA』と認識できるのです。
これを拙作のゴースト「もへじ男爵」で採用したのは、「トークナンバー(何番目のトークか?)を指定して、トークを再生させたかった」からです。feath さん作のゴースト「ラベンダー畑から」でそうした実装を見て、これいいな!と思ったのがきっかけでした*4

でもそれだけ?

「でもこれって、単に何番目のトークかを AYA/YAYA で管理できるようになるだけ?」と思ってしまいますが、実は複雑なトーク管理をしようとするほど、今回の方法の優位性が分かってきます。
たとえば、次のような応用例を挙げてみます。

// ランダムトーク発動
RandomTalk : nonoverlap
{
  parallel NormalTalkArray
  parallel AbnormalTalkArray
}

// トークの数を喋らせる
CountTalk
{
  "\0\s[0]健全なトークの数は、\w5%(ARRAYSIZE(NormalTalkArray))個です。\w9\n/
  \0\s[3]変態なトークの数は、\w5%(ARRAYSIZE(AbnormalTalkArray))個です。\e"
}

// 健全なトーク
NormalTalk : nonoverlap
{
  parallel NormalTalkArray
}
NormalTalkArray : array
{
  "\0\s[0]これは、\w5健全なトークAです。\e"
  "\0\s[0]これは、\w5健全なトークBです。\e"
  "\0\s[0]これは、\w5健全なトークCです。\e"
}

// 変態なトーク
AbnormalTalk : nonoverlap
{
  parallel AbnormalTalkArray
}
AbnormalTalkArray : array
{
  "\0\s[0]これは、\w5変態なトークAです。\e"
  "\0\s[0]これは、\w5変態なトークBです。\e"
  "\0\s[0]これは、\w5変態なトークCです。\e"
}

RandomTalk 関数では、NormalTalkArray と AbnormalTalkArray に納められているトークを parallel によって列挙して、それら(健全トーク・変態トーク)の全ての中からトークを選んで出力しています。このように、トークをグループごとにまとめておき、どのグループからトークを選んで出力するかというのを、柔軟に定義できるようになるのです。
また AYA/YAYA には、「配列」を操作するための様々なシステム関数が用意されていますので、それらを使って複雑な管理を行うことも可能です*5。ここでは、納められているデータの個数を調べるシステム関数 ARRAYSIZE を使って、トークの数をゴーストに喋らせるための関数 CountTalk を作成しています*6

最後に

今回紹介した以外にも、最近更新されたトークを優先して喋らせるなど、色々と応用は効くテクニックだと思いますので、うまく取り入れてみてはいかがでしょうか。

補遺

こちらの記事も是非ご覧下さい。

  • Ponapalt さんの記事 (id:ponapalt:20101225) にて、フラグ分岐させる場合についてのやり方が紹介されています。
  • ヒノハルさんの記事 (id:hinoharu:20101223) にて、用語解説に使用している応用例が紹介されています。

*1:他の SHIORI ユーザの皆様ごめんなさい

*2:ランダムトークって、そういうことですよね

*3:トークが選ばれて出力される訳ではないことに注意

*4:ゴースト「ラベンダー畑から」は里々ゴーストでしたので、AYA/YAYA で実装するにあたっては、ヒノハルさん作のゴースト「レチハルカ」でのランダムトーク管理を参考に作成しました

*5:どのようなシステム関数があるかについては、マニュアルを参照のこと(えー

*6:この例では、数えればすぐに分かりますが、トーク数が増えれば数えるのは大変になりますからね……