システム改造Q&A¶
元となったページ
eraシリーズを語るスレ まとめWiki V3 システム改造Q&A
主に新バリアントや大規模パッチの作者向けのプログラミング情報をまとめたページです。
特に記載が無い限り、その時点で最新のEmueraで動作させる事が前提になります。
eramakerや古いEmueraでは上手く動かない場合があります。
基礎知識¶
プライベート変数について(A~ZやLOCALではなく#DIMで)¶
- 関数の中だけで使う変数は#DIMで宣言して使う
- セーブしたいデータを増やす時は#DIMをERHファイルに書いて使う
- 普段からLOCALを使う理由は思いつかないけど、サンプルコードでは使います
古いerabasicでは、一時的に使う変数としてA~Z
の一文字変数を使っていますが、現在は推奨されていません。
あちこちで同じ変数を使えるので、CALL
した先で書き換えられる等して、気付かない間に値が変わってしまうことがあるからです。
でもループ回数を記録したり、計算の途中経過を保存したりという事に使える変数が他にありませんでした。
そのため、その関数の中だけで使える変数(ローカル変数)として、LOCAL
という変数が追加されています。
(文字型のローカル変数はLOCALS
)
しかしこれは名前が全部LOCAL
なので、1つ2つならいいのですが、LOCAL:1
とかLOCAL:4
とか色々使っていると、プログラムの見た目が悪くなり、それぞれ何に使っている変数なのかもわかりにくいという問題がありました。
そこでさらに新しく追加されたものがプライベート変数です。#DIM
と作りたい変数の名前を書くことで、その関数でだけ使える変数を新しく作ることが出来ます。
@EVENTFIRST
#DIM LCOUNT
LCOUNT = 99
#DIM
はそれぞれの@~~~
の直後に書かないと無効です。別の関数では使えません。セーブもされません。
文字列型は#DIMS
で作れます。巨大な配列等も作成可能です。詳しくは下記ページを参照して下さい。
ユーザー定義の変数
LOCAL
にはもう1つ使い方があって、「LOCAL@USER_SHOP
」のようにして、後ろに関数名を付けると他の関数の変数が書き換える事が出来ます。(本来はデバッグ用の機能です)
以前はこれを利用して広域変数の不足を補っていたのですが、そういう使い方をしてしまうとローカルでもなんでもなくなって、結局A~Z
と同じような問題が出てきます。
こちらも今では#DIM
で新しい名前の変数を作るのですが、@~~~
の直後ではなく、ERHファイルを作ってその中に書きます。
セーブするかしないか、あるいはグローバルデータにセーブするかも決められます。
最近の大規模バリアントではだいたいERHが使われているので、見慣れない変数名があって困った時はERHの拡張子のファイルを探してみて下さい。
(ERBフォルダの直下に置いてある事が多く、複数ある場合もあります)
ERH(ヘッダーファイル)について
今あえてLOCAL
を使う理由は、パッチを作る時にプログラムを大きく変えたくない、Emueraのバージョンを上げたく無いという時ぐらいだろうと思います。
ただ、このページ内で解説に使っているサンプルコードにはLOCAL
を使っている場合があります。
サンプルが関数全体ではなく部分的な物になる場合、書く場所が関数ラベルの直後に限定された#DIM
とは相性が悪いためです。
実際にバリアントやパッチ制作に使う場合は、LOCAL
やLOCAL:1
などといった部分を#DIM
で作った変数に置き換えて下さい。
最後に一般的なプログラム言語でいうローカル変数との違いを説明します。(erabasic以外使った事がない人は無視してです)
Emueraのローカル変数は、C言語やJavaScript、Rubyといった今普及しているプログラミング言語でいうローカル変数とは違います。LOCAL広域変数にあたります。
#DIM
宣言でも前回の関数呼び出し時のデータは残っているので、性質的に広域変数に近いです。
通常それで困ることはないですが、いわゆる再帰処理を作る時等に問題になります。同時に呼び出されている関数が全て同じ変数を読み書きしてしまうのです。
Emueraで一般的な意味でのローカル変数を作るには、#DIM
の時にDYNAMIC
を付けて宣言して下さい。
関数の中での移動方法(制御構文)¶
erabasicのプログラムは(他のプログラム言語でもだいたいそうですが)、上から下に、書いてある順番通り実行していくのが基本です。逐次実行といいます。
小説や映画のように順番通り進めていく物はそれでいいのですが、ゲームの場合条件によって次に何をするかがかわってきます。こういう順番を変更するためのプログラムを制御構文といいます。
同じ本でもゲームブックには「勇者の剣がある場合は23ページへ」等と書いてあって、読者はこれに合わせて次のページではなく指定のページを開きます。つまり読者へ向けた制御構文です。
制御構文にはCALL
やJUMP
のような別関数を使うものや、ゲーム終了の命令なども含まれるのですが、ここでは関数の中で実行順序を変えるものについて書きます。
文の名前 | 前に進む | 後ろに戻る | 他の制御構文の中への移動 |
---|---|---|---|
TRYGOTO・GOTOFORM | $ラベル | $ラベル | 出来るけど非推奨 |
GOTO | $ラベル | $ラベル | 出来るけど非推奨 |
LOOP・WHILE・FOR | ループの先頭 | ループの終わり | ☓ |
IF・SELECTCASE | ELSE・ENDIF・CASE | ☓ | ☓ |
RESTART | ☓ | 関数の先頭 | ☓ |
基本的には色々使える強力な構文より、範囲を限定した命令文を使う方が安全で見やすいプログラムになります。
どれを使っても良さそうな場合は、上記の表で言えば下にある物を優先して使って下さい。
制御構文の基本はGOTO
文です。これにIF
文や簡単な計算式を組み合わせるだけで、他の構文は全てGOTO
で書き直すことが出来るからです。 ただ強力すぎるので想定外の事が起きやすく、なるべく使わない方がいいとされています。
(詳しく知りたい人は”構造化プログラミング”について調べてください)
必ず対応ラベルが必要になるのも欠点で、どのラベルとどのGOTO
が対応しているのか、他の書き方に比べて構造がわかりにくくなる傾向にあります。
古いerabasicでは、入力結果が正しくない場合にループさせるためのGOTO
が頻繁に使われています($INPUT_LOOP
)が、大部分はLOOP
文かWHILE
文で置き換えられます。EM+EEではBINPUT
という命令もあります。
GOTO
にしかできないのは別の制御構文の中に移動することですが、これはなるべくやらない方がいいです。
例えばFOR
ループの外からループの中にGOTO
すると何回目のループなのかよくわからなくなります。 IF
文なら条件を満たしてないのに実行される可能性が出てきます。バグではないのでemueraは規則通りに正しく動作しますが、その規則が思っているのと同じとは限りません。
同じ制御構文の中での移動や、構文の中から外への移動であれば問題はありません。特に何重にもなったループの中から一気に外に抜け出すのはGOTO
の有効な使い方の一つです。
(GOTO
を使わないと、複数のBREAK
やCONTINUE
、IF
文等の組み合わせが必要で、かえってわかりづらくなります)
TRY
系制御構文はパッチや口上等で、その関数(が書かれたファイル)があってもなくても動くような仕組みの場合に使います。
FORM
系制御構文は変数の状態によってジャンプ先を変えるのに、SELECTCASE
と大量のGOTO
文を書きたくない、もしくは後で数を増やしたりする時に使います。
欠点は起動時にはラベルが正しいか判断できず、実行してみないとわからないのでバグに気付きづらい事です。
CALL
やJUMP
はともかく、GOTO
はその関数の中だけの話なので、あまり有効な場面はないと思います。
-
繰り返し(
LOOP
,WHILE
,FOR
)
繰り返しも制御構文の1つです。
指定された条件で繰り返すのは条件付きのGOTO
ですが、それ以外にもCONTINUE
で先頭部分へのGOTO
、BREAK
でその制御構文の直後にGOTO
と同じ事が出来ます。
(無限)ループの最後にBREAK
を書いておけば繰り返しにならず、CONTINUE
しない時はそのまま先への進むので、後ろへ向かうGOTO
文を置き換えることができます。 -
分岐(
IF
,SELECTCASE
)
条件に一致していないIF
文はELSE
の直後へのGOTO
、ELSE
がなければENDIF
の直後へのGOTO
と同じ意味になります。SELECTCASE
は複数の条件が一度に設定出来るGOTO
です。
分岐は前の方に進んでいく制御には使えますが後ろに戻るためには使えません。条件付きで後ろに戻るようにしたい場合は、別の命令文と併用する必要があります。 -
RESTART
関数の先頭部分へのGOTO
です。@SHOP
や@ABLUP
などでキャンセルした場合最初の画面にもどってやり直すような動作で使われています。
最初からやり直すわけではなく先頭部分へのGOTO
なので、変数は初期状態ではなく変更後のものになっています。
先頭ではなく先頭のちょっと下に移動したい場合は、その場所にラベルを作ってGOTO
か、繰り返し構文とCONTINUE
を使う事になります。
繰り返し処理の書き方(FOR
とREPEAT
の違いと推奨書式)¶
REPEAT
はなるべく使わないFOR
はプライベート変数かローカル変数とセットで使うWHILE
とDO
は上級者向け。ループ回数を事前に把握しにくい時等に使う
同じような事を何回も繰り返す処理、というのがerabasicでは頻繁に出てきます。
一番わかりやすいのは所有キャラの一覧表です。1番目のキャラの名前やパラメータを表示、2番目のキャラの名前やパラメータを表示…というのを繰り返して作ります。
全員の体力を回復させる時も同じように、1人目のHPを増やして、それを人数分繰り返します。
REPEAT~REND
はerabasicの初期から使われてきた繰り返し処理の構文です。
これは簡単に書ける反面いくつか問題がある事がわかっています。
何回目かを調べるためのCOUNT
変数が広域変数なので、REPEAT
を2つ重ねるような仕組みは作れないし、REPEAT
中にCALL
された関数の中でREPEAT
を使うと、CALL
が終わった後で順番がめちゃくちゃになります。
そこで用意されたのがFOR~NEXT構文です。
COUNT
以外の変数も使えるようになるので、上記のような問題は起こりません。
(COUNT
を含めた広域変数も使えますが、それだとREPEAT
でも一緒なので、通常はプライベート変数を使います)
数字も0からではなく変えられるので、「あなた(0番のキャラ)」を除外したい時に番号0ではなく1から繰り返しを始めるといった事が出来ます。
他のプログラミング言語ではFOR
文の中で専用のローカル変数を宣言出来るものもありますが、EmueraのFOR
文にはその機能がないので、他の変数と同じように#DIM
で宣言して下さい。
FOR
で使う変数名はなんでもいいのですが、「繰り返しに使う時に使うのはこの名前」と決めておいた方が、後で見た時にわかりやすくなると思います。
他の言語では慣習的にi
、複数のループを重ねる時はi,j,k
等を使う事が多いのですが、erabasicだとA~Z
がグローバル変数で、小文字と大文字も区別しないのでこの手は使えません。
案としてはローカルとわかるように先頭にL
を付けてLCOUNT
、COUNT
を縮めてCNT
、グローバル変数と区別するために_
を付けて_I
、いっそ日本語にしてカウンタ
、などなど色々考えられますが、長さとわかりやすさ等好みのやり方を選んで下さい。
;例:全員の体力をMAXにする
@~~~~
#DIM LCOUNT
FOR LCOUNT, 0, CHARANUM
BASE:LCOUNT:体力 = MAXBASE:LCOUNT:体力:
NEXT
他に繰り返しに使える構文として、WHILE~WENDがあります。
主に何回ループさせたらいいのかわからない場合に使うので、2つはよく似ていますが、終了条件をループ前にチェックするか、ループ後にチェックするかの違いがあります。
簡単にいえば、1度もループ内を実行しない可能性がある時はWHILE
、必ず1度は実行する場合はLOOP
、という使い分けになります。
ただBREAK
やIF
の書き方次第でどちらでも同じ事は出来るので、正しく動けば後は好みの問題です。
どちらもカウンタ用の変数を設定しないので、何回目のループか調べたい時は、自分でループ前にローカル変数に0を代入して、ループ毎に1づつ増やすような処理を書く必要があります。
良く使われるのはBREAK
するまで無限ループするパターンで、WHILE 1~WEND
、DO~LOOP 1
、どちらも同じ動作です。
(条件部分が1
だけだと必ず条件を満たします。数字は2でも3でも999でも、0以外ならいいのですが、慣習的に1を使います)
WHILE
とDO
は他の言語で使った事がないと、どういう時に使うのか想像しにくい構文だと思います。
実際のバリアントで使われている例を調べると、独自の並べ替え処理(ソート)、否定の珠がなくなるまで他の珠を減らしつづける、レベルアップ時のパラメータ割り振りが終わるまで繰り返す…等といった使い方がありました。
ありえないぐらい大きな数のFOR
文や、IF
文とGOTO
文の組み合わせでも可能ですが、意味の無い大きな数字を書くのは気持ち悪いし、GOTO
だとラベル名を考えるのがめんどくさいので、WHILE
やDO
の方がすっきりと書けます。
例えば別項目のCSVのキャラクター一覧を表示する時も、途中の番号が欠番になっている可能性を考慮してFOR
文を使っていますが、仮に欠番が無いとわかっている場合であればWHILE
(DO
)が使えます。 無限ループを作って、EXISTCSV
に失敗した時点でBREAK
すればスマートです。
使用例:「はい」「いいえ」の選択式で、「はい」と答えるまで先に進まないプログラム
PRINTL お主なら「はい」を選んでくれると信じておる……選んでくれるな?
DO
PRINTL [0]はい
PRINTL [1]いいえ
INPUT
IF RESULT==0
BREAK
ENDIF
PRINTL もう一度言うぞ。選ぶのは「はい」だ
LOOP 1
RESULTと式中関数¶
RESULT
は関数の結果を返すために使われる変数です。
RESULT
がよく使われるのはINPUT
命令の直後だと思いますが、どの関数をCALL
してもRESULT
は書き換えられます。
複数の関数を実行してその結果を足し合わせるといった場合、その都度プライベート変数にRESULT
の中身をコピーしておかないと、最後に実行した関数のRESULT
だけしかわからなくなります。
そしてどうせプライベート変数に入れる場合、式中関数を使った方が早いです。組み込み関数にも多くの場合式中関数版が用意されています。
;通常の関数呼び出しの場合
CALL TEST 70
LOCAL = RESULT
;式中関数の場合
LOCAL = TEST(70)
自分で作る関数も式中関数にする事が出来ます。
下記に当てはまる物は式中関数と作った方が都合がよくなる事が多いでしょう
- INPUT
等文字の入力はしない
- PRINT
文等で文字を表示しない
- CFLAG
やABL
等変数を書き換えていない(読み込みだけならセーフ)
IF
・ELSEIF
のかたまりはSELECTCASE
文に出来るかも¶
ひとつの変数とか計算結果とか乱数とかでたくさんの分岐を作りたいときがあります。
入力によって違う結果出したりとか。乱数によって違う結果出したりとか。
そういうときです。
そんなとき、IF
文だとIF
とかELSEIF
とかの後に一個一個評価式を書かなければなりません。
割と手間ですしミスが紛れ込む原因にもなります。
そんなとき役立つのがSELECTCASE文。
一個のものを評価して複数に分岐するための命令で、IF
より速いです。
評価対象を書かないといけないのはSELECTCASE
の後に一回だけ。
あとはCASE
の後に条件を書いていけばいいだけです。だいぶすっきりします。
以上以下ならIS
、範囲を問うならTO
とかありますが詳細は上のリンクからどうぞ。
締めはENDSELECT
。簡単ですね。
;ただLOCALで分岐するよりちょっと手間なものにしてみた
;IFを使った分岐
IF LOCAL+LOCAL:1 == 0
PRINT 0でした
ELSEIF LOCAL+LOCAL:1 == 1
PRINT 1でした
ELSEIF LOCAL+LOCAL:1 == 2
PRINT 2でした
ELSEIF LOCAL+LOCAL:1 == 3
PRINT 3でした
ELSE
PRINT 0から3ではありませんでした
ENDIF
;SELECTCASEを使った分岐
SELECTCASE LOCAL+LOCAL:1
CASE 0
PRINT 0でした
CASE 1
PRINT 1でした
CASE 2
PRINT 2でした
CASE 3
PRINT 3でした
CASEELSE
PRINT 0から3ではありませんでした
ENDSELECT
初期設定について¶
CSVとERBと2つの設定方法がありますが、一度設定したら変更しない物、タイトル画面だけで使う物などはCSVでしか設定できなくなっています。
下記の表以外にもいくつかありますが、だいたいGAMEBASE.CSVか_replace.csvで設定できるので、ここに書いてない物はCSVではなくERBで設定する物です。
項目 | 設定に使うCSV |
---|---|
タイトル・作者名・製作年等 | GAMEBASE.CSV(※1) |
初期状態で存在するキャラ | GAMEBASE.CSV(※1※2) |
キャラクター名、初期能力 | CHARA*.CSV |
Now Loading表示 | _replace.csv |
お金の単位 | _replace.csv |
汚れの初期値 | _replace.csv |
TINPUTの時間切れ表示 | _replace.csv |
EXPLVが上がるタイミング | _replace.csv |
PALAMLVが上がるタイミング | _replace.csv |
RELATIONが未指定の場合の値 | _replace.csv |
※1 @SYSTEM_TITLE
を定義した場合は無効
※2 0番のキャラクタは強制加入で、0番以外に1名だけ指定出来る。
所持金や初期アイテムは普通@EVENT_FIRST
関数で設定します。新しくゲームを始める場合に一度だけ実行されるので、初期設定に向いています。
設定する前に難易度選択を挟んで、難易度によって変えるという流れもよく使われています。
キャラクタについても同じです。0番のキャラクタ(ほとんどのバリアントでは「あなた」)は自動加入ですが、他に初期加入のキャラクタが必要なら手動で追加しなくてはいけません。
1人だけならGAMEBASE.CSV
でも出来ますが、複数居る場合は1人だけCSVで設定すると混乱するので、全員ERB側で追加するのが無難です。
主人公選択式の場合はいったん0番のキャラを削除してから別のキャラクタを追加します。
それぞれがAIで行動するタイプのゲーム(era紅魔館、era恋姫等)は、仲間や奴隷にしていない状態でもキャラデータが必要なので、最初に全員ADDCHARA
してデータを作っておいて、必要な分だけ表示する仕組みになっています。
emuera.configは同梱しない¶
配布ファイルにemuera.config
を含めると、バージョンアップの時にプレイヤーがカスタマイズした設定を上書きしてしまいます。
ただ何も設定が無いとレイアウト等が大幅に崩れてしまう場合が多いので、[_defaulf.configの仕組みを使うと便利です。
具体的な手順は以下のような感じになると思います。
オプションを変えない更新の場合は(4)だけでいいです。
- 普通に自分好みの設定にして
emuera.config
を作る emuera.config
をcsvフォルダにコピーして、_default.config
に名前変更する
(派生バリアントの場合など、元々_default.config
がある場合は、それを消すか別の名前にしておく)- exeと同じフォルダにある
emuera.config
を消して、その状態起動とセーブ・ロードに問題がないか確認する - 上記(3)の時に
emuera.config
が作られているはずなので、もう一回emuera.config
を消してzipに圧縮する
見た目が崩れるとかではなく、完全に動かなくなるレベルの設定はcsvフォルダに_fixed.config
を作る事が推奨されています。
例えば_Rename.csv
や_Replace.csv
の設定は_fixed
向きです。
そんなオプション普通は変えないのでdefaultだけでもいいのですが、大幅バージョンアップ等で途中で設定を変えた場合、そしてそれが必須の場合は_fixed.config
を使ってください。
_fixed
にはしたくないけど重要なオプションを変えた場合は、いったんemuera.config
を消してから遊ぶようにプレイヤーに伝えてください。
(プレイヤーの立場からは、バージョンアップで異常が起きた場合、いったん手元のemuera.config
を消して動くか確認して、それから作者に報告すると良いです)
ウィンドウ幅とウィンドウ高さはバリアントによっては超重要ですが、_fixed
にはしない方がいいです。
フォントの種類やサイズを変えて、画面サイズも調整して遊ぶ事がよくあるので。
ファイル名はわかりやすく¶
- ファイルを説明する1行コメントと考える
- 新しく追加するファイルは日本語推奨
- 派生元からあるファイルで、特に機能も変更していない場合はそのままで良い
- 途中で名前を変えた時は、パッチの形ではなく全体を配布する
- 悩む時は関数の詰め込みすぎや統一感がない場合があるので、ファイルを分けた方が良くないか考える
(関数1つまで分けても悩む時は、1つの関数に詰め込みすぎの可能性あり)
eraRoronaのファイル名の付け方はとても参考になります。
例えば調教関連フォルダ、先頭に番号を付ける事でファイルの並び順を揃えて、実行される順番や場面ごとに整理されています。
フォルダ分けも有効ですが、あまり細かく分けるとファイルが探しづらくなるので、そういう時に先頭に番号を付ける管理法はおすすめです。実行する順番がわかりにくい場合にも効果的です。
またABL
やChara.csv
では、従来の名前と説明とを_
でつなぐ事で、従来のバリアントでいうどのファイルにあたるかも、内容がどういうものかも、両方同時にわかるようになっています。
派生バリアントからあるファイルの改名にはこの方法が良さそうです。
変数名・関数名の付け方¶
- 大文字小文字を区別するオプションは使わない
- 複数の英単語をつなげる時は空白の代わりに_でつなげる
- 何度も繰り返し使う物は短い名前に、回数が少ないものはわかりやすさ優先
- スッと名前が決まらない時は日本語の名前を積極的に使う
TALENT
やABL
などのシステムで使われている単語の部分はそのままにする。無理に日本語訳しない
日本語名に関しては、過去のトラウマや入力切り替えが面倒、英語圏の人が開発に参加している等の理由で使わない人もいますが、そういった理由がなければ使った方がいいと思います。
英数字にこだわりすぎた場合に起こる問題として、例えば全部時間関係だからといってTIME
、TOKI
、TIMER
、TIME2
…等と色々作ってしまって、あとで見た時に全然わからなくなるということがあります。 わからない名前を付けて、わかるようにコメントを付けるのは二度手間です。
複雑な計算式等で何度も同じ変数が出てくる場合は、名前が長いとめんどくさいので、短さや書きやすさを優先する場合もあります。
それとemueraの大文字小文字のオプションは半角文字には効きますが、全角文字には効かないので注意が必要です。ゲーム中の固有名詞でもなければ、全角アルファベットは変数名に使わないのが無難です。
マジックナンバーをなくす¶
- 書き換えた方がいい数字
- キャラクタや素質等の、内容と関係ない整理番号
- 上限の値などの特別な意味をもつ数字
- 同じ数字が何度も出てきて、それが同じ意味を持つ場合
- そのままでいい数字
- 何番目等の数字自体の意味があるもの
- 変数や定数の初期化のための数字
- 判断が難しい数字
- 初期値、最低値
- その関数の中だけしか使わない、1度だけ使われる数字
[200]~
のようなコマンド番号
プログラミングで言うマジックナンバーとは、見ただけでは意味がわからない、コメントがないとわからないような数字のことです。
eraの場合だと、技巧の値を参照するためにABL:2
と書いた場合、この2
という数字がマジックナンバーです。
ABL.CSV
で2番として定義されている能力という事がわかるだけで、バリアントによっても違うし、そもそも2
という数字と技巧とは全く関係がないです。
表示関連等では、2番目である事に意味があって、技巧である事には意味がない場合もあります。この時は2と書くべきです。技巧と書く方が意味をわかりにくくします。
主な書き換え方法は下記の3つです
- ABL:技巧
のようにCSVの表記で書く
- 定数を作る#DIM CONST(変数や式中関数でも可)
- #DEFINE
も使えますが、扱いが難しいので上級者向けです。
例えばキャラクターの最大人数、それが100だとして、いろんなところに100を書いてしまうと、それを見て最大人数だとすぐにはわかりません。
#DIM CONST 最大人数 = 100
このようにERHに書いておくと、後で人数を変える時も簡単だし、「最大人数」でGREP検索すれば使用箇所も簡単に調べられます。
最大値関係はだいたい定数にした方がいいのですが、最小値は場合によります。
FOR
ループを作る時に#DIM 最小人数 = 0
と書いても、わかりやすさにはつながりません。
しかし0番のあなたを飛ばして1から始まるFOR
ループの時、この1
を定数にするかは悩むところです。
#DIM CONST あなたを除く先頭 = 1
のように書いてもいいですが、むしろ1を使わず0からのループにして、== MASTER
の時だけCONTINUE
するように書き換える方が自然かもしれません。
コマンド番号については、PRINT
部分とIF
(SELECTCASE
)部分とで統一してください。もし条件部分を定数にするなら選択肢の表示部分もPRINTFORM
等で同じ定数を使います。片方だけ定数にする意味はないし、何か特殊な意図があるのかと深読みされるので。
マジックナンバーの変更例(キャラクター指定)¶
ADDCHARA
やGETCHARA
でキャラクターを指定する場合、Emuera側に対応機能がないので、マジックナンバーとしてソースコードに残りがちです。
ショップでキャラを買う時などは販売番号のままで問題は出てこないのですが、イベント関連ではキャラを指定するために番号が必要になってきます。
Emueraでは現在キャラクタを名前で指定出来るのはRELATION
配列だけです。それ以外は全部番号指定なので、最終的には数字になるのですが、その途中については工夫出来る部分があります。
考え方としては、主に2つのパターンがあります
- _Rename.csv
やERHを使う
- GETNUM
を使う
1つは対応する定数を作る方法。
eraMegatenでは_Rename.csv
でキャラ名と番号の対照表を作って、実行時にそのキャラの番号に置き換わる仕組みになっています。
ADDCHARA [[キャラ:アメノウズメ]]
のように書くことが出来ます。
番号よりもわかりやすい表記になって、かつ誤植があると起動時に警告を出してくれるのが便利です。
角かっこが若干邪魔なのと、CSVの準備が大変なところが欠点です
準備についてはeraMegatenでは生成用のERBを作って、CSVの中身やTRYCALL
で必要なデータをPRINT
文で表示、ログを保存で保存した物が_Rename.csv
として使えるようにしています。
手作業でやるとその段階で誤植や追加を忘れるなどのミスが必ず起こるからです。特に_Rename.csv
はファイルを分けられないので、パッチごとに個別に追加していくと面倒なことになります。csvではなくERHで定数を作る場合も同じです。
人数が少ない場合は手動でも大丈夫です。名前の指定が必要なキャラは通常多くないので、全キャラではなく最低限必要な分だけ書いておく方法もあります。
それと定数化全般の問題ですが、誤植でのエラーは検出されますが、別の種類の定数と勘違いした時はエラーが出てきません。
例えばGETCHARA
に間違って建物名を書いても、たまたま同じ番号のキャラをチェックしたり、必ず居ない状態になったりするだけで、エラーが出ません。
このへんはどうしても公式機能による名前表記に劣ります。
2つ目はGETNUMにNAMEで指定する方法です。Emuera ver1.819以降が必要になります。
たとえばeratohoではGETNUM(CALLNAME, "霊夢")
と書けば、霊夢の番号が取得できます。
実用例は見かけないですが、理屈ではこの2つは併用出来ます。
例えば_Rename.csv
で[[霊夢]]
を"霊夢"
に置き換え、ADDCHARA GETCHARANO([[霊夢]])
と書くと、起動時と実行時の両方で厳密にチェックされます。
ただ最初の準備に手間がかかるので、どちらか片方を使えば十分だと思います。
2の方が準備などが不要で、本体の更新のみで使用できるのでおすすめです。
GREPのやり方¶
バグの原因を調べたり、派生元の仕組みを調べたりするのに、GREPによる検索はほぼ必須です。
GREP機能はサクラエディタやVSCodeに標準搭載されています。サクラエディタならCtrl+G、VSCodeならサイドバーの検索メニューから検索してください。
検索には通常の文字をそのまま検索するパターンと、正規表現という特殊な記法を使った調べ方があります。
例えばFLAG:100
を使った場所を特定したい時、普通に検索するとTFLAG:100
もCFLAG:100
も引っかかりますが、正規表現で[^TC]FLAG:100
という風に書けば、直前にT
とC
が付いてないFLAG
だけを探せます。
[^TC]FLAG:10[0-9]
なら、FLAG:100~109
が引っかかります。
細かい文法は正規表現についての解説サイトなどを見てください。
量が少なければ、正規表現を考えるより、普通に検索して目で探した方が早いという事もよくあります。方法はともかく見つかればいいので。
次に探し方ですが、基本的には次の3パターンです。
- 変数名や関数名で検索する
- 調べたい事柄についてコメントに書いてありそうな文字を検索する
- 調べたいタイミングで画面に表示されている文字を検索する
1.使われている変数や関数がわかっている場合は、単純にその名前で検索すれば、それらが使われている場所がずらっと出てきます。
正規表現を上手く使えば、その変数を使っている場所と、書き換えている場所と区別して探す事も出来ます。
対象がわかっていても、それがLOCAL
とかA
とかだとこの方法は上手くいきません。わかりやすい変数名は検索しやすい変数名でもあります。
2.「恋慕」とか「妊娠」とかに関連した仕組みを探したい時は、その単語で検索すればだいたい見つかります。
画面にメッセージが出てこない部分を探す場合もこの方法になります。
この方法の欠点は、コメントが書かれてないと駄目というのと、変数名などと違って表記ゆれがあると検索にかからないことです。コメントがあっても、「妊娠」じゃなく「にんしん」や「懐妊」と書いてあれば見つかりません。
コメントを書く時には検索する時のことも考えておかないと、自分でも見つけられなくなる事があります。
3.は多少コツが要ります。画面に出てる内容が、プログラムやPRINTFORM
で整形された結果かもしれないからです。
胸が大きくなる時の処理の入ったバリアントを調べる時、
<○○○の胸が大きくなった>
というメッセージを検索しても、絶対に検索結果には出てきません。なぜなら○○○
のところはキャラによって違うので、そのままの文章でERBに書かないからです。
こういう場合は単語を細かく切って調べてきます。第一候補は「胸が大きくなった>
」ですが、仮に胸とお尻が共通の仕組みなら、これでも駄目かもしれません。「大きく」と「小さく」もプログラムで処理されている可能性があります。
何も引っかからない、引っかかっても違うものばかりという時は、「が大きくなった
」「大きく
」「胸
」 「なった
」…という具合に試していきます。
区切って上手くいかなければ、直前か直後の文章で、探せるものから探します。その文章の近くにCALL
があればCALL
の先も見に行きます。そうやって流れを追っていけば必ずたどり着きます。
調教ものバリアント前提の話のため折りたたみ
### 調教コマンドの実行判定の違いについて 1. 表示されていて実行できる(普通の) 2. 表示されているけど実行できない(対象のやる気や`PALAM`が足りてない) 3. 表示されていないし実行も出来ない(アイテム不足、性別が違う、アナルが狭い等) 4. 表示されないけど実行できる(派生コマンド) 5. どうやっても実行できない(バグや作成途中、バランス崩壊で無効化等) 調教コマンドはこの5つに分類されて、自分や相手の状況によって変化します。 少しわかりにくいのが(2)と(3)の違いで、同じ出来ないコマンドなのに表示されているのといない物で違いがあります。 基本的には(2)は実行値不足で、実行値は調教対象のやる気を数値化したものです。 欲情や潤滑を高めることで実行値は変動するので、その時間帯の調教の間にも実行できる可能性があります。 例えば自慰をするだけなら特殊な技術は要りませんが、本人がやる気にならないと出来ません。(こちらからやると愛撫になる) フェラチオも同意が無いとイラマチオのような形になるし、噛まれるかもしれません。 実行出来ない事と必要実行値を示すだけで終わる事もありますが、拒否口上が出たり体力減少を伴うこともあります。 実行値判定が複数あるバリアントもあって、同じ実行するにしても、強引な形になるか、合意を得てスムーズにやるかが変わります。 (3)はアイテムが足りなかったり、ABLが足りなかったり、ともかくその調教中には出来そうにないものがこの扱いになります。 `ABL`上昇やアイテム購入など、調教の後でしか条件を満たせず、満たした場合その次の調教から使えるようになります。 人を選ぶコマンドについてオプション画面で表示切り替えする時にも使えます。 (4)の派生コマンドは、特定のコマンドを組み合わせる事で出来る裏技的な存在です。 クンニとフェラチオと連続させるとシックスナインなど、多くのバリアントで採用されています。 3つ以上のコマンドでも原理的には可能ですが、だいたい直前のコマンド(`PREVCOM`)と現在のコマンドと2つの組み合わせで発動します。 裏技だけあって通常のコマンドよりも効果が強力な事が多いです。 (5)はコマンドが増えすぎた場合に使われていましたが、最近だとオプション画面で設定して、そのフラグを条件に(3)の仕組みで非表示にする事が多いです。 バリアントの方針や作者の好みでも違いますが、だいたいこういった分類です。 奉仕系でも難度が高いものは`ABL:奉仕精神`などが足りないと非表示の(3)で、表示後も高い実行値も必要なコマンドもあります。 コマンドの表示条件は、以下の2点です。 - `Train.csv`に記載がある - 対応する`COM_ABLE◯◯◯`関数の返り値が1、もしくは`COM_ABLE◯◯◯`関数自体が無い 常に(1)である場合は`Train.csv`に書くだけで、`COM_ABLE◯◯◯`を作らなければいいです。 (2)は実行値が足りない時に`COMF◯◯◯`の中で`RETURN 0`を返す事で作れます。 (3)は`COM_ABLE◯◯◯`を作って、その中で実行出来るかどうかをチェックします (4)の派生コマンドは`Train.csv`に書かれてないか、CSV内でコメント化されています。派生出来る場合、派生元コマンドの先頭で`JUMP COMF◯◯◯`を使います。 (5)はCSVでコメント化して、派生用の`JUMP`もなければ、`Train.csv`で`;`を取ると使えるコマンドになります。 eraMegatenの場合、実行すると派生コマンドになる場合、一覧でも派生先コマンドの名前を表示する仕組みがありますが、これは標準のコマンド表示では無理です。 そのため`COM_ABLE◯◯◯`が0を返すようにして通常のコマンド一覧を無効化、`@SHOW_USERCOM`ですべて表示しています。 (正確には、`CALLTRAIN`命令の時だけ`COM_ABLE◯◯◯`から条件チェック用の関数が呼び出されて、それ以外の場合は無条件に0を返す仕組みです) ---小数の計算、表示について¶
erabasicではTIMES
命令という例外を除いて、小数を扱う仕組みがありません。
TIMES
を使うにしても、引数として渡せないので、実際の処理は別の関数で行うといった場合には不向きです。
しかし実際はTIMES
を使っていないバリアントでも小数計算が行われています。
例えばキャラクター同士の相性(RELATION
)の値、これは倍率を表すものなので、小数で書くなら100%が1.00、1%が0.01にあたります。
どうやって計算してするかというと、その100倍されている数字を掛けて、結果を100で割っているのです。
UP:4 *= RELATION:R
UP:4 /= 100
ほとんどのバリアントで、こういう感じのコードがSOURCE関連に含まれています。
いったん調教対象との相性値をそのまま掛けて、それを100で割って、UP:4 * 相性(%)
という計算結果を出しているのです。
100倍した状態で計算ですることで、整数の100倍の細かさで計算が出来ます。
計算だけでなく表示も小数にすることが出来ます。
280.56
という小数を表示したい場合、内部での保存や計算には28056
という整数を使っておいて、表示の時にだけそれらしく加工して表示をします。
LOCAL = 28056
PRINTFORML {LOCAL/100}.{LOCAL%100}
100で割った数の280が整数部、小数点を入れて、100で割った余りの56が小数部……という風に表示されて、プレイヤーは280.56
という小数だと認識します。
これは固定小数点と呼ばれる方式で、整数と掛け算と割り算(と余りの計算)があれば使えるので、小数機能の無いeraでもよく使われています。
パーセント表示と同じで馴染みやすい100倍で計算するケースが多いですが、0.1刻みであれば10倍でいいし、0.001単位で指定したい時は1000倍にしないと駄目だし、もっと細かい数字が必要ならどんどん桁を増やします。
ただし固定小数点で小数の桁を増やすというのは、整数部の桁数を減らすことなので、億とか兆とかの巨大な数字がありえる計算式では、小数部を増やしすぎないようにしてください。
慣れないうちは思った数字と違う結果、特に桁のズレが発生すると思います。
例えば掛けられる数と掛ける数の両方を100倍していると、元の10000万倍の数字になっているので、100で割ってもまだ100倍の数字が出てきて変な事になります。
足し算引き算の場合は、同じ倍率にした数字同士で計算しないといけません。
明らかに桁がおかしいと感じたら、電卓で計算した結果と見比べながらデバッグしてください。
それと固定小数点やeraに限った話ではないですが、掛けるのと割るのとどちらが先でも同じ結果になる計算の場合、先に掛け算をやって、その後で割り算という順序にして下さい。
分数を扱えるプログラム言語や、高性能な電卓は別ですが、コンピューターの計算だと先に割った時の切り捨てで結果に誤差が出ます。
1000*3/3
は1000ですが、1000/3*3
の計算結果は999になります。
IFの条件式についてのこみいった説明¶
IF
構文は通常、「==
」や「>
」といった、比較のための条件式とセットで使われます。
条件に合致していればそのまま実行、そうでない場合ELSE部分を、ELSE
がなければENDIF
の直後からプログラムを再開します。
ただ様々なバリアントのコードを見て勉強していると、それだけでは説明出来ないような、不思議なIF
文を見かける事があります。
正確に言うと、IF
がチェックしているのは、条件式の計算結果が0なのか、0でないかということです。
ですので、下記の様なプログラムを書いてもエラーにはならず、その時点でのAの値によって分岐が行われます。
IF A
PRINTL Aは0ではない
ELSE
PRINTL Aは0である
ENDIF
これは下記のように書いた場合と同じ結果になります。
IF A != 0
PRINTL Aは0ではない
ELSE
PRINTL Aは0である
ENDIF
==
や!=
のような比較条件式は、条件に一致した場合に1に、そうでない場合に0になる計算式なのです。条件に一致した場合、それは0ではないのでIF
文でも予定通りに判定されます。
IF
文以外でもWHILE
や三項演算子等、条件によって分岐するタイプの仕組みは全部同じです。
条件の判定結果としての0のことを「偽(False)」、0以外のことを「真(True)」という言い方もします。オンオフで言えば、真がオンで、偽がオフです。
もしA>5が真の場合は~
みたいな感じです。
真・偽というのはEmueraでというよりはプログラミング全般での呼び方です。
比較は計算で、結果は数字だというのは、条件分岐以外の場合にも適用されます。
下記は条件結果をそのまま代入に使ったものです。
A = 5
B = A == 5
この場合、A==5の結果が1なので、Bの値は1になります。
これをIF文で書けばこういう感じになります。
A = 5
IF A == 5
B = 1
ELSE
B = 0
ENDIF
この仕組みを応用して、複雑条件をチェックする場合に、いくつかの式に分けて計算するというやりかたも出来ます。
A = TALENT:処女 == 1
B = ABL:技巧 > 3
IF A && B
PRINTL (TALENT:処女 == 1)&&(ABL:技巧 > 3) が真の場合
ENDIF
大抵の場合は普通に条件式を書くのが一番わかりやすいのですが、コードが長くなりがちなので、無駄を省くために一見するとわかりにくいIF
文が使われる事があります。
Emueraの条件判定の仕組みはC言語風のもので、他のプログラミング言語でもだいたいの考え方は同じですが、細かい部分では違っている部分もあります。
例えばEmueraでは比較結果は整数ですが、論理型という整数と別の仕組みが用意されている言語もあり、そういう言語では比較結果を整数に代入出来ません。
他の言語を勉強する場合には、その言語ごとの「真」「偽」の扱いがどうなっているか、マニュアルに書いてあるので確認して下さい。
2進法によるビット操作(STAIN
の仕組み)¶
- 1つの変数にたくさんのフラグを詰め込める
&
や|
が出てきたらだいたいこれ関連- 今使うならSETBIT・GETBIT
erabasicの仕組みの中で、STAIN
はかなりわかりにくい仕組みだと思います。
1つの整数変数を、たくさんの小さい数字に分解することで、単純なフラグを大量に作る方法です。
STAIN
以外でも使われているところを見かけます。
例えば0~9までの数字を6つ使いたいと思った時、変数が6つある配列を使うのが普通のやり方ですが、406478
のような6桁の数字を、6つの0~9が並んでいると考えるやり方もあります。
1000の位の数を調べたい時は、いったん文字列化して右から4文字目を調べるか、全体を10000で割った余りを1000で割ればいいです。計算を工夫すれば狙った桁の数字だけ書き換える事も出来ます。
整数は最大で19桁ですが、全桁を9で埋められる範囲だと18桁なので、この方法で18個の0~9が詰め込めます。その分だけ必要な変数の数が減って、セーブデータが小さくて済みます。
標準のSTAIN
の場合では、0~9までの範囲は必要なくて、汚れがあるかないか区別できればいいという考え方です。
そうすると0と1だけあればいいので、10ではなく2で1桁と考えるようにすれば、10ずつ分けた場合よりも沢山のフラグが作れそうです。
2で1桁だと考えることを2進法、2進法の考え方で書きだした数字を2進数といいます。
Emuera
では2進数を書くために先頭に0b
を付ける書き方が用意されています。
(変数名等は数字から始められない規則なので、0から始まる2進数と名前がかぶる心配はありません)
元々コンピューターの内部装置は全て2進法で動いているのですが、表示等で10進法に変換しているので、通常は人間が2進法を意識する事はありません。特殊な場合だけ2進法の状態で扱います。
eraバリアントで2進法を使うのは、STAIN
の様に1つの変数に複数の数を詰め込みたい時だけだと思います。
2で桁がくり上がるというのはなかなか想像しにくいと思うのですが、例えば上の珠しかないソロバンのようなイメージです。オンオフ出来るスイッチの集まりのようにも見えると思います。
(通常のソロバンは、2進法の天の珠と、5進法の地の珠が組み合わさっていて、桁全体としては10進法の仕組みです)
10進数と2進数は単に書き方考え方の問題で、数としては全く同じだというのは重要な点です。1と書こうが、壱と書こうが、ONEと書こうが同じ数を表してるのと一緒です。プラスとマイナスのような別の数ではありません。
内部的にも普通の整数と区別されていないので、プログラム上は2進数で書いて代入した変数でも、PRINTV
等で文字表示すると10進法で表示されます。PRINTV
は厳密には指定した変数を画面に表示する命令ではなく、指定した変数を10進法で表示する命令なのです。 デバッグ用に2進数として画面表示したい場合は、CONVERT
関数で変換後にPRINTS
等で文字として表示します。
2進法は2ごとに桁が上がっていくので、いちじゅうひゃくせんまん…という風に桁ごとに10倍にはならず、2倍で増えていきます。
10進数 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 |
---|---|---|---|---|---|---|---|---|---|
2進数 | 0b1 | 0b10 | 0b100 | 0b1000 | 0b10000 | 0b100000 | 0b1000000 | 0b10000000 | 0b100000000 |
よく使われるパターンは暗記しておくと便利ですが、全部のパターン覚えるのは不可能です。Windowsの電卓をプログラム用設定にすれば2進法と10進法で相互変換出来るので、これを利用して必要な数を調べて下さい。
2進法では1の位、10の位、100の位…という言い方が出来ないので、何ビット目という言い方をします。
ビット(bit)というのは2進法でいう桁の事です。Emueraの整数は64ビットなので、フラグ64個分という事になります。
Emueraでは2進数で書いた時の右端を0ビット目として、左に向けて1ビット目、2ビット目…と数えていき、左端が63ビット目です。
各桁の取り出しは10進法の場合と同じ様な計算でも出来ますが、通常は動作が高速で、簡潔に書けるビットマスクを使います。Emueraでは「&
」演算子がAND
、「|
」演算子がOR
に相当します。
汚れについて(ページ下の方)
マスク (情報工学)
eratohoまとめ V3 - ERB構文講座3
ついでに&&
と&
の違いについてふれると、&
は数値そのままでのAND
、&&
は両側を1(真)か0(偽)に直した後でのAND
です。
「A && B
」と「(A != 0)&(B != 0)
」は同じになります。
通常は&&
を使って、ビットマスクとして使う時だけ&
を使うようにすれば問題ないはずです。逆に言うと&&
が書いてあれば通常の条件式で、&
が書いてあればビットマスク関連という事です。||
と|
の関係も同じです。
古いビットマスクのプログラムは、10進数の部分を2進数に書き換えるだけでもだいぶわかりやすくはなりますが、現在はGETBIT
・SETBIT
・CLEARBIT
という3つの命令で簡単にビット操作が出来ます。
複数のビットをまとめて取り出す場合でもなければビットマスクは必要ないです。(ここでは実用というよりもバリアント改変のための知識として書いています)
BIT操作系命令
この方法による詰め込みの欠点は、あとになって64個以上のフラグが必要になったり、1以上の数を設定したくなったりした時に対処がめんどくさいという事です。配列のように簡単に上限は増やせません。
最近のEmueraなら#DIM
で変数を追加する事も出来るので、その方が簡単に作れる場合もあると思います。
実践例¶
キャラクター固有の番号(ID)の作成方法¶
eramakerは元々同じNO
を持つキャラクタが居なかったのですが、Megatenの様に同じ種族のキャラが複数仲魔に出来たり、ランダムキャラを追加したりで、NO
以外にこのキャラクターだと特定出来る情報が必要になってきています。
例えば別記事の妊娠時の親情報や、SORTCHARA
でMASTER:0
とTARGET:0
以外の番号を並び替え後に追尾する時に必要な情報です。
キャラIDとかIDとか呼ばれる事が多いようなので、この記事ではIDと呼びます。
今のところeramakerやemueraのシステムには用意されていないため、必要なバリアントごとにCFLAG
に保存したり、関数で取得出来るようにしています。
バリアント名 | ID保存場所 | 上限 | 仕組み |
---|---|---|---|
eraMegaten | CFLAG:キャラ固有の番号 | 200(保有上限) | 今居るキャラとかぶらない最小の数 |
eraRorona | CFLAG:キャラID | 生成時点のCHARANUM | 今居るキャラとかぶらない最小の数 |
eraWeapon | CFLAG:3109 | 整数の上限 | カウンタを1ずつ増やす |
他のバリアントもだいたいこのどれかの方法に近いです。
CFLAG
ではなく@GET_ID
という関数で取得出来るようにしてある事も多かったです。
MegatenとRoronaは基本的には同じ仕組みで、今居る他のキャラクタと番号がかぶらなければ良いという考え方です。
この方法はソート後の追尾には十分ですが、プレイを続けると当然IDが同じキャラが出るので、血縁関係等でこのIDを使うと後でデータ不詳ではなく別人が表示されたりします。
そういう使い方をしないか、削除したキャラのIDの参照箇所を消す等の対応が必要です。
Weaponや恋姫等で採用しているのは、単純に作った順に1から通し番号を付けるだけの方法です。
そのうち限界が来てエラーが出るんじゃないの?と心配になるかもしれませんが、「そのうち」というのがいつ頃になるかをざっと計算するとこんな感じです。
9223372036854775808/(100000000*60*60*24*365) = 2924
emueraの整数値の上限は922京なので、毎秒1億キャラを3000年ぐらい連続生成しないとIDは使いきれないということです。
現実的に1秒で1億も生成したらメモリが足りないし、それを3000年続ける前にPCが壊れます。普通に考えると番号が尽きるより先に年表示が4桁で足りなくなります。
上限固定で使い回しするメリットは、キャラ変数とは別に配列を使ってデータ管理している場合等です。
例えばキャラ同士の相性を入れた配列を922京×922京の2次元配列としては作れないので、現実的な数で作る必要があります。
配列の並び順ではなく、配列に入れたIDで読み書きを管理するなどして考える必要があります。
そういった理由が特に無ければWeapon方式をおすすめします。一番簡単な方法だし、後で何か工夫したくなった時にも対応しやすいので。
CFLAG
の空きを探すのがめんどくさい時は#DIM CHARADATA
で専用変数を作ってもいいです。
そしてIDは0
ではなく1
から始めるようにして下さい。0だとIDの設定漏れと区別出来ないので。(Weaponも恋姫もIDが1からで、多分同じ理由だと思います)
後からIDの仕組みを追加する時にも、セーブデータのバージョンは気にせず、IDが0のキャラに自動的にIDを割り当てるだけで済みます。
キャラクタの作成をする時にADDCHARA
やADDVOIDCHARA
を直接使わず、必ず自作関数を経由させて、その中でIDの設定をすれば漏れは起きにくくなります。
キャタクター一覧のページ切り替え¶
人数が多いバリアントだと、キャラクター選択画面が画面内に収まらなくなるため、そういったバリアントにはページ切り替え機能が付いています。
一般的にページナビゲーションやページネーションと呼ばれているものです。
保有キャラクターから調教相手や助手、ステータス表示する対象を選んだり、購入キャラクターを選ぶ時などに使います。
ここでは保有キャラクターの方をメインに書きますが、購入時の処理も仕組みとしては同じです。
先に既存バリアントの例を紹介した方がわかりやすそうなのでいくつか挙げます。
ここで言う「キャラの番号」とは、TARGET
やASSI
で指定する、現在のキャラクタの並び順です。NO
とは違います。
- eraMegatenの場合
- どの場面でも1ページあたり20人の表示
- 一文字変数
A
に表示人数、表示するキャラの番号をQ:0
からQ:A
に、ページ番号をPに代入して、SHOW_CHARA_LIST
命令を使う @SHOW_CHARA_LIST
では、A
とQ
とP
の内容に従って表示- 表示する内容の違いは
FLAG:ショップコマンド
で分岐 P
が1以上なら前のページの、P
が(人数-1)/20
より小さい場合次のページへの表示-
ページが変更の場合
P
を変更、A
とQ
はそのままでSHOW_CHARA_LIST
をやり直す -
erainSchool
- 1ページに10人表示
@DISPLAY_COMMON
の中で表示もページ切り替えも行う- 呼び出す場面ごとに違う部分は
DISPLAY_COMMON
の引数として設定 - 呼び出された場面ごとに違う部分は別関数にして
TRYCALLFORM
で呼び出す
(調教選択時には@DISPLAY_SET01_FUNCTION
、助手変更時には@DISPLAY_SET03_FUNCTION
等) REPEAT CHARANUM
でループを回し、表示しないキャラの時はCONTINUE
、ページ範囲外のキャラは非表示でCONTINUE
せず、範囲内のキャラのみ表示- 表示位置が先頭以外の場合は「前のページに戻る」、表示位置から10人以上キャラが残っている場合は「次のページに進む」の表示
他にも細かい仕組みはあるのですが、だいたいこういう仕組みでした。
どの方式でも必要な仕様は、1ページの人数を決める事は必要です。
想定画面サイズや上下に表示する物によりけりですが、1列1キャラ方式なら10~20、多くても30人程度ではないかと思います。
次に表示するキャラとしないキャラの分別です。
例えば1ページ10人の設定で、24番目のキャラは通常3ページに表示されるはずです。
ところが24番より前の人間が何らかの事情で非表示になっていると、2ページかもしれないし、1ページ目なのかもしれません。キャラ番号だけでは計算出来なくなります。
あるいは1ページ目は4人、2ページは8人等、ページごとにまちまちの人数を表示する事になります。
この問題を避けるには3つの方法があります
- Megaten式で表示する番号だけ詰めた配列を用意する
- inSchool式で表示しない範囲のキャラも含めて毎回チェックする
SORTCHARA
で表示するキャラが先頭側に並べておく
それぞれ表示する人数が最大で何人かというのも同時に調べておいて、最大ページ数の計算に使います。
Megaten式がオススメですが、Qのような大域変数を関数同士の受け渡しに使うのはよくないので、ERH
に#DIM
で専用変数を作るか、引数で渡す仕組みが良いと思います。
条件や表示内容が場面ごとに違うのはページ無しの場合と同じですが、SELECTCASE
やIF
で分岐したり、別関数にしたり。
中には文字列で条件一覧を作って渡すバリアントもありました。これだと呼び出し部分を見ただけで条件がわかるのが利点です。
他の言語でいう無名関数やインターフェース継承に相当する考え方を、erabasicで可能な範囲で各自工夫して作っている感じです。
ほとんど違いがなければIFでもいいですが、場面ごとに表示内容が全然違ったり、表示種別が多いようなら別関数がいいかもしれません。
前のページに戻るは、1ページ目では表示しない、それ以外は表示だけなので単純です。
ただし1ページ目が数字的に0なのか1なのかは確認が必要です。
一応ここでは1ページ目は1だとして話を進めます。
次のページに進むかどうかは現在のページ番号×10より総件数が多い場合、もしくは現在のページ番号が最大ページ数より少ない場合に表示します。
通販サイトのように1.2.3.4.5…
のようにして任意のページに飛べるようにすることも可能です。ちょっとめんどくさいですが。
他のプログラム言語用でよければネット上で作り方が見つかると思います。
ページナビゲーションの様な仕組みは、上手くいかなくなった時は、いったん小規模にして、紙に書きながらテストするといいです。
例えばページ数の計算なら1ページに3人とか4人とか、まずは暗算出来る程度のコンパクトなものにします。
それで人数が4人なら何ページになるか?5人ならどうなるか?というのを、計算結果や表示したい結果を書き出して行くと、頭の中が整理出来てきます。
SORTCHARAで複雑な並べ替え処理を行う¶
通常ADDCHARA
をした順番に並ぶキャラクタ変数ですが、人数が多くなってくると色々な条件で並べ替え(ソート)がしたくなってきます。
そういった場合SORTCHARA
命令で高速に並べ替えをすることができます。
通常の使い方はSORTCHARA MAXBASE:0
のようにして、キャラクタ変数の大きい順か小さい順かで並べかえるというものです。
これで自分好みになる場合はいいのですが、変数1つで済まないような条件の指定だと、そのままでは使えません。
1つ目の方法は複数回のSORTCHARA
に分けて使う方法です。
- 条件1の順番で並べて、条件1が同じ場合条件2で並べる
- 条件1の順番で並べて、条件2に当てはまる物はリストの下の方に
こういった場合SORTCHARA
を2回使えば解決出来ます。
SORTCHARA
はいわゆる安定ソートという仕組みで、並び替える時に数字が同じなら元の並び方のままになります。
そのため(1)の場合は「SORTCHARA 条件2
」「SORTCHARA 条件1
」の順序で実行すると、条件1が同じ場合だけ、条件2の並び方が残ります。
(2)の場合は条件1、条件2の順番でSORTCHARA
すればいいです。ただ0と1しかない素質等はこれでいいのですが、従順が3以下といった細かい指定は出来ません。 従順でソートすると1・2・3とそれぞれ並び替えてしまって、意図した並び順になりません。後述の方法を併用する必要があります。
2つ目の方法は条件を計算してキャラ変数に入れておく方法です。
例えば先程の従順が3以下という話で言うと、ソートの前に全キャラの従順が3以下かチェックして、キャラ変数に入れておけば問題は解決します。
FOR LOCAL, 0, CHARANUM
;実際使用する時は777ではなく未使用の番号か、#DIM CHARADATAで新しい変数を作る
IF ABL:LOCAL:従順 <= 3
CFLAG:LOCAL:777 = 0
ELSE
CFLAG:LOCAL:777 = 1
ENDIF
NEXT
こうした上でSORTCHARA CFLAG:777
とすれば、従順3以下と、それより大きいキャラとではっきりと分離出来ます。
体力と気力の合計値で並び替えるといったような複合的な並びかえも、
CFLAG:LOCAL:777 = MAXBASE:LOCAL:体力 + MAXBASE:LOCAL:気力
計算式をこのように変えれば対応出来ます。
もっと複雑な、例えば売却価格の様な物であっても同じです。
複数回のSORTと事前の計算は同時に使う事が出来るので、思った通りの並び替えが出来るようになります。
手動で並び替えをさせたい場合、SWAPCHARA
を使って1人1人並びかえる方法もありますが、その後でSORTCHARA
を使うと手動指定分が変わってしまいます。
内部的にSORTCHARA
を使わざるをえない場合は、ソート前にその時点での順序を変数に保存しておいて用が済んだら戻すとか、並び替えではなく優先キャラを指定する方式にしておくとか、工夫が必要になってきます。
CSVのあるキャラクタを一覧表示¶
Q. 主人公を選択式にしたいのですが、キャラクターのリストが上手く出せません。
A. CSVNAMEやCSVABLなどを利用すれば、CSVに記述されている内容を取得できます。
またEXISTCSVによって、任意のキャラ番号をもったCSVが存在するかどうかを取得することができます。
それらを使いながら適当にループを回しましょう。
使用例
キャラクタの購入や選択で使う事が多い仕組みです。
下記の例はCSV登録されたキャラクタの名前を番号付きで一覧表示する物です。
途中欠番のキャラがいてもEXISTCSV
で事前にチェックしているので変な表示にはなりません。
かといって上限を10000人とかにしても動作が遅くなるだけで意味がないので、とりあえず99番までをチェックするようにしてあります。
実際使われているケースでは、隠しキャラや選択不能キャラの非表示、パラメータや金額の表示等も処理も一緒にやっている事が多いです。
(今回の例だと隠しキャラを100番以降にしておくと簡単に選択不能に出来ます)
FOR LOCAL,0,100
IF EXISTCSV(LOCAL)
PRINTFORMLC [{LOCAL}]%CSVNAME(LOCAL)%
ENDIF
NEXT
この例の100はマジックナンバーとなるので、実際に使用する場合は
マジックナンバーをなくすを参考に書き換えるのが望ましいでしょう。
ランダムキャラを作る¶
通常のCSV通りのキャラが生成されるシステムとは違う、毎回違うキャラクタが出てくる仕組みを採用したバリアントがいくつかあります。
通称ランダムキャラです。
原作の登場人物が足りないとか、毎回違う遊び方をしたいとか、入れる理由は色々ですが人気のあるシステムです。
ランダムキャラを作る時は、元になるCSVからADDCHARA
で作る方法と、ADDVOIDCHARA
を使う方法があります。
ADDCHARA
で作る場合はランダムキャラ用のCSVを作っておかないといけませんが、大まかな設定値をCSV側で設定出来るというメリットがあります。
例えばeraWizの場合だと職業ごとに別のCSVがあり、それを元にERB側で調整を加えているかんじです。
昔はADDVOIDCHARA
がなかったので、とりあえず空に近いCSVを作っておくという手法もありましたが、今ならADDVOIDCHARA
で済みます。
そうやって作ったキャラクタの体力やパラメータをいじっていきます。
MAXBASE:0 += RAND:200
とすれば、HPが初期値~初期値+199の範囲で変動するランダムキャラになります。
こんな感じの事を体力・気力・素質・経験…という感じで繰り返していくのが基本です。
ただ完全にサイコロ任せのキャラクタだとかなり雑に仕上がります。
例えばプライド高いとプライド低い、楽観的と悲観的といった素質を両方持ってるとおかしいです。そしてどっちかを必ず持ってるというのでもやっぱりおかしいわけです。
プライド高いが20%・低いが20・どちらでもない60%…といった感じで、そこそこバラつきがあって、不自然に感じない様に調節していく地道な作業が必要です。
好みの問題なので、その雑さが良いというのも当然有りですが、その場合も雑さの範囲は決めないといけません。
場合によっては能力カンストの調教済みキャラが出てもいいのかどうか、それは何%ぐらいの確率なのか。
eraバリアントだけでなくいろんなゲームで共通する課題なので、ランダムキャラが出てくるゲームの攻略wikiを見るのも参考になるはずです。
名前の問題もあります。
50音の完全ランダムの名前だと、まずまともに発音出来ません。
いくつかの名前をERBの中に書き込んでおいて、その中から今居るキャラと被ってない名前を使う…というのが基本的な仕組みです。
日本人や中国人の場合だと、名前によく使う漢字をランダムに組み合わせというのもあります。
これもそれっぽい名前を出すのは難しいですが、少なくとも名字と名前は分けて良いと思います。
いくつかランダムキャラ生成の実例を紹介します。
まずeraWiz。職業の他に種族を決めて、それにくわえてランダムでおおまかな性格で分岐をさせて、性格にあった素質がつきやすくなるという工夫をしています。
「高貴」なキャラならプライド高くなりやすく、「乱暴」なキャラなら反抗的になりやすいなどです。
キャラにあった素質になりつつ、性格分類は口上にも使えるというすぐれものです。
名前も性格ごとにわかれていますが全部で約200種類です。
次にeraWeapon。同時に付いたらおかしい素質は同時に付かないようにしつつ、武器の特性に応じてつきやすい素質(鞭擬人化ならサド率が上がる等)もある感じで、オーソドックスな生成処理だと思います。
名前は50種類。自分で作った武器の擬人化という設定なので、自分で名前を付けることが推奨されていて、ランダム名の数は他より少なめです。
他のバリアントでも、元になるキャラクタを作って・無理の無い範囲で数字を調節して・名前を付ける…という基本構造は同じはずなので、そのへんを考えながら読むと解読しやすいと思います。
娘(息子)調教機能の作り方¶
(調教可能にするという前提の記事ですが、妊娠出産のみで調教は行わない場合でも、キャラ生成以外の仕組みは共通です)
ランダムキャラと考え方は同じですが、親のデータを参照しつつ作る事が多いです。
必須ではないのですが、性格が似てるとか、能力を継いだ強キャラとか、完全なランダムよりもそういうのがあった方が雰囲気が出ます。
親と同じ素質はが付きやすくなるとか、親の能力の10%が初期値に上乗せされるとか、そういう補正処理を加えたランダムキャラになります。
もちろんランダム要素無しでも子供は作れます。
eraではないですが、ファイアーエムブレム覚醒や聖戦の系譜では、母親ごとに名前やクラスが固定、父親毎に上がる能力と下がる能力が固定で、ランダム要素はありません。
また第一子だけは固定キャラ、第二子以降ランダムという手法もあります。これは歴史シミュレーションに多い方法です。
ただ複数の子供が生まれる前提だと、同じ能力ばかりになってつまらないので、今のところeraバリアントで固定方式というのは無いようです。(eraMegatenの合体はこれに近い考え方です)
子供の性別については、娘限定だったり、オプションで比率を変えられたり、バリアント毎に対応はまちまちです。好みの問題だと思います。
子供キャラで困るのが父親を識別する方法です。
妊娠したキャラのCFLAGあたりに父親の情報を記録しておくことが多いですが、CSVごとに1キャラしか居ない場合はNO
だけでよくても、ランダムキャラが居たり、同じCSVのキャラが複数居るという場合もあります。
そこでeraMegatenでは「CFLAG:キャラ固有の番号
」という数字を全キャラが持つようにして、この数字はキャラ毎にかぶらないようにして、父親の特定に使っています。
口上や妄想でも続柄は大事なので、キャラクターのデータとして保存して、ステータス画面にも父母の名前を出すといいでしょう。
妊娠と出産の時期のズレがあるため、出産時に父親が売却済みという場合もあります。
売却してもデータだけは残しておくという方法も考えられますが、そういう実装をしている例は見つかりませんでした。
セーブデータがどんどん大きくなっていくし、キャラクターリストに不要な物が混ざるといったデメリットが多いのと、そんな大事なキャラは売らないだろうという判断だと思います。
eraMegatenではキャラ固有の番号と別に親のNO
も記録していて、売却された場合はそちらを参照して種族等を割り当てています。
他にも臨月時の特殊処理、産後の母乳や育児等がありますが、基本的には妊娠してからの日数がわかる数字を母親のCFLAG
に保存して、毎日の終わりにその日数をチェックして、メッセージ表示や能力変更をする事で対応します。
あと何日ではなく、何日に出産という形でのパラメータを持つ方法もありますが、この方法は強くてニューゲーム系の機能と相性が悪いです。
引き継ぎ時に妊娠情報をリセットするなどの対処が必要です。
難しいのが子供の年齢設定です。何歳から調教出来ると良い感じなのか?親も含めて成長するのか?世代交代するのか?人数制限はするか?等など。
成長して代替わりをするようなパターンなら日単位ではなく週や月でやらないと、成長するまでに飽きてしまうおそれがありますが、あまりはやいと十分な調教をする前に寿命という事もありえます。
また妊娠期間を何ターンとするかも悩みどころです。
短すぎると調教やイベントに妊娠プレイ系を組み込むのが難しくなります。
全体のゲームシステムや口上等にも関わってきて、妊娠システムで一番難しいのはこの時間設定の部分だと思います。
多いパターンとしては、妊娠期間を短縮、子供は急激に成長してその状態で固定という時空です。
これだと元々妊娠のなかったバリアントでも極端にバランスを変えずに済みます。
ただ成長を見守りながらのセックスや年の差近親相姦といった楽しみ方には不向きです。
全年齢のゲームでも子供が出てくるものは結構あるので、それらのやり方を応用する手もあります。
寿命を短くしてドンドン世代交代するとか、イベント毎の区切りで年月が経つとか、出産が確定した瞬間に未来からタイムトラベルして来るとか。
全ての願望を満たせる方法は今のところ見つかっていません。自分が一番興奮するシチュエーションを重点的に考えつつ設定を練りましょう。
特定のキャラが奴隷(仲間)に居るか調べる¶
イベント発生等でキャラクターが居る(ADDCHARA
されている)かどうかが条件になる場合、GETCHARA
やFINDCHARA
でそれを調べる事ができます。
GETCHARA
(キャラ番号)で、そのキャラが居るかどうか、居た場合は先頭から何番目に居るかを調べる事ができます。
居ない場合は-1
がかえってくるので、居るか居ないかだけで良い場合、IF GETCHARA(キャラ番号)!=-1
という調べ方をします。
条件がキャラ番号(NO変数)だけで良い場合はGETCHARA
を使いますが、NAME
やCFLAG
等別の条件で調べる時は、FINDCHARA
を使います。
キャラクター変数のうち1つを条件として、GETCHARA
と同じ事が出来ます。
FINDCHARA
は条件として変数1つしか指定出来ないので、もっと込み入った条件の時は、自前で処理を書く必要があります。
0~CHARANUM-1
までのループで、1人づつチェックするプログラムを書くことになると思います。
その他¶
文字コードには出来るだけUTF-8を使ってほしい¶
SHIFT-JISは日本語版Windows標準の文字コードですが、海外では全くといっていいほど知られていません。
知っていても歴史的事情によるあれこれを知れば使いたいと思わないはずです。
そのため海外製のエディタではSHIFT-JISのファイルは表示できなかったり、一部の字がおかしくなるという事が起きています。修正の見込みもありません。
日本製のエディタにしても内部の隅々まで日本製という事はまれなので、やはり対応が難しい場面があります。
その結果現状ではERBファイルの編集に使えるソフトがかなり制限されています。
海外のソフトで良い感じのを見かけて、ERB用の色分け設定などを作ったとしても、SHIFT-JISのファイルだと上手く扱えません。
ERBの加工用プログラムを作る時もSHIFT-JISに対応したプログラム言語で作らないといけないというのが足かせになっています。
その点UTF-8は現在世界標準といっていい状態にあります。海外製のエディタもプログラム言語も、UTF-8であれば対応しています。
エディタ制作によく使われる基本部品が対応済みなので、各エディタの作者が別に世界対応とか考えてなくても、ちゃんと読み書き出来るのです。
サクラエディタも以前はUTF-8の扱いに問題がありましたが、バージョン2以降は内部的にUTF-8で扱うという、海外製ソフトのやり方に近くなっています。
eramakerや古いERB対応プログラムを使いたい場合はやむをえませんが、Emuera専用バリアントでUTF-8にする必要はもう無いだろうと思います。
UTF-8が普及してけば各種の補助ソフトなどもUTF-8専用でよくなって作りやすくなります。
ただしパッチ作成時には文字コードは変えない方がいいです。
そのパッチで追加した部分がわかりにくくなって、作者や利用者が困ります。
変更ではなく追加するファイルに関してはUTF-8にしてもいいのですが、やはりそのバリアントの中では統一した方が混乱が少なくて良いだろうと思います。
emueraはBOM付きのUTF-8にしか対応していないようです。
サクラエディタの保存画面で、"BOM"と書かれたチェックボックスがあるので、そこにチェックを入れてください。
SJISやUTF-8と選ぶ欄の右の方です。
他のツールでもだいたいどちらか選択出来るようになっていると思います。UTF-8とUTF-8Nという選び方の場合は、Nがついてない方がBOM付きです。
プログラミングの学習法¶
erabasicの力を上げるには、他のプログラミングを学ぶ事が必要になってきます。
他の言語を知らないと、eraだから出来ない事なのか、他の理由で出来ない事なのか、区別が付かないからです。
erabasic以外にもよく使う言語、使わないけどだいたい知ってる言語というのがたくさんあると、なんだかんだで役に立ちます。
例えば便利なeramaker用のツールは、ほとんどがeraBasic以外の言語で作られています。
Emueraの場合はC#という言語で作られたもので、C#が扱える人なら自分好みに改造することが出来ます。実際に改造したEmueraを使っているバリアントもあります。
そこまで大規模な物でなくても、作業用に適当なプログラムを書いて使っている事は多いです。
例えばchara0.csv
、chara1.csv
といったファイルを、chara0_あなた.csv
のように名前付きに変えたいとします。
ファイルの読み書きと簡単な文字列処理の知識があれば、全ファイルを誤字なく書き換えるというプログラムを書くことが出来ます。
最近はオンラインで学習環境が整っているので、色々試してみて、見た感じ良さそうなサイトや言語からやってみるのがいいと思います。
特にブラウザの入力フォームに書きこんで送信すると実行されるサイトは、何もインストールせずに始められるのがいいです。
初心者にとって最初の難関はプログラム自体よりもプログラムが出来る状態にする事だと思うので。
プログラミングの独学に最適!日本語対応オンライン学習サービス10選【体験レポートあり】
ゲーム制作系のツールから入るのも良いです。
erabasicのようにそのツール専用言語を使う場合もありますが、ここでは一般的な言語が使える物をいくつか紹介します。入門用のサイトや解説書が充実しています。
ツール名 | 使用言語 |
---|---|
RPGツクールVX・RPGツクールVX ACE | Ruby |
Unity4 | C#、JavaScript |
NScripter | Lua(NLua) |
吉里吉里2 | JavaScript(TJS) |
自分のプログラミングがどの程度のレベルなのか確かめるには、paizaが使えます。
本来は転職サイトですが、プログラムを使って回答するクイズゲームみたいなもので、初心者向けの問題から上級者向けの問題まであります。
どうしても解き方法がわからない、解けたけどもっと効率の良い方法がありそうな気がする…と思ったら、アルゴリズムの勉強が効果的です。
どうやって色んな問題を解決するかという考え方・理論です。
これも初心者向けから上級者向けまで、本やネットの記事が色々あります。
例えばキャラクターの並び替えシステムを自分で作る場合、ソートアルゴリズムの学習をする前と後とでは、人数が増えた時の速さには大きな違いが出ます。
TRPGのルールブックを読む¶
ゲームシステムを作るということは、自分の脳内設定を数字に置き換えるということです。
なんだか難しそうな話ですが、その逆の、数字から設定を想像は普段eraのプレイでやっている事なので、そんなに理解しにくい感覚ではないと思います。
どういう風にやればいいかを研究するにはゲームをやってみるのが一番ですが、コンピューターゲームだと細かいルールは開示されていない事が多いです。
攻略本を読んでも細かい計算式までは書いてないです。
そこでこの項ではテーブルトークRPG(TRPG)のルールブックをおすすめします。
本は1000円ぐらいしますが、他に必要なのは筆記用具ぐらいで、サイコロもスマホやブラウザ用のサイコロアプリで代用できます。
本来は何人かで集まってそのルールを見ながらゲームをするのですが、ゲームシステムに興味のある人にとっては読み物として興味深い物です。
エロのあるTRPGでも良いのですが、そうでない普通の全年齢ゲームでも構いません。
力の強い人と弱い人を表現したいから筋力値を作るのも、おっぱいの大きい人と小さい人を表現したいから乳サイズを作るのも、根本的には同じ事だからです。
特に最近のバリアントは調教以外の日常生活やダンジョン探索など、エロだけでないシステムが多くなってきています。
ゲームごと作者ごとに色んな考え方があるので、そういったものを参考にしつつ、自分なりのゲームが作れるといいと思います。
TRPGといっても色々あるので、いくつかおすすめの物を挙げておきます。
-
ソードワールド
オーソドックスなファンタジー世界を題材にしたTRPGです。
実際のプレイ内容をノベライズしたリプレイ小説が人気でラノベコーナーに置いてあります。
現在書店に置いてあるのは大幅リニューアルした2.0ですが、電子書籍や古本で古い本も入手可能です。
昔ながらのファンタジー好きには古いバージョンを、ドワーフ(女)はロリキャラだと思う人には2.0をおすすめ。 -
サタスペ
東洋の裏社会を題材にしたTRPGです。
ルールの中に娼婦や犯罪といった要素があって、パラメータやスキルにもそんな感じの物が多いです。ちょっと値段が高めなのが難点。 -
絶対隷奴
18禁のTRPGです。バトルファック系とはちょっと違いますが、戦闘で相手を倒してもいいし、調教して奴隷にしちゃってもいい、そんなゲームです。とにかくエロがないとやる気でないという人はこれを。 -
無料で閲覧できるルールブック
図書館に置いてある本もありますが、最近はネットで見られる物も多くなっています。
http://jinriki.tumblr.com/post/60355051949/trpg
最新のルールのサンプルから、絶版になってる古いルール、二次創作物、個人制作のオリジナルなどなど、かなりの数があります。
若干読みにくい物が多いのが難点ですが、数が多い分ルールの比較がしやすいし、比較する事でシステムの特徴やよくあるパターン等がわかってきます。 -
動画サイトで実況されてるもの
実際に自分で遊ぶ必要はないのですが、どういう風に遊ぶかはわかっていた方がいいです。面白い動画を見ながらだと、この数字はこういう意味があるのか、といった事がわかりやすいです。
「パラノイア」や「クトゥルフ神話TRPG」といった作品をよく目にします。 -
eraTRPGのお気に入りキャラが出てるゲーム
TRPGのリプレイ小説の登場キャラクタを調教するバリアントなので、出てくるキャラクタにはTRPGの元ネタがあります。プレイの充実度を高めるためにもルールブックとリプレイを読んでおくといいかもしれません
(同じルールに複数のリプレイシリーズがあるので、どの本に出てくるキャラなのか確認した方がいいです) -
原作を知ってるもの
eraMegatenプレイヤーなら真・女神転生RPG※とか、アニメ好きならログ・ホライズンTRPGとか。元ネタを知っている状態の方が、何をどういう数字で表現したかったのか、というあたりがわかりやすいです。
(※真・女神転生RPGはナイトテイルで使われている最新版(魔都東京200X)が現在入手困難なようです。他の絶版ルールブックもですが、出版社から出てる本は国会図書館で閲覧可能なはずです。近くの図書館で取り寄せてくれる場合もあるので相談してみて下さい。合う合わないは個人差があるのでプレミア価格で買うのはおすすめ出来ません) -
リプレイ小説が面白かったもの
先に原作を読んでからの方がわかりやすいのと同じ理由で、リプレイ小説を読んでからルールブックを読んだ方がわかりやすいです。
野球やサッカーを知らない人がルールブックだけ読んでも多分さっぱりわからないだろうと思います。
小説が面白いからといってゲームが面白いわけではない(もちろんその逆もある)のですが、テンションは違ってくるので。口上があるとやる気が出るのと同じです。
特にルールブック発売後の最初のリプレイは、初心者用にスキルや段取りなど説明してある物なので、ルールブック無しでもだいたいどういうルールかわかるように書いてあります。
バリアントに戦略要素や経営要素を取り入れたい場合は、TRPGだけでなくボードゲームも参考になります。
特に1人プレイに対応したボードゲームは、よっぽど変なボードでも使ってなければeramakerでも再現出来るはずです。
(対戦用のでも再現は出来ますが、対戦用に作るか、それなりに強いAIを作らないといけないので厳しいです)
ファミコンやゲームボーイなどのレトロゲームも最近のゲームほど複雑化してないので仕組みが把握しやすいです。
こちらもドット絵グラフィックや音楽以外の、ゲームシステムとしては同じような物が作れます。
フレーバー要素にしない方法(する方法)¶
eraバリアント関連のスレッドで「フレーバー」という言葉をちょくちょく見かけます。
カードゲームやTRPGあたりで使われはじめた言葉のようですが、プレイやルールに直接関係しない要素という意味で使われています。
eraバリアントでいうと、口上や地の文と呼ばれる物がそうです。一部能力変化をともなう口上を除けば基本的にフレーバーテキストです。あってもなくてもパラメータや貰える珠の数は同じ、でもプレイした時の感覚は違ってきます。
髪の色のような要素も時々見かけますが、キャラの想像に使うだけでルール上の意味はありません。
衣服に関しては効果を持たせていないバリアントと、服によって使えるコマンドやパラメータ変化に違いがあるバリアントと両方あります。
フレーバー機能をそのつもりで作った場合はいいのですが、そうでないとあまりその機能が使われず、残念な事になります。
また新しいパッチを作る事で従来の機能が無意味になってしまう場合もあります。
この項ではフレーバーにならないようにする方法について書きます。(逆のことをすれば意図的にフレーバー化する事も出来ます)
-
違いを作る
あってもなくてもルール的に同じだからフレーバーなので、あるかないかで違うようにします。
例えば素質「巨乳」はそれによって実行可能コマンド等が違っていますが、「巨乳」のキャラしか出ないバリアントの場合、「巨乳」はフレーバー素質になります。その素質がある事によってキャラごとの調教方法にも売却額にも変化がないということなので。
(派生バリアントの場合流用の都合があるので、システムを巨乳用に改造するより全員に素質を付ける方が簡単ではあります)
「美人」素質を見かけないのは、多分素質を作らなくても「美人」しか出てこないからです。ランダムキャラ用に逆魅力的素質を付けるバリアントはあります。「人間」素質も人間しか居なければ不要ですが、eraMegatenのようなバリアントでは種族が重要パラメータになっています。
「魅力」「プライド高い」「A敏感」などもつい全員に付けたくなるものですが、やりすぎるとキャラクタの個性としては薄れてしまいます。ある程度素質がばらつくようにキャラクタを作った方がプレイに幅が出るし、素質が意味を持ってきます。
ちなみに「処女」素質は全員に付けてもフレーバーにはなりません。キャラごとの違いはなくても、「処女」の時とそうでない時の違いがあって、その事がプレイに影響するからです。 -
ゲームの目的に絡める
その要素がフレーバーかどうかはゲームの目的によって変わります。
ゲームの目的は通常エンディングですが、複数のエンディングがあったり、実績解除の様な仕組みも含まれます。
例えば日数表示は、クリア条件等で日数制限がある場合はルール上重要な表示ですが、日数を数える必要がないゲームならフレーバー要素になります。
プレイしててお金に困らないバリアントなら所持金に大した意味はありません。
もし所持金を重要視したプレイをして欲しいなら、クリア条件や調教の度合いに関わるようにしないといけません。
これといって目的が無いバリアントやモード設定もありますが、その場合システム全体がシチュエーションを楽しむためのフレーバーになります。
ただシムシティの様なゲームでも、一定の人口毎に褒められる実績的な仕組みがあって、実績のMAXである50万人都市を目指すというモチベーションになっているので、何かしら目標の提示や褒められる事があった方がゲームっぽくなると思います。 -
プレイ中の状況によって変える
全て状況で優れているコマンドや選択肢があると、そっちだけを使えばよくなるので、劣った方のコマンドは使う理由がなくなります。
劣っていた方を単純に強くしても優劣が逆になるだけで、どちらかが必ずフレーバーになります。
状況によって有利不利が変わる仕組みにすれば、場合によって使い分けが出来るようになります。
eraKanonの場合だと、C感覚が低いキャラではEマッサージャの効率が圧倒的に良いですが、C感覚が上がっている状態だとローターの方が体力1あたりのC快感上昇値が大きくなります。
(体力気力の消費バランスやソースの量も微妙に違っています)
eraKanonでは素質次第では快楽や奉仕よりSM系コマンドの方がスムーズに調教が進むのですが、誰に対してもSMの効果が低い(もしくは体力がなくなる)バリアントもあって、その場合SM系全体が使われにくくなります。
eratohoA及び派生バリアントのルート分岐では、SMで調教した場合の売却額を増やしたり、口上分岐を作る事によってSMの使い道が出来るようにしてあります。 -
使用に制限を付ける
他に絶対的に有利な選択肢があっても、有利な方に何かしらの制限を付ける事で、両方のコマンドが必要な状況を作る事が出来ます。
例えば同一コマンドの実行は効果が落ちるバリアントが多いですが、これがあるとコマンド2つまでは使う理由が出来ます。2つ前のコマンドまでチェックするようにすれば3つまでです。
強力なコマンドに1日1回しか使えないとか、使うと有利だけど使わなければ実績解除出来るという制限方法もあります。
高価な器具や使い捨てアイテムが無いと使えないというのも制限ですが、お金がフレーバー化していると意味がありません。
強力すぎるとプレイヤーが判断した場合、自主的に制限した縛りプレイを行う事もあります。それはプレイヤーの自由ですが、使って欲しいコマンドは安心して使えるようにゲーム側で調整した方がいいでしょう。 -
上記のような事に気付いてもらう
せっかく調整しても意図に気付いてもらえなければ意味がありません。
eraKanonのようにキャラクタやコマンドの数が限られていれば、調べてもらうのも楽しみの1つになりますが、大規模化したバリアントだと試すパターンも膨大になります。
あまり効果は無いけどフレーバーとして作った物だからそれでいいんだろう…と思われると質問なども来ません。
有効に機能する状況が限られたコマンドについては、ネタバレ用テキストに書いたり、ゲーム中で村人に話してもらったり、何かしら使い方のヒントがあった方がいいだろうと思います。
プレイヤーの意見を聞きながら調整するにしても、こういう方向性にしたいというのを作品なりパッチなり書き添えておくと、意見が出やすくなるし、意見を取り入れる時の指針にもなります。
〇〇というコマンドを作ったけど☓☓と使い分け出来るようにしたいとか、△△の強さは変えたくないけど乱発は出来ないようにしたいとか。
新機能がフレーバーの場合もそう書いておいた方がいいです。特に発生条件が難しいものは、意図せずにゲーム進行上の罠になってしまうかもしれません。
バージョン管理システムを使う¶
バージョン管理というのは、簡単に言うと更新履歴を残しておいて、後で調べられるようにすることです。
古いデータをzipなどで保存したり、コメントやテキストファイルに進捗状況を書くなどして、履歴を残しておく事はよくあると思います。
この方法の難点は、ファイル単位だとファイルの中のどこが違うのかわからないし、細かく保存していくとファイルの数と容量が増えてしまいます。
そこで問題を解決した、専用のバージョン管理システムがプログラミングにはよく使われています。
基本的な使い方は、事前にバージョン管理システムをインストールして、バリアントなどがあるフォルダを、バージョン管理システムで使う設定にします。リポジトリの作成と言います。
その後普通にエディタで保存した後、ある程度の区切りごとに、だいたい1つの機能追加ごとにですが、変更したファイルを更新履歴として登録します。これをコミットと言います。
後から「何月何日に変更したファイルはどれか?」とか、「このファイルを変更したのは何日と何日か?」とかいった事が調べられます。
この部分は何のために変更したんだったかな?と思った時に履歴をたどって調べられますし、この変更はやっぱり失敗だったなと思ったら元に戻す事も出来ます。
WinMergeを使っている人なら差分表示に慣れていると思いますが、バージョン管理システムではこの差分を保存しています。変更のあるところだけ保存しておくので全バージョンをzipで保存するより効率がいいのです。
バージョン管理用データは作業用で遊ぶためには不要なので、配布ファイルには含めないことが多いですが、開発者向けに添付されている場合もありますし、うっかり同梱してしまうということもたまにあります。
実際にはかなりの人数がバージョン管理システムを使って自作のバリアントやまとめ等を管理しているはずです。emueraの開発にも使われています。
パッチの開発をしていると、製作中に本家のバージョンがあがったりして困る事がありますが、そういう場合も差分で更新履歴がわかっているので、自分が追加した分と、本家で追加された部分と、統合作業が楽になります。
同じファイルといっても、書き換える箇所は全然別の事が多いので、そういう場合はほとんど自動で修正が終わります。
古いファイルで上書きした事によるバグの復活もおこりにくいし、おこったとしても原因の把握と修正はやりやすいです。
パッチの統合のような作業になると難しい部分もあるのですが、変更の記録とその確認だけならわりと簡単なので、興味のある方は一度チャレンジしてみてください。
元々はプログラマーだけが使うものでしたが、ファイルの更新履歴を管理するだけなので、実は色んな用途に使える仕組みです。
Officeのデータや、イラスト、小説等の分野でも使われているようです。変な状態でうっかり上書きしたとか、前の方が良かったかも…といったトラブルはどの分野でも起こる事なので。
Subversion(SVN)、Git、Mercurial等など色々あって、微妙に得意分野が違うのですが、差分を更新履歴として登録して、後から扱えるようにするという仕組みはどれも同じです。
入門サイトや比較サイトなどを見てピンと来た物があればそれを、特になければ利用者の多いSVNかGitが困った時に調べやすいです。
eraRoronaにはBazaarというシステム用のデータが添付されています。
どのシステムでもいいのですが、コマンドラインから直接というのは大変なので、TortoiseSVNやTortoiseGit、あるいはSourceTreeの様に、GUIで操作出来るソフトを使うのがおすすめです。