bcdice 3.12.0 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/lib/bcdice/arithmetic/parser.rb +4 -2
- data/lib/bcdice/base.rb +1 -1
- data/lib/bcdice/command/parser.rb +4 -2
- data/lib/bcdice/common_command/add_dice/parser.rb +4 -2
- data/lib/bcdice/common_command/barabara_dice/parser.rb +4 -2
- data/lib/bcdice/common_command/calc/parser.rb +4 -2
- data/lib/bcdice/common_command/reroll_dice/parser.rb +4 -2
- data/lib/bcdice/common_command/tally_dice/parser.rb +4 -2
- data/lib/bcdice/common_command/upper_dice/parser.rb +4 -2
- data/lib/bcdice/game_system/Airgetlamh.rb +1 -1
- data/lib/bcdice/game_system/Alsetto.rb +2 -2
- data/lib/bcdice/game_system/AniMalus.rb +221 -0
- data/lib/bcdice/game_system/ArknightsFan.rb +182 -0
- data/lib/bcdice/game_system/Avandner.rb +1 -1
- data/lib/bcdice/game_system/BBN.rb +1 -1
- data/lib/bcdice/game_system/BadLife.rb +3 -3
- data/lib/bcdice/game_system/BarnaKronika.rb +1 -1
- data/lib/bcdice/game_system/Chill3.rb +6 -6
- data/lib/bcdice/game_system/DarkSouls.rb +1 -1
- data/lib/bcdice/game_system/Elric.rb +1 -1
- data/lib/bcdice/game_system/FullFace.rb +92 -0
- data/lib/bcdice/game_system/InfiniteFantasia.rb +4 -1
- data/lib/bcdice/game_system/Irisbane.rb +1 -1
- data/lib/bcdice/game_system/KillDeathBusiness.rb +1 -1
- data/lib/bcdice/game_system/KyokoShinshoku.rb +158 -0
- data/lib/bcdice/game_system/Liminal.rb +136 -0
- data/lib/bcdice/game_system/MetalHead.rb +1 -1
- data/lib/bcdice/game_system/MetalHeadExtream.rb +1 -1
- data/lib/bcdice/game_system/NRR.rb +122 -0
- data/lib/bcdice/game_system/NSSQ.rb +1 -1
- data/lib/bcdice/game_system/NightWizard.rb +1 -1
- data/lib/bcdice/game_system/NightWizard3rd.rb +15 -2
- data/lib/bcdice/game_system/OneWayHeroics.rb +1 -1
- data/lib/bcdice/game_system/PastFutureParadox.rb +1238 -0
- data/lib/bcdice/game_system/Postman.rb +3 -3
- data/lib/bcdice/game_system/RecordOfSteam.rb +1 -1
- data/lib/bcdice/game_system/RuneQuestRoleplayingInGlorantha.rb +1 -1
- data/lib/bcdice/game_system/Ryutama.rb +4 -4
- data/lib/bcdice/game_system/Siren.rb +97 -0
- data/lib/bcdice/game_system/Skynauts.rb +1 -1
- data/lib/bcdice/game_system/Strave.rb +1 -1
- data/lib/bcdice/game_system/TherapieSein.rb +1 -1
- data/lib/bcdice/game_system/TrinitySeven.rb +1 -1
- data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +12 -6
- data/lib/bcdice/game_system/WerewolfTheApocalypse5th.rb +12 -6
- data/lib/bcdice/game_system/cthulhu7th/full_auto.rb +1 -1
- data/lib/bcdice/game_system/sword_world/rating_parser.rb +4 -2
- data/lib/bcdice/game_system.rb +8 -0
- data/lib/bcdice/loader.rb +1 -1
- data/lib/bcdice/version.rb +1 -1
- metadata +27 -5
| @@ -0,0 +1,182 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module BCDice
         | 
| 4 | 
            +
              module GameSystem
         | 
| 5 | 
            +
                class ArknightsFan < Base
         | 
| 6 | 
            +
                  # ゲームシステムの識別子
         | 
| 7 | 
            +
                  ID = "ArknightsFan"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  # ゲームシステム名
         | 
| 10 | 
            +
                  NAME = "アークナイツTRPG by Dapto"
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # ゲームシステム名の読みがな
         | 
| 13 | 
            +
                  SORT_KEY = "ああくないつTRPGはいたふと"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  HELP_MESSAGE = <<~TEXT
         | 
| 16 | 
            +
                    ■ 判定 (nADm>=x)
         | 
| 17 | 
            +
                      nDmのダイスロールをして、x 以下であれば成功。
         | 
| 18 | 
            +
                      出目が91以上でエラー。
         | 
| 19 | 
            +
                      出目が10以下でクリティカル。
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    ■ 判定 (nABm>=x)
         | 
| 22 | 
            +
                      nBmのダイスロールをして、
         | 
| 23 | 
            +
                        x 以下であれば成功数+1。
         | 
| 24 | 
            +
                        出目が91以上でエラー。成功数+1。
         | 
| 25 | 
            +
                        出目が10以下でクリティカル。成功数-1。
         | 
| 26 | 
            +
                      上記による成功数をカウント。
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    ■ 判定 (nABm>=x--役職)
         | 
| 29 | 
            +
                      nBmのダイスロールをして、
         | 
| 30 | 
            +
                        出目が x 以下であれば成功数+1。
         | 
| 31 | 
            +
                        出目が91以上でエラー。成功数+1。
         | 
| 32 | 
            +
                        出目が10以下でクリティカル。成功数-1。
         | 
| 33 | 
            +
                      上記による成功数をカウントした上で、以下の役職による成功数増加効果を適応。
         | 
| 34 | 
            +
                        狙撃(SNIPER) 成功数1以上のとき、成功数+1。
         | 
| 35 | 
            +
                  TEXT
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  register_prefix('\d*AD\d*', '\d*AB\d*', '--ADDICTION', '--WORSENING')
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def eval_game_system_specific_command(command)
         | 
| 40 | 
            +
                    roll_ad(command) || roll_ab(command) || roll_addiction(command) || roll_worsening(command)
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  private
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  def roll_ad(command)
         | 
| 46 | 
            +
                    m = /^(\d*)AD(\d*)<=(\d+)$/.match(command)
         | 
| 47 | 
            +
                    return nil unless m
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    times = m[1]
         | 
| 50 | 
            +
                    sides = m[2]
         | 
| 51 | 
            +
                    target = m[3].to_i
         | 
| 52 | 
            +
                    times = !times.empty? ? times.to_i : 1
         | 
| 53 | 
            +
                    sides = !sides.empty? ? sides.to_i : 100
         | 
| 54 | 
            +
                    return roll_d(command, times, sides, target)
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  def roll_ab(command)
         | 
| 58 | 
            +
                    m = /^(\d*)AB(\d*)<=(\d+)(?:--([^\d\s]+)(0)?)?$/.match(command)
         | 
| 59 | 
            +
                    return nil unless m
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    times = m[1]
         | 
| 62 | 
            +
                    sides = m[2]
         | 
| 63 | 
            +
                    target = m[3].to_i
         | 
| 64 | 
            +
                    type = m[4]
         | 
| 65 | 
            +
                    suffix = m[5]
         | 
| 66 | 
            +
                    times = !times.empty? ? times.to_i : 1
         | 
| 67 | 
            +
                    sides = !sides.empty? ? sides.to_i : 100
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    if suffix || type.nil?
         | 
| 70 | 
            +
                      roll_b(command, times, sides, target)
         | 
| 71 | 
            +
                    else
         | 
| 72 | 
            +
                      roll_b_withtype(command, times, sides, target, type)
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  def roll_d(command, times, sides, target)
         | 
| 77 | 
            +
                    dice_list = @randomizer.roll_barabara(times, sides).sort
         | 
| 78 | 
            +
                    total = dice_list.sum
         | 
| 79 | 
            +
                    success = total <= target
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    crierror =
         | 
| 82 | 
            +
                      if total <= 10
         | 
| 83 | 
            +
                        "Critical"
         | 
| 84 | 
            +
                      elsif total >= 91
         | 
| 85 | 
            +
                        "Error"
         | 
| 86 | 
            +
                      else
         | 
| 87 | 
            +
                        "Neutral"
         | 
| 88 | 
            +
                      end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                    result =
         | 
| 91 | 
            +
                      if success && (crierror == "Critical")
         | 
| 92 | 
            +
                        "クリティカル!"
         | 
| 93 | 
            +
                      elsif success && (crierror == "Neutral")
         | 
| 94 | 
            +
                        "成功"
         | 
| 95 | 
            +
                      elsif success && (crierror == "Error")
         | 
| 96 | 
            +
                        "成功"
         | 
| 97 | 
            +
                      elsif !success && (crierror == "Critical")
         | 
| 98 | 
            +
                        "失敗"
         | 
| 99 | 
            +
                      elsif !success && (crierror == "Neutral")
         | 
| 100 | 
            +
                        "失敗"
         | 
| 101 | 
            +
                      elsif !success && (crierror == "Error")
         | 
| 102 | 
            +
                        "エラー"
         | 
| 103 | 
            +
                      end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                    if times == 1
         | 
| 106 | 
            +
                      return "(#{command}) > #{dice_list.join(',')} > #{result}"
         | 
| 107 | 
            +
                    else
         | 
| 108 | 
            +
                      return "(#{command}) > #{total}[#{dice_list.join(',')}] > #{result}"
         | 
| 109 | 
            +
                    end
         | 
| 110 | 
            +
                  end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                  def roll_b(command, times, sides, target)
         | 
| 113 | 
            +
                    dice_list, success_count, critical_count, error_count = process_b(times, sides, target)
         | 
| 114 | 
            +
                    result_count = success_count + critical_count - error_count
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    return "(#{command}) > [#{dice_list.join(',')}] > #{success_count}+#{critical_count}C-#{error_count}E > 成功数#{result_count}"
         | 
| 117 | 
            +
                  end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                  def roll_b_withtype(command, times, sides, target, type)
         | 
| 120 | 
            +
                    dice_list, success_count, critical_count, error_count = process_b(times, sides, target)
         | 
| 121 | 
            +
                    result_count = success_count + critical_count - error_count
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                    type_effect =
         | 
| 124 | 
            +
                      if (type == "SNIPER") && (result_count > 0)
         | 
| 125 | 
            +
                        1
         | 
| 126 | 
            +
                      else
         | 
| 127 | 
            +
                        0
         | 
| 128 | 
            +
                      end
         | 
| 129 | 
            +
                    result_count += type_effect
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    return "(#{command}) > [#{dice_list.join(',')}] > #{success_count}+#{critical_count}C-#{error_count}E+#{type_effect}(#{type}) > 成功数#{result_count}"
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  def process_b(times, sides, target)
         | 
| 135 | 
            +
                    dice_list = @randomizer.roll_barabara(times, sides).sort
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                    success_count = 0
         | 
| 138 | 
            +
                    critical_count = 0
         | 
| 139 | 
            +
                    error_count = 0
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                    dice_list.each do |value|
         | 
| 142 | 
            +
                      success_count += 1 if value <= target
         | 
| 143 | 
            +
                      critical_count += 1 if value <= 10
         | 
| 144 | 
            +
                      error_count += 1 if value >= 91
         | 
| 145 | 
            +
                    end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                    return [dice_list, success_count, critical_count, error_count]
         | 
| 148 | 
            +
                  end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                  ADDICTION_TABLE = [
         | 
| 151 | 
            +
                    "中枢神経障害",
         | 
| 152 | 
            +
                    "多臓器不全",
         | 
| 153 | 
            +
                    "急性ストレス反応",
         | 
| 154 | 
            +
                  ].freeze
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                  def roll_addiction(command)
         | 
| 157 | 
            +
                    return nil if command != "--ADDICTION"
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                    value = @randomizer.roll_once(3)
         | 
| 160 | 
            +
                    chosen = ADDICTION_TABLE[value - 1]
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                    return "--ADDICTION > #{chosen}"
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                  WORSENING_TABLE = [
         | 
| 166 | 
            +
                    "末梢神経障害",
         | 
| 167 | 
            +
                    "内臓機能不全",
         | 
| 168 | 
            +
                    "精神症状",
         | 
| 169 | 
            +
                  ].freeze
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                  def roll_worsening(command)
         | 
| 172 | 
            +
                    return nil if command != "--WORSENING"
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                    value = @randomizer.roll_once(3)
         | 
| 175 | 
            +
                    chosen = WORSENING_TABLE[value - 1]
         | 
| 176 | 
            +
                    elapse = @randomizer.roll_once(6) + 1
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                    return "--WORSENING > #{chosen}: #{elapse} rounds"
         | 
| 179 | 
            +
                  end
         | 
| 180 | 
            +
                end
         | 
| 181 | 
            +
              end
         | 
| 182 | 
            +
            end
         | 
| @@ -85,7 +85,7 @@ module BCDice | |
| 85 85 | 
             
                      totalDamage = totalSuccessCount * damage + totalCriticalCount * criticalTrigger
         | 
| 86 86 |  | 
| 87 87 | 
             
                      result += "(#{diceCount}D10\<\=#{target}) > #{text} > Hits:#{totalSuccessCount}*#{damage}"
         | 
| 88 | 
            -
                      result += " + Trigger:#{totalCriticalCount}*#{criticalTrigger}" if | 
| 88 | 
            +
                      result += " + Trigger:#{totalCriticalCount}*#{criticalTrigger}" if criticalTrigger > 0
         | 
| 89 89 | 
             
                      result += " > #{totalDamage}ダメージ"
         | 
| 90 90 | 
             
                    else
         | 
| 91 91 | 
             
                      result += "(#{diceCount}D10\<\=#{target}) > #{text} > 成功数:#{totalSuccessCount}"
         | 
| @@ -58,7 +58,7 @@ module BCDice | |
| 58 58 | 
             
                    fumble = 1
         | 
| 59 59 |  | 
| 60 60 | 
             
                    isStormy = (m[2] == 'GL') # 波乱万丈
         | 
| 61 | 
            -
                    if | 
| 61 | 
            +
                    if isStormy
         | 
| 62 62 | 
             
                      critical -= 3
         | 
| 63 63 | 
             
                      fumble += 1
         | 
| 64 64 | 
             
                    end
         | 
| @@ -69,7 +69,7 @@ module BCDice | |
| 69 69 | 
             
                    critical, fumble = get_critival_fumble(critical, fumble, m[8], m[9])
         | 
| 70 70 |  | 
| 71 71 | 
             
                    target = get_value(m[11])
         | 
| 72 | 
            -
                    optionalText =  | 
| 72 | 
            +
                    optionalText = m[13] || ''
         | 
| 73 73 |  | 
| 74 74 | 
             
                    return checkRoll(diceCount, modify, critical, fumble, target, isStormy, optionalText)
         | 
| 75 75 | 
             
                  end
         | 
| @@ -116,7 +116,7 @@ module BCDice | |
| 116 116 |  | 
| 117 117 | 
             
                      if isCritical
         | 
| 118 118 | 
             
                        result += "成功(クリティカル)"
         | 
| 119 | 
            -
                      elsif | 
| 119 | 
            +
                      elsif total >= target
         | 
| 120 120 | 
             
                        result += "成功"
         | 
| 121 121 | 
             
                      else
         | 
| 122 122 | 
             
                        result += "失敗"
         | 
| @@ -16,7 +16,7 @@ module BCDice | |
| 16 16 | 
             
                  HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
         | 
| 17 17 | 
             
                    ・1D100で判定時に成否、Botchを判定
         | 
| 18 18 | 
             
                     例)1D100<=50
         | 
| 19 | 
            -
             | 
| 19 | 
            +
                       (1D100<=50) > 55 > Botch
         | 
| 20 20 | 
             
                  INFO_MESSAGE_TEXT
         | 
| 21 21 |  | 
| 22 22 | 
             
                  def result_1d100(total, dice_total, cmp_op, target)
         | 
| @@ -30,21 +30,21 @@ module BCDice | |
| 30 30 | 
             
                    if tens == ones
         | 
| 31 31 | 
             
                      if (total > target) || (dice_total == 100) # 00は必ず失敗
         | 
| 32 32 | 
             
                        if target > 100 # 目標値が100を超えている場合は、00を振ってもBotchにならない
         | 
| 33 | 
            -
                          return Result.failure(" | 
| 33 | 
            +
                          return Result.failure("Failure")
         | 
| 34 34 | 
             
                        else
         | 
| 35 35 | 
             
                          return Result.fumble("Botch")
         | 
| 36 36 | 
             
                        end
         | 
| 37 37 | 
             
                      else
         | 
| 38 | 
            -
                        return Result.critical(" | 
| 38 | 
            +
                        return Result.critical("Colossal Success")
         | 
| 39 39 | 
             
                      end
         | 
| 40 40 | 
             
                    elsif (total <= target) || (dice_total == 1) # 01は必ず成功
         | 
| 41 41 | 
             
                      if total <= (target / 2)
         | 
| 42 | 
            -
                        return Result.success(" | 
| 42 | 
            +
                        return Result.success("High Success")
         | 
| 43 43 | 
             
                      else
         | 
| 44 | 
            -
                        return Result.success(" | 
| 44 | 
            +
                        return Result.success("Low Success")
         | 
| 45 45 | 
             
                      end
         | 
| 46 46 | 
             
                    else
         | 
| 47 | 
            -
                      return Result.failure(" | 
| 47 | 
            +
                      return Result.failure("Failure")
         | 
| 48 48 | 
             
                    end
         | 
| 49 49 | 
             
                  end
         | 
| 50 50 | 
             
                end
         | 
| @@ -0,0 +1,92 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module BCDice
         | 
| 4 | 
            +
              module GameSystem
         | 
| 5 | 
            +
                class FullFace < Base
         | 
| 6 | 
            +
                  # ゲームシステムの識別子
         | 
| 7 | 
            +
                  ID = 'FullFace'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  # ゲームシステム名
         | 
| 10 | 
            +
                  NAME = 'フルフェイス'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # ゲームシステム名の読みがな
         | 
| 13 | 
            +
                  SORT_KEY = 'ふるふえいす'
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  # ダイスボットの使い方
         | 
| 16 | 
            +
                  HELP_MESSAGE = <<~INFO_MESSAGETEXT
         | 
| 17 | 
            +
                    ■判定 x+bFF<=t   x:ヒート(省略時は3) b:判定修正 t:能力値
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    例)FF<=2:   能力値2で判定し、その結果(成功数,1の目の数,バースト)を表示。
         | 
| 20 | 
            +
                       6FF<=3:  ヒート6,能力値3で戦闘判定し、その結果( 〃 )を表示。
         | 
| 21 | 
            +
                       8+2FF<=3:ヒート8,判定修正+2,能力値3で戦闘判定し、その結果( 〃 )を表示。
         | 
| 22 | 
            +
                  INFO_MESSAGETEXT
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  register_prefix('([+\d]+)*FF')
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def eval_game_system_specific_command(command)
         | 
| 27 | 
            +
                    resolute_action(command)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  private
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  # 技能判定
         | 
| 33 | 
            +
                  # @param [String] command
         | 
| 34 | 
            +
                  # @return [Result]
         | 
| 35 | 
            +
                  def resolute_action(command)
         | 
| 36 | 
            +
                    m = /^(\d*)([+\d]+)*FF<=(\d)$/.match(command)
         | 
| 37 | 
            +
                    return nil unless m
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    heat_level = m[1].to_i
         | 
| 40 | 
            +
                    heat_level = 3 if heat_level == 0
         | 
| 41 | 
            +
                    modify = Arithmetic.eval("0#{m[2]}", @round_type)
         | 
| 42 | 
            +
                    status_no = m[3].to_i
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                    dice_array = []
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    dice = @randomizer.roll_barabara(heat_level, 6)
         | 
| 47 | 
            +
                    ones = dice.count(1)
         | 
| 48 | 
            +
                    sixs = dice.count(6)
         | 
| 49 | 
            +
                    success_num = dice.count { |val| val <= status_no }
         | 
| 50 | 
            +
                    dice_array.push(dice.join(","))
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                    if modify > 0
         | 
| 53 | 
            +
                      dice = @randomizer.roll_barabara(modify, 6)
         | 
| 54 | 
            +
                      ones += dice.count(1)
         | 
| 55 | 
            +
                      success_num += dice.count { |val| val <= status_no }
         | 
| 56 | 
            +
                      dice_array.push(dice.join(","))
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                    ones_total = ones
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    while ones > 0
         | 
| 61 | 
            +
                      dice = @randomizer.roll_barabara(ones, 6)
         | 
| 62 | 
            +
                      ones = dice.count(1)
         | 
| 63 | 
            +
                      ones_total += ones
         | 
| 64 | 
            +
                      success_num += dice.count { |val| val <= status_no }
         | 
| 65 | 
            +
                      dice_array.push(dice.join(","))
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    return Result.new.tap do |result|
         | 
| 69 | 
            +
                      if sixs >= 2
         | 
| 70 | 
            +
                        result.fumble = true
         | 
| 71 | 
            +
                        result.condition = false
         | 
| 72 | 
            +
                      else
         | 
| 73 | 
            +
                        result.condition = (success_num > 0)
         | 
| 74 | 
            +
                        result.critical = (ones_total > 0)
         | 
| 75 | 
            +
                      end
         | 
| 76 | 
            +
                      result_txt = []
         | 
| 77 | 
            +
                      result_txt.push("成功度(#{success_num})")
         | 
| 78 | 
            +
                      result_txt.push("1の目(#{ones_total})") if ones_total > 0
         | 
| 79 | 
            +
                      result_txt.push("バースト") if result.fumble?
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                      sequence = [
         | 
| 82 | 
            +
                        "(#{heat_level}#{Format.modifier(modify)}FF<=#{status_no})",
         | 
| 83 | 
            +
                        dice_array.join('+').to_s,
         | 
| 84 | 
            +
                        result_txt.join(',').to_s,
         | 
| 85 | 
            +
                      ].compact
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                      result.text = sequence.join(" > ")
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
            end
         | 
| @@ -13,7 +13,10 @@ module BCDice | |
| 13 13 | 
             
                  SORT_KEY = 'むけんのふあんたしあ'
         | 
| 14 14 |  | 
| 15 15 | 
             
                  # ダイスボットの使い方
         | 
| 16 | 
            -
                  HELP_MESSAGE =  | 
| 16 | 
            +
                  HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
         | 
| 17 | 
            +
                    1D20に目標値を設定した場合に、成功レベルの自動判定を行います。
         | 
| 18 | 
            +
                    例: 1D20<=16
         | 
| 19 | 
            +
                  INFO_MESSAGE_TEXT
         | 
| 17 20 |  | 
| 18 21 | 
             
                  # ゲーム別成功度判定(1d20)
         | 
| 19 22 | 
             
                  def result_1d20(total, _dice_total, cmp_op, target)
         | 
| @@ -37,7 +37,7 @@ module BCDice | |
| 37 37 | 
             
                    SceneSituation, SSi
         | 
| 38 38 | 
             
                  HELP
         | 
| 39 39 |  | 
| 40 | 
            -
                  ATTACK_ROLL_REG = %r{^AT(TACK|K)?([+\-*/()\d]+)@([+\-*/()\d]+)<=([+\-*/()\d]+)(\[([ | 
| 40 | 
            +
                  ATTACK_ROLL_REG = %r{^AT(TACK|K)?([+\-*/()\d]+)@([+\-*/()\d]+)<=([+\-*/()\d]+)(\[([+-])([+\-*/()\d]+)\])?}i.freeze
         | 
| 41 41 | 
             
                  register_prefix('AT(TACK|K)?')
         | 
| 42 42 |  | 
| 43 43 | 
             
                  def initialize(command)
         | 
| @@ -0,0 +1,158 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module BCDice
         | 
| 4 | 
            +
              module GameSystem
         | 
| 5 | 
            +
                class KyokoShinshoku < Base
         | 
| 6 | 
            +
                  # ゲームシステムの識別子
         | 
| 7 | 
            +
                  ID = "KyokoShinshoku"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  # ゲームシステム名
         | 
| 10 | 
            +
                  NAME = "虚構侵蝕TRPG"
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # ゲームシステム名の読みがな
         | 
| 13 | 
            +
                  SORT_KEY = "きよこうしんしよくTRPG"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  # ダイスボットの使い方
         | 
| 16 | 
            +
                  HELP_MESSAGE = <<~MESSAGETEXT
         | 
| 17 | 
            +
                    ・判定
         | 
| 18 | 
            +
                     ダイスを指定数ダイスロールして、最も高い出目を出力します。難易度を指定すると成否を判定します。
         | 
| 19 | 
            +
                    KS(x,y)
         | 
| 20 | 
            +
                    x:ダイスサイズ。1=D4(能力値1、2以上の出目が出ていたとしても最大1)/2=D4(能力値2、3以上の出目が出ていたとしても最大2)/3=D4(能力値3、出目4が出ていたとしても最大3)/4=D4/6=D6/8=D8/10=D10/12=D12/20=D20
         | 
| 21 | 
            +
                    y:ダイス数(省略:1)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    KS(x,y)>=z
         | 
| 24 | 
            +
                    x:ダイスサイズ。1=D4(能力値1、2以上の出目が出ていたとしても最大1)/2=D4(能力値2、3以上の出目が出ていたとしても最大2)/3=D4(能力値3、出目4が出ていたとしても最大3)/4=D4/6=D6/8=D8/10=D10/12=D12/20=D20
         | 
| 25 | 
            +
                    y:ダイス数(省略:1)
         | 
| 26 | 
            +
                    z:難易度
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    ・観測ロール
         | 
| 29 | 
            +
                     [現実乖離]の段階に応じたダイスを指定数ダイスロールして、最も高い出目を出力します。
         | 
| 30 | 
            +
                    KR(x)
         | 
| 31 | 
            +
                    x=[現実乖離]の段階(1=D4/2=D6/3=D8/4=D10/5=D12/6=D20)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    KR(x,y) 観測ロール(リアリティラインあり)
         | 
| 34 | 
            +
                    x=[現実乖離]の段階(1=D4/2=D6/3=D8/4=D10/5=D12/6=D20)
         | 
| 35 | 
            +
                    y=[リアリティライン]のレベル(3=1個/2=2個/1=3個)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    ・虚構の収束の侵蝕度減少ロール
         | 
| 38 | 
            +
                     [現実乖離]の段階に応じたダイスを指定数ダイスロールして、その合計を出力します。
         | 
| 39 | 
            +
                    KRS(x,y)
         | 
| 40 | 
            +
                    x=[現実乖離]の段階(1=D4/2=D6/3=D8/4=D10/5=D12/6=D20)
         | 
| 41 | 
            +
                    y=ダイスの個数
         | 
| 42 | 
            +
                  MESSAGETEXT
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  register_prefix('KS', 'KR', 'KRS')
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  def eval_game_system_specific_command(command)
         | 
| 47 | 
            +
                    roll_check(command) || roll_kansoku(command) || roll_shusoku(command)
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  private
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  DICE_SIZE_TO_SIDES = {
         | 
| 53 | 
            +
                    1 => 4,
         | 
| 54 | 
            +
                    2 => 4,
         | 
| 55 | 
            +
                    3 => 4,
         | 
| 56 | 
            +
                    4 => 4,
         | 
| 57 | 
            +
                    6 => 6,
         | 
| 58 | 
            +
                    8 => 8,
         | 
| 59 | 
            +
                    10 => 10,
         | 
| 60 | 
            +
                    12 => 12,
         | 
| 61 | 
            +
                    20 => 20,
         | 
| 62 | 
            +
                  }.freeze
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  def roll_check(command)
         | 
| 65 | 
            +
                    m = /^KS(?:\((\d+),([-+\d]+)?\)|(\d+))(?:>=([-+\d]+))?$/.match(command)
         | 
| 66 | 
            +
                    return nil unless m
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    dice_size = m[1]&.to_i || m[3].to_i
         | 
| 69 | 
            +
                    times = m[2] ? Arithmetic.eval(m[2], @round_type) : 1
         | 
| 70 | 
            +
                    target = m[4] && Arithmetic.eval(m[4], @round_type)
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    sides = DICE_SIZE_TO_SIDES[dice_size]
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    return nil if sides.nil? || times.nil?
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                    dice_list = @randomizer.roll_barabara(times, sides).sort
         | 
| 77 | 
            +
                    value = dice_list.max.clamp(1, dice_size)
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    result =
         | 
| 80 | 
            +
                      if value == 1
         | 
| 81 | 
            +
                        Result.fumble("ファンブル")
         | 
| 82 | 
            +
                      elsif target && value < target
         | 
| 83 | 
            +
                        Result.failure("失敗")
         | 
| 84 | 
            +
                      elsif target && value == sides
         | 
| 85 | 
            +
                        Result.critical("クリティカル")
         | 
| 86 | 
            +
                      elsif target && value >= target
         | 
| 87 | 
            +
                        Result.success("成功")
         | 
| 88 | 
            +
                      else
         | 
| 89 | 
            +
                        Result.new()
         | 
| 90 | 
            +
                      end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                    result.text = [
         | 
| 93 | 
            +
                      target ? "(KS(#{dice_size},#{times})>=#{target})" : "(KS(#{dice_size},#{times}))",
         | 
| 94 | 
            +
                      ("#{value}[#{dice_list.join(',')}]" if times > 1),
         | 
| 95 | 
            +
                      value,
         | 
| 96 | 
            +
                      result.text,
         | 
| 97 | 
            +
                    ].compact.join(" > ")
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                    return result
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  GENJITU_KAIRI_TO_SIDES = [4, 6, 8, 10, 12, 20].freeze
         | 
| 103 | 
            +
                  REALITY_LINE_TO_TIMES = {
         | 
| 104 | 
            +
                    3 => 1,
         | 
| 105 | 
            +
                    2 => 2,
         | 
| 106 | 
            +
                    1 => 3,
         | 
| 107 | 
            +
                  }.freeze
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  def roll_kansoku(command)
         | 
| 110 | 
            +
                    m = /^KR(?:(\d+)|\((\d),(\d)\))$/.match(command)
         | 
| 111 | 
            +
                    return nil unless m
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                    dice_size = m[1]&.to_i || m[2].to_i
         | 
| 114 | 
            +
                    reality_line = m[3]&.to_i
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    if reality_line && (reality_line > 3 || reality_line < 1)
         | 
| 117 | 
            +
                      return nil
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                    sides = GENJITU_KAIRI_TO_SIDES[dice_size - 1]
         | 
| 121 | 
            +
                    times = REALITY_LINE_TO_TIMES[reality_line] || 1
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                    return nil unless sides
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                    dice_list = @randomizer.roll_barabara(times, sides).sort
         | 
| 126 | 
            +
                    value = dice_list.max
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    cmd = reality_line ? "KR(#{dice_size},#{reality_line})" : "KR(#{dice_size})"
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                    if times == 1
         | 
| 131 | 
            +
                      "(#{cmd}) > #{value}"
         | 
| 132 | 
            +
                    else
         | 
| 133 | 
            +
                      "(#{cmd}) > #{value}[#{dice_list.join(',')}] > #{value}"
         | 
| 134 | 
            +
                    end
         | 
| 135 | 
            +
                  end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                  def roll_shusoku(command)
         | 
| 138 | 
            +
                    m = /^KRS(?:\((\d),([-+\d]+)\))$/.match(command)
         | 
| 139 | 
            +
                    return nil unless m
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                    dice_size = m[1].to_i
         | 
| 142 | 
            +
                    times = m[2] && Arithmetic.eval(m[2], @round_type)
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                    sides = GENJITU_KAIRI_TO_SIDES[dice_size - 1]
         | 
| 145 | 
            +
                    return nil if sides.nil? || times.nil?
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                    dice_list = @randomizer.roll_barabara(times, sides)
         | 
| 148 | 
            +
                    value = dice_list.sum
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                    if times == 1
         | 
| 151 | 
            +
                      "(KRS(#{dice_size},#{times})) > #{value}"
         | 
| 152 | 
            +
                    else
         | 
| 153 | 
            +
                      "(KRS(#{dice_size},#{times})) > #{value}[#{dice_list.join(',')}] > #{value}"
         | 
| 154 | 
            +
                    end
         | 
| 155 | 
            +
                  end
         | 
| 156 | 
            +
                end
         | 
| 157 | 
            +
              end
         | 
| 158 | 
            +
            end
         |