跳转至

ERB構文講座

元となったページ
eratohoまとめ V3 ERB構文講座

前編 基本、変数、表示
後編 分岐と反復、関数と関数呼び出し、ラベルとキー入力、その他
特別編 ビット演算について
参考 ERBファイルの作成や改造時によくあるミスについてのQ&A


基本

構文以前の部分です。不明な~などのエラーが出る時はこの部分が怪しいかも。


構文の記述は半角で行う

日本語の文章以外の部分は全て半角で入力しましょう。
見落としやすいのは全角スペースが主です。テキストエディタの検索機能で
全角スペースを検索すれば簡単に見つけられるはず。


分岐や反復にはインデントを行う

これは直接エラーには繋がりませんが、後述する分岐や反復を使う際には
インデントを使用しましょう。インデントとは行頭に決まった量の空白を
置くことによって記述の位置をずらし、ここからここまでが
一塊の処理です、というのをわかりやすくします。
インデントの空白にはTABキーを使用します。
インデントに処理上の効果はありませんが、デバッグで自分が見直す時や
他の人に見てもらう時などに役立ちます。
必要ないだろうと思っても一応はつけておきましょう。


コメントアウト部分の行頭には;(半角セミコロン)をつける

構文の行頭に;をつけることによってその行をコメント化することができます。これをコメントアウトと言います。
コメントアウトとは書かれている処理が実行されない部分のことで
一時的にその処理を無効にしたり、付近の処理についての
メモ書き代わりに使われることがあります。
なお、コメントアウトでは全角文字を使っても構いません。

ERB
;ここはコメントだから実行されないよ!  

Emuera1.807以降の追加機能で、構文の途中からでもコメントアウトを書けるようになりました。
ただし、PRINT系命令の後にある;はコメントアウトとして認識されず、文字列としてそのまま表示されます。

ERB
A = A + B ;ここはコメントアウト  
PRINT ほげほげ ;でもここはコメントアウトにならない  

コメントアウトは詳しく正確につけましょう

コメントアウトを正しくつけることにより、なにか不具合があっても対処しやすくなります。
また自分自身や他人がソースを見直すときの理解の助けにもなります。
デバッグや改造にも有用ですので、なるべくコメントアウトはつけたほうがいいでしょう。
ただし、そのコメントの内容が間違っていてはいけません。
コメントの中身もしっかりとチェックすべきです。

eramakerの仕様 ### 各ファイルの最後の行には必ず1行以上の空行を入れる `eramaker`の仕様上の問題で、ファイルの最後に空行がない場合
その直前の行が認識されなくなってしまいます。
`ENDIF~`というエラーのよくある原因の1つです。
(Emueraではこの問題は発生しません。)

変数

計算などの処理で使われる変数についてです。

変数とは?

変数とは計算結果を保存したり、ある数値とある数値を比較したりする際に
使用する入れ物のようなものです。
文章による説明だけではわかりづらいので一例を。

ERB
A = 0  
B = 0  
C = 0  

A = 0とは、変数A0を代入する、ということを表しています。
上のA,B,Cがそれぞれ変数です。現在はいずれも0が中に入っています。

ERB
B = A + 1  
C = A + 2  

B = A + 1とは、変数BA + 1の結果を代入する、ということを表しています。
ここで計算が行われ、BCの中身が書き換えられました。A0なので
B0 + 11C0 + 22となります。A0のまま変化していません。

ERB
A = C  
A = B  

次にAC、つまり2が代入されました。これでA2になります。
しかし、次の行でAB、つまり1が代入されたため、A1となります。
このように、同じ変数に複数回代入が行われると結果は上書きされます。

ERB
C = C + 2  
A = B + C  

次に、CC + 2が代入されます。
計算前のC2だったので、計算後のC2 + 24です。
そしてAB + C、つまり1 + 4が代入されます。
ここまでの処理の結果、A5B1C4となりました。


変数の種類

変数には大きく分けて2種類のものがあります。
上のA,B,Cのように数字を格納する『数値型変数(int型)』と
文字を格納する『文字列型変数(string型)』です。
数値変数は計算や条件判断に、文字列変数は主に文章の表示に使われます。
また、変数には『配列』という概念があります。配列を使うことで変数に複数の値を
格納することができるようになります。
例えばAという変数の配列は、A:0,A:1,A:2,A:3, …という風に
(変数名):(配列番号)で表現します。(:は半角のコロンを使用します)

ERB
A:0 = 0  
A:1 = 1  
A:2 = 2  
A:3 = 0  

A:3 = A:0 + A:1 + A:2  

この式はA:3A:0 + A:1 + A:2の結果、つまり0 + 1 + 2を代入することを表します。
処理の結果、A:33になります。

一部の変数には、2次元配列という形式のものもあります。2次元配列は
A:0:0,A:0:1, …,A:1:0,A:1:1, …のように記述し、更に多くの値を格納できます。

どの変数がどの配列形式かは、eramaker用変数リストEmuera用定数・変数に載っています。


変数の使い方

基本的にはeramakerの変数リストのページに書いてある通りです。
ここでは扱いに注意が必要なものを主に取り上げます。

  • A - Z 上記ページでは記述されていませんが、配列として使用できます。
    AA:0と同じです。
    つまり、A:0の値を変えたあとはAの値も同様に変化しています。

  • FLAG/TFLAG/CFLAG FLAGTFLAGはゲームシステムに関する部分に使われるため
    特定のキャラのみに使用するフラグを管理する際にはCFLAGを使用しましょう。
    また、非常に被りやすいので使用の際はフラグ一覧表を良く確認しましょう。
    フラグ一覧表は、各バリアントに同梱されている「変数資料.txt」などを見てください。

eramakerの仕様 なお、`eramaker`の仕様では`0~999`までの1000個の数字を使えるとなっていますが、実際にはバグにより`0~998`までの999個しか使えません。
999を使うとセーブデータが破壊されてしまいますので絶対に使用しないでください。
TFLAGは調教ごとにリセットされることにも注意してください。
(Emueraを使用する場合には、CFLAG:999を利用してもセーブデータ破壊は起こりません。また設定により、1000個を超える数字を使うこともできます。)
  • TEQUIP  上のフラグ系と同様に被りやすいので使用の際はフラグ一覧表を確認しましょう。

2次元配列について

2次元配列形式の変数は、主にキャラに関するデータに使われています。
そのため、2次元配列変数の読み方は以下のようになっていることがほとんどです。

ERB
;変数「ABL」、「TALENT」などの例
(能力の種類):(キャラの登録番号):(能力の番号)  

  • TALENT:5:20 これは登録番号5のキャラの20番の素質を表します。(20の部分はtalent.csvで定義した名前で代替可能)
    ここで気をつけないといけないことは、キャラの登録番号(ID)とキャラ番号(NO)の違いです。
    eratohoならキャラ番号5はチルノとなっていますが
    登録番号5は常にチルノを指すとは限りません。
    登録番号はSHOPでキャラを購入する(ADDCHARA)などして調教可能になった際に
    割り振られる番号で、キャラリストの並び順を表しています。
    例えば最初に霊夢を購入し、次にチルノを購入した場合
    チルノの登録番号は2となり、その状態で霊夢を売却(DELCHARA)するとリスト全体が
    1つ手前にずれ、チルノの登録番号は1となります。

  • TALENT:100 見た感じこれは2次元配列ではないように見えますね。
    しかし、これはTALENT:TARGET:100が省略されたもので、現在調教中もしくは
    調教予定のキャラの100番の素質を表しています。
    TARGETは現在調教中もしくは調教予定のキャラの登録番号を示す変数です。
    TARGETは指定されることが多いためか省略可能となっています。

eramakerの仕様 ちなみに、上の項で`TALENT:5:20`というのを説明しましたが
eramakerの仕様上の問題で実際にこう記述しても登録番号5の
キャラの20番の素質を表すことはできません。
その原因がこの`TARGET`の省略で、`TALENT:5`まで読み込んだ時点で
`TALENT:TARGET:5`の省略されたものと判断されてしまい
エラーの原因になってしまうようです。
実際に登録番号5のキャラの20番の素質を表したい場合は
A = 5
TALENT:A:20
というように、一旦変数に登録番号を格納するなどの工夫が必要となります。
(Emueraを使用する場合にはこの問題は発生しません。`TALENT:5:20`も意図通り利用できます。)

演算

数値処理には欠かせない計算の方法です。

基本的な四則演算

四則演算を行うための基本的な演算子

コード 結果
A + B AとBの和をとる。(足し算)
A - B AとBの差をとる。(引き算)
A * B AとBの積をとる。(掛け算)
A / B AとBの商をとる。(割り算)小数点以下は切り捨て。
A % B AをBで割ったときの余りをとる。(剰余)

自身に対する四則演算

A = A + Bの様な形式は次のように省略できる。

コード 結果
A += B A = A + Bと同じ。
A -= B A = A - Bと同じ。
A *= B A = A * Bと同じ。
A /= B A = A / Bと同じ。
A %= B A = A % Bと同じ。

論理演算子

ビット演算のために使う特殊な演算子です。

コード 結果
A \| B AとBをOR演算したものを返す。
A & B AとBをAND演算したものを返す。

表示

主に口上で使用する、画面に文字などを表示させるPRINT系の構文です。

PRINT系命令の種類

PRINT系の命令には主に以下のものがあります。

記法 概要
PRINT 通常の文字列を表示します。変数等は使用できません。
PRINTV 数値変数を表示します。
PRINTS 文字列変数を表示します。
PRINTFORM 通常の文字列に数値・文字列変数を複合して表示します。

あまり使われませんが、以下のようなものもあります。

記法 概要
PRINTFORMS 文字列変数を表示します。
PUTFORM PRINTFORMと同様ですが、セーブデータ専用です。

各命令の後にLWをつけると、改行や入力待ち(Enterキーを押すまで進まない)を
させることができます。例えば、

ERB
PRINT あ  
PRINT い  
PRINTL う  
PRINTW え  
PRINTL お  

と記述すると、まず

あいう  
え  

と表示され、入力待ち状態になります。
ここでEnterキーを入力すると残りも表示され

あいう  
え  
お  

と表示されます。


上の項にある通り、PRINT系の命令にはそれぞれの用途がありますが
実際にはPRINTFORMでほとんどのものを代用することができます。
普通の文章を表示させるなら

ERB
PRINTFORM あいうえお  

のようにそのまま記述します。この時、PRINTFORMと表示させる文章の間に
半角スペースを入れておくのを忘れないようにしましょう。
数値変数を組み合わせて表示させるなら

ERB
A = 5  
PRINTFORM 変数Aは{A}です  

のように変数名を半角の{~~~}で括って記述します。

文字列変数なら

ERB
STR:0 = かきくけこ  
PRINTFORM あいうえお%STR:0%さしすせそ  

のように変数名を%~~~%で括って記述します。

PRINTFORMもまた後ろにLWをつけることで、

  • PRINTFORML:改行ありだが改行や入力待ちをせず次の行も表示
  • PRINTFORMW:改行してその行で表示を止める

と使い分けることができます。

セーブデータに表示させるPUTFORMのみPRINTFORMでは代用できませんが
セーブデータの表示を変更する機会は少ないと思われるので割愛します。
詳しくはPUTFORMのページを参照


その他の表示

文字を表示した後改行させるにはPRINTFORMLを使いますが
文字を表示させずに改行させたい、つまり空白行を表示させたいという
場合にもPRINTLPRINTFORMLを使います。

ERB
PRINTFORML あいう  
PRINTFORML   
PRINTFORML えお  

2行目はPRINTFORMLの後に半角スペースのみを入力しており、これによって

あいう  

えお  

のように空白行を表示させることができます。PRINTLでも全く同じ表示がされます。

また、DRAWLINEを使用することで

-------------------------------------------------------------------------------  
 このように長い横線を表示させることができます。


分岐と反復

条件式

分岐や反復の前に、それらの実行される基準となる条件式についてです。

比較演算子

条件式は変数と変数、変数と数値の大小などを比較し、それが正しいかどうかを判定します。
その比較に使われるのが『比較演算子』で、==,!=,<,>,<=,>=などがあります。
==は等しい、!=は等しくない、不等号はそれぞれそのままの意味です。
例えば、A = 0, B = 1, C = 0のとき

真偽(Emueraでは真は1、偽は0を返す)
A == B 偽(false、正しくない)
A == C 真(true、正しい)
A != C
A > B
B > C
B <= A
A >= C

の結果になります。

また、比較演算子を使った条件式の代わりに0かそれ以外の数字を書くことでも
真偽を表すことができます。
この場合、0が偽、それ以外が真です。

否定演算子

Emueraでは、比較演算子の他に『否定演算子』というものがあり、!(感嘆符)で表します。
これには、直後の条件式の結果を逆転させる効果があります。上の例で言えば、
!(A > B)は真、!(A <= C)は偽になります。

条件式の結合

複数の条件式を使う場合は、条件式と条件式の間に&&||を記述します。
&&は「○○かつ××」に使用し、||は「○○または××」に使用します。
例えば、A == 0かつB == 1という条件の場合は

ERB
A == 0 && B == 1  

となります。

A == 0またはB == 0という条件なら

ERB
A == 0 || B == 0  

となります。

もっと複雑に、A == 0B == 1、またはA == 0C == 1なら

ERB
(A == 0 && B == 1) || (A == 0 && C == 1) もしくは  
A == 0 && (B == 1 || C == 1)  

となります。


キャラの能力や素質を判定する

よく使われる条件式の中に、キャラの能力や素質を判断するものがあります。
例えば、調教中のキャラが処女の時、TALENT:TARGET:処女 == 1が成立します。
素質は持っている状態が1、持っていない状態が0となるため、
条件式に単にTALENT:TARGET:処女と書いた場合、「調教中のキャラが処女である」
という条件と同じ意味になります。

逆に、TALENT:TARGET:処女 == 0(あるいは!TALENT:TARGET:処女)と書いた場合には、
「調教中のキャラが処女ではない」という意味になります。

調教中のキャラの従順がLv3以上の時は、ABL:TARGET:従順 >= 3が成立します。
能力や刻印はLvがそのまま数値となります。
体力や経験などレベルで表されない能力は、値がそのまま使用されます。
調教中のキャラのV経験が10以上であるという条件を表すなら、
EXP:TARGET:V経験 >= 10となります。


ランダム(乱数)

RAND:(数値もしくは数値変数)と記述することで、一定の範囲の中から
ランダムで数値を決定することができます。
例えば、A = RAND:10と記述した場合、変数Aは0から9(0からカウントするため上限は9)までの
いずれかの整数になります。また、

ERB
A = 5  
B = RAND:A  

の場合、変数Bは0から4(0からカウントするため上限は4)までのいずれかの整数になります。


分岐

○○が××した時□□を表示する、のような処理を行うのが分岐です。
分岐に使われる構文には主にIFSIFSELECTCASEなどがあります。

IF - ELSEIF - ELSE - ENDIF

もし○○ならば、という処理に最もよく使われる構文です。
IFのリファレンスページ

ERB
IF A == 0  
  PRINTFORML 変数Aは0です。  
ELSEIF B == 0  
  PRINTFORML 変数Aは0でなく、変数Bは0です。  
ELSE  
  PRINTFORML 変数Aは0でなく、変数Bも0ではありません。  
ENDIF  

上がIF - ELSEIF - ELSE - ENDIF構文の基本的な形です。上の構文は

  • もし変数A0ならば(IF A == 0)、『変数Aは0です。』と表示します。
  • 変数A0でなく変数B0ならば(ELSEIF B == 0)、『変数Aは0でなく、変数Bは0です。』と表示します。
  • いずれの条件にも当てはまらないならば(ELSE)、『変数Aは0でなく、変数Bも0ではありません。』と表示します。

このように一つのIF - ENDIF間では上から順に条件式を判定していき、
条件の成立した部分の直後の処理のみを行います。
上の例文では処理の部分が1行ずつしかありませんが、実際には
次のELSEIF,ELSE,ENDIFまでの処理が全て行われます。

ERB
IF 条件式1  
  処理1  
  処理2  
  処理3  
ELSEIF 条件式2  
  処理4  
  処理5  
ELSE  
  処理6  
ENDIF  

(条件式1が成立の時は処理1~3、条件式1が不成立で条件式2が成立の時は
 処理4と5、どちらも不成立の時は処理6のみが行われる)

判定したい条件が3つ以上ある場合は、ELSEIFを増やしていくことができます。

ERB
IF A == 0  
  PRINTFORML 変数Aは0です。  
ELSEIF B == 0  
  PRINTFORML 変数Aは0でなく、変数Bは0です。  
ELSEIF C == 0  
  PRINTFORML 変数A、Bは0でなく、変数Cは0です。  
ELSE  
  PRINTFORML 変数A、B、Cはいずれも0ではありません。  
ENDIF  

判定したい条件が1つの場合は、ELSEIF以下の部分はなくても構いません。

ERB
IF A == 0  
  PRINTFORML 変数Aは0です。  
ELSE  
  PRINTFORML 変数Aは0ではありません。  
ENDIF  

条件を満たさない時何もしない場合、ELSE以下の部分はなくても構いません。

ERB
IF A == 0  
  PRINTFORML 変数Aは0です。  
ELSEIF B == 0  
  PRINTFORML 変数Aは0でなく、変数Bは0です。  
ENDIF  

IFENDIFは絶対に必要です。
ENDIFの書き忘れはエラーの原因になりますので注意しましょう。


SIF

上のIF - ENDIFを簡略化したのがSIFになります。
SIFのリファレンスページ

ERB
SIF A == 0  
  PRINTFORML 変数Aは0です。  

SIFにはENDIFが必要ない、ELSEIFELSEが使用できない、
直後の1行しか実行できない、などの特徴があります。例えば

ERB
SIF 条件式  
  処理1  
  処理2  

と記述すると、条件式の真偽に関わらず処理2は実行されてしまうので
注意しましょう。
2つ以上の処理を行う時は上のIF - ELSEIF - ELSE - ENDIFを使いましょう。

eramakerの仕様 また、eramakerでは
SIF 条件式
  ;コメント
  処理1
のように、SIF の直後にコメント行を入れると、必ず処理1が実行されてしまいますので、これも注意が必要です。
(Emueraではコメント行がきちんと無視されるので、条件式が真であるときのみ処理1が実行されます。)

IFSIFの組み合わせ

ERB
IF 条件式1  
  SIF 条件式2  
    処理1  
  処理2  
  処理3  
ENDIF  

と記述すると、条件式1と条件式2の両方が真である場合は処理1から3を全て実行し、
条件式2だけが成立する時は処理2と3のみを実行します。

ERB
SIF 条件式1  
  IF 条件式2  
    処理1  
    処理2  
  ENDIF  
逆にこう記述すると、条件式1が成立しない時にエラーが発生します。
(条件式1が偽の場合はIF 条件式2の行だけを読み飛ばすので、「ENDIFに対応するIFが無い!」というエラーになる)
SIFの直後の行にIFSIFなどの分岐や反復を行う文は書かないようにしましょう。


SELECTCASE - CASE - CASEELSE - ENDSELECT

IF 文と似た機能を持つ構文としてSELECTCASE - CASE - CASEELSE - ENDSELECTがあります。
1つの数値変数の値によって処理を分岐させる時に使います。
例えば乱数によって処理を分岐させる時に便利な構文です。
SELECTCASEのリファレンスページ

ERB
SELECTCASE A  
  CASE 0  
    PRINTFORML 変数Aは0です。  
  CASE 1  
    PRINTFORML 変数Aは1です。  
  CASEELSE  
    PRINTFORML 変数Aは0でも1でもありません。  
ENDSELECT  

これは、次のIF文と同じ意味を持ちます。

ERB
IF A == 0  
  PRINTFORML 変数Aは0です。  
ELSEIF A == 1  
  PRINTFORML 変数Aは1です。  
ELSE  
  PRINTFORML 変数Aは0でも1でもありません。  
ENDIF  

SELECTCASE文は、CASEの後ろに書かれた数値がSELECTCASEの直後に書かれた数値変数(この場合はA)と等しいかどうかを判定して分岐します。
CASEについては次のような書き方をすることもできます。

ERB
SELECTCASE A  
  CASE 1, 2, 3  
    PRINTFORML 変数Aは1、2、3のいずれかです。  
  CASE 4 TO 9  
    PRINTFORML 変数Aは4以上9以下です。  
  CASE IS >= 50  
    PRINTFORML 変数Aは50以上です。  
  CASE 10 TO 20, IS >= 40  
    PRINTFORML 変数Aは50以上ではありません。  
    PRINTFORML 変数Aは10以上20以下、あるいは40以上(かつ49以下)です。  
  CASEELSE  
    PRINTFORML 変数Aは0以下(上の条件のいずれも満たさない)です。  
ENDSELECT  

CASE X TO Yは、数値変数がX以上Y以下の場合に分岐に入ります。
CASE IS >= Xは、数値変数がX以上の場合に分岐に入ります。
また、CASEに書く条件は、カンマで区切って複数指定することができます。
よってこのSELECTCASE文は、次のIF文と同じ意味を持ちます。

ERB
IF A == 1 || A == 2 || A == 3  
  PRINTFORML 変数Aは1、2、3のいずれかです。  
ELSEIF A >= 4 && A <= 9  
  PRINTFORML 変数Aは4以上9以下です。  
ELSEIF A >= 50  
  PRINTFORML 変数Aは50以上です。  
ELSEIF (A >= 10 && A <= 20) || A >= 40  
  PRINTFORML 変数Aは50以上ではありません。  
  PRINTFORML 変数Aは10以上20以下、あるいは40以上(かつ49以下)です。  
ELSE  
  PRINTFORML 変数Aは0以下(上の条件のいずれも満たさない)です。  
ENDIF  

三項演算子

三項演算子は、正確に言えば分岐構文ではありませんが、IF文から派生してできた演算子なので、ここで説明します。
三項演算子は、次のような形を取ります。

ERB
<代入先変数> = <条件式> ? <真の場合の代入値> # <偽の場合の代入値>  

例えば、変数Aが3以上の時に1、そうでない場合に0を変数Bに代入する操作は、IF文を使うと次のようになります。

ERB
IF A >= 3  
  B = 1  
ELSE  
  B = 0  
ENDIF  
これを三項演算子で表現すると、次のように1行で書けます。

ERB
B = A >= 3 ? 1 # 0  

三項演算子は文字列変数に対しても使用できます。文字列を扱う場合は、三項演算子を \@ ~ \@で囲みます。

ERB
PRINTFORML %CALLNAME:TARGET%は\@ TALENT:処女 ? 処女です。 # 処女ではありません。 \@  

上の文は、TALENT:TARGET:処女が0以外の時に『(TARGETの呼び名)は処女です。』と出力し、
TALENT:TARGET:処女が0の時に『(TARGETの呼び名)は処女ではありません。』と出力します。


三項演算子とSELECTCASEとの組み合わせ

SELECTCASE文に三項演算子を組み込むと、条件式を更に分岐させられます。

ERB
SELECTCASE RAND:(TALENT:処女 ? 3 # 2)  
    CASE 0  
        PRINTFORMW 無条件1  
    CASE 1  
        PRINTFORMW 無条件2  
    CASE 2  
        PRINTFORMW 処女限定  
ENDSELECT  

この構文では、対象の処女素質(TALENT:処女)で条件式を分岐させています。
条件式は、判定結果が真ならRAND:3、偽ならRAND:2と扱われます。
実行すると、CASE 0CASE 1は無条件でRAND抽選の対象になりますが、CASE 2は対象が処女でないとRAND抽選から弾かれます。
このSELECTCASE文は、次のIF文と同じ意味を持ちます。

ERB
IF RAND:3 == 0 && TALENT:0 == 1  
    PRINTFORMW 処女限定  
ELSEIF RAND:2 == 0  
    PRINTFORMW 無条件2  
ELSE  
    PRINTFORMW 無条件1  
ENDIF  

反復

同じ処理を複数回繰り返すときに使うのが反復(ループ処理)です。


REPEAT - REND

REPEATのリファレンスページ

ERB
REPEAT 数式  
  処理  
REND  

REPEAT - REND間の処理を繰り返し実行します。
繰り返す回数はREPEATの直後にある数値、または数値変数に代入されている値です。A + 1などの数式を置くこともできます。
例えば、

ERB
REPEAT 10  
  PRINTFORML あ  
REND  
と記述すると、『あ』が10行表示されます。


COUNT

変数COUNTは、現在までに何回繰り返しを行ったかを格納しています。
REPEAT - REND内の処理を最初に行う時はまだ1回目の繰り返しの途中(1回目の繰り返しが完了していない)なので

ERB
REPEAT 10  
  PRINTFORML 現在{COUNT}回目です。  
REND  

こう記述した場合、表示されるのは0回目から9回目となります。
COUNTがとる値は 0 からREPEATの直後の数値 - 1 までと覚えておきましょう。
また、COUNTに数値を代入するのはエラーの原因となるので注意しましょう。

REPEATIF,SIFの組み合わせ

REPEAT - RENDの間にもIFSIFを使用することができます。

ERB
REPEAT 10  
  IF COUNT == 5  
    PRINTFORML 6回目です?  
  ELSE  
    PRINTFORML {COUNT + 1}回目です  
  ENDIF  
REND  

と記述すると、COUNTが5、つまり6回目のみ最後に『?』が表示されます。
また、REPEAT - RENDの間にもう一つREPEAT - RENDを使用する(入れ子にする)ことは
可能ですが、COUNTの値が2つ目のREPEAT - RENDによって変更されてしまうため
そのままでは正常に動作しません。
REPEAT - RENDを入れ子にしたい場合は、内側のREPEAT - RENDの前後にCOUNTの値を
退避・返還する処理を行うなどの工夫をするか、
後で説明するFOR - NEXTで代用する必要があります。

ERB
;REPEAT を入れ子にする例  
REPEAT 10  
  COUNT:1 = COUNT  
  REPEAT 10  
    処理  
  REND  
  COUNT = COUNT:1  
REND  

CONTINUEBREAK

REPEAT - REND間で、以降の処理を行わずに次の繰り返しに入る場合にはCONTINUEを、
以降の処理を行わず、繰り返し自体を終了させる場合にはBREAKを使用します。

ERB
REPEAT 10  
  A = COUNT  
  IF A == 5  
    CONTINUE  
  ENDIF  
  PRINTFORM {A}:  
REND  

これを実行すると、COUNTが5の時にCONTINUEが実行されるので、実際に表示されるのは

0:1:2:3:4:6:7:8:9:  

となります。また、

ERB
REPEAT 10  
  A = COUNT  
  IF A == 5  
    BREAK  
  ENDIF  
  PRINTFORM {A}:  
REND  

を実行すると、COUNTが5の時にBREAKが実行されREPEAT - RENDから抜けるので、実際に表示されるのは

0:1:2:3:4:  

までになります。


FOR - NEXT

FOR-NEXTのリファレンスページ

ERB
FOR <カウンタ数値変数>, <数式>, <数式>[, <数式>]  
  処理  
NEXT  

REPEAT - RENDの機能強化版がFOR - NEXTです。
例えば、次の2つのスクリプトは全く同じ動作をします。

ERB
FOR COUNT, 0, 10  
  PRINTFORML {COUNT}回目  
NEXT  
ERB
REPEAT 10  
  PRINTFORML {COUNT}回目  
REND  

FORの直後の<カウンタ数値変数>REPEATでいうCOUNTに相当します。
REPEATでは繰り返しの回数を数える変数はCOUNTに固定されていましたが、FORではこの変数を好きな変数に設定することができます。
カウンタ変数を別にすることで、REPEATでは面倒だったループの入れ子を簡単に実現できます。

ERB
;入れ子の例  
FOR A, 0, 10  
  FOR B, 0, 10  
    処理  
  NEXT  
NEXT  

FORの後ろに来る2番目の<数式>は、繰り返しを始める<カウンタ数値変数>の値を設定します。
3番目の<数式>で、繰り返しを終わる<カウンタ数値変数>の値を指定します。
例えば、

ERB
FOR COUNT, 3, 8  
  PRINTFORM {COUNT}:  
NEXT  

を実行すると、

3:4:5:6:7:  

と表示されます。

FORの後ろの4番目の<数式>は、ループを1回繰り返すごとにカウンタ変数に加算される値を設定できます。省略すると自動的に1が設定されます。
例えば、

ERB
FOR COUNT, 0, 10, 2  
  PRINTFORM {COUNT}:  
NEXT  

を実行すると、

0:2:4:6:8:  

と表示されます。
なお、REPEAT - RENDと同様にCONTINUEBREAKも使用できます。


WHILE - WEND

WHILE-WENDのリファレンスページ

ERB
WHILE 条件式  
  処理  
WEND  

条件式が真である間、ループを繰り返します。
例えば、次のスクリプトは「あ」を10行表示します。

ERB
A = 0  
WHILE A < 10  
  PRINTFORML あ  
  A += 1  
WEND  

このとき、A += 1の行を書き忘れると、変数Aの値は0のままになってしまうので、
A < 10はいつまでも真のままとなり、無限ループに陥ってしまいますので注意が必要です。
WHILE - WENDでもCONTINUEBREAKを使用できます。


DO - LOOP

DO-LOOPのリファレンスページ

ERB
DO  
  処理  
LOOP 条件式  

条件式が真である間、ループを繰り返します。
WHILE - WENDとの見た目の違いは条件式の位置が違う程度ですが、最初の繰り返しが必ず実行されるという特徴があります。
次の2つのスクリプトを見比べてみてください。

ERB
A = 0  
WHILE A < 0  
  PRINTFORML あ  
WEND  
ERB
A = 0  
DO  
  PRINTFORML あ  
LOOP A < 0  

WHILE文はループの最初に条件式が真かどうか評価するので、この場合はPRINTFORMLは一度も実行されません。
一方DO - LOOPはループの最後に条件式を評価するので、この例ではPRINTFORMLが1回実行され、その後に式が評価されてループを抜けます。

また、DO - LOOP内でCONTINUE文を呼ぶと、DOではなくLOOPに飛ぶことにも注意してください。
次のスクリプトは(DO → CONTINUE → DOではなく)DO → CONTINUE → LOOP 0の順に実行されるので、無限ループにはなりません。

ERB
DO  
  CONTINUE  
LOOP 0  

関数と関数呼び出し

ここからは主に機能パッチやバリアントを作成する際に使う範囲となります。

関数とは

いくつかの決まった処理を行わせたい時、それを予め別の場所に記述しておいて、
任意の場所から使えるようにしたものを関数と言います。
例として、変数Aの値を10倍にする関数を作ってみましょう。

ERB
@A_TEN_TIMES  
A = A * 10  

@の後に半角英数と_(アンダーバー)で関数の名前を付けることができます。
それ以降の処理が関数で行う内容となります。

ERB
A = 0  
CALL A_TEN_TIMES  
PRINTFORML 変数Aは{A}です。  

A = 5  
CALL A_TEN_TIMES  
PRINTFORML 変数Aは{A}です。  

作った関数を利用する(呼び出す)にはCALL <関数名>と記述します。
この結果、上は『変数Aは0です。』下は『変数Aは50です。』と表示されます。
また、関数を呼び出すのにJUMP <関数名>を使うこともあります。
CALLJUMPの違いは関数での処理を実行した後、元の場所に戻るかどうかで、
CALLは戻る、JUMPは戻らないようになっています。

なお、同じ名前の関数が複数ある時はどれか1つだけが呼び出されます(イベント関数という特殊な関数を除く)。
関数の名前は他と同じにならないよう注意しましょう。


RETURNと戻り値

ある条件を満たした時、関数を途中で終わらせたいという場合は
RETURN <数値> と記述します。

ERB
@TEST  
SIF A == 0  
  RETURN 0  
A = A * 5  

この場合、関数@TESTを呼び出した時Aが0なら何も行われず、そうでなければAが5倍されます。
また、RETURN文で関数を終了し元の場所に戻ってくると、変数RESULTRETURNで指定された数値に書き変えられます。
この時、RESULTを関数の 戻り値(返り値) といいます。
例えば、

ERB
@TEST2  
IF A == 0  
  RETURN 0  
ELSEIF A == 1  
  RETURN 1  
ELSEIF A == 2  
  RETURN 2  
ELSE  
  RETURN 9  
ENDIF  
という関数を作り、別の場所から呼び出すと

ERB
A = 0  
CALL TEST2  
PRINTFORML {RESULT}  

A = 2  
CALL TEST2  
PRINTFORML {RESULT}  

A = 3  
CALL TEST2  
PRINTFORML {RESULT}  

上から順に0,2,9が表示されます。
なおEmueraでは、RETURN文に数値変数や数式を指定できるほか、カンマで区切って複数の戻り値を指定することもできます。


引数

Emueraでは、関数は 引数 を取ることができます。引数とは、関数をCALLで呼び出す時に関数に渡すことのできる変数です。
上に書いた関数@TEST2を、引数を取るように書き換えたのが次の例文です。

ERB
@TEST2, ARG  
IF ARG == 0  
  RETURN 0  
ELSEIF ARG == 1  
  RETURN 1  
ELSEIF ARG == 2  
  RETURN 2  
ELSE  
  RETURN 9  
ENDIF  

呼び出すときは次のようにします。

ERB
CALL TEST2, 0  
PRINTFORML {RESULT}  

CALL TEST2, 2  
PRINTFORML {RESULT}  

CALL TEST2, 3  
PRINTFORML {RESULT}  

CALL TEST2, 0を実行すると、ARGに0が代入され、関数内でARGを参照することができます。
引数は複数取ることができ、そのような場合はARG, ARG:1, ARG:2, …のように定義します。

ERB
@TEST3, ARG, ARG:1, ARG:2  
(略)  
ERB
CALL TEST3, 0, 7, 3  

引数には文字列変数も取ることができ、その場合は ARGS を使います。


ローカル変数

A,Bなどの一文字変数やCOUNTなど多くの変数は、プログラム全体で同時に一つの変数を共通で使用します。
ですが、それが原因でバグが発生することがあります。

ERB
@MAIN  
FOR COUNT, 0, 10  
  CALL FUNC  
NEXT  

@FUNC  
FOR COUNT, 0, 3  
  (何か処理)  
NEXT  

上の例文で@MAIN関数を実行すると、@FUNCが呼ばれるたびにCOUNTが3にセットされるので、無限ループに陥ります。
この例では@FUNC内のFORループのカウンタ変数をCOUNT:1にすれば問題は解決しますが、
1つのバリアント内で使われる関数は1000個を軽く超えるので、どこかで必ずこういった問題が発生します。

そこで、ある関数の中でしか使えない変数(ローカル変数)を用意すれば、この問題は解決するはずです。
そのローカル変数がLOCALLOCALSです。次の例を見てください。

ERB
@EVENTFIRST  
  LOCAL = 123  
  CALL FUNC001  
  PRINTFORML {LOCAL}  

@FUNC001  
  LOCAL = 567  
  RETURN  

一見するとLOCALという同じ変数に数値を代入しているように見えますが、
@EVENTFIRSTの中で使っているLOCAL」と「@FUNC001の中で使っているLOCAL」は別物として扱われるので、
PRINTFORML文の結果は「123」と出力されます。

なお、LOCALSLOCALの文字列変数バージョンです。
先に説明したARGARGSもローカル変数として扱われます。


LOCAL, ARG の初期化タイミングに注意

他の言語でプログラミングをしたことのある人には特に注意して頂きたいのですが、
LOCALARGは関数が呼び出されたタイミングで初期化されない
関数が呼び出されるたびに同じLOCAL,ARGを使いまわす
の2点に気をつける必要があります。
この特徴は、関数の再帰などを利用した場合に注意が必要です。

ERB
@SAMPLE  
LOCAL += 1  
IF LOCAL < 10  
  CALL SAMPLE  
ENDIF  

上のコードは、プログラミング経験のある人からしてみれば
LOCALはローカル変数で呼び出し時に0に初期化されるので、LOCALは1のままで無限ループになり、そのうちスタックが溢れるはず」
と思われるかもしれません。しかし実際に@SAMPLEを呼び出すと、
最初の外部からの呼び出しでは SAMPLE が9回再帰呼び出しされ、2回目以降は再帰呼び出しがされません。
なぜかといえば、最初の呼び出しでLOCALに1が代入されると、次に再帰で呼び出された時にLOCALが0で初期化されず、1という値が保持されるからです。
また再帰が完了して@SAMPLE関数から抜けた後も、LOCALの最終的な値である10が保持され続けるので、これ以降は外部から呼び出されても再帰はされません。

ARGについても同様です。

ERB
@SAMPLE2, ARG  
SIF ARG >= 10  
  RETURN  
CALL SAMPLE2, ARG + 1  
PRINTVL ARG  

上のコードを書き、CALL SAMPLE2, 0 と呼び出すと''10が10回表示されます''。

プログラマ向けの話 Emueraの内部の話になりますが、`LOCAL`はEmuera内部で「`関数名@LOCAL`」という名前の変数として定義されています。
言い換えれば、erabasicのローカル変数は、特定の関数の中でしか参照できないグローバル変数(のようなもの)ということになります。
C# でいえば次のようなコードに相当します。
class SampleClass  
{  
  int SAMPLE@LOCAL = 0; // グローバル変数として宣言  

  void SAMPLE()  
  {  
    SAMPLE@LOCAL += 1;  
    if (SAMPLE@LOCAL < 10)  
    {  
      SAMPLE();  
    }  
  }  
}  

式中で使える関数

erabasicにおいて、値を返す命令の戻り値はRESULTを経由して受け取ります。
例えば、与えられた数式の絶対値を返すABSという命令を使って、
変数Aの絶対値をLOCALに格納するには次のように記述します。

ERB
ABS A  
LOCAL = RESULT  

これに対し、ABSという名前の「式中で使える関数(以下「式中関数」と書きます)」を使うと、上のスクリプトを次のように書くことができます。

ERB
LOCAL = ABS(A)  

「式中関数」の名前通り、代入式の中から直接関数を呼び出し、RESULTを介さずに戻り値をLOCALに代入することができます。
式中関数では、引数を(A)のように丸括弧で囲んで呼び出します。
引数が複数ある場合は(A, B, C)のように丸括弧の中でカンマで区切って書きます。
逆に引数がない場合は()と丸括弧だけを書きます。引数がなくても丸括弧は省略できません。
ABSのリファレンスページ

文字列を返す命令でも、同様の書き方ができます。

ERB
STRLENS STR:0  
IF RESULT > A  
  SUBSTRING STR:0, A, 1  
  LOCALS:0 = %RESULTS:0%  
ENDIF  
ERB
IF STRLENS(STR:0) > A  
  LOCALS:0 = %SUBSTRING(STR:0, A, 1)%  
ENDIF  
上の2つの例文は、同じ動作をします。
式中関数の一覧は命令・式中関数のページで確認できます。


式中関数を自分で定義する

式中関数は自分で定義することができます。
関数を定義する@行の直後に#FUNCTIONと書き、RETURNRETURNFに置換するだけで、その関数は式中関数になります。

ERB
;下の行は @TEST2, ARG と書いてもよいが、慣習的にこう書くことが多い  
@TEST2(ARG)  
#FUNCTION  
IF ARG == 0  
  RETURNF 0  
ELSEIF ARG == 1  
  RETURNF 1  
ELSEIF ARG == 2  
  RETURNF 2  
ELSE  
  RETURNF 9  
ENDIF  

呼び出すときは次のようにします。

ERB
PRINTFORML {TEST2(0)}  
PRINTFORML {TEST2(2)}  
PRINTFORML {TEST2(3)}  

文字列を返す式中関数を作りたい場合は、#FUNCTIONSと書きます。
ただし、RETURNFの書き方が他の命令(PRINTFORMなど)とは異なるので注意してください。

関連ページ:ユーザー定義の式中関数


ラベルとキー入力

主に選択肢による分岐で使用されるのがラベルとキー入力です。

ERB
PRINTFORML 選択してください  
PRINTFORML [0] 選択肢1  
PRINTFORML [1] 選択肢2  
;Emueraは上のような[ ]で囲まれた数字を見つけると自動的にボタンに変換してくれます  

$INPUT_LOOP  
INPUT  

IF RESULT != 0 && RESULT != 1  
  GOTO INPUT_LOOP  
ELSEIF RESULT == 0  
  処理1  
ELSEIF RESULT == 1  
  処理2  
ENDIF  

INPUTはキー入力(またはボタン操作)を待ち、入力された数値をRESULTに格納します。
この場合、0を入力すれば処理1、1を入力すれば処理2を実行します。
0でも1でもない数値を入力した場合、RESULT != 0 && RESULT != 1
成立するためGOTO INPUT_LOOPが実行されます。
GOTO (ラベル名)$(ラベル名)の処理に移動するもので、CALLJUMP@との
関係に似ていますが、GOTO$に関しては同じ関数内にある必要があります。
GOTO INPUT_LOOP$INPUT_LOOPに移動すると再びINPUTを実行するため、
この一連の処理は0か1かを入力するまで繰り返されることになります。

また、一つの関数内で複数の$GOTOの組み合わせを使用すると
IFに対応しないELSEIF,ELSE,ENDIFが~』というエラーが発生することがあります。
この場合、2つ目の入力処理を別の関数に移すなどの工夫をしましょう。


その他注意点など

キャラの追加と削除

キャラの追加と削除には、ADDCHARADELCHARAを使用します。
ADDCHARAのリファレンスページ DELCHARAのリファレンスページ

ERB
ADDCHARA 1  
ADDCHARA 5  
ADDCHARA 9  

Emueraでは次のように書くことができます。

ERB
ADDCHARA 1, 5, 9  

ADDCHARAではCSVにあるキャラ番号が参照されます。

ERB
DELCHARA 3  
DELCHARA 1  

DELCHARAではキャラ番号(NO)ではなく、キャラの登録番号(ID)が参照されます。
ここまでの処理でキャラ番号(NO)、1(ID=1)、5(ID=2)、9(ID=3)のキャラが追加され、
次に登録番号(ID)3番、つまりキャラ番号(NO)9のキャラが削除、
その後登録番号(ID)1番、つまりキャラ番号(NO)1番のキャラが削除され、
キャラ番号(NO)5番のキャラのみが残る状態になります。
DELCHARAを続けて使用する際には、削除された登録番号より後のキャラは
それぞれ前に詰められることに注意しましょう。

また、キャラの追加・削除をする場合は調教中のキャラ、助手などの状態を
確認しましょう。例えば助手をやっていたキャラがDELCHARAで削除されても
助手の登録番号を保存しているASSIは変化しません。しかし全体の登録番号は
前にずれてしまうため、助手になる条件を満たしていないキャラが助手に
なってしまうこともあります。


グラフ表示

BARBARL)を使用することで数値の表示を視覚的に行うことができます。
BAR (数値or変数),(数値or変数),(グラフの長さ)のように記述し

ERB
A = 80  
B = 100  
BAR A, B, 10  

では

[********..]  

と表示されます。
Aに現在の値、Bにその最大値を入れることで、現在の値が最大値の
どのくらいの割合かを示す際によく使用されます。
BARLでは表示後に改行されることも覚えておきましょう。


小数の乗算

erabasicでは変数などは全て整数で処理されますが、例外として
TIMESを使用することで小数の計算を行うことができます。
TIMESのリファレンスページ

ERB
A = 1000  
TIMES A, 1.5  

これで変数A1000×1.51500となります。
なお、TIMESを使用した結果が小数になっても整数に丸められます。


その他の命令

WAIT…入力待ちのみを行います。RESULTに値は格納されません。
QUIT…eramakerを終了させます。主にゲームオーバー時などに使用します。


ビット演算について

anonymous>よう俺。コンフィグのところでよく使われてる&が一つしかない文ってどういう意味なんだ? &&の間違い?  
anonymous>ああ、それはビット演算ってやつだな。[ここ](../eramaker/variables.md)にちゃんと載ってる  
anonymous>一番下のやつな  
 ---------------------------------------  
anonymous>……よし、さっぱりだ  
anonymous>だろうと思った。二進数なんて普段使わないだろうしな  
anonymous>そもそも二進数?それおいしいの?な俺に隙は  
anonymous>仕方ないな、まずはそこから説明してやろう  

二進数

二進数とは

その方面について勉強している人でもなければ馴染みは薄いと思われる
二進数ですが、ビット演算を利用するなら是非覚えておきましょう。

日頃よく使われる数字、0,1,2,...,9,10,11,...99,100,101,...
これらは十進数と言われます。そーなのかー
他にも○進数と呼ばれる数値の表現はありますが、その見分け方として
桁上がりするタイミングで見るのを覚えましょう。
十進数なら0,1,2,3,4,5,6,7,8,9,10,11,...というように
9の次で二桁になります。10から次の桁に進むので、十進数ということですね。
つまり二進数なら2で次の桁に進みます。具体的には1の次が「10」という表記になります。
十進数の「2」と二進数の「10」は同じ数値を表すということですね。
十進数の「10」との混乱を避けるため、二進数の「10」は「イチゼロ」と呼ぶことが多いです。

   0 - 0  
   1 - 1  
  10 - 2  
  11 - 3  
 100 - 4  
 101 - 5  
 110 - 6  
 111 - 7  
1000 - 8  

上に並べた9つの数字は同じ数値を二進数と十進数で表したものです。
右の列が馴染み深い十進数ですね。
一方の左、二進数の列を見てみると2,4,8と2のX乗の数になるごとに
桁が増えているのがわかると思います。
これが二進数の表し方の基本となります。

二進数については

  • 全ての桁は常に0か1である
  • 2のX乗ごとに桁が増える

この二点を覚えておきましょう。


よくわかる二進数→十進数の直し方

桁が2のX乗に云々というのでは難しいので、二進数を十進数に直す時は
こう見るといいでしょう。

例)

1011011→(64*1+32*0+16*1+8*1+4*0+2*1+1*1)
    →(64+16+8+2+1)→91


anonymous>こんなものか  
anonymous>んー……まあ何となくわかった……かな  
anonymous>しかし、これがコンフィグなんかとどう関係するんだ?  
anonymous>うむ。eraのコンフィグってのはこの機能を使う・使わないで設定するよな?  
anonymous>ああ、そうだな。各項目にONとかOFFとか出てるしな  
anonymous>二進数は1か0しか使わない、これはさっき理解したよな?  
anonymous>ああ、そうだったな  
anonymous>ということは?  
入室 anonymous anonymous!anonymous@anonymous.  
anonymous>にんっ  
anonymous>しんっ  
anonymous>すうっ  
anonymous>なるほど。各機能のONに1を、OFFに0を対応させて見るわけか  
anonymous>そういうことだ  
anonymous>次はそれを実際にどう書くかだな  

ビット演算

ビット演算とは

前項で二進数が各桁1か0で表される数値であることを勉強しました。
ビット演算ではこの各桁が1であるか0であるかを判定することによって
条件分岐に使用したりします。

ERB
FLAG:1 = 0  
FLAG:2 = 1  

IF FLAG:1 & 1  
    PRINTFORML FLAG:1はONです。  
ELSE  
    PRINTFORML FLAG:1はOFFです。  
ENDIF  
IF FLAG:2 & 1  
    PRINTFORML FLAG:2はONです。  
ELSE  
    PRINTFORML FLAG:2はOFFです。  
ENDIF  

&はその前後の値を二進数に直し、同じ桁が1であるものを1、それ以外の
桁を0として計算し、それを並べた結果を十進数で表します。
FLAG:1 & 1を見る時、まずFLAG:1の値は0、二進数でも0です。
それと比較する1は二進数でも1ですから、01で一致しません。
つまり、FLAG:1 & 10となります。
一方FLAG:2 & 1の方では、FLAG:21も二進数で1となります。
どちらも一桁目が1なのでFLAG:2 & 11となります。
これを上のIF文に当てはめると

ERB
IF 0  
    PRINTFORML FLAG:1はONです。  
ELSE  
    PRINTFORML FLAG:1はOFFです。  
ENDIF  
IF 1  
    PRINTFORML FLAG:2はONです。  
ELSE  
    PRINTFORML FLAG:2はOFFです。  
ENDIF  

となり、表示される結果はこのようになります。

FLAG:1はOFFです。  
FLAG:2はONです。  

複数の条件を判定する

上の例ではFLAG:1,FLAG:2それぞれに1つずつの条件を判定する
処理を説明しましたが、ビット演算を利用すると一つのフラグで複数の
条件を判定させることができます。

ERB
IF FLAG:1 & 1  
    PRINTFORML 条件1はONです。  
ELSE  
    PRINTFORML 条件1はOFFです。  
ENDIF  
IF FLAG:1 & 2  
    PRINTFORML 条件2はONです。  
ELSE  
    PRINTFORML 条件2はOFFです。  
ENDIF  
IF FLAG:1 & 4  
    PRINTFORML 条件3がONです。  
ELSE  
    PRINTFORML 条件3がOFFです。  
ENDIF  

このようなIF文がある時、FLAG:1の値によって結果はどうなるでしょうか。
まずFLAG:10の時、先の例でもあったようにFLAG:1 & 10です。
FLAG:1 & 2を見ると、0(00)2(10)でどちらも1になる桁はなく
やはり0になります。FLAG:1 & 40(000)4(100)0ですね。

次にFLAG:11の時、これも先の例の通りFLAG:1 & 11です。
FLAG:1 & 21(01)2(10)なので0
FLAG:1 & 41(001)4(100)0になります。

FLAG:12の時、FLAG:1 & 12(10)1(01)0です。
FLAG:1 & 22(10)2(10)で二桁目がどちらも1になりました。
このため、FLAG:1 & 2は二進数で10、つまり2になります。
FLAG:1 & 42(010)4(100)0になります。

FLAG:13の時、FLAG:1 & 13(11)1(01)で一桁目が一致し
1になります。FLAG:1 & 2では3(11)2(10)で二桁目が一致し
2になります。FLAG:1 & 43(011)4(100)0です。

FLAG:13の時の結果表示はこのようになります。

条件1はONです。  
条件2はONです。  
条件3はOFFです。  

このようにビット演算を利用することで複数の条件の組み合わせを
一つのフラグで表現することができます。
ただし、判断できる条件はON/OFFやあり/なしなど二択のものに
限られることに注意しましょう。
また、条件一つ一つの判断を行う式で&の後に使う数値は2のX乗の値を
使います。理由は後の項で説明します。


ビット演算で使う値を設定するには

ここまではビット演算での判定を行う部分について説明してきました。
しかし、実際に処理中でビット演算を利用するには判定に使われる
値を動かす方法も必要となってきます。
他の処理のようにFLAG:1 += 1FLAG:1 -= 2と計算を行っても
いいのですが、この方法だと問題が発生する場合があります。

ERB
FLAG:1 = 0  

@CONFIG_1  
PRINTFORML [0]機能1をONにする  
PRINTFORML [1]機能1をOFFにする  

INPUT  

IF RESULT == 0  
    PRINTFORML 機能1をONにします。  
    FLAG:1 += 1  
ELSEIF RESULT == 1  
    PRINTFORML 機能1をOFFにします。  
    FLAG:1 -= 1  
ENDIF  


@PRINT_CONFIG  
SIF FLAG:1 & 1  
    PRINTFORML 機能1がONです。  
SIF FLAG:1 & 2  
    PRINTFORML 機能2がONです。  
SIF FLAG:1 & 4  
    PRINTFORML 機能3がONです。  
;・・・(以下略)  

このような処理があった場合、「機能1をONにする」というコマンドを
2回以上実行してしまうとFLAG:1の値が2,3,4,...と増え続けるため
正しく動作しない可能性があります。

そこで、ビット演算の判断用変数の計算に使われるのが|です。
|は前後の値を二進数に直した時、同じ桁同士でどちらか片方でも
1となる桁を1にする計算を行います。
例えば、5(101) | 3(011)なら三桁とも1となるので
結果は二進数で111、つまり十進数だと7になります。

ERB
A = 5  
B = 3  

C = A | B  

PRINTFORML 変数Cは{C}です。  

変数Cは7です。  

また、A = A | BA |= Bと書くこともできます。
ビット演算に使用する変数は元のものに上書きすることが多いため
ぜひ覚えておきましょう。

では逆に、機能をOFFにしたりする時にはどうすればいいでしょうか。
上の例で、今度は機能1・2・3全てONの状態とし、そこから機能2を
OFFにする方法を考えてみましょう。
まず、機能1~3がONということはFLAG:1 & 1FLAG:1 & 2
FLAG:1 & 40でない、つまりFLAG:1を二進数で表した時の下三桁は
111となっています。
ここから機能2をOFFにするには、他の桁はそのままでFLAG:1 & 20
つまり下から二桁目のみを0にすればいいということになります。
二桁目を0にするなら二進数の10、つまり十進数の2を引けばいいと
考えることもできますが、それでは先の例のように2回以上行われた時に
数値がおかしくなってしまいます。

そこで再び使うのが&です。
7(111) & 5(101)の結果は二進数で101となり、他の桁を変えずに
二桁目だけ0にすることができました。

機能1・2がONの状態から機能2をOFFにするには、011001にする
必要がありますが、これも3(011) & 5(101)で実現できます。

それでは、ここで&@の後に持ってきた5(101)はどういう値なのでしょうか。 二進数で見ると、0にするべき二桁目以外が1の数値、と言えますね。 これは切り替える機能の総数が増えても同じことで、5個の機能の中で 4つ目をOFFにするなら10111、10個の機能の中で3つ目をOFFにするなら1111111011&`の後に持ってくればいいことになります。

これらを踏まえて先の例のON/OFF部分だけを書き換えてみると

ERB
@CONFIG_1  
PRINTFORML [0]機能1をONにする  
PRINTFORML [1]機能1をOFFにする  

INPUT  

IF RESULT == 0  
    PRINTFORML 機能1をONにします。  
    FLAG:1 |= 1  
ELSEIF RESULT == 1  
    PRINTFORML 機能1をOFFにします。  
    FLAG:1 &= 6(→110→2+4)  
ENDIF  

となります。  
(FLAG:1 &= 6 は FLAG:1 = FLAG:1 & 6 と同じ処理になります)  

anonymous>ということだ。わかったか?  
anonymous>………………  
anonymous>……まあ、実際わかるように説明できた自信もないからな  
anonymous>あとは自力でやってもらうしかないな  
anonymous>説明を見ながら自分で組んでみたり、使われてるバリアントやパッチの構文を追ってみたり、方法はあるんだ  
anonymous>うーむ……  
退出 anonymous 霊夢様は俺のy……主 anony!anony@anony.  
anonymous>橙曰く、分からなかったら人肉、じゃない人に聞くだな  
anonymous>IRCでもスレでも、奇特な職人様がいれば答えてくれるだろう  
anonymous>そうだな……まあ何とか頑張ってみるよ  
anonymous>おう。何かは知らんが完成待ってるよ  

ERB編集における代表的なエラー

以下、eratohoやeramakerに依存した解説が多い点に注意

この項ではeramakerおよびEmueraで利用されるERBファイルの作成や改造にあたり様々なエラーや不具合が発生するということをここで晒して、後進の人たちの参考にしょうというものである。
なお、基本的にはeramaker基準ではあるが、Emueraでのエラーも記述する。

なお、開発用ツールまとめで紹介されている各種ツールを利用すると基本的なミスを発見しやすくなるので是非導入しておこう。ただしTALENTの参照ミスや死に分岐など一部のエラーは発見できないので油断は禁物、自分の目で見直してしっかり確認するようにしたい。
また、前もって上のページで紹介されている各種構文講座を読んで内容を理解しておくと初歩的なミスを未然に防げるだろう。

以下の例などで[EOF]はそこでファイルが終わってることを示し、[CR]は改行を示し、は全角の空白(スペース)を示す。いずれもここの字面どおりに入力すればいいものというわけではないので注意。またメモ帳は特に[CR]が分からないことに注意のこと。


ループの閉じ忘れ

適切にインデントを設定していないことによりみずらいソースを記述してしまうと往々にしてこういう事態になってしまう。
具体的には、

ERB
IF A == 2  
    IF B == 3  
    IF C == 4  
        PRINTL Aが2でBが3でCが4です。  
    ELSE  
        PRINTL Aが2でBが3ですがCは4ではないです。  
    ENDIF  
    PRINT Aが2でBが3ではないです。  
ELSE  
ENDIF  

上の例では3つ目のIFのインデントが適切でないため、ENDIFがひとつ不足してしまっている。これを実行すればエラーで動かなくなってしまう。
つまり、人間は往々にしてミスしやすいので見やすいようにしっかりインデントをしておこうということである。


ループの閉じすぎ

ENDIFが足りないから文句言われるのならば、いっぱい置けばいいじゃないなんてことももちろんない。ちゃんと適切に配置すべきである。

ERB
IF A == 2  
    IF B == 3  
        PRINTL Aは2でBは3です。  
    ENDIF  
    ENDIF  
ENDIF  

これなら大丈夫だろ?と思われるかもしれないが、eramaker(もしくはEmuera)内部ではつじつまが合わないことが起こると予期せぬ挙動により変なところでエラー落ちしたりフラグを破壊したりとその後の構文が全て実行されなくなったりとろくなことにならない。


SIF文にENDIFを付けてしまいました

SIF文はその直後の1行だけで完結するのでENDIFで閉じる必要はない。これはむしろ、IF文として作ったあとにそれをSIF文に直したときにその後方のENDIFを消し忘れておこってしまうケースがありうる。

ERB
 SIF A == 2  
     PRINTL Aは2です。  
 ENDIF  

まあ、最後にもう一度見直すとか何らかのチェッカーを通せば分かると思われるけど。ともかく、注意すべきである。


SIF文に複数の行を収めようとしてしまう

前述の通りSIF文はその直後の1行だけで完結する。つまりIF~ENDIFと同じノリで複数行をSIF文で分岐させることはできない。これはSIF文で作った分岐に新たに処理を加える際にやらかしやすい。

ERB
 SIF TALENT:MASTER:117  
     A += 100  
     B += 100  

上記の例の場合、B += 100TALENT:MASTER:117の有無に関係なく必ず実行されてしまう。チェッカーの類では検出出来ないミスなので十分注意したい。

ERB
 SIF TALENT:MASTER:117  
     A += 100  
 SIF TALENT:MASTER:117  
     B += 100  

このように書けば一応意図通りに実行されるが、それなら最初からIF文を使って書いた方が早いしわかりやすい。 そもそも、SIF文を使わないことが最善の対策だろう。


SIFの直後にコメントを置くのは危険

SIF文はその分岐が真ならばその直後の一行を実行するというものだが、Emueraの場合その直後がコメント行ならそれをカウントせず、その次の行以降の最初に来る非コメント行を実行する。 だが、eramakerは直後のコメント行を「実行」してしまうため、両者では挙動が異なる。それに気をつけておかないといけないので注意すること。コメントに関してはできるならSIFの前の行に付けておくといいだろう。


ELSEIFELSEとしてしまう/ELSE IFとしてしまう

IF~ELSE~ENDIF文においてときどき以下のようなことを記述してしまってエラーを出すことがあるかもしれない。

ERB
 IF TALENT:120  
     PRINTL オトコですぜ。  
 ELSE TALENT:121  
     PRINTL ふたなってます。  
 ELSE IF TALENT:122 || TALENT:123  
     PRINTL そのうち生えるかも?  
 ENDIF  

さて、上の例で2つのELSEはいずれもエラーだったりする。最初のはIFを忘れた例。二番目のはELSEIFが分離しちゃった例。
ELSEには条件文をつけられない仕様なので、どちらも正常に判定されない。
いずれにせよこういうことがないようにすべき。


お前はもう死んでいる分岐

IF~ELSE~ENDIF構文においてやりかねない過ちのひとつが「死に分岐」である。それ自体はエラー落ちしたりすることはないかもしれないがなるべくならそういうことはないほうがいい。

ERB
 IF TALENT:120 == 1 || TALENT:121 == 1  
     PRINTL ペニスあるぜ!  
 ELSEIF TALENT:120 == 1  
     PRINTL オトコだぜ!  
 ENDIF  

さて、上の例でELSEIF TALENT:120 == 1の行が成り立って実行されることは絶対にない。つまりこの部分は「死に分岐」である。
なぜなら、TALENT:120が存在する時点で最初のIFが実行されてしまい、次のELSEIFの判定が実行されることはないからだ。

ERB
 IF TALENT:120 == 1 && TALENT:121 == 1  
     PRINTL オトコだしふたなりだぜ。  
 ELSEIF TALENT:120 == 1  
     PRINTL オトコだぜ!  
 ENDIF  

では上のようにしたら?
もちろん、これなら下のELSEIFの条件は「死に分岐」ではなくなる。だが…、オトコでなおかつふたなりっていったいなに?これは仕様上ありえない条件なので最初のIF文が「死に分岐」となっている。
「オトコ」「ふたなり」が両立する世界なら「死に分岐」ではないので、こっちのに関しては背景設定や世界観などを考慮しなければならないがこういう「死に分岐」にも注意すべき。


助手を見る前にまずは助手が存在するかを確かめよう

erabasicにおいて、キャラ登録番号は全て0を含む自然数であり負の数はありえない。
ただしASSIが存在しない場合、空白は代入できないので一時的に-1が代入される。
そのため、助手がいない状態で助手の番号や状態を確認しようとすると第1引数(-1)はキャラ登録番号の範囲外ですと表示されエラーになってしまう。
何らかの形で助手を参照する場合、必ずその条件式の前にIF ASSI > 0という条件式を組み、助手が存在しない場合を弾くようにしよう。

ERB
 IF ASSI >= 0  
     SIF TALENT:ASSI:0 == 1  
         PRINTL 助手は処女です。  
 ENDIF  

また口上テンプレでは特定のキャラが助手をしているという条件式で助手の番号をY1と仮定してあることがある。
上記の通りASSIには自然数しか入れないので、IF ASSI:NO == Y1という式があるとエラーになってしまう。
通常この部分はコメントアウトしてあるはずなので、助手番号を指定しない場合は行頭の;を外さずそのままにしておこう。


eramakerは短絡評価なんてしない

EmueraにおいてはIF文の短絡評価(前の条件が偽の場合、それ以降の条件判定を行わない)が実装されているが、eramakerには実装されていない。 なので少々回りくどい構文を組む必要がある。特に便利な拡張文法を使えるEmuera専用バリアントで製作したあとにeramakerバリアントで製作すると往々にしてこのあたりをすっとばしてしまいがち。

ERB
 SIF ASSI >= 0 && TALENT:ASSI:0  
     PRINTL 助手は処女です。  

上の例はEmueraならばASSI-1(存在しない)場合、IFが成り立たないことが明白なのでその後方のTALENT:ASSI:0を評価せず無視する。そのため存在しない助手の能力を参照しようとして起きるエラーにより止まることはない。
だが、eramakerの場合IF文の条件はみんなチェックしてしまうので、助手が存在しないときも助手のTALENTを参照しようとしてエラーが発生してしまう。
そのため前項で説明したようにまず助手の有無を判定し、助手が存在する場合のみTALENTなどを参照するという手順が必要。


!= 0は-1も含まれる

!=は『○○を含まない』という条件式で、つまりその数値以外の全数値が真になる。
実はこの時負の値も範囲に含まれているので、例えばASSI != 0(助手が「あなた」ではない)ならば助手がいない時(ASSI == -1)も真と判定されるのだ。
これが原因で範囲指定を通過した結果、後の部分でエラーを吐くこともあるので注意。
なお、IF TALENT:0のように省略した文型で条件式を書いた場合、erabasicではIF TALENT:0 != 0と解釈される。
つまり負の値も真になるので、IF ASSIという条件式では助手がいない時を弾くことができないので注意。きちんとIF ASSI > 0と書こう。


REPEATループに注意

REPEAT文は繰り返しの処理に便利である。ただし、勘違いしている人がいるかもしれない。

ERB
 REPEAT 4  
     SIF COUNT == 4  
         PRINTL 4番目  
 REND  

上の文において、4番目がPRINTされることは決してありえない。なぜならREPEAT 4とはCOUNT1~4まで繰り返されるのではなくて、0~3まで繰り返されるのである。 すなわちREPEAT nnは繰り返し回数であって、COUNTの最終値から-1を引いたものが最後のループだからである。
これを知らないといろいろと死に分岐を作ってしまうので注意だ。
あ、あとループ終了だからって、RENDでなくてENDIFで閉じるなんて斬新なことをしてもいけない。REPEATRENDでしか、IFENDIFでしか閉じられない。


二重REPEAT

REPEAT文はCOUNTという専用の変数を制御に使いますが、COUNT自体はプログラム全体で同時に一つしか使用できないので、REPEAT文が入れ子になった二重REPEATはeramakerでは実行されません。
しかし、REPEAT~RENDの間でCALL命令を使ってREPEAT文を実行する関数を呼び出すと、二重REPEATREPEAT文を作ることが出来ます。

ERB
 REPEAT 10  
    CALL FUNC  
 REND  
 @FUNC  
 REPEAT 3  
 REND  

二重REPEAT文を作ってしまうと、内側のREPEAT文により外側のREPEAT文の情報が上書きされ、最悪の場合無限ループになります。 例えば上の例は、@FUNCの終わりでは必ずCOUNT3になるので、呼び出し元のREPEAT文から脱出することが出来ません。
関数を呼び出す際にCOUNTを別の変数へ待避すれば問題は起きませんが、eramakerでは確実な待避先が存在しないので、根本的な解決は出来ません。 Emueraであれば、LOCAL変数を待避先に使うか、REPEAT文をLOCAL変数をカウンタにしたFOR~NEXT文に置き換えることで解決します。


コメント行に注意

コメント行は適切に配置・記述してあれば、デバグや改造の助けになるが、ときどき失敗することがある。 たとえばコメント行を記したつもりでついうっかり先頭の;を忘れてしまったり消してしまったりした場合である。
もちろん、そのときは基本的にそこでエラー落ちするわけだが、コメント内容によってはそうでない場合もある。例えば、

ERB
 ;デバグのときはここで以下のとおりにすればお金は減らない  
 ;なおMONEY:1は掛かった経費とする  
 ;MONEY:1 = 0  
 MONEY -= MONEY:1  

上記のように書きたかったコードが下のようになってしまうと

ERB
 ;デバグのときはここで以下のとおりにすればお金は減らない  
 ;なおMONEY:1は掛かった経費とする  
 MONEY:1 = 0  
 MONEY -= MONEY:1  

ERB文法的には間違っていないので下の記述でもエラー落ちはしない。 だが、内部挙動は全然違っているため作者が望むとおりの結果は得られていない。こういうバグもまた恐ろしいものである。


PRINTFORMFORMは大切です。

よくあるのが%CALLNAME:MASTER%などの名前を表示するときに下のようにしてしまうことである。

ERB
 PRINTL %CALLNAME:MASTER%は%CALLNAME:TARGET%を抱いた  

%CALLNAME:MASTER%は文字型変数であるのでそれの内容を表示するためにはPRINT(文をそのまま表示)ではなくPRINTFORM(変数を変換して表示)を使用しなければならない。ちなみに上の例だと

 %CALLNAME:MASTER%は%CALLNAME:TARGET%を抱いた  

と表示されてしまう。
基本的にPRINTFORMPRINTの完全上位互換なので、よくわからなければPRINTFORMを使っておけばよい。
また無印、LWの使い分けだが、PRINTFORMは改行なしで表示も止まらない、PRINTFORMLは改行ありだが止まらず次の行も表示、PRINTFORMWは改行してその行で表示を止めるというのを覚えておこう。


(関数が)かぶった!?

eramakerでは同じ名前の関数を複数定義してもエラーとしては検出されません。そのため、関数名を被らせてしまうと、何もエラーは出ないけど、何かがおかしいという一番困った状況に陥ります。
そのため、後述するシステム関数など変更できない特別な事情があるもの以外は、同じ関数名を利用しないようにしましょう。
同名の関数をCALLなどで呼び出した場合の優先順位は、ファイル読み込み順に依存します。同一ファイル内では、ファイルの先頭に近い方が呼び出されます。ファイルの読み込み順はeramakerではファイルシステムに依存しますが、Emueraではコンフィグである程度は制御が可能です。
なお、RR系列の口上呼び出しはこの仕様を利用しています。
また、口上内で独自関数を作る場合、別の口上でたまたま同じ関数名を使っていたりすると誤動作の原因になります。関数名にK(キャラ番号)を含めるなど被らないよう工夫しましょう。
イベント関数は通常の関数と異なり、複数同じものがあってもすべて実行する仕様(#SINGLEがある場合は特殊)になってます。イベント関数がどれであるか?というのはwikiのほかの記述や本家の記述を参考にしてください。


RANDの使い方

RAND(乱数選出)は特に口上を書く際によく使われる便利な構文だが、使うときに気をつけるべき点がある。
まずRAND:Xで選出される数値は0~(X-1)の間で、Xの数値が選ばれることはない。つまりIF RAND:3 == 3という分岐を作っても絶対に条件が満たされない死に分岐となってしまう。
また、以下のようなミスも行いやすい。

ERB
 IF RAND:3 == 0  
  PRINTFORMW 「あ」  
 ELSEIF RAND:3 == 1  
  PRINTFORMW 「い」  
 ELSEIF RAND:3 == 2  
  PRINTFORMW 「う」  
 ENDIF  

一見それぞれ1/3の確率で表示されるようにみえるが、実際はこの書き方では等確率にはならない。 RANDは利用ごとに乱数を選出し直すため、この場合「あ」が表示される確率は1/3、「い」が表示される確率は(1-1/3)×1/3=2/9、「う」が表示される確率が{1-(1/3+2/9)}×1/3=4/27となり、8/27の確率で何も表示されなくなってしまう。
等確率で表示されるようにしたい場合、以下のどちらかの形式で書く必要がある。

ERB
 IF RAND:3 == 0  
  PRINTFORMW 「あ」  
 ELSEIF RAND:2 == 0  
  PRINTFORMW 「い」  
 ELSE  
  PRINTFORMW 「う」  
 ENDIF  

これならば「あ」が1/3、「い」が(1-1/3)×1/2=1/3、「う」が残り1/3となり、同じ1/3の確率で表示される。
変数を利用する場合は以下のようになる。ただし変数が本体やパッチがその部分の処理で使用しているものとバッティングしないように注意。

ERB
 A = RAND:3  
 IF A == 0  
  PRINTFORMW 「あ」  
 ELSEIF A == 1  
  PRINTFORMW 「い」  
 ELSE  
  PRINTFORMW 「う」  
 ENDIF  

なお、Emuera専用ならば拡張文法を用いた以下のような記述も使える。当然eramakerでは使えないので注意。
例)SELECTCASEを使った処理

ERB
 SELECTCASE RAND:3  
  CASE 0  
   PRINTFORMW 「あ」  
  CASE 1  
   PRINTFORMW 「い」  
  CASEELSE  
   PRINTFORMW 「う」  
 ENDSELECT  

例)PRINTDATAを使った処理

ERB
 PRINTDATAW  
  DATAFORM 「あ」  
  DATAFORM 「い」  
  DATAFORM 「う」  
 ENDDATA  

最後の改行は重要だ。

eramakerにおいては、ERBファイルにせよCSVファイルにせよ、最終行は読まれない。つまり、一番最後は改行してから終了しよう。
以下はとあるERBファイルの末尾である。最終行のENDIFできっちり終わっている。

ERB
 IF RESULT == 0  
      CALL REPLAY_GAME  
 ELSEIF RESULT != 1  
      GOTO INPUT_LOOP  
 ENDIF[EOF]  

さて、上の例。Emueraなら何の問題もないが、eramakerの場合、一番最終行のENDIFが認識できずにエラーになってしまう。必ずENDIFのあと改行してから保存しよう。そうすればエラーにならない。すなわち、

ERB
 IF RESULT == 0  
      CALL REPLAY_GAME  
 ELSEIF RESULT != 1  
      GOTO INPUT_LOOP  
 ENDIF[CR]  
 [EOF]  

とすればOKである。


命令文や条件文は半角空白で区切る。

各命令文の後ろには必ず半角スペースを入れる必要がある。
わかりやすいようこの項では半角スペースを_、全角スペースをと表記するが、実際書く時は「_」ではなく「」と書くように。

ERB
 PRINTL_ロードします  

下の例は両方ともeramakerが正常に解釈できずエラーが出てしまう。
前者はPRINTLの後に空白がないため、後者はPRINTLの後に半角ではなく全角スペースを入れているため、PRINTLを命令文だと認識できないからである。

ERB
 PRINTLロードします  
 PRINTL□ロードします  

また、複数の条件文を並べる場合も、それぞれの間に半角スペースを入れなければならない。

ERB
 ○:IF_TALENT:85_&&_TALENT:88  
 ×:IF_TALENT:85□&&TALENT:88  

このエラーが出ても警告だけで落ちないことが多いが、結果的にIF-ENDIF関係が崩れたりして以降の動作が不安定になり意図せぬフラグ破壊などが起こってしまうかもしれない。


GOTOで飛ぶと自分がいた場所を忘れます。

入力した数字や特定の条件で分岐先を決め分岐させる際、入れ子で構文を書くのではなく独自関数やラベルを使って独立項目として管理する方法がある。
複雑な分岐でも全体を把握しやすくなるメリットがあるのだが、この時一つ注意することがある。
$で始まるラベルを使いGOTO命令でそのラベルへ飛ばした場合、erabasicではこの時自分が今まで自分がどこに居たのかを忘れてしまうのだ。
その為、元のIF構文の外にラベルをおくと元の場所に戻れなくなってしまうので致命的なエラーが発生することがある。
ラベルを使うのは意図しない数字を入力した時に選択画面へ戻すような単純な処理だけにし、分岐先で再度分岐を発生させるような複雑な処理を行うつもりならば@で始まる関数として扱いCALLで呼び出した方がいいだろう。


同じGOTOラベル名は使わない。(INPUT_LOOPに関するバグ)

同一関数内で同じ名前のラベルが存在した場合、eramakerでは直前のラベルではなくその関数の一番初めにあるラベルへとジャンプします。
そのため意図した動作をしなくなる可能性があることから、現行のEmueraではクリティカルなバグとして扱われるようになっています。
$INPUT_LOOP_01のようにナンバリングを施したり、$EXTRAMODE_VIRGINのようにわかりやすい独自名を付けるなどして被らないよう工夫しましょう。


eramakerはERBフォルダ内のERBファイルとCSVフォルダ内のCSVファイルを読み込む

CSVファイルやERBファイルの実体はテキストファイルだが、だからといって普通のテキストファイルと同じように~~~.TXTという名前で作ってはいけない。
eramakerやEmueraではCSVファイルとERBファイル(とconfigファイルとERHファイル)以外は認識しないので、それに構文が書いてあっても存在しないことになってしまうからだ。
またeramakerはCSVフォルダ直下とERBフォルダ直下しか読み込まないため、CSVファイルやERBファイルをサブフォルダ内に保存してもやはり無視されてしまう(Emueraならばサブディレクトリを検索するオプションをYESにすることで認識させることが可能)
なお、eramakerやEmueraは起動時に認識できるファイルをファイル名や中身に関係なく全て読み込む。
改造などをする時にバックアップのつもりで同じフォルダ内にコピーしていると関数が衝突してしまうので、バックアップは必ず別のフォルダに保存しよう。
書き換えた後eramakerやEmueraを再起動させないと改造結果が反映されないことも忘れないように。
さて、ここで、ERBとかCSVとかTXTがマイ コンピュータやエクスプローラなどで表示されない環境の人に強く警告しておこう。それらはファイルの属性を表す拡張子であるが、いかなる理由であれ「表示させる」ことを強く推奨する。というか義務化していいぐらいだ。
拡張子というのはそのファイルの属性の一部を示すとても重要なものであり、WINDOWSの初期設定においてはなぜか表示されない設定になっている場合があるが、そのままでは非常に不便で危険で他人にも迷惑であるので必ず表示させておこう。拡張子を表示させる方法はWINDOWSのVERSIONごとに異なるが例えばXPの場合、マイ コンピュータやエクスプローラのフォルダオプションの表示タグの詳細設定から登録されている拡張子は表示しないという項目のチェックを外せばいい。


EmueraであってもCSVを読み込むときは注意

前項のとおり、Emueraにおいて、コンフィグ設定のサブディレクトリを検索するオプションがYesのときにはCSVファイルだって問題なくサブディレクトリを読む…わけではない。
CSVファイルのうちChara**.csv以外のCSVファイルについてはちゃんとCSVフォルダ直下に置かないと読んでくれない。これはEmueraの仕様なので仕方がない。


CharaXX.CSVを読むのはADDCHARAするときだけ

キャラcsvを書き換えて再起動しても、既に居るキャラのデータは書き換わりません。一見不便に見えますが、キャラcsvはキャラクターの初期ステータスを定義しているものなので、既存のキャラがcsvに同期してしまうと、「せっかく上げたレズっ気が下がった」などということが起こります。でも、eramaker(とEmuera)はそんなことしない。話の分かる奴です。
また、この仕様を使えば、とあるキャラを初期状態に戻したい場合、ちまちまとフラグを弄るのではなく、ADDCHARAして、入れ替えて、古い方をDELCHARAすればあら不思議、元通りというテクニックも使える。ただまあ、これはTARGETやその他周辺変数はそれに応じて書き換える必要があるのだけれど…。


CFLAG:999は避けよう

このwikiのeramaker変数情報にeramakerで利用できる要素数の範囲が書かれているが、一つ注意することがある。
実はeramakerには、CFLAG:999のような配列変数の最後の要素が0で無い場合、セーブ・ロード後にデータが破壊されるバグがあるのだ。
なので実際に使えるのは要素数-2まで(CFLAGならば998まで)と考えよう。
なおEmueraではこのバグが修正されている。VariableSize.CSVを利用することで要素数そのものも増やせるのでEmuera専用バリアントならば安心して使っていい。


CSVファイルをExcelで編集してはいけません。

PCにOfficeなどがインストールされ、CSVファイルがExcelなどの表計算ソフトに関連付けられている人も多いだろう。
だがeramakerバリアントのCSVファイルは必ずテキストエディタで編集するようにしよう。
Excelは自分が処理しやすいよう段落分けなどの記号を勝手に追加するので、eramakerで正常に読めなくなってしまうことがあるからだ。
といってもCSVファイルの関連付けそのものをテキストエディタに変更すると都合の悪い人も多いはずなので、ファイルを右クリックした時に表示されるコンテキストメニューの『送る』にテキストエディタを登録するか、ファイルの種類の設定でテキストエディタから開く項目を作っておくといいだろう。


RAND:0に注意しよう。

RAND:0とすると、eramakerでは0を返す。だが、Emueraではエラー落ちしてしまう。 単純な問題に思えるが、たとえば、RAND:変数として、その変数が別のところで代入・計算されてからその処理に来た場合、Emueraでは必ず直前にその変数が0より大きい数であることを確認しておくべきであろう。


TALENT:0(処女)による分岐について。

バリアントの仕様によります

俗に言う初体験時の口上を書く際にやってしまいがちなのがTALENT:0(処女)の有無で分岐させようとするミスだ。
それのどこが悪いのか?と疑問に思う人も多いだろうが、バイブや性交などのように処女喪失するコマンドの場合、基本的にほとんどのバリアントで処女喪失処理→口上呼び出しという処理順になっているため、口上が呼び出される時点で既に素質:処女が失われているため分岐には使えないのだ。
よって処女喪失時の口上を書きたい場合は、EXP:0(V経験) == 1を条件に使うようにしよう。ただし、YMrev.6に関してはEXP加算はターンラストに回されているので、この条件は、EXP:0(V経験) ==0 && TCVAR:0(V経験) > 0としなければならないだろう。
なおこの方法は純正処女専用で、再生処女の時には対応できない。
どうしても再生処女時の分岐を作りたいならば調教開始時に処女が存在したら適当なCFLAGに数値を代入し、V経験がその数値+1になっているかどうかで判別するといった工夫をしよう。
A開発時など処女喪失するコマンド以外の場面ならば、もちろん普通にTALENT:0を分岐条件に使っても構わない。