summaryrefslogtreecommitdiff
path: root/data/rbot/plugins/dice.rb
blob: 7e0662b1d0f42a3dd5f96660fa51d6eec543f4ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#-- vim:sw=2:et
#++
#
# :title: dice plugin for rbot
#
# Author:: David Dorward (http://david.us-lot.org/ - you might find a more up to date version of this plugin there)
# Author:: Moritz Augsburger <moritz@augsburger.name>
#
# Description:: Rolls rpg style dice
# Version:: 0.4
# Date:: Mon 8 Feb 2008
#
# Changelog
# 0.1 - Initial release
# 0.1.1 - bug fix, only 1 digit for number of dice sides on first roll
# 0.3.0 - Spelling correction on changelog 0.1.1
#       - Return results of each roll
# 0.3.1 - Minor documentation update
# 0.3.2 - Bug fix, could not subtract numbers (String can't be coerced into Fixnum)
# 0.4 - Limit number of dices and number of sides per dice
#
# TODO:: Test! Test! Test!
#        Comment!
#        Fumble/Critical counter (1's and x's where x is sides on dice)

class DiceDisplay
  attr_reader :total, :view, :dice
  def initialize(dice, view, total)
    @total = total
    @dice = dice
    @view = view
  end

  def get_view()
    return "["+ dice.to_s + ": " + total.to_s + " | " + view + "] "
  end
end

class DicePlugin < Plugin
  Config.register Config::IntegerValue.new('dice.max_dices',
      :default => 100, :validate => Proc.new{|v| v > 0},
      :desc => "Maximum number of dices to throw.")

  Config.register Config::IntegerValue.new('dice.max_sides',
      :default => 100, :validate => Proc.new{|v| v > 0},
      :desc => "Maximum number of sides per dice.")

  def help(plugin, topic="")
    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"
  end

  def rolldice(d)
    dice = d.split(/d/)
    repr = []
    r = 0
    unless dice[0] =~ /^\d+/
      dice[0] = 1
    end
    for i in 0...dice[0].to_i
      tmp = rand(dice[1].to_i) + 1
      repr << tmp.to_s
      r = r + tmp
    end
    return DiceDisplay.new(d, repr.join(", "), r)
  end

  def iddice(d)
    dice = d
    porm = d.slice!(0,1)
    if d =~ /d/
      rolled = rolldice(d)
      d = rolled.view
      r = rolled.total
    else
      r = d
    end

    if porm == "-"
      r = 0 - r.to_i
    end

    viewer = DiceDisplay.new(porm + dice, d.to_s, r)
    return viewer
  end

  def privmsg(m)
    # If either not given parameters or given incorrect parameters, return with
    # the help message
    unless m.params && m.params =~ /^\d*d\d+(\s*[+-]\s*(\d+|\d*d\d)+)*$/
      m.reply "incorrect usage: " + help(m.plugin)
      return
    end

    # Extract the actual dice request from the message parameters, splitting it
    # into dice and modifiers
    a = m.params.gsub(/\s+/,'').scan(/^\d*d\d+|[+-]\d*d\d+|[+-]\d+/)
    # check nr of total dices and sides per dice
    nr = 0
    a.each { |dice|
      dc, ds = dice.split(/d/)
      # check sides
      if ds.to_i > @bot.config['dice.max_sides']
       m.reply "sorry, don't have any dices with more than %u sides" % @bot.config['dice.max_sides'], :nick => true
       return
      end
      # We use .max with 1 so that specs such as d6 count as 1 and not as 0
      nr += [dc.to_i, 1].max
    }
    if nr > @bot.config['dice.max_dices']
      m.reply "can't handle more than %u dices" % @bot.config['dice.max_dices'], :nick => true
      return
    end

    # Roll the dice with the extracted request
    rolled = rolldice(a[0])
    r = rolled.total
    t = rolled.get_view()

    # Deal with all the remaining parts of the given dice request
    for i in 1...a.length
      tmp = iddice(a[i])
      r = r + tmp.total.to_i
      t = t + tmp.get_view
    end
    t.chop!
    m.reply(r.to_s + " || " + m.params + ": " + t, :nick => true)
  end
end
plugin = DicePlugin.new
plugin.register("dice")
plugin.register("roll")
##############################################
#fin