class Roulette
Constants
- BET_TYPES
- COLUMN_NUMBERS
- LEADERBOARD_TITLE
- RED_NUMBERS
- TITLE
- WHEEL_ORDER
Public Class Methods
Source
# File plugins/roulette.rb, line 103 def self.bet_error { error: usage_message } end
Source
# File plugins/roulette.rb, line 111 def self.bet_wins?(bet_type, bet_value, number) case bet_type when :red then red?(number) when :black then !number.zero? && !red?(number) when :odd then number.positive? && number.odd? when :even then number.positive? && number.even? when :low then number.between?(1, 18) when :high then number.between?(19, 36) when :dozen1 then number.between?(1, 12) when :dozen2 then number.between?(13, 24) when :dozen3 then number.between?(25, 36) when :column1 then COLUMN_NUMBERS[:column1].include?(number) when :column2 then COLUMN_NUMBERS[:column2].include?(number) when :column3 then COLUMN_NUMBERS[:column3].include?(number) when :straight then number == bet_value else false end end
Source
# File plugins/roulette.rb, line 138 def self.calculate_winnings(amount, bet_type, won:) return 0 unless won amount * payout_multiplier(bet_type) end
Source
# File plugins/roulette.rb, line 151 def self.colored_number(number) style = case number_color(number) when :red then STYLE_RED when :black then STYLE_BLACK else STYLE_GREEN end "#{style}#{number.to_s.rjust(2)}#{IRC_RESET}" end
Source
# File plugins/roulette.rb, line 15 def self.command_pattern /roulette(?: (.+))?$/i end
Source
# File plugins/roulette.rb, line 178 def self.format_balance(user, balance) super(user, balance, title: TITLE) end
Calls superclass method
Game::format_balance
Source
# File plugins/roulette.rb, line 144 def self.format_bet_label(bet_type, bet_value) case bet_type when :straight then "straight #{bet_value}" else bet_type.to_s end end
Source
# File plugins/roulette.rb, line 182 def self.format_leaderboard(store) super(store, title: LEADERBOARD_TITLE, empty_message: "No bets placed yet — spin the wheel!") end
Calls superclass method
Game::format_leaderboard
Source
# File plugins/roulette.rb, line 186 def self.format_result(user:, bet_type:, bet_value:, amount:, number:, won:, balance:) outcome_style = won ? STYLE_WIN : STYLE_LOSE outcome_text = won ? "WIN!" : "LOSE" bet_label = format_bet_label(bet_type, bet_value) color_name = number_color(number).to_s.upcase lines = [ format_wheel_art(number), "#{STYLE_TITLE}══════ ROULETTE ══════#{IRC_RESET}", "#{STYLE_LABEL}Player:#{IRC_RESET} #{STYLE_NICK}#{user}#{IRC_RESET}", "#{STYLE_LABEL}Bet:#{IRC_RESET} #{STYLE_VALUE}#{bet_label}#{IRC_RESET} " \ "#{STYLE_LABEL}for#{IRC_RESET} #{STYLE_VALUE}#{amount}#{IRC_RESET}", "#{STYLE_LABEL}Ball landed on#{IRC_RESET} #{colored_number(number)} " \ "#{STYLE_LABEL}(#{color_name})#{IRC_RESET}", "#{outcome_style}>>> #{outcome_text} <<<#{IRC_RESET}", "#{STYLE_LABEL}Balance:#{IRC_RESET} #{STYLE_VALUE}#{balance}#{IRC_RESET} #{STYLE_LABEL}credits#{IRC_RESET}" ] lines.join("\n") end
Source
# File plugins/roulette.rb, line 167 def self.format_wheel_art(number) left, centre, right = wheel_neighbours(number) [ "#{STYLE_WHEEL} .─────────.#{IRC_RESET}", "#{STYLE_WHEEL} /#{IRC_RESET} #{colored_number(left)} #{STYLE_WHEEL}│#{IRC_RESET} #{colored_number(centre)} #{STYLE_WHEEL}│#{IRC_RESET} #{colored_number(right)} #{STYLE_WHEEL}\\#{IRC_RESET}", "#{STYLE_WHEEL} │ ◉ │#{IRC_RESET}", "#{STYLE_WHEEL} \\ #{STYLE_LABEL}SPIN#{IRC_RESET}#{STYLE_WHEEL} /#{IRC_RESET}", "#{STYLE_WHEEL} '─────────'#{IRC_RESET}" ].join("\n") end
Source
# File plugins/roulette.rb, line 50 def self.number_color(number) return :green if number.zero? red?(number) ? :red : :black end
Source
# File plugins/roulette.rb, line 70 def self.parse_bet(parts) if parts[0] =~ /\A\d+\z/ return bet_error unless parts.length >= 2 bet_value = parts[0].to_i amount = parts[1].to_i return bet_error unless valid_straight_number?(bet_value) return bet_error unless valid_amount?(amount) return { action: :bet, bet_type: :straight, bet_value: bet_value, amount: amount } end if parts[0].casecmp("straight").zero? return bet_error unless parts.length >= 3 bet_value = parts[1].to_i amount = parts[2].to_i return bet_error unless valid_straight_number?(bet_value) return bet_error unless valid_amount?(amount) return { action: :bet, bet_type: :straight, bet_value: bet_value, amount: amount } end return bet_error unless parts.length >= 2 bet_type = parts[0].downcase.to_sym amount = parts[1].to_i return bet_error unless BET_TYPES.include?(bet_type) return bet_error unless valid_amount?(amount) { action: :bet, bet_type: bet_type, amount: amount } end
Source
# File plugins/roulette.rb, line 60 def self.parse_command(text) parts = text.to_s.strip.split(/\s+/) return { action: :help } if parts.empty? meta = parse_meta_command(parts) return meta if meta parse_bet(parts) end
Source
# File plugins/roulette.rb, line 130 def self.payout_multiplier(bet_type) case bet_type when :straight then 35 when :dozen1, :dozen2, :dozen3, :column1, :column2, :column3 then 2 else 1 end end
Source
# File plugins/roulette.rb, line 206 def self.place_bet(user, bet_type:, amount:, bet_value: nil, store: default_store, rand: ->(max) { Random.rand(0..max) }) balance = balance_for(user, store: store) if amount > balance return { error: "#{user}, not enough credits (balance: #{balance})." } end deduct_bet(user, amount, store: store) number = spin_number(rand: rand) won = bet_wins?(bet_type, bet_value, number) winnings = calculate_winnings(amount, bet_type, won: won) credit_winnings(user, amount + winnings, store: store) if won new_balance = balance_for(user, store: store) { won: won, number: number, balance: new_balance, message: format_result( user: user, bet_type: bet_type, bet_value: bet_value, amount: amount, number: number, won: won, balance: new_balance ) } end
Source
# File plugins/roulette.rb, line 46 def self.red?(number) RED_NUMBERS.include?(number) end
Source
# File plugins/roulette.rb, line 235 def self.roulette(args_text, user:, store: default_store, rand: ->(max) { Random.rand(0..max) }) parsed = parse_command(args_text.to_s) return parsed[:error] if parsed[:error] return usage_message if parsed[:action] == :help case parsed[:action] when :balance format_balance(user, balance_for(user, store: store)) when :leaderboard format_leaderboard(store) when :bet result = place_bet( user, bet_type: parsed[:bet_type], bet_value: parsed[:bet_value], amount: parsed[:amount], store: store, rand: rand ) return result[:error] if result[:error] result[:message] else usage_message end end
Source
# File plugins/roulette.rb, line 56 def self.spin_number(rand: ->(max) { Random.rand(0..max) }) rand.call(36) end
Source
# File plugins/roulette.rb, line 40 def self.usage_message "Usage: !roulette <bet> <amount> — e.g. !roulette red 50, !roulette 17 100, " \ "!roulette straight 7 25 | Bets: red, black, odd, even, low, high, " \ "dozen1-3, column1-3, straight (0-36) | !roulette balance | !roulette leaderboard" end
Source
# File plugins/roulette.rb, line 107 def self.valid_straight_number?(number) number.between?(0, 36) end
Source
# File plugins/roulette.rb, line 160 def self.wheel_neighbours(number) index = WHEEL_ORDER.index(number) || 0 left = WHEEL_ORDER[(index - 1) % WHEEL_ORDER.length] right = WHEEL_ORDER[(index + 1) % WHEEL_ORDER.length] [left, number, right] end
Public Instance Methods
Source
# File plugins/roulette.rb, line 266 def execute(m, args_text = nil) themed_flood_safe_reply(m, roulette(args_text, user: m.user.nick)) end
Source
# File plugins/roulette.rb, line 262 def roulette(args_text = nil, **options) self.class.roulette(args_text, **options) end