「BCDice/内部処理/BCDiceクラス」の版間の差分
ナビゲーションに移動
検索に移動
Ochaochaocha3 (トーク | 投稿記録) (目次を追加する) |
タグ: 取り消し |
||
(2人の利用者による、間の10版が非表示) | |||
8行目: | 8行目: | ||
https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L1778-L1801 | https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L1778-L1801 | ||
+ | |||
+ | 指定されたゲーム名のダイスボットを使うように設定する。 | ||
# カード機能を初期化する。 | # カード機能を初期化する。 | ||
38行目: | 40行目: | ||
return message | return message | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == setMessage == | ||
+ | |||
+ | https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L146-L163 | ||
+ | |||
+ | ダイスボットに実行させるメッセージを設定する。 | ||
+ | |||
+ | # メッセージのパターンに合わせて指定されたメッセージを加工する。 | ||
+ | #* <code>Open Dice!</code> や <code>Open Plot!</code>、<code>Set</code> 系は指定されたメッセージそのまま。 | ||
+ | #* それ以外の場合、空白の前まで。 | ||
+ | # 括弧内前処理を行う。「[[#parren_killer]]」を参照。結果を <code>@messageOriginal</code> に記録する。 | ||
+ | # 括弧内前処理の結果に対して、アルファベットを大文字にする。これを次に実行させるメッセージとして <code>@message</code> に記録する。 | ||
+ | |||
+ | <syntaxhighlight lang="ruby"> | ||
+ | def setMessage(message) | ||
+ | # 設定で変化し得るためopen系はここで正規表現を作る | ||
+ | openPattern = /\A\s*(?:#{$OPEN_DICE}|#{$OPEN_PLOT})\s*\z/i | ||
+ | |||
+ | messageToSet = | ||
+ | case message | ||
+ | when openPattern, SET_COMMAND_PATTERN | ||
+ | message | ||
+ | else | ||
+ | # 空白が含まれる場合、最初の部分だけを取り出す | ||
+ | message.split(/\s/, 2).first | ||
+ | end | ||
+ | debug("setMessage messageToSet", messageToSet) | ||
+ | |||
+ | @messageOriginal = parren_killer(messageToSet) | ||
+ | @message = @messageOriginal.upcase | ||
+ | debug("@message", @message) | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == parren_killer == | ||
+ | |||
+ | https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L1550-L1608 | ||
+ | |||
+ | 括弧内前処理、つまり括弧で囲まれた数式部分を還元して整数に変える処理。 | ||
+ | |||
+ | BCDiceのダイス構文は正規文法ではないのに、正規表現だけで処理しようとしているため、無理矢理気味な処理となっている。また、原理上、文法エラーを検出できない場合がある。例えば、 | ||
+ | |||
+ | * <code>(2*/2)d6</code> → <code>(2*/2)d6 : (1D6) > 3</code> | ||
+ | |||
+ | など。 | ||
+ | |||
+ | 処理の流れは以下のとおり。 | ||
+ | |||
+ | # <code>[<var>n</var>D<var>s</var>]</code> の加算ロールを先に実行する。実際の処理は「[[#rollDiceAddingUp]]」が担当する。 | ||
+ | # 範囲構文を数字に変える。「[[#changeRangeTextToNumberText]]」を参照。 | ||
+ | # 括弧に入った四則演算(<code>+-*/</code>)を処理する。 | ||
+ | # <code><var>n</var>D</code> が残っていたら、<code><var>n</var>D6</code> に変える。 | ||
+ | |||
+ | <syntaxhighlight lang="ruby"> | ||
+ | def parren_killer(string) | ||
+ | debug("parren_killer input", string) | ||
+ | |||
+ | while( /^(.*?)\[(\d+[Dd]\d+)\](.*)/ =~ string ) | ||
+ | str_before = "" | ||
+ | str_after = "" | ||
+ | dice_cmd = $2 | ||
+ | str_before = $1 if($1) | ||
+ | str_after = $3 if($3) | ||
+ | rolled, dmy = rollDiceAddingUp(dice_cmd) | ||
+ | string = "#{str_before}#{rolled}#{str_after}" | ||
+ | end | ||
+ | |||
+ | string = changeRangeTextToNumberText(string) | ||
+ | |||
+ | while(/^(.*?)(\([\d\/*+-]+?\))(.*)/ =~ string) | ||
+ | debug("while string", string) | ||
+ | |||
+ | str_a = $3 | ||
+ | str_a ||= "" | ||
+ | |||
+ | str_b = $1 | ||
+ | str_b ||= "" | ||
+ | debug("str_b", str_b) | ||
+ | |||
+ | par_i = $2 | ||
+ | |||
+ | debug("par_i", par_i) | ||
+ | par_o = paren_k(par_i) | ||
+ | debug("par_o", par_o) | ||
+ | |||
+ | if(par_o != 0) | ||
+ | if(par_o < 0) | ||
+ | if(/(.+?)(\+)$/ =~ str_b) | ||
+ | str_b = $1 | ||
+ | elsif(/(.+?)(-)$/ =~ str_b) | ||
+ | str_b = "#{$1}+" | ||
+ | par_o = par_o * -1 | ||
+ | end | ||
+ | end | ||
+ | string = "#{str_b}#{par_o}#{str_a}" | ||
+ | else | ||
+ | if(/^([DBRUdbru][\d]+)(.*)/ =~ $str_a) | ||
+ | str_a = $2 | ||
+ | end | ||
+ | string = "#{str_b}0#{str_a}" | ||
+ | end | ||
+ | end | ||
+ | |||
+ | debug("diceBot.changeText(string) begin", string) | ||
+ | string = @diceBot.changeText(string) | ||
+ | debug("diceBot.changeText(string) end", string) | ||
+ | |||
+ | string = string.gsub(/([\d]+[dD])([^\d\w]|$)/) {"#{$1}6#{$2}"} | ||
+ | |||
+ | debug("parren_killer output", string) | ||
+ | |||
+ | return string | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == setCollectRandResult == | ||
+ | |||
+ | https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L1046-L1052 | ||
+ | |||
+ | 出目を記録するかどうかを設定するメソッドのようだが、実際には、引数 <code>b</code> に <code>true</code> を設定すると記録スロットを初期化するという動作になっている。<code>false</code> を設定すると記録スロットが <code>nil</code> でクリアされる。 | ||
+ | |||
+ | <syntaxhighlight lang="ruby"> | ||
+ | def setCollectRandResult(b) | ||
+ | if( b ) | ||
+ | @randResults = [] | ||
+ | else | ||
+ | @randResults = nil | ||
+ | end | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == dice_command == | ||
+ | |||
+ | https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L769-L801 | ||
+ | |||
+ | ダイスロールを実行する。以下の順で、実行できる処理があればそれを実行し、できなければ次の処理を試すことを繰り返す。 | ||
+ | |||
+ | # 指定されたゲームシステムの固有コマンド | ||
+ | # D66ロール | ||
+ | # 加算ロール <code><var>x</var>D<var>n</var></code> | ||
+ | # バラバラロール <code><var>x</var>B<var></var></code> | ||
+ | # 個数振り足しロール <code><var>x</var>R<var>n</var></code> | ||
+ | # 上方無限ロール <code><var>x</var>U<var>n</var></code> | ||
+ | # ランダム選択 <code>choice[<var>A</var>, <var>B</var>, ...]</code> | ||
+ | # 独自の表から項目を引く | ||
+ | |||
+ | 戻り値は、結果のメッセージと、シークレットロールかどうか。すべての処理に失敗した場合は結果のメッセージが <code>"1"</code> となることに注意。これはPerl時代の名残りと思われる。 | ||
+ | |||
+ | <syntaxhighlight lang="ruby"> | ||
+ | def dice_command # ダイスコマンドの分岐処理 | ||
+ | arg = @message.upcase | ||
+ | |||
+ | debug('dice_command arg', arg) | ||
+ | |||
+ | output, secret = @diceBot.dice_command(@message, @nick_e) | ||
+ | return output, secret if( output != '1' ) | ||
+ | |||
+ | output, secret = rollD66(arg) | ||
+ | return output, secret unless( output.nil? ) | ||
+ | |||
+ | output, secret = checkAddRoll(arg) | ||
+ | return output, secret unless( output.nil? ) | ||
+ | |||
+ | output, secret = checkBDice(arg) | ||
+ | return output, secret unless( output.nil? ) | ||
+ | |||
+ | output, secret = checkRnDice(arg) | ||
+ | return output, secret unless( output.nil? ) | ||
+ | |||
+ | output, secret = checkUpperRoll(arg) | ||
+ | return output, secret unless( output.nil? ) | ||
+ | |||
+ | output, secret = checkChoiceCommand(arg) | ||
+ | return output, secret unless( output.nil? ) | ||
+ | |||
+ | output, secret = getTableDataResult(arg) | ||
+ | return output, secret unless( output.nil? ) | ||
+ | |||
+ | output = '1' | ||
+ | secret = false | ||
+ | return output, secret | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> |
2020年8月25日 (火) 07:45時点における最新版
BCDiceの司令塔といえるクラス。ゲームの指定、ダイスロールなどの主要な操作は、このクラスを介して行う。
- v2.02.80.01:https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb
setGameByTitle
指定されたゲーム名のダイスボットを使うように設定する。
- カード機能を初期化する。
- 指定されたゲーム名のダイスボットを設定する。
- 設定後の処理を行う(
diceBot.postSet
)。
- 設定後の処理を行う(
- ゲームを設定したことを示すメッセージを返す。
# 指定したタイトルのゲームを設定する
# @param [String] gameTitle ゲームタイトル
# @return [String] ゲームを設定したことを示すメッセージ
def setGameByTitle(gameTitle)
debug('setGameByTitle gameTitle', gameTitle)
@cardTrader.initValues
loader = DiceBotLoaderList.find(gameTitle)
diceBot =
if loader
loader.loadDiceBot
else
DiceBotLoader.loadUnknownGame(gameTitle) || DiceBot.new
end
setDiceBot(diceBot)
diceBot.postSet
message = "Game設定を#{diceBot.gameName}に設定しました"
debug( 'setGameByTitle message', message )
return message
end
setMessage
ダイスボットに実行させるメッセージを設定する。
- メッセージのパターンに合わせて指定されたメッセージを加工する。
Open Dice!
やOpen Plot!
、Set
系は指定されたメッセージそのまま。- それ以外の場合、空白の前まで。
- 括弧内前処理を行う。「#parren_killer」を参照。結果を
@messageOriginal
に記録する。 - 括弧内前処理の結果に対して、アルファベットを大文字にする。これを次に実行させるメッセージとして
@message
に記録する。
def setMessage(message)
# 設定で変化し得るためopen系はここで正規表現を作る
openPattern = /\A\s*(?:#{$OPEN_DICE}|#{$OPEN_PLOT})\s*\z/i
messageToSet =
case message
when openPattern, SET_COMMAND_PATTERN
message
else
# 空白が含まれる場合、最初の部分だけを取り出す
message.split(/\s/, 2).first
end
debug("setMessage messageToSet", messageToSet)
@messageOriginal = parren_killer(messageToSet)
@message = @messageOriginal.upcase
debug("@message", @message)
end
parren_killer
括弧内前処理、つまり括弧で囲まれた数式部分を還元して整数に変える処理。
BCDiceのダイス構文は正規文法ではないのに、正規表現だけで処理しようとしているため、無理矢理気味な処理となっている。また、原理上、文法エラーを検出できない場合がある。例えば、
(2*/2)d6
→(2*/2)d6 : (1D6) > 3
など。
処理の流れは以下のとおり。
[nDs]
の加算ロールを先に実行する。実際の処理は「#rollDiceAddingUp」が担当する。- 範囲構文を数字に変える。「#changeRangeTextToNumberText」を参照。
- 括弧に入った四則演算(
+-*/
)を処理する。 nD
が残っていたら、nD6
に変える。
def parren_killer(string)
debug("parren_killer input", string)
while( /^(.*?)\[(\d+[Dd]\d+)\](.*)/ =~ string )
str_before = ""
str_after = ""
dice_cmd = $2
str_before = $1 if($1)
str_after = $3 if($3)
rolled, dmy = rollDiceAddingUp(dice_cmd)
string = "#{str_before}#{rolled}#{str_after}"
end
string = changeRangeTextToNumberText(string)
while(/^(.*?)(\([\d\/*+-]+?\))(.*)/ =~ string)
debug("while string", string)
str_a = $3
str_a ||= ""
str_b = $1
str_b ||= ""
debug("str_b", str_b)
par_i = $2
debug("par_i", par_i)
par_o = paren_k(par_i)
debug("par_o", par_o)
if(par_o != 0)
if(par_o < 0)
if(/(.+?)(\+)$/ =~ str_b)
str_b = $1
elsif(/(.+?)(-)$/ =~ str_b)
str_b = "#{$1}+"
par_o = par_o * -1
end
end
string = "#{str_b}#{par_o}#{str_a}"
else
if(/^([DBRUdbru][\d]+)(.*)/ =~ $str_a)
str_a = $2
end
string = "#{str_b}0#{str_a}"
end
end
debug("diceBot.changeText(string) begin", string)
string = @diceBot.changeText(string)
debug("diceBot.changeText(string) end", string)
string = string.gsub(/([\d]+[dD])([^\d\w]|$)/) {"#{$1}6#{$2}"}
debug("parren_killer output", string)
return string
end
setCollectRandResult
出目を記録するかどうかを設定するメソッドのようだが、実際には、引数 b
に true
を設定すると記録スロットを初期化するという動作になっている。false
を設定すると記録スロットが nil
でクリアされる。
def setCollectRandResult(b)
if( b )
@randResults = []
else
@randResults = nil
end
end
dice_command
ダイスロールを実行する。以下の順で、実行できる処理があればそれを実行し、できなければ次の処理を試すことを繰り返す。
- 指定されたゲームシステムの固有コマンド
- D66ロール
- 加算ロール
xDn
- バラバラロール
xB
- 個数振り足しロール
xRn
- 上方無限ロール
xUn
- ランダム選択
choice[A, B, ...]
- 独自の表から項目を引く
戻り値は、結果のメッセージと、シークレットロールかどうか。すべての処理に失敗した場合は結果のメッセージが "1"
となることに注意。これはPerl時代の名残りと思われる。
def dice_command # ダイスコマンドの分岐処理
arg = @message.upcase
debug('dice_command arg', arg)
output, secret = @diceBot.dice_command(@message, @nick_e)
return output, secret if( output != '1' )
output, secret = rollD66(arg)
return output, secret unless( output.nil? )
output, secret = checkAddRoll(arg)
return output, secret unless( output.nil? )
output, secret = checkBDice(arg)
return output, secret unless( output.nil? )
output, secret = checkRnDice(arg)
return output, secret unless( output.nil? )
output, secret = checkUpperRoll(arg)
return output, secret unless( output.nil? )
output, secret = checkChoiceCommand(arg)
return output, secret unless( output.nil? )
output, secret = getTableDataResult(arg)
return output, secret unless( output.nil? )
output = '1'
secret = false
return output, secret
end