【伺か】ココがわからなかったよ!里々君!

ukagaka

初めに。

この記事は2023年 伺か アドベントカレンダー 12/3の記事です。
前日は ななっちさんの自作のゴースト開発ツール・サービスの1年間のアップデートをご紹介 です。

これを書いている人はどんな人?

yayaしか書いたことがない人
SSPが吐き出すOnXXXイベントはある程度把握している。
プログラム言語は必要なときに必要な言語を軽く触るだけの人。

結論から言って?

ココがわからなかった。と名指してずらりと並べたかったが、何もかも書き方が違って全部わからなかった。タイトル詐欺です。

辞書とジャンプを駆使するだけならとっても使いやすい栞だということはわかったが、
複雑な処理は未知の地雷原を突っ切るような開発体験であり、どこにハマりポイントがあるのか未だにわからない。
この記事は、これはこうすれば書けるようになるとかではなく、
ニューゲームしたマインスイーパーに、ちょっと旗を立てておいた感じの記事です。

初めに

里々を最新版にしましょう。
今を生きる伺かは化石ではありません。
先月もアップデートされています。
でもバグもあったよ(はーと)修正もされたよ(はーと)
Releases · ukatech/satoriya-shiori · GitHub
サンプルゴーストの里々が古すぎて一部の関数が使えなかったりした。(一敗)

動作を確認してみる。

コメントアウト

プログラムを書くときは、メモの書き方から覚える派です。

#里々辞書では全角の#によってコメントアウトする。

コメントアウトは我々が思っているような挙動ではない。
驚くべきことに、コメントアウトした行は改行文字に変換されるのである。
comment.png

コメントについてはこちらにあるが、トークの途中でなければ改行されないようである。
特殊記号一覧 – 里々Wiki

イベントの動き

里々は同じ名前のイベント名を使用できる。
下記の場合、キー入力の度にランダムでいずれかが呼ばれる。

#key入力を検知するイベント
*OnKeyPress
A

*OnKeyPress 
B

イベントを呼び出す。

はジャンプと呼ばれているようだ。

*OnKeyPress
>呼び出し名

*呼び出し名
:呼ばれた

呼び出すイベントに条件を付ける。

#イベント名と式の間にはタブ文字が入る。エディタによってはスペースに置き換えられたりする。
#Ctrl + V の後に Tab を入力するとタブ文字を出せたりする。
>イベント名  条件 == 条件

キー入力を検知するイベントOnKeyPress。
OnKeyPressには(R0)に 入力されたアルファベットが入る。

*OnKeyPress
>Key_A  (R0)==a
>Key_B  (R0)==b
:それ以外が呼ばれた

*Key_A
A
*Key_B
B

発言はイベントをつなげることができる。

のイベントからジャンプした場合、末尾に改行が付く。
この場合、aaa\nbbbaaa\ncccのどちらかが発生する。

*OnKeyPress
:aaa
>OnKeyPressEX

*OnKeyPressEX
:bbb

*OnKeyPressEX
:ccc

変数の動き

変数に値をセットする方法は三種類ある。

#$変数名=値
#この間はタブスペース。
#$変数名   値
#(set,変数名,値)

*OnKeyPress 
$X=AIUEO
$X  AIUEO
(set,X,AIUEO)

どちらも同じ動作をする。と思っていたが違うらしい。
困ったときの対処法 – 里々Wiki

  • =を使用した場合
    値に書き込んだモノに演算処理(足し算引き算等)を適応したのち、全角で代入される。
  • タブ文字を使用した場合
    そのまま代入される。
  • set関数
    計算結果を半角で代入。
    無題.png

変数の保存

プログラムを書いているとx = 1といったスペースを開けたい人間であるが、それは里々では通用しない。
(二敗目)

*OnKeyPress 
:
#保存されるし(X)として呼び出すことが出来る。
$X=(X)+1
X = (X)

#保存されるが(Y)ではなく(Y )
$Y = 5
Y = (Y)
Y = (Y )

変数に初期値を設定する。

satori_conf.txtに下記のように記入すると、変数が存在しなかった時に書き換えてくれる。

$変数名=値

関数

(関数名,引数…..)とすることで処理を入れることができる。

:(erase,aiueo,o)
-> aiue

関数一覧はココを見ると良い。
関数一覧 – 里々Wiki

自分で関数を作る。

から始まるモノは関数として扱える。
(call,関数名,引数)とすることで呼ぶことができる。
R0にはもともとの呼び出し元のR0が入ったままである。
関数Aが受け取る引数はA0に格納されている。
これは関数名をOn~から始まるものにしても同じである。

関数Aに記載されているランダム行が結果として返るので、
下記のコードだとAAA or R0 or A0 という出力になる。

*OnKeyPress
(call,A,aiueo)

@A
AAA
(R0)
(A0)

A関数を下記のようにすると囲んである範囲が一行扱いとなり
AAA + R0 + A0 という出力になる。

@A
(
AAA
(R0)
(A0)
)

@についてもうちょっと掘り下げる。

正直これが一番わかりやすかった。
@は単語群としての使い方が一番ポピュラーっぽい。
引数を与えずにただ呼ぶだけなら(@の名前)と言った形で変数と同じように使用できる。
ありがたいのは末尾に改行等が付かないので下記のようにそのまま呼べる。

@One
あ
い
う
え
お

*OnKeyPress
>ずきゅんずきゅーん

*ずきゅんずきゅーん
:(One)んこ

でも同じように呼び出せるが、「あ」の後に改行が入ってしまう。

*One
あ

さらにもうちょっと掘り下げる。

@をうまく使う人はこのように使っているようだ。
()で囲えば一行扱いなので、下記だと(割と)読みやすくかけて全部実行してくれる。
初期化等はこのように書けばよいのだろう。

@One
(
set,A,1
)(
set,B,2
)(
set,C,3
)(
set,D,4
)

*OnKeyPress
:(One)ABCD変数を初期化した。
(A)
(B)
(C)
(D)

SAORIを使う。

(set,XXX,YYY)といった形でSAORIを呼び出せる。
SAORIが書けるならば、里々の辞書がややこしくなくなるだろう。
今回は例としてGitHub – ambergon/ukagakaSaori_CalcCalendarClangを使用した。
ディレクトリ構造はこのようにする。

├─satori.dll
└─Saori
    └─ukagakaSaori_CalcCalendar.dll

satori_confに登録する。

@SAORI
#呼び出し名,ディレクトリ/名前.dll
CalcCalendar,Saori/ukagakaSaori_CalcCalendar.dll

実際に呼び出す。
S0…はSAORIの返り値である。

:(CalcCalendar,(現在年),(現在月),(現在日),0,0,0)
現在年 : (現在年)
現在月 : (現在月)
現在日 : (現在日)
計算年 : (S0)
計算月 : (S1)
計算日 : (S2)

辞書ファイル

ファイル名

辞書ファイルはsatori.dllがあるフォルダにdicXXX.txtとして保存しておけば読み込んでくれる。
一部の名前は専用の挙動をする。

文字コードの話。

どの文字コードでも勝手に判定してくれるらしい。
判定には里々特有の全角記号を使用しているらしく、全角を5つほどつけておけば自動判別してくれる。

各ファイルごとに文字コードが違っても動作する。すっごいもやもやする。
が、後述するreplace.txtとreplace_after.txtは強制Shift-JIS指定である。(Mc169で変更できるようになった。)
(三敗目)

すべてを強制的にUTF-8を使用する。

文字コードについての愚痴を伺かユーザの隠れ里、うかどんでこぼした次の日、アップデートによりsatori_bootconf.txtを以下のようにすればShift-JISを淘汰できるようになった。
satori.dllを最新版Mc169-2に差し替えると使えるようになる。

# 辞書をUTF-8で読み込む。
is_utf8_dic,true

# replace/replace_afterをUTF-8で読み込む。
is_utf8_replace,true

# セーブデータをUTF-8で読み込む。
is_utf8_savedata,true

# characters.iniをUTF-8で読み込む。
is_utf8_charactersini,true

最新版Mc169-3で一行で全部UTF-8指定に出来るようになった。

is_utf8_all,true

里々が備える置換機能を確認する。

充実している。
ただし破壊的な機能であり、人の書いたコードをコピペしても動かなくなる可能性が高い。

  • replace.txt
    辞書が読み込まれる前に置換される。
  • replace_after.txt
    実際にSSPに渡される前に置換される。
  • OnTranslateイベント
    文字列がバルーンに表示される前に置換される。

全角文字と戦う(replace.txt)

下記のようにすることで、使い慣れた半角括弧で辞書に記入することができる。
読み込まれる前に全角に置き換えてくれるので、テキストエディタのパワーを存分に奮えるようになる。

#間はタブ文字で区切る
#置換前    置換後
#全角括弧を淘汰する。
(   (
)   )

おすすめはしないが、独自記法を導入するのも簡単である。

#Functionの末尾にスペースが一つある。
Function    *

下記のように書けるようになる。

Function Key_X
:X

replace_after.txtの挙動も見ておく。

これはSSPから出力される前に置換する機能であり、OnTranslateに近いものである。

#間はタブ文字で区切る
#置換前    置換後
。   \w9\w9\w9\w9\w9\w9\w9

が、これは発言時の修正ではないので
右クリック時のメニュー項目にも影響がある。

@inforootbutton.caption
情報の名称。

menu.png

OnTranslateを使用する。

SSPから渡されたテキストがバルーンに表示される前に処理される。
適切な遅延を自動化した。

*OnTranslate
$引数区切り追加    (バイト値、2)
$TransText  (R0)
$TransText  (replace(バイト値、2)(TransText)(バイト値、2)。(バイト値、2)。\w9\w9\w9)
$TransText  (replace(バイト値、2)(TransText)(バイト値、2)?(バイト値、2)?\w9\w9\w9)
(TransText)

キャラクター切り替えを楽にする。

characters.iniを設定することで、下記のような切り替えができるようになり、多人数を管理できるようになる。

#\0から5人まで表示してみた
A:テキスト0
B:テキスト1
C:テキスト2
D:テキスト3
E:テキスト4

satori.dllと同じディレクトリにcharacters.iniを設置した。

#\0
[0]
#一文字のみ
initial-letter=A
base-surface=0

#\1
[1]
initial-letter=B
base-surface=500

[2]
initial-letter=C
base-surface=1000

[3]
initial-letter=D
base-surface=1500

[4]
initial-letter=E
base-surface=2000

実際に表示されたテキスト

\0\s[0]\1\s[10]\p[2]\s[1000]\p[3]\s[1500]\p[4]\s[2000]\1\n\0テキスト0 \n\n[half]\1\_w[36]テキスト1\n\n[half]\p[2]\_w[33]テキスト2\n\n[half]\p[3]\_w[33]テキスト3\n\n[half]\p[4]\_w[33]テキスト4\e

iniファイルを用意すると、セーブデータに下記が自動で作られていた。

$デフォルトサーフェス0    0
$デフォルトサーフェス1    10
$デフォルトサーフェス2    1000
$デフォルトサーフェス3    1500
$デフォルトサーフェス4    2000

普通の人は さとりすと2 なる専用エディタを使う。

さとりすと
が、わたくしは宗教上の理由があるため紹介のみにとどめさせていただく。

でもVimでも多少は戦えるよ。(ささやかな抵抗)

我、テキストエディタVimを盲信するもの也。
下記のようにすることで、記号の入力時に全角に自動変更をするようにした。

"FileTypeの手動追加
autocmd BufRead,BufNewFile dic*.txt set filetype=satori
autocmd FileType satori inoremap ¥ /
autocmd FileType satori inoremap @ @
autocmd FileType satori inoremap ( (
autocmd FileType satori inoremap ) )
autocmd FileType satori inoremap * *
autocmd FileType satori inoremap $ $
autocmd FileType satori inoremap # #
autocmd FileType satori inoremap : :
autocmd FileType satori inoremap > >
autocmd FileType satori setl autoindent

大分いい加減だが、シンタックスハイライトをつけて見えるようにした。

"""ファイルタイプsatoriを作成しておく必要がある。
"行頭記号
"コメントアウト
syn region SatoriComment start="^#" end="$" oneline
hi def link SatoriComment Comment

"function
syn region SatoriFunction start="^*" end="$" oneline
hi def link SatoriFunction Type

"function
syn region SatoriAFunction start="^@" end="$" oneline
hi def link SatoriAFunction Type

"set var
syn region SatoriSetVar start="^$" end="=" oneline
hi def link SatoriSetVar PreProc
syn region SatoriSetVarTab start="^$" end=" " oneline
hi def link SatoriSetVarTab PreProc

"サクラスクリプト
"surface
syn match SatoriSurface "\\s\[.\{-}\]"
hi def link SatoriSurface Special

"特殊変数
"OnEvent
syn match SatoriEventVar "(R\d\{-})"
hi def link SatoriEventVar PreProc

"SAORI
syn match SatoriSaoriVar "(S\d\{-})"
hi def link SatoriSaoriVar Special

"Call var
syn match SatoriSaoriVar "(A\d\{-})"
hi def link SatoriSaoriVar SpecialKey

syntaxsatori.png

里々の挙動を監視するツールがある。

起動してどのようなイベントが呼ばれたか、変数の動き等を出力・保存ができるツール。
これまた別のバグに出くわした時(4敗目)にお世話になった。
ログを先人たちに見ていただいたところ原因が判明したので覚えておこう。
GitHub – nikolat/recv_net: 里々ログビューア

ここまでで。

どうにもWikiに書かれているものは一ページにおける情報量が多すぎる。
今回、サンプルゴーストや人のゴーストを見たり改変するのに最低限必要な範囲をまとめてみた。

何が為に里々を学んだ?

僕の目的は、面白い人たちの創作物を楽しむところにあり、
そんな人達にSAORIやプラグインを気持ちよく使ってもらうためには里々を理解する必要があった。

厚かましいことに今年は複数の枠を頂いているので、そこでそれらをお披露目させていただこうと思う。

明日の12/4は、りすなさんです。よろしくお願いします。
伺か Advent Calendar 2023 – Adventar

参考

レゴキチ/里々まとめ – SpecWiki
ファイル構成 – 里々Wiki