Satori (里々) English Guide

by ray.m

Table of Contents:

Introduction

Satori, written in Japanese as 里々, is a Shiori, or a sort of programming language for writing Ukagaka Ghosts. It is still regularly updated, and is relatively easy to understand and write once you get the hang of it.

Satori, being designed for use by speakers of the Japanese language, requires frequent use of full width characters. If you'd like to type these without constantly copying and pasting, you'll need to install a Japanese IME. The ability to read Japanese also makes working with Satori much easier, as some predefined functions and variables are in Japanese.

Much information on this page is referenced from the Japanese Satori Wiki.

Satolist2 is an editor for making Ghosts in Satori, but you can also use any plain text editor.

This guide also assumes you're familiar with the basics of Ghost descript files and other files not immediately related to Satori.

Back to top

Post and Komainu, the Template Ghost

A good place to start with Satori is the template Ghost Post and Komainu (ポストと狛犬), which can be downloaded from the Satori Wiki. (Post or ポスト is the Japanese word for mailbox.)

Back to top

satori.dll and ssu.dll

satori.dll belongs in the Ghost's master folder, while ssu.dll goes in the saori folder under the aforementioned master folder. These are what you will download if you're making a Satori Ghost from scratch or if you want to update your Ghost's version of Satori.

Back to top

Configuration Files

In descript.txt, make sure you have your Shiori set to satori.dll.

shiori,satori.dll

satori_conf.txt is where you will declare variables set when the Ghost boots for the first time, as well as the Saori your Ghost uses.

*初期化
$喋り間隔【タブ】180秒
$喋り間隔誤差【タブ】10%

@SAORI
fill_desktop,saori/fill_desktop.dll

Changed variables while the Ghost is running will be written to the satori_savedata.txt file.

developer_options.txt is mainly where you will designate what doesn't get archived in the .nar or update files for distribution purposes. By default, because you don't want to distribute your Ghost with them, you should at least have these written in there:

ghost/master/satori_savebackup.txt,nonar,noupdate
ghost/master/satori_savedata.txt,nonar,noupdate
ghost/master/satorite.txt,nonar,noupdate
ghost/master/satorite.exe,nonar,noupdate
ghost/master/れしば.txt,nonar,noupdate
ghost/master/れしば.exe,nonar,noupdate

replace.txt is for replacing text in the other files. Of note here is replacing the tab character with 【タブ】 if you'd like to use it instead of writing a tab character, which is used widely in Satori. 【タブ】 is easer to see, but if you're using Notepad++, you can also go to View->Show Symbol->Show Space and Tab, and this will show the tabs. Additionally, this is where full width wait times are written as an alternative to SakuraScript, if you'd like to use them instead.

【タブ】

w1 \w1
w2 \w2
w3 \w3
w4 \w4
w5 \w5
w6 \w6
w7 \w7
w8 \w8
w9 \w9

This guide will use 【タブ】 for visibility where it is valid to use.

Back to top

Dictionary Files

These will make up your Ghost. They begin with dic and end with the .txt file extension.

They don't have to be numbered in a certain order or at all, but the template Ghost comes with them numbered and generally sorted rather well.

Back to top

Special Characters

Satori uses several full width characters that it parses in different ways.

* (full width asterisk)

Without anything following the asterisk, this is where you write your random dialogue.


:This is a random line of speech.


:This is also random.
:Yeah, it is.

The asterisk followed by an event designates what is said when that event is called.

*OnBoot
:Hi! I just booted.

: (full width colon)

Used to specify whether the main or sub character is talking.

Starting the first line of dialogue with : will have the main character say it. Starting without it makes the sub character say it. Further use of : after either changes the character speaking.


:I'm the main character!
:I'm not!
:I am!


I'm the sub character!
:I'm not!
I'm the main character!

You can optionally use SakuraScript \0 and \1 instead of this, if it's clearer.

> (full width greater than)

Used to jump to a different, named part of the code.


>JumpExample

*JumpExample
:We just jumped here from a random piece of dialogue.

@ (full width at symbol)

Used to make lists that can be pulled from.

@Seasons
Winter
Spring
Summer
Autumn

(...) (full width parentheses)

Surrounds variables to print them. In the case of lists, pulls a random entry.


:(UserName), do you like (Seasons) the most?

Full width parentheses can also be used for surfaces instead of \s.


:(0)Heya!

$ (full width dollar sign)

Used to set variables. Tab is used for setting strings, whereas = is used for calculating; it's the difference between "1 + 1" as a string and "1 + 1" as a mathematical equation.

$Score【タブ】0

$Score=(Score)+1

_ (full width underscore)

Used for menu choices. Jumps to the choice name, otherwise can jump to a specified location using tab.


:Do you like games?

_Yes【タブ】GamesYes
_No【タブ】GamesNo

*GamesYes
:Cool.

*GamesNo
:Aw.

【タブ】 (tab)

Alternatively, a literal tab character.

For *, >, or @, means if.

For $, sets a variable.

*【タブ】(現在曜日)==日
:Today is Sunday!

# (full width pound)

For commenting out lines.


:I'm so smart!
# They're actually an idiot.
Back to top

Predefined Variables

Satori has many variables ready for use.

(R…) (Reference...)

Used for events. Many events have "references". See the Shiori Event List on Ukadoc. (English translation.)

(A…)

Arguments used in call functions.

(S…)

Used in split functions.

(乱数x~y) (random number)

Picks a random number from x through y.

(現在…) (current...)

Returns a value based on the current time.

The "…" here can be:

:Today is (zen2han,(現在月))/(zen2han,(現在日))/(zen2han,(現在年)).

曜日, day of the week, does not return a number! Rather, it returns a character based on the day of the week in Japanese:

*【タブ】(現在曜日)==火
:Tuesday again?

(起動回数) (times run)

Number of times the Ghost has been run.

(起動…) (startup time)

Time the Ghost was run. Takes 時 (hour), 分 (minute), and 秒 (second).

(累計…) (total time)

Total amount of time the Ghost has been open. Like the startup time, it takes 時 (hour), 分 (minute), and 秒 (second), but these are not total amounts, they're split into hour:minute:second; that is, calling (累計分) at 1 hour and 50 minutes open will return 50, not 110.

(OS起動…) (OS startup time)

Either this is the time the OS was booted, or the time since then. I'm admittedly unsure. Also takes 時 (hour), 分 (minute), and 秒 (second). Does not work on the baseware NiseRingo.

(単純…) (plain time)

Adding 単純 before 起動, 累計, or OS起動 times lets you return the actual number of minutes or seconds. For example, calling (単純累計分) at 1 hour and 50 minutes open should return 110 as opposed to 50.

(最終トークからの経過秒) (seconds since last talk)

Seconds passed since the Ghost last talked.

(前回終了時サーフェス…) (surface when last closed)

Obtains the surface ID of the surface displayed when the Ghost was closed last. "…" here is replaced with the ID of the character; 0 for the main and 1 for the sub.

(変数「…」の存在) (variable existence)

Checks for the existence of the variable in the quote brackets. Returns 1 if it exists, otherwise returns 0.

*【タブ】(変数「UserName」の存在)==1
:So, your name is (UserName)?

(プロセス「…」の存在) (process existence)

Checks for if the process named in the quote brackets is running. Returns 1 if it exists, otherwise returns 0.

(「…」を含むプロセスの存在) (process containing...)

Checks for a process containing the string in the quotes.

(ウインドウ「…」の存在) (window existence)

Checks for an exact match of a window named in the quotes.

(「…」を含むウインドウの存在) (window containing...)

Checks for a window title containing the string in the quotes.

*【タブ】(プロセス「notepad++.exe」の存在)==1||(「Notepad++」を含むウインドウの存在)==1
:Coding something?

(隣で起動しているゴースト) (simultaneous ghost)

If another Ghost is running, returns the name of the main character. If not, is empty.

(…の存在) (other ghost existence)

Checks if a named Ghost character is running. Returns 1 if so, otherwise 0.

(…のサーフェス) (other ghost surface)

Returns the current surface ID of the specified Ghost character. Also works for sub characters.

(導入済みゴースト「…」の存在) (prexisting ghost installed)

Checks if a Ghost named in the quotes is already installed.

Replace ゴースト with シェル (shell), バルーン (balloon), フォント (font), ヘッドライセンサ (headline sensor), or プラグイン (plugin) as needed.

Requires NOTIFYの自動保存 set to 有効.

Back to top

Special Variables

There are also special variables which have importance when set.

$次のトーク (next talk)

Used to denote the immediate next piece of dialogue.


:I want snacks.
$次のトーク【タブ】WantSnacks

*WantSnacks
:...Like cookies or something.

$次から…回目のトーク (talk after ... many times)

Replace the "…" with the number of random dialogue in between and it will jump in that many turns.


:I need water.
$次から5回目のトーク【タブ】NeedWater

*NeedWater
:I still need water, by the way.

$辞書フォルダ (dictionary folder)

Changes the folder containing dictionary files. The folder must be under the master folder.


:Changing dictionaries!
$辞書フォルダ【タブ】another


:Going back to normal.
$辞書フォルダ【タブ】.

$辞書リロード (dictionary reload)

Reloads the dictionary files when set to 実行.

*OnKeyPress【タブ】(R0)==r
$辞書リロード【タブ】実行
:Dictionary reloaded.

$辞書接頭辞 (dictionary prefix)

Changes the prefix for the dictionary files. Goes in satori_conf.txt.

$辞書接頭辞【タブ】dict

$辞書拡張子 (dictionary extension)

Changes the file extension for the dictionary files. Goes in satori_conf.txt. Does not affect replace.txt and satori_conf.txt.

$辞書拡張子【タブ】uka

$自動セーブ間隔 (save interval)

Sets the interval between automatic saves to save data, in seconds. Setting it to 0 disables automatic saving.

$自動セーブ間隔【タブ】300秒

$手動セーブ (manual save)

Manually saves when set to 実行.

$手動セーブ【タブ】実行

$セーブデータ暗号化 (save data encryption)

Saves the save data in satori_savedata.sat instead of satori_savedata.txt.

Goes in satori_conf.txt. This makes the save data hard to edit, so be aware of this during development.

$セーブデータ暗号化【タブ】有効

$喋り間隔 (talk interval)

Time between random dialogue, in seconds. If set to 0, the Ghost will not talk on their own.

$喋り間隔【タブ】180秒

$自動改行挿入 (automatic line break)

Used to designate if you want to keep the line breaks as they are coded or not. 有効 to keep them, 無効 to disable.

$自動改行挿入【タブ】有効
Back to top

Functions

Functions are written with full width parentheses in the format (function,arguments).

calc

Calculates a mathematical equation and disregards anything beyond the decimal point.


:2 times 2 is (calc,2*2)!

calc_float

Same as calc, but retains the decimal.


:5 divided by 2 is (calc_float,5/2)!

set

Sets variables. Same as using $.

(set,Mood,Happy)

nop,(function)

Returns a value from a function but doesn't print. Often used with split.

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

call

Calls from something defined with @ or *, potentially a list of objects.

For example, this will call a sound by defining the SakuraScript for playing a sound from a folder named sfx:


:(call,SFX)This could be playing sound1.wav or sound2.wav.

@SFX
\_v[sfx/sound1.wav]
\_v[sfx/sound2.wav]

Additional arguments are written as A0, A1, A2, and so on.


:(call,SFX,sound1)This is playing sound1.wav.


:(call,SFX,sound2)This is playing sound2.wav.

@SFX
\_v[sfx/(A0).wav]

Another example of call, for math:


:We're gonna add 20 and 32.
(call,DoMath,20,32)

*DoMath
:(A0) plus (A1) is (calc,(A0)+(A1)).

split

Splits a string based on a character or characters, subtracting them from the original string and dividing it into S0, S1, S2, and so on.

(nop,(split,言葉も想いも全部,も))(S0)、(S1)、(S2)

...Will display 言葉、想い、全部, with 言葉 as S0, 想い as S1, and 全部 as S2.

Multiple characters used as the divider will be used as an or, not and.

split_string

Like split, but splits a string based on another whole string.

(nop,(split_string,わたしのココロとキミのココロ,のココロ))(S0)(S1)

...Will display わたしとキミ, with わたし as S0 and とキミ as S1.

when

Typical if statement. You can also write if instead of when, but it's calculated a little differently.

Written as (when,Condition,Result,Else). The else part is optional.

(when,(Mood)==Happy,I'm so happy!,I'm not very happy.)

...Will display I'm so happy!

unless

Like if and when, but the inverse.

at

Finds a character in a string, starting from 0.

(at,Hello World,4)

...Will return o.

replace

Replaces a string within a string with another.

(replace,master-san,san,sama)

...Will return master-sama.

replace_first

Like replace, but only affects the first occurrence of the found string.

(replace_first,miko miko miko miko nurse,miko miko,kaeru pyokopyoko)

...Will return kaeru pyokopyoko miko miko nurse.

erase

Erases a string within a string.

(erase,raburabu,bura)

...Will return rabu.

erase_first

Like erase, but only affects the first occurrence of the found string.

(erase_first,miko miko miko miko nurse,miko miko )

...Will return miko miko nurse.

join

Joins multiple strings together.

(join,(UserName),-,san)

...Will display the value of UserName followed by -san.

reverse

Reverses a string.

(reverse,Hello World!)

...Will display !dlroW olleH

zen2han

Converts a full width string to a half width one. han2zen does the reverse.

kata2hira

Converts katakana to hiragana. hira2kata does the reverse.

compare

Compares two strings and returns 1 if true, otherwise 0.

equal

Like compare but much more strict - the strings have to be exact in character width and case.

count

Counts the number of times a string occurs within another.

(count,kanakana,kana)

...Will return 2.

length

Counts the number of characters in a string.

is_empty

Returns 1 if a string is empty, otherwise 0.

is_digit

Returns 1 if a string is a number, otherwise 0.

is_alpha

Returns 1 if a string is in the alphabet, otherwise 0.

choice

Picks one randomly from a set of choices.


:(choice,apple,orange,banana) is my favorite fruit.

単語の追加 (adding words to group)

Adds a string to a list defined with @ and saves that to satori_savedata.txt.

(単語の追加,Fruits,banana)

@Fruits
apple

追加単語の削除 (removal of added word)

Removes a specific string added with 単語の追加.

(追加単語の削除,Fruits,banana)

追加単語の全削除 (removal of all added words)

Removes all the strings added to a list with 単語の追加.

(追加単語の全削除,Fruits)

合成単語群 (combine word groups)

Combines the contents of lists into one list and chooses one object from it.


:I need to buy (合成単語群,Fruits,Vegetables,Meat) at the store.

@Fruits
apples
oranges

@Vegetables
onions
potatoes

@Meat
steak
turkey

load_saori

Loads a Saori based on the name it's defined as in satori_conf.

Back to top

Mouse Interaction

Some of these are already defined in Post, the Satori template Ghost.

xyつつかれ (double clicking)

x is the character ID, y is the name of the collision area. You can omit the collision area name to double click the character as a whole.

*OnMouseDoubleClick
>(R3)(R4)つつかれ
()

*0Faceつつかれ
>Menu

*0Headつつかれ
:Don't flick my forehead!

xyころころ (mouse wheel)

Same xy mechanics as double clicking. Occurs when the mouse wheel is spun.

*OnMouseWheel【タブ】(count,(Status),talking)==0
>(R3)(R4)ころころ上【タブ】(R2)>0
>(R3)(R4)ころころ下
>(R3)(R4)ころころ

*0Skirtころころ
:Huh? Is it windy?

xyなでられ (petting)

Same xy mechanics as double clicking. Occurs when the character is "pet" with the mouse cursor by moving it back and forth in a collision area.

*0Headなでられ
:Headpats...

xyホールド (holding)

Same xy mechanics as double clicking. Occurs when the character is left clicked and held onto without letting go of the mouse.

xyホールド終了 occurs when you let go.

*0ホールド
:Don't cling onto me.

*0ホールド終了
:Thanks for finally letting go of me...

Other mouse interactions can be written according to the relevant Shiori events.

Back to top

Communication

Communication between Ghosts, and between the user and the Ghost, have some overlap in how they are treated in Satori.

→ (talking to a Ghost)

The right pointing arrow can be used after an empty full width asterisk to have your Ghost talk to any other active Ghost (through Call Ghost). The intention is that the other Ghost will have its own code to parse what yours has said.


→:Hello there.

$Value0 (talking to a specific Ghost)

Using Value0 and tab, you can look for if a specfic main character is running, and talk to them.


$Value0【タブ】ポスト
:Hello, ポスト.

*ユーザ「  (user communication)

Runs when the user inputs something in the Communicate box.

There must be a full width space to separate keywords; a half width space will not break. This can be used in English speaking Ghosts to search for phrases. Unfortunately, similarly because Japanese generally lacks spaces, searching for "hello" in the user input with also return true if the user types, for instance, "Othello", because it contains "hello".

*ユーザ「 check my email check email メール
:Okay, I can check your email.\![biff]

*…「  (response to ...)

Starting the conversation is great, but what if you want to respond to what another Ghost has said?

By replacing the … with the name of that character, you can have your Ghost respond to keywords from that character. This functions like user communication above.

*ポスト「 こんにちは
:Hi to you too, ポスト.

*「  (response to either user or Ghost)

This will run when either another Ghost or the user says something (the user via the Communicate box).

*「 morning おはよう
:Morning!

COMMUNICATE該当なし (communication not applicable)

Occurs when communication happens but no keywords are found.

*COMMUNICATE該当なし
:...Sorry? What did you say?
Back to top

Recommended Sites and Portal Sites

This is the format for sakura.recommendsites, kero.recommendsites, and sakura.portalsites.

You can use - on a new line to make a divider in portalsites.

*sakura.recommendsites
Name (of the site as it will appear in the menu)
http://…… (URL)
file:///…… (banner)
:Write any dialogue about the site here.

You can leave the banner file an empty line and it will work fine.

You can change the name of the categories in the menu like so:

@recommendrootbutton.caption
Websites of Interest

@portalrootbutton.caption
Friends' Websites

@kero.recommendbuttoncaption
Sub Characters's Recommended Sites
Back to top

Conclusion

Satori is a very simple but capable way to write a Ghost with many resources available, particularly if you're familiar with Japanese.

Hopefully by the end of this guide you now understand the basic concepts of Satori.

Good luck making your Ghost!

Back to top