「BCDice/内部処理/BCDiceクラス」の版間の差分

提供: TRPGツール開発・運用Wiki
ナビゲーションに移動 検索に移動
(0ヴ (トーク) による版 176 を取り消し)
タグ: 取り消し
 
(2人の利用者による、間の6版が非表示)
73行目: 73行目:
 
   @message = @messageOriginal.upcase
 
   @message = @messageOriginal.upcase
 
   debug("@message", @message)
 
   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の司令塔といえるクラス。ゲームの指定、ダイスロールなどの主要な操作は、このクラスを介して行う。

setGameByTitle

https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L1778-L1801

指定されたゲーム名のダイスボットを使うように設定する。

  1. カード機能を初期化する。
  2. 指定されたゲーム名のダイスボットを設定する。
    1. 設定後の処理を行う(diceBot.postSet)。
  3. ゲームを設定したことを示すメッセージを返す。
# 指定したタイトルのゲームを設定する
# @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

https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L146-L163

ダイスボットに実行させるメッセージを設定する。

  1. メッセージのパターンに合わせて指定されたメッセージを加工する。
    • Open Dice!Open Plot!Set 系は指定されたメッセージそのまま。
    • それ以外の場合、空白の前まで。
  2. 括弧内前処理を行う。「#parren_killer」を参照。結果を @messageOriginal に記録する。
  3. 括弧内前処理の結果に対して、アルファベットを大文字にする。これを次に実行させるメッセージとして @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

https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L1550-L1608

括弧内前処理、つまり括弧で囲まれた数式部分を還元して整数に変える処理。

BCDiceのダイス構文は正規文法ではないのに、正規表現だけで処理しようとしているため、無理矢理気味な処理となっている。また、原理上、文法エラーを検出できない場合がある。例えば、

  • (2*/2)d6(2*/2)d6 : (1D6) > 3

など。

処理の流れは以下のとおり。

  1. [nDs] の加算ロールを先に実行する。実際の処理は「#rollDiceAddingUp」が担当する。
  2. 範囲構文を数字に変える。「#changeRangeTextToNumberText」を参照。
  3. 括弧に入った四則演算(+-*/)を処理する。
  4. 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

https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L1046-L1052

出目を記録するかどうかを設定するメソッドのようだが、実際には、引数 btrue を設定すると記録スロットを初期化するという動作になっている。false を設定すると記録スロットが nil でクリアされる。

def setCollectRandResult(b)
  if( b )
    @randResults = []
  else
    @randResults = nil
  end
end

dice_command

https://github.com/torgtaitai/BCDice/blob/86b8dd03ae00f8ea6a8787f9f514a5d83b2e3d41/src/bcdiceCore.rb#L769-L801

ダイスロールを実行する。以下の順で、実行できる処理があればそれを実行し、できなければ次の処理を試すことを繰り返す。

  1. 指定されたゲームシステムの固有コマンド
  2. D66ロール
  3. 加算ロール xDn
  4. バラバラロール xB
  5. 個数振り足しロール xRn
  6. 上方無限ロール xUn
  7. ランダム選択 choice[A, B, ...]
  8. 独自の表から項目を引く

戻り値は、結果のメッセージと、シークレットロールかどうか。すべての処理に失敗した場合は結果のメッセージが "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