sapling-dialogue 0.1.0 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5aaa32f64d5d1e66ff4d8418c48067f2e8a4c283
4
- data.tar.gz: ddd847cc2912019b12de02680dd35282d7108be3
3
+ metadata.gz: 3acc37ddfad7efb3df53deafd404aea470df1fc7
4
+ data.tar.gz: ce6e29ac7f95c6c0db76cfeffb2e3ba86c1ba81f
5
5
  SHA512:
6
- metadata.gz: 798eb921d6a9b8774de8c0353a38b4e7201aebeee83badb67047c3e9f14f2d82886b470f797f1709f977d88c17584299ffbd12f23db74ed1597d5b7434c6c43e
7
- data.tar.gz: fb7ac1db708b798f8599d758ada08c7176fcd94a0ef94955ff3871793ce1b0d0776e00def90f255a94afd465df4e0f4b333983f43f3a0c110a0d5be61025589d
6
+ metadata.gz: efe7c71965dc68be6471cf121102678c9a54a2c77bc379016db257c89a8bbb25d74300fc1eecb5f1cf3be62e01bfc9908a0730fc1951a3e6d3f55f15bb8aaed7
7
+ data.tar.gz: ecfa454ac7df9d6f4e2d21b6a31051a20d690beb2df16a69cfab249e6af97f0d94559be0bc0ce61b1f3652ee2dfbad3624ed4b4c49ef5ba5a4f8f88f5efb7763
data/lib/sapling.rb CHANGED
@@ -8,19 +8,20 @@ Dir[File.join(__dir__, 'sapling', '*.rb')].each { |file| require file }
8
8
  # The main Sapling interface.
9
9
  class Sapling < Thor
10
10
  desc 'read TREE', 'Load and traverse the TREE'
11
- def read(tree)
12
- exit unless verify_tree(tree)
11
+ def read(file)
13
12
  puts 'Welcome to Sapling, a Dialogue Tree Utility.'
14
- speaker = Dialogue::Speaker.new(YAML.load_file(tree), false)
13
+ exit unless verify_tree(file)
14
+ tree = Gardner::Plot.new(YAML.load_file(file))
15
+ speaker = Dialogue::Speaker.new(tree, false)
15
16
  speaker.conversation
16
17
  end
17
18
 
18
19
  desc 'edit TREE', 'Edit a new or existing TREE'
19
- def edit(tree = '')
20
+ def edit(file = '')
20
21
  puts 'Welcome to Sapling, a Dialogue Tree Utility.'
21
22
  if !tree.empty?
22
- puts "Loading tree: #{tree}"
23
- exit unless verify_tree(tree)
23
+ puts "Loading tree: #{file}"
24
+ exit unless verify_tree(file)
24
25
  gardner = Planter::Spade.new(YAML.load_file(tree, false))
25
26
  else
26
27
  puts 'Creating a new tree!'
@@ -2,16 +2,15 @@ require_relative './gardner'
2
2
 
3
3
  # Dialogue is the module for traversing an existing tree.
4
4
  module Dialogue
5
-
6
5
  # Format and display the trunk
7
6
  #
8
7
  # @param trunk [Hash] The trunk hash
9
8
  # @param debug [Boolean] The status of showing debug information
10
- def self.display_trunk(trunk, debug=false)
11
- 40.times { print "-" }
9
+ def self.display_trunk(trunk, debug = false)
10
+ 40.times { print '-' }
12
11
  puts "\n[ Trunk ]\n" if debug
13
- puts "\n#{trunk["trunk"]}"
14
- 40.times { print "-" }
12
+ puts "\n#{trunk['trunk']}"
13
+ 40.times { print '-' }
15
14
  puts "\n"
16
15
  end
17
16
 
@@ -20,11 +19,11 @@ module Dialogue
20
19
  # @param branch [Hash] A branch data set
21
20
  # @param branch_no [Integer] The branch number
22
21
  # @param debug [Boolean] Status of showing debug information
23
- def self.display_branch(branch, branch_no, debug=false)
22
+ def self.display_branch(branch, branch_no, debug = false)
24
23
  puts "\n[ Branch: #{branch_no} ]" if debug
25
- puts "\n#{branch["desc"]}\n\n"
24
+ puts "\n#{branch['desc']}\n\n"
26
25
 
27
- branch["options"].each_pair do |k,v|
26
+ branch['options'].each_pair do |k, v|
28
27
  puts "\t#{k}: #{v.keys[0]}"
29
28
  puts "\t\t[ Goes to branch #{v.values[0]} ]\n" if debug
30
29
  end
@@ -32,30 +31,27 @@ module Dialogue
32
31
 
33
32
  # Speaker holds the functionality for going through a dialogue tree.
34
33
  class Speaker
35
- # The file, which should be a dialogue tree YAML file.
36
- attr_accessor :file
34
+ # The tree, an instance of Gardner::Plot
35
+ attr_reader :tree
37
36
  # Status of verbose/debug mode. True = on; false = off.
38
- attr_accessor :debug
37
+ attr_reader :debug
39
38
 
40
- def initialize(file="", debug=false)
41
- @file = file
39
+ def initialize(tree, debug = false)
40
+ @tree = tree
42
41
  @debug = debug
43
42
  end
44
43
 
45
44
  # Conversation handles navigating the tree, until the option to end is
46
45
  # reached.
47
- def conversation()
48
- tree = Gardner.prune_trunk(@file)
49
-
50
- Dialogue.display_trunk(tree[0], false)
51
- branches = Gardner.prune_branches(tree[1])
46
+ def conversation
47
+ Dialogue.display_trunk(@tree.trunk, @debug)
52
48
 
53
49
  next_branch = 1
54
- until next_branch == 0 do
55
- next_branch = talk(branches[next_branch], next_branch)
50
+ until next_branch.zero?
51
+ next_branch = talk(@tree.branches[next_branch], next_branch)
56
52
  end
57
53
 
58
- puts "\n#{branches[0]["desc"]}"
54
+ puts "\n#{@tree.branches[0]['desc']}"
59
55
  exit
60
56
  end
61
57
 
@@ -65,25 +61,18 @@ module Dialogue
65
61
  # @param branch_no [Integer] The branch number
66
62
  # @return [Integer] The number of the next branch
67
63
  def talk(branch, branch_no)
68
- # If there are no options on this branch, we assume it's a terminal
69
- # branch. Return 0, and end the program.
70
- if branch["options"].empty?
71
- puts "\n#{branch["desc"]}\n\n"
72
- return 0
73
- end
64
+ return 0 if terminal?(branch)
74
65
 
75
66
  Dialogue.display_branch(branch, branch_no, @debug)
76
67
 
77
68
  response = get_response(branch)
78
69
 
79
- unless response == 0
80
- puts "\n"
81
- 10.times { print "*" }
82
- puts "\n(Your choice: #{branch["options"][response].keys[0]})"
83
- response = branch["options"][response].values[0].to_i
70
+ unless response.zero?
71
+ puts "(Your choice: #{branch['options'][response].keys[0]})"
72
+ response = branch['options'][response].values[0].to_i
84
73
  end
85
74
 
86
- return response
75
+ response
87
76
  end
88
77
 
89
78
  # Get a response for the displayed branch
@@ -91,20 +80,33 @@ module Dialogue
91
80
  # @param branch [Hash] A branch data set
92
81
  # @return [Integer] the next branch
93
82
  def get_response(branch)
94
- valid_options = branch["options"].keys.join(", ")
83
+ valid_options = branch['options'].keys.join(', ')
95
84
 
96
85
  print "\n[#{valid_options}]> "
97
86
  STDOUT.flush
98
87
  response = STDIN.gets.chomp.to_i
99
88
 
100
- until branch["options"].keys.include?(response) or response == 0
101
- print "[## Invalid options. "
89
+ until branch['options'].keys.include?(response) || response.zero?
90
+ print '[## Invalid options. '
102
91
  print "Valid options are #{valid_options}, or 0 to exit."
103
92
  print "\n[#{valid_options}]> "
104
93
  response = STDIN.gets.chomp.to_i
105
94
  end
106
95
 
107
- return response
96
+ response
97
+ end
98
+
99
+ # Check if a branch is terminal
100
+ #
101
+ # @param branch [Hash] A branch data set
102
+ # @return [Boolean] true if the branch is terminal, false otherwise
103
+ def terminal?(branch)
104
+ if branch['options'].empty?
105
+ puts "\n#{branch['desc']}\n\n"
106
+ return true
107
+ end
108
+
109
+ false
108
110
  end
109
111
  end
110
112
  end
@@ -2,47 +2,95 @@ require 'yaml'
2
2
 
3
3
  # Gardner is the module for working with a dialogue tree file
4
4
  module Gardner
5
+ # The Plot class handles a specific tree file. It provides functionality for
6
+ # parsing trunks and branches, and provides these as class attributes.
7
+ class Plot
8
+ # The trunk and branches instance variables
9
+ attr_reader :branches, :tree, :trunk
5
10
 
6
- # Parse the tree array into an array of numbered branches, and ordered leaves.
7
- #
8
- # @param tree [Array] The dialogue tree
9
- # @return [Array] An array of numbered branches, with numbered leaves
10
- def self.prune_branches(tree)
11
- branches = { 0 => { "desc" => "Thanks for using Sapling!" } }
12
- tree.each do |b|
13
- branches[b["branch"]["number"]] = {
14
- "desc" => b["branch"]["text"],
15
- "options" => prune_leaves(b["branch"]["leaf"]) }
11
+ # Initialize a new Plot from a tree file
12
+ #
13
+ # @param tree [File] The dialogue tree file
14
+ def initialize(file)
15
+ @tree = file
16
+ prune_trunk
17
+ prune_branches
16
18
  end
17
19
 
18
- return branches
19
- end
20
+ # Parse the tree array into an array of numbered branches, and ordered
21
+ # leaves.
22
+ #
23
+ # @param tree [File] The dialogue tree
24
+ # @return [Array] An array of numbered branches, with numbered leaves
25
+ def prune_branches
26
+ @branches = { 0 => { 'desc' => 'Thanks for using Sapling!' } }
27
+ @tree.each do |b|
28
+ @branches[b['branch']['number']] = {
29
+ 'desc' => b['branch']['text'],
30
+ 'options' => prune_leaves(b['branch']['leaf'])
31
+ }
32
+ end
33
+ end
34
+
35
+ # Parse the leaves of a branch into a numbered hash of options.
36
+ #
37
+ # @param leaves [Array] The option of leaf hashes
38
+ # @return [Hash] A numbered hash of options
39
+ def prune_leaves(leaves)
40
+ x = 1
41
+ options = {}
20
42
 
21
- # Parse the leaves of a branch into a numbered hash of options.
22
- #
23
- # @param leaves [Array] The option of leaf hashes
24
- # @return [Hash] A numbered hash of options
25
- def self.prune_leaves(leaves)
26
- x = 1
27
- options = {}
43
+ return options if leaves.nil?
28
44
 
29
- return options if leaves.nil?
45
+ leaves.each do |l|
46
+ options[x] = { l['text'] => l['branch'] }
47
+ x += 1
48
+ end
30
49
 
31
- leaves.each do |l|
32
- options[x] = { l["text"] => l["branch"] }
33
- x += 1
50
+ options
34
51
  end
35
52
 
36
- return options
53
+ # Parse the trunk of the tree.
54
+ #
55
+ # @return [Array] The trunk, and the remainder of the tree
56
+ def prune_trunk
57
+ @trunk = @tree.shift
58
+ end
37
59
  end
38
60
 
39
- # Parse the trunk of the tree.
40
- #
41
- # @param tree [Hash] The entire tree
42
- # @return [Array] The trunk, and the remainder of the tree
43
- def self.prune_trunk(tree)
44
- trunk = tree.shift
61
+ # Digiplot represents a Plot used for editing. The Digiplot functions exactly
62
+ # like a Plot, except with additional functionality for over-writing existing
63
+ # branches, leaves, and the trunk.
64
+ class Digiplot < Plot
65
+ # Duplicate the "old" trunk and branches, for restoration purposes
66
+ attr_reader :old_branches, :old_trunk
67
+
68
+ # Enable editing for the trunk
69
+ attr_writer :trunk
45
70
 
46
- return [trunk,tree]
71
+ # Initialize a Digiplot just like a Plot, but also copy the trunk and
72
+ # branches to "old" instance variables.
73
+ def initialize
74
+ super
75
+ @old_trunk = @trunk
76
+ @old_branches = @branches
77
+ end
78
+
79
+ # Change a branch
80
+ #
81
+ # @param branch [Integer] the number of the branch to be edited
82
+ def branch=(branch, text)
83
+ @branches[branch]['desc'] = text
84
+ end
85
+
86
+ # Change a leaf on a branch, grasshopper
87
+ #
88
+ # @param branch [Integer] the number of the branch to be edited
89
+ # @param leaf [Integer] the number of the leaf to be edited
90
+ # @param text [String] the new text for the leaf
91
+ # @param target [Integer] the branch number target for the leaf option
92
+ def leaf=(branch, leaf, text, target)
93
+ @branches[branch]['options'][leaf] = { text => target }
94
+ end
47
95
  end
48
96
  end
@@ -7,34 +7,32 @@
7
7
  # documentation.
8
8
 
9
9
  # The default trunk text of a new tree
10
- SKELE_TRUNK_TEXT = "Welcome to the Sapling Editor. For details, please see the
11
- documentation!"
10
+ SKELE_TRUNK_TEXT = 'Welcome to the Sapling Editor. For details, please see the
11
+ documentation!'.freeze
12
12
 
13
13
  # The default first-branch text of a new tree
14
- SKELE_BRANCH_TEXT = "The first branch is always shown by default. It should act
15
- as the introduction to the story. From here, the user enters your world!"
14
+ SKELE_BRANCH_TEXT = 'The first branch is always shown by default. It should act
15
+ as the introduction to the story. From here, the user enters your world!'.freeze
16
16
 
17
17
  # The default first-leaf text of the first branch of a new tree. The leaf points
18
18
  # to it's own branch. The only way out of the program is to either force-quit or
19
19
  # reply with option 0.
20
- SKELE_LEAF_TEXT = "Each branch can have any number of leaves, which represent
20
+ SKELE_LEAF_TEXT = 'Each branch can have any number of leaves, which represent
21
21
  the options a user has on that branch. Each leaf points to another branch, or
22
- can point to branch 0 to immediately exit."
22
+ can point to branch 0 to immediately exit.'.freeze
23
23
 
24
24
  # The final tree
25
25
  SKELETON_TREE = [
26
- {"trunk" => "#{SKELE_TRUNK_TEXT}"},
27
- {"branch" => {
28
- "number" => 1,
29
- "text" => "#{SKELE_BRANCH_TEXT}",
30
- "leaf" => [{
31
- "text" => "#{SKELE_LEAF_TEXT}",
32
- "branch" => 1
33
- }]
34
- }
35
- }
36
- ]
37
-
26
+ { 'trunk' => SKELE_TRUNK_TEXT.to_s },
27
+ { 'branch' => {
28
+ 'number' => 1,
29
+ 'text' => SKELE_BRANCH_TEXT.to_s,
30
+ 'leaf' => [{
31
+ 'text' => SKELE_LEAF_TEXT.to_s,
32
+ 'branch' => 1
33
+ }]
34
+ } }
35
+ ].freeze
38
36
 
39
37
  # Verify that a file is a dialogue tree file.
40
38
  #
@@ -44,13 +42,13 @@ def verify_tree(file)
44
42
  results = []
45
43
  begin
46
44
  tree = YAML.load_file(file)
47
- results << tree[0].keys.include?("trunk")
48
- results << tree[1]["branch"].keys.include?("number")
49
- results << tree[1]["branch"].keys.include?("text")
50
- results << tree[1]["branch"].keys.include?("leaf")
45
+ results << tree[0].keys.include?('trunk')
46
+ results << tree[1]['branch'].keys.include?('number')
47
+ results << tree[1]['branch'].keys.include?('text')
48
+ results << tree[1]['branch'].keys.include?('leaf')
51
49
  rescue
52
50
  puts "Sorry chummer, I don't think this is a tree."
53
- puts "Verify your YAML file is formatted properly."
51
+ puts 'Verify your YAML file is formatted properly.'
54
52
  results << false
55
53
  end
56
54
 
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sapling-dialogue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bill Niblock
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-14 00:00:00.000000000 Z
11
+ date: 2017-10-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Create, edit, and traverse Dialogue trees
13
+ description: Create, edit, and traverse dialogue trees
14
14
  email: azulien@gmail.com
15
15
  executables:
16
16
  - sapling