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