ここでは「どどんとふ」のダイスボットを自作してみたい人用に具体的な手順について記述しています。
「ダイス+ロボット」でダイスボット。 元々はチャットソフトでダイスを振ってくれるロボットの様なツールを指す言葉ですね。 どどんとふではそのネーミングを引き継いでゲーム用のダイステキストを処理する機能を「ダイスボット」と呼んでいます。
どどんとふで遊ぼうと思ったゲームがダイスボットの一覧に無い。 そんな時にどうするか?
作者に頼むのもモチロンいいですね。
でも、超マイナールールだったり自作TRPGだったり、あるいは単純にプログラミングってのが楽しそうだったり。 色んな理由で自分で作りたくなる時ってのはあるものです。 そんなダイスボットの自作が出来ちゃうのがどどんとふの魅力の一つ。 オープンソースの素晴らしさというわけですね。
どどんとふのダイスボットは「Ruby」というプログラミング言語でソースコードを書くことで追加・変更することができます。 「うっはープログラミングとかサッパリだわー」という人は、流石にこの先は読まなくてもOKです。
「Ruby!いいね!俺大好きなんだよ!」なんて酔狂な方はもちろんウェルカム! でもここでは、どちらかというと「Rubyかー、この機会にちょっと勉強してみようかな?」という方向けに説明を進めていきます。
それではWindows環境向けにダイスボットを自作するための手順を説明していきましょう。 (Unix系OSの人なら当然Rubyはインストール済みと信じて説明は割愛。)
ダイスボットの作成のためにはWindows用のRuby実行環境を作成する必要があります。
RubyInstallerの「Download」ページから、 Ruby+Devkit 2.X.X-X (x64)
(Xは任意の数字)をダウンロードします。
あとは、インストーラーの指示に従ってインストール。
そしてインストールディレクトリの bin にパスを通します。(パスを通す、の意味が知らない人はネットで検索だ!)
Ruby 2.6.5のデフォルトだと C:\Ruby26-x64\bin
ですかね。
ruby.exe のある場所にパスを通すのがポイントです。
後はコマンドプロンプト開いて(コマンドプロンプト、の意味が分からない人はネットで(略))、
ruby -v
とコマンドを実行して、Rubyのバージョン情報が表示されればOKです。 準備万端。それではダイスボットを作っていきましょう!
今回サンプルとして作るダイスボット用に架空のゲームシステムがあるとしましょう。
タイトル
仮ダイス
判定方法
6面ダイスをX個振るシステム。
判定コマンドは KDx>=y(xはダイスロール数、yは目標値)
これをダイスボットで実装する方法を考えて行きましょう。
まずは src/diceBot
ディレクトリを開きます。
その中に _Template.rb
という名前のファイルがあります。
テンプレート、TRPGでもよく使われる単語ですね。
要は「ひな型」って意味でして、それをもとに作れば1から作るよりも楽だよーってニュアンスですね。
ではでは、そのニュアンスを信じて _Template.rb
ファイルを元に作ってみましょう。
_Template.rb
ファイルをコピーして、今回のゲーム用のタイトルをファイル名に付けましょう。
タイトルが「仮ダイス」ですから
KariDice.rb
ですかね。
このKariDiceという名前は「ダイスボットの型名」と呼んで他でも使いますので「ファイル名なんてなんでもいいや」とか思わずにしっかり決めてくださいね。
プログラミングでは命名が何より大事ですので。
この KariDice.rb
を以降は編集していきます。
KariDice.rb
はまだ中身は _Template.rb
ファイルのままですね。
この中身をチョイチョイっと書き換えて仮ダイスを実装していきましょう。
ファイルを開いて、
class Template < DiceBot
ここを、今回のダイスボットは名前が KariDice
なので
class KariDice < DiceBot
と書き換え。ファイル名の(~.rb)部分と同じにするわけですね。
続いて
# ゲームシステムの識別子
ID = 'SystemID'
# ゲームシステム名
NAME = 'ゲームシステム名'
# ゲームシステム名の読みがな
SORT_KEY = 'けえむしすてむめい'
を
# ゲームシステムの識別子
ID = 'KariDice'
# ゲームシステム名
NAME = '仮ダイス'
# ゲームシステム名の読みがな
SORT_KEY = 'かりたいす'
に変更。
ID
ではファイル名と同じ英文字でのファイル名と同じ英文字での型名を、NAME
では日本語のゲーム名を定義しています。
また、SORT_KEY
ではゲーム名の読みがなを定義します。辞書と同じ並び順になるように、濁点を省いたひらがなで設定してください(詳しくは「ゲームシステム名の読みがなの設定方法」を参照)。
では書き間違いがないか、念のため KariDice.rb
の置いてあるディレクトリで
ruby -cw KariDice.rb
とコマンドを実行しましょう。
Syntax OK
と表示されれば問題ありません。
エラーが表示される場合はそこに文法間違いがあるので確認しましょう。 もうこれだけでダイスボットとしての形は整ったことになります!
では、今回実装する予定の判定コマンドを実装していきましょう。 定義はこうでしたね。
判定方法
6面ダイスをX個振るシステム。
判定コマンドは KDx>=y(xはダイスロール数、yは目標値)
これを実装するには、
setPrefixes([])
と
def rollDiceCommand(command)
''
end
の2つのメソッドを書き換えることになります。
引数の command
にダイスボットとして入力した文字列が渡されますので、そこからロールの判定を行い、結果の文字列を戻り値に渡せばOKです。
では早速実装!
…とその前に、動作テストの用意をしましょう。
どどんとふのダイスボットには、作成時の動作検証がしやすいように動作テスト用の仕組みが用意されています(「ユニットテスト」と呼ばれます)。
これを活用すればダイスボットが正しく動いているかをどどんとふ上で確認しなくてもよいのでとっても楽です。
src
に移動。
そこにある test.rb
がテスト用のスクリプト。 そして test/data/
配下にあるテキストファイルが全てテスト用のデータです。
ここでは例として Cthulhu.txt を開きましょう。
============================
input:
1D100<=10
output:
Cthulhu : (1D100<=10) > 98 > 致命的失敗
rand:98/100
============================
input:
1D100<=10
output:
Cthulhu : (1D100<=10) > 45 > 失敗
rand:45/100
============================
といった記述が並んでいますね。 テストデータの書式は
input:
(テストしたいデータ)
output:
(ダイスボットの型名) : (出力される文字列)
rand:(テストしたいダイスの出目)
となります。 また、複数テストデータを記述するときは、データの間を
============================
で区切る必要があります。
output
の「(ダイスボットの型名):」はダイスボットの内部で自動的に生成されるので常に必要です。
実際に表示される文字を意識したいので、省略はできなくなっています。
rand
では 1/6,2/6
のように「(出目)/(ロールするダイス)」を ,
で区切って並べる形で記述します。
これを使えば3D6で「1, 1, 1」を出すようなパターンでも 1/6,1/6,1/6
と記述してしまえばすぐ検証できるわけですね。便利!
今回は、新しいテストデータファイル KariDice.txt
を作成してみましょう。
.rb と同じ名前でテストデータの .txt を作成するわけですね。
input:
KD3>=10
output:
KariDice : (KD3>=10) > 10[2,5,3] > 成功
rand:2/6,5/6,3/6
============================
input:
KD3>=10
output:
KariDice : (KD3>=10) > 9[1,5,3] > 失敗
rand:1/6,5/6,3/6
そしてテストの実行。
ruby test.rb KariDice
このコマンドを実行すると、以下のように出力されます。
ruby test.rb KariDice
XX
[Failures]
Game type: KariDice
Index: 1
Input:
KD3>=10
Expected:
KariDice : (KD3>=10) > 10[2,5,3] > 成功
Result:
ダイス残り:2/6, 5/6, 3/6
Rands: 2/6, 5/6, 3/6
===========================
Game type: KariDice
Index: 2
Input:
KD3>=10
Expected:
KariDice : (KD3>=10) > 9[1,5,3] > 失敗
Result:
ダイス残り:1/6, 5/6, 3/6
Rands: 1/6, 5/6, 3/6
これは xx
と x
が2つなので「テスト2件に失敗」を示します。成功なら ..
となって、「OK」が表示されます。
ここでは判定成功時と失敗時の2件の動作を確認して、両方に失敗したということですね。
早く「OK」が表示されるのが楽しみですね!
以後は「ソースコードを変更したらテストを実行して動作を確認」、 新しい実装をする時には「先にテストデータを作って、動作確認」を繰り返すことになります。 「テスト→実装→テスト→実装→…」の順ですね。
ちなみに、こうやって先にテストを作ってからプログラムを作成する方法を「テストファースト」って呼んだりします。 ぜひ実践していきましょう!
準備もできたので、ダイスボットの実装を。
まずはコマンドを setPrefixes
で定義して、どどんとふに教えてやる必要があります。忘れがちなので注意!
setPrefixes(['KD\d+>=\d+'])
ポイントは、文字列を " "
ではなく ' '
で囲むことです。
こうしないと d
が \
文字でエスケープされてしまい、\d
という文字列にならないのですね。
正規表現相当の文字をここで文字列として定義してRubyとActionScript両方で使っているので、扱いにクセがあります。
分かりにくい場合は、今後の拡張性も考えて
setPrefixes(['KD.\*'])
みたいに手を抜いた記述にしてしまうのも手です。
とりあえず動かしてみたいですしね。
次にコマンドの判定部分を実装。
def rollDiceCommand(command)
debug("rollDiceCommand Begin")
m = /^KD(\d+)>=(\d+)$/.match(command)
unless m
return ''
end
debug("command", command)
diceCount = m[1].to_i
target = m[2].to_i
total, diceText, _ = roll(diceCount, 6)
result = (total >= target ? "成功" : "失敗")
debug("rollDiceCommand result")
return "(#{command}) > #{total}[#{diceText}] > #{result}"
end
これで成否判定は実装完了。 rollメソッドはDiceBotクラスで実装済みのメソッドで、
合計, ダイスの文字列, [その他のデータ] = roll(ダイス数, ダイス種別)
みたいに使います。今回は [その他のデータ]
は使わないので省略して
合計, ダイスの文字列, _ =
となっています。 =
の直前に , _
があるのがポイントです。
この書き方で [その他のデータ]
は無視するよーって宣言しているわけですね。
あと、
debug("rollDiceCommand Begin")
と書いている箇所はデバッグ用の文字列です。 さっきテストを実行したときに
Index: 1
みたいな表示がありましたが、ここにあるIndexというのはテストの通番でして、
ruby test.rb KariDice 1
のようにテスト時にダイスボット名と共にインデックス番号を指定すると、そのテスト1件だけを実行してくれます。 特定のテストを詳細に検証する時に使うわけですが、その際にはデバッグ文が出力されるようになります。
たとえば、
debug("command", command)
と書くと
command : "KD3>=10"
みたいにデバッグ文が出力されるので読みやすく検証に便利です。 つまりテストでは
ruby test.rb (ダイスボット名)
で全体を確認しつつ、失敗パターンをピックアップ確認したいときは
ruby test.rb (ダイスボット名) (インデックス番号)
で実行。これがテストの王道ということですね。
あ、ちなみに
ruby test.rb
だけなら全ダイスボットのテストが実行されます。 最後の最後に試しておくと、他に影響を与えていないことが確認できて安心です。
さてさて、では先ほど提示した内容を実装してテストしてみましょう。
ruby test.rb KariDice
..
OK.
「OK」が表示されました!やったね!!
ダイスボットを自作するのではなく、既存のダイスボットを拡張する、という方も多いでしょう。 その場合も、基本的には同じ手順で大丈夫です。 ただ、ここでひとつ注意が必要となるのが「後方互換性」について。
「どどんとふ」では過去のバージョンとの互換性を何よりも重視しています。 オンセ用に作った自キャラ用のダイスボットのコマンドがある日急に使えなくなる、というのは最も避けたい事態ですね。 なので、コマンドや機能を拡張する場合には既存の機能を変更しないのが大事です。 これが「後方互換性」です。
もちろん、オリジナルのダイスボットを作る場合や、個人的に拡張する場合には自由に作ってOKですが、 「完成したら公式にも送ろう…」なんて素晴らしいことを考えている方は注意していただければと思います。
ここまでできれば、後は同じことの繰り返しでダイスボットを実装できます。
まとめると
- テストファーストでテスト作成し失敗することを確認。
- コードを実装、テスト。
- うまく動かなかったらインデックス指定しデバッグ表示で内容確認。
- OKが表示されたら祝杯!
こんな感じですね。
テストデータの作成にはパターンの網羅や以上・以下の閾値確認など色々ポイントがあるんですが、 それ書き出すとまた長文になりそうなので各自で工夫してみてくださいね。
ではでは!