コンテンツにスキップ

ACP 版との違い

Unicode 版(Mc2XX)は、ACP 版(Mc1XX、Shift_JIS ベース)から内部の文字列を Unicode にしたものです。

TL;DR

satori.dll を置き換えるだけで、今までの辞書とセーブデータはそのまま動きます。 辞書の文字コードを変える必要も、書き直す必要もありません。開発チームの側でも、ほとんどの場合は何も考えずに置き換えています。

気にするのは、次のような場合だけです。

  • 一度 Unicode 版で動かすと、セーブデータは UTF-8 で保存されます。ACP 版に戻すと文字化けすることがあります(戻す予定があるなら、置き換える前にバックアップを)
  • (バイト値、n) の返す文字、sprintf の %s の幅、括弧展開サイズ制限の数え方が変わります。これらを使っている辞書だけ、下の表で確認してください

UTF-8 の辞書も読めるので、新しく書く辞書は UTF-8 でも構いません。

多くの辞書はそのまま動きますが、次の違いがあります。

互換のない点・注意点

項目 ACP 版 Unicode 版
辞書の文字コード Shift_JIS Shift_JIS のほか UTF-8 も読める(自動判定)
セーブデータ Shift_JIS 常に UTF-8 で保存。読み込みは自動判定
自動ウェイト Shift_JIS のバイト数で数える(全角 1 文字が 2) 半角換算で数える(全角 1 文字が 2、半角 1 文字が 1)。ACP 版と同じ長さ(Mc202-1以降。それ以前は文字数で数えており、日本語では約半分でした)
calc の文字列の長さ比較 バイト数 文字数
(バイト値、n) 1 バイトの文字を返す n を Unicode のコードポイントとして 1 文字を返す
SHIORI の通信 Shift_JIS リクエストの Charset に従う
SAORI・SSTP・ssu との通信 ACP UTF-8(GET Version に Charset を返さない SAORI には Shift_JIS。Mc203-2以降)
括弧展開サイズ制限 バイト数 文字数(実質約 2 倍)
サロゲートペア 対象外 1 文字として扱う
コミュニケートの点数 バイト数に基づく 文字数に基づく(一致した語が全角のみなら同じ点数)
sprintf の %s の幅 バイト数 半角換算(全角は 2)で数える

引き継ぎに関する注意

  • Unicode 版で保存した UTF-8 のセーブデータは、ACP 版に戻して読むと文字化けする可能性があります。
  • 暗号化(.sat)の辞書やセーブデータは、Unicode 版でも読めます。書き出す暗号化セーブデータは、UTF-8 のバイト列を暗号化したものです。

判定が変わるかもしれない点

  • UTF-8 の辞書では、波ダッシュ(U+301C)や全角チルダ(U+FF5E)、マイナスの記号が Shift_JIS 由来の文字と別の文字になります。里々は両方を受け付けます(文字コード)。
  • 内部の特殊表現に、Unicode の私用領域(U+E0FF ほか)を使います。辞書の本文にこれらを含めないでください。

追加された機能

ACP 版にはなかった機能です。

文・選択肢・イベント

  • 選択肢に引数を付けられます。_ラベル【タブ】ID【タブ】引数… が \q[ラベル,ID,引数…] になり、選ばれると ID の文が (A0)〜付きで実行されます(引数を渡す)。
  • タイマが発動したときに *名前 の文がなければ、*OnSatoriTimer を実行します。(A0) がタイマの名前、(A1) が遅れた秒数です(OnSatoriTimer)。

内蔵関数・ssu

システム変数

  • $呼び出し総数制限(既定 100000)。呼び出しと繰り返しの合計回数の上限で、超えるとログに 呼び出し総数超過 と出ます。深さを制限する $呼び出し回数制限 では止められなかった、分岐する再帰や空の長い繰り返しを止めます。
  • 括弧の入れ子の深さにも上限(1000 段)があります(括弧の入れ子の深さ)。calc と calc_float の式のカッコは 200 段までです。

ログ

  • YAYA と同じ Set_loghandler エクスポートに対応しました。コールバックが設定されている間は、ログをウィンドウに送らず、YAYA と同じ形でコールバックに渡します(ログ)。

直された不具合

ACP 版や、Unicode 版の初期のものから直っている点を、里々の使い手に関わる順にまとめます。

書いたとおりに動かなかったもの

  • $システム変数=式 で、システム変数に計算前の値が渡っていました。$名前タイマ=3*60 が 3 秒のタイマになるなど、値を数値として読むシステム変数すべてに当たっていました。今は計算結果が整数ならその値が渡ります(代入)。
  • 同じ ID の選択肢が 1 つの応答に複数あると、選択番号 が 2 つめ以降で同じ番号になっていました(選択の記録)。
  • (直前の選択肢名) が常に空でした。選ばれた選択肢の ID を返します。
  • SAORI や内蔵関数(set、nop など)の引数に (R0) の値などから (…) が入ってくると、中身がもう一度展開され、単語の選択や set などの副作用が余計に起きていました。
  • 名前だけ登録されていて使えなかった関数があります。load_saori は not found になり、文の数 は常に空文字列でした((文「名前」の数) と同じ値を返します)。
  • vncall は、呼び出し先が見つからないと最後の引数の展開結果を返していました。今は空文字列です。
  • (文「名前」の他) (単語群「名前」の他) のように表にない書き方、表にない (count名前)、n のない (FMO項目名) が、見つからない名前ではなく空文字列になっていました(状態・存在確認)。
  • 文中の % タグで、%month の直後に day が続くと %day になるなど、一致したあとも続きを別のタグとして読んでいました(%selfname2 は先に判定します)。
  • 自動アンカー:アンカーが隣り合っていると、2 つめがアンカーになりませんでした。
  • さくらスクリプトが \p[2] だけのトークが「空」と判定されず、何も喋らないはずのイベントで \p[2]\e を返していました。さくらスクリプトの [ に ] がない場合の不具合も直っています。
  • コミュニケートの検索で、「 だけの名前の文が二重に候補に入っていました。採用条件の異なる同名の文が複数あると、候補が条件の数だけ重複して、選ばれる確率が偏っていました。
  • ) の直前の処理で 1 文字多く削っていた箇所があります。
  • 自動ウェイト:全角 1 文字を 1 として数えていたため、日本語の自動ウェイトが ACP 版の約半分になっていました(Mc201-1〜Mc201-11)。ACP 版と同じ半角換算(全角 2、半角 1)に戻しました(Mc202-1以降)。
  • 重複回避:単語の追加 追加単語の削除 をすると、そのあと重複回避の記録(使用済みかどうか、順番の位置)が消えて、同じ単語が続けて選ばれたり、順番が最初に戻ったりすることがありました。今は残った候補の記録が引き継がれます(Mc202-2以降)。
  • 重複回避:正順 逆順 で、直前に選んだ候補が採用条件で外れると、辞書の定義順や環境によって、最初に戻ることがありました。今は順番どおりの次の候補から続けます(Mc202-2以降)。
  • 変数の列挙:接頭辞を空にすると、すべての変数ではなく空文字列が返っていました。今はすべての変数を返します(Mc203-1以降。issue #1)。
  • なでられ:Windows 以外のビルド(POSIX)では Status ヘッダを見ていなかったため、喋っている最中などにもなでられに反応していました。Windows と同じく反応しないようにしました(Mc203-4以降)。

計算(calc・式)

  • 数値が 32 ビットで、2147483647 を超えるとあふれていました。今は 64 ビットです。最小値を -1 で割る・その余りを求める式で異常終了するおそれもありましたが、直っています(商は最小値、余りは 0)。
  • ^ がビット XOR になっていました。今はべき乗です。
  • =~ !~ が常に 0 でした。今は部分文字列の判定です。
  • (time_t) が 2038 年以降に負の数になっていました。
  • 文字列*数値 に巨大な数値を書くとメモリを使い果たしていました(4194304 文字までです)。

ssu

  • sprintf:%i が 8 進になっていました(10 進にしました)。%.3s のような文字列の精度が効いていませんでした。末尾の % や %z のような正しくない指定で、% が消えて値も 1 つ使われていました(% をそのまま残し、値は使いません)。幅は 4096、精度は 512 までです。
  • calc_float:結果が 128 文字を超えると異常終了し、24 桁を超える結果は文字化けや空文字列になっていました。
  • split_string:最大個数に達したとき、2 文字以上の区切りの 2 文字目以降が残っていました。
  • is_digit:第 2 引数が int 以外でも整数モードになっていました。
  • substr:開始位置が 1 以上で長さが 2147483647 のような大きな数だと異常終了していました。
  • join:引数が区切りだけのとき、範囲外を読んでいました。
  • reverse:長い文字列(20 万文字)で数十秒止まっていました。
  • mkdir と lsimg が、外部からのイベント(SecurityLevel: external)でも実行できていました。local のときだけ実行します(ssu.dll を単体で使うときも、リクエストの SecurityLevel に従います)。lsimg は Windows 以外では常に 0 を返していましたが、POSIX でも動作するようにしました(Mc203-4以降)。

異常終了・無限ループ・止まる問題

  • 内部で例外(メモリ不足・範囲外など)が起きても、ベースウェアごと異常終了しなくなりました。そのリクエストは 500 で終わります(エラーメッセージ)。
  • $R… $S… に巨大な番号($R1000000000=1 など)を代入すると異常終了していました(参照値)。
  • 辞書の拡張子・接頭辞を変えていて、名前が拡張子より短いファイル(dic_x.txt など)がフォルダにあると、読み込みで異常終了していました($辞書拡張子)。辞書フォルダの列挙に失敗したときの不具合も直っています。
  • ≧ のコミュニケート検索で、検索語が 「 で終わると異常終了していました。
  • 括弧の入れ子が極端に深いと、スタックを使い果たして異常終了していました(SAORI の返り値は再展開されるので、外部の文字列でも起こり得ました)。
  • 辞書や入力に内部用の私用領域の文字(U+E0FF の後に U+E0FD / U+E0FC)があると、無限ループになっていました。
  • times for while loop:結果が $括弧展開サイズ制限を超えたら打ち切ります。for と loop は、終了値が 2147483647 だと終わらないことがありました。
  • 展開中に 単語の追加 などで単語群が変わっても、選んだ単語の展開が壊れません。$変数=式 の代入先も、式の展開中に変数や R・S が増減しても壊れません。
  • split_to:接頭辞の数 の変数に巨大な値があると、何十億回も回っていました(添字の上限は 65536 です)。
  • Reference の足りないリクエスト(OnSecondChange など)や、長押しの直後に別のクリックをしたときの ○○ホールド の処理で、範囲外を読んでいました。足りない分は空として扱います。

速度

  • 単語群・文を選ぶ時間が、要素の数に比例して長くなっていました。条件式のない群では、要素が変わるまで候補を作り直しません(3000 語の群から選ぶ時間が、約 280μs から約 12μs になりました)。
  • カッコの展開やトークの変換が、長いトークほど文字数の割合以上に遅くなっていました。

SAORI・ログ・ツール

  • 華和梨の SAORI モード(kawari.dll)のように、Charset ヘッダを見ずに Shift_JIS として読む SAORI へも UTF-8 で送っていたため、日本語を含む呼び出し名や引数が通らず、結果が返りませんでした(Mc201-1〜Mc203-1)。GET Version の応答に Charset がない SAORI には、ACP 版と同じく Shift_JIS で送ります(Mc203-2以降。SAORI の通信)。
  • YAYA as SAORI(yaya.dll)で古い ayasaori.aym を使うと、最初の呼び出しの引数や結果だけが文字化けしていました。GET Version の応答に Charset がない SAORI には、直後に何もしない EXECUTE を 1 回送って読み捨てます(SAORI の通信)。
  • SAORI Basic(コンソールアプリ):出力が 4KB を超えると 10 秒待たされたり、出力し続ける相手だとタイムアウト後も戻れなかったりしました。出力を読みながら待ち、タイムアウトした相手は終了させます(1 回に読む量と総量 16MB に上限があります)。
  • tama(tamac)などへのエラーログ([ERROR] の行)が、遅れたり、つながったり、欠けたりしていました。calc の失敗などの実行時エラーが [ERROR] として届かず、応答に ErrorLevel: critical も付かなかった点も直っています。終了の通知(E_END)の値も YAYA に合わせました(5 → 6)。
  • 内蔵の ssu を使っているとき、SAORI のエラーログと ErrorDescription には存在しない saori\ssu.dll のパスではなく (internal ssu) と出ます(SAORI)。
  • さとりて:出力が 4095 文字を超えると途中で切れ、壊れた文字列が表示されることがありました。