Class: Dicey::AbstractDie

Inherits:
Object
  • Object
show all
Defined in:
lib/dicey/abstract_die.rb

Overview

Asbtract die which may have an arbitrary list of sides, not even neccessarily numbers but strings or other objects.

As the base class for all dice, defines their API.

Dice can be created through several methods:

Rolling a die is done through #roll. #current returns the current side of the die.

AbstractDie.srand can be used to (re)set the internal randomizer's state for all dice, allowing to reproduce the same sequence of rolls (if it was done with a known state).

Direct Known Subclasses

NumericDie, StaticDie

Constant Summary collapse

@@random =

Shared randomness source, accessed through rand and srand.

Random.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sides_list) ⇒ AbstractDie

Returns a new instance of AbstractDie.

Parameters:

  • sides_list (Enumerable<Any>)

Raises:



91
92
93
94
95
96
97
98
99
# File 'lib/dicey/abstract_die.rb', line 91

def initialize(sides_list)
  @sides_list = sides_list.to_a
  @sides_list = @sides_list.dup if @sides_list.equal?(sides_list) && !@sides_list.frozen?
  raise DiceyError, "dice must have at least one side!" if @sides_list.empty?

  @sides_list.freeze
  @sides_num = @sides_list.size
  @current_side_index = 0
end

Instance Attribute Details

#sides_listArray<Any> (readonly)

Die's list of sides.

Returns:

  • (Array<Any>)


82
83
84
# File 'lib/dicey/abstract_die.rb', line 82

def sides_list
  @sides_list
end

#sides_numInteger (readonly)

Number of sides of the die.

Returns:

  • (Integer)


87
88
89
# File 'lib/dicey/abstract_die.rb', line 87

def sides_num
  @sides_num
end

Class Method Details

.describe(dice) ⇒ String

Get a text representation of a list of dice.

Parameters:

Returns:

  • (String)


49
50
51
52
53
54
55
56
57
58
# File 'lib/dicey/abstract_die.rb', line 49

def self.describe(dice)
  return dice.to_s if AbstractDie === dice

  dice.map(&:to_s).reduce do |string, die|
    die_string = die.to_s
    string << "+" unless die_string.match?(/\A[+-]/)
    string << die_string
    string
  end
end

.from_count(count, definition) ⇒ Array<AbstractDie>

Create a number of equal dice from one definition.

Parameters:

  • count (Integer)

    number of dice to create

  • definition (Enumerable<Any>, Any)

    definition suitable for the dice class

Returns:



75
76
77
# File 'lib/dicey/abstract_die.rb', line 75

def self.from_count(count, definition)
  Array.new(count) { new(definition) }
end

.from_list(*definitions) ⇒ Array<AbstractDie>

Create a bunch of different dice at once from a list of definitions.

Parameters:

  • definitions (Array<Enumerable<Any>>, Array<Any>)

    list of definitions suitable for the dice class

Returns:



65
66
67
# File 'lib/dicey/abstract_die.rb', line 65

def self.from_list(*definitions)
  definitions.map { new(_1) }
end

.randObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get a random value using a private instance of Random.

Do not use this method directly. Reproducible rolls depend on it being called only internally.

See Also:

  • Random#rand


30
31
32
# File 'lib/dicey/abstract_die.rb', line 30

def self.rand(...)
  @@random.rand(...)
end

.srandObject

Reset internal randomizer using a new seed.

See Also:

  • Random.new


36
37
38
# File 'lib/dicey/abstract_die.rb', line 36

def self.srand(...)
  @@random = Random.new(...)
end

Instance Method Details

#==(other) ⇒ Boolean

Determine if this die and the other one have the same list of sides. Be aware that differently ordered sides are not considered equal.

Parameters:

Returns:

  • (Boolean)

See Also:



142
143
144
# File 'lib/dicey/abstract_die.rb', line 142

def ==(other)
  AbstractDie === other && same_sides?(other)
end

#currentAny

Get current side of the die.

Returns:

  • (Any)

    current side



104
105
106
# File 'lib/dicey/abstract_die.rb', line 104

def current
  @sides_list[@current_side_index]
end

#eql?(other) ⇒ Boolean

Determine if this die and the other one are of the same class and have the same list of sides. Be aware that differently ordered sides are not considered equal.

die_1.eql?(die_2) implies die_1.hash == die_2.hash.

Parameters:

Returns:

  • (Boolean)

See Also:



156
157
158
# File 'lib/dicey/abstract_die.rb', line 156

def eql?(other)
  self.class === other && same_sides?(other)
end

#hashInteger

Generates an Integer hash value for this object.

Returns:

  • (Integer)


163
164
165
# File 'lib/dicey/abstract_die.rb', line 163

def hash
  [self.class, @sides_list].hash
end

#nextAny

Get next side of the die, advancing internal state. Starts from first side, wraps from last to first side.

Returns:

  • (Any)

    next side



112
113
114
115
116
# File 'lib/dicey/abstract_die.rb', line 112

def next
  ret = current
  @current_side_index = (@current_side_index + 1) % @sides_num
  ret
end

#numeric?Boolean

Whether all sides of this die are Numeric.

Returns:

  • (Boolean)


170
171
172
173
174
# File 'lib/dicey/abstract_die.rb', line 170

def numeric?
  return @numeric if defined?(@numeric)

  @numeric = @sides_list.all?(Numeric)
end

#rollAny

Move internal state to a random side.

Returns:

  • (Any)

    rolled side



121
122
123
124
# File 'lib/dicey/abstract_die.rb', line 121

def roll
  @current_side_index = self.class.rand(@sides_num)
  current
end

#to_sString

Return a string representing the die.

Default representation is a list of sides in round brackets.

Returns:

  • (String)


131
132
133
# File 'lib/dicey/abstract_die.rb', line 131

def to_s
  (@sides_list.size > 1) ? "(#{@sides_list.join(",")})" : "(#{@sides_list.first},)"
end