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:
parent
bdc101a6db
commit
707d5692cb
|
@ -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
|
||||
|
|
36
output.py
36
output.py
|
@ -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)
|
||||
|
|
110
paragraphs.py
110
paragraphs.py
|
@ -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):
|
||||
|
|
43
readme.org
43
readme.org
|
@ -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
14
test.gamebook
Normal 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.
|
||||
|
18
test.json
18
test.json
|
@ -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
10
test.sh
|
@ -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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue