Claudia
ランタイムの道具を一望にする頁ですわ。ACT、WORD、GLOBAL、SAVE、PASTA――scripts/ から呼べる道具を、ここにまとめて並べましたの。
Anthony
どの道具で何ができるのか、ここを開けば分かるわけでございますね。
この章は、ゴースト作者が scripts/ 配下の Lua スクリプトと Pasta DSL の Lua ブロックから呼ぶランタイム API のリファレンスである。作例と記述の型は scripts/ の記述パターン で扱う。対象方言は LuaJIT 2.1(Lua 5.1 系)である。
ACT(act)は、シーン関数とイベントハンドラが第 1 引数で受け取るオブジェクトである。台詞や表示制御をトークンとして積み、ランタイムがそれをさくらスクリプトに組み立てて応答にする。SHIORI のイベントごとに新しい ACT が作られる。SHIORI リクエストの内容を表す act.req のフィールドは act.req を参照する。
| フィールド | 内容 |
act.actors | アクター名 → アクターオブジェクトの表(pasta.toml の [actor] とアクター辞書で定義したアクター) |
act.save | 永続化データの表(SAVE) |
act.var | ローカル変数の表。DSL の $名前 は var.名前 になる。ACT ごとに新しい表で、Call で呼んだ先のシーンやチェイントークの続きとも共有される(ローカル変数) |
act.app_ctx | ゴーストの実行中(辞書の再読込まで)保たれる汎用の表。全 ACT で同じ表であり、永続化はされない |
act.req | SHIORI リクエストの内容(act.req) |
act.アクター名 | そのアクターのアクタープロキシ(アクタープロキシ) |
- 上記以外のフィールド(
act.token・act.current_scene など)はランタイムが使う。スクリプトから書き換えない。
local save, var = act:init_scene(SCENE)
act:init_scene(scene, scene_name?, local_scene_name?, line_map?) -> save, var
- Lua ブロックで定義するシーン関数(
function SCENE.名前(act, ...))の先頭で呼ぶ。SCENE は、その Lua ブロックが属するグローバルシーンのシーンテーブルである。
- 2 番目以降の引数は、止まるエラーの表記に止まった場所を示すために、辞書から作った関数(生成コード)が渡す。作者が Lua で書くシーン関数では省略できる。省略すると、止まった場所は登録名から通し番号を落とした名前(
*名前)で示し、.pasta の行は示さない。
| パラメータ | 型 | 説明 |
scene | table | シーンテーブル |
scene_name | string または nil | グローバルシーンの、辞書に書いた名前(別名で置き換える前の名前) |
local_scene_name | string または nil | ローカルシーンの、辞書に書いた名前。暗黙の開始ブロックでは nil |
line_map | string または nil | 生成コードの行と .pasta の行の対応(生成される Lua コードの形) |
- 渡した名前と対応は、
act.scene_name・act.local_scene_name・act.line_map に控えるだけで、止まるエラーの表記にだけ使う。出力・名前の検索には使わない。
- 戻り値の
save・var は act.save・act.var と同じ表である。
- 呼ぶと、そのシーンが実行中のシーンになる。名前の検索(検索と呼び出し)の 1・2 段目と、選択肢が記録する「選択肢を出したグローバルシーン」(choice)は、実行中のシーンを基準にする。
- 実行中のシーンは、次に
init_scene が呼ばれるまで変わらない。ただし、call_restore・word・expr_fn・expr_fn_var・global_fn で呼んだ関数から戻ると、呼ぶ前のシーンに戻る(検索と呼び出し)。
- シーン関数でない関数(
GLOBAL の関数など)で save・var が必要なときは、init_scene を呼ばずに act.save・act.var を使う。
- シーン関数は、アクション行の
@名前(…)・@単語・@$変数名(…)・@$変数名 から呼ばれた場合も、第 1 引数に ACT を受け取る。アクタープロキシを受け取るのは、アクション行のアクターの表の関数だけである(関数スコープの展開先)。
function SCENE.カウント(act)
local save, var = act:init_scene(SCENE)
save.count = (save.count or 0) + 1 -- 永続化される
var.temp = "一時データ" -- この ACT の間だけ有効
end
| メソッド | 積むもの | 戻り値 |
act:talk(actor, text) | アクターの台詞 | act |
act:sakura_script(actor, text) | アクターに属するさくらスクリプト | act |
act:raw_script(text) | 変換しないさくらスクリプト | act |
act:talk(actor, text) -> act
| パラメータ | 型 | 説明 |
actor | Actor | 発言するアクターのアクターオブジェクト(act.アクター名.actor) |
text | any | 台詞。nil のときは何も積まない。それ以外の値は tostring で文字列にする |
- 台詞は、応答を組み立てるときに、アクターの表を使って
@pasta_sakura_script の talk_to_script でウェイト付きのさくらスクリプトに変換される(act:talk との関係)。
- 発言するアクターが替わると、そのアクターの立ち位置を示す
\p[番号] が台詞の前に出力される(スポット操作)。同じアクターの続けての台詞は 1 つにつながる。
- 第 3 引数は生成コードが使う(変数参照の値が
nil のとき、値の無い変数の失敗として報告する変数名。実行時の失敗の出力)。
act:talk(act.さくら.actor, "こんにちは")
act.さくら:talk("こんにちは") -- アクタープロキシ経由。同じ台詞を積む
act:sakura_script(actor, text) -> act
アクターに属するさくらスクリプトを積む。アクション行に書いたさくらスクリプトの生成先である。talk と同じく、組み立て時に talk_to_script を通る。
talk と違い、続けて積んでも他のトークンとつながらず、1 回の呼び出しのテキストごとに talk_to_script を通る。
- 囲み(
\_?…\_?・\_!…\_!)は、開きと閉じを 1 回の呼び出しのテキストに入れる。開きと閉じを別々の呼び出しで積むと囲みとして読まれず、それぞれ閉じの無い \_?(\_!)としてただのタグになる(文字の分類)。
act:sakura_script(act.さくら.actor, "\\_?\\s[1]\\_?") -- 囲みとして読まれる
act:raw_script(text) -> act
さくらスクリプトを、変換せずに(ウェイトの挿入を経ずに)積んだ順の位置へ出力する。アクターに属さないため、\p[番号] の出力やアクターの切り替えには関わらない。
act:raw_script("\\![raise,OnMyEvent]")
SHIORI のイベントでランタイムが渡す ACT は SHIORI 用の ACT であり、pasta.act の共通のメソッドに加えて次のメソッドを持つ。テストなどで pasta.act の ACT.new から作った ACT には無い。
| メソッド | 内容 | 戻り値 |
act:set_property(name, value) | ベースウェアのプロパティへの書き込み(次節) | act |
act:get_property(name_or_names, timeout, timeout_message) | ベースウェアのプロパティの読み取り(次節) | プロパティの値 |
act:transfer_date_to_var() | act.req.date の日時を var の日時変数に入れる。act.req か act.req.date が無ければ何もしない(日時変数) | act |
act:transfer_req_to_var() | Reference 0〜9 と act.req.id・act.req.base_id を var のリクエスト変数に入れる。act.req が無ければ何もしない(リクエスト変数) | act |
act:set_property(name, value) -> act
| パラメータ | 型 | 説明 |
name | string | プロパティ名。nil・空文字列は不可 |
value | any | 値。nil は空文字列として扱い、それ以外は tostring で文字列にする |
- プロパティの書き込みタグ
\![set,property,名前,値] を、raw_script と同じ扱いのトークンとして積む。
name が nil か空文字列のときは error になる。
- 名前と値はタグの引数として自動でエスケープされる。
\ は \\、% は \%、] は \] になり、, か " を含む場合は全体を " で囲んで中の " を "" にする。
- DSL の
$%名前=値 は act:set_property("名前", 値) になる(プロパティ変数)。
act:set_property("sakura.name", "Alice")
act:set_property("score", 100) -- 数値は tostring される
act:set_property("flag", "on"):talk(act.さくら.actor, "設定しました")
act:get_property(name_or_names, timeout?, timeout_message?) -> string | nil, ...
| パラメータ | 型 | 既定 | 説明 |
name_or_names | string または string の配列 | — | プロパティ名、または名前の配列(1 つ以上) |
timeout | number | 5 | 結果を待つ秒数 |
timeout_message | string | "callback timeout: get_property" | タイムアウトしたときのエラーの理由 |
戻り値: 名前の数だけの値。名前を配列で渡したときは、配列の順の多値で返る。値が空文字列のものと、結果に含まれなかったものは nil になる。
- シーンのコルーチンの中でだけ呼べる。コルーチンの外(
REG のハンドラの本体など)で呼ぶと error になる。
name_or_names が nil・空文字列・空の配列のとき、配列に nil や空文字列の名前があるとき、文字列でも表でもないときは error になる。
- 呼ぶと
\![get,property,OnPastaCallBack{N},名前,…] のタグだけを応答として返してシーンを中断し、ベースウェアから結果が届くと再開して値を返す(OnPastaCallBack)。
- 呼ぶ前に積んだトークンは、中断の応答には含まれない。再開した後にそのまま残り、以降に積んだトークンと一緒に出力される。
timeout 秒を過ぎても結果が届かないと、シーンの中で timeout_message を理由とするエラーが発生し、シーンはそこで終わる(警告ログが出る)。期限は呼び出し時の時刻に timeout を足した時刻で、時刻の設定し直しによる飛びを差し引いた時計で数える(時刻の飛び)。判定は OnSecondChange の既定ハンドラが行う。
- 名前は
set_property と同じ規則でエスケープされる。
- DSL の
$x=$%名前 は var.x = act:get_property("名前") になる(プロパティ変数)。
local version = act:get_property("baseware.version")
local w, h = act:get_property({
"currentghost.balloon.scope(0).validwidth.initial",
"currentghost.balloon.scope(0).validheight.initial",
})
local name = act:get_property("sakura.name", 10, "name取得タイムアウト")
| メソッド | 積むもの | 出力 |
act:surface(id) | サーフェスの変更(id は数値または文字列) | \s[id] |
act:wait(ms) | ウェイト。ms を切り捨てた整数で、負の値と nil は 0 | \_w[ms] |
act:newline(n) | 改行。n を省くと 1 | \n を n 個 |
act:clear() | 表示のクリア | \c |
- いずれも
act を返し、続けて呼べる。
- 表示制御のトークンは、直前に積まれた
talk・sakura_script のアクターの出力の中に入る(そのアクターの立ち位置に効く)。
- 1 回の出力(
yield またはシーンの終了で区切られる範囲)の中で、まだ talk も sakura_script も積まれていないうちに積んだ表示制御は、どのアクターにも結び付かず、スコープ切替タグを付けずに、積んだ位置にそのまま出力される。clear_spot の後、まだ発言を積んでいないうちに積んだ表示制御も同じである。choice・choice_timeout も同じ規則に従う。
- 発言者の表情は、発言の中か発言の後に書く。発言より前に積んだ
surface は、次の発言者の表情にはならない。
act:talk(act.さくら.actor, "えっ")
act:surface(5):wait(500):talk(act.さくら.actor, "驚いた!"):newline()
| メソッド | 内容 | 戻り値 |
act:set_spot(name, number) | アクター name の立ち位置(スポット番号)を number にする。act.actors に無い名前は無視する | nil |
act:clear_spot() | すべてのアクターの立ち位置を消す | nil |
- 立ち位置の変更は、応答を組み立てるときに積んだ順に反映され、以降の発言の
\p[番号] が変わる。設定はイベントをまたいで保たれる。
- 立ち位置が無いアクターは、スポット 0 で話す(警告ログが出る。actor_proxy が作るその場限りのアクターでは出ない)。
- 1 回の出力の中で、同じアクターの発言が
set_spot の前後に続くと、後の発言も変更前の立ち位置で出力される(変更はそのアクターの続く発言の後に反映される)。
clear_spot の後の発言は、前の発言と同じアクターでも、clear_spot とその後の set_spot を反映した立ち位置で出力される。
- 戻り値が
nil のため、続けて呼べない。
- DSL の
% 行は、シーンの先頭で clear_spot() と、並べたアクターごとの set_spot(名前, 番号) を生成する(シーンスコープ内でのアクター指定)。
act.アクター名(act.さくら など)は、そのアクターを添えて ACT のメソッドを呼ぶアクタープロキシを返す。
| 呼び方 | 内容 | 戻り値 |
act.さくら:talk(text) | act:talk(act.さくら.actor, text) と同じ | nil |
act.さくら:sakura_script(text) | act:sakura_script(act.さくら.actor, text) と同じ | nil |
act.さくら:word(name, var_path) | アクター辞書を先に探してから単語を探す(アクタースコープと単語参照の統合)。見つかった関数には、アクターの表で見つかったときはプロキシを、それ以外の段で見つかったときは ACT を渡す。var_path の扱いは act:word と同じで、動的参照のときアクターの表は、表自身のフィールド(name と pasta.toml の [actor.名前] で設定した値など。create_word などのメソッドは含まない)だけを探す | 単語、関数の戻り値、または nil |
act.さくら:expr_fn(key, ...) | act:expr_fn と同じ検索で関数を探して呼ぶ(アクターの表は探さない)。関数の第 1 引数は ACT | 関数の戻り値、または nil |
act.さくら:expr_fn_var(value, var_path, ...) | act:expr_fn_var と同じ検索で関数を探して呼ぶ(アクターの表は探さない)。関数の第 1 引数は ACT | 関数の戻り値、または nil |
act.さくら.actor | アクターオブジェクト | — |
act.さくら.act | 元の ACT | — |
word・expr_fn・expr_fn_var は、呼んだ関数の先頭の戻り値が ACT またはそのプロキシそのものなら nil を返す。それ以外の戻り値は、複数の値も含めてそのまま返す。ACT の word・expr_fn・expr_fn_var・global_fn は戻り値を変えない(関数スコープの展開先)。
talk・sakura_script は nil を返すため、プロキシの呼び出しは続けて書けない。
- メソッド名(
talk・wait・yield など)やフィールド名(save・var・actors など)と同じ名前のアクターは、act.名前 ではプロキシにならない。
- 生成コードは、アクション行の発言とアクター付きの単語参照・関数呼び出しを、
act.名前 ではなく actor_proxy で得たプロキシで書く(ぱすた:こんにちは は act:actor_proxy("ぱすた"):talk("こんにちは"))。名前を文字列で渡すため、メソッド名・フィールド名と同じ名前のアクターも、アクション行では話せる。
以下のメソッドは、名前を スコープ解決アルゴリズム の 5 段で探す。モード(mode)によって、2 段目と 5 段目で探す対象が変わる。
| モード | 2 段目(前方一致) | 5 段目(前方一致) | 使うメソッド |
"word" | 実行中のシーンのローカル単語 | グローバル単語 | word |
"scene" | 実行中のシーンのローカルシーン | グローバルシーン | find_scene・call・call_restore |
"expr" | 実行中のシーンのローカルシーン | グローバルシーン | expr_fn・expr_fn_var |
- 以下のメソッドが「失敗を報告する」とは、ログに警告を 1 行出し、失敗表記を act に積むことである(実行時の失敗の出力)。
- 1 段目(実行中のシーンのシーンテーブル)・3 段目(act のメソッド。関数の値だけ)・4 段目(
GLOBAL テーブル)は、どのモードでも同じである。
@pasta_search を読み込めない環境(テストなど)では、2 段目と 5 段目を飛ばす。
- 5 段目でグローバルシーンを探すときは、範囲を指定しない search_scene を使うため、検索キーが pasta.toml の別名表の別名と完全に一致すると、置き換え先の名前で探す(シーン名の別名)。既定の別名表のもとでは、
act:call(nil, "会話", nil) は act:call(nil, "OnTalk", nil) と同じ候補(*OnTalk と *会話 で宣言したシーンを含む)から選ぶ。2 段目(ローカルシーン)と単語の検索は置き換えない。
word・expr_fn・expr_fn_var・call_restore と、アクタープロキシの word・expr_fn・expr_fn_var は、見つけた関数から戻った後、実行中のシーンを呼ぶ前のシーンに戻す。関数の中で別のシーンが init_scene を呼んでも、戻った後の名前の検索は呼び出し元のシーンを基準にする。call は戻さない(call)。
- 変数の値を名前にする動的参照(
var_path を渡した word と expr_fn_var。DSL の 動的単語参照)は、3 段目を探さず、1 段目はシーンテーブル自身のキー(__global_name__・シーン関数・Lua ブロックで定義した関数)だけを探す。4 段目の GLOBAL は探すため、値が GLOBAL に登録された名前(ランタイムが登録する yield・チェイントーク を含む)と同じなら、その関数が見つかって呼ばれる。
act:word(name, var_path?) -> string | nil
| パラメータ | 型 | 説明 |
name | string(var_path があるときは任意の値) | 単語名。var_path があるときは変数の値 |
var_path | string または nil | 動的参照のときの変数の場所("var.x"・"save.x"・"args[1]")。警告ログと失敗表記に使う |
var_path が nil のとき、name が nil か空文字列なら、何もせずに nil を返す。
var_path があるときは、name を WORD.dynamic_key で単語名に直してから探す(WORD.dynamic_key)。直せない値なら、失敗を報告して探さずに nil を返す。探すときは動的参照の探し方(検索と呼び出し)になる。
"word" モードで探し、見つかったのが関数なら 関数(act) を呼んでその戻り値をそのまま返す。関数以外の値なら tostring した文字列を返す。
- 見つからなければ失敗を報告して
nil を返す。
- DSL の
$x=@単語 は var.x = act:word("単語")、$x=@$y は var.x = act:word(var.y, "var.y") になる。アクション行の @単語・@$y はアクタープロキシの word を使う(DSL と Lua の対応表)。
act:find_handler(mode, key, skip_methods?) -> any | nil
act:find_act_handler(mode, key, skip_methods?) -> any | nil
| パラメータ | 型 | 説明 |
mode | string | "word"・"scene"・"expr" |
key | string | 検索する名前 |
skip_methods | boolean または nil | 真なら動的参照の探し方(3 段目を探さず、1 段目はシーンテーブル自身のキーだけ)にする。省略時は通常の探し方 |
- 5 段で探し、最初に見つかった値(関数・文字列など)を、呼ばずにそのまま返す。見つからなければ
nil を返す(失敗は報告しない)。
- ACT の
find_handler は find_act_handler と同じ結果を返す。アクタープロキシの find_handler は、"word" モードのときアクター辞書を先に探す。
"word" モードの 2・5 段目は、単語辞書から候補の値(文字列)を 1 つ返す。候補のシャッフル&順次消費はこの呼び出しでも 1 つ進む(シャッフル&順次消費)。
"scene"・"expr" モードの 2・5 段目は、見つかったシーンのシーン関数を返す。
act:expr_fn(key, ...) -> any
"expr" モードで探し、見つかったのが関数なら 関数(act, ...) を呼んでその戻り値を返す。2・5 段目でシーンが見つかった場合も、そのシーン関数を同じく呼ぶ。
- 関数以外の値が見つかったとき、または見つからないときは、失敗を報告して
nil を返す。
- DSL の式の中の
@関数(…) は act:expr_fn("関数", …) になる。アクション行の中ではアクタープロキシの expr_fn を使う(関数スコープの展開先)。
act:expr_fn_var(value, var_path, ...) -> any
| パラメータ | 型 | 説明 |
value | any | 関数名にする変数の値 |
var_path | string | 変数の場所("var.f" など)。警告ログと失敗表記に使う |
... | any | 呼び出す関数に渡す引数 |
value を WORD.dynamic_key で関数名に直し(WORD.dynamic_key)、動的参照の探し方(検索と呼び出し)で "expr" モードで探す。見つかった後の扱いは expr_fn と同じである。
value を関数名に直せないときは、失敗を報告して探さずに nil を返す。
- DSL の式の中の
@$f(…) は act:expr_fn_var(var.f, "var.f", …) になる。アクション行の中ではアクタープロキシの expr_fn_var を使う(動的関数呼び出し)。
act:find_scene(key) -> function | nil
"scene" モードで探し、見つかった値(通常は関数)を呼ばずに返す。act:find_handler("scene", key) と同じである。
- 第 2・第 3 引数(
global_scene_name・attrs)は受け取るが使わない。
SCENE.co_exec(act, 名前) は、この方法で名前を解決する(REG)。
act:call(global_scene_name, key, attrs, ...) -> any
| パラメータ | 型 | 説明 |
global_scene_name | string または nil | 使わない(生成コードは SCENE.__global_name__ を渡す) |
key | string または nil | 検索する名前。動的ターゲットの生成コードは call_key の戻り値を渡す |
attrs | table または nil | 使わない(生成コードは {} を渡す) |
... | any | 呼び出す関数に渡す引数 |
"scene" モードで key を探し、見つかったのが関数なら 関数(act, ...) を呼んでその戻り値を返す。関数は末尾位置で呼ぶ(return 関数(act, ...))ため、return act:call(…) の形で呼び出しをつないでも、呼び出しは深くならない。
- 関数以外の値が見つかったとき、または見つからないときは、警告ログ
act:call - handler not found: key='名前', mode='scene', via=act とともにシーンが見つからない失敗を報告して、nil を返す。Lua から直接呼んだ場合も、DSL の Call 行と同じく失敗表記を積む。
key が nil のときは、検索せずに警告ログ act:call - nil key (undefined variable?), skipping scene search とともに名前にならない値の失敗を報告して nil を返す。
key が call_key の返した「呼ばない」印のときは、検索も警告もせずに nil を返す(警告と失敗表記は call_key が出している)。
- 呼び出しはコルーチンを新しく作らず、実行中のシーンのコルーチンの中で行う。呼んだ先で
yield すると、呼び出し元のシーンごと中断する。
- 実行中のシーンは戻さない。呼んだ先のシーン関数が
init_scene を呼ぶと、戻った後も実行中のシーンは呼んだ先のシーンのままになる。戻った後に呼ぶ前のシーンへ戻す呼び出しは call_restore である。
- DSL の Call 行は、ローカルシーンの最後の行なら
return act:call(SCENE.__global_name__, "名前", {}, 引数…)、それ以外の行なら act:call_restore(SCENE.__global_name__, "名前", {}, 引数…) になる。動的ターゲット(>$名前 など)では、"名前" の代わりに act:call_key(…) が入る(Call / Jump)。
act:call(nil, "挨拶", nil) -- 「挨拶」で前方一致するシーンを探して呼ぶ
local fn = act:find_scene("挨拶") -- 呼ばずに関数だけを得る
act:call_restore(global_scene_name, key, attrs, ...) -> any
- 引数は call と同じである。
act:call を呼び、その戻り値をすべてそのまま返す。
- 戻った後、実行中のシーンを呼ぶ前のシーンに戻す。呼んだ先がシーン関数でも Lua の関数でも、見つからなかった場合や
key が nil・「呼ばない」印の場合でも戻す。呼んだ先が yield で中断した場合は、再開して戻った時点で戻す。
- 実行中のシーンと一緒に、
init_scene が控えたシーンの名前 2 つと行の対応も呼ぶ前のものに戻す(止まるエラーの表記が、戻った後の行で止まったとき呼び出し元のローカルシーンまで示せる)。
- 戻すのは実行中のシーン(と上の控え)だけである。記録の無い選択 ID の行き先の検索に使う「最後に
init_scene を呼んだグローバルシーン」(OnChoiceSelectEx)は戻さない。
- 戻った後に処理が残るため、呼び出しの段が 1 つ残る(
return act:call(…) は末尾呼び出しで段を残さない)。呼んだ先の中で return act:call(…) でつないだ呼び出しは深くならない。
- DSL の Call 行のうち、ローカルシーンの最後の行でないものはこの呼び出しになる。
act:call_restore(nil, "雑談", nil) -- 「雑談」を呼び、戻った後も実行中のシーンは呼ぶ前のまま
act:call_key(value, var_path?, desc?) -> string | 「呼ばない」印
| パラメータ | 型 | 説明 |
value | any | 動的ターゲットの式の値 |
var_path | string または nil | 式が変数参照 1 つのときの変数の場所("var.x"・"save.x"・"args[1]")。警告ログと失敗表記に使う |
desc | string または nil | 式が関数呼び出し 1 つのときの表記("@名前()"・"@*名前()"・"@$var.名前()")。警告ログと失敗表記に使う |
- 空でない文字列(文字列
"nil" を含む)はそのまま、数値は tostring(value) を検索キーとして返す。
- それ以外の値(
nil・空文字列・真偽値・表など)では、失敗を報告し、「呼ばない」印を返す。印を受け取った act:call・act:call_restore は、検索せずに nil を返す。印は外から作れない値で、文字列 "nil" とも false とも区別される。
- 警告ログは、
var_path があれば WORD.dynamic_key(value, var_path, "act:call") の警告(WORD.dynamic_key)、無ければ act:call - key is not a string or number: operand='@名前()', value=nil の形である。operand= は desc があるときだけ付き、value= の表記は PASTA.num と同じである。値が nil で var_path も desc も無いとき(手書きの Lua から nil を渡した場合。DSL の動的ターゲットでは起きない)は警告しない。
desc があり var_path が無く、式の関数呼び出しがすでに失敗を報告していた(関数が見つからない・動的参照の値が名前にならない)ときは、重ねて報告せずに「呼ばない」印を返す。
- 失敗表記の文言は 実行時の失敗の出力 のとおりである。
- DSL の動的ターゲットは、
>$x が act:call_key(var.x, "var.x")、>@f() が act:call_key(act:expr_fn("f"), nil, "@f()")、それ以外の式が act:call_key(式) になる。
act:restore_scene(scene, ...) -> ...
- 実行中のシーンを
scene(シーンテーブルまたは nil)にし、2 番目以降の引数をそのまま返す。
word・expr_fn・expr_fn_var・global_fn とアクタープロキシの word・expr_fn・expr_fn_var が、関数から戻った後に実行中のシーンを戻すのに使う(call_restore は自分で戻す)。
init_scene と違い、最後に init_scene を呼んだグローバルシーンの記録は変えない。
init_scene が控えたシーンの名前は、グローバルシーンの名前だけを、scene で init_scene を呼んだときに控えた名前に戻し、ローカルシーンの名前と行の対応は空にする。呼ぶ前のローカルシーンは分からないため、止まるエラーの表記は *天気 のようにグローバルシーンまでになるが、別のシーンの名前は出さない。
act:failure(text, warning?) -> nil
- 辞書の失敗と同じ出口から失敗を報告する。
【text】 を失敗表記として積み、warning があれば警告ログに出す(nil ならログには出さない)。text は他の失敗表記と同じくエスケープされ、表記は [logging] balloon_warning に従う。
- 表記の出る位置と形は 実行時の失敗の出力の act:failure を参照する。
call_restore・call_key・restore_scene・failure は act のメソッドのため、ほかの act のメソッドと同じく、@名前(…)・@名前・>名前 の検索の 3 段目で名前から見つかる(検索と呼び出し)。
アクション行のアクターと @*名前(…) の生成コードは、次のメソッドを呼ぶ。どちらも、アクターや関数が無いときに Lua のエラーにせず、失敗を報告して続ける(実行時の失敗の出力)。手書きの Lua からも呼べる。
| メソッド | 内容 | 戻り値 |
act:actor_proxy(name) | アクター name のアクタープロキシを得る | アクタープロキシ(常に nil でない) |
act:global_fn(name, ...) | GLOBAL の関数 name を呼ぶ | 関数の戻り値、または nil |
- 2 つの名前は act のメソッドのため、ほかの act のメソッド(
talk・wait など)と同じ制限を受ける。手書き Lua の act.actor_proxy・act.global_fn は、同じ名前のアクターがいてもプロキシにならない(アクタープロキシ)。また、@名前(…)・@名前 の検索の 3 段目で見つかるため、GLOBAL に同じ名前の関数があっても @名前(…) では届かない(@*名前(…) では届く)。1・2 段目(実行中のシーンのシーンテーブル、ローカル単語・ローカルシーン)にある同じ名前は、3 段目より先に見つかる(検索と呼び出し)。
- 式の算術と連結の生成コードが被演算子に使う関数は、act のメソッドではなく
pasta モジュールの関数である(PASTA)。
act:actor_proxy(name) -> ActorProxy
act.actors に name があれば、act.名前 と同じアクタープロキシを返す。ログもトークンも出さない。名前を文字列で受け取るため、メソッド名・フィールド名と同じ名前のアクターでもプロキシになる。
- 無ければ、名前だけを持つその場限りのアクターのプロキシを返す。このアクターは登録されず、
act.actors にも立ち位置にも書かれない(立ち位置が無いため、スポット 0 で話す)。直前の話者(直前に積まれた talk・sakura_script・目印)が同じ名前のその場限りのアクターでなければ、警告ログ act:actor_proxy - unregistered actor: name='名前' とともに未登録アクターの失敗を報告し、目印をそのアクターの発言として積む。
- アクション行の生成コードは、アクターをこの形で参照する。DSL での見え方は 登録していないアクター名 を参照する。
act:global_fn(name, ...) -> any
GLOBAL[name] が関数なら 関数(act, ...) を呼び、その戻り値をすべて返す。関数の中で起きたエラーは、そのまま伝わる。
- 無いとき、関数でない値のときは、警告ログ
act:global_fn - function not found: key='名前' とともに関数が見つからない失敗を報告して nil を返す。
- 5 段の検索は行わず、
GLOBAL だけを見る。
- 関数から戻った後、実行中のシーンを呼ぶ前のシーンに戻す(検索と呼び出し)。
- DSL の
@*名前(…) は act:global_fn("名前", …) になる。アクション行の中でも、関数の第 1 引数は act である(関数スコープの展開先)。
act:yield() -> act
- ここまでに積んだトークンをさくらスクリプトに組み立て、それを応答としてシーンのコルーチンを中断する。積んだトークンは空に戻る。
- 積んだトークンが無いときは何も返さずに中断し、ランタイムはすぐに再開する。
- 続きは、次の自然なおしゃべり(仮想ディスパッチャが起こす OnTalk)の機会に再開される。DSL の
>yield・>チェイントーク と同じ動作である(チェイントーク)。
- シーン関数が終わると、残っているトークンは自動で組み立てられて出力される。そのため、シーン関数の最後に
yield は要らない。最後に yield を置くと、シーンは中断した状態で残り、次の自然なおしゃべりの機会に再開されて何も出力せずに終わる。
- シーンのコルーチンの外(
REG のハンドラの本体など)で呼ぶと、Lua のエラーになる。
function SCENE.物語(act)
local save, var = act:init_scene(SCENE)
act:talk(act.さくら.actor, "最初のセリフ")
act:yield() -- ここまでを出力して中断する
act:talk(act.さくら.actor, "次のセリフ")
-- 残りはシーンの終了時に出力される
end
act:choice(target, display?) -> act
| パラメータ | 型 | 説明 |
target | string | 選択肢の ID(行き先のシーン名) |
display | string または nil | 表示テキスト。nil なら target を表示する |
\![*]\q[表示テキスト,ID,グローバルシーン名] を出力する選択肢を積む。グローバルシーン名は、choice を呼んだ時点の実行中のシーンのグローバルシーンの登録名(メイン_1 の形)で、選択肢を出したグローバルシーンを表す。表示テキスト・ID・グローバルシーン名の中の \・]・, は \ でエスケープされる。
- 実行中のシーンが無いとき(シーンの外で呼んだとき)と、ID が
On または script: で始まるときは、3 番目の引数を付けずに \![*]\q[表示テキスト,ID] を出力する。
- 選ばれると、OnChoiceSelectEx の既定の処理が、ID と前方一致するローカルシーンを、選択肢を出したグローバルシーンの配下から探して実行する。見つからなければ、ID と前方一致するグローバルシーンを探す(OnChoiceSelectEx)。
- 表示制御と同じく、1 回の出力の中で
talk・sakura_script より前に積むと、どのアクターにも結び付かず、積んだ位置にそのまま出力される(表示制御)。
- DSL の選択肢行
@?行き先 も同じ選択肢を出力する(選択肢行)。
- 選択肢は、選択肢行で出した選択肢と同じ配置で、バルーンの 1 行に 1 つずつ表示される。選択肢の直前と、選択肢の後に続く台詞の直前に出力される改行の条件と幅は、選択肢行 を参照する。
- どのアクターにも結び付かずに出力される選択肢は、配置の判定では、スポット 0 のバルーンに表示したものとして数える。続けて積んだ選択肢の前の改行と、その後にスポット 0 のアクターが出す台詞の前の改行は、選択肢の後に出すものとして決まる。
- 配置の判定でバルーンの消去に数えるのは、
act:clear() と、talk・sakura_script に渡したテキストの中の引数の無い \c である。raw_script に渡したテキストの中の \c は数えない。act:clear_spot() を呼ぶと、すべてのバルーンを、まだ何も表示していないものとして数え直す。
act:talk(act.さくら.actor, "どうする?")
act:choice("挨拶", "挨拶する")
act:choice("自己紹介") -- 表示テキストは「自己紹介」
act:choice_timeout(seconds?) -> act
- 選択肢のタイムアウトを設定するタグ
\![set,choicetimeout,ミリ秒] を積む。ミリ秒は seconds の 1000 倍を切り捨てた整数で、seconds が nil なら 0(タイムアウトなし)である。
choice と同じく、1 回の出力の中で talk・sakura_script より前に積むと、どのアクターにも結び付かず、積んだ位置にそのまま出力される(表示制御)。
act:choice_timeout(30) -- 30 秒でタイムアウト
act:choice_timeout() -- タイムアウトなし
pasta.word は、Lua から単語を定義するモジュールである。DSL の単語定義と同じ辞書に登録される。
local WORD = require("pasta.word")
| 関数 | 登録先 | 探されるとき |
WORD.create_global(key) | グローバル単語 | 単語参照の 5 段目 |
WORD.create_local(scene_name, key) | scene_name のローカル単語 | 実行中のシーンが scene_name のときの単語参照の 2 段目 |
WORD.create_actor(actor_name, key) | actor_name のアクター単語 | そのアクターを付けた単語参照(アクタースコープと単語参照の統合) |
WORD.create_word(key) | グローバル単語(create_global の別名) | 単語参照の 5 段目 |
require("pasta").create_word(key) も WORD.create_global(key) と同じである。
scene_name には、グローバルシーンの登録名(シーン名の照合用の名前の後ろに _ と、照合用の名前が同じシーンの通し番号を付けた名前。1 つ目の *メイン なら "メイン_1"、1 つ目の *挨拶・朝 なら "挨拶_朝_1"。別名で宣言したシーンは置き換え後の名前から作られ、既定の別名表のもとで *OnTalk の無いゴーストの 1 つ目の *会話 なら "OnTalk_1")を渡す(search_scene)。
- どの関数もビルダーを返す。値はビルダーの
entry で足す。
- 単語の検索対象は、シーン辞書の読み込みの最後に確定する(利用できる時期)。
main.lua や Lua ブロックのトップレベルで登録した単語は検索できる。シーン関数やイベントハンドラの実行中に登録した単語は、検索の対象にならない。
builder:entry(...) -> builder
- 引数の値(文字列)が、それぞれ単語の候補になる。引数が 0 個なら何もしない。
- ビルダー自身を返すため、続けて呼べる。
- 同じキーのビルダーを何度作っても、同じキーに候補が足されていく。DSL で定義した同じキーの単語とも候補が合わさる。
- 候補は前方一致で探され、シャッフル&順次消費で選ばれる(前方一致検索・シャッフル&順次消費)。
WORD.create_global("好きな食べ物")
:entry("ラーメン", "カレー")
:entry("寿司")
:entry("焼肉", "パスタ")
local WORD = require("pasta.word")
-- ループによる一括投入
local foods = { "ラーメン", "カレー", "寿司", "焼肉", "パスタ" }
local builder = WORD.create_global("好きな食べ物")
for _, food in ipairs(foods) do
builder:entry(food)
end
-- ローカル単語の投入(1 つ目の *メイン のローカル単語)
WORD.create_local("メイン_1", "返事")
:entry("はい", "ええ")
:entry("そうね")
-- アクター単語の投入
WORD.create_actor("さくら", "一人称")
:entry("わたし")
:entry("あたし")
WORD.dynamic_key(value, var_path, via, act?) -> string | nil
動的参照の変数の値を、単語名・関数名に直す補助関数である。act:word(var_path を渡したとき)と act:expr_fn_var が使う。act:call_key(var_path を渡したとき)は、値を検索キーにできないときの報告にだけ使う。
value | 戻り値 |
| 空でない文字列 | その文字列 |
| 数値 | tostring(value)(3 なら "3") |
nil・空文字列・それ以外の型 | nil(名前にならない値の失敗を報告する) |
- 文字列は DSL として読み直さない。
__tostring を持つ表も文字列にしない。
- 警告ログは
{via} - undefined variable: '{var_path}'(nil)・{via} - empty variable: '{var_path}'(空文字列)・{via} - unsupported value type: '{var_path}' ({型名})(それ以外の型)である。ランタイムは via に "act:word"・"act:expr_fn"・"act:call"・"proxy:word"・"proxy:expr_fn" を渡す。
act を渡すと、失敗表記をその act に積む。省略すると警告ログだけを出し、失敗表記は出さない(実行時の失敗の出力)。ランタイムは実行中の act を渡す。
WORD.resolve_value(value, act) -> any
検索で得た値を単語の値に直す補助関数である。value が nil なら nil、関数なら value(act) の戻り値、表なら最初の要素(空の表なら nil)、それ以外なら tostring(value) を返す。
pasta.global は、ユーザー定義のグローバル関数を登録するテーブルを返すモジュールである。
local GLOBAL = require("pasta.global")
GLOBAL.時報 = function(act)
return os.date("%H") .. "時です"
end
-- DSL からの呼び出し: @*時報()
-- 変数への代入: $result=@*時報()
-- 式文(戻り値不要): $=@*時報()
戻り値を使わない呼び出し $=式 は 式文 で扱う。
- DSL の
@*名前(引数…) は act:global_fn("名前", 引数…) になり、GLOBAL の関数を (act, 引数…) で呼ぶ。5 段の検索は行わない。未定義の名前・関数でない値のときは、失敗を報告して nil になる(global_fn)。アクション行で呼んだ場合は戻り値が出力され(nil なら何も出力しない)、変数代入の右辺なら戻り値が代入される(関数スコープの展開先)。
GLOBAL は 5 段の検索の 4 段目(完全一致)でもある。@名前(…)(ローカル呼び出し)・@名前(単語参照)・>名前(Call)は、1〜3 段目に無ければ GLOBAL の値を見つける(検索と呼び出し)。関数は (act, 引数…) で呼ばれる(アクション行の中の単語参照と関数呼び出しでも第 1 引数は act である。関数スコープの展開先)。関数以外の値は、単語参照では文字列として出力される。
- DSL の
@名前() は GLOBAL の関数を直接は呼ばない。グローバル関数を確実に呼ぶには * を付けた @*名前() を使う。
- 関数は、呼ばれる前であればいつ登録してもよい(
main.lua・Lua ブロックなど)。
ランタイムはあらかじめ次の名前を登録している。
| 名前 | 内容 |
GLOBAL.yield | act:yield() を呼ぶ |
GLOBAL["チェイントーク"] | GLOBAL.yield と同じ関数。>チェイントーク が呼ぶ(チェイントーク) |
GLOBAL.close_ghost | close_ghost(act, ms)。ms が 1 以上の数値なら act:wait(ms) を積み、ゴーストを終了させる \- を raw_script で積む |
GLOBAL["ゴースト終了"] | GLOBAL.close_ghost と同じ関数。>ゴースト終了 が呼ぶ(ゴースト終了) |
GLOBAL.pause_auto_talk | pause_auto_talk(act)。ランダムトーク・時報などの自動トークを止める。出力は積まない |
GLOBAL["自動トーク停止"] | GLOBAL.pause_auto_talk と同じ関数。>自動トーク停止 が呼ぶ(自動トーク停止・自動トーク再開) |
GLOBAL.resume_auto_talk | resume_auto_talk(act)。止めていれば再開し、仮想ディスパッチャの時計を決め直す(自動トークを止めている間)。出力は積まない |
GLOBAL["自動トーク再開"] | GLOBAL.resume_auto_talk と同じ関数。>自動トーク再開 が呼ぶ |
GLOBAL.close_ghost・GLOBAL["ゴースト終了"]・GLOBAL.pause_auto_talk・GLOBAL["自動トーク停止"]・GLOBAL.resume_auto_talk・GLOBAL["自動トーク再開"] は、main.lua の後に読み込まれる pasta.shiori.entry が登録する。main.lua でこれらの名前に代入しても上書きされる(読み込み順は 起動シーケンスとモジュール解決)。
pasta.save は、セッションをまたいで保持される永続化データのテーブルを返すモジュールである。
シーン関数では init_scene の戻り値の save を使う。シーン関数でない関数では act.save を使う。
function SCENE.カウント(act)
local save, var = act:init_scene(SCENE)
save.count = (save.count or 0) + 1 -- セッションをまたいで保持される
end
local save = require("pasta.save")
save.talk_count = (save.talk_count or 0) + 1
require("pasta.save") が返す表は、act.save・init_scene の戻り値の save と同じ表である。ACT を受け取らない場所(main.lua のトップレベルなど)から永続化データを読み書きするときに使う。
pasta モジュール(require "pasta")の関数のうち、式の算術と連結の生成コードが使う 2 つを扱う。DSL の式の算術と連結は、演算ごとに Lua の演算子を括弧で囲んだ (左 演算子 右) になり、被演算子はこの 2 つの関数で数値・文字列にしてから演算子に渡される(DSL と Lua の対応表)。
- 2 つとも act のメソッドではない(
self を取らない)。そのため、@名前(…)・@名前 の検索の 3 段目では見つからない(検索と呼び出し)。
- 被演算子の表に
__add・__concat・__tostring などのメタメソッドがあっても呼ばない。
- Lua のエラーを投げない。手書きの Lua からも呼べる。
PASTA.num(op, v, desc?) -> number
| パラメータ | 型 | 説明 |
op | string | 警告ログに出す演算子("+"・"-"・"*"・"/"・"%") |
v | any | 被演算子の値 |
desc | string または nil | 警告ログと失敗表記に出す被演算子の説明("var.x"・"@f()" など) |
| 値 | 戻り値 | 警告ログ |
| 数値 | そのまま | なし |
文字列で、tonumber が数値を返すもの("12"・"1.5" など) | その数値 | なし |
nil | 0 | なし |
| それ以外(数字でない文字列・空文字列・全角数字だけの文字列・真偽値・表・関数) | 0 | 1 行(失敗表記も出す) |
- 警告ログは
act:arith - operand is not a number: op='*', operand='var.x', value='abc' (string) の形である。接頭辞の act:arith は算術の警告であることを表す(関数の名前ではない)。operand= は desc があるときだけ付く。value= は値の種類を表し、'abc' (string)・true (boolean)、それ以外は (table) のように型名だけになる(表の __tostring は呼ばない)。
- 警告ログを出すときは、数にできない値の失敗表記を実行中の act に積む(実行中の act の制限)。
op は警告ログに出すだけで、演算はしない。演算は生成コードの Lua の演算子が行う。
- DSL の式の算術では、数値のリテラルと算術の演算の結果を除く被演算子が
PASTA.num を通る(算術の評価)。
PASTA.str(v, desc?) -> string
| パラメータ | 型 | 説明 |
v | any | 被演算子の値 |
desc | string または nil | 警告ログと失敗表記に出す被演算子の説明("var.x"・"@f()" など) |
| 値 | 戻り値 | 警告ログ |
| 文字列 | そのまま | なし |
| 数値 | tostring(v)(アクション行で表示したときと同じ表記) | なし |
nil | "" | なし |
| それ以外(真偽値・表・関数) | "" | 1 行(失敗表記も出す) |
- 警告ログは
act:concat - operand is not a string or number: op='&', operand='@真()', value=true (boolean) の形である。接頭辞の act:concat は連結の警告であることを表す。op は DSL で全角・半角のどちらを書いても '&' である。operand= は desc があるときだけ付き、value= の表記は PASTA.num と同じである。
- 警告ログを出すときは、文字列にできない値の失敗表記を実行中の act に積む(実行中の act の制限)。
- DSL の式の連結では、文字列のリテラルと連結の演算の結果を除く被演算子(数値のリテラルを含む)が
PASTA.str を通る(連結の評価)。
local PASTA = require "pasta"
PASTA.num("+", "12") -- 12
PASTA.num("+", nil, "var.x") -- 0(警告しない)
PASTA.num("*", "abc", "var.x") -- 0(警告を 1 行出し、失敗表記を積む)
PASTA.str(3) -- "3"
PASTA.str(nil, "var.x") -- ""(警告しない)
PASTA.str(true, "@真()") -- ""(警告を 1 行出し、失敗表記を積む)
Claudia
道具の一覧は手に入りましたわね。あとは使いこなすだけ――さあ、あなたのゴーストに存分に働いてもらいましょう!
Anthony
お嬢様、一度に全部を働かせては、ゴーストも息切れいたします。