dice plugin: dice.max_dices option to prevent nice people from asking for 987654321d100
[rbot] / data / rbot / plugins / dice.rb
1 ##################
2 # Filename: dice.rb
3 # Description: Rbot plugin. Rolls rpg style dice
4 # Author: David Dorward (http://david.us-lot.org/ - you might find a more up to date version of this plugin there)
5 # Version: 0.3.2
6 # Date: Sat 6 Apr 2002
7 #
8 # You can get rbot from: http://www.linuxbrit.co.uk/rbot/
9 #
10 # Changelog
11 # 0.1 - Initial release
12 # 0.1.1 - bug fix, only 1 digit for number of dice sides on first roll
13 # 0.3.0 - Spelling correction on changelog 0.1.1
14 #       - Return results of each roll
15 # 0.3.1 - Minor documentation update
16 # 0.3.2 - Bug fix, could not subtract numbers (String can't be coerced into Fixnum)
17 #
18 # TODO: Test! Test! Test!
19 #       Comment!
20 #       Fumble/Critical counter (1's and x's where x is sides on dice)
21 ####################################################
22
23 class DiceDisplay
24   attr_reader :total, :view, :dice
25   def initialize(dice, view, total)
26     @total = total
27     @dice = dice
28     @view = view
29   end
30
31   def get_view()
32     return "["+ dice.to_s + ": " + total.to_s + " | " + view + "] "
33   end
34 end
35
36 class DicePlugin < Plugin
37   BotConfig.register BotConfigIntegerValue.new('dice.max_dices',
38       :default => 100, :validate => Proc.new{|v| v > 0},
39       :desc => "Maximum number of dices to throw.")
40
41   def help(plugin, topic="")
42     plugin + " <string> (where <string> is something like: d6 or 2d6 or 2d6+4 or 2d6+1d20 or 2d6+1d5+4d7-3d4-6) => Rolls that set of virtual dice"
43   end
44
45   def rolldice(d)
46     dice = d.split(/d/)
47     repr = []
48     r = 0
49     unless dice[0] =~ /^[0-9]+/
50       dice[0] = 1
51     end
52     for i in 0...dice[0].to_i
53       tmp = rand(dice[1].to_i) + 1
54       repr << tmp.to_s
55       r = r + tmp
56     end
57     return DiceDisplay.new(d, repr.join(", "), r)
58   end
59
60   def iddice(d)
61     dice = d
62     porm = d.slice!(0,1)
63     if d =~ /d/
64       rolled = rolldice(d)
65       d = rolled.view
66       r = rolled.total
67     else
68       r = d
69     end
70
71     if porm == "-"
72       r = 0 - r.to_i
73     end
74
75     viewer = DiceDisplay.new(porm + dice, d.to_s, r)
76     return viewer
77   end
78
79   def privmsg(m)
80     # If either not given parameters or given incorrect parameters, return with
81     # the help message
82     unless(m.params && m.params =~ /^[0-9]*d[0-9]+(\s*[+-]\s*([0-9]+|[0-9]*d[0-9])+)*$/)
83       m.nickreply "incorrect usage: " + help(m.plugin)
84       return
85     end
86
87     # Extract the actual dice request from the message parameters, splitting it
88     # into dice and modifiers
89     a = m.params.gsub(/\s+/,'').scan(/^[0-9]*d[0-9]+|[+-][0-9]*d[0-9]+|[+-][0-9]+/)
90     # check nr of total dices
91     nr = 0
92     a.each { |dice|
93       # We use .max with 1 so that specs such as d6 count as 1 and not as 0
94       nr += [dice.split(/d/)[0].to_i, 1].max
95     }
96     if nr > @bot.config['dice.max_dices']
97       m.reply "can't handle more than %u dices" % @bot.config['dice.max_dices']
98       return
99     end
100
101     # Roll the dice with the extracted request
102     rolled = rolldice(a[0])
103     r = rolled.total
104     t = rolled.get_view()
105
106     # Deal with all the remaining parts of the given dice request
107     for i in 1...a.length
108       tmp = iddice(a[i])
109       r = r + tmp.total.to_i
110       t = t + tmp.get_view
111     end
112     t.chop!
113     m.nickreply r.to_s + " || " + m.params + ": " + t
114   end
115 end
116 plugin = DicePlugin.new
117 plugin.register("dice")
118 plugin.register("roll")
119 ##############################################
120 #fin