]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/games/roulette.rb
Module\#define_structure method: define a new Struct only if doesn't exist already...
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / games / roulette.rb
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