tablescript 0.0.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|