■The Making of -nomine.mp4-/環境解説:里々はひょっとしてSAORIにした方がいいのでは論
この記事は、Web企画「ゴーストマスカレード3」の参加ゴースト「nomine.mp4」に関する一連の技術および創作論等の解説記事の一つです。
- 記事群全体のインデックスはこちら→The Making of -nomine.mp4-
- 前の記事はこちら→環境解説:使用したツールやパーツ
- 次の記事はこちら→演出解説:伺かでできるホラー表現?
前置き
里々と灯についての基本情報
里々(改修版)
配布元 | https://github.com/ponapalt/satoriya-shiori/wiki |
ukatec内の用語集 | 里々 |
補足事項 | 里々はSAORIとしても使える |
灯
配布元 | http://le.silk.to/ |
ukatec内の用語集 | 灯 |
……なおこの記事では灯について以下一切触れません。灯は数多くの通信機能やマルチスレッド機能、DB機能などの変態機能を備えたC言語風記法のSHIORI(例によってSAORIにもできるし多分PLUGINとかMAKOTOにしようと思ったらそれもできそう)なんですが、nomine.mp4で採用されたのは、配列が多次元化できて辞書型のデータ構造があって便利という一点のみで、あまりそのポテンシャルは引き出せていないです。
この記事の用語について
この記事では相当雑な言葉の使い方をしておりますが、特に頻出する以下2語についてはおおよそ以下のようなふわっ…としたイメージで語っております。そういう目線の記事ですのであしからずご了承ください……
- 複雑な機能
- 複雑な処理、複雑なことなどの表現も同義。だいたいcallを使って「関数を自作し始める」「自作した関数を組み合わせ始める」あたりがボーダーかなと思います。また、call使ってないけど逆にcall使わないでそれやっちゃうの?みたいなことをジャンプ文(>)だけで実現してしまっているようなものも当然含まれます。timesとかforとか言い出すのもかなり末期ですね。あと、\![raise]とかSSP特有のさくらスクリプトの直打ちが目立ち始めているのも複雑ポイント高めです(?)
- ぷろぐらみんぐ的な
- 何がプログラミング的なのかを語れるほど作者はプログラミングをやったことがありませんが、やたら半角記号を多用し始めて、ifとかforとか言いながら{}で物を囲いだしたらだいぶプログラミング的だと思います。えっpythonとかは普通{}ないけどどうなのって? インデントが意味を持ち始めた時点でプログラミング的だと思います。そもそも関数とか引数とか言い出した時点で危ういですね。
nomine.mp4のSHIORIとSAORI
まずnomine.mp4のコンセプトについてを飛ばした方向けに改めて必要部分だけ説明しますが、nomine.mp4のSHIORI/SAORIの構成は少し独特なものになっています。
辞書フォルダを覗くとsatori.dllがいるので一見標準的里々ゴ構成のように見えますが、descript.txtよく見ると
shiori,akari.dll
となっています。つまりnomine.mp4がSHIORIとして使っているのは、「灯」と呼ばれるSHIORIになります。
ではghost/masterに間違いなく入っている「satori.dll」は何なのかというと、この記事のタイトル通りSAORIとして使われているわけです。
※SHIORIやSAORIが何かについてよくわかっていない方は、ukatecの基本用語集もご参照ください。
以上踏まえつつ、以下ではこの構成をやってみてわかったことや、長所と短所について現時点での所感をまとめていきたいと思います。
(なお、このような構成を試して見ようと思ったごく個人的な背景については、先述のコンセプトについての記事にまとめておりますので、もしご興味があればご参照ください)。
里々の長所と短所
里々をSAORIとして使うことの利点については、Donさんが書かれている記事が既にあり、当記事では里々が備えているHWND取得やSAORI-basicコールなどの機能が利点としてあげられています。
しかしながら、nomine.mp4はそれらの機能は特に用いていません。
つまり個人的には、里々をSAORIとして使うことの強みは別にあると考えているわけです。
といっても、その強みというのは、実は里々をSHIORIとして使った場合の強み(の一つ)そのままかと思います。
つまり、「トークを書くのが楽!」という一点です。
それだけならSHIORIとして普通に里々を使えばいいということになるのですが、ここで重くのしかかってくるのが里々弱点の一つである「難しいことをやり始めると途端に辞書がグチャグチャする!」ということですね。
里々で複雑なことをやりはじめると、里々は突如そのシンプルでわかりやすい外殻を突き破って名状しがたい異様な本性を表します。
それはさながら黙示録の預言の一節であり、世界中のスパゲッティコードに巻き込まれた浮かばれない丸カッコとgoto文の怨念が大理石のオベリスクに刻み付けた呪わしく古い紋様であり、朧気な猟犬に追われ狂った男が丸みを帯びた建材のみで部屋を増やし続けるウィンチェスター・ミステリー・ハウスであり、ガン化して異常増殖した孔辺細胞がみっしりと集まってできた数多くの隙間を持つ冒涜的生命であり、――つまり、この世の終わりです。
試しに先程6年ぶりに、暦にしきの辞書に掛けられていた厳重な封印を解き、スクリーンショットを撮ってきたので以下にその一部を掲載します。
SANチェック!!!SANチェック!!!!
そもそも里々の使い方を間違えているのではないか
今こうしている間にも恐ろしさのあまり筆を折りそうになっていますが、どうにか話を戻します。
とにかく里々は文字列処理が苦手です。byte値だとか変なものを使って回りくどいことをしないと、トークに含まれる特定の文字で関数がズタズタにされたりします。
変数もグローバル変数ただ一種類しかありません。軽率にローカル変数を生み出して捨てる気楽な関数の描き方もできません。
配列だとかなんだとか、いろいろな構造のデータを扱うこともできません。
そもそも型の概念もなく数値と文字列の区別もありませんので、扱いに気を付けないと1+1を2にしてほしいのに、気づいたら「1+1」という文字列になっていたり、反対に「1+1」という言葉がいつのまにか2に化けたりします。
更に輪をかけて混乱が深まるのは、上記のような仕様を支えるために、里々は水面下でものすごく変な処理をしていたり、副作用的に不思議な挙動を発生させたりするので、慣れてくるとこれら里々が覗かせたグロテスクな部分に直面して戸惑わされる瞬間です。
※なお、里々が文字列処理が苦手と内部処理とかか、そのあたりの話は詳しく書くと作者の精神が疲弊するだけでなく、記事が度し難いほど長くなるので里々wikiの下記記事なども読んでみてください。
- ユーザー入力やファイル名など外部から取得した文字列の中の()が展開されてしまう
- 里々の選択肢処理
しかし里々は、里々が想定するような使い方をする限りにおいて、あまりにも圧倒的な書きやすさがあります。
それは文字列と記号や数値を区別するためにいちいちダブルクォーテーションを書かなければいけなかったり、半角の記号や英語を並べなければいけなかったりしないからで、つまり「ぷろぐらみんぐ的」ではないからこそ実現されているされているもの。
ひるがえって、里々の辞書がすぐグロ画像になるのはなぜか? それはぷろぐらみんぐ的なことをしているからです!
それはエクセル方眼紙です! それはタガネのように使われるマイナスドライバーであり、便箋の封に使われるマスキングテープです!
といったようなことを考えながら道を模索したうちの一つが、SAORIとして里々を使う方法でした。
つまりこの構成は、里々の特定の機能を使いたいというよりは、里々のいいところをそのまま生かしつつ、見たくない部分を見なくするにはどうすればよいかという着想から来ているわけですね。
里々をSAORIとして使うという生き方
里々をSAORIとして使う構成のゴーストは、大体どんな作りになるでしょうか。
ファイル構成についてと、典型的運用イメージを挙げてみます。
ファイル構成
SAORIとして使う場合の里々のファイル構成は、だいたい以下のような感じになると思います
・[SHIORI].dll
・satori.dll(必須)
・satori_license.txt(必須!ライセンス条件なので)
・dic**.txt(今回の運用では任意。もし里々の組み込み機能だけ直接使う場合は不要。ファイル名も不要)
・replace.txt(任意)
・replace_after.txt(任意)
・dicAnchor**.txt(任意)
・satori_conf.txt(任意)
・その他SHIORI側辞書ファイル等々
replace/replace_afterも使えるのは結構便利なのではないでしょうか。Anchorも動いたはず。
なお、セーブデータ正直フォルダ内がごちゃごちゃするだけなので吐き出したくないんですが、累計起動なんちゃらみたいなシステム変数を保存するために里々が自動生成しちゃうので止められません。
以下ちょっと検証不十分なものも含めて、里々をSAORIとして使う場合はSHIORIと挙動が違うなと思われる部分の列挙です。嘘だったらすみません。
- satori_conf.txtにおいて、辞書系の設定変数がうまく機能しない。
SAORIとして動作する場合はある種SHIORIの一部として機能するので、たとえsatori.dllがSHIORI本体のdllより深いディレクトリに置かれていても、里々側辞書の階層はSHIORI本体側のdllが置かれている場所がルートディレクトリになる上2つの挙動が組み合わさった結果、里々側の辞書だけフォルダを分けて整理するということができない。里々側の辞書は、全部SHIORI側のdllと同じ場所に置かなければならなくなる。気がする。作者の勘違いでなければ、正直改修依頼出したいポイント。どうやら打消し線部の挙動は、nomine.mp4で使用したSHIORIである灯側の実装による影響の可能性が高まっているため、この部分訂正いたします。ご指摘いただいた方ありがとうございました。YAYAなどがSHIORIの場合はこの事象は起きない様子。(2021.5.29)- characters.iniは動作しないっぽい?
基本的な運用イメージ
先立って、nomine.mp4作成時に意識していた運用上の原則を以下並べます。
- 里々側の辞書はただの文字列取得用リソースと心得よ(ある意味本来的な意味での「辞書ファイル」)
- 里々側で変数保存すべからず(といっても自動保存される里々のシステム変数的なものがあるためセーブデータは出ちゃうんですけど)
- 里々側の条件分岐は最小限にとどむるべし(SHIORI側でやろう)
- 里々側の括弧は極力入れ子にすべからず(その処理SHIORI側でできませんか?)
単に里々をSAORIにするだけではなく、里々に複雑な処理をさせないという強い気持ちをもち、里々のもつ「素直にトークを書く」こと以外の機能は決断的に無視していくことが重要なわけですね。
基本的に、SHIORIイベントが発生したときにどのような処理をするかはSHIORI側で実装します。
例えばOnMouseDoubleClickが来たとして「当たり判定が●●のときは『●●つつかれ』というトークを探し、なければメニューを開く」といった処理の流れはSHIORIで記述します。
そしてこの「●●つつかれ」というトークを探すときに、SHIORIは自分の辞書内からではなく、SAORIとして里々を呼び出し、「●●つつかれ」という機能名で実行しようとするわけです。里々側で指定されたモノが見つからなければ、204 No Contetntが返りますので、その場合は「なければ」の処理に入るという具合です。
里々の呼び出し時、当然引数を渡すことももちろんできます。フラグ(変数)に応じて実行されるトークの種類が変わるような場合には、SHIORI側で持っている変数を引数として里々側に渡して簡単な分岐程度はさせることも可能です。なお、SAORI呼び出し時の引数は、里々側辞書では「(R*)」で参照できます。そのまま条件式にして
*throatつつかれ【タブ】(R0)==強 :グエッ!!! *throatつつかれ【タブ】(R0)==弱 :どうしました?
とかも動きます。なんたって里々そのままなので!
ただし↑例のR0はSHIORIとして里々がOnMouseDoubleClickを受けた時のR0と同じではなく、あくまでSHIORIから里々に渡した0番の引数である点は注意が必要ですね。
上の例のように里々の記法で書かれたトークを呼び出した場合は、戻り値ももちろんいつもどおりの里々の挙動でさくらスクリプトに変換されたものが返ります。
ちなみにファイル構成のところでも書きましたが、replaceもreplace_afterも使えますよ。ただ里々側でreplaceしてSHIORI側でOnTranslateでまた変換してみたいなことをやると多分頭が疲れるので程々にですが。
なお、SAORIとして戻り値を返したい場合は、下記のように「Value*」へ代入してやればよいです。
*throatつつかれ :グエッ!!! $Value0=1
この場合Resultが「\0グエッ!!!」とかになって、Value0が「1」になるはずです。
一応これで、SHIORI/SAORI間の情報の受け渡しもできるので、例えば特定のトークがランダムに選ばれた場合にだけ進行するフラグ、とかも対応可能です。
っていうか里々のValue*はゴースト間コミュニケートだけが役割じゃなかったんですね。地味に里々マニアとしては興奮ポイントですよ。
なお、呼び出された「●●つつかれ」の実体が里々にとって何であるかは自由なことも一つポイントです。つまりその呼び出されたものが単語群でも、トークでも、ビルトイン関数でも、あんまりやりたくないけど変数でも、()で呼び出せるものはSAORI機能として呼び出せます。このあたり、変な使い方ができそうでワクワクしますが、趣旨から外れそうなので節制しています。
既存構成との比較
さて、ここで既存の各構成との比較をざっくりまとめてみました。
「SHIORI:里々 SAORI:なし」構成の長所と短所
100%里々の持ち味と付き合っていくスタイル。
ここまでに述べた通り、トークが書きやすい(こともその一つの現れとして、本質的にはいわゆるC言語ライクのプログラミング的な記号やルールがないので、とっつきやすく見える)、というのが特徴ですね。
長所 | ・トークがすごく書きやすいよ ・ドキュメント豊富だよ ・さとりすとなどのツールも充実! |
短所 | ・複雑なことが苦手(文字列処理が苦手/そもそも複雑なことをやるための仕組みが控えめ/それでも無理やり複雑なことをやると辞書の可読性が著しく下がりやすい) |
どんな人/ゴーストに向いている? | ・プログラミング的な経験がない方 ・プログラミング的な記号に拒否反応がある方 ・アルファベットに親を何人かころされている ・ランダムトークや触り反応メインなど、スクリプトの構造としてはオーソドックスなゴーストを作りたい場合 |
「SHIORI:里々 + SAORI」構成の長所と短所
いわゆるYAYA as SAORIを使っている里々の構成を想定しています。
実際多少面倒な機能を実現したくとも、これで十分な場合も非常に多いのですが、1機能単位で複雑なことをやりたい場合(例えば特定のファイルの読み書きがしたい)についてはこの構成で十分でも、ゴーストの中核的なコンセプトがむしろトークではなくその機能、という場合には不十分な可能性があります。
長所 | ・ほぼ里々単体のゴーストの制作スタイルを変えずに純粋な拡張だけで実現可能 ・そのわりに複雑なことや里々が苦手な文字列処理なども補えるよ |
短所 | ・ゴーストの中核的な部分に複雑な機能が絡んでくる場合、里々の短所がモロに見えてくる場合があるよ ・実現したい機能によっては、SAORIにする側の辞書記法も習得する必要がある |
どんな人/ゴーストに向いている? | ・里々でゴースト制作経験があるが、複雑な機能もやってみたくなった方 ・複雑な機能がゴーストにとってオプションであったりごく一部の機能レベルにとどまる場合 |
「SHIORI:里々以外 SAORI:なし」構成の長所と短所
主として作者が使ったことのあるYAYAとか灯を想定しています。
長所 | ・SHIORIによるが、複雑なことをやりたい場合たいてい里々より機能も用意されておりゴチャゴチャもしにくい |
短所 | ・里々みたいにトークが書けない(暴論) ・里々ほどドキュメントの整備やツールの支援がされていない場合がある |
どんな人/ゴーストに向いている? | ・プログラミング経験者 ・ゴーストの中核的な部分に複雑な機能が絡んでくる場合 ・機能面メインで、トークの量や長さに重きを置いていない |
「SHIORI:里々以外」+「里々風トーク記法モジュール」という構成
ここではあやりりすExや、灯のサンプルゴースト「639C 灯花」のような、拡張機能的に里々に近い記法を実現している里々以外のSHIORIを想定しています。
プログラミング経験者にとっては、ゴーストを初めて作ろうと思った場合、里々を使うよりもこの構成の方がずっと直感的でやりやすいこともあるのではないでしょうか。
ただ、作者としてはこの構成を試そうとしてみてあまりしっくりこなかったのが、「里々をSAORIにしよう」という動機の一つでもありました。
長所 | ・プログラミング的処理部分と単なるトーク記述が分離されているため、処理の書きやすさ/読みやすさとトークの書きやすさが両立している |
短所 | ・里々に慣れ過ぎているとかえって「里々のようだけど里々じゃない」部分への不自由さが目立つ |
どんな人/ゴーストに向いている? | ・プログラミング経験者 ・機能面もトークの量もどっちにも重きを置きたい場合 |
「SHIORI:里々以外 + 里々」構成の長所と短所
長所 | ・プログラミング的処理部分と単なるトーク記述が分離されているため、処理の書きやすさ/読みやすさとトークの書きやすさが両立している ・トーク部分では里々の記法が「そのまま」使えるので、里々利用者の移植先として使いやすい ・(めちゃめちゃ元も子もないことを言うと)頑張って処理部分とトーク部分を分離しようと思ったけどさっぱりどうにもならんと思ったら里々側で複雑なことを……しちゃえなくもない…… |
短所 | ・2種類の記法を必ず習得する必要がある ・あまりにもSAORI呼び出し頻度が高すぎると動作速度に影響が出る可能性(まあ呼び出しタイミングとか工夫で割とどうにでも問題ないレベルにできるのでは) |
どんな人/ゴーストに向いている? | ・里々に慣れ過ぎた方が、別のプログラミング的な記法ができるSHIORIに移植したい場合 ・里々に慣れ過ぎた方が、機能面もトークの量もどっちにも重きを置きたい場合 |
まとめ?
長々と(文字量的にも執筆時間的にも)書いてきたこの記事ですが、言いたいことは三行でまとめられます。
- 里々で処理フローとか文字列処理とかその他もろもろやるのしんどいが里々のトーク記述楽過ぎて逃げられん
- あやりりすExとか639C 灯花みたいな「里々ライク」記法はかえって似ているが故の違和感があり移植も面倒
- じゃあむしろ条件分岐とかフラグ管理とか(≒SHIORIの分担)は他でやって、里々は軽量マークアップ言語的用法に留めては?
つまり…
里々の幻影に取り憑かれて里々に似た何かでは満足できなくなってしまっている人が、トークもそこそこ書きたいけど、ゴーストの構造自体を特定の機能に特化した作りにしたい(例えばランダムトークやらメニュー表示やらは排除して一本道の「動画再生風ゴースト」にしたい、というレベルの特殊な構造)というニッチジャンルすぎる欲望を抱いた場合にしかあんまり用がないです。
さらなるツッコミとオチ
話の終わりに、一つ釈明したいです。
ひょっとしたら薄々気づいている方もいるかもしれませんが、実はnomine.mp4はそんなに「里々をSAORIとしてつかう」構成には向いていません。なぜなら全然普通のトークをしてないからです。
里々の長所が全然活きていないので、nomine.mp4にとっては、正直純粋に全部灯かYAYAでやったほうが良かったとおもいます。
このことについて特に考えがあってそうなっているわけではなく、コンセプトとして挙げたうち「里々をSAORIとして使ってみようぜ」の部分だけが他の要素と致命的にかみ合わせが悪かったというだけです。
なのでこの構成のポテンシャルがまだ全然掴めてない……というのが現時点の結論なのでした。このクソ長文はなんだったんだ?
ただ、更新停止からはや数年、うちで放置され続けている暦にしきという奴には、だいぶ向いていると思うんですよね。
検証は続きます。