0からDiscordのダイスボットを作成する:その2
2回目。前回記事はこれ。
前回、
こんな感じにダイスボットを実装することができました。
今回は「2d6+5」みたいな固定値の加算を分かりやすく表示するのと、「k10@10」みたいな威力表ロールを実装していきます。
・固定値の加算を分かりやすく表示する
前回書いた正規表現がこれ。
d = "#{event.content}".match(/\A([0-9]*)[Dd]([0-9]+)(?:\+([0-9]*))?(?: .*)?\z/)
これで、「xDy+z 任意の文字列」というダイスコードを読むことができます。
次は読み取ったダイスコードを元にダイスをロールする部分。
if d.nil?
else
puts d.inspect
dice = (1..[1,d[1].to_i].max).inject(0){|sum| sum += rand(d[2].to_i)+1}
event.respond "(#{event.content}) 出目: #{dice} 結果: #{dice+d[3].to_i}"
end
上記で、変数dがnil(今回の場合、xDyの形になっていない限りnilになる…はずです)のときは何もせず、nilでない場合(値が入っている場合)は、xDyのxの値(0の場合は代わりに1)の回数だけ sum+=rand以下略 が読まれます。
以下略の部分は、xDyのyの部分を読んで、0からy未満までのランダムな整数を返します。1足してやると1からy以下の整数となるので、サイコロになってくれます((1..d[2].to_i)でもイケると思います)
実はevent.respond以下略の部分以外は前回から変わってません(前回はコードを載せてなかったので載せました)
これで「xDy+z 任意の文字列」の実装は終わりです。
次は威力表ロールです。
まず「kx@y」(xとyは任意の整数)を読むための正規表現を書きます。
k = "#{event.content}".match(/\Ak([0-9]+)@([0-9]+)(?:\+([0-9]*))?\z/)
書きました。これで、k[1]には威力、k[2]にはC値、k[3]には固定値が入ります(固定値の加算は実装予定は今のところないですが)。
if k.nil?
else
puts k.inspect
roll = (1..2).inject(0){|sum| sum += rand(1..6)}
puts roll
if roll == 2
event.respond"威力表:#{k[1]}(C値#{k[2]}) 出目 = #{roll} 結果 = 自動失敗"
else
rating = open("rating.txt", "r")
if roll < k[2].to_i
event.respond"威力表:#{k[1]}(C値#{k[2]}) 出目 = #{roll} 結果 = #{rating.readlines[k[1].to_i*10+roll-3]}"
else
event.respond"威力表:#{k[1]}(C値#{k[2]}) 出目 = #{roll} 結果 = #{rating.readlines[k[1].to_i*10+roll-3]} Critical!"
end
rating.close
end
例によって、最初に変数kがnilかどうかを判別します。nilでなければ、rollに2d6の値を入れます。
次に、rollの値が2(ピンゾロ)だった場合、入力された「kx@y」に従って威力表とC値、自動失敗を出力します。
そうでなかった場合は、威力表を書き込んだファイル(rating.txt)を読み込み、威力と出目に従って参照します。
配列を良く分かってないので1行ごとに威力0の出目3、威力0の出目4と入力していき、[威力*10+出目-3]番目の行を参照することで擬似的に二次元配列っぽくしてます。
デキる人はたぶんcsv?とか使って二次元配列とか利用するとカッコよくエレガントに実装できると思います。
また、結果を出力する際に、rollの値がC値(k[2])未満かどうかを判定します。未満であればそのまま出力し、以上であれば文の末尾にCritical!の文字を表示します。
これで威力表ロールの実装は終了です。テキストファイルから威力表を参照してる都合、別の型からInt型に変換しなきゃいけないと思うので、固定値の加算はめんどくさいです。そのうち実装すると思います。
今回はここまで。このふたつの実装だけで3時間もかかりました。