Compare commits
No commits in common. "master" and "gh-pages" have entirely different histories.
48 changed files with 0 additions and 1020 deletions
61
.gitignore
vendored
61
.gitignore
vendored
|
@ -1,61 +0,0 @@
|
|||
# Global gitignore file
|
||||
# bill_niblock@yahoo.com
|
||||
|
||||
##
|
||||
# Stolen from octocat: https://gist.github.com/octocat/9257657
|
||||
##
|
||||
|
||||
# Compiled source #
|
||||
###################
|
||||
*.com
|
||||
*.class
|
||||
*.dll
|
||||
*.exe
|
||||
*.o
|
||||
*.so
|
||||
|
||||
# Packages #
|
||||
############
|
||||
# it's better to unpack these files and commit the raw source
|
||||
# git has its own built in compression methods
|
||||
*.7z
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
|
||||
# Logs and databases #
|
||||
######################
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
##
|
||||
# Additions
|
||||
##
|
||||
|
||||
# Vim Related #
|
||||
###############
|
||||
*.swp
|
||||
.netrwhist
|
||||
*.un~
|
||||
|
||||
# YARD Related #
|
||||
################
|
||||
# doc/ is the generated documentation for Yard, which can easily be generated
|
||||
# locally with yardoc
|
||||
# .yardoc/ is yard metadata, not necessary to be uploaded to GH
|
||||
.yardoc/
|
|
@ -1,4 +0,0 @@
|
|||
language: ruby
|
||||
sudo: false
|
||||
rvm:
|
||||
- 2.2
|
|
@ -1,9 +0,0 @@
|
|||
--title "Sapling Documentation"
|
||||
-
|
||||
README.md
|
||||
var/docs/config_file.md
|
||||
var/docs/config_file_example.md
|
||||
var/docs/editor.md
|
||||
CONTRIBUTING.md
|
||||
LICENSE
|
||||
lib/**.*.rb
|
|
@ -1,14 +0,0 @@
|
|||
# Contributing to Sapling
|
||||
|
||||
If you actually want to contribute to this software, first off: Thanks! Sapling
|
||||
is just a side-project, unintended for any significant use.
|
||||
|
||||
Sapling is written in Ruby, and adheres to the standard Rubocop rules. So long
|
||||
as your code passes those rules, it should be good. At time of writing, Sapling
|
||||
has no testing, because I honestly have very little experience writing tests.
|
||||
Hopefully this changes soon!
|
||||
|
||||
If you don't know how to program in Ruby, but wish to improve this software,
|
||||
feel free to submit an issue or reach out to me directly.
|
||||
|
||||
Thanks again for your interest in Sapling!
|
12
Gemfile
12
Gemfile
|
@ -1,12 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
source "https://rubygems.org"
|
||||
|
||||
# Documentation
|
||||
gem "rdoc"
|
||||
gem "redcarpet"
|
||||
gem "thor"
|
||||
gem "yard"
|
||||
gem "yard-ghpages"
|
||||
|
||||
# Testing
|
||||
gem "rubocop"
|
41
Gemfile.lock
41
Gemfile.lock
|
@ -1,41 +0,0 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
ast (2.3.0)
|
||||
git (1.3.0)
|
||||
parser (2.4.0.0)
|
||||
ast (~> 2.2)
|
||||
powerpack (0.1.1)
|
||||
rainbow (2.2.2)
|
||||
rake
|
||||
rake (11.3.0)
|
||||
rdoc (5.1.0)
|
||||
redcarpet (3.4.0)
|
||||
rubocop (0.48.1)
|
||||
parser (>= 2.3.3.1, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
rainbow (>= 1.99.1, < 3.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||
ruby-progressbar (1.8.1)
|
||||
thor (0.20.0)
|
||||
unicode-display_width (1.2.1)
|
||||
yard (0.9.9)
|
||||
yard-ghpages (0.0.2)
|
||||
git (~> 1.3)
|
||||
rake (~> 11.1)
|
||||
yard (~> 0.8)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
rdoc
|
||||
redcarpet
|
||||
rubocop
|
||||
thor
|
||||
yard
|
||||
yard-ghpages
|
||||
|
||||
BUNDLED WITH
|
||||
1.14.6
|
21
LICENSE
21
LICENSE
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017 Bill Niblock
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
85
README.md
85
README.md
|
@ -1,85 +0,0 @@
|
|||
<!--
|
||||
# @markup markdown
|
||||
# @title README
|
||||
-->
|
||||
|
||||
# Sapling: A Dialogue Tree CLI Utility
|
||||
|
||||
[](
|
||||
https://badge.fury.io/rb/sapling-dialogue) [](
|
||||
https://travis-ci.org/VagabondAzulien/sapling)
|
||||
|
||||
Sapling allows for easy creation and use of dialogue trees.
|
||||
|
||||
A dialogue tree is a series of dialogues which follow sequentially, though with
|
||||
branching options. Examples include "Choose Your Own Adventure" games, or the
|
||||
dialogues seen in many video games.
|
||||
|
||||
## Structure
|
||||
|
||||
A dialogue tree can be broken down into three distinct parts: the trunk,
|
||||
branches, and leafs. The trunk represents the main structure of the tree. Unlike
|
||||
a branch, which displays content and options, the trunk provides metadata.
|
||||
Generally speaking, it is a branch, with the exception that it has no options. A
|
||||
branch represents a choice taken in the dialogue. Branches flow to each other
|
||||
through leafs, which are the actual choices.
|
||||
|
||||
You can experience this yourself, by loading "Example Quest! - A Meta Dialogue
|
||||
Tree!". You can find the tree itself at [var/trees/example\_quest.yaml](
|
||||
https://github.com/VagabondAzulien/sapling/blob/master/var/trees/example_quest.yaml).
|
||||
To run it, just type `sapling read path/to/example_quest.yaml`.
|
||||
|
||||
## Building a New Tree
|
||||
|
||||
To build a new tree, you have two options. You can manually edit a configuration
|
||||
file, or go through the construction wizard. Either way, the end result is a
|
||||
plain-text configuration file, which can be easily shared, edited, and viewed.
|
||||
For more details on the configuration file itself, check out the [Configuration
|
||||
File documentation](
|
||||
http://www.theinternetvagabond.com/sapling/file.config_file.html), or the
|
||||
self-documented [configuration file example](
|
||||
http://www.theinternetvagabond.com/sapling/file.config_file_example.html).
|
||||
Alternatively, you can checkout [Example Quest](
|
||||
https://github.com/VagabondAzulien/sapling/blob/master/var/trees/example_quest.yaml)
|
||||
for a complete tree.
|
||||
|
||||
### Manual Edit
|
||||
|
||||
1. Open your preferred text editor.
|
||||
2. Refer to the [Configuration File documentation](
|
||||
http://www.theinternetvagabond.com/sapling/file.config_file.html)
|
||||
3. Make your changes.
|
||||
4. Save your changes.
|
||||
|
||||
### Automatic Edit -- Coming Soon(tm)!
|
||||
|
||||
1. Run the configuration editor: `sapling edit [TREE]`
|
||||
2. If you don't include a TREE, `sapling` will create a new tree in the current
|
||||
directory.
|
||||
3. If you choose to modify an existing file, `sapling` will open the tree at the
|
||||
trunk, and show you the first branch.
|
||||
4. Make your changes.
|
||||
5. Save your changes.
|
||||
|
||||
More details on the editor can be found in the [Editor
|
||||
documentation](
|
||||
http://www.theinternetvagabond.com/sapling/file.editor.html).
|
||||
|
||||
## Contributing
|
||||
|
||||
You can contribute to Sapling by following these instructions:
|
||||
1. Fork this repository.
|
||||
2. In your fork, make your changes.
|
||||
3. Make sure your changes respect the [contribution
|
||||
guidelines](
|
||||
http://www.theinternetvagabond.com/sapling/file.CONTRIBUTING.html).
|
||||
4. Submit a pull request.
|
||||
|
||||
## License
|
||||
|
||||
Sapling is licensed under the MIT license. The full text can be found in
|
||||
[LICENSE](
|
||||
http://www.theinternetvagabond.com/sapling/file.LICENSE.html).
|
3
Rakefile
3
Rakefile
|
@ -1,3 +0,0 @@
|
|||
require 'yard-ghpages'
|
||||
|
||||
Yard::GHPages::Tasks.install_tasks
|
|
@ -1,5 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'sapling'
|
||||
|
||||
Sapling.start(ARGV)
|
0
doc/js/jquery.js → js/jquery.js
vendored
0
doc/js/jquery.js → js/jquery.js
vendored
|
@ -1,44 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'thor'
|
||||
require 'yaml'
|
||||
|
||||
Dir[File.join(__dir__, 'sapling', '*.rb')].each { |file| require file }
|
||||
|
||||
# The main Sapling interface.
|
||||
class Sapling < Thor
|
||||
desc 'read TREE', 'Load and traverse the TREE'
|
||||
def read(file)
|
||||
puts 'Welcome to Sapling, a Dialogue Tree Utility.'
|
||||
exit unless verify_tree(file)
|
||||
tree = Gardner::Plot.new(YAML.load_file(file))
|
||||
speaker = Dialogue::Speaker.new(tree, false)
|
||||
speaker.conversation
|
||||
end
|
||||
|
||||
desc 'edit TREE', 'Edit a new or existing TREE'
|
||||
def edit(file = '')
|
||||
puts 'Welcome to Sapling, a Dialogue Tree Utility.'
|
||||
if !tree.empty?
|
||||
puts "Loading tree: #{file}"
|
||||
exit unless verify_tree(file)
|
||||
gardner = Planter::Spade.new(YAML.load_file(tree, false))
|
||||
else
|
||||
puts 'Creating a new tree!'
|
||||
gardner = Planter::Spade.new(SKELETON_TREE)
|
||||
end
|
||||
gardner.plant
|
||||
end
|
||||
|
||||
desc 'serve TREE', 'Load TREE in a web-based interface'
|
||||
def serve(tree)
|
||||
exit unless verify_tree(tree)
|
||||
puts 'Sinatra will be cool.'
|
||||
end
|
||||
|
||||
desc 'export TREE', 'Save a portable HTML version of TREE'
|
||||
def export(tree)
|
||||
exit unless verify_tree(tree)
|
||||
puts 'Cool feature, bro!'
|
||||
end
|
||||
end
|
|
@ -1,111 +0,0 @@
|
|||
require_relative './gardner'
|
||||
|
||||
# Dialogue is the module for traversing an existing tree.
|
||||
module Dialogue
|
||||
# Format and display the trunk
|
||||
#
|
||||
# @param trunk [Hash] The trunk hash
|
||||
# @param debug [Boolean] The status of showing debug information
|
||||
def self.display_trunk(trunk, debug = false)
|
||||
40.times { print '-' }
|
||||
puts "\n[ Trunk ]\n" if debug
|
||||
puts "\n#{trunk['trunk']}"
|
||||
40.times { print '-' }
|
||||
puts "\n"
|
||||
end
|
||||
|
||||
# Format and display a branch and the options
|
||||
#
|
||||
# @param branch [Hash] A branch data set
|
||||
# @param branch_no [Integer] The branch number
|
||||
# @param debug [Boolean] Status of showing debug information
|
||||
def self.display_branch(branch, branch_no, debug = false)
|
||||
puts "\n[ Branch: #{branch_no} ]" if debug
|
||||
puts "\n#{branch['desc']}\n\n"
|
||||
|
||||
branch['options'].each_pair do |k, v|
|
||||
puts "\t#{k}: #{v.keys[0]}"
|
||||
puts "\t\t[ Goes to branch #{v.values[0]} ]\n" if debug
|
||||
end
|
||||
end
|
||||
|
||||
# Speaker holds the functionality for going through a dialogue tree.
|
||||
class Speaker
|
||||
# The tree, an instance of Gardner::Plot
|
||||
attr_reader :tree
|
||||
# Status of verbose/debug mode. True = on; false = off.
|
||||
attr_reader :debug
|
||||
|
||||
def initialize(tree, debug = false)
|
||||
@tree = tree
|
||||
@debug = debug
|
||||
end
|
||||
|
||||
# Conversation handles navigating the tree, until the option to end is
|
||||
# reached.
|
||||
def conversation
|
||||
Dialogue.display_trunk(@tree.trunk, @debug)
|
||||
|
||||
next_branch = 1
|
||||
until next_branch.zero?
|
||||
next_branch = talk(@tree.branches[next_branch], next_branch)
|
||||
end
|
||||
|
||||
puts "\n#{@tree.branches[0]['desc']}"
|
||||
exit
|
||||
end
|
||||
|
||||
# Talk displays a branch, the options, and prompts for a response.
|
||||
#
|
||||
# @param branch [Hash] A branch data set
|
||||
# @param branch_no [Integer] The branch number
|
||||
# @return [Integer] The number of the next branch
|
||||
def talk(branch, branch_no)
|
||||
return 0 if terminal?(branch)
|
||||
|
||||
Dialogue.display_branch(branch, branch_no, @debug)
|
||||
|
||||
response = get_response(branch)
|
||||
|
||||
unless response.zero?
|
||||
puts "(Your choice: #{branch['options'][response].keys[0]})"
|
||||
response = branch['options'][response].values[0].to_i
|
||||
end
|
||||
|
||||
response
|
||||
end
|
||||
|
||||
# Get a response for the displayed branch
|
||||
#
|
||||
# @param branch [Hash] A branch data set
|
||||
# @return [Integer] the next branch
|
||||
def get_response(branch)
|
||||
valid_options = branch['options'].keys.join(', ')
|
||||
|
||||
print "\n[#{valid_options}]> "
|
||||
STDOUT.flush
|
||||
response = STDIN.gets.chomp
|
||||
|
||||
until valid_options.include?(response) || response.to_i.zero?
|
||||
print "[## Invalid options. Valid options are #{valid_options}," \
|
||||
"or 0 to exit.\n[#{valid_options}]> "
|
||||
response = STDIN.gets.chomp
|
||||
end
|
||||
|
||||
response.to_i
|
||||
end
|
||||
|
||||
# Check if a branch is terminal
|
||||
#
|
||||
# @param branch [Hash] A branch data set
|
||||
# @return [Boolean] true if the branch is terminal, false otherwise
|
||||
def terminal?(branch)
|
||||
if branch['options'].empty?
|
||||
puts "\n#{branch['desc']}\n\n"
|
||||
return true
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,96 +0,0 @@
|
|||
require 'yaml'
|
||||
|
||||
# Gardner is the module for working with a dialogue tree file
|
||||
module Gardner
|
||||
# The Plot class handles a specific tree file. It provides functionality for
|
||||
# parsing trunks and branches, and provides these as class attributes.
|
||||
class Plot
|
||||
# The trunk and branches instance variables
|
||||
attr_reader :branches, :tree, :trunk
|
||||
|
||||
# Initialize a new Plot from a tree file
|
||||
#
|
||||
# @param tree [File] The dialogue tree file
|
||||
def initialize(file)
|
||||
@tree = file
|
||||
prune_trunk
|
||||
prune_branches
|
||||
end
|
||||
|
||||
# Parse the tree array into an array of numbered branches, and ordered
|
||||
# leaves.
|
||||
#
|
||||
# @param tree [File] The dialogue tree
|
||||
# @return [Array] An array of numbered branches, with numbered leaves
|
||||
def prune_branches
|
||||
@branches = { 0 => { 'desc' => 'Thanks for using Sapling!' } }
|
||||
@tree.each do |b|
|
||||
@branches[b['branch']['number']] = {
|
||||
'desc' => b['branch']['text'],
|
||||
'options' => prune_leaves(b['branch']['leaf'])
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the leaves of a branch into a numbered hash of options.
|
||||
#
|
||||
# @param leaves [Array] The option of leaf hashes
|
||||
# @return [Hash] A numbered hash of options
|
||||
def prune_leaves(leaves)
|
||||
x = 1
|
||||
options = {}
|
||||
|
||||
return options if leaves.nil?
|
||||
|
||||
leaves.each do |l|
|
||||
options[x] = { l['text'] => l['branch'] }
|
||||
x += 1
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
# Parse the trunk of the tree.
|
||||
#
|
||||
# @return [Array] The trunk, and the remainder of the tree
|
||||
def prune_trunk
|
||||
@trunk = @tree.shift
|
||||
end
|
||||
end
|
||||
|
||||
# Digiplot represents a Plot used for editing. The Digiplot functions exactly
|
||||
# like a Plot, except with additional functionality for over-writing existing
|
||||
# branches, leaves, and the trunk.
|
||||
class Digiplot < Plot
|
||||
# Duplicate the "old" trunk and branches, for restoration purposes
|
||||
attr_reader :old_branches, :old_trunk
|
||||
|
||||
# Enable editing for the trunk
|
||||
attr_writer :trunk
|
||||
|
||||
# Initialize a Digiplot just like a Plot, but also copy the trunk and
|
||||
# branches to "old" instance variables.
|
||||
def initialize
|
||||
super
|
||||
@old_trunk = @trunk
|
||||
@old_branches = @branches
|
||||
end
|
||||
|
||||
# Change a branch
|
||||
#
|
||||
# @param branch [Integer] the number of the branch to be edited
|
||||
def branch=(branch, text)
|
||||
@branches[branch]['desc'] = text
|
||||
end
|
||||
|
||||
# Change a leaf on a branch, grasshopper
|
||||
#
|
||||
# @param branch [Integer] the number of the branch to be edited
|
||||
# @param leaf [Integer] the number of the leaf to be edited
|
||||
# @param text [String] the new text for the leaf
|
||||
# @param target [Integer] the branch number target for the leaf option
|
||||
def leaf=(branch, leaf, text, target)
|
||||
@branches[branch]['options'][leaf] = { text => target }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,210 +0,0 @@
|
|||
require_relative './dialogue'
|
||||
require_relative './gardner'
|
||||
require_relative './utility'
|
||||
|
||||
# Planter is the module for creating or editing a tree.
|
||||
module Planter
|
||||
|
||||
# In-memory tree
|
||||
class Plot
|
||||
|
||||
# The tree, trunk, and branches
|
||||
attr_accessor :tree, :trunk, :branches
|
||||
|
||||
# Edit the trunk of the tree
|
||||
def edit_trunk
|
||||
puts "Current Trunk:\n"
|
||||
Dialogue.display_trunk(@trunk, true)
|
||||
print "\n[ =EDITING= ](CTRL-C to abort)> "
|
||||
STDOUT.flush
|
||||
begin
|
||||
new_trunk = STDIN.gets.to_s
|
||||
rescue Interrupt
|
||||
puts "\n**Aborting edit**\n\n"
|
||||
new_trunk = @trunk["trunk"]
|
||||
end
|
||||
@trunk["trunk"] = new_trunk
|
||||
end
|
||||
|
||||
# Edit a branch on the tree
|
||||
#
|
||||
# @param branch [Integer] The number of the branch to be edited.
|
||||
def edit_branch(branch_no)
|
||||
puts "Current Branch:\n"
|
||||
Dialogue.display_branch(@branches[branch_no], branch_no, true)
|
||||
print "\n[ =EDITING= ](CTRL-C to abort)> "
|
||||
STDOUT.flush
|
||||
begin
|
||||
new_branch = STDIN.gets.to_s
|
||||
rescue Interrupt
|
||||
puts "\n**Aborting edit**\n\n"
|
||||
new_branch = @branches[branch_no]["desc"]
|
||||
end
|
||||
@branches[branch_no]["desc"] = new_branch
|
||||
end
|
||||
|
||||
# Edit a leaf on a branch, grasshopper
|
||||
#
|
||||
# @param branch [Integer] The number of the branch to be edited.
|
||||
# @param leaf [Hash] The leaf hash to be edited.
|
||||
def edit_leaf(branch, leaf)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# Utilities for editing specific parts of a tree.
|
||||
class Spade
|
||||
|
||||
# The file we parse into a tree
|
||||
attr_writer :file
|
||||
|
||||
def initialize(file)
|
||||
@file = file
|
||||
end
|
||||
|
||||
# Establish and populate a new Plot (in-memory tree), then control the flow
|
||||
# of editing the Plot
|
||||
def plant
|
||||
@plot = Plot.new
|
||||
@plot.tree = @file
|
||||
@plot.trunk = @file.shift
|
||||
@plot.branches = Gardner.prune_branches(@file)
|
||||
|
||||
next_branch = dig(1)
|
||||
until next_branch == 0 do
|
||||
next_branch = dig(next_branch)
|
||||
end
|
||||
|
||||
puts "\n#{@plot.branches[0]["desc"]}"
|
||||
exit
|
||||
end
|
||||
|
||||
# Function for displaying a single branch in debug mode. We also always
|
||||
# display the trunk, since otherwise it's displayed a single time then gone
|
||||
# forever (until next time).
|
||||
#
|
||||
# @param branch_no [Integer] The number of the branch to be displayed.
|
||||
def dig(branch_no)
|
||||
branch = @plot.branches[branch_no]
|
||||
|
||||
Dialogue.display_trunk(@plot.trunk, true)
|
||||
Dialogue.display_branch(branch, branch_no, true)
|
||||
|
||||
response = get_response(branch)
|
||||
to_branch = parse_response(response, branch_no)
|
||||
|
||||
return to_branch
|
||||
end
|
||||
|
||||
# Get a response for the displayed branch
|
||||
#
|
||||
# @param branch [Hash] A branch data set
|
||||
# @return [Integer] the next branch
|
||||
def get_response(branch)
|
||||
total_branches = @plot.branches.count - 1
|
||||
valid_options = ["1-#{total_branches}","t","a","b","x","l","s","q"]
|
||||
print_options = valid_options.join(",")
|
||||
|
||||
print "\n[#{print_options}]> "
|
||||
STDOUT.flush
|
||||
response = STDIN.gets.chomp.to_s.downcase
|
||||
|
||||
until valid_options.include?(response) or response.to_i.between?(1,total_branches)
|
||||
print "[## Invalid response. "
|
||||
print "Valid options are #{print_options}"
|
||||
print "\n[#{print_options}]> "
|
||||
response = STDIN.gets.chomp.to_s.downcase
|
||||
end
|
||||
|
||||
return response
|
||||
end
|
||||
|
||||
# Parse the response from get_response
|
||||
#
|
||||
# @param response [String] The option selected
|
||||
# @param branch_no [Integer] The currently-displayed branch
|
||||
# @return [Integer] the branch to display
|
||||
def parse_response(response, branch_no)
|
||||
10.times { print "*" }
|
||||
print "\n(Your choice: "
|
||||
|
||||
if response.to_i >= 1
|
||||
print "Change to branch #{response.to_i})\n\n"
|
||||
return response.to_i
|
||||
|
||||
end
|
||||
|
||||
case response.to_s.downcase
|
||||
when "t"
|
||||
print "Edit the trunk.)\n\n"
|
||||
@plot.edit_trunk
|
||||
return branch_no
|
||||
when "a"
|
||||
print "Add a new branch.)\n\n"
|
||||
return branch_no
|
||||
when "b"
|
||||
print "Edit the current branch.)\n\n"
|
||||
@plot.edit_branch(branch_no)
|
||||
return branch_no
|
||||
when "x"
|
||||
print "Delete the current branch.)\n\n"
|
||||
return branch_no
|
||||
when "l"
|
||||
print "Edit leaves of current branch.)\n\n"
|
||||
return branch_no
|
||||
when "s"
|
||||
print "Save changes.)\n\n"
|
||||
return branch_no
|
||||
when "q"
|
||||
print "Quit without saving.)\n\n"
|
||||
print "Unsaved changes will be lost. Still quit? [y/n]> "
|
||||
verify = STDIN.gets.chomp.to_s.downcase
|
||||
|
||||
return 0 if verify == "y"
|
||||
return branch_no
|
||||
else
|
||||
print "Unknown option. Returning to current branch.)\n\n"
|
||||
return branch_no
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
Process:
|
||||
- User selects to create/edit a tree
|
||||
- If the user presented a file, use it as the tree file
|
||||
- If the user failed to provide a file, create a new tree file in the current directory
|
||||
|
||||
- Check if the file is empty.
|
||||
- If so, assume a new tree
|
||||
- If not, verify formatting
|
||||
|
||||
- If new tree, prompt for trunk
|
||||
- If existing tree, display trunk and first branch
|
||||
|
||||
- At this point, editing is the same
|
||||
- Prompt provides options:
|
||||
- #: Go to that branch number
|
||||
- T: Modify the tree trunk
|
||||
- A: Add a new branch (append to list of branches)
|
||||
- B: Modify the current branch description
|
||||
- X: Delete the current branch (does this renumber branches?)
|
||||
- L: Modify the current leaves, respond with leaf prompt
|
||||
- S: Save changes
|
||||
- Q: Quit
|
||||
|
||||
- Example prompt:
|
||||
[ 0-5,T,A,B,X,L,S,Q ]>
|
||||
- Leaf prompt:
|
||||
|
||||
Details:
|
||||
|
||||
- Regardless of the file existing, the user will be editing a Hash, not the actual YAML file
|
||||
- Use Gardner to build and interact with the tree
|
||||
- Use Planter to modify the tree "in memory" (aka, the hash)
|
||||
- Use Dialog to interact with the tree "in memory", to test-run it
|
||||
- After each edit option, display the current branch with the new changes.
|
||||
|
||||
=end
|
|
@ -1,56 +0,0 @@
|
|||
# Utility functionality for all of Sapling to reference
|
||||
|
||||
# Constants
|
||||
|
||||
# A series of constants for handing a brand new tree. The skeleton tree provides
|
||||
# a very basic introduction to Sapling. More details can be found in the
|
||||
# documentation.
|
||||
|
||||
# The default trunk text of a new tree
|
||||
SKELE_TRUNK_TEXT = 'Welcome to the Sapling Editor. For details, please see the
|
||||
documentation!'.freeze
|
||||
|
||||
# The default first-branch text of a new tree
|
||||
SKELE_BRANCH_TEXT = 'The first branch is always shown by default. It should act
|
||||
as the introduction to the story. From here, the user enters your world!'.freeze
|
||||
|
||||
# The default first-leaf text of the first branch of a new tree. The leaf points
|
||||
# to it's own branch. The only way out of the program is to either force-quit or
|
||||
# reply with option 0.
|
||||
SKELE_LEAF_TEXT = 'Each branch can have any number of leaves, which represent
|
||||
the options a user has on that branch. Each leaf points to another branch, or
|
||||
can point to branch 0 to immediately exit.'.freeze
|
||||
|
||||
# The final tree
|
||||
SKELETON_TREE = [
|
||||
{ 'trunk' => SKELE_TRUNK_TEXT.to_s },
|
||||
{ 'branch' => {
|
||||
'number' => 1,
|
||||
'text' => SKELE_BRANCH_TEXT.to_s,
|
||||
'leaf' => [{
|
||||
'text' => SKELE_LEAF_TEXT.to_s,
|
||||
'branch' => 1
|
||||
}]
|
||||
} }
|
||||
].freeze
|
||||
|
||||
# Verify that a file is a dialogue tree file.
|
||||
#
|
||||
# @param file [File] The provided file
|
||||
# @return [Boolean] True if the file is a tree; false otherwise
|
||||
def verify_tree(file)
|
||||
results = []
|
||||
begin
|
||||
tree = YAML.load_file(file)
|
||||
results << tree[0].keys.include?('trunk')
|
||||
results << tree[1]['branch'].keys.include?('number')
|
||||
results << tree[1]['branch'].keys.include?('text')
|
||||
results << tree[1]['branch'].keys.include?('leaf')
|
||||
rescue
|
||||
puts "Sorry chummer, I don't think this is a tree."
|
||||
puts 'Verify your YAML file is formatted properly.'
|
||||
results << false
|
||||
end
|
||||
|
||||
results.include?(false) ? false : true
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
Gem::Specification.new do |s|
|
||||
s.name = 'sapling-dialogue'
|
||||
s.version = '0.1.2'
|
||||
s.executables << 'sapling'
|
||||
s.date = '2017-10-19'
|
||||
s.summary = 'A Dialogue Tree Utility'
|
||||
s.description = 'Create, edit, and traverse dialogue trees'
|
||||
s.authors = ['Bill Niblock']
|
||||
s.email = 'azulien@gmail.com'
|
||||
s.files = Dir['lib/**/*.rb'] + Dir['bin/*']
|
||||
s.homepage = 'http://www.theinternetvagabond.com/sapling/'
|
||||
s.license = 'MIT'
|
||||
end
|
|
@ -1,66 +0,0 @@
|
|||
<!--
|
||||
# @markup markdown
|
||||
# @title Configuration File
|
||||
-->
|
||||
|
||||
# Configuration File Documentation
|
||||
|
||||
The configuration file for `sapling` is a standard YAML file. The general
|
||||
outline looks something like this:
|
||||
|
||||
---
|
||||
-
|
||||
trunk: "This is a description of the dialogue tree."
|
||||
-
|
||||
branch:
|
||||
number: 1
|
||||
text: "This is the overall text for the branch."
|
||||
leaf:
|
||||
-
|
||||
text: "This is option 1."
|
||||
branch: 2
|
||||
-
|
||||
text: "This is option 2."
|
||||
branch: 3
|
||||
-
|
||||
branch:
|
||||
number: 2
|
||||
text: "This is the overall text for the branch."
|
||||
leaf:
|
||||
-
|
||||
text: "This is option 1."
|
||||
branch: 1
|
||||
-
|
||||
text: "This is option 2."
|
||||
branch: 3
|
||||
-
|
||||
branch:
|
||||
number: 3
|
||||
text: "This is the overall text for the branch."
|
||||
|
||||
## Outline
|
||||
|
||||
#### Trunk
|
||||
|
||||
The `trunk` is a metadata list. Currently, the only information we really care
|
||||
about is a general description for the tree. Because of this, `trunk` is the
|
||||
key, and the description is the value.
|
||||
|
||||
#### Branch
|
||||
|
||||
Branches are the content of a dialogue tree. Each `branch` has the following
|
||||
options:
|
||||
|
||||
- `number`: The branch number. This is how leaves get around. It must be unique.
|
||||
- `text`: The text provided by getting to this branch. The first branch is shown
|
||||
by default when the tree is opened.
|
||||
- `leaf`: [Optional] The list of options for the branch. Details for leaves are
|
||||
below. If no leaves are provided, the branch is considered a "terminal
|
||||
branch", and the program will end after reaching it.
|
||||
|
||||
#### Leaf
|
||||
|
||||
Leaves are the options of a branch. Each `leaf` has the following options:
|
||||
|
||||
- `text`: The text shown as the option.
|
||||
- `branch`: The branch this option takes the user to.
|
|
@ -1,42 +0,0 @@
|
|||
<!--
|
||||
# @markup markdown
|
||||
# @title Example YAML File
|
||||
-->
|
||||
# Example Dialogue Tree
|
||||
---
|
||||
# The trunk is a general introduction to the tree. It shouldn't include any
|
||||
# thematic details, rather a one-liner to let the user know what they're getting
|
||||
# into.
|
||||
-
|
||||
trunk: "This is a general introduction to the dialogue tree."
|
||||
|
||||
# Branches are the content of a dialogue tree. Each branch is numbered, and that
|
||||
# number is used as the primary means of navigation. The text of a branch is the
|
||||
# story provided to the user; the result of getting to the branch. The leaves
|
||||
# (the section titled leaf) represent the options. Options are displayed in the
|
||||
# order they appear. Within a leaf, the text is what the option says, and the
|
||||
# branch is the branch number which this option will lead to. Leading to branch
|
||||
# number 0 will immediately exit the program.
|
||||
#
|
||||
# You can have as many branches and leaves as you wish, though having too many
|
||||
# leaves may lead to both display problems, and paralyzing indecision.
|
||||
-
|
||||
branch:
|
||||
number: 1
|
||||
text: "The first branch. Displayed first, by default."
|
||||
leaf:
|
||||
-
|
||||
text: "The first option for this branch. It leads to branch 2"
|
||||
branch: 2
|
||||
-
|
||||
text: "The second branch. It immediately exits the program."
|
||||
branch: 0
|
||||
|
||||
# A terminal branch is a branch which has no leaves. This represents an ending.
|
||||
# Once a user hits a terminal branch, the program will display the branch text,
|
||||
# and then redirect the user to branch 0, to exit.
|
||||
-
|
||||
branch:
|
||||
number: 2
|
||||
text: "This is a terminal branch. After displaying this text,
|
||||
the program will exit."
|
|
@ -1,37 +0,0 @@
|
|||
# @title Example YAML File
|
||||
---
|
||||
# The trunk is a general introduction to the tree. It shouldn't include any
|
||||
# thematic details, rather a one-liner to let the user know what they're getting
|
||||
# into.
|
||||
- trunk: "This is a general introduction to the dialogue tree."
|
||||
|
||||
# Branches are the content of a dialogue tree. Each branch is numbered, and that
|
||||
# number is used as the primary means of navigation. The text of a branch is the
|
||||
# story provided to the user; the result of getting to the branch. The leaves
|
||||
# (the section titled leaf) represent the options. Options are displayed in the
|
||||
# order they appear. Within a leaf, the text is what the option says, and the
|
||||
# branch is the branch number which this option will lead to. Leading to branch
|
||||
# number 0 will immediately exit the program.
|
||||
#
|
||||
# You can have as many branches and leaves as you wish, though having too many
|
||||
# leaves may lead to both display problems, and paralyzing indecision.
|
||||
-
|
||||
branch:
|
||||
number: 1
|
||||
text: "The first branch. Displayed first, by default."
|
||||
leaf:
|
||||
-
|
||||
text: "The first option for this branch. It leads to branch 2"
|
||||
branch: 2
|
||||
-
|
||||
text: "The second branch. It immediately exits the program."
|
||||
branch: 0
|
||||
|
||||
# A terminal branch is a branch which has no leaves. This represents an ending.
|
||||
# Once a user hits a terminal branch, the program will display the branch text,
|
||||
# and then redirect the user to branch 0, to exit.
|
||||
-
|
||||
branch:
|
||||
number: 2
|
||||
text: "This is a terminal branch. After displaying this text,
|
||||
the program will exit."
|
|
@ -1,16 +0,0 @@
|
|||
<!--
|
||||
# @markup markdown
|
||||
# @title Using the Editor
|
||||
-->
|
||||
# Sapling Editor
|
||||
|
||||
Sapling provides an editor for creating and modifying dialogue trees. The editor
|
||||
allows for editing all parts of a tree, from the trunk to the leaves.
|
||||
|
||||
## Creating a new tree
|
||||
|
||||
Pending
|
||||
|
||||
## Editing an existing tree
|
||||
|
||||
Pending
|
|
@ -1,74 +0,0 @@
|
|||
---
|
||||
- trunk: "Example Quest: Learn what it looks like to use Sapling!"
|
||||
|
||||
-
|
||||
branch:
|
||||
number: 1
|
||||
text: "You stumble upon the first branch of a dialogue tree.
|
||||
You find yourself at a junction..."
|
||||
leaf:
|
||||
-
|
||||
text: "Go to the next branch."
|
||||
branch: 2
|
||||
-
|
||||
text: "Go to the frigid north-lands, because there's always a
|
||||
frigid north-lands."
|
||||
branch: 3
|
||||
-
|
||||
text: "Leave this silly place, but with a reason."
|
||||
branch: 5
|
||||
-
|
||||
text: "Leave this silly place immediately, without any reason."
|
||||
branch: 0
|
||||
-
|
||||
branch:
|
||||
number: 2
|
||||
text: "Ye find ye-self at branch 2. Your options are north, south
|
||||
or Dennis."
|
||||
leaf:
|
||||
-
|
||||
text: "North, to frigidity!"
|
||||
branch: 3
|
||||
-
|
||||
text: "South, back the way you came!"
|
||||
branch: 1
|
||||
-
|
||||
text: "Dennis"
|
||||
branch: 6
|
||||
-
|
||||
branch:
|
||||
number: 3
|
||||
text: "It's cold up here. You decide to go someplace else!"
|
||||
leaf:
|
||||
-
|
||||
text: "Head on home."
|
||||
branch: 4
|
||||
-
|
||||
text: "Head south (back the way you came)"
|
||||
branch: 2
|
||||
-
|
||||
branch:
|
||||
number: 4
|
||||
text: "You head on home! Bye bye!"
|
||||
-
|
||||
branch:
|
||||
number: 5
|
||||
text: "You leave the dialogue tree, and all its textual glory, behind
|
||||
and go find a nice GUI to settle down with."
|
||||
-
|
||||
branch:
|
||||
number: 6
|
||||
text: "Dennis appreciates your interest, but is really just trying to
|
||||
hangout and play video games."
|
||||
leaf:
|
||||
-
|
||||
text: "Join Dennis, and play video games with him."
|
||||
branch: 7
|
||||
-
|
||||
text: "Reconsider your options."
|
||||
branch: 2
|
||||
-
|
||||
branch:
|
||||
number: 7
|
||||
text: "You sit down next to Dennis, and together you conquer all sorts of
|
||||
realms and wizards and stuff. Nice!"
|
Loading…
Reference in a new issue