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.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/.rubocop.yml +9 -0
- data/Gemfile +20 -0
- data/README.md +55 -44
- data/Rakefile +27 -3
- data/examples/namespaces.rb +33 -0
- data/examples/wandering_monsters.rb +15 -0
- data/lib/tablescript.rb +22 -66
- data/lib/tablescript/api.rb +50 -0
- data/lib/tablescript/exception.rb +24 -0
- data/lib/tablescript/library.rb +44 -0
- data/lib/tablescript/library_dumper.rb +42 -0
- data/lib/tablescript/lookup_strategy.rb +41 -0
- data/lib/tablescript/namespace.rb +85 -0
- data/lib/tablescript/namespace_generator.rb +20 -0
- data/lib/tablescript/roll_and_ignore_duplicates_strategy.rb +69 -0
- data/lib/tablescript/roll_and_ignore_strategy.rb +49 -0
- data/lib/tablescript/roll_context.rb +51 -0
- data/lib/tablescript/roll_strategy.rb +48 -0
- data/lib/tablescript/table.rb +54 -32
- data/lib/tablescript/table_entries.rb +66 -0
- data/lib/tablescript/table_entry.rb +18 -14
- data/lib/tablescript/version.rb +8 -8
- data/spec/spec_helper.rb +4 -0
- data/spec/tablescript/api_spec.rb +66 -0
- data/spec/tablescript/library_spec.rb +13 -0
- data/spec/tablescript/lookup_strategy_spec.rb +35 -0
- data/spec/tablescript/namespace_spec.rb +25 -0
- data/spec/tablescript/roll_and_ignore_strategy_spec.rb +57 -0
- data/spec/tablescript/roll_strategy_spec.rb +56 -0
- data/spec/tablescript/table_entry_spec.rb +42 -0
- data/spec/tablescript/table_spec.rb +88 -0
- data/spec/tablescript_spec.rb +7 -0
- data/tablescript.gemspec +26 -20
- metadata +112 -5
- data/lib/tablescript/dice_roller.rb +0 -94
- data/lib/tablescript/roll_descriptor.rb +0 -55
- data/lib/tablescript/table_entry_environment.rb +0 -124
data/lib/tablescript/table.rb
CHANGED
@@ -1,53 +1,75 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2017 Jamie Hale
|
2
2
|
#
|
3
|
-
# This file is part of the Tablescript
|
3
|
+
# This file is part of the Tablescript gem.
|
4
4
|
#
|
5
|
-
# Tablescript
|
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
|
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
|
17
|
-
|
18
|
-
module
|
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
|
-
|
23
|
-
|
24
|
-
def initialize( name, roller )
|
23
|
+
attr_reader :name, :entries
|
24
|
+
|
25
|
+
def initialize(name, namespace, &blk)
|
25
26
|
@name = name
|
26
|
-
@
|
27
|
-
@entries =
|
27
|
+
@namespace = namespace
|
28
|
+
@entries = TableEntries.new
|
29
|
+
instance_eval(&blk)
|
28
30
|
end
|
29
|
-
|
30
|
-
def
|
31
|
-
@entries
|
32
|
-
@entries.instance_eval( &blk )
|
31
|
+
|
32
|
+
def f(roll = nil, &blk)
|
33
|
+
@entries.add_fixed(roll, &blk)
|
33
34
|
end
|
34
|
-
|
35
|
-
def
|
36
|
-
@
|
35
|
+
|
36
|
+
def d(count = 1, &blk)
|
37
|
+
@entries.add_dynamic(count, &blk)
|
37
38
|
end
|
38
|
-
|
39
|
-
def lookup(
|
40
|
-
@entries.lookup(
|
39
|
+
|
40
|
+
def lookup(roll)
|
41
|
+
@entries.lookup(roll).evaluate(roll, self)
|
41
42
|
end
|
42
|
-
|
43
|
-
def roll
|
44
|
-
|
43
|
+
|
44
|
+
def lookup_on(path, roll)
|
45
|
+
LookupStrategy.new(resolve(path.to_s), roll).value
|
45
46
|
end
|
46
|
-
|
47
|
-
def
|
48
|
-
@entries.
|
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
|
1
|
+
# Copyright 2017 Jamie Hale
|
2
2
|
#
|
3
|
-
# This file is part of the Tablescript
|
3
|
+
# This file is part of the Tablescript gem.
|
4
4
|
#
|
5
|
-
# Tablescript
|
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
|
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
|
17
|
-
|
18
|
-
module
|
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
|
-
|
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(
|
27
|
-
|
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
|
data/lib/tablescript/version.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
# Copyright
|
1
|
+
# Copyright 2017 Jamie Hale
|
2
2
|
#
|
3
|
-
# This file is part of the Tablescript
|
3
|
+
# This file is part of the Tablescript gem.
|
4
4
|
#
|
5
|
-
# Tablescript
|
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
|
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
|
17
|
-
|
18
|
-
module
|
19
|
-
VERSION =
|
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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|