coop_al 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +9 -0
- data/Gemfile +3 -0
- data/README.md +89 -0
- data/Rakefile +10 -0
- data/coop.gemspec +29 -0
- data/examples/filler.rb +9 -0
- data/examples/test.rb +15 -0
- data/exe/coop +131 -0
- data/lib/coop_al/adventure.rb +52 -0
- data/lib/coop_al/adventure_generator.rb +35 -0
- data/lib/coop_al/bestiary.rb +51 -0
- data/lib/coop_al/bestiary_generator.rb +3 -0
- data/lib/coop_al/bestiary_populator.rb +14 -0
- data/lib/coop_al/chapter.rb +51 -0
- data/lib/coop_al/chapter_generator.rb +32 -0
- data/lib/coop_al/encounter.rb +148 -0
- data/lib/coop_al/encounter_generator.rb +67 -0
- data/lib/coop_al/exception.rb +7 -0
- data/lib/coop_al/item.rb +30 -0
- data/lib/coop_al/library.rb +54 -0
- data/lib/coop_al/library_generator.rb +4 -0
- data/lib/coop_al/loot.rb +49 -0
- data/lib/coop_al/loot_generator.rb +42 -0
- data/lib/coop_al/monster.rb +19 -0
- data/lib/coop_al/monster_definition.rb +18 -0
- data/lib/coop_al/path.rb +65 -0
- data/lib/coop_al/path_follower.rb +34 -0
- data/lib/coop_al/random_encounter.rb +30 -0
- data/lib/coop_al/random_encounter_generator.rb +37 -0
- data/lib/coop_al/session.rb +55 -0
- data/lib/coop_al/session_date_generator.rb +43 -0
- data/lib/coop_al/session_encounter.rb +76 -0
- data/lib/coop_al/session_log.rb +51 -0
- data/lib/coop_al/state.rb +85 -0
- data/lib/coop_al/state_reporter.rb +72 -0
- data/lib/coop_al/trace.rb +29 -0
- data/lib/coop_al/treasure.rb +21 -0
- data/lib/coop_al/treasure_tables.rb +28 -0
- data/lib/coop_al/value.rb +167 -0
- data/lib/coop_al/version.rb +3 -0
- data/lib/coop_al/xp.rb +86 -0
- data/lib/coop_al.rb +34 -0
- data/res/srd.rb +400 -0
- metadata +188 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 940d2406792da127d6db1a622ff9fe6d7dfae655
|
4
|
+
data.tar.gz: 742e038d58588e7b58634201f6ae371f83fa2b47
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 49ac99bf96894e7162ff25da3e4124511d4f2cce35d18131d610b674f8435327b9955bd13817326c2bd32885ac48ca44714df20960f61fd62669126648fbc4eb
|
7
|
+
data.tar.gz: fcb213c0563ecc6a93f03b9b4555650b4df458bf2a3ab8c51406f23a0ba20adc2095adb524798d06b3aa8363c56f9fa55dcd982da5b7042f392355b21cae40a9
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# Coop - Adventurers League Character Log Generator
|
2
|
+
|
3
|
+
> "Reality is frequently inaccurate." -- Douglas Adams
|
4
|
+
|
5
|
+
Coop is a little tool that uses simple DSL-specified Dungeons and Dragons adventures to generate a log of pretend gameplay to support an Adventurers League character.
|
6
|
+
|
7
|
+
It includes SRD content, but nothing else. You'll have to supply your own copy of WoTC material.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
$> gem install coop_al
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
$> coop --help
|
16
|
+
coop [options] resource [resource...]
|
17
|
+
--path <path1>[,<path2>,...] Specify path to follow
|
18
|
+
--path-file <filename> Specify paths in a file, one per line
|
19
|
+
--no-loot Do not report loot
|
20
|
+
--no-xp Do not report accumulated XP
|
21
|
+
--no-paths Do not report available paths
|
22
|
+
--party-size n Total XP and treasure is divided by n [6]
|
23
|
+
--encounter-count n Encounters per session [10]
|
24
|
+
--end-date YYYY-MM-DD Most recent session [today]
|
25
|
+
--session-frequency n Sessions every n days [7]
|
26
|
+
--blackout-dates YYYY-MM-DD[,YYYY-MM-DD,...]
|
27
|
+
--skip-frequency n Chance of skipping week is 1 in n [never]
|
28
|
+
--srd Use included SRD file for monsters
|
29
|
+
--trace Print encounter details
|
30
|
+
--help Print this help
|
31
|
+
|
32
|
+
## Customization
|
33
|
+
|
34
|
+
Check out the examples provided.
|
35
|
+
|
36
|
+
### Bestiary
|
37
|
+
|
38
|
+
Create your own bestiary by providing a resource file in the form:
|
39
|
+
|
40
|
+
bestiary do
|
41
|
+
add :scary_monster, :cr1_2
|
42
|
+
add :scarier_monster, :cr17
|
43
|
+
end
|
44
|
+
|
45
|
+
### Adventures
|
46
|
+
|
47
|
+
Create your own adventures by providing a resource file in the form:
|
48
|
+
|
49
|
+
adventure :shortname, 'Adventure Name' do
|
50
|
+
entry :chapter_1
|
51
|
+
chapter :chapter_1, 'Chapter 1. Surrounding Area' do
|
52
|
+
5.times do
|
53
|
+
random 'Random Encounter' do
|
54
|
+
f(1..2) { monster :scary_monster }
|
55
|
+
f(3..20) { monsters '3d6', :scarier_monster }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
encounter 'Some old weak guy' do
|
59
|
+
npc :cr0
|
60
|
+
treasure 2000.gp + 400.pp
|
61
|
+
treasure 1000.gp, 'diamond'
|
62
|
+
item 'Vorpal sword'
|
63
|
+
end
|
64
|
+
encounter 'Bag of XP' do
|
65
|
+
xp 500
|
66
|
+
end
|
67
|
+
link_to :chapter_2
|
68
|
+
end
|
69
|
+
chapter :chapter_2, 'Chapter 2. The Caves' do
|
70
|
+
...
|
71
|
+
link_to_downtime
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
## Development
|
76
|
+
|
77
|
+
Coop is written in Ruby, and requires the [Tablescript gem](https://github.com/jamiehale/tablescript.rb).
|
78
|
+
|
79
|
+
### Tests
|
80
|
+
|
81
|
+
Such as they are...
|
82
|
+
|
83
|
+
$> rake spec
|
84
|
+
|
85
|
+
Coverage provided by simplecov.
|
86
|
+
|
87
|
+
### Rubocop
|
88
|
+
|
89
|
+
$> rake rubocop
|
data/Rakefile
ADDED
data/coop.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'coop_al/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'coop_al'
|
7
|
+
spec.version = CoopAl::VERSION
|
8
|
+
spec.authors = ['Jamie Hale']
|
9
|
+
spec.email = ['jamie@smallarmyofnerds.com']
|
10
|
+
spec.summary = 'Adventurers League Character Log Generator'
|
11
|
+
spec.description = 'Tool for automated character growth through predefined adventures'
|
12
|
+
spec.homepage = 'https://github.com/jamiehale/coop'
|
13
|
+
spec.license = 'GPL-3.0'
|
14
|
+
|
15
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
|
16
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
spec.add_dependency 'tablescript', '0.0.3'
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
24
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.5'
|
26
|
+
spec.add_development_dependency 'cucumber', '~> 2.4'
|
27
|
+
spec.add_development_dependency 'simplecov', '~> 0.13'
|
28
|
+
spec.add_development_dependency 'rubocop', '~> 0.47'
|
29
|
+
end
|
data/examples/filler.rb
ADDED
data/examples/test.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
adventure :test, 'Simple Adventure' do
|
2
|
+
entry :chapter_1
|
3
|
+
chapter :chapter_1, 'Chapter 1' do
|
4
|
+
encounter '1. Entrance' do
|
5
|
+
monster :goblin
|
6
|
+
monsters 2, :orc
|
7
|
+
treasure '2d6*10'.gp
|
8
|
+
item 'Potion of healing'
|
9
|
+
end
|
10
|
+
link_to :chapter_2
|
11
|
+
link_to_downtime
|
12
|
+
end
|
13
|
+
chapter :chapter_2, 'Chapter 2' do
|
14
|
+
end
|
15
|
+
end
|
data/exe/coop
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'tablescript'
|
4
|
+
require 'coop_al'
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
def version
|
8
|
+
puts "Coop v#{CoopAl::VERSION} - \"Reality is frequently inaccurate.\""
|
9
|
+
exit
|
10
|
+
end
|
11
|
+
|
12
|
+
def display_message(message)
|
13
|
+
puts
|
14
|
+
puts message
|
15
|
+
end
|
16
|
+
|
17
|
+
def usage(message = nil)
|
18
|
+
puts 'coop [options] resource [resource...]'
|
19
|
+
puts ' --path <path1>[,<path2>,...] Specify path to follow'
|
20
|
+
puts ' --path-file <filename> Specify paths in a file, one per line'
|
21
|
+
puts ' --no-loot Do not report loot'
|
22
|
+
puts ' --no-xp Do not report accumulated XP'
|
23
|
+
puts ' --no-paths Do not report available paths'
|
24
|
+
puts ' --party-size n Total XP and treasure is divided by n [6]'
|
25
|
+
puts ' --encounter-count n Encounters per session [10]'
|
26
|
+
puts ' --end-date YYYY-MM-DD Most recent session [today]'
|
27
|
+
puts ' --session-frequency n Sessions every n days [7]'
|
28
|
+
puts ' --blackout-dates YYYY-MM-DD[,YYYY-MM-DD,...]'
|
29
|
+
puts ' --skip-frequency n Chance of skipping week is 1 in n [never]'
|
30
|
+
puts ' --srd Use included SRD file for monsters'
|
31
|
+
puts ' --trace Print encounter details'
|
32
|
+
puts ' --help Print this help'
|
33
|
+
display_message(message) unless message.nil?
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
resource_files = []
|
38
|
+
paths = []
|
39
|
+
options = {
|
40
|
+
party_size: 6,
|
41
|
+
encounter_count: 10,
|
42
|
+
end_date: Date.today,
|
43
|
+
session_frequency: 7,
|
44
|
+
blackout_dates: []
|
45
|
+
}
|
46
|
+
until ARGV.empty?
|
47
|
+
parameter = ARGV.shift
|
48
|
+
case parameter
|
49
|
+
when '--help'
|
50
|
+
usage
|
51
|
+
when '--version'
|
52
|
+
version
|
53
|
+
when '--path'
|
54
|
+
usage unless paths.empty?
|
55
|
+
parameter = ARGV.shift
|
56
|
+
usage if parameter.nil?
|
57
|
+
paths = parameter.split(',').map { |p| CoopAl::Path.parse(p) }
|
58
|
+
when '--path-file'
|
59
|
+
usage unless paths.empty?
|
60
|
+
parameter = ARGV.shift
|
61
|
+
usage if parameter.nil?
|
62
|
+
File.open(parameter, 'r') do |f|
|
63
|
+
f.each_line do |line|
|
64
|
+
paths << CoopAl::Path.parse(line.strip)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
when '--no-loot'
|
68
|
+
options[:show_loot] = false
|
69
|
+
when '--no-xp'
|
70
|
+
options[:show_xp] = false
|
71
|
+
when '--no-paths'
|
72
|
+
options[:show_paths] = false
|
73
|
+
when '--party-size'
|
74
|
+
parameter = ARGV.shift
|
75
|
+
usage if parameter.nil?
|
76
|
+
options[:party_size] = parameter.to_i
|
77
|
+
when '--encounter-count'
|
78
|
+
parameter = ARGV.shift
|
79
|
+
usage if parameter.nil?
|
80
|
+
options[:encounter_count] = parameter.to_i
|
81
|
+
when '--end-date'
|
82
|
+
parameter = ARGV.shift
|
83
|
+
usage if parameter.nil?
|
84
|
+
options[:end_date] = Date.parse(parameter)
|
85
|
+
when '--session-frequency'
|
86
|
+
parameter = ARGV.shift
|
87
|
+
usage if parameter.nil?
|
88
|
+
options[:session_frequency] = parameter.to_i
|
89
|
+
when '--blackout-dates'
|
90
|
+
parameter = ARGV.shift
|
91
|
+
usage if parameter.nil?
|
92
|
+
options[:blackout_dates] = parameter.split(',').map { |d| Date.parse(d) }
|
93
|
+
when '--skip-frequency'
|
94
|
+
parameter = ARGV.shift
|
95
|
+
usage if parameter.nil?
|
96
|
+
options[:skip_frequency] = parameter.to_i
|
97
|
+
usage('Invalid skip frequency') if options[:skip_frequency] < 1
|
98
|
+
when '--srd'
|
99
|
+
resource_files << File.expand_path('../res/srd.rb', File.dirname(__FILE__))
|
100
|
+
when '--trace'
|
101
|
+
CoopAl::Trace.instance.tracing = true
|
102
|
+
else
|
103
|
+
resource_files << parameter
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
usage('No resources specified') if resource_files.empty?
|
108
|
+
begin
|
109
|
+
resource_files.each do |filename|
|
110
|
+
require filename
|
111
|
+
end
|
112
|
+
rescue StandardError => e
|
113
|
+
puts e
|
114
|
+
exit
|
115
|
+
end
|
116
|
+
|
117
|
+
date_generator = CoopAl::SessionDateGenerator.new(options)
|
118
|
+
log = CoopAl::SessionLog.new(date_generator, options)
|
119
|
+
|
120
|
+
state = CoopAl::State.new
|
121
|
+
follower = CoopAl::PathFollower.new(CoopAl::Library.instance, state)
|
122
|
+
begin
|
123
|
+
follower.follow(paths, log)
|
124
|
+
rescue StandardError => e
|
125
|
+
puts e
|
126
|
+
exit
|
127
|
+
end
|
128
|
+
|
129
|
+
CoopAl::StateReporter.new(state, CoopAl::Library.instance, options).report(STDOUT)
|
130
|
+
|
131
|
+
log.dump(STDOUT)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module CoopAl
|
2
|
+
##
|
3
|
+
# Adventure
|
4
|
+
#
|
5
|
+
class Adventure
|
6
|
+
attr_reader :name, :description, :chapters
|
7
|
+
|
8
|
+
def initialize(name, description)
|
9
|
+
@name = name
|
10
|
+
@description = description
|
11
|
+
@entries = []
|
12
|
+
@chapters = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_entry(path)
|
16
|
+
@entries << path
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_chapter(chapter)
|
20
|
+
@chapters[chapter.name] = chapter
|
21
|
+
end
|
22
|
+
|
23
|
+
def all_chapter_names
|
24
|
+
@chapters.keys
|
25
|
+
end
|
26
|
+
|
27
|
+
def chapter_by_path(path)
|
28
|
+
@chapters[path.chapter]
|
29
|
+
end
|
30
|
+
|
31
|
+
def chapter_paths
|
32
|
+
@chapters.values.map(&:absolute_path)
|
33
|
+
end
|
34
|
+
|
35
|
+
def all_entries
|
36
|
+
@entries.map { |e| Path.absolute(@name, e) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def chapter?(name)
|
40
|
+
@chapters.key?(name)
|
41
|
+
end
|
42
|
+
|
43
|
+
def chapter(name)
|
44
|
+
raise "Chapter (#{name}) not found" unless @chapters.key?(name)
|
45
|
+
@chapters[name]
|
46
|
+
end
|
47
|
+
|
48
|
+
def full_name
|
49
|
+
@description
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module CoopAl
|
2
|
+
##
|
3
|
+
# AdventureGenerator
|
4
|
+
#
|
5
|
+
class AdventureGenerator
|
6
|
+
attr_reader :adventure
|
7
|
+
|
8
|
+
def initialize(name, description, bestiary)
|
9
|
+
initialize_adventure(name, description)
|
10
|
+
@bestiary = bestiary
|
11
|
+
end
|
12
|
+
|
13
|
+
def entry(name)
|
14
|
+
@adventure.add_entry(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def chapter(name, description, &blk)
|
18
|
+
generator = ChapterGenerator.new(name, description, @adventure, @bestiary)
|
19
|
+
generator.instance_eval(&blk)
|
20
|
+
@adventure.add_chapter(generator.chapter)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def initialize_adventure(name, description)
|
26
|
+
if Library.instance.adventure?(name)
|
27
|
+
@adventure = Library.instance.adventure(name)
|
28
|
+
else
|
29
|
+
raise "Description required for adventure (#{name})" if description.nil?
|
30
|
+
@adventure = Adventure.new(name, description)
|
31
|
+
Library.instance.add_adventure(@adventure)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module CoopAl
|
4
|
+
##
|
5
|
+
# Bestiary
|
6
|
+
#
|
7
|
+
class Bestiary
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@monsters = {}
|
12
|
+
@xp_lookup = XpRewardTable.new
|
13
|
+
@loot_generator = LootGenerator.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def empty?
|
17
|
+
@monsters.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def add(monster)
|
21
|
+
@monsters[monster.id] = monster
|
22
|
+
end
|
23
|
+
|
24
|
+
def monster?(id)
|
25
|
+
@monsters.key?(id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def monster(id)
|
29
|
+
@monsters[id]
|
30
|
+
end
|
31
|
+
|
32
|
+
def create(id, treasure, encounter)
|
33
|
+
raise "Invalid monster ID (#{id})" unless @monsters.key?(id)
|
34
|
+
monster = @monsters[id]
|
35
|
+
xp = calculate_xp(monster)
|
36
|
+
loot = generate_loot(monster, treasure)
|
37
|
+
Monster.new(id, xp, loot, encounter)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def calculate_xp(monster)
|
43
|
+
@xp_lookup[monster.cr]
|
44
|
+
end
|
45
|
+
|
46
|
+
def generate_loot(monster, treasure)
|
47
|
+
return @loot_generator.generate(monster.cr, monster.treasure) if treasure == :default
|
48
|
+
@loot_generator.generate(monster.cr, treasure)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module CoopAl
|
2
|
+
##
|
3
|
+
# BestiaryPopulator
|
4
|
+
#
|
5
|
+
class BestiaryPopulator
|
6
|
+
def initialize(&blk)
|
7
|
+
instance_eval(&blk)
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(id, cr, treasure = :individual)
|
11
|
+
Bestiary.instance.add(MonsterDefinition.new(id, cr, treasure))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module CoopAl
|
2
|
+
##
|
3
|
+
# Chapter
|
4
|
+
#
|
5
|
+
class Chapter
|
6
|
+
attr_reader :name, :description, :encounters, :links
|
7
|
+
|
8
|
+
def initialize(name, description, adventure)
|
9
|
+
@name = name
|
10
|
+
@description = description
|
11
|
+
@adventure = adventure
|
12
|
+
@encounters = []
|
13
|
+
@links = []
|
14
|
+
@links_to_downtime = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def adventure_name
|
18
|
+
@adventure.description
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_encounter(encounter)
|
22
|
+
@encounters << encounter
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_link(path)
|
26
|
+
@links << path
|
27
|
+
end
|
28
|
+
|
29
|
+
def link_to_downtime
|
30
|
+
@links_to_downtime = true
|
31
|
+
end
|
32
|
+
|
33
|
+
def links_to_downtime?
|
34
|
+
@links_to_downtime
|
35
|
+
end
|
36
|
+
|
37
|
+
def follow(state, log)
|
38
|
+
@encounters.each do |encounter|
|
39
|
+
encounter.run(state, log)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def absolute_path
|
44
|
+
Path.Absolute(@adventure.name, @name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def full_name
|
48
|
+
@adventure.full_name + ' - ' + @description
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module CoopAl
|
2
|
+
##
|
3
|
+
# ChapterGenerator
|
4
|
+
#
|
5
|
+
class ChapterGenerator
|
6
|
+
attr_reader :chapter
|
7
|
+
|
8
|
+
def initialize(name, description, adventure, bestiary)
|
9
|
+
@adventure = adventure
|
10
|
+
@chapter = Chapter.new(name, description, adventure)
|
11
|
+
@bestiary = bestiary
|
12
|
+
end
|
13
|
+
|
14
|
+
def encounter(name, &blk)
|
15
|
+
generator = EncounterGenerator.new(name, @chapter, @bestiary)
|
16
|
+
@chapter.add_encounter(generator.generate_encounter(&blk))
|
17
|
+
end
|
18
|
+
|
19
|
+
def random(name, &blk)
|
20
|
+
generator = RandomEncounterGenerator.new(name, @chapter, @bestiary)
|
21
|
+
@chapter.add_encounter(generator.generate_encounter(&blk))
|
22
|
+
end
|
23
|
+
|
24
|
+
def link_to(chapter)
|
25
|
+
@chapter.add_link(Path.absolute(@adventure.name, chapter))
|
26
|
+
end
|
27
|
+
|
28
|
+
def link_to_downtime
|
29
|
+
@chapter.link_to_downtime
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|