Skip to content

Latest commit

 

History

History
218 lines (157 loc) · 8.07 KB

README.markdown

File metadata and controls

218 lines (157 loc) · 8.07 KB

Reader Beware

Reader Beware is a set of cli tools for creating gamebooks. Gamebooks are typically works of fiction written in the 2nd person which offers the reader choices throughout the book which affects how the story moves forward. Often times these are referred to Choose Your Own Adventure novels.

Historically CYOA novels have involved each branching path being hand written and printed to physical book. Modern tools like Twine and ChoiceScript offer the ability to maintain complex state throughout the story and use it to change how portions of the story unfold further down the line but only work on phones and computers using special software/browsers. ChoiceScript ultimately makes application that works similar to a book but Twine has the ability to make complex multimedia experiences.

Ultimately both Twin and ChoiceScript are designed to build dynamic books and work in the browser or require custom software to run.

With Reader Beware I wanted to find a way to do stories as complex as a Twine game but that had the persistence and UI of a book while also being able to be run on any ebook reader, browser, or even in theory printed to a book(sometimes a impossibly long book though).

Syntax Overview

It has a simple syntax which can be quickly learned but is also very powerful in terms of ability to change state. The language consists of a yaml file with narrative sections generated by jinja2 templates which generate markdown. Each a version of each section is then compiled into a different chapter of the ebook.

A simple example is as follows

---
entrypoint:
  body: |
    This is your opening page.

    [go left]({{ 'left'|explore }})

    [go right]({{ 'right'|explore }})

left:
  body: |
    This is going left

right:
  body: |
    This is going right

Each book must have a entrypoint which marks the first page of the book. Each narative section has a unique name which other sections can link to. In the example above the book opens with a page containing the text 'This is your opening page.' with two links at the bottom 'go left' and 'go right' each which will take you to different sections. This example works the same a normal CYOA novel.

Looking in the syntax at the top level is Yaml and for our purposes the file just needs to start with --- on the first like and each section looks like

section_name:
  body: |
    Markdown text that will appear on page.

The body of each narative section is Markdown templated using jinja2. From the example above you can see that two newlines is a paragraph and a link is formatted like [display text](link url)

The {{ }} syntax is jinja2 way of saying evaluate the variables and print them. In this case 'left'|explore takes the string left and creates a link to the left page and passes down the current state of the "world".

Here is an exmple sets global "world" variables and then uses then further down the line in the story.

---
entrypoint:
  body: |
    This is your opening page.

    [put on red shirt]({{ 'put-on-shirt'|choice(shirt_color='red') }})

    [put on green shirt]({{ 'put-on-shirt'|choice(shirt_color='green') }})

put-on-shirt:
  body: |
    You put on the {{ shirt_color }} shirt.

    [And go outside]({{ 'go-outside'|explore }})

go-outside:
  body: |
    Outside you see Jane and she says "{% if shirt_color== 'green' %}I like your green shirt very much.{% else %}I dislike that color on you.{% endif %}."

You can see that like explore choice takes in a section name but in this case it updates the work with the variables set as arguements. This world state is accessable in all future sections. If a variable isn't set it returns 'None' to a the template.

In the go outside section you can see an example of of a if and else statement. For more about Markdown or Jinja2 please see its documentation directly.

Install instructions

In a Python 3.5+ environment(untested in python less than that). Currently its not on pypi so install from github.

This has been tested in linux and works fine. Maybe it works in Windows but if you use it and it fails just make an issue and I'll try and get fix any bugs.

pip install -e git+https://github.com/glassresistor/reader-beware.git

Running commands

To see the most up to date instructions run

beware --help

To build html files designed primarily for debugging run this.

beware build-html --narative-path narative.yaml --output output_folder

Once it runs you can open your browser to file://path_to_folder/entrypoint-{}.html and it will be the first page.

To build epub files run the below command. This will create both an epub file and a folder with the epub files unzipped with the same name.

beware build-epub --narative-path narative.yaml --output output_file

Acfter this I typically use Calibre to view the epub file and use it to create a mobi file and transfer it to my Kindle but it should work for any ebook reader that Calibre works with or accepts epub/mobi files.

Other Examples

The Square

This book creates a -100 by 100 grid maze with. In the maze only one room exits the maze and many rooms will kill you as soon as you enter them.

It takes about 5-10min to run and create ~22,000 sections. Each section is named go-{ x: -100:100, y: -100:100 }. It would create 4002 rooms but a number of areas are surrounded by kill rooms and so those sections are not accessible and so are never generated.

---
entrypoint:
  body: |
    Your dropped off on the roof of a huge square maze.

    Your scared and hungry and the only way down is through a hole in the roof.

    [go down]({{ 'go'|choice(x=0, y=0) }})
go:
  body: |
    You enter a room with four doors with the numbers {{ x }},{{ y }} on the floor.
    {% if x+y in [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97] %}
    Monsters and horrible machines eat you!

    Then End
    {% else %}
    {% if x == 42 and y == 69 %}
    [Exit]({{ 'exit'|explore  }}) the room through a hole in the floor.
    {% endif %}
    {% if x > -100 %}
    [left]({{ 'go'|choice(x=x-1, y=y) }})
    {% endif %}
    {% if x < 100 %}
    [right]({{ 'go'|choice(x=x+1, y=y) }})
    {% endif %}
    {% if y < 100 %}
    [up]({{ 'go'|choice(x=x, y=y+1) }})
    {% endif %}
    {% if y > -100 %}
    [down]({{ 'go'|choice(x=x, y=y-1) }})
    {% endif %}
    {% endif %}
exit:
  body: |
    You survive!

    The end!

Infinite Loop

Beware will not create the same section more than once but its still possible to create infinite loops for the reader.

This example with allow the user to loop forever but will only consist of two sections linking back to each other.

---
entrypoint:
  body: |
    [entrypoint]({{ 'loop'|explore }})
loop:
  body: |
    [loop]({{ 'loop'|explore }})

Beware can be made to run forever and produce an infinitely large book by incrementing(or appending) to a variable without building in a breakpoint. The below example will fill up your harddrive if you don't stop it.

---
entrypoint:
  body: |
    [entrypoint]({{ 'loop'|choice(value=0) }})
loop:
  body: |
    [loop]({{ 'loop'|choice(value=value+1) }})

If you do want to make a loop that increments or do incrementing in general with a large story that will naturally loop then put in switches into the templates which break the loop. Like so

---
entrypoint:
  body: |
    [entrypoint]({{ 'loop'|choice(value=0) }})
loop:
  body: |
    {% if value<10 %}
    [loop]({{ 'loop'|choice(value=value+1) }})
    {% endif %}

TODO

  • Generate mobi files directly
  • Remove underline from link formatting on Kindle
  • Add config file for ebook title, description, etc.
  • Add cover options
  • Add html templates for copyright/etc. pages
  • Add dead pages between sections
  • Add css to html for dev and production purposes which make it look better than default html
  • Add tests
  • Make jinja2 filters and markdown2's behaviour plugable
  • Work on compressing large ass files.
  • Make tiny webapp that dyanamically makes sections on load and reloads yaml files on save.
  • Move to folder of yaml files? How to merge? Namespacing?
  • Codify book folder structure?