1
0
Fork 0
mirror of https://github.com/Oreolek/gamebookformat.git synced 2024-06-16 15:10:45 +03:00

Switched from JSON to simpler format.

Code is a bit of a mess at the moment. Might have to generate some JSON
later anyway to make it easier to make playable game in browser.
This commit is contained in:
Pelle Nilsson 2013-05-30 00:18:05 +02:00
parent bdc101a6db
commit 707d5692cb
7 changed files with 91 additions and 170 deletions

View file

@ -50,6 +50,7 @@ OUTPUT_FORMATS = [LatexFormat(),
HtmlFormat(),
DebugFormat()]
def make_supported_formats_list_string():
return "Supported Output Formats:\n" + "\n".join(
[str(f) for f in OUTPUT_FORMATS])
@ -62,21 +63,34 @@ def format_gamebook(inputfilenames, outputfilename):
output_format.write(book, open(outputfilename, 'w'))
def parse_file_to_book(inputfile, book):
for name,contents in json.load(inputfile).iteritems():
paragraph = paragraphs.Paragraph(name)
if 'text' in contents:
paragraph.addtext(contents['text'])
if 'number' in contents:
book.add(paragraph, contents['number'])
name = None
number = None
text = ""
for line in inputfile.readlines():
if line.startswith('*'):
if name:
book.add(paragraphs.Paragraph(name, text), number)
number = None
text = ""
heading = line[1:].strip().split(' ')
if len(heading) == 1:
name = heading[0]
elif len(heading) == 2:
number = int(heading[0])
name = heading[1]
else:
raise Exception("bad paragraph heading %s" % str(heading))
else:
book.add(paragraph)
text = text + " " + line.strip()
if name:
book.add(paragraphs.Paragraph(name, text), number)
def find_output_format(outputfilename):
for of in OUTPUT_FORMATS:
if of.supports(outputfilename):
return of
raise Exception("Unsupported or unknown output format for %s."
% outputfile)
% outputfilename)
if __name__ == '__main__':
import argparse

View file

@ -2,8 +2,6 @@ import os
import os.path
import sys
from paragraphs import paragraph_refs_format
class OutputFormat (object):
def __init__(self, extension, name):
self.extension = extension
@ -29,19 +27,13 @@ class OutputFormat (object):
def write_paragraph(self, paragraph, shuffled_paragraphs, output):
refs = []
def paragraph_link_render(to_paragraph, shuffled_paragraphs):
s = self.load_template("paragraph_ref") % {
'nr' : shuffled_paragraphs.to_nr[to_paragraph],
'from_nr' : shuffled_paragraphs.to_nr[paragraph]
}
refs.append(s)
return s
formatted_text = paragraph.format(shuffled_paragraphs,
paragraph_link_render)
refsdict = ReferenceFormatter(paragraph, shuffled_paragraphs,
self.load_template("paragraph_ref"))
formatted_text = paragraph.format(refsdict)
print >> output, self.load_template("paragraph") % {
'nr' : shuffled_paragraphs.to_nr[paragraph],
'text' : formatted_text,
'refs' : '\n'.join(refs) # hack for DOT output reallyn
'refs' : '\n'.join(refsdict.getfound()) # hack for DOT output
},
def write_end(self, book, output):
@ -64,3 +56,23 @@ class OutputFormat (object):
self.cached_templates[name] = template
return template
class ReferenceFormatter (object):
"There is probably a better way, but this hack seems to work."
def __init__(self, paragraph, shuffled_paragraphs, ref_template):
self.paragraph = paragraph
self.shuffled_paragraphs = shuffled_paragraphs
self.found = set()
self.ref_template = ref_template
def __getitem__(self, key):
to_paragraph = self.shuffled_paragraphs.from_name[key]
res = self.ref_template % {
'nr' : self.shuffled_paragraphs.to_nr[to_paragraph],
'from_nr' : self.shuffled_paragraphs.to_nr[self.paragraph]
}
if key in self.shuffled_paragraphs.name_to_nr:
self.found.add(res)
return res
def getfound(self):
return list(self.found)

View file

@ -1,116 +1,16 @@
#!/usr/bin/env python2.5
import random
import sys
def paragraph_refs_format(s,
refs,
shuffled=None,
render_callback=None,
bad_callback=None):
"""
render_callback, if set, must be a function accepting a paragraph name
and a ShuffledParagraphs object. It must return a string formatting
of a link to that reference. Its use is for instance if you render
the paragraphs to HTML you can return a HTML link. It will only be
used if format %c is used.
bad_callback, if set, must be a function accepting a paragraph
name and a ShuffledParagraphs object. It may attempt to construct
a new Paragraph object standing in for a missing paragraph, if there
is a way to automatically construct some paragraphs in the game.
If it can not construct a paragraph it should return None or False
which will cause the formatting to fail and raise an exception.
"""
oi = 0
next_ref = 0
res = ''
i = s.find('%')
while i >= 0:
res = res + s[oi:i]
skip = 0
code = s[i+1]
if code == '%':
res += '%'
else:
if code == '(':
ei = s.find(')', i+1)
if ei < 0:
raise "bad format, missing ) after %("
ref = s[i+2:ei]
skip = len(ref) + 2
code = s[ei+1]
else:
ref = refs[next_ref]
if type(ref) in set([str, unicode]):
if ref in shuffled.from_name:
ref = shuffled.from_name[ref]
elif bad_callback:
created_ref = bad_callback(ref, shuffled)
if not created_ref:
raise "bad reference " + ref
ref = created_ref
if code == 'n':
res += str(shuffled.to_nr[ref])
elif code == 'c':
if render_callback:
res += render_callback(ref, shuffled)
else:
res += str(ref)
elif code == 's':
res += str(ref.name)
elif code == 'r':
res += repr(ref.name)
next_ref = next_ref + 1
oi = i + 2 + skip
i = s.find('%', oi)
return res + s[oi:]
class ParagraphItem:
def __init__(self, text, refs=None, title=None):
self.text = text
self.title = title
if refs:
self.refs = refs
else:
self.refs = []
def __repr__(self):
return "ParagraphItem(%s, %s, %s)" % (self.text.__repr__(),
self.refs.__repr__(),
self.title.__repr__())
def format(self, shuffled=None, render_callback=None, bad_callback=None):
return paragraph_refs_format(self.text, self.refs, shuffled, render_callback,
bad_callback)
class Paragraph:
def __init__(self, name, text=None, refs=None, items=None):
def __init__(self, name, text):
self.name = name
if text:
self.text = text
else:
self.text = ''
if items:
self.items = items
else:
self.items = []
if refs:
self.refs = refs
else:
self.refs = []
self.text = text
def __repr__(self):
return "Paragraph(%s, %s, %s, %s)" % (self.name.__repr__(),
self.text.__repr__(),
self.refs.__repr__(),
self.items.__repr__())
def addtext(self, moretext):
self.text = self.text + moretext
return "Paragraph(%s, %s)" % (repr(self.name), repr(self.text))
def format(self, shuffled=None, render_callback=None, bad_callback=None):
return paragraph_refs_format(self.text, self.refs, shuffled, render_callback,
bad_callback)
def format(self, references):
return self.text % references
class ShuffledParagraphs:
def __init__(self, as_list, from_nr, to_nr, from_name):

View file

@ -3,6 +3,27 @@
A tool to format [[http://www.gamebooks.org/][gamebooks]] into various formats useful for playing the
gamebook on paper or a screen (or for debugging it).
** Supported Output Formats
| Name | Extension | Description |
|------------------+-----------+-------------------------------------------------------------------------------------------------|
| LaTeX | .tex | Useful to generate PDFs using pdflatex or whatever LaTeX tools you prefer. |
| Rich Text Format | .rtf | Supported because the Windhammer Prize requires it. |
| Graphviz DOT | .dot | Use with the Graphviz dot tool to generate a flowchart graph of all paragraphs in the gamebook. |
| HTML | .html | Play gamebook in browser. |
| Debug Plain Text | .debug | Plain text debug output of gamebook contents. |
More to be added.
** Gamebook Format
The input file expected by the formatgamebook.py script must be in a
format containing information about all paragraphs in the book
plus some optional metadata. The format should (when TBD) be documented
here, but it is not expected that most users would ever have to look
at the gamebook file, but rather use a higher level format or a
GUI tool.
** License
Copyright (c) 2013, Pelle Nilsson
@ -31,25 +52,3 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
** Supported Output Formats
| Name | Extension | Description |
|------------------+-----------+-------------------------------------------------------------------------------------------------|
| LaTeX | .tex | Useful to generate PDFs using pdflatex or whatever LaTeX tools you prefer. |
| Rich Text Format | .rtf | Supported because the Windhammer Prize requires it. |
| Graphviz DOT | .dot | Use with the Graphviz dot tool to generate a flowchart graph of all paragraphs in the gamebook. |
| HTML | .html | Play gamebook in browser. javascript to make fully playable not yet implemented. |
| Debug Plain Text | .debug | Plain text debug output of gamebook contents. |
More to be added.
** JSON Gamebook Format
The input file expected by the formatgamebook.py script must be in a
JSON format containing information about all paragraphs in the book
plus some optional metadata. The format should (TBD) be documented
here, but it is not expected that most users would ever have to look
at the gamebook JSON file, but rather use a higher level format or a
GUI tool.

14
test.gamebook Normal file
View file

@ -0,0 +1,14 @@
*1 start
This is where the adventure begins. You can go on to the
next paragraph, see %(next)s or try the other instead, see %(other)s.
*next
This is the next paragraph. Go on to the end at %(end)s.
*other
This is another paragraph. You can try the next paragraph now,
see %(next)s, or go on to the end, see %(end)s.
*end
The end.

View file

@ -1,18 +0,0 @@
{
"start" : {
"text" : "This is where the adventure begins. You can go on to the next paragraph, see %(next)c or try the other instead, see %(other)c.",
"number" : 1
},
"next" : {
"text" : "This is the next paragraph. Go on to the end at %(end)c."
},
"other" : {
"text" : "This is another paragraph. You can try the next paragraph now, see %(next)c, or go on to the end, see %(end)c."
},
"end" : {
"text" : "The end."
}
}

10
test.sh
View file

@ -1,18 +1,18 @@
#!/bin/sh
./formatgamebook.py test.json test.debug
./formatgamebook.py test.gamebook test.debug
cat test.debug
./formatgamebook.py test.json test.dot
./formatgamebook.py test.gamebook test.dot
dot -Tpng test.dot > test.png && open test.png
./formatgamebook.py test.json test.tex
./formatgamebook.py test.gamebook test.tex
pdflatex test.tex && open test.pdf
./formatgamebook.py test.json test.html
./formatgamebook.py test.gamebook test.html
open test.html
./formatgamebook.py test.json test.rtf
./formatgamebook.py test.gamebook test.rtf
open test.rtf