これらのキーワードがハイライトされています:今日

関数一覧

里々で使うことのできる関数の一覧。
Mc157-1からssu*1は里々内部に統合され不要になりました。

構文・コマンドループ条件分岐文字列操作文字列調査未分類



関数解説

calc / calc_float

(calc,計算式)
(calc_float,計算式)

計算式を計算した結果が返ります。
calcは小数点以下を無視(切り捨て?)して計算し、calc_floatは小数点以下も計算します。
ただしこのままだと整数で計算した結果を渡してしまうため、自動計算は無効にしておく必要があります。
ifswitchなどの引数は、暗黙のうちにこれを実行しているようです。

*
$SAORI引数の計算【タブ】無効
:計算するよー。5÷2は(calc_float,5÷2)っ!
$SAORI引数の計算【タブ】自動
 ↓ 
計算するよー。5÷2は2.5っ!

set

(set,変数名,値)

変数に値を代入します。値が式の場合計算結果が入ります。

$変数名=値

と基本的には同じ。(set,変数名,)と空を代入する事で変数の削除ができる点も同じ。
各種特殊変数への設定についても使用できます。
関連→変数

「$変数名=値」記法との違い

nop

(nop,引数)

何も表示しません。
具体的には引数に指定したものを括弧ごと非表示にします。
使い所は、関数やSAORIの戻り値を捨てる時など。
例えばsplit関数は分割数を返し、そのままトーク中に使うと処理のあとに分割数を喋ってしまうので、次のようにnopで包んで何も表示しないようにします。

(nop,(split,一二三四五六七八九))

call

(call,文または単語群名[,引数n…])

文または単語群名を引数つきで呼び出します。
詳しくはcall関数を参照。

vncall

call関数に与える引数を「名前」で与えるバージョンの関数。
ただしwhenのような引数を解釈するタイミングに違いのある関数を呼び出したケースはサポートしていません。

$v0【タブ】ユーザ名
$v1【タブ】ユーザさん
(vncall,set,v0,v1)
(call,set,(v0),(v1))

上のように書くと、呼び出す際に下のイメージで解釈され、v0とv1がその名前の「中身」に置き換えられます。
最終的には(set,ユーザ名,ユーザさん)と同じ結果が得られます。

 

ただし、「最初に引数を区切った後はそれ以降引数を区切らない」というルールがあります。
これにより里々の区切り文字問題を解決できます。
たとえばssuのsplit関数を使って文字を「,(カンマ)」で区切りたい場合、普通に呼び出すと「,」が区切り文字として解釈されて期待する結果が得られませんが、vncallで次のように書くと期待通りの結果を得ることができます。

$v0【タブ】区切りたい,文字
$v1【タブ】,
(vncall,split,v0,v1)

ループ

里々ではループは構文でサポートされていないので、関数またはジャンプ文で実現します。
loop関数のみ昔からある関数で、times,for,while関数は、整備班verで追加された関数です。
この二つにはループ本文やループカウンタの扱いで下記の差があります。

ループブレイクは loop,for,times関数ではサポートされていません。while関数かジャンプ文によるループを使って下さい。

[注意]引数区切りについて
times,while,for関数は、括弧の展開を遅らせる仕組みの関係上、
(バイト値、1)のように引数区切りを括弧で呼び出すと
(C0)の中身が常に空となり、正しく動作しないようです。
⇒対処法

loop

ある文または単語群を指定回数だけ繰り返し呼び出す関数。
この関数のみ、ループ本文を文または単語群で書かないといけません。

(loop,文または単語群名,回数)
(loop,文または単語群名,開始値,終了値)
(loop,文または単語群名,開始値,終了値,増分)

*文または単語群名
ループさせたい本文

ループ中は本文に([文または単語群名]カウンタ)という名前の変数が使用できるようになります。

単語群での使用例

*
:好きな食べ物は (loop,好きな食べ物,3)だよ

@好きな食べ物
すきやき、
焼肉、
フライドチキン、
焼き鳥、
シャブシャブ、
手羽先、

カウンタとトークでの使用例(ヘッドラインを変数に落とす)

*installedheadlinename
(loop,HL格納,0,(Rの数))

*HL格納
$HL(HL格納カウンタ)【タブ】(R(HL格納カウンタ))

プログラミング的な記述の仕方に慣れている人はloopよりtimesの方が使いやすいかも。

times

指定回数ループを繰り返します。

(times,回数[,カウンタ初期値],ループ本体)

「ループ本体」を「回数」回繰り返し、戻り値を連結して返す。
プログラムに慣れてる人はloopよりこちらの方が分かりやすいかも。

#----loopとtimesの指定方法の違い。どちらも同じものを出力する。
*サンプル
(loop,ただの幼女好きの犬コロ,3)
(times,3,(ただの幼女好きの犬コロ))

@ただの幼女好きの犬コロ
エンテイ

while

(while,条件式[,カウンタ初期値],ループ本体)

条件式が真(0以外)である限り、ループ本体を繰り返します。結果は連結して返します。
その性質から無限ループに陥りやすいので取り扱いは慎重に。最悪フリーズしたり落ちたりする事も。

*異なる乱数を二つ作る
$ランダム1【タブ】(乱数0~9)
$ランダム2【タブ】(乱数0~9)
(while,(ランダム1)==(ランダム2),(set,ランダム2,(乱数0~9)))

for

指定開始値から増分ずつカウンタを増加させ、終了値迄ループを繰り返します。

(for,開始値,終了値[,増分],ループ本体)

カウンタが「開始値」から「終了値」に向かって「増分」ずつ進み、その度に「ループ本体」を繰り返し、結果を連結して返します。
(C0)も同様に「開始値」から「終了値」に向かって「増分」ずつ進みます。
「開始値」が「終了値」より大きい値で「増分」にマイナス値も指定できます。
loopと構文が入れ替わった感じ。when同様、カッコは事前に評価されない……はず。

使用例(ヘッドラインを変数に落とす)

*installedheadlinename
(for,0,(Rの数)-1,(HL格納))

*HL格納
$HL(C0)【タブ】(R(C0))
*installedheadlinename
(for,0,(Rの数)-1,(set、HL(C0)、(R(C0))))

条件分岐

if / when

(if,条件式,真の結果[,偽の結果])
(when,条件式,真の結果[,偽の結果])

条件式を評価し、真ならば真の結果を、そうでないなら偽の結果を返します。
偽の結果は省略でき、その場合は空を返します。

*
$たこ数【タブ】(乱数0~3)
:たこが(たこ数)匹釣れました。今日は(if,(たこ数)>1,大漁,普通)です。
:(if,(たこ数)==0,普通ってお前、釣れてないだろそれ……。)

whenは、ifよりも使いやすいように処理順序が修正された関数です。
迷ったらwhenを使っておけば間違いありません。

 

もう少し詳しくいうと、里々は原則として内側のカッコから順番に展開するので、結果に関数などの命令を入れてしまうと条件式に関係なく両方実行されてしまうのです。
下記はその例。

(if,(天気)==晴れ,(set,気分,1),(set,気分,0))
(when,(天気)==晴れ,(set,気分,1),(set,気分,0))
ifの場合whenの場合
「気分」に1をset

「気分」に0をset

「天気」が「晴れ」かどうかチェック
(チェックするだけ)

「気分」は常に0になる
「天気」が「晴れ」かどうかチェック

「天気」が「晴れ」なら「気分」に1をset
それ以外は「気分」に0をset

このようにwhenはカッコの展開の順番に手を加え、条件式を評価したあと「真の結果」「偽の結果」の片方だけを展開します。
ただし、when関数でも区切りを(バイト値、1)のように括弧で呼び出すと、ifと同じ動作になってしまうようです。
⇒対処法

結果の部分にかっこ付きの処理を書く場合はwhenを、そうでなければどちらを使ってもOKといったところですが、
先述したように迷ったらwhenを使えば間違いありません。

unless

(unless,条件式,偽の結果[,真の結果])

ifやwhenと同じように条件式を評価し、分岐します。
違いは条件式の結果が偽なら偽の結果を返し、それ以外で真の結果を返す点(真の結果を省略したら空)。
つまり偽の結果を先に書きたい時に。

iflist / whenlist

(iflist,左辺,右辺1,結果1[,右辺2,結果2[…,右辺n,結果n]])
(iflist,左辺,右辺1,結果1[,右辺2,結果2[…,右辺n,結果n]],偽の結果)
(whenlist,左辺,右辺1,結果1[,右辺2,結果2[…,右辺n,結果n]])
(whenlist,左辺,右辺1,結果1[,右辺2,結果2[…,右辺n,結果n]],偽の結果)

ifと違う点は、条件式が左右に分かれ、複数の条件を順番に評価する点。
ifとwhenの違いについてはif / whenを参照のこと。迷ったらwhenlistを使っておけばOKです。
順序としては以下のようになります。

  1. 左辺と右辺1を組み合わせた条件式が真 → 結果1が返る
  2. 左辺と右辺2と組み合わせた条件式が真 → 結果2が返る
  3. 左辺と右辺3を…以下略

という風に、組み合わせた条件式を「真だったら結果を返し、偽だったら次の条件式へ」と順番に評価します。
どの条件式も真にならなかった場合、偽の結果(省略した場合は空)が返ります。

左辺と右辺の文字列を単純に結合した結果を数式として取り扱い真偽判定するので、結合した結果が正しい数式となるよう注意してください。
通常は左辺の右端か右辺の左端のいずれかに演算子(==とか)を入れる必要があります。

(iflist,(現在時)==,6,朝飯,12,昼飯,15,おやつ,17,ディナー)

上の例では演算子を左辺に使っていますが、右辺に使っても動作します。

switch

(switch,左辺,右辺1,結果1[,右辺2,結果2[,右辺n,結果n…]][,該当なし])

条件並列分岐。左辺も右辺も数値である必要があります。
iflistと似ていて、こちらは左辺と右辺が「等しいかどうか」を順番にチェックする簡略的な関数です。

  1. 左辺と右辺1が等しい → 結果1が返る
  2. 左辺と右辺2が等しい → 結果2が返る
  3. 左辺と右辺3を…以下略

いずれの右辺とも等しくなかった場合は、該当なし(省略した場合は空)を返します。

内部では、

(左辺)==(右辺1)
(左辺)==(右辺2)
(左辺)==(右辺3)

 …

というふうに数式を使い真偽を判定しているので、左辺・右辺ともに「括弧を展開した結果が数値として扱えるもの」にする必要があります。
また、上記仕組みのため、iflist/whenlistと比べて、処理速度はほとんど変わらない、単なる簡略表記になります。

サンプル:

*
:今月は(switch、
(現在月)、
1、お正月ですね、
2、バレンタインデーがあります、
3、ひなまつりがあります、
5、こどもの日があります、
8、夏休みですね、
12、クリスマスがあります、
特に何もありません)。

nswitch

(nswitch,数値,結果1[,結果2[…,結果n]])

数値による分岐。switchをさらにシンプルにしたような関数です。
数値が1なら結果1を、数値が2なら結果2を…というように、数字順にしたもの。
数値に文字列を指定したり、0以下だったり、結果の数より大きい値だったりした場合は空が返ります。

*
:サイコロを振りました。
(nswitch、(乱数1~6)、一、ニ、三、四、五、六)がでました。

文字列操作

substr

(substr,文字列,開始位置[,抽出文字数])

文字列の開始位置から抽出文字数ぶんを取り出します。
マイナス値も指定可能。

開始位置の場合
0 1 2 3 4 5
あいうえおかきくけこ
          -5-4-3-2-1
長さの場合(開始位置が「か」の場合)
          1 2 3 4 5
あいうえおかきくけこ
-5-4-3-2-1
(substr,あいうえおかきくけこ,5,3)
(substr,あいうえおかきくけこ,5,-3)
 ↓
かきく
うえお

at

(at,文字列,位置)

0から始まる指定文字数目の文字を返します。

(at,お酒に逃げた,3)
↓
逃

split

(split,分割する文字列[,区切文字列[,最大分割数[,空要素分割可否]]])

文字列を分割し、分割数を返します。
分割数がいらない時はnop関数とセットで使います。

(split,栄☆養☆☆補☆給,☆,0,1)
#splitの戻り値=5
#(S0)栄 (S1)[空] (S2)養 (S3)補 (S4)給
(split,栄☆養☆☆補☆給,☆,0,0)
#splitの戻り値=4
#(S0)栄 (S1)養 (S2)補 (S3)給
(split,焼きイカ風味カルビ味ソイソース,イカ)
#splitの戻り値=4
#(S0)焼き (S1)風味 (S2)ルビ味ソ (S3)ソース

上記の場合、『焼き』『風味カルビ味ソイソース』ではありません。「イ」「カ」それぞれ一文字で分割されます。
×『焼きイカ風味カルビ味ソイソース』
○『焼き風味ルビ味ソソース』
二文字以上からなる文字列で分割したい場合、あらかじめreplace関数で一文字の記号に置換するなどの工夫が必要です。

 

よくイベントの引数(R0など)で使用されているバイト値1区切りのデータを分割するのも、sprintf関数と組み合わせる事で対処できます。
様々なデータを取り扱おうと考えると、分割文字列に半角カンマ","がよく使われるので、これで文字列を分割する場合は下記を使います。

(split,(R0),(sprintf,%c,1))
(split、(R0)、,)

文字列に","や"、"が両方とも含まれる可能性がある場合は、引数区切り文字を新たに定義する事で対応します。使用する文字は文字列中に含まれないと断定可能な文字ならなんでも良いですが通常はバイト値を使用しましょう。

$B3【タブ】(バイト値、3)
$引数区切り追加【タブ】(B3)
(split(B3)(R0)(B3)(バイト値、1))
$引数区切り削除【タブ】(B3)

特殊変数の引数区切り参考。

replace / replace_first

(replace,文字列,検索文字列,置換文字列)
(replace_first,文字列,検索文字列,置換文字列)

文字列の中にある、検索文字列を置換文字列で全て置き換えます。
replace_firstは最初の候補ひとつだけ置換します。

(replace,なまむぎなまごめなまたまご,なま,生)
↓
生むぎ生ごめ生たまご
(replace_first,なまむぎなまごめなまたまご,なま,生)
↓
生むぎなまごめなまたまご

erase / erase_first

(erase,文字列,消去文字列)
(erase_first,文字列,消去文字列)

文字列の中にある、消去文字列を全て消します。
erase_firstは最初の候補ひとつだけ消去します。

(erase,なまむぎなまごめなまたまご,なま)
↓
むぎごめたまご
(erase_first,なまむぎなまごめなまたまご,なま)
↓
むぎなまごめなまたまご

join

(join,区切り文字,文字列1[,文字列n…])

引数の文字列1~nを区切り文字で連結したものが返ります。

(join,と,汗,涙,酒)
↓
汗と涙と酒

reverse

(reverse,文字列)

文字列を前後反転して返します。

(reverse,文字列)
↓
列字文

zen2han / han2zen

(zen2han,文字列[,変換タイプ])
(han2zen,文字列[,変換タイプ])

zen2hanは文字列の中にある「数字、アルファベット、カナ、一部の記号」を全角から半角に変換します。
han2zenは逆に半角を全角に変換します。
変換タイプは変換する文字の種類を指定でき、「数字」「アルファベット」「カナ」「記号」から複数指定・任意の組み合わせができます。
指定は空白等適当な文字で区切って行い、指定したタイプのもののみ変換されます。省略時は全てが対象です。

kata2hira / hira2kata

(kata2hira,文字列)
(hira2kata,文字列)

kata2hiraは文字列の中にあるカタカナをひらがなに、hira2kataはひらがなをカタカナに変換します。

文字列調査

compare / compare_head / compare_tail

(compare,文字列,比較文字列)
(compare_head,文字列,比較文字列)
(compare_tail,文字列,比較文字列)

文字列と比較文字列が一致していれば1(真)、そうでないなら0(偽)を返します。
この関数による比較は、大文字・小文字、半角・全角を同一と見なす特性があります。

(compare,ABC,ABC)
(compare,ABC,ABC)
(compare,ABC,abc)
(compare,ABCダ,AbCダ)

上記の実行結果はいずれも1となります。

compare_headは「文字列の先頭に比較文字列が含まれているか」
compare_tailは「文字列の末尾に比較文字列が含まれているか」
をそれぞれ判定します。

compare_case / compare_head_case / compare_tail_case

(compare_case,文字列,比較文字列)
(compare_head_case,文字列,比較文字列)
(compare_tail_case,文字列,比較文字列)

半角と全角を同一視しますが、大文字・小文字を同一視しないcompare関数です。
compare_head_case、compare_tail_caseもそれぞれ準じます。

equal

(equal,文字列,比較文字列)

より正確な比較。
半角・全角も、大文字・小文字も同一視せず、完全に一致した場合のみ1(真)、そうでないなら0(偽)を返します。

count

(count,文字列,検索文字列)

文字列の中に、検索文字列がいくつ含まれているかを返します。
条件式に使えば、単純に「検索文字列が存在するかどうか」の判定としても使えます。

「なまむぎなまごめなまたまご」の中に
「なま」は(count,なまむぎなまごめなまたまご,なま)個入っています。
↓
「なまむぎなまごめなまたまご」の中に
「なま」は3個入っています。

length

(length,文字列)

文字列の文字数を返します。バイト数ではないので注意。

(length,台風99号)
↓
5

is_empty

(is_empty,文字列)

文字列が空文字列であるかを判定。空文字列なら1(真)、そうでないなら0(偽)を返します。
たぶん想定される使い方は下。
(変数「○○」の存在)と同じ?

(is_empty,(確認したい変数名))

is_digit

(is_digit,文字列[,integer又は整数])

文字列が数値であるかを判定し、数値なら1(真)、そうでないなら0(偽)を返します。
小数点一つまでは数値だと判定されます。
また、下記のどちらかの記述で、引数が整数の場合のみ1(真)を返すようになります。

(is_digit,引数,integer)
(is_digit,引数,[整数])

is_alpha

(is_alpha,文字列)

アルファベットの文字列であれば1(真)、そうでないなら0(偽)を返します。

未分類

choice

(choice,引数1[,引数n…])

指定した全ての引数からランダムに1つを選んで返します。

*
:何が釣れた?
:(choice,鯛,イワシ,鮫,くじら,長靴)が釣れたよ。

lsimg

(lsimg,絶対パス)

指定パスのフォルダ内にある画像ファイルの数を調べる?

mkdir

(mkdir,絶対パスorベースウェアからの相対パス)

フォルダを作成し、成功したら1、失敗したら0を返します。

*フォルダ作成
>成功【タブ】(mkdir,ghost\satori\ghost\master\新規フォルダ)==1
:失敗したみたい…。

*成功
:新規フォルダをつくったよ。

remember

(remember,参照値)

過去に話したランダムトークの内容を取得?
参照値は0スタートで、(remember,0)で直前になります。

sync

(sync,関数名[,引数n…])

処理をしゃべりと同期します。SAORIを任意のタイミングで発動させたい時に。

sprintf

(sprintf,フォーマット[,引数n…])

引数1~nをフォーマットに従って変換したものを返します。
フォーマットは下記のように、「%」から始まる「フォーマット指定子」を含む文字列で、フォーマット指定子の出現順と対応する順序の引数がフォーマット指定子の出力の元となります。

(sprintf,%02d月%02d日,12,3)

フォーマット指定子

基本の書きかた

%[フラグ指定][最小幅指定][.精度指定][出力指定]

出力指定以外は省略可能。

フラグ指定

指定説明
+常に正負符号を表示する
-最小幅に足りない分だけ末尾を半角スペースで埋める(左詰)
 *2最小幅に足りない分だけ先頭を半角スペースで埋める
0最小幅に足りない分だけ先頭を0で埋める
#代替形式。後述

複数続けて指定できる(競合する場合は後に書いた方優先)
「0」「 」の「先頭」は、正負符号がある場合はその後ろ
全角文字は2幅分と数える

#出力結果:ユーザ    様
(sprintf,%-10s様,ユーザ)
#出力結果:1234年05月06日
(sprintf,%04d年%02d月%02d日,1234,5,6)
#出力結果:-1+3は?
(sprintf,%+d%+dは?,-1,+3)
#出力結果:-  12
(sprintf,% 5d,-12)

最小幅指定
文字列の最小幅(最小文字数)を指定できる
数字を入れる場合、正負符号や小数点「.」も数えることに注意
フラグ指定と合わせて用いる

#出力結果:   -12
#フラグ「 」を指定した場合と異なり空白は符合よりも前
(sprintf,%6d,-12)
#出力結果:-012
(sprintf,%04d,-12)

精度指定
「.」に続けて実数の有効桁数が指定できる

#出力結果:3.142
(sprintf,%1.3f,3.141529)

出力指定

指定対応する引数説明引数「63」の出力例
s,S全て文字列をそのまま表示(sもSも同じ)63
c,C整数指定した10進整数に対応する文字を表示(cもCも同じ)?
d,u実数10進整数で表示(dは符号なし、uは符号付き)63
o,i実数8進整数で表示(oもiも同じ)77
x,X実数16進符号なし整数で表示(xは小文字表記、Xは大文字表記)3f
f実数実数を少数形式(固定小数点による標準記法)で表示63.000000
e,E実数実数を指数形式(科学的記法)で表示(eは小文字表記、Eは大文字表記)6.300000+e001
g,G実数f,eのうち適した方の形式で表示(gは小文字表記、Gは大文字表記)63.000000

フラグ「#」の代替形式について
変換指定に応じて意味が変わる
o,x,Xの場合:基数を明確にする
f,e,E,g,Gの場合:常に小数点を表示
:無視される

#出力結果:0XA
(sprintf,%#X,10)

補足
引数の番号指定はできない

バイト値

(バイト値、1)

バイト値1が得られます。主に引数の区切りなどで利用します。
ほかにバイト値3なども同じ書き方で得ることができます。

1だとメールを処理する時の分割子がバイト1なので、リプレイスとかでバグる可能性に注意して下さい。
1ではないものを推奨する、が、0とか入れると大変なことになるらしい?
分割子は自分でも設定できるので、使わない記号が一番安全かも。

[注意]when,times,while,forについて
これらの関数は、引数内の括弧を展開するタイミングを遅らせる仕様の関係から、
(バイト値、1)などの関数が実行されるタイミングも遅れてしまうので、
(バイト値、1)で引数を区切ろうとしても、正しく認識されないようです。
whenはifと同じ処理になり、ループ系の関数は(C0)が常に空になります。
⇒対処法

単語の追加

(単語の追加,単語群名,単語)

@単語群名に「単語」を追加します。該当する単語群名が無ければ新規に作成します。
追加された単語の情報はsatori_savedata.txtに保存されます。

(単語の追加、果物、バナナ)
@果物
りんご

単語群「果物」に「バナナ」を追加します。

追加単語の削除

(追加単語の削除、単語群名、単語)

単語の追加で追加した単語を削除します。

追加単語の全削除

(追加単語の全削除、単語群名)

単語の追加で追加した単語を全て削除します。

合成単語群

(合成単語群,単語群名1[,単語群名n…])

指定した単語群名を全部候補として、その中からランダムに一つ選んで返します。

(合成単語群、果物、野菜、海産物)
@果物
りんご
みかん

@野菜
にんじん
じゃがいも

@海産物
いか
たこ

上の例では「りんご」「みかん」「にんじん」「じゃがいも」「いか」「たこ」のどれか一つが選ばれます。

load_saori

(load_saori,呼び出し名,モジュールパス[,引数n…])

satori_conf.txt に書いていないSAORIを関数実行時にロードすることができます。
引数はsatori_conf.txt に記載の順番で記述。
ロードするタイミングがロードするかどうかを制御したい場合に。
一度ロードしたSAORIは、satori_conf.txt に書かれているSAORIと同じタイミングでアンロードされます。


*1 里々の関数をまとめたSAORI。初期の里々は多くの関数を外部関数として利用する形式でした。
*2 半角スペース。

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2022-12-15 (木) 20:51:13