| 1 | define_structure :RouletteHistory, :games, :shots, :deaths, :misses, :wins |
|---|
| 2 | |
|---|
| 3 | class RoulettePlugin < Plugin |
|---|
| 4 | BotConfig.register BotConfigBooleanValue.new('roulette.autospin', |
|---|
| 5 | :default => true, |
|---|
| 6 | :desc => "Automatically spins the roulette at the butlast shot") |
|---|
| 7 | BotConfig.register BotConfigBooleanValue.new('roulette.kick', |
|---|
| 8 | :default => false, |
|---|
| 9 | :desc => "Kicks shot players from the channel") |
|---|
| 10 | BotConfig.register BotConfigBooleanValue.new('roulette.twice_in_a_row', |
|---|
| 11 | :default => false, |
|---|
| 12 | :desc => "Allow players to go twice in a row") |
|---|
| 13 | |
|---|
| 14 | def initialize |
|---|
| 15 | super |
|---|
| 16 | reset_chambers |
|---|
| 17 | @players = Array.new |
|---|
| 18 | end |
|---|
| 19 | |
|---|
| 20 | def help(plugin, topic="") |
|---|
| 21 | "roulette => play russian roulette - starts a new game if one isn't already running. One round in a six chambered gun. Take turns to say roulette to the bot, until somebody dies. roulette reload => force the gun to reload, roulette stats => show stats from all games, roulette stats <player> => show stats for <player>, roulette clearstats => clear stats (config level auth required), roulette spin => spins the cylinder" |
|---|
| 22 | end |
|---|
| 23 | |
|---|
| 24 | def clearstats(m, params) |
|---|
| 25 | @registry.clear |
|---|
| 26 | m.okay |
|---|
| 27 | end |
|---|
| 28 | |
|---|
| 29 | def roulette(m, params) |
|---|
| 30 | if m.private? |
|---|
| 31 | m.reply "you gotta play roulette in channel dude" |
|---|
| 32 | return |
|---|
| 33 | end |
|---|
| 34 | |
|---|
| 35 | playerdata = nil |
|---|
| 36 | if @registry.has_key?("player " + m.sourcenick) |
|---|
| 37 | playerdata = @registry["player " + m.sourcenick] |
|---|
| 38 | else |
|---|
| 39 | playerdata = RouletteHistory.new(0,0,0,0,0) |
|---|
| 40 | end |
|---|
| 41 | |
|---|
| 42 | totals = nil |
|---|
| 43 | if @registry.has_key?("totals") |
|---|
| 44 | totals = @registry["totals"] |
|---|
| 45 | else |
|---|
| 46 | totals = RouletteHistory.new(0,0,0,0,0) |
|---|
| 47 | end |
|---|
| 48 | |
|---|
| 49 | if @players.last == m.sourcenick and not @bot.config['roulette.twice_in_a_row'] |
|---|
| 50 | m.reply "you can't go twice in a row!" |
|---|
| 51 | return |
|---|
| 52 | end |
|---|
| 53 | |
|---|
| 54 | unless @players.include?(m.sourcenick) |
|---|
| 55 | @players << m.sourcenick |
|---|
| 56 | playerdata.games += 1 |
|---|
| 57 | end |
|---|
| 58 | playerdata.shots += 1 |
|---|
| 59 | totals.shots += 1 |
|---|
| 60 | |
|---|
| 61 | shot = @chambers.pop |
|---|
| 62 | if shot |
|---|
| 63 | m.reply "#{m.sourcenick}: chamber #{6 - @chambers.length} of 6 => *BANG*" |
|---|
| 64 | playerdata.deaths += 1 |
|---|
| 65 | totals.deaths += 1 |
|---|
| 66 | @players.each {|plyr| |
|---|
| 67 | next if plyr == m.sourcenick |
|---|
| 68 | pdata = @registry["player " + plyr] |
|---|
| 69 | next if pdata == nil |
|---|
| 70 | pdata.wins += 1 |
|---|
| 71 | totals.wins += 1 |
|---|
| 72 | @registry["player " + plyr] = pdata |
|---|
| 73 | } |
|---|
| 74 | @players = Array.new |
|---|
| 75 | @bot.kick(m.replyto, m.sourcenick, "*BANG*") if @bot.config['roulette.kick'] |
|---|
| 76 | else |
|---|
| 77 | m.reply "#{m.sourcenick}: chamber #{6 - @chambers.length} of 6 => +click+" |
|---|
| 78 | playerdata.misses += 1 |
|---|
| 79 | totals.misses += 1 |
|---|
| 80 | end |
|---|
| 81 | |
|---|
| 82 | @registry["player " + m.sourcenick] = playerdata |
|---|
| 83 | @registry["totals"] = totals |
|---|
| 84 | |
|---|
| 85 | if shot || @chambers.empty? |
|---|
| 86 | reload(m) |
|---|
| 87 | elsif @chambers.length == 1 and @bot.config['roulette.autospin'] |
|---|
| 88 | spin(m) |
|---|
| 89 | end |
|---|
| 90 | end |
|---|
| 91 | |
|---|
| 92 | def reload(m, params = {}) |
|---|
| 93 | if m.private? |
|---|
| 94 | m.reply "you gotta play roulette in channel dude" |
|---|
| 95 | return |
|---|
| 96 | end |
|---|
| 97 | |
|---|
| 98 | m.act "reloads" |
|---|
| 99 | reset_chambers |
|---|
| 100 | # all players win on a reload |
|---|
| 101 | # (allows you to play 3-shot matches etc) |
|---|
| 102 | totals = nil |
|---|
| 103 | if @registry.has_key?("totals") |
|---|
| 104 | totals = @registry["totals"] |
|---|
| 105 | else |
|---|
| 106 | totals = RouletteHistory.new(0,0,0,0,0) |
|---|
| 107 | end |
|---|
| 108 | |
|---|
| 109 | @players.each {|plyr| |
|---|
| 110 | pdata = @registry["player " + plyr] |
|---|
| 111 | next if pdata == nil |
|---|
| 112 | pdata.wins += 1 |
|---|
| 113 | totals.wins += 1 |
|---|
| 114 | @registry["player " + plyr] = pdata |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | totals.games += 1 |
|---|
| 118 | @registry["totals"] = totals |
|---|
| 119 | |
|---|
| 120 | @players = Array.new |
|---|
| 121 | end |
|---|
| 122 | |
|---|
| 123 | def spin(m, params={}) |
|---|
| 124 | # Spinning is just like resetting, except that nobody wins |
|---|
| 125 | if m.private? |
|---|
| 126 | m.reply "you gotta play roulette in channel dude" |
|---|
| 127 | return |
|---|
| 128 | end |
|---|
| 129 | |
|---|
| 130 | m.act "spins the cylinder" |
|---|
| 131 | reset_chambers |
|---|
| 132 | end |
|---|
| 133 | |
|---|
| 134 | def reset_chambers |
|---|
| 135 | @chambers = [false, false, false, false, false, false] |
|---|
| 136 | @chambers[rand(@chambers.length)] = true |
|---|
| 137 | end |
|---|
| 138 | |
|---|
| 139 | def playerstats(m, params) |
|---|
| 140 | player = params[:player] |
|---|
| 141 | pstats = @registry["player " + player] |
|---|
| 142 | if pstats.nil? |
|---|
| 143 | m.reply "#{player} hasn't played enough games yet" |
|---|
| 144 | else |
|---|
| 145 | m.reply "#{player} has played #{pstats.games} games, won #{pstats.wins} and lost #{pstats.deaths}. #{player} pulled the trigger #{pstats.shots} times and found the chamber empty on #{pstats.misses} occasions." |
|---|
| 146 | end |
|---|
| 147 | end |
|---|
| 148 | |
|---|
| 149 | def stats(m, params) |
|---|
| 150 | if @registry.has_key?("totals") |
|---|
| 151 | totals = @registry["totals"] |
|---|
| 152 | total_games = totals.games |
|---|
| 153 | total_shots = totals.shots |
|---|
| 154 | else |
|---|
| 155 | total_games = 0 |
|---|
| 156 | total_shots = 0 |
|---|
| 157 | end |
|---|
| 158 | |
|---|
| 159 | total_players = 0 |
|---|
| 160 | |
|---|
| 161 | died_most = [nil,0] |
|---|
| 162 | won_most = [nil,0] |
|---|
| 163 | h_win_percent = [nil,0] |
|---|
| 164 | l_win_percent = [nil,0] |
|---|
| 165 | h_luck_percent = [nil,0] |
|---|
| 166 | l_luck_percent = [nil,0] |
|---|
| 167 | @registry.each {|k,v| |
|---|
| 168 | match = /player (.+)/.match(k) |
|---|
| 169 | next unless match |
|---|
| 170 | k = match[1] |
|---|
| 171 | |
|---|
| 172 | total_players += 1 |
|---|
| 173 | |
|---|
| 174 | win_rate = v.wins.to_f / v.games * 100 |
|---|
| 175 | if h_win_percent[0].nil? || win_rate > h_win_percent[1] && v.games > 2 |
|---|
| 176 | h_win_percent = [[k], win_rate] |
|---|
| 177 | elsif win_rate == h_win_percent[1] && v.games > 2 |
|---|
| 178 | h_win_percent[0] << k |
|---|
| 179 | end |
|---|
| 180 | if l_win_percent[0].nil? || win_rate < l_win_percent[1] && v.games > 2 |
|---|
| 181 | l_win_percent = [[k], win_rate] |
|---|
| 182 | elsif win_rate == l_win_percent[1] && v.games > 2 |
|---|
| 183 | l_win_percent[0] << k |
|---|
| 184 | end |
|---|
| 185 | |
|---|
| 186 | luck = v.misses.to_f / v.shots * 100 |
|---|
| 187 | if h_luck_percent[0].nil? || luck > h_luck_percent[1] && v.games > 2 |
|---|
| 188 | h_luck_percent = [[k], luck] |
|---|
| 189 | elsif luck == h_luck_percent[1] && v.games > 2 |
|---|
| 190 | h_luck_percent[0] << k |
|---|
| 191 | end |
|---|
| 192 | if l_luck_percent[0].nil? || luck < l_luck_percent[1] && v.games > 2 |
|---|
| 193 | l_luck_percent = [[k], luck] |
|---|
| 194 | elsif luck == l_luck_percent[1] && v.games > 2 |
|---|
| 195 | l_luck_percent[0] << k |
|---|
| 196 | end |
|---|
| 197 | |
|---|
| 198 | if died_most[0].nil? || v.deaths > died_most[1] |
|---|
| 199 | died_most = [[k], v.deaths] |
|---|
| 200 | elsif v.deaths == died_most[1] |
|---|
| 201 | died_most[0] << k |
|---|
| 202 | end |
|---|
| 203 | if won_most[0].nil? || v.wins > won_most[1] |
|---|
| 204 | won_most = [[k], v.wins] |
|---|
| 205 | elsif v.wins == won_most[1] |
|---|
| 206 | won_most[0] << k |
|---|
| 207 | end |
|---|
| 208 | } |
|---|
| 209 | if total_games < 1 |
|---|
| 210 | m.reply "roulette stats: no games completed yet" |
|---|
| 211 | else |
|---|
| 212 | m.reply "roulette stats: #{total_games} games completed, #{total_shots} shots fired at #{total_players} players. Luckiest: #{h_luck_percent[0].join(',')} (#{sprintf '%.1f', h_luck_percent[1]}% clicks). Unluckiest: #{l_luck_percent[0].join(',')} (#{sprintf '%.1f', l_luck_percent[1]}% clicks). Highest survival rate: #{h_win_percent[0].join(',')} (#{sprintf '%.1f', h_win_percent[1]}%). Lowest survival rate: #{l_win_percent[0].join(',')} (#{sprintf '%.1f', l_win_percent[1]}%). Most wins: #{won_most[0].join(',')} (#{won_most[1]}). Most deaths: #{died_most[0].join(',')} (#{died_most[1]})." |
|---|
| 213 | end |
|---|
| 214 | end |
|---|
| 215 | end |
|---|
| 216 | |
|---|
| 217 | plugin = RoulettePlugin.new |
|---|
| 218 | |
|---|
| 219 | plugin.default_auth('clearstats', false) |
|---|
| 220 | |
|---|
| 221 | plugin.map 'roulette reload', :action => 'reload' |
|---|
| 222 | plugin.map 'roulette spin', :action => 'spin' |
|---|
| 223 | plugin.map 'roulette stats :player', :action => 'playerstats' |
|---|
| 224 | plugin.map 'roulette stats', :action => 'stats' |
|---|
| 225 | plugin.map 'roulette clearstats', :action => 'clearstats' |
|---|
| 226 | plugin.map 'roulette' |
|---|
| 227 | |
|---|