Skip to content

Latest commit

 

History

History
453 lines (321 loc) · 15.7 KB

how_to_make_dicebot.md

File metadata and controls

453 lines (321 loc) · 15.7 KB

ダイスボットのつくりかた

概要

ここでは「どどんとふ」のダイスボットを自作してみたい人用に具体的な手順について記述しています。

そもそもダイスボットって何?

「ダイス+ロボット」でダイスボット。 元々はチャットソフトでダイスを振ってくれるロボットの様なツールを指す言葉ですね。 どどんとふではそのネーミングを引き継いでゲーム用のダイステキストを処理する機能を「ダイスボット」と呼んでいます。

ダイスボットの自作って?

どどんとふで遊ぼうと思ったゲームがダイスボットの一覧に無い。 そんな時にどうするか?

作者に頼むのもモチロンいいですね。

でも、超マイナールールだったり自作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です。 準備万端。それではダイスボットを作っていきましょう!

自作ダイスボットの作り方:その1 名前大事!

今回サンプルとして作るダイスボット用に架空のゲームシステムがあるとしましょう。

タイトル
    仮ダイス

判定方法
    6面ダイスをX個振るシステム。
    判定コマンドは KDx>=y(xはダイスロール数、yは目標値)

これをダイスボットで実装する方法を考えて行きましょう。

まずは src/diceBot ディレクトリを開きます。 その中に _Template.rb という名前のファイルがあります。

テンプレート、TRPGでもよく使われる単語ですね。 要は「ひな型」って意味でして、それをもとに作れば1から作るよりも楽だよーってニュアンスですね。 ではでは、そのニュアンスを信じて _Template.rb ファイルを元に作ってみましょう。 _Template.rb ファイルをコピーして、今回のゲーム用のタイトルをファイル名に付けましょう。 タイトルが「仮ダイス」ですから

 KariDice.rb

ですかね。 このKariDiceという名前は「ダイスボットの型名」と呼んで他でも使いますので「ファイル名なんてなんでもいいや」とか思わずにしっかり決めてくださいね。 プログラミングでは命名が何より大事ですので。 この KariDice.rb を以降は編集していきます。

自作ダイスボットの作り方:その2 まずは形から

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

と表示されれば問題ありません。

エラーが表示される場合はそこに文法間違いがあるので確認しましょう。 もうこれだけでダイスボットとしての形は整ったことになります!

自作ダイスボットの作り方:その3 テストファースト!

では、今回実装する予定の判定コマンドを実装していきましょう。 定義はこうでしたね。

判定方法
    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

これは xxx が2つなので「テスト2件に失敗」を示します。成功なら .. となって、「OK」が表示されます。 ここでは判定成功時と失敗時の2件の動作を確認して、両方に失敗したということですね。 早く「OK」が表示されるのが楽しみですね!

以後は「ソースコードを変更したらテストを実行して動作を確認」、 新しい実装をする時には「先にテストデータを作って、動作確認」を繰り返すことになります。 「テスト→実装→テスト→実装→…」の順ですね。

ちなみに、こうやって先にテストを作ってからプログラムを作成する方法を「テストファースト」って呼んだりします。 ぜひ実践していきましょう!

自作ダイスボットの作り方:その4 そして実装

準備もできたので、ダイスボットの実装を。

まずはコマンドを 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ですが、 「完成したら公式にも送ろう…」なんて素晴らしいことを考えている方は注意していただければと思います。

終わりに

ここまでできれば、後は同じことの繰り返しでダイスボットを実装できます。

まとめると

  1. テストファーストでテスト作成し失敗することを確認。
  2. コードを実装、テスト。
  3. うまく動かなかったらインデックス指定しデバッグ表示で内容確認。
  4. OKが表示されたら祝杯!

こんな感じですね。

テストデータの作成にはパターンの網羅や以上・以下の閾値確認など色々ポイントがあるんですが、 それ書き出すとまた長文になりそうなので各自で工夫してみてくださいね。

ではでは!