]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - data/rbot/plugins/games/roulette.rb
plugin(points): new message parser, see #34
[user/henk/code/ruby/rbot.git] / data / rbot / plugins / games / roulette.rb
1 define_structure :RouletteHistory, :games, :shots, :deaths, :misses, :wins, :points
2
3 class RoulettePlugin < Plugin
4   Config.register Config::BooleanValue.new('roulette.autospin',
5     :default => true,
6     :desc => "Automatically spins the roulette at the butlast shot")
7   Config.register Config::BooleanValue.new('roulette.kick',
8     :default => false,
9     :desc => "Kicks shot players from the channel")
10   Config.register Config::BooleanValue.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     @last = ''
19   end
20
21   def help(plugin, topic="")
22     "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"
23   end
24
25   def clearstats(m, params)
26     @registry.clear
27     m.okay
28   end
29
30   def roulette(m, params)
31     if m.private?
32       m.reply "you gotta play roulette in channel dude"
33       return
34     end
35
36     playerdata = nil
37     if @registry.has_key?("player " + m.sourcenick)
38       playerdata = @registry["player " + m.sourcenick]
39     else
40       playerdata = RouletteHistory.new(0,0,0,0,0,0)
41     end
42
43     totals = nil
44     if @registry.has_key?("totals")
45       totals = @registry["totals"]
46     else
47       totals = RouletteHistory.new(0,0,0,0,0,0)
48     end
49
50     if @last == m.sourcenick and not @bot.config['roulette.twice_in_a_row']
51       m.reply "you can't go twice in a row!"
52       return
53     end
54
55     @last = m.sourcenick
56     unless @players.include?(m.sourcenick)
57       @players << m.sourcenick
58       playerdata.games += 1
59     end
60     playerdata.shots += 1
61     totals.shots += 1
62
63     shot = @chambers.pop
64     chamberNo = 6 - @chambers.length
65     if shot
66       m.reply "#{m.sourcenick}: chamber #{chamberNo} of 6 => *BANG*"
67       playerdata.deaths += 1
68       totals.deaths += 1
69       @players.each {|plyr|
70         next if plyr == m.sourcenick
71         pdata = @registry["player " + plyr]
72         next if pdata == nil
73         pdata.wins += 1
74         totals.wins += 1
75         @registry["player " + plyr] = pdata
76       }
77       @players.clear
78       @last = ''
79       @bot.kick(m.replyto, m.sourcenick, "*BANG*") if @bot.config['roulette.kick']
80     else
81       m.reply "#{m.sourcenick}: chamber #{chamberNo} of 6 => +click+"
82       playerdata.misses += 1
83       playerdata.points += 2**chamberNo
84       totals.misses += 1
85     end
86
87     @registry["player " + m.sourcenick] = playerdata
88     @registry["totals"] = totals
89
90     if shot || @chambers.empty?
91       reload(m)
92     elsif @chambers.length == 1 and @bot.config['roulette.autospin']
93       spin(m)
94     end
95   end
96
97   def reload(m, params = {})
98     if m.private?
99       m.reply "you gotta play roulette in channel dude"
100       return
101     end
102
103     m.act "reloads"
104     reset_chambers
105     # all players win on a reload
106     # (allows you to play 3-shot matches etc)
107     totals = nil
108     if @registry.has_key?("totals")
109       totals = @registry["totals"]
110     else
111       totals = RouletteHistory.new(0,0,0,0,0,0)
112     end
113
114     @players.each {|plyr|
115       pdata = @registry["player " + plyr]
116       next if pdata == nil
117       pdata.wins += 1
118       totals.wins += 1
119       @registry["player " + plyr] = pdata
120     }
121
122     totals.games += 1
123     @registry["totals"] = totals
124
125     @players.clear
126     @last = ''
127   end
128
129   def spin(m, params={})
130     # Spinning is just like resetting, except that nobody wins
131     if m.private?
132       m.reply "you gotta play roulette in channel dude"
133       return
134     end
135
136     m.act "spins the cylinder"
137     reset_chambers
138   end
139
140   def reset_chambers
141     @chambers = [false, false, false, false, false, false]
142     @chambers[rand(@chambers.length)] = true
143   end
144
145   def playerstats(m, params)
146     player = params[:player]
147     pstats = @registry["player " + player]
148     if pstats.nil?
149       m.reply "#{player} hasn't played enough games yet"
150     else
151       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."
152     end
153   end
154
155   def stats(m, params)
156     if @registry.has_key?("totals")
157       totals = @registry["totals"]
158       total_games = totals.games
159       total_shots = totals.shots
160     else
161       total_games = 0
162       total_shots = 0
163     end
164
165     total_players = 0
166
167     died_most = [nil,0]
168     won_most = [nil,0]
169     h_win_percent = [nil,0]
170     l_win_percent = [nil,0]
171     h_luck_percent = [nil,0]
172     l_luck_percent = [nil,0]
173     @registry.each {|k,v|
174       match = /player (.+)/.match(k)
175       next unless match
176       k = match[1]
177
178       total_players += 1
179
180       win_rate = v.wins.to_f / v.games * 100
181       if h_win_percent[0].nil? || win_rate > h_win_percent[1] && v.games > 2
182         h_win_percent = [[k], win_rate]
183       elsif win_rate == h_win_percent[1] && v.games > 2
184         h_win_percent[0] << k
185       end
186       if l_win_percent[0].nil? || win_rate < l_win_percent[1] && v.games > 2
187         l_win_percent = [[k], win_rate]
188       elsif win_rate == l_win_percent[1] && v.games > 2
189         l_win_percent[0] << k
190       end
191
192       luck = v.misses.to_f / v.shots * 100
193       if h_luck_percent[0].nil? || luck > h_luck_percent[1] && v.games > 2
194         h_luck_percent = [[k], luck]
195       elsif luck == h_luck_percent[1] && v.games > 2
196         h_luck_percent[0] << k
197       end
198       if l_luck_percent[0].nil? || luck < l_luck_percent[1] && v.games > 2
199         l_luck_percent = [[k], luck]
200       elsif luck == l_luck_percent[1] && v.games > 2
201         l_luck_percent[0] << k
202       end
203
204       if died_most[0].nil? || v.deaths > died_most[1]
205         died_most = [[k], v.deaths]
206       elsif v.deaths == died_most[1]
207         died_most[0] << k
208       end
209       if won_most[0].nil? || v.wins > won_most[1]
210         won_most = [[k], v.wins]
211       elsif v.wins == won_most[1]
212         won_most[0] << k
213       end
214     }
215     if total_games < 1
216       m.reply "roulette stats: no games completed yet"
217     else
218       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]})."
219     end
220   end
221
222   # Figure out who the winnar is!
223   def hof(m, params)
224     fool = m.sourcenick
225     tmpKey = params[:key].to_s
226     targetKey = tmpKey.to_sym
227     m.reply("Checking out the #{tmpKey} HoF...")
228     tmp = @registry.to_hash
229     tmp.delete("totals")
230     sorted = tmp.sort { |a,b| b[1][targetKey] <=> a[1][targetKey] }
231
232     winnersLeft = 5
233
234     winners = []
235     sorted.each do |player|
236       playerName = player[0].split(" ")[1]
237       if player[0] == "totals" or playerName == ""
238         next
239       end
240       winners << "#{playerName} has #{player[1][targetKey]}"
241       winnersLeft -= 1
242       if winnersLeft == 0
243         break
244       end
245     end
246     m.reply(winners.join(" | "))
247   end
248 end
249
250 plugin = RoulettePlugin.new
251
252 plugin.default_auth('clearstats', false)
253
254 plugin.map 'roulette reload', :action => 'reload'
255 plugin.map 'roulette spin', :action => 'spin'
256 plugin.map 'roulette stats :player', :action => 'playerstats'
257 plugin.map 'roulette stats', :action => 'stats'
258 plugin.map 'roulette clearstats', :action => 'clearstats'
259 plugin.map 'roulette hof :key', :action => 'hof', :defaults => {:key => "points"}, :requirements => {:key => /^(?:games|shots|deaths|misses|wins|points)$/}
260 plugin.map 'roulette'
261