tablescript 0.0.4 → 1.0.0

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.rubocop.yml +9 -0
  4. data/Gemfile +20 -0
  5. data/README.md +55 -44
  6. data/Rakefile +27 -3
  7. data/examples/namespaces.rb +33 -0
  8. data/examples/wandering_monsters.rb +15 -0
  9. data/lib/tablescript.rb +22 -66
  10. data/lib/tablescript/api.rb +50 -0
  11. data/lib/tablescript/exception.rb +24 -0
  12. data/lib/tablescript/library.rb +44 -0
  13. data/lib/tablescript/library_dumper.rb +42 -0
  14. data/lib/tablescript/lookup_strategy.rb +41 -0
  15. data/lib/tablescript/namespace.rb +85 -0
  16. data/lib/tablescript/namespace_generator.rb +20 -0
  17. data/lib/tablescript/roll_and_ignore_duplicates_strategy.rb +69 -0
  18. data/lib/tablescript/roll_and_ignore_strategy.rb +49 -0
  19. data/lib/tablescript/roll_context.rb +51 -0
  20. data/lib/tablescript/roll_strategy.rb +48 -0
  21. data/lib/tablescript/table.rb +54 -32
  22. data/lib/tablescript/table_entries.rb +66 -0
  23. data/lib/tablescript/table_entry.rb +18 -14
  24. data/lib/tablescript/version.rb +8 -8
  25. data/spec/spec_helper.rb +4 -0
  26. data/spec/tablescript/api_spec.rb +66 -0
  27. data/spec/tablescript/library_spec.rb +13 -0
  28. data/spec/tablescript/lookup_strategy_spec.rb +35 -0
  29. data/spec/tablescript/namespace_spec.rb +25 -0
  30. data/spec/tablescript/roll_and_ignore_strategy_spec.rb +57 -0
  31. data/spec/tablescript/roll_strategy_spec.rb +56 -0
  32. data/spec/tablescript/table_entry_spec.rb +42 -0
  33. data/spec/tablescript/table_spec.rb +88 -0
  34. data/spec/tablescript_spec.rb +7 -0
  35. data/tablescript.gemspec +26 -20
  36. metadata +112 -5
  37. data/lib/tablescript/dice_roller.rb +0 -94
  38. data/lib/tablescript/roll_descriptor.rb +0 -55
  39. data/lib/tablescript/table_entry_environment.rb +0 -124
@@ -1,53 +1,75 @@
1
- # Copyright 2015 Jamie Hale
1
+ # Copyright 2017 Jamie Hale
2
2
  #
3
- # This file is part of the Tablescript.rb gem.
3
+ # This file is part of the Tablescript gem.
4
4
  #
5
- # Tablescript.rb is free software: you can redistribute it and/or modify
5
+ # Tablescript is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
7
7
  # the Free Software Foundation, either version 3 of the License, or
8
8
  # (at your option) any later version.
9
9
  #
10
- # Tablescript.rb is distributed in the hope that it will be useful,
10
+ # Tablescript is distributed in the hope that it will be useful,
11
11
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  # GNU General Public License for more details.
14
14
  #
15
15
  # You should have received a copy of the GNU General Public License
16
- # along with Foobar. If not, see <http://www.gnu.org/licenses/>.
17
-
18
- module TableScript
19
-
16
+ # along with Tablescript. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module Tablescript
19
+ ##
20
+ # Table
21
+ #
20
22
  class Table
21
-
22
- attr_reader :entries
23
-
24
- def initialize( name, roller )
23
+ attr_reader :name, :entries
24
+
25
+ def initialize(name, namespace, &blk)
25
26
  @name = name
26
- @roller = roller
27
- @entries = nil
27
+ @namespace = namespace
28
+ @entries = TableEntries.new
29
+ instance_eval(&blk)
28
30
  end
29
-
30
- def build( &blk )
31
- @entries = TableEntryEnvironment.new( @name, @roller )
32
- @entries.instance_eval( &blk )
31
+
32
+ def f(roll = nil, &blk)
33
+ @entries.add_fixed(roll, &blk)
33
34
  end
34
-
35
- def random_entry
36
- @roller.rollD( @entries.die_to_roll )
35
+
36
+ def d(count = 1, &blk)
37
+ @entries.add_dynamic(count, &blk)
37
38
  end
38
-
39
- def lookup( index )
40
- @entries.lookup( index )
39
+
40
+ def lookup(roll)
41
+ @entries.lookup(roll).evaluate(roll, self)
41
42
  end
42
-
43
- def roll
44
- @entries.reroll
43
+
44
+ def lookup_on(path, roll)
45
+ LookupStrategy.new(resolve(path.to_s), roll).value
45
46
  end
46
-
47
- def roll_and_ignore_duplicates( times, args )
48
- @entries.reroll_and_ignore_duplicates( times, args )
47
+
48
+ def dice_to_roll
49
+ "d#{@entries.size}"
49
50
  end
50
-
51
- end
52
51
 
52
+ def roll_on(path)
53
+ RollStrategy.new(resolve(path.to_s)).value
54
+ end
55
+
56
+ def roll_on_and_ignore(path, *args)
57
+ RollAndIgnoreStrategy.new(resolve(path.to_s), RpgLib::RollSet.new(*args)).value
58
+ end
59
+
60
+ def roll_on_and_ignore_duplicates(path, times)
61
+ RollAndIgnoreDuplicatesStrategy.new(resolve(path.to_s), times).value
62
+ end
63
+
64
+ private
65
+
66
+ def resolve(path)
67
+ namespace = @namespace
68
+ until namespace.nil?
69
+ return namespace.resolve(path) if namespace.resolve?(path)
70
+ namespace = namespace.parent
71
+ end
72
+ raise Exception, "No such table #{path}"
73
+ end
74
+ end
53
75
  end
@@ -0,0 +1,66 @@
1
+ module Tablescript
2
+ ##
3
+ # TableEntries
4
+ #
5
+ class TableEntries
6
+ def initialize
7
+ @entries = []
8
+ @next_id = 0
9
+ end
10
+
11
+ def size
12
+ @entries.size
13
+ end
14
+
15
+ def entry(index)
16
+ @entries[index]
17
+ end
18
+
19
+ def lookup(roll)
20
+ entry(roll - 1)
21
+ end
22
+
23
+ def add_fixed(roll, &blk)
24
+ if roll.nil?
25
+ add_entry(blk)
26
+ elsif roll.is_a?(Integer)
27
+ set_entry(roll, blk)
28
+ elsif roll.is_a?(Range)
29
+ set_range(roll, blk)
30
+ else
31
+ raise Exception, "Unrecognized parameter type (#{roll.class}) for fixed roll definition"
32
+ end
33
+ end
34
+
35
+ def add_dynamic(count, &blk)
36
+ range = next_single_roll..(next_single_roll + count - 1)
37
+ entry = TableEntry.new(next_id, range, blk)
38
+ count.times { @entries << entry }
39
+ end
40
+
41
+ private
42
+
43
+ def next_id
44
+ id = @next_id
45
+ @next_id += 1
46
+ id
47
+ end
48
+
49
+ def next_single_roll
50
+ @entries.size + 1
51
+ end
52
+
53
+ def add_entry(blk)
54
+ @entries << TableEntry.new(next_id, next_single_roll, blk)
55
+ end
56
+
57
+ def set_entry(roll, blk)
58
+ @entries[roll - 1] = TableEntry.new(next_id, roll, blk)
59
+ end
60
+
61
+ def set_range(range, blk)
62
+ entry = TableEntry.new(next_id, range, blk)
63
+ range.each { |r| @entries[r - 1] = entry }
64
+ end
65
+ end
66
+ end
@@ -1,31 +1,35 @@
1
- # Copyright 2015 Jamie Hale
1
+ # Copyright 2017 Jamie Hale
2
2
  #
3
- # This file is part of the Tablescript.rb gem.
3
+ # This file is part of the Tablescript gem.
4
4
  #
5
- # Tablescript.rb is free software: you can redistribute it and/or modify
5
+ # Tablescript is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
7
7
  # the Free Software Foundation, either version 3 of the License, or
8
8
  # (at your option) any later version.
9
9
  #
10
- # Tablescript.rb is distributed in the hope that it will be useful,
10
+ # Tablescript is distributed in the hope that it will be useful,
11
11
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  # GNU General Public License for more details.
14
14
  #
15
15
  # You should have received a copy of the GNU General Public License
16
- # along with Foobar. If not, see <http://www.gnu.org/licenses/>.
17
-
18
- module TableScript
19
-
16
+ # along with Tablescript. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module Tablescript
19
+ ##
20
+ # TableEntry
21
+ #
20
22
  class TableEntry
21
-
22
- def initialize( blk )
23
+ attr_reader :id, :roll, :blk
24
+
25
+ def initialize(id, roll, blk)
26
+ @id = id
27
+ @roll = roll
23
28
  @blk = blk
24
29
  end
25
-
26
- def evaluate( roll )
27
- @blk.call( roll )
30
+
31
+ def evaluate(roll, table)
32
+ table.instance_exec(RollContext.new(roll, table, self), &@blk)
28
33
  end
29
34
  end
30
-
31
35
  end
@@ -1,20 +1,20 @@
1
- # Copyright 2015 Jamie Hale
1
+ # Copyright 2017 Jamie Hale
2
2
  #
3
- # This file is part of the Tablescript.rb gem.
3
+ # This file is part of the Tablescript gem.
4
4
  #
5
- # Tablescript.rb is free software: you can redistribute it and/or modify
5
+ # Tablescript is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
7
7
  # the Free Software Foundation, either version 3 of the License, or
8
8
  # (at your option) any later version.
9
9
  #
10
- # Tablescript.rb is distributed in the hope that it will be useful,
10
+ # Tablescript is distributed in the hope that it will be useful,
11
11
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  # GNU General Public License for more details.
14
14
  #
15
15
  # You should have received a copy of the GNU General Public License
16
- # along with Foobar. If not, see <http://www.gnu.org/licenses/>.
17
-
18
- module TableScript
19
- VERSION = "0.0.4"
16
+ # along with Tablescript. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module Tablescript
19
+ VERSION = '1.0.0'.freeze
20
20
  end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ require 'tablescript'
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ module Tablescript
4
+ describe Api do
5
+ let(:api) { Class.new { include Api }.new }
6
+
7
+ describe 'table' do
8
+ end
9
+
10
+ describe 'rolling' do
11
+ let(:values) { %w(red green blue) }
12
+
13
+ before(:each) do
14
+ Library.instance = Library.new
15
+ api.table :colours do
16
+ f { 'red' }
17
+ f { 'green' }
18
+ f { 'blue' }
19
+ end
20
+ end
21
+
22
+ describe 'roll_on' do
23
+ it 'rolls on the table' do
24
+ 10.times do
25
+ expect(values).to include(api.roll_on(:colours))
26
+ end
27
+ end
28
+ end
29
+
30
+ describe 'roll_on_and_ignore' do
31
+ it 'rolls on the table and ignores certain rolls' do
32
+ 10.times do
33
+ expect(%w(red blue)).to include(api.roll_on_and_ignore(:colours, 2))
34
+ end
35
+ end
36
+ end
37
+
38
+ describe 'roll_on_and_ignore_duplicates' do
39
+ before(:each) do
40
+ @results = []
41
+ 10.times do
42
+ @results << api.roll_on_and_ignore_duplicates(:colours, 2)
43
+ end
44
+ end
45
+
46
+ it 'returns the expected number of results' do
47
+ @results.each do |roll_results|
48
+ expect(roll_results.size).to eq(2)
49
+ end
50
+ end
51
+
52
+ it 'ignores duplicate rolls' do
53
+ @results.each do |roll_results|
54
+ expect(roll_results[0]).not_to eq(roll_results[1])
55
+ end
56
+ end
57
+ end
58
+
59
+ describe 'lookup' do
60
+ it 'returns the specified entry' do
61
+ expect(api.lookup(:colours, 2)).to eq('green')
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ module Tablescript
4
+ describe Library do
5
+ it 'is a singleton' do
6
+ expect { Library.instance }.not_to raise_error
7
+ end
8
+
9
+ it 'knows its root namespace' do
10
+ expect(Library.instance.root).to be_a(Namespace)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ module Tablescript
4
+ describe LookupStrategy do
5
+ it 'can be created' do
6
+ expect { LookupStrategy.new(:table, :roll) }.not_to raise_error
7
+ end
8
+
9
+ describe 'value' do
10
+ let(:table) { double('table') }
11
+ let(:roll) { 6 }
12
+ let(:value) { 'Vorpal sword' }
13
+ let(:strategy) { LookupStrategy.new(table, roll) }
14
+
15
+ before(:each) do
16
+ allow(table).to receive(:evaluate) { value }
17
+ @value = strategy.value
18
+ end
19
+
20
+ it 'defers to the table' do
21
+ expect(table).to have_received(:evaluate).with(roll)
22
+ end
23
+
24
+ it 'provides the tables result' do
25
+ expect(@value).to eq(value)
26
+ end
27
+
28
+ it 'does not evaluate twice' do
29
+ strategy.value
30
+ strategy.value
31
+ expect(table).to have_received(:evaluate).once
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ module Tablescript
2
+ describe Namespace do
3
+ describe 'add' do
4
+ let(:table) { double('table', name: :table) }
5
+ let(:namespace) { Namespace.new }
6
+
7
+ it 'knows it has added table' do
8
+ namespace.add(table)
9
+ expect(namespace.table?(:table)).to be true
10
+ end
11
+
12
+ it 'retrieves the table' do
13
+ namespace.add(table)
14
+ expect(namespace.table(:table)).to eq(table)
15
+ end
16
+
17
+ describe 'duplicates' do
18
+ it 'throws when trying to add a duplicate' do
19
+ namespace.add(table)
20
+ expect { namespace.add(table) }.to raise_error(Exception)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ module Tablescript
4
+ describe RollAndIgnoreStrategy do
5
+ it 'can be created' do
6
+ expect { RollAndIgnoreStrategy.new(:table, :rollset) }.not_to raise_error
7
+ end
8
+
9
+ describe 'evaluate' do
10
+ let(:dice) { 'd20' }
11
+ let(:table) { double('table', dice_to_roll: dice) }
12
+ let(:rollset) { double('rollset') }
13
+ let(:roll) { 6 }
14
+ let(:value) { 'Vorpal sword' }
15
+ let(:roller) { RpgLib::DiceRoller.clone.instance }
16
+ let(:strategy) { RollAndIgnoreStrategy.new(table, rollset, roller) }
17
+
18
+ before(:each) do
19
+ allow(roller).to receive(:roll_and_ignore) { roll }
20
+ allow(table).to receive(:evaluate) { value }
21
+ @value = strategy.value
22
+ end
23
+
24
+ it 'defers to the roller' do
25
+ expect(roller).to have_received(:roll_and_ignore).with(dice, rollset)
26
+ end
27
+
28
+ it 'defers to the table' do
29
+ expect(table).to have_received(:evaluate).with(roll)
30
+ end
31
+
32
+ describe 'value' do
33
+ it 'provides the tables result' do
34
+ expect(@value).to eq(value)
35
+ end
36
+
37
+ it 'only evaluates once' do
38
+ strategy.value
39
+ strategy.value
40
+ expect(table).to have_received(:evaluate).once
41
+ end
42
+ end
43
+
44
+ describe 'roll' do
45
+ it 'knows its roll' do
46
+ expect(strategy.roll).to eq(roll)
47
+ end
48
+
49
+ it 'only evaluates once' do
50
+ strategy.roll
51
+ strategy.roll
52
+ expect(table).to have_received(:evaluate).once
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end