class BCDice::CommonCommand::RerollDice::Node::Command

Public Class Methods

new(secret:, notations:, source:, cmp_op: nil, target_number: nil, reroll_cmp_op: nil, reroll_threshold: nil) click to toggle source
# File lib/bcdice/common_command/reroll_dice/node.rb, line 8
def initialize(secret:, notations:, source:, cmp_op: nil, target_number: nil, reroll_cmp_op: nil, reroll_threshold: nil)
  @secret = secret
  @notations = notations
  @cmp_op = cmp_op
  @target_number_node = target_number
  @reroll_cmp_op = reroll_cmp_op
  @reroll_threshold_node = reroll_threshold
  @source = source
end

Public Instance Methods

eval(game_system, randomizer) click to toggle source
# File lib/bcdice/common_command/reroll_dice/node.rb, line 18
def eval(game_system, randomizer)
  round_type = game_system.round_type
  cmp_op = @cmp_op || game_system.default_cmp_op
  reroll_cmp_op = @reroll_cmp_op || cmp_op || :>=

  target_number =
    @target_number_node&.eval(round_type) ||
    game_system.default_target_number

  reroll_threshold =
    @reroll_threshold_node&.eval(round_type) ||
    game_system.reroll_dice_reroll_threshold ||
    target_number

  reroll_condition = RerollCondition.new(reroll_cmp_op, reroll_threshold)

  dice_queue = @notations.map { |node| node.to_dice(round_type) }
  unless dice_queue.all? { |d| reroll_condition.valid?(d.sides) }
    return result_with_text("#{@source} > 条件が間違っています。2R6>=5 あるいは 2R6[5] のように振り足し目標値を指定してください。")
  end

  dice_list_list = roll(
    dice_queue,
    randomizer,
    reroll_condition,
    game_system.sort_barabara_dice?
  )

  dice_list = dice_list_list.flatten

  # 振り足し分は出目1の個数をカウントしない
  one_count = dice_list_list
              .take(@notations.size)
              .flatten
              .count(1)

  success_count =
    if cmp_op
      dice_list.count { |val| val.send(cmp_op, target_number) }
    else
      0
    end

  sequence = [
    expr(round_type, reroll_condition, cmp_op, target_number),
    dice_list_list.map { |list| list.join(",") }.join(" + "),
    "成功数#{success_count}",
    game_system.grich_text(one_count, dice_list.size, success_count),
  ].compact

  result_with_text(sequence.join(" > "))
end

Private Instance Methods

expr(round_type, reroll_condition, cmp_op, target_number) click to toggle source
# File lib/bcdice/common_command/reroll_dice/node.rb, line 100
def expr(round_type, reroll_condition, cmp_op, target_number)
  notation = @notations.map { |n| n.to_dice(round_type) }.join("+")

  reroll_cmp_op_text =
    if reroll_condition.cmp_op == cmp_op
      ""
    else
      Format.comparison_operator(reroll_condition.cmp_op)
    end

  cmp_op_text = Format.comparison_operator(cmp_op)

  "(#{notation}[#{reroll_cmp_op_text}#{reroll_condition.threshold}]#{cmp_op_text}#{target_number})"
end
result_with_text(text) click to toggle source
# File lib/bcdice/common_command/reroll_dice/node.rb, line 115
def result_with_text(text)
  Result.new.tap do |r|
    r.secret = @secret
    r.text = text
  end
end
roll(dice_queue, randomizer, reroll_condition, sort) click to toggle source

ダイスロールを行う @param dice_queue [Array<Dice>] ダイスキュー @param randomizer [Randomizer] 乱数生成器 @param reroll_condition [RerollCondition] 振り足し条件 @param sort [Boolean] 出目を並び替えるか @return [Array<Array<Integer>>]

# File lib/bcdice/common_command/reroll_dice/node.rb, line 79
def roll(dice_queue, randomizer, reroll_condition, sort)
  dice_list_list = []
  loop_count = 0

  while !dice_queue.empty? && loop_count < REROLL_LIMIT
    dice = dice_queue.shift
    loop_count += 1

    dice_list = dice.roll(randomizer)
    dice_list.sort! if sort
    dice_list_list.push(dice_list)

    reroll_count = dice_list.count { |val| reroll_condition.reroll?(val) }
    if reroll_count > 0
      dice_queue.push(Dice.new(reroll_count, dice.sides))
    end
  end

  return dice_list_list
end