calyx 0.16.0 → 0.16.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2dd4b07658e5e6d37f0b1c7a1f75afb08d61ae5f
4
- data.tar.gz: 6cf84a9ef492e359ff297a84129abca738c4ca91
3
+ metadata.gz: 414d8c715cd98f914a199935c68c0b2a06b479c2
4
+ data.tar.gz: 71fb631f0746d89d96bc20d6897cc0c65201b2ab
5
5
  SHA512:
6
- metadata.gz: c8bcd0a0eddc36040f008dc22de6d9df8b8f8e204e036c77f0efaceb226ab835888cfe997b4d9807f01e002b067de1f5b7750c1698711d3e0b05e92d3aac795f
7
- data.tar.gz: fe055edd5d1062a6e55ab474ed9d923bc228ed276cb22dca3ce3c5c0cb218361208635bfeeff24112ca159f44d9914ac1ed535a1301f23c68bd73411f0b2fb5d
6
+ metadata.gz: 6aaaec468253bddaf2ac68e81e87fca1c4a3654a23c2a1ea3bf6e63cd276d466b74995695b15429b6e57bef930ef35e2d37aad0ea81c939b089353ad5b385d0e
7
+ data.tar.gz: b2180e9d495f6d1e08a02a28bbf50ad09bd29a60a6e9c47e8c4c649fc8c112c98602c921c60cf0f2039968a79b13bbfa3fdcce2ab33ab3f53be82b7e95fd2af9
data/README.md CHANGED
@@ -231,26 +231,54 @@ end
231
231
 
232
232
  When a random seed isn’t supplied, `Time.new.to_i` is used as the default seed, which makes each run of the generator relatively unique.
233
233
 
234
- ### Weighted Selection
234
+ ### Weighted Choices
235
235
 
236
- If you want to supply a weighted probability list, you can pass in arrays to the rule constructor, with the first argument being the template text string and the second argument being a float representing the probability between `0` and `1` of this choice being selected.
236
+ Choices can be weighted so that some rules have a greater probability of expanding than others.
237
237
 
238
- For example, you can model the triangular distribution produced by rolling 2d6:
238
+ Weights are defined by passing a hash instead of a list of rules where the keys are strings or symbols representing the grammar rules and the values are weights.
239
+
240
+ Weights can be represented as floats, integers or ranges.
241
+
242
+ - Floats must be in the interval 0..1 and the given weights for a production must sum to 1.
243
+ - Ranges must be contiguous and cover the entire interval from 1 to the maximum value of the largest range.
244
+ - Integers (Fixnums) will produce a distribution based on the sum of all given numbers, with each number being a fraction of that sum.
245
+
246
+ The following definitions produce an equivalent weighting of choices:
239
247
 
240
248
  ```ruby
241
- class Roll2D6 < Calyx::Grammar
249
+ Calyx::Grammar.new do
250
+ start 'heads' => 1, 'tails' => 1
251
+ end
252
+
253
+ Calyx::Grammar.new do
254
+ start 'heads' => 0.5, 'tails' => 0.5
255
+ end
256
+
257
+ Calyx::Grammar.new do
258
+ start 'heads' => 1..5, 'tails' => 6..10
259
+ end
260
+
261
+ Calyx::Grammar.new do
262
+ start 'heads' => 50, 'tails' => 50
263
+ end
264
+ ```
265
+
266
+ There’s a lot of interesting things you can do with this. For example, you can model the triangular distribution produced by rolling 2d6:
267
+
268
+ ```ruby
269
+ Calyx::Grammar.new do
242
270
  start(
243
- ['2', 0.0278],
244
- ['3', 0.556],
245
- ['4', 0.833],
246
- ['5', 0.1111],
247
- ['6', 0.1389],
248
- ['7', 0.1667],
249
- ['8', 0.1389],
250
- ['9', 0.1111],
251
- ['10', 0.833],
252
- ['11', 0.556],
253
- ['12', 0.278]
271
+ '2' => 1,
272
+ '3' => 2,
273
+ '4' => 3,
274
+ '5' => 4,
275
+ '6' => 5,
276
+ '7' => 6,
277
+ '8' => 5,
278
+ '9' => 4,
279
+ '10' => 3,
280
+ '11' => 2,
281
+ '12' => 1
254
282
  )
255
283
  end
256
284
  ```
@@ -258,16 +286,15 @@ end
258
286
  Or reproduce Gary Gygax’s famous generation table from the original [Dungeon Master’s Guide](https://en.wikipedia.org/wiki/Dungeon_Master%27s_Guide#Advanced_Dungeons_.26_Dragons) (page 171):
259
287
 
260
288
  ```ruby
261
- class ChamberOrRoomContents < Calyx::Grammar
289
+ Calyx::Grammar.new do
262
290
  start(
263
- [:empty, 0.6],
264
- [:monster, 0.1],
265
- [:monster_treasure, 0.15],
266
- [:special, 0.05],
267
- [:trick_trap, 0.05],
268
- [:treasure, 0.05]
291
+ :empty => 0.6,
292
+ :monster => 0.1,
293
+ :monster_treasure => 0.15,
294
+ :special => 0.05,
295
+ :trick_trap => 0.05,
296
+ :treasure => 0.05
269
297
  )
270
-
271
298
  empty 'Empty'
272
299
  monster 'Monster Only'
273
300
  monster_treasure 'Monster and Treasure'
@@ -518,8 +545,8 @@ Rough plan for stabilising the API and features for a `1.0` release.
518
545
  | `0.12` | ~~API documentation~~ |
519
546
  | `0.13` | ~~Support for unique rules~~ |
520
547
  | `0.14` | ~~Support for Ruby 2.4~~ |
521
- | `0.15` | Options config and ‘strict mode’ error handling |
522
- | `0.16` | Improve representation of weighted probability selection |
548
+ | `0.15` | ~~Options config and ‘strict mode’ error handling~~ |
549
+ | `0.16` | ~~Improve representation of weighted probability selection~~ |
523
550
  | `0.17` | Introduce wildcard syntax for meta rules (rules returning rules) |
524
551
 
525
552
  ## Credits
@@ -20,6 +20,10 @@ module Calyx
20
20
  @options[:rng]
21
21
  end
22
22
 
23
+ def rand
24
+ rng.rand
25
+ end
26
+
23
27
  def strict?
24
28
  @options[:strict]
25
29
  end
@@ -5,10 +5,14 @@ module Calyx
5
5
  # being chosen.
6
6
  class WeightedChoices
7
7
  # Parse a given list or hash of productions into a syntax tree of weighted
8
- # choices.
8
+ # choices. Supports weights specified as Range, Fixnum and Float types.
9
+ #
10
+ # All weights get normalized to a set of values in the 0..1 interval that
11
+ # sum to 1.
9
12
  #
10
13
  # @param [Array<Array>, Hash<#to_s, Float>] productions
11
14
  # @param [Calyx::Registry] registry
15
+ # @return [Calyx::Production::WeightedChoices]
12
16
  def self.parse(productions, registry)
13
17
  if productions.first.last.is_a?(Range)
14
18
  range_max = productions.max { |a,b| a.last.max <=> b.last.max }.last.max
@@ -30,9 +34,15 @@ module Calyx
30
34
  memo += choice.last
31
35
  end
32
36
 
33
- raise Errors::InvalidDefinition, 'Weights must sum to 1' if weights_sum != 1.0
34
-
35
- normalized_productions = productions
37
+ if productions.first.last.is_a?(Float)
38
+ raise Errors::InvalidDefinition, 'Weights must sum to 1' if weights_sum != 1.0
39
+ normalized_productions = productions
40
+ else
41
+ normalized_productions = productions.map do |choice|
42
+ weight = choice.last.to_f / weights_sum.to_f * 1.0
43
+ [choice.first, weight]
44
+ end
45
+ end
36
46
  end
37
47
 
38
48
  choices = normalized_productions.map do |choice, weight|
@@ -63,7 +73,7 @@ module Calyx
63
73
  # @return [Array]
64
74
  def evaluate(options)
65
75
  choice = @collection.max_by do |_, weight|
66
- options.rng.rand ** (1.0 / weight)
76
+ options.rand ** (1.0 / weight)
67
77
  end.first
68
78
 
69
79
  [:weighted_choice, choice.evaluate(options)]
@@ -1,3 +1,3 @@
1
1
  module Calyx
2
- VERSION = '0.16.0'.freeze
2
+ VERSION = '0.16.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calyx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.16.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Rickerby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-31 00:00:00.000000000 Z
11
+ date: 2017-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler