ERB構文講座¶
元となったページ
eratohoまとめ V3 ERB構文講座
前編 基本、変数、表示
後編 分岐と反復、関数と関数呼び出し、ラベルとキー入力、その他
特別編 ビット演算について
参考 ERBファイルの作成や改造時によくあるミスについてのQ&A
基本¶
構文以前の部分です。不明な~
などのエラーが出る時はこの部分が怪しいかも。
構文の記述は半角で行う¶
日本語の文章以外の部分は全て半角で入力しましょう。
見落としやすいのは全角スペースが主です。テキストエディタの検索機能で
全角スペースを検索すれば簡単に見つけられるはず。
分岐や反復にはインデントを行う¶
これは直接エラーには繋がりませんが、後述する分岐や反復を使う際には
インデントを使用しましょう。インデントとは行頭に決まった量の空白を
置くことによって記述の位置をずらし、ここからここまでが
一塊の処理です、というのをわかりやすくします。
インデントの空白にはTABキーを使用します。
インデントに処理上の効果はありませんが、デバッグで自分が見直す時や
他の人に見てもらう時などに役立ちます。
必要ないだろうと思っても一応はつけておきましょう。
コメントアウト部分の行頭には;
(半角セミコロン)をつける¶
構文の行頭に;
をつけることによってその行をコメント化することができます。これをコメントアウトと言います。
コメントアウトとは書かれている処理が実行されない部分のことで
一時的にその処理を無効にしたり、付近の処理についての
メモ書き代わりに使われることがあります。
なお、コメントアウトでは全角文字を使っても構いません。
;ここはコメントだから実行されないよ!
Emuera1.807以降の追加機能で、構文の途中からでもコメントアウトを書けるようになりました。
ただし、PRINT
系命令の後にある;
はコメントアウトとして認識されず、文字列としてそのまま表示されます。
A = A + B ;ここはコメントアウト
PRINT ほげほげ ;でもここはコメントアウトにならない
コメントアウトは詳しく正確につけましょう¶
コメントアウトを正しくつけることにより、なにか不具合があっても対処しやすくなります。
また自分自身や他人がソースを見直すときの理解の助けにもなります。
デバッグや改造にも有用ですので、なるべくコメントアウトはつけたほうがいいでしょう。
ただし、そのコメントの内容が間違っていてはいけません。
コメントの中身もしっかりとチェックすべきです。
eramakerの仕様
### 各ファイルの最後の行には必ず1行以上の空行を入れる `eramaker`の仕様上の問題で、ファイルの最後に空行がない場合その直前の行が認識されなくなってしまいます。
`ENDIF~`というエラーのよくある原因の1つです。
(Emueraではこの問題は発生しません。)
変数¶
計算などの処理で使われる変数についてです。
変数とは?¶
変数とは計算結果を保存したり、ある数値とある数値を比較したりする際に
使用する入れ物のようなものです。
文章による説明だけではわかりづらいので一例を。
A = 0
B = 0
C = 0
A = 0
とは、変数A
に0
を代入する、ということを表しています。
上のA
,B
,C
がそれぞれ変数です。現在はいずれも0
が中に入っています。
B = A + 1
C = A + 2
B = A + 1
とは、変数B
にA + 1
の結果を代入する、ということを表しています。
ここで計算が行われ、B
とC
の中身が書き換えられました。A
は0
なので
B
は0 + 1
で1
、C
は0 + 2
で2
となります。A
は0
のまま変化していません。
A = C
A = B
次にA
にC
、つまり2
が代入されました。これでA
が2
になります。
しかし、次の行でA
にB
、つまり1
が代入されたため、A
は1
となります。
このように、同じ変数に複数回代入が行われると結果は上書きされます。
C = C + 2
A = B + C
次に、C
にC + 2
が代入されます。
計算前のC
は2
だったので、計算後のC
は2 + 2
で4
です。
そしてA
にB + C
、つまり1 + 4
が代入されます。
ここまでの処理の結果、A
は5
、B
は1
、C
は4
となりました。
変数の種類¶
変数には大きく分けて2種類のものがあります。
上のA
,B
,C
のように数字を格納する『数値型変数(int型)』と
文字を格納する『文字列型変数(string型)』です。
数値変数は計算や条件判断に、文字列変数は主に文章の表示に使われます。
また、変数には『配列』という概念があります。配列を使うことで変数に複数の値を
格納することができるようになります。
例えばA
という変数の配列は、A:0
,A:1
,A:2
,A:3
, …という風に
(変数名):(配列番号)
で表現します。(:
は半角のコロンを使用します)
A:0 = 0
A:1 = 1
A:2 = 2
A:3 = 0
A:3 = A:0 + A:1 + A:2
この式はA:3
にA:0 + A:1 + A:2
の結果、つまり0 + 1 + 2
を代入することを表します。
処理の結果、A:3
は3
になります。
一部の変数には、2次元配列という形式のものもあります。2次元配列は
A:0:0
,A:0:1
, …,A:1:0
,A:1:1
, …のように記述し、更に多くの値を格納できます。
どの変数がどの配列形式かは、eramaker用変数リストやEmuera用定数・変数に載っています。
変数の使い方¶
基本的にはeramakerの変数リストのページに書いてある通りです。
ここでは扱いに注意が必要なものを主に取り上げます。
-
A - Z
上記ページでは記述されていませんが、配列として使用できます。
A
はA:0
と同じです。
つまり、A:0
の値を変えたあとはA
の値も同様に変化しています。 -
FLAG
/TFLAG
/CFLAG
FLAG
・TFLAG
はゲームシステムに関する部分に使われるため
特定のキャラのみに使用するフラグを管理する際にはCFLAGを使用しましょう。
また、非常に被りやすいので使用の際はフラグ一覧表を良く確認しましょう。
フラグ一覧表は、各バリアントに同梱されている「変数資料.txt」などを見てください。
eramakerの仕様
なお、`eramaker`の仕様では`0~999`までの1000個の数字を使えるとなっていますが、実際にはバグにより`0~998`までの999個しか使えません。999を使うとセーブデータが破壊されてしまいますので絶対に使用しないでください。
TFLAGは調教ごとにリセットされることにも注意してください。
(Emueraを使用する場合には、CFLAG:999を利用してもセーブデータ破壊は起こりません。また設定により、1000個を超える数字を使うこともできます。)
TEQUIP
上のフラグ系と同様に被りやすいので使用の際はフラグ一覧表を確認しましょう。
2次元配列について¶
2次元配列形式の変数は、主にキャラに関するデータに使われています。
そのため、2次元配列変数の読み方は以下のようになっていることがほとんどです。
;変数「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 と同様ですが、セーブデータ専用です。 |
各命令の後にL
やW
をつけると、改行や入力待ち(Enterキーを押すまで進まない)を
させることができます。例えば、
PRINT あ
PRINT い
PRINTL う
PRINTW え
PRINTL お
と記述すると、まず
あいう
え
と表示され、入力待ち状態になります。
ここでEnterキーを入力すると残りも表示され
あいう
え
お
と表示されます。
PRINT系命令の使い方¶
上の項にある通り、PRINT
系の命令にはそれぞれの用途がありますが
実際にはPRINTFORM
でほとんどのものを代用することができます。
普通の文章を表示させるなら
PRINTFORM あいうえお
のようにそのまま記述します。この時、PRINTFORM
と表示させる文章の間に
半角スペースを入れておくのを忘れないようにしましょう。
数値変数を組み合わせて表示させるなら
A = 5
PRINTFORM 変数Aは{A}です
のように変数名を半角の{~~~}
で括って記述します。
文字列変数なら
STR:0 = かきくけこ
PRINTFORM あいうえお%STR:0%さしすせそ
のように変数名を%~~~%
で括って記述します。
PRINTFORM
もまた後ろにL
、W
をつけることで、
PRINTFORML
:改行ありだが改行や入力待ちをせず次の行も表示PRINTFORMW
:改行してその行で表示を止める
と使い分けることができます。
セーブデータに表示させるPUTFORM
のみPRINTFORM
では代用できませんが
セーブデータの表示を変更する機会は少ないと思われるので割愛します。
詳しくはPUTFORM
のページを参照
その他の表示¶
文字を表示した後改行させるにはPRINTFORML
を使いますが
文字を表示させずに改行させたい、つまり空白行を表示させたいという
場合にもPRINTL
、PRINTFORML
を使います。
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
という条件の場合は
A == 0 && B == 1
となります。
A == 0
またはB == 0
という条件なら
A == 0 || B == 0
となります。
もっと複雑に、A == 0
でB == 1
、またはA == 0
でC == 1
なら
(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)までの
いずれかの整数になります。また、
A = 5
B = RAND:A
の場合、変数B
は0から4(0からカウントするため上限は4)までのいずれかの整数になります。
分岐¶
○○が××した時□□を表示する、のような処理を行うのが分岐です。
分岐に使われる構文には主にIF
やSIF
、SELECTCASE
などがあります。
IF - ELSEIF - ELSE - ENDIF
¶
もし○○ならば、という処理に最もよく使われる構文です。
IF
のリファレンスページ
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
構文の基本的な形です。上の構文は
- もし変数
A
が0
ならば(IF A == 0
)、『変数Aは0です。』と表示します。 - 変数
A
が0
でなく変数B
が0
ならば(ELSEIF B == 0
)、『変数Aは0でなく、変数Bは0です。』と表示します。 - いずれの条件にも当てはまらないならば(
ELSE
)、『変数Aは0でなく、変数Bも0ではありません。』と表示します。
このように一つのIF - ENDIF
間では上から順に条件式を判定していき、
条件の成立した部分の直後の処理のみを行います。
上の例文では処理の部分が1行ずつしかありませんが、実際には
次のELSEIF
,ELSE
,ENDIF
までの処理が全て行われます。
IF 条件式1
処理1
処理2
処理3
ELSEIF 条件式2
処理4
処理5
ELSE
処理6
ENDIF
(条件式1が成立の時は処理1~3、条件式1が不成立で条件式2が成立の時は
処理4と5、どちらも不成立の時は処理6のみが行われる)
判定したい条件が3つ以上ある場合は、ELSEIF
を増やしていくことができます。
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
以下の部分はなくても構いません。
IF A == 0
PRINTFORML 変数Aは0です。
ELSE
PRINTFORML 変数Aは0ではありません。
ENDIF
条件を満たさない時何もしない場合、ELSE
以下の部分はなくても構いません。
IF A == 0
PRINTFORML 変数Aは0です。
ELSEIF B == 0
PRINTFORML 変数Aは0でなく、変数Bは0です。
ENDIF
IF
とENDIF
は絶対に必要です。
ENDIF
の書き忘れはエラーの原因になりますので注意しましょう。
SIF
¶
上のIF - ENDIF
を簡略化したのがSIF
になります。
SIF
のリファレンスページ
SIF A == 0
PRINTFORML 変数Aは0です。
SIF
にはENDIF
が必要ない、ELSEIF
やELSE
が使用できない、
直後の1行しか実行できない、などの特徴があります。例えば
SIF 条件式
処理1
処理2
と記述すると、条件式の真偽に関わらず処理2は実行されてしまうので
注意しましょう。
2つ以上の処理を行う時は上のIF - ELSEIF - ELSE - ENDIF
を使いましょう。
eramakerの仕様
また、eramakerではSIF 条件式
;コメント
処理1
(Emueraではコメント行がきちんと無視されるので、条件式が真であるときのみ処理1が実行されます。)
IF
とSIF
の組み合わせ¶
IF 条件式1
SIF 条件式2
処理1
処理2
処理3
ENDIF
と記述すると、条件式1と条件式2の両方が真である場合は処理1から3を全て実行し、
条件式2だけが成立する時は処理2と3のみを実行します。
SIF 条件式1
IF 条件式2
処理1
処理2
ENDIF
(条件式1が偽の場合は
IF 条件式2
の行だけを読み飛ばすので、「ENDIF
に対応するIF
が無い!」というエラーになる)SIF
の直後の行にIF
やSIF
などの分岐や反復を行う文は書かないようにしましょう。 SELECTCASE - CASE - CASEELSE - ENDSELECT
¶
IF 文と似た機能を持つ構文としてSELECTCASE - CASE - CASEELSE - ENDSELECT
があります。
1つの数値変数の値によって処理を分岐させる時に使います。
例えば乱数によって処理を分岐させる時に便利な構文です。
SELECTCASE
のリファレンスページ
SELECTCASE A
CASE 0
PRINTFORML 変数Aは0です。
CASE 1
PRINTFORML 変数Aは1です。
CASEELSE
PRINTFORML 変数Aは0でも1でもありません。
ENDSELECT
これは、次のIF
文と同じ意味を持ちます。
IF A == 0
PRINTFORML 変数Aは0です。
ELSEIF A == 1
PRINTFORML 変数Aは1です。
ELSE
PRINTFORML 変数Aは0でも1でもありません。
ENDIF
SELECTCASE
文は、CASE
の後ろに書かれた数値がSELECTCASE
の直後に書かれた数値変数(この場合はA
)と等しいかどうかを判定して分岐します。
CASE
については次のような書き方をすることもできます。
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
文と同じ意味を持ちます。
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
文から派生してできた演算子なので、ここで説明します。
三項演算子は、次のような形を取ります。
<代入先変数> = <条件式> ? <真の場合の代入値> # <偽の場合の代入値>
例えば、変数A
が3以上の時に1、そうでない場合に0を変数B
に代入する操作は、IF
文を使うと次のようになります。
IF A >= 3
B = 1
ELSE
B = 0
ENDIF
B = A >= 3 ? 1 # 0
三項演算子は文字列変数に対しても使用できます。文字列を扱う場合は、三項演算子を \@ ~ \@
で囲みます。
PRINTFORML %CALLNAME:TARGET%は\@ TALENT:処女 ? 処女です。 # 処女ではありません。 \@
上の文は、TALENT:TARGET:処女
が0以外の時に『(TARGETの呼び名)は処女です。』と出力し、
TALENT:TARGET:処女
が0の時に『(TARGETの呼び名)は処女ではありません。』と出力します。
三項演算子とSELECTCASE
との組み合わせ¶
SELECTCASE
文に三項演算子を組み込むと、条件式を更に分岐させられます。
SELECTCASE RAND:(TALENT:処女 ? 3 # 2)
CASE 0
PRINTFORMW 無条件1
CASE 1
PRINTFORMW 無条件2
CASE 2
PRINTFORMW 処女限定
ENDSELECT
この構文では、対象の処女素質(TALENT:処女
)で条件式を分岐させています。
条件式は、判定結果が真ならRAND:3
、偽ならRAND:2
と扱われます。
実行すると、CASE 0
、CASE 1
は無条件でRAND
抽選の対象になりますが、CASE 2
は対象が処女でないとRAND
抽選から弾かれます。
このSELECTCASE
文は、次のIF
文と同じ意味を持ちます。
IF RAND:3 == 0 && TALENT:0 == 1
PRINTFORMW 処女限定
ELSEIF RAND:2 == 0
PRINTFORMW 無条件2
ELSE
PRINTFORMW 無条件1
ENDIF
反復¶
同じ処理を複数回繰り返すときに使うのが反復(ループ処理)です。
REPEAT - REND
¶
REPEAT 数式
処理
REND
REPEAT - REND
間の処理を繰り返し実行します。
繰り返す回数はREPEAT
の直後にある数値、または数値変数に代入されている値です。A + 1
などの数式を置くこともできます。
例えば、
REPEAT 10
PRINTFORML あ
REND
COUNT
¶
変数COUNT
は、現在までに何回繰り返しを行ったかを格納しています。
REPEAT - REND
内の処理を最初に行う時はまだ1回目の繰り返しの途中(1回目の繰り返しが完了していない)なので
REPEAT 10
PRINTFORML 現在{COUNT}回目です。
REND
こう記述した場合、表示されるのは0回目から9回目となります。
COUNT
がとる値は 0 からREPEAT
の直後の数値 - 1 までと覚えておきましょう。
また、COUNT
に数値を代入するのはエラーの原因となるので注意しましょう。
REPEAT
とIF
,SIF
の組み合わせ¶
REPEAT - REND
の間にもIF
やSIF
を使用することができます。
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
で代用する必要があります。
;REPEAT を入れ子にする例
REPEAT 10
COUNT:1 = COUNT
REPEAT 10
処理
REND
COUNT = COUNT:1
REND
CONTINUE
とBREAK
¶
REPEAT - REND
間で、以降の処理を行わずに次の繰り返しに入る場合にはCONTINUE
を、
以降の処理を行わず、繰り返し自体を終了させる場合にはBREAK
を使用します。
REPEAT 10
A = COUNT
IF A == 5
CONTINUE
ENDIF
PRINTFORM {A}:
REND
これを実行すると、COUNT
が5の時にCONTINUE
が実行されるので、実際に表示されるのは
0:1:2:3:4:6:7:8:9:
となります。また、
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
REPEAT - REND
の機能強化版がFOR - NEXT
です。
例えば、次の2つのスクリプトは全く同じ動作をします。
FOR COUNT, 0, 10
PRINTFORML {COUNT}回目
NEXT
REPEAT 10
PRINTFORML {COUNT}回目
REND
FOR
の直後の<カウンタ数値変数>
はREPEAT
でいうCOUNT
に相当します。
REPEAT
では繰り返しの回数を数える変数はCOUNT
に固定されていましたが、FOR
ではこの変数を好きな変数に設定することができます。
カウンタ変数を別にすることで、REPEAT
では面倒だったループの入れ子を簡単に実現できます。
;入れ子の例
FOR A, 0, 10
FOR B, 0, 10
処理
NEXT
NEXT
FOR
の後ろに来る2番目の<数式>
は、繰り返しを始める<カウンタ数値変数>
の値を設定します。
3番目の<数式>
で、繰り返しを終わる<カウンタ数値変数>
の値を指定します。
例えば、
FOR COUNT, 3, 8
PRINTFORM {COUNT}:
NEXT
を実行すると、
3:4:5:6:7:
と表示されます。
FOR
の後ろの4番目の<数式>
は、ループを1回繰り返すごとにカウンタ変数に加算される値を設定できます。省略すると自動的に1が設定されます。
例えば、
FOR COUNT, 0, 10, 2
PRINTFORM {COUNT}:
NEXT
を実行すると、
0:2:4:6:8:
と表示されます。
なお、REPEAT - REND
と同様にCONTINUE
とBREAK
も使用できます。
WHILE - WEND
¶
WHILE 条件式
処理
WEND
条件式が真である間、ループを繰り返します。
例えば、次のスクリプトは「あ」を10行表示します。
A = 0
WHILE A < 10
PRINTFORML あ
A += 1
WEND
このとき、A += 1
の行を書き忘れると、変数A
の値は0のままになってしまうので、
A < 10
はいつまでも真のままとなり、無限ループに陥ってしまいますので注意が必要です。
WHILE - WEND
でもCONTINUE
とBREAK
を使用できます。
DO - LOOP
¶
DO
処理
LOOP 条件式
条件式が真である間、ループを繰り返します。
WHILE - WEND
との見た目の違いは条件式の位置が違う程度ですが、最初の繰り返しが必ず実行されるという特徴があります。
次の2つのスクリプトを見比べてみてください。
A = 0
WHILE A < 0
PRINTFORML あ
WEND
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
の順に実行されるので、無限ループにはなりません。
DO
CONTINUE
LOOP 0
関数と関数呼び出し¶
ここからは主に機能パッチやバリアントを作成する際に使う範囲となります。
関数とは¶
いくつかの決まった処理を行わせたい時、それを予め別の場所に記述しておいて、
任意の場所から使えるようにしたものを関数と言います。
例として、変数A
の値を10倍にする関数を作ってみましょう。
@A_TEN_TIMES
A = A * 10
@
の後に半角英数と_
(アンダーバー)で関数の名前を付けることができます。
それ以降の処理が関数で行う内容となります。
A = 0
CALL A_TEN_TIMES
PRINTFORML 変数Aは{A}です。
A = 5
CALL A_TEN_TIMES
PRINTFORML 変数Aは{A}です。
作った関数を利用する(呼び出す)にはCALL <関数名>
と記述します。
この結果、上は『変数Aは0です。』下は『変数Aは50です。』と表示されます。
また、関数を呼び出すのにJUMP <関数名>
を使うこともあります。
CALL
とJUMP
の違いは関数での処理を実行した後、元の場所に戻るかどうかで、
CALL
は戻る、JUMP
は戻らないようになっています。
なお、同じ名前の関数が複数ある時はどれか1つだけが呼び出されます(イベント関数という特殊な関数を除く)。
関数の名前は他と同じにならないよう注意しましょう。
RETURN
と戻り値¶
ある条件を満たした時、関数を途中で終わらせたいという場合は
RETURN <数値> と記述します。
@TEST
SIF A == 0
RETURN 0
A = A * 5
この場合、関数@TEST
を呼び出した時A
が0なら何も行われず、そうでなければA
が5倍されます。
また、RETURN
文で関数を終了し元の場所に戻ってくると、変数RESULT
がRETURN
で指定された数値に書き変えられます。
この時、RESULT
を関数の 戻り値(返り値) といいます。
例えば、
@TEST2
IF A == 0
RETURN 0
ELSEIF A == 1
RETURN 1
ELSEIF A == 2
RETURN 2
ELSE
RETURN 9
ENDIF
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
を、引数を取るように書き換えたのが次の例文です。
@TEST2, ARG
IF ARG == 0
RETURN 0
ELSEIF ARG == 1
RETURN 1
ELSEIF ARG == 2
RETURN 2
ELSE
RETURN 9
ENDIF
呼び出すときは次のようにします。
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, …
のように定義します。
@TEST3, ARG, ARG:1, ARG:2
(略)
CALL TEST3, 0, 7, 3
引数には文字列変数も取ることができ、その場合は ARGS を使います。
ローカル変数¶
A
,B
などの一文字変数やCOUNT
など多くの変数は、プログラム全体で同時に一つの変数を共通で使用します。
ですが、それが原因でバグが発生することがあります。
@MAIN
FOR COUNT, 0, 10
CALL FUNC
NEXT
@FUNC
FOR COUNT, 0, 3
(何か処理)
NEXT
上の例文で@MAIN
関数を実行すると、@FUNC
が呼ばれるたびにCOUNT
が3にセットされるので、無限ループに陥ります。
この例では@FUNC
内のFOR
ループのカウンタ変数をCOUNT:1
にすれば問題は解決しますが、
1つのバリアント内で使われる関数は1000個を軽く超えるので、どこかで必ずこういった問題が発生します。
そこで、ある関数の中でしか使えない変数(ローカル変数)を用意すれば、この問題は解決するはずです。
そのローカル変数がLOCAL
とLOCALS
です。次の例を見てください。
@EVENTFIRST
LOCAL = 123
CALL FUNC001
PRINTFORML {LOCAL}
@FUNC001
LOCAL = 567
RETURN
一見するとLOCAL
という同じ変数に数値を代入しているように見えますが、
「@EVENTFIRST
の中で使っているLOCAL
」と「@FUNC001
の中で使っているLOCAL
」は別物として扱われるので、
PRINTFORML
文の結果は「123
」と出力されます。
なお、LOCALS
はLOCAL
の文字列変数バージョンです。
先に説明したARG
とARGS
もローカル変数として扱われます。
LOCAL, ARG の初期化タイミングに注意¶
他の言語でプログラミングをしたことのある人には特に注意して頂きたいのですが、
LOCAL
やARG
は関数が呼び出されたタイミングで初期化されない
関数が呼び出されるたびに同じLOCAL
,ARG
を使いまわす
の2点に気をつける必要があります。
この特徴は、関数の再帰などを利用した場合に注意が必要です。
@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
についても同様です。
@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
に格納するには次のように記述します。
ABS A
LOCAL = RESULT
これに対し、ABS
という名前の「式中で使える関数(以下「式中関数」と書きます)」を使うと、上のスクリプトを次のように書くことができます。
LOCAL = ABS(A)
「式中関数」の名前通り、代入式の中から直接関数を呼び出し、RESULT
を介さずに戻り値をLOCAL
に代入することができます。
式中関数では、引数を(A)
のように丸括弧で囲んで呼び出します。
引数が複数ある場合は(A, B, C)
のように丸括弧の中でカンマで区切って書きます。
逆に引数がない場合は()
と丸括弧だけを書きます。引数がなくても丸括弧は省略できません。
ABS
のリファレンスページ
文字列を返す命令でも、同様の書き方ができます。
STRLENS STR:0
IF RESULT > A
SUBSTRING STR:0, A, 1
LOCALS:0 = %RESULTS:0%
ENDIF
IF STRLENS(STR:0) > A
LOCALS:0 = %SUBSTRING(STR:0, A, 1)%
ENDIF
式中関数の一覧は命令・式中関数のページで確認できます。
式中関数を自分で定義する¶
式中関数は自分で定義することができます。
関数を定義する@
行の直後に#FUNCTION
と書き、RETURN
をRETURNF
に置換するだけで、その関数は式中関数になります。
;下の行は @TEST2, ARG と書いてもよいが、慣習的にこう書くことが多い
@TEST2(ARG)
#FUNCTION
IF ARG == 0
RETURNF 0
ELSEIF ARG == 1
RETURNF 1
ELSEIF ARG == 2
RETURNF 2
ELSE
RETURNF 9
ENDIF
呼び出すときは次のようにします。
PRINTFORML {TEST2(0)}
PRINTFORML {TEST2(2)}
PRINTFORML {TEST2(3)}
文字列を返す式中関数を作りたい場合は、#FUNCTIONS
と書きます。
ただし、RETURNF
の書き方が他の命令(PRINTFORM
など)とは異なるので注意してください。
関連ページ:ユーザー定義の式中関数
ラベルとキー入力¶
主に選択肢による分岐で使用されるのがラベルとキー入力です。
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 (ラベル名)
は$(ラベル名)
の処理に移動するもので、CALL
やJUMP
と@
との
関係に似ていますが、GOTO
と$
に関しては同じ関数内にある必要があります。
GOTO INPUT_LOOP
で$INPUT_LOOP
に移動すると再びINPUT
を実行するため、
この一連の処理は0か1かを入力するまで繰り返されることになります。
また、一つの関数内で複数の$
とGOTO
の組み合わせを使用すると
『IF
に対応しないELSEIF
,ELSE
,ENDIF
が~』というエラーが発生することがあります。
この場合、2つ目の入力処理を別の関数に移すなどの工夫をしましょう。
その他注意点など¶
キャラの追加と削除¶
キャラの追加と削除には、ADDCHARA
とDELCHARA
を使用します。
ADDCHARA
のリファレンスページ DELCHARA
のリファレンスページ
ADDCHARA 1
ADDCHARA 5
ADDCHARA 9
Emueraでは次のように書くことができます。
ADDCHARA 1, 5, 9
ADDCHARA
ではCSVにあるキャラ番号が参照されます。
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
は変化しません。しかし全体の登録番号は
前にずれてしまうため、助手になる条件を満たしていないキャラが助手に
なってしまうこともあります。
グラフ表示¶
BAR
(BARL
)を使用することで数値の表示を視覚的に行うことができます。
BAR (数値or変数),(数値or変数),(グラフの長さ)
のように記述し
A = 80
B = 100
BAR A, B, 10
では
[********..]
と表示されます。
A
に現在の値、B
にその最大値を入れることで、現在の値が最大値の
どのくらいの割合かを示す際によく使用されます。
BARL
では表示後に改行されることも覚えておきましょう。
小数の乗算¶
erabasicでは変数などは全て整数で処理されますが、例外として
TIMES
を使用することで小数の計算を行うことができます。
TIMES
のリファレンスページ
A = 1000
TIMES A, 1.5
これで変数A
は1000×1.5
の1500
となります。
なお、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であるかを判定することによって
条件分岐に使用したりします。
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
ですから、0
と1
で一致しません。
つまり、FLAG:1 & 1
は0
となります。
一方FLAG:2 & 1
の方では、FLAG:2
も1
も二進数で1
となります。
どちらも一桁目が1
なのでFLAG:2 & 1
は1
となります。
これを上のIF
文に当てはめると
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つずつの条件を判定する
処理を説明しましたが、ビット演算を利用すると一つのフラグで複数の
条件を判定させることができます。
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:1
が0
の時、先の例でもあったようにFLAG:1 & 1
は0
です。
FLAG:1 & 2
を見ると、0(00)
と2(10)
でどちらも1
になる桁はなく
やはり0
になります。FLAG:1 & 4
も0(000)
と4(100)
で0
ですね。
次にFLAG:1
が1
の時、これも先の例の通りFLAG:1 & 1
は1
です。
FLAG:1 & 2
は1(01)
と2(10)
なので0
、
FLAG:1 & 4
も1(001)
と4(100)
で0
になります。
FLAG:1
が2
の時、FLAG:1 & 1
は2(10)
と1(01)
で0
です。
FLAG:1 & 2
は2(10)
と2(10)
で二桁目がどちらも1
になりました。
このため、FLAG:1 & 2
は二進数で10
、つまり2
になります。
FLAG:1 & 4
は2(010)
と4(100)
で0
になります。
FLAG:1
が3
の時、FLAG:1 & 1
は3(11)
と1(01)
で一桁目が一致し
1
になります。FLAG:1 & 2
では3(11)
と2(10)
で二桁目が一致し
2
になります。FLAG:1 & 4
は3(011)
と4(100)
で0
です。
FLAG:1
が3
の時の結果表示はこのようになります。
条件1はONです。
条件2はONです。
条件3はOFFです。
このようにビット演算を利用することで複数の条件の組み合わせを
一つのフラグで表現することができます。
ただし、判断できる条件はON/OFFやあり/なしなど二択のものに
限られることに注意しましょう。
また、条件一つ一つの判断を行う式で&の後に使う数値は2のX乗の値を
使います。理由は後の項で説明します。
ビット演算で使う値を設定するには¶
ここまではビット演算での判定を行う部分について説明してきました。
しかし、実際に処理中でビット演算を利用するには判定に使われる
値を動かす方法も必要となってきます。
他の処理のようにFLAG:1 += 1
やFLAG:1 -= 2
と計算を行っても
いいのですが、この方法だと問題が発生する場合があります。
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
になります。
A = 5
B = 3
C = A | B
PRINTFORML 変数Cは{C}です。
↓
変数Cは7です。
また、A = A | B
はA |= B
と書くこともできます。
ビット演算に使用する変数は元のものに上書きすることが多いため
ぜひ覚えておきましょう。
では逆に、機能をOFFにしたりする時にはどうすればいいでしょうか。
上の例で、今度は機能1・2・3全てONの状態とし、そこから機能2を
OFFにする方法を考えてみましょう。
まず、機能1~3がONということはFLAG:1 & 1
もFLAG:1 & 2
も
FLAG:1 & 4
も0
でない、つまりFLAG:1
を二進数で表した時の下三桁は
111
となっています。
ここから機能2をOFFにするには、他の桁はそのままでFLAG:1 & 2
が0
、
つまり下から二桁目のみを0
にすればいいということになります。
二桁目を0
にするなら二進数の10
、つまり十進数の2
を引けばいいと
考えることもできますが、それでは先の例のように2回以上行われた時に
数値がおかしくなってしまいます。
そこで再び使うのが&です。
7(111) & 5(101)
の結果は二進数で101
となり、他の桁を変えずに
二桁目だけ0にすることができました。
機能1・2がONの状態から機能2をOFFにするには、011
を001
にする
必要がありますが、これも3(011) & 5(101)
で実現できます。
それでは、ここで&@の後に持ってきた
5(101)はどういう値なのでしょうか。 二進数で見ると、
0にするべき二桁目以外が
1の数値、と言えますね。 これは切り替える機能の総数が増えても同じことで、5個の機能の中で 4つ目をOFFにするなら
10111、10個の機能の中で3つ目をOFFにするなら
1111111011を
&`の後に持ってくればいいことになります。
これらを踏まえて先の例のON/OFF部分だけを書き換えてみると
@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]
と□
が分からないことに注意のこと。
ループの閉じ忘れ¶
適切にインデントを設定していないことによりみずらいソースを記述してしまうと往々にしてこういう事態になってしまう。
具体的には、
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
が足りないから文句言われるのならば、いっぱい置けばいいじゃないなんてことももちろんない。ちゃんと適切に配置すべきである。
IF A == 2
IF B == 3
PRINTL Aは2でBは3です。
ENDIF
ENDIF
ENDIF
これなら大丈夫だろ?と思われるかもしれないが、eramaker(もしくはEmuera)内部ではつじつまが合わないことが起こると予期せぬ挙動により変なところでエラー落ちしたりフラグを破壊したりとその後の構文が全て実行されなくなったりとろくなことにならない。
SIF
文にENDIF
を付けてしまいました¶
SIF
文はその直後の1行だけで完結するのでENDIF
で閉じる必要はない。これはむしろ、IF
文として作ったあとにそれをSIF
文に直したときにその後方のENDIF
を消し忘れておこってしまうケースがありうる。
SIF A == 2
PRINTL Aは2です。
ENDIF
まあ、最後にもう一度見直すとか何らかのチェッカーを通せば分かると思われるけど。ともかく、注意すべきである。
SIF
文に複数の行を収めようとしてしまう¶
前述の通りSIF
文はその直後の1行だけで完結する。つまりIF~ENDIF
と同じノリで複数行をSIF
文で分岐させることはできない。これはSIF
文で作った分岐に新たに処理を加える際にやらかしやすい。
SIF TALENT:MASTER:117
A += 100
B += 100
上記の例の場合、B += 100
はTALENT:MASTER:117
の有無に関係なく必ず実行されてしまう。チェッカーの類では検出出来ないミスなので十分注意したい。
SIF TALENT:MASTER:117
A += 100
SIF TALENT:MASTER:117
B += 100
このように書けば一応意図通りに実行されるが、それなら最初からIF
文を使って書いた方が早いしわかりやすい。 そもそも、SIF
文を使わないことが最善の対策だろう。
SIF
の直後にコメントを置くのは危険¶
SIF
文はその分岐が真ならばその直後の一行を実行するというものだが、Emueraの場合その直後がコメント行ならそれをカウントせず、その次の行以降の最初に来る非コメント行を実行する。 だが、eramakerは直後のコメント行を「実行」してしまうため、両者では挙動が異なる。それに気をつけておかないといけないので注意すること。コメントに関してはできるならSIF
の前の行に付けておくといいだろう。
ELSEIF
をELSE
としてしまう/ELSE IF
としてしまう¶
IF~ELSE~ENDIF
文においてときどき以下のようなことを記述してしまってエラーを出すことがあるかもしれない。
IF TALENT:120
PRINTL オトコですぜ。
ELSE TALENT:121
PRINTL ふたなってます。
ELSE IF TALENT:122 || TALENT:123
PRINTL そのうち生えるかも?
ENDIF
さて、上の例で2つのELSE
はいずれもエラーだったりする。最初のはIF
を忘れた例。二番目のはELSE
とIF
が分離しちゃった例。
ELSE
には条件文をつけられない仕様なので、どちらも正常に判定されない。
いずれにせよこういうことがないようにすべき。
お前はもう死んでいる分岐¶
IF~ELSE~ENDIF
構文においてやりかねない過ちのひとつが「死に分岐」である。それ自体はエラー落ちしたりすることはないかもしれないがなるべくならそういうことはないほうがいい。
IF TALENT:120 == 1 || TALENT:121 == 1
PRINTL ペニスあるぜ!
ELSEIF TALENT:120 == 1
PRINTL オトコだぜ!
ENDIF
さて、上の例でELSEIF TALENT:120 == 1
の行が成り立って実行されることは絶対にない。つまりこの部分は「死に分岐」である。
なぜなら、TALENT:120
が存在する時点で最初のIF
が実行されてしまい、次のELSEIF
の判定が実行されることはないからだ。
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
という条件式を組み、助手が存在しない場合を弾くようにしよう。
IF ASSI >= 0
SIF TALENT:ASSI:0 == 1
PRINTL 助手は処女です。
ENDIF
また口上テンプレでは特定のキャラが助手をしているという条件式で助手の番号をY1
と仮定してあることがある。
上記の通りASSI
には自然数しか入れないので、IF ASSI:NO == Y1
という式があるとエラーになってしまう。
通常この部分はコメントアウトしてあるはずなので、助手番号を指定しない場合は行頭の;
を外さずそのままにしておこう。
eramakerは短絡評価なんてしない¶
EmueraにおいてはIF
文の短絡評価(前の条件が偽の場合、それ以降の条件判定を行わない)が実装されているが、eramakerには実装されていない。 なので少々回りくどい構文を組む必要がある。特に便利な拡張文法を使えるEmuera専用バリアントで製作したあとにeramakerバリアントで製作すると往々にしてこのあたりをすっとばしてしまいがち。
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
文は繰り返しの処理に便利である。ただし、勘違いしている人がいるかもしれない。
REPEAT 4
SIF COUNT == 4
PRINTL 4番目
REND
上の文において、4番目がPRINT
されることは決してありえない。なぜならREPEAT 4
とはCOUNT
が1~4
まで繰り返されるのではなくて、0~3
まで繰り返されるのである。 すなわちREPEAT n
のn
は繰り返し回数であって、COUNT
の最終値から-1を引いたものが最後のループだからである。
これを知らないといろいろと死に分岐を作ってしまうので注意だ。
あ、あとループ終了だからって、REND
でなくてENDIF
で閉じるなんて斬新なことをしてもいけない。REPEAT
はREND
でしか、IF
はENDIF
でしか閉じられない。
二重REPEAT
文¶
REPEAT
文はCOUNT
という専用の変数を制御に使いますが、COUNT
自体はプログラム全体で同時に一つしか使用できないので、REPEAT
文が入れ子になった二重REPEAT
はeramakerでは実行されません。
しかし、REPEAT~REND
の間でCALL
命令を使ってREPEAT
文を実行する関数を呼び出すと、二重REPEAT
なREPEAT
文を作ることが出来ます。
REPEAT 10
CALL FUNC
REND
@FUNC
REPEAT 3
REND
二重REPEAT
文を作ってしまうと、内側のREPEAT
文により外側のREPEAT
文の情報が上書きされ、最悪の場合無限ループになります。 例えば上の例は、@FUNC
の終わりでは必ずCOUNT
が3
になるので、呼び出し元のREPEAT
文から脱出することが出来ません。
関数を呼び出す際にCOUNT
を別の変数へ待避すれば問題は起きませんが、eramakerでは確実な待避先が存在しないので、根本的な解決は出来ません。 Emueraであれば、LOCAL
変数を待避先に使うか、REPEAT
文をLOCAL
変数をカウンタにしたFOR~NEXT
文に置き換えることで解決します。
コメント行に注意¶
コメント行は適切に配置・記述してあれば、デバグや改造の助けになるが、ときどき失敗することがある。 たとえばコメント行を記したつもりでついうっかり先頭の;
を忘れてしまったり消してしまったりした場合である。
もちろん、そのときは基本的にそこでエラー落ちするわけだが、コメント内容によってはそうでない場合もある。例えば、
;デバグのときはここで以下のとおりにすればお金は減らない
;なおMONEY:1は掛かった経費とする
;MONEY:1 = 0
MONEY -= MONEY:1
上記のように書きたかったコードが下のようになってしまうと
;デバグのときはここで以下のとおりにすればお金は減らない
;なおMONEY:1は掛かった経費とする
MONEY:1 = 0
MONEY -= MONEY:1
ERB文法的には間違っていないので下の記述でもエラー落ちはしない。 だが、内部挙動は全然違っているため作者が望むとおりの結果は得られていない。こういうバグもまた恐ろしいものである。
PRINTFORM
のFORM
は大切です。¶
よくあるのが%CALLNAME:MASTER%などの名前を表示するときに下のようにしてしまうことである。
PRINTL %CALLNAME:MASTER%は%CALLNAME:TARGET%を抱いた
%CALLNAME:MASTER%
は文字型変数であるのでそれの内容を表示するためにはPRINT
(文をそのまま表示)ではなくPRINTFORM
(変数を変換して表示)を使用しなければならない。ちなみに上の例だと
%CALLNAME:MASTER%は%CALLNAME:TARGET%を抱いた
と表示されてしまう。
基本的にPRINTFORM
はPRINT
の完全上位互換なので、よくわからなければPRINTFORM
を使っておけばよい。
また無印、L
、W
の使い分けだが、PRINTFORM
は改行なしで表示も止まらない、PRINTFORML
は改行ありだが止まらず次の行も表示、PRINTFORMW
は改行してその行で表示を止めるというのを覚えておこう。
(関数が)かぶった!?¶
eramakerでは同じ名前の関数を複数定義してもエラーとしては検出されません。そのため、関数名を被らせてしまうと、何もエラーは出ないけど、何かがおかしいという一番困った状況に陥ります。
そのため、後述するシステム関数など変更できない特別な事情があるもの以外は、同じ関数名を利用しないようにしましょう。
同名の関数をCALL
などで呼び出した場合の優先順位は、ファイル読み込み順に依存します。同一ファイル内では、ファイルの先頭に近い方が呼び出されます。ファイルの読み込み順はeramakerではファイルシステムに依存しますが、Emueraではコンフィグである程度は制御が可能です。
なお、RR系列の口上呼び出しはこの仕様を利用しています。
また、口上内で独自関数を作る場合、別の口上でたまたま同じ関数名を使っていたりすると誤動作の原因になります。関数名にK(キャラ番号)を含めるなど被らないよう工夫しましょう。
イベント関数は通常の関数と異なり、複数同じものがあってもすべて実行する仕様(#SINGLE
がある場合は特殊)になってます。イベント関数がどれであるか?というのはwikiのほかの記述や本家の記述を参考にしてください。
RANDの使い方¶
RAND
(乱数選出)は特に口上を書く際によく使われる便利な構文だが、使うときに気をつけるべき点がある。
まずRAND:X
で選出される数値は0~(X-1)
の間で、X
の数値が選ばれることはない。つまりIF RAND:3 == 3
という分岐を作っても絶対に条件が満たされない死に分岐となってしまう。
また、以下のようなミスも行いやすい。
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
の確率で何も表示されなくなってしまう。
等確率で表示されるようにしたい場合、以下のどちらかの形式で書く必要がある。
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の確率で表示される。
変数を利用する場合は以下のようになる。ただし変数が本体やパッチがその部分の処理で使用しているものとバッティングしないように注意。
A = RAND:3
IF A == 0
PRINTFORMW 「あ」
ELSEIF A == 1
PRINTFORMW 「い」
ELSE
PRINTFORMW 「う」
ENDIF
なお、Emuera専用ならば拡張文法を用いた以下のような記述も使える。当然eramakerでは使えないので注意。
例)SELECTCASE
を使った処理
SELECTCASE RAND:3
CASE 0
PRINTFORMW 「あ」
CASE 1
PRINTFORMW 「い」
CASEELSE
PRINTFORMW 「う」
ENDSELECT
例)PRINTDATA
を使った処理
PRINTDATAW
DATAFORM 「あ」
DATAFORM 「い」
DATAFORM 「う」
ENDDATA
最後の改行は重要だ。¶
eramakerにおいては、ERBファイルにせよCSVファイルにせよ、最終行は読まれない。つまり、一番最後は改行してから終了しよう。
以下はとあるERBファイルの末尾である。最終行のENDIF
できっちり終わっている。
IF RESULT == 0
CALL REPLAY_GAME
ELSEIF RESULT != 1
GOTO INPUT_LOOP
ENDIF[EOF]
さて、上の例。Emueraなら何の問題もないが、eramakerの場合、一番最終行のENDIF
が認識できずにエラーになってしまう。必ずENDIF
のあと改行してから保存しよう。そうすればエラーにならない。すなわち、
IF RESULT == 0
CALL REPLAY_GAME
ELSEIF RESULT != 1
GOTO INPUT_LOOP
ENDIF[CR]
[EOF]
とすればOKである。
命令文や条件文は半角空白で区切る。¶
各命令文の後ろには必ず半角スペースを入れる必要がある。
わかりやすいようこの項では半角スペースを_
、全角スペースを□
と表記するが、実際書く時は「_
」ではなく「」と書くように。
PRINTL_ロードします
下の例は両方ともeramakerが正常に解釈できずエラーが出てしまう。
前者はPRINTL
の後に空白がないため、後者はPRINTL
の後に半角ではなく全角スペースを入れているため、PRINTL
を命令文だと認識できないからである。
PRINTLロードします
PRINTL□ロードします
また、複数の条件文を並べる場合も、それぞれの間に半角スペースを入れなければならない。
○: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
を分岐条件に使っても構わない。