Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A script for transitioning characters to retirement, yet not allowing them off of the hook.
require 'logger'
ABILITY_SCORE_MODIFIER = {
0 => :dead,
1 => -3, 2 => -3, 3 => -3,
4 => -2, 5 => -2,
6 => -1, 7 => -1, 8 => -1,
9 => 0, 10 => 0, 11 => 0, 12 => 0,
13 => 1, 14 => 1, 15 => 1,
16 => 2, 17 => 2,
18 => 3,
}.freeze
class Character
attr_accessor :luck, :trauma, :complication_score, :complication_die, :desperate, :state
attr_reader :starting_luck, :starting_trauma, :tests, :starting_complication_die, :desperation_checks
alias desperate? desperate
def initialize(luck:, trauma:, complication_die:)
@luck = luck
@starting_luck = luck
@trauma = trauma
@starting_trauma = trauma
@complication_score = 0
@complication_die = complication_die
@starting_complication_die = complication_die
@desperation_checks = 0
@desperate = false
@state = nil
@tests = 0
end
def increment_test_count
@tests += 1
if @desperate
@desperation_checks += 1
end
end
def luck_modifier
ABILITY_SCORE_MODIFIER.fetch(luck)
end
def continue?
@state.nil?
end
def dies!
@state = :dead
end
def reduce_complication_die
return true if @complication_die == 0
dice_chain_index = DICE_CHAIN.index(@complication_die)
if dice_chain_index == 0
@complication_die = 0
return true
else
@complication_die = DICE_CHAIN[dice_chain_index - 1]
end
end
def increase_complication_score
result = roll_d(complication_die)
return if result < 3
@complication_score += result
end
def becomes_desperate!
@desperate = true
end
def becomes_uneventful!
@state = :uneventful
end
def burn_luck(value)
@luck += value
return true if @luck > 0
@state = :dead
end
end
def round(value)
(value * 10000).round / 100.0
end
def logger
@logger ||= Logger.new(STDOUT)
end
def roll_d(i)
rand(i) + 1
end
module ComplicationProcedure
def self.call(character:)
if character.trauma < 1
character.reduce_complication_die
if character.complication_die < MINIMUM_COMPLICATING_DICE
return character.becomes_uneventful!
end
end
if LUCK_BASED
delta = roll_d(20) + character.luck_modifier - character.complication_score
return character if delta > 0
else
return character if roll_d(character.complication_die) < 3
end
if character.desperate?
character.dies!
else
character.becomes_desperate!
end
end
end
module RetiredProcedure
def self.call(character:)
if character.trauma == 0
return true
elsif roll_d(20) > character.luck
character.increase_complication_score
else
character.trauma -= 1
end
end
end
DICE_CHAIN = [3,4,5,6,7,8,10,12,14,16,20,24,30].freeze
LUCK_BASED = true
puts "Staring Complication Die | Uneventful (Average Checks) | Dead (Average Checks) | Checks While Desperate "
puts "-|-|-|-"
[3].each do |i|
MINIMUM_COMPLICATING_DICE = i
DICE_CHAIN.each do |complication_die|
tests_til_safe = 0
tests_til_dead = 0
desperation_checks = 0
dead = 0
uneventful = 0
STDOUT.tap do |file|
(1..10000).each do
(1..20).each do |trauma_score|
next unless roll_d(20) > trauma_score # Make sure the character is considering retiring
luck_score = roll_d(6) + roll_d(6) + roll_d(6)
character = Character.new(luck: luck_score, trauma: trauma_score, complication_die: complication_die)
while character.continue?
character.increment_test_count
RetiredProcedure.call(character: character)
ComplicationProcedure.call(character: character)
end
if character.state == :dead
desperation_checks += character.desperation_checks
dead += 1
tests_til_dead += character.tests
else
uneventful += 1
tests_til_safe += character.tests
end
end
end
end
line = []
line << "d#{complication_die}"
line << "#{round(uneventful / (dead+uneventful).to_f)}% (#{(tests_til_safe / uneventful.to_f * 100).round / 100.0})"
line << "#{round(dead / (dead+uneventful).to_f)}% (#{(tests_til_dead / dead.to_f * 100).round / 100.0})"
line << "#{((desperation_checks / dead.to_f) * 100).round / 100.0}"
puts line.join(" | ")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.