tabletop 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/.gitignore +1 -0
  2. data/Rakefile +1 -1
  3. data/doc/Fixnum.html +313 -0
  4. data/doc/Tabletop/Coin.html +351 -0
  5. data/doc/Tabletop/Die.html +480 -0
  6. data/doc/Tabletop/FudgeDie.html +315 -0
  7. data/doc/Tabletop/NotEnoughTokensError.html +146 -0
  8. data/doc/Tabletop/Pool.html +770 -0
  9. data/doc/Tabletop/Possibility.html +235 -0
  10. data/doc/Tabletop/Roll.html +731 -0
  11. data/doc/Tabletop/TokenStack.html +394 -0
  12. data/doc/Tabletop.html +185 -0
  13. data/doc/created.rid +8 -0
  14. data/doc/images/brick.png +0 -0
  15. data/doc/images/brick_link.png +0 -0
  16. data/doc/images/bug.png +0 -0
  17. data/doc/images/bullet_black.png +0 -0
  18. data/doc/images/bullet_toggle_minus.png +0 -0
  19. data/doc/images/bullet_toggle_plus.png +0 -0
  20. data/doc/images/date.png +0 -0
  21. data/doc/images/find.png +0 -0
  22. data/doc/images/loadingAnimation.gif +0 -0
  23. data/doc/images/macFFBgHack.png +0 -0
  24. data/doc/images/package.png +0 -0
  25. data/doc/images/page_green.png +0 -0
  26. data/doc/images/page_white_text.png +0 -0
  27. data/doc/images/page_white_width.png +0 -0
  28. data/doc/images/plugin.png +0 -0
  29. data/doc/images/ruby.png +0 -0
  30. data/doc/images/tag_green.png +0 -0
  31. data/doc/images/wrench.png +0 -0
  32. data/doc/images/wrench_orange.png +0 -0
  33. data/doc/images/zoom.png +0 -0
  34. data/doc/index.html +167 -0
  35. data/doc/js/darkfish.js +116 -0
  36. data/doc/js/jquery.js +32 -0
  37. data/doc/js/quicksearch.js +114 -0
  38. data/doc/js/thickbox-compressed.js +10 -0
  39. data/doc/lib/fixnum_rb.html +54 -0
  40. data/doc/lib/tabletop/pool_rb.html +54 -0
  41. data/doc/lib/tabletop/randomizers_rb.html +52 -0
  42. data/doc/lib/tabletop/roll_rb.html +52 -0
  43. data/doc/lib/tabletop/token_rb.html +52 -0
  44. data/doc/lib/tabletop/version_rb.html +52 -0
  45. data/doc/lib/tabletop_rb.html +52 -0
  46. data/doc/rdoc.css +763 -0
  47. data/lib/fixnum.rb +8 -0
  48. data/lib/tabletop/pool.rb +32 -1
  49. data/lib/tabletop/randomizers.rb +22 -1
  50. data/lib/tabletop/roll.rb +65 -10
  51. data/lib/tabletop/token.rb +7 -4
  52. data/lib/tabletop/version.rb +1 -1
  53. data/spec/randomizers_spec.rb +6 -1
  54. data/spec/spec_helper.rb +1 -1
  55. data/tabletop.gemspec +1 -0
  56. metadata +60 -5
data/lib/fixnum.rb CHANGED
@@ -1,16 +1,22 @@
1
1
  require 'tabletop'
2
2
 
3
3
  class Fixnum
4
+
5
+ # Returns a pool of dice of the given sides and size self
4
6
  def dX(sides)
5
7
  dice = []
6
8
  times { dice << Tabletop::Die.new(sides) }
7
9
  Tabletop::Pool.new(dice)
8
10
  end
11
+
12
+ # Returns a pool of fudge dice of size self
9
13
  def dF
10
14
  dice = []
11
15
  times {dice << Tabletop::FudgeDie.new}
12
16
  Tabletop::Pool.new(dice)
13
17
  end
18
+
19
+ # Matches any methods of the form d(.*), and calls #dX($1.to_i)
14
20
  def method_missing(symbol, *args, &block)
15
21
  if symbol =~ /^d(.*)$/
16
22
  dX($1.to_i)
@@ -18,6 +24,8 @@ class Fixnum
18
24
  super
19
25
  end
20
26
  end
27
+
28
+ # Returns true for :dN, where N.to_i is a number > 0
21
29
  def respond_to?(symbol, include_private = false)
22
30
  if symbol.to_s =~ /^d(.*)$/
23
31
  true if $1.to_i > 0
data/lib/tabletop/pool.rb CHANGED
@@ -4,6 +4,10 @@ require 'delegate'
4
4
  module Tabletop
5
5
  class Pool < DelegateClass(Array)
6
6
  include Comparable
7
+
8
+ # requires one parameter, which can be either of
9
+ # - an array of Die objects
10
+ # - a string of d-notation
7
11
  def initialize(init_dice)
8
12
  return super(init_dice) if init_dice.instance_of?(Array)
9
13
  d_groups = init_dice.split
@@ -21,6 +25,10 @@ module Tabletop
21
25
  super(dice)
22
26
  end
23
27
 
28
+ # Behavior depends on the class of what is passed to it.
29
+ # Numeric:: returns the sum of the operand and the values of all dice in the receiving pool
30
+ # Pool:: returns a new pool with copies of all the dice in both operands
31
+ # AnythingElse:: raises an ArgumentError
24
32
  def +(operand)
25
33
  # if the operator is a pool, or an array only of Die objects...
26
34
  if operand.instance_of?(Pool) or (operand.instance_of?(Array) and !(operand.detect{|obj| !(obj.instance_of?(Die))}))
@@ -32,21 +40,26 @@ module Tabletop
32
40
  end
33
41
  end
34
42
 
43
+ # Compares the operand to #sum
35
44
  def <=>(operand)
36
45
  sum <=> operand.to_int
37
46
  end
38
47
 
48
+ # Returns #sum times the operand
39
49
  def *(operand)
40
50
  sum * operand
41
51
  end
42
52
 
43
- def coerce(other)
53
+ def coerce(other) #:nodoc:
44
54
  [other, sum]
45
55
  end
46
56
 
57
+ # Returns an array of the value of each die in the pool
47
58
  def values
48
59
  map {|die| die.value}
49
60
  end
61
+
62
+ # Returns a string of the pool's dice in d-notation
50
63
  def dice
51
64
  fudge = nil
52
65
  result = {}
@@ -68,18 +81,24 @@ module Tabletop
68
81
  end
69
82
  d_array
70
83
  end
84
+
85
+ # Rolls every die in the pool, and returns the Pool.
71
86
  def roll
72
87
  each do |die|
73
88
  die.roll
74
89
  end
75
90
  self
76
91
  end
92
+
93
+ # Returns the sum of all values of dice in the pool
77
94
  def sum
78
95
  inject(0) {|sum, d| sum + d.value}
79
96
  end
80
97
  def to_int
81
98
  sum
82
99
  end
100
+
101
+ # Returns a string describing all sets of die values in the pool in ORE notation.
83
102
  def sets
84
103
  result = {}
85
104
  each do |die|
@@ -87,18 +106,30 @@ module Tabletop
87
106
  end
88
107
  result.sort_by{|height, width| [width, height] }.collect {|i| i[1].to_s+"x"+i[0].to_s}.reverse
89
108
  end
109
+
110
+ # Returns a Pool containing copies of the n highest dice
90
111
  def highest(n=1)
91
112
  Pool.new(sort.reverse.first(n))
92
113
  end
114
+
115
+ # Returns a Pool containing copies of the n lowest dice
93
116
  def lowest(n=1)
94
117
  Pool.new(sort.first(n))
95
118
  end
119
+
120
+ # Returns a copy of the Pool, minus the n highest-value dice
96
121
  def drop_highest(n=1)
97
122
  Pool.new(self-highest(n))
98
123
  end
124
+
125
+ # Returns a copy of the Pool, minus the n lowest-value dice.
99
126
  def drop_lowest(n=1)
100
127
  Pool.new(self-lowest(n))
101
128
  end
129
+
130
+ # Returns a copy of the current pool, minus any
131
+ # dice with values equal the value (or in the array
132
+ # of values) passed.
102
133
  def drop(to_drop)
103
134
  to_drop = [to_drop].flatten #turn it into an array if it isn't one.
104
135
  kept = reject{|die| to_drop.any?{|drop_value| die.value == drop_value }}
@@ -1,7 +1,11 @@
1
1
  module Tabletop
2
2
  class Die
3
3
  include Comparable
4
+
4
5
  attr_reader :sides, :value
6
+
7
+ # Sides must be greater then or equal to 1.
8
+ # If init_value is nil, then #roll is called.
5
9
  def initialize(sides=6, init_value=nil)
6
10
  if sides <= 1
7
11
  raise ArgumentError, "Die cannot have #{sides} sides"
@@ -17,21 +21,29 @@ module Tabletop
17
21
  end
18
22
  @value = init_value
19
23
  end
24
+
25
+ # Sets @value to a random number n, where 1 <= n <= @sides
20
26
  def roll
21
27
  @value = rand(sides)+1
22
28
  end
23
29
 
30
+ # Returns a string in the form "[@value]/d@sides"
24
31
  def to_s
25
32
  "[#{value}]/d#{sides}"
26
33
  end
27
34
 
35
+ # Raises ArgumentError if new_value isn't between 1 and @sides inclusive
28
36
  def value=(new_value)
29
37
  raise ArgumentError unless valid_value?(new_value)
30
38
  @value = new_value
31
39
  end
40
+
41
+ # Compares based on value of the die
32
42
  def <=>(operand)
33
43
  @value <=> operand.to_int
34
44
  end
45
+
46
+ # Returns the die's value
35
47
  def to_int
36
48
  @value
37
49
  end
@@ -42,6 +54,9 @@ module Tabletop
42
54
  end
43
55
  end
44
56
 
57
+
58
+ # A FudgeDie is a kind of three-sided Die that has a value
59
+ # of either 0, 1, or -1.
45
60
  class FudgeDie < Die
46
61
  def initialize(init_value = nil)
47
62
  super(3, init_value)
@@ -50,6 +65,7 @@ module Tabletop
50
65
  @value = rand(sides)-1
51
66
  end
52
67
 
68
+ # Returns either "[-]", "[ ]", or "[+]", depending on @value
53
69
  def to_s
54
70
  "[#{['-', ' ', '+'][@value+1]}]"
55
71
  end
@@ -60,20 +76,25 @@ module Tabletop
60
76
  end
61
77
  end
62
78
 
79
+
80
+ # A coin is a kind of two-sided Die that has a value of
81
+ # either 0 or 1
63
82
  class Coin < Die
64
83
  def initialize(value=nil)
65
84
  super(2, value)
66
85
  end
67
86
 
68
- def roll
87
+ def roll #:nodoc:
69
88
  @value = rand(sides)
70
89
  end
71
90
 
91
+ # set to a random value, then return itself
72
92
  def flip
73
93
  roll
74
94
  self
75
95
  end
76
96
 
97
+ # Returns either "( )" or "(+)" depending on @value
77
98
  def to_s
78
99
  "(#{[' ', '+'][value]})"
79
100
  end
data/lib/tabletop/roll.rb CHANGED
@@ -2,18 +2,25 @@ require_relative 'pool'
2
2
 
3
3
  module Tabletop
4
4
 
5
- class Possibility
6
- attr_reader :outcomes, :conditions
5
+ class Possibility #:nodoc: all
6
+ attr_reader :outcomes
7
7
 
8
+ attr_reader :conditions
9
+
8
10
  def initialize(outcomes, conditions)
9
- @outcomes = outcomes
10
- @conditions = conditions
11
+ @outcomes, @conditions = outcomes, conditions
11
12
  end
12
13
  end
13
14
 
14
15
  class Roll
15
- attr_reader :pool, :possibilities
16
+ # Rolls of necessity have a Pool object against which they check possible results.
17
+ attr_accessor :pool
16
18
 
19
+
20
+ # The block contains methods that further detail the roll, as described below.
21
+ # pool must be (surprise!) a Pool. It's optional, because if #sides is passed
22
+ # in the block, then #roll can be called with a number of dice to roll, and a
23
+ # new Pool object will be instantiated every time this is done.
17
24
  def initialize(pool=nil, &block)
18
25
  if pool
19
26
  raise ArgumentError if pool.class != Tabletop::Pool
@@ -30,6 +37,12 @@ module Tabletop
30
37
  end
31
38
  end
32
39
 
40
+
41
+ # Returns an array.
42
+ # + The first value in the array is #result
43
+ # + If a "difficulty" was set in the most call of #roll, and #result meets or exceeds it, then the second element will be "Success".
44
+ # + if the conditions of any of the roll's @possibilities are met (see #meets?), then their outcomes will be all following elements.
45
+ # + if none of the above conditions are met, the second and final element is nil.
33
46
  def effects
34
47
  results = []
35
48
 
@@ -48,7 +61,6 @@ module Tabletop
48
61
  end
49
62
  end
50
63
  end
51
-
52
64
 
53
65
  if results.empty?
54
66
  results << nil
@@ -57,6 +69,15 @@ module Tabletop
57
69
  results.unshift(result)
58
70
  end
59
71
 
72
+ # Without any options passed, calls Pool#roll on the roll's pool. Returns the Roll.
73
+ #
74
+ # opts can have a few different values:
75
+ # :modifier:: adds to all subsequent calls to #sum, until #roll is called again
76
+ # :pool:: if #sides was called in the initialize block, and this is set, then a Pool of appropriate sides and number is created and assigned to @pool.
77
+ # :difficulty:: see #effects
78
+ #--
79
+ # TODO: @difficulty changes back to nil if it is not called in a given roll.
80
+ # TODO: abstract out ternary?
60
81
  def roll(opts={})
61
82
  @roll_modifier = opts[:modifier] ? opts[:modifier] : 0
62
83
  if @die_sides
@@ -73,6 +94,10 @@ module Tabletop
73
94
  self
74
95
  end
75
96
 
97
+ # Takes an object, returns false if anything set in the object's conditions hash
98
+ # are not met by #sum, otherwise returns true
99
+ #--
100
+ # TODO: checks #result, not #sum
76
101
  def meets?(p)
77
102
  answer = true
78
103
  if p.conditions[:>=]
@@ -86,17 +111,26 @@ module Tabletop
86
111
  answer
87
112
  end
88
113
 
114
+ # The sum of the values of dice in the pool, and any modifier set in
115
+ # instantiation (see #add), or the most recent call to #roll.
89
116
  def sum
90
117
  @pool.sum + @static_modifier + @roll_modifier
91
118
  end
92
119
 
93
- # instance_eval methods
94
-
95
- ## Possibility-creating methods
120
+ # Attaches an object to work with #meets?.
121
+ #
122
+ # value:: An integer.
123
+ # outcomes:: An array of values to contribute to #effects if #meets? is true.
96
124
  def at_least(value, *outcomes)
97
125
  @possibilities << Possibility.new(outcomes, :>= => value)
98
126
  end
99
127
 
128
+ # Attaches an object to work with #meets?.
129
+ #
130
+ # values:: Can be either an integer, or a Range. If it's a range, then #equals creates an object for each number in the range. If it's an integer, it creates just one.
131
+ # outcomes:: An array of values to contribute to #effects if #meets? is true.
132
+ #--
133
+ # TODO: values can be an array
100
134
  def equals(values, *outcomes)
101
135
  if values.instance_of?(Range)
102
136
  values.each do |val|
@@ -107,6 +141,19 @@ module Tabletop
107
141
  end
108
142
  end
109
143
 
144
+ # Defines a #result method, used by #effects.
145
+ #
146
+ # If symbol is ':count', then args must include a :at_least option, and #result will
147
+ # be equal to the number of dice in @pool of value equal or greater than
148
+ # args[:at_least].
149
+ #
150
+ # Optionally, args can also include a :doubles option, for values that add 2 to #result
151
+ #
152
+ # In all other cases, #result is aliased to #sum
153
+ #
154
+ # Meant to be used in the initialize block.
155
+ #--
156
+ # TODO: raise an error symbol is :count but :at_least is not set
110
157
  def set_result(symbol, args={})
111
158
  if symbol == :count
112
159
  @count_at_least = args[:at_least]
@@ -124,11 +171,19 @@ module Tabletop
124
171
  @result_set = true
125
172
  end
126
173
 
127
- # instance-variable-setting methods
174
+ # Sets a modifier that's added to #sum.
175
+ #
176
+ # Meant to be used in the initialize block.
128
177
  def add(mod)
129
178
  @static_modifier = mod
130
179
  end
131
180
 
181
+ # Sets a default die size. If set, roll can be called with a :pool argument to
182
+ # create and roll a new Pool of the indicated number and type of dice.
183
+ #
184
+ # Can be an integer other than zero, or :fudge for fudgedice.
185
+ #
186
+ # Meant to be used in the initialize block.
132
187
  def sides(num_sides)
133
188
  @die_sides = num_sides
134
189
  end
@@ -4,11 +4,13 @@ module Tabletop
4
4
  end
5
5
 
6
6
  class TokenStack
7
+
8
+ # The number of tokens in the Stack
7
9
  attr_accessor :count
8
10
  include Comparable
9
11
 
10
- def initialize(n = 1)
11
- @count = n
12
+ def initialize(num_tokens = 1)
13
+ @count = num_tokens
12
14
  end
13
15
 
14
16
  def <=>(operand)
@@ -20,6 +22,7 @@ module Tabletop
20
22
  @count += n
21
23
  end
22
24
 
25
+ # Raises NotEnoughTokensError if there aren't enough tokens to remove
23
26
  def remove(n=1)
24
27
  raise ArgumentError unless n.instance_of?(Fixnum) and n > 0
25
28
  if n > @count
@@ -36,12 +39,12 @@ module Tabletop
36
39
  @count -= n
37
40
  end
38
41
 
42
+ # Removes N tokens from the receiver stack, then
43
+ # adds them to the stack in opts[:to]
39
44
  def move(n, opts)
40
45
  raise(ArgumentError, "target is #{opts[:to].class}, not TokenStack") unless opts[:to].instance_of?(TokenStack)
41
46
  remove(n)
42
47
  opts[:to].add(n)
43
48
  end
44
49
  end
45
-
46
-
47
50
  end
@@ -1,3 +1,3 @@
1
1
  module Tabletop
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -191,8 +191,13 @@ module Tabletop
191
191
  describe "#flip" do
192
192
  it {subject.flip.should be_instance_of(Coin)}
193
193
  it "should alias roll" do
194
- subject.should_receive(:roll)
194
+ mock(subject).roll
195
195
  subject.flip
196
+ # I have to use implicit expectations, because the below code doesn't
197
+ # work in rspec2
198
+ #stub(subject).roll
199
+ #subject.flip
200
+ #subject.should have_received.roll
196
201
  end
197
202
  end
198
203
 
data/spec/spec_helper.rb CHANGED
@@ -15,5 +15,5 @@ require 'tabletop'
15
15
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
16
16
 
17
17
  RSpec.configure do |config|
18
-
18
+ config.mock_framework = :rr
19
19
  end
data/tabletop.gemspec CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.require_paths = ['lib']
28
28
 
29
29
  s.add_development_dependency 'rspec'
30
+ s.add_development_dependency 'rr'
30
31
  s.add_development_dependency 'bundler'
31
32
  s.add_development_dependency 'rake'
32
33
  s.add_development_dependency 'rdoc'
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: tabletop
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.0
5
+ version: 0.2.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nick Novitski
@@ -24,7 +24,7 @@ dependencies:
24
24
  prerelease: false
25
25
  version_requirements: *id001
26
26
  - !ruby/object:Gem::Dependency
27
- name: bundler
27
+ name: rr
28
28
  requirement: &id002 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
@@ -35,7 +35,7 @@ dependencies:
35
35
  prerelease: false
36
36
  version_requirements: *id002
37
37
  - !ruby/object:Gem::Dependency
38
- name: rake
38
+ name: bundler
39
39
  requirement: &id003 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
@@ -46,7 +46,7 @@ dependencies:
46
46
  prerelease: false
47
47
  version_requirements: *id003
48
48
  - !ruby/object:Gem::Dependency
49
- name: rdoc
49
+ name: rake
50
50
  requirement: &id004 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
@@ -56,6 +56,17 @@ dependencies:
56
56
  type: :development
57
57
  prerelease: false
58
58
  version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: rdoc
61
+ requirement: &id005 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *id005
59
70
  description: Tabletop aims to provide a simple way of describing, automating and tracking the tools and tasks involved in "analog" games, determining results from the motions and properties of various dice and chips.
60
71
  email: nicknovitski@gmail.com
61
72
  executables: []
@@ -66,6 +77,50 @@ extra_rdoc_files:
66
77
  - LICENSE
67
78
  - README.markdown
68
79
  files:
80
+ - doc/created.rid
81
+ - doc/Fixnum.html
82
+ - doc/images/brick.png
83
+ - doc/images/brick_link.png
84
+ - doc/images/bug.png
85
+ - doc/images/bullet_black.png
86
+ - doc/images/bullet_toggle_minus.png
87
+ - doc/images/bullet_toggle_plus.png
88
+ - doc/images/date.png
89
+ - doc/images/find.png
90
+ - doc/images/loadingAnimation.gif
91
+ - doc/images/macFFBgHack.png
92
+ - doc/images/package.png
93
+ - doc/images/page_green.png
94
+ - doc/images/page_white_text.png
95
+ - doc/images/page_white_width.png
96
+ - doc/images/plugin.png
97
+ - doc/images/ruby.png
98
+ - doc/images/tag_green.png
99
+ - doc/images/wrench.png
100
+ - doc/images/wrench_orange.png
101
+ - doc/images/zoom.png
102
+ - doc/index.html
103
+ - doc/js/darkfish.js
104
+ - doc/js/jquery.js
105
+ - doc/js/quicksearch.js
106
+ - doc/js/thickbox-compressed.js
107
+ - doc/lib/fixnum_rb.html
108
+ - doc/lib/tabletop/pool_rb.html
109
+ - doc/lib/tabletop/randomizers_rb.html
110
+ - doc/lib/tabletop/roll_rb.html
111
+ - doc/lib/tabletop/token_rb.html
112
+ - doc/lib/tabletop/version_rb.html
113
+ - doc/lib/tabletop_rb.html
114
+ - doc/rdoc.css
115
+ - doc/Tabletop/Coin.html
116
+ - doc/Tabletop/Die.html
117
+ - doc/Tabletop/FudgeDie.html
118
+ - doc/Tabletop/NotEnoughTokensError.html
119
+ - doc/Tabletop/Pool.html
120
+ - doc/Tabletop/Possibility.html
121
+ - doc/Tabletop/Roll.html
122
+ - doc/Tabletop/TokenStack.html
123
+ - doc/Tabletop.html
69
124
  - Gemfile
70
125
  - lib/fixnum.rb
71
126
  - lib/tabletop/pool.rb
@@ -98,7 +153,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
153
  requirements:
99
154
  - - ">="
100
155
  - !ruby/object:Gem::Version
101
- hash: 3490526089610525128
156
+ hash: 4463756612085784934
102
157
  segments:
103
158
  - 0
104
159
  version: "0"