Class: Polyhedral::Die

Inherits:
Object
  • Object
show all
Defined in:
lib/polyhedral/die.rb

Constant Summary collapse

DEFAULT_SIDES =
6
DEFAULT_TIMES =
1

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sides = DEFAULT_SIDES, name = nil, material = nil, color = nil, seed = nil) ⇒ Die

initialize Die instance

Raises:

  • (ArgumentError)


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
# File 'lib/polyhedral/die.rb', line 15

def initialize(sides=DEFAULT_SIDES, name=nil, material=nil, color=nil,
  seed=nil
)
  raise ArgumentError, 'nil sides' if sides.nil?
  raise ArgumentError, 'invalid sides class' if !sides.is_a?(Integer)
  if !name.nil?
    raise ArgumentError, 'nil name' if name.nil?
    raise ArgumentError, 'invalid name' if name.class != String
    raise ArgumentError, 'empty name' if name.empty?
  end
  if !material.nil?
    raise ArgumentError, 'nil material' if material.nil?
    raise ArgumentError, 'invalid material' if material.class != String
    raise ArgumentError, 'empty material' if material.empty?
  end
  if !color.nil?
    raise ArgumentError, 'nil color' if color.nil?
    raise ArgumentError, 'invalid color' if color.class != String
    raise ArgumentError, 'empty color' if color.empty?
  end
  if !seed.nil?
    raise ArgumentError, 'invalid seed class' if !seed.is_a?(Integer)
  end

  @sides = sides
  @seed = seed

  if !@seed.nil?
    srand(@seed)
  else
    srand
  end

  @count = 0
  @frequency = Array.new(@sides, 0)

  @name = name
  @material = material
  @color = color

  nil
end

Instance Attribute Details

#colorObject (readonly)

Returns the value of attribute color.



8
9
10
# File 'lib/polyhedral/die.rb', line 8

def color
  @color
end

#materialObject (readonly)

Returns the value of attribute material.



8
9
10
# File 'lib/polyhedral/die.rb', line 8

def material
  @material
end

#nameObject

Returns the value of attribute name.



9
10
11
# File 'lib/polyhedral/die.rb', line 9

def name
  @name
end

#sidesObject (readonly)

Returns the value of attribute sides.



8
9
10
# File 'lib/polyhedral/die.rb', line 8

def sides
  @sides
end

Class Method Details

.from_file(pathname) ⇒ Object

load Die instance from disk

Raises:

  • (ArgumentError)


269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/polyhedral/die.rb', line 269

def Die.from_file(pathname)
  # validate arguments
  raise ArgumentError, 'nil pathname' if pathname.nil?
  raise ArgumentError, 'invalid pathname class' if pathname.class != String
  raise ArgumentError, 'empty pathname' if pathname.empty?

  begin
    f = File.open(pathname, 'r')
    object = Marshal.load(f)
  rescue Exception => e
    return nil
  ensure
    f.close unless f.nil?
  end

  return object
end

Instance Method Details

#dump(stream = STDOUT, indent = 0) ⇒ Object

dump instance state to specified output stream

Raises:

  • (ArgumentError)


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
# File 'lib/polyhedral/die.rb', line 59

def dump(stream=STDOUT, indent=0)
  raise ArgumentError, 'nil stream' if stream.nil?
  raise ArgumentError, 'invalid stream class' if stream.class != IO
  raise ArgumentError, 'nil indent' if indent.nil?
  raise ArgumentError, 'invalid indent class' if !indent.is_a?(Integer)
  raise ArgumentError, 'indent range error' if indent < 0

  # instance
  indent.times { stream << ' ' }
  stream << "#{self.class}<id=#{self.object_id}>:\n"

  indent += 2

  # sides
  indent.times { stream << ' ' }
  stream << "sides: #{@sides}\n"

  # seed
  indent.times { stream << ' ' }
  stream << "seed: #{@seed ? @seed : 'nil'}\n"

  # count
  indent.times { stream << ' ' }
  stream << "count: #{@count}\n"

  # frequency
  indent.times { stream << ' ' }
  stream << "frequency<id=#{@frequency.object_id}>:\n"
  (indent-1).times { stream << ' ' }
  @frequency.each { |f| stream << " #{f}" }
  stream << "\n"

  # name
  indent.times { stream << ' ' }
  stream << "name: #{@name ? @name : 'nil'}\n"

  # material
  indent.times { stream << ' ' }
  stream << "material: #{@material ? @material : 'nil'}\n"

  # color
  indent.times { stream << ' ' }
  stream << "color: #{@color ? @color : 'nil'}\n"

  nil
end

#frequency(stream = STDOUT) ⇒ Object

dump frequency graph to specified output stream

Raises:

  • (ArgumentError)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/polyhedral/die.rb', line 161

def frequency(stream=STDOUT)
  raise ArgumentError, 'nil stream' if stream.nil?
  raise ArgumentError, 'invalid stream class' if stream.class != IO

  num = max_frequency
  min = min_frequency
  min -= 1 if min > 0

  stream << "Throws  Frequency Graph"
  stream << " for #{@name}" if !@name.nil? && !@name.empty?
  stream << "\n\n"

  while num > min do
    printf(stream, "%6d", num)

    @frequency.each do |f|
      if f >= num
        stream << '  *'
      else
        stream << '   '
      end
    end

    stream << "\n"
    num -= 1
  end

  stream << "\n      "
  @frequency.length.times do |f|
    n = f+1
    if n.to_s.length >= 2
      stream << ' '
    else
      stream << '  '
    end
    stream << n
  end
  stream << "\n"

  nil
end

#highestObject

return array of historically highest scoring side(s)



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/polyhedral/die.rb', line 227

def highest
  max_f = 0
  high_side = 0

  @sides.times do |s|
    if @frequency[s] > max_f
      max_f = @frequency[s]
      high_side = s
    end
  end

  high_set = Array.new
  high_set << high_side+1

  @sides.times do |s|
    next if s == high_side
    high_set << s+1 if @frequency[s] == @frequency[high_side]
  end

  high_set
end

#inspectObject

return description of the Die instance



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/polyhedral/die.rb', line 141

def inspect
  desc = []

  desc << "#{@name} is " if !@name.nil? && !@name.empty?
  desc << 'a'
  desc << " #{@color}" if !@color.nil? && !@color.empty?
  desc << " #{@material}" if !@material.nil? && !@material.empty?
  desc << " #{self}"

  desc << " (#{@count} throw"
  if @count != 1
    desc << 's)'
  else
    desc << ')'
  end

  desc.join
end

#lowestObject

return array of historically lowest scoring side(s)



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/polyhedral/die.rb', line 204

def lowest
  min_f = 1000000
  low_side = @sides-1

  @sides.times do |s|
    if @frequency[s] < min_f
      min_f = @frequency[s]
      low_side = s
    end
  end

  low_set = Array.new
  low_set << low_side+1

  @sides.times do |s|
    next if s == low_side
    low_set << s+1 if @frequency[s] == @frequency[low_side]
  end

  low_set
end

#throw(quantity = DEFAULT_TIMES, modifier = 0) ⇒ Object

throw die n times (applying modifier as appropriate)

Raises:

  • (ArgumentError)


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/polyhedral/die.rb', line 107

def throw(quantity=DEFAULT_TIMES, modifier=0)
  raise ArgumentError, 'nil quantity' if quantity.nil?
  raise ArgumentError, 'invalid quantity class' if !quantity.is_a?(Integer)
  raise ArgumentError, 'invalid quantity value' if quantity < 1
  raise ArgumentError, 'nil modifier' if modifier.nil?
  raise ArgumentError, 'invalid modifier class' if !modifier.is_a?(Integer)

  score = 0

  # update throw count
  @count += quantity

  quantity.times do
    result = rand(@sides) + 1
    score += result

    # update frequency count
    @frequency[result-1] += 1
  end

  score+modifier
end

#to_file(pathname) ⇒ Object

store Die instance to disk

Raises:

  • (ArgumentError)


250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/polyhedral/die.rb', line 250

def to_file(pathname)
  # validate arguments
  raise ArgumentError, 'nil pathname' if pathname.nil?
  raise ArgumentError, 'invalid pathname class' if pathname.class != String
  raise ArgumentError, 'empty pathname' if pathname.empty?

  begin
    f = File.open(pathname, 'w')
    Marshal.dump(self, f)
  rescue Exception => e
    return false
  ensure
    f.close
  end

  return true
end

#to_iObject

emit Die instance as Integer



131
132
133
# File 'lib/polyhedral/die.rb', line 131

def to_i
  @sides
end

#to_sObject

emit Die instance as String



136
137
138
# File 'lib/polyhedral/die.rb', line 136

def to_s
  "d#{sides}"
end