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

Use term section instead of paragraph.

Because it will become confusing later when there is support
for sections split up in several paragraphs otherwise.
This commit is contained in:
Pelle Nilsson 2013-06-03 21:57:55 +02:00
parent 81f27d0648
commit 5d42472385
20 changed files with 171 additions and 172 deletions

View file

@ -33,7 +33,7 @@ import os.path
import sys
import json
import paragraphs
import sections
from output import OutputFormat
from latex import LatexFormat
@ -57,7 +57,7 @@ def make_supported_formats_list_string():
def format_gamebook(inputfilenames, outputfilename):
output_format = find_output_format(outputfilename)
book = paragraphs.Book()
book = sections.Book()
for inputfilename in inputfilenames:
parse_file_to_book(open(inputfilename, 'r'), book)
output_format.write(book, open(outputfilename, 'w'))
@ -69,7 +69,7 @@ def parse_file_to_book(inputfile, book):
for line in inputfile.readlines():
if line.startswith('*'):
if name:
book.add(paragraphs.Paragraph(name, text), number)
book.add(sections.Section(name, text), number)
number = None
text = ""
heading = line[1:].strip().split(' ')
@ -79,11 +79,11 @@ def parse_file_to_book(inputfile, book):
number = int(heading[0])
name = heading[1]
else:
raise Exception("bad paragraph heading %s" % str(heading))
raise Exception("bad section heading %s" % str(heading))
else:
text = text + " " + line.strip()
if name:
book.add(paragraphs.Paragraph(name, text), number)
book.add(sections.Section(name, text), number)
def find_output_format(outputfilename):
for of in OUTPUT_FORMATS:

View file

@ -13,7 +13,7 @@ class OutputFormat (object):
def write(self, book, output):
self.write_begin(book, output)
self.write_shuffled_paragraphs(book.shuffle(), output)
self.write_shuffled_sections(book.shuffle(), output)
self.write_end(book, output)
def write_begin(self, book, output):
@ -21,17 +21,17 @@ class OutputFormat (object):
'max' : book.max
},
def write_shuffled_paragraphs(self, shuffled_paragraphs, output):
for p in shuffled_paragraphs.as_list[1:]:
self.write_paragraph(p, shuffled_paragraphs, output)
def write_shuffled_sections(self, shuffled_sections, output):
for p in shuffled_sections.as_list[1:]:
self.write_section(p, shuffled_sections, output)
def write_paragraph(self, paragraph, shuffled_paragraphs, output):
def write_section(self, section, shuffled_sections, output):
refs = []
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],
refsdict = ReferenceFormatter(section, shuffled_sections,
self.load_template("section_ref"))
formatted_text = section.format(refsdict)
print >> output, self.load_template("section") % {
'nr' : shuffled_sections.to_nr[section],
'text' : formatted_text,
'refs' : '\n'.join(refsdict.getfound()) # hack for DOT output
},
@ -58,19 +58,19 @@ class OutputFormat (object):
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
def __init__(self, section, shuffled_sections, ref_template):
self.section = section
self.shuffled_sections = shuffled_sections
self.found = set()
self.ref_template = ref_template
def __getitem__(self, key):
to_paragraph = self.shuffled_paragraphs.from_name[key]
to_section = self.shuffled_sections.from_name[key]
res = self.ref_template % {
'nr' : self.shuffled_paragraphs.to_nr[to_paragraph],
'from_nr' : self.shuffled_paragraphs.to_nr[self.paragraph]
'nr' : self.shuffled_sections.to_nr[to_section],
'from_nr' : self.shuffled_sections.to_nr[self.section]
}
if key in self.shuffled_paragraphs.name_to_nr:
if key in self.shuffled_sections.name_to_nr:
self.found.add(res)
return res

View file

@ -1,61 +0,0 @@
import random
import sys
class Paragraph:
def __init__(self, name, text):
self.name = name
self.text = text
def __repr__(self):
return "Paragraph(%s, %s)" % (repr(self.name), repr(self.text))
def format(self, references):
return self.text % references
class ShuffledParagraphs:
def __init__(self, as_list, from_nr, to_nr, from_name):
self.as_list = as_list
self.from_nr = from_nr
self.to_nr = to_nr
self.from_name = from_name
self.name_to_nr = {}
for n in from_name:
self.name_to_nr[n] = to_nr[from_name[n]]
class Book:
def __init__(self):
self.paragraphs = []
self.nr_paragraphs = {}
self.max = 0
def add(self, paragraph, nr=None):
self.paragraphs.append(paragraph)
if len(self.paragraphs) > self.max:
self.max = len(self.paragraphs)
if nr:
self.nr_paragraphs[nr] = paragraph
if nr > self.max:
self.max = nr
def shuffle(self):
as_list = [None]
from_nr = {}
to_nr = {}
from_name = {}
shuffled = self.paragraphs[:]
for p in self.nr_paragraphs.values():
shuffled.remove(p)
random.shuffle(shuffled)
for nr in range(1, self.max + 1):
if self.nr_paragraphs.has_key(nr):
paragraph = self.nr_paragraphs[nr]
elif len(shuffled):
paragraph = shuffled.pop()
else:
paragraph = None
as_list.append(paragraph)
from_nr[nr] = paragraph
if paragraph:
to_nr[paragraph] = nr
from_name[paragraph.name] = paragraph
return ShuffledParagraphs(as_list, from_nr, to_nr, from_name)

View file

@ -9,7 +9,7 @@ gamebook on paper or a screen (or for debugging it).
|------------------+-----------+-------------------------------------------------------------------------------------------------|
| 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. |
| Graphviz DOT | .dot | Use with the Graphviz dot tool to generate a flowchart graph of all sections in the gamebook. |
| HTML | .html | Play gamebook in browser. |
| Debug Plain Text | .debug | Plain text debug output of gamebook contents. |
@ -18,7 +18,7 @@ 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
format containing information about all sections 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

61
sections.py Normal file
View file

@ -0,0 +1,61 @@
import random
import sys
class Section:
def __init__(self, name, text):
self.name = name
self.text = text
def __repr__(self):
return "Section(%s, %s)" % (repr(self.name), repr(self.text))
def format(self, references):
return self.text % references
class ShuffledSections:
def __init__(self, as_list, from_nr, to_nr, from_name):
self.as_list = as_list
self.from_nr = from_nr
self.to_nr = to_nr
self.from_name = from_name
self.name_to_nr = {}
for n in from_name:
self.name_to_nr[n] = to_nr[from_name[n]]
class Book:
def __init__(self):
self.sections = []
self.nr_sections = {}
self.max = 0
def add(self, section, nr=None):
self.sections.append(section)
if len(self.sections) > self.max:
self.max = len(self.sections)
if nr:
self.nr_sections[nr] = section
if nr > self.max:
self.max = nr
def shuffle(self):
as_list = [None]
from_nr = {}
to_nr = {}
from_name = {}
shuffled = self.sections[:]
for p in self.nr_sections.values():
shuffled.remove(p)
random.shuffle(shuffled)
for nr in range(1, self.max + 1):
if self.nr_sections.has_key(nr):
section = self.nr_sections[nr]
elif len(shuffled):
section = shuffled.pop()
else:
section = None
as_list.append(section)
from_nr[nr] = section
if section:
to_nr[section] = nr
from_name[section.name] = section
return ShuffledSections(as_list, from_nr, to_nr, from_name)

View file

@ -1,2 +1,2 @@
BEGIN DEBUG OUTPUT
Number of paragraphs: %(max)d
Number of sections: %(max)d

View file

@ -1,12 +1,12 @@
*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 section, 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.
This is the next section. Go on to the end at %(end)s.
*other
This is another paragraph. You can try the next paragraph now,
This is another section. You can try the next section now,
see %(next)s, or go on to the end, see %(end)s.
*end

View file

@ -1,76 +0,0 @@
#!/usr/bin/env python2.5
import unittest
from unittest import TestCase
import paragraphs
class TestParagraph(TestCase):
def setUp(self):
pass
def test_create(self):
p = paragraphs.Paragraph("foo")
self.assertEqual(p.name, "foo")
class TestBook(TestCase):
def setUp(self):
pass
def test_create(self):
g = paragraphs.Book()
self.assertEqual(g.paragraphs, [])
self.assertEqual(g.nr_paragraphs, {})
self.assertEqual(g.max, 0)
def test_old_big_mess(self):
"""This was tested using print statements in the old
paragraphs __main__. Not pretty. Keeping it here anyway
as long as it doesn't cause too many problems to update."""
from paragraphs import paragraph_refs_format
g = paragraphs.Book()
c = paragraphs.Paragraph("c", "aaac")
g.add(paragraphs.Paragraph("a", "aaa"))
g.add(paragraphs.Paragraph("b", "aaab"))
g.add(c)
g.add(paragraphs.Paragraph("d", "aaad"), 22)
g.add(paragraphs.Paragraph("e", "aaae"), 1)
g.add(paragraphs.Paragraph("f", "aaaf",
[paragraphs.ParagraphItem("fff")]))
g.add(paragraphs.Paragraph("g", "aaag",
[paragraphs.ParagraphItem("ggg", "G")]))
m = paragraphs.Paragraph("m")
m.addtext("m")
m.addtext("t")
g.add(m)
shuffled = g.shuffle()
self.assertEqual(len(shuffled.as_list), 23)
self.assertEqual(paragraph_refs_format('abc', []), 'abc')
self.assertEqual(paragraph_refs_format('abc%%z', []), 'abc%z')
self.assertEqual(paragraph_refs_format(
'abc%sx',
[paragraphs.Paragraph("p1", "111")]),
'abcp1x')
self.assertEqual(paragraph_refs_format(
'abc%ry', [paragraphs.Paragraph("p2", "222")]),
"abc'p2'y")
self.assertEqual(paragraph_refs_format('%%a%nbc%su', ["f", c],
shuffled),
'%%a%dbccu' % shuffled.name_to_nr["f"])
self.assertEqual(paragraph_refs_format('abc%nu', ["c"], shuffled),
'abc%du' % shuffled.name_to_nr["c"])
self.assertEqual(paragraph_refs_format('%s', [m]),
'm')
self.assertEqual(m.text, 'mt')
def test_name_replace(self):
game = paragraphs.Book()
game.add(paragraphs.Paragraph('foo'))
shuffled = game.shuffle()
self.assertEqual(
'a1b',
paragraphs.paragraph_refs_format('a%(foo)nb', [], shuffled))
if __name__ == '__main__':
unittest.main()

76
test_sections.py Executable file
View file

@ -0,0 +1,76 @@
#!/usr/bin/env python2.5
import unittest
from unittest import TestCase
import sections
class TestSection(TestCase):
def setUp(self):
pass
def test_create(self):
p = sections.Section("foo")
self.assertEqual(p.name, "foo")
class TestBook(TestCase):
def setUp(self):
pass
def test_create(self):
g = sections.Book()
self.assertEqual(g.sections, [])
self.assertEqual(g.nr_sections, {})
self.assertEqual(g.max, 0)
def test_old_big_mess(self):
"""This was tested using print statements in the old
sections __main__. Not pretty. Keeping it here anyway
as long as it doesn't cause too many problems to update."""
from sections import section_refs_format
g = sections.Book()
c = sections.Section("c", "aaac")
g.add(sections.Section("a", "aaa"))
g.add(sections.Section("b", "aaab"))
g.add(c)
g.add(sections.Section("d", "aaad"), 22)
g.add(sections.Section("e", "aaae"), 1)
g.add(sections.Section("f", "aaaf",
[sections.SectionItem("fff")]))
g.add(sections.Section("g", "aaag",
[sections.SectionItem("ggg", "G")]))
m = sections.Section("m")
m.addtext("m")
m.addtext("t")
g.add(m)
shuffled = g.shuffle()
self.assertEqual(len(shuffled.as_list), 23)
self.assertEqual(section_refs_format('abc', []), 'abc')
self.assertEqual(section_refs_format('abc%%z', []), 'abc%z')
self.assertEqual(section_refs_format(
'abc%sx',
[sections.Section("p1", "111")]),
'abcp1x')
self.assertEqual(section_refs_format(
'abc%ry', [sections.Section("p2", "222")]),
"abc'p2'y")
self.assertEqual(section_refs_format('%%a%nbc%su', ["f", c],
shuffled),
'%%a%dbccu' % shuffled.name_to_nr["f"])
self.assertEqual(section_refs_format('abc%nu', ["c"], shuffled),
'abc%du' % shuffled.name_to_nr["c"])
self.assertEqual(section_refs_format('%s', [m]),
'm')
self.assertEqual(m.text, 'mt')
def test_name_replace(self):
game = sections.Book()
game.add(sections.Section('foo'))
shuffled = game.shuffle()
self.assertEqual(
'a1b',
sections.section_refs_format('a%(foo)nb', [], shuffled))
if __name__ == '__main__':
unittest.main()

View file

@ -4,20 +4,19 @@
- [X] LaTeX output
- [X] RTF output
- [X] HTML output
- [ ] Save paragraph-number mapping and reuse automatically
- [ ] Add support for custom begin/end document templates.
- [ ] Save section-number mapping and reuse automatically
- [ ] Add support for custom document templates.
Fixed names and/or command-line options.
- [ ] Add paragraph links in LaTeX output.
- [ ] Add section links in LaTeX output.
- [ ] Debug HTML output
- [ ] Inventory (take, drop, check)
- [ ] Codewords/Sightings (set, check, clean)
- [ ] Skill checks? Or is this higher level? No?
- [ ] More formatting possibilities in paragraphs
- [ ] More formatting possibilities in sections
Look at existing gamebooks to get ideas.
- [ ] Prettier LaTeX output
Look at how some existing gamebooks are formatted.
- [ ] Command-line flag to set max paragraph number to use
- [ ] Dummy paragraphs
- [ ] Command-line flag to set max section number to use
- [ ] Dummy sections
- [ ] Combat? Or is this higher level?
- [ ] Document Gamebook JSON format.
- [ ] Higher level text-language for Gamebooks