mirror of
https://github.com/Oreolek/gamebookformat.git
synced 2024-06-26 03:41:04 +03:00
Text format brackets.
Switched to text mark-up even more similar to org-mode, also more similar to typical wiki mark-up, removing python-style format from sections (but not from the templates).
This commit is contained in:
parent
a58a237bc1
commit
f723ee0a9c
|
@ -1,2 +1,28 @@
|
||||||
* 1 start
|
* 1 start
|
||||||
Demonstrating how codewords (AKA sightings) can be used.
|
Demonstrating how codewords (AKA sightings) can be used.
|
||||||
|
Go to [[second]].
|
||||||
|
|
||||||
|
* 2 second
|
||||||
|
Simple enough to set. Turn to [[choice]].
|
||||||
|
FIXME not actually setting anything here yet.
|
||||||
|
|
||||||
|
* choice
|
||||||
|
If you have the codeword [has]warrior[/has] you may
|
||||||
|
turn to [[the_end]]. If you do not have the codeword
|
||||||
|
[hasnot]fun[/hasnot], you may turn to [[notsofun]].
|
||||||
|
Otherwise see [[forced]].
|
||||||
|
|
||||||
|
* notsofun
|
||||||
|
This is just to demonstrate choices allowed when not
|
||||||
|
having a codeword. Now go on to [[forced]].
|
||||||
|
|
||||||
|
* forced
|
||||||
|
OK, if you have the codeword [has forced]warrior[/has], turn to
|
||||||
|
[[the_end]].
|
||||||
|
|
||||||
|
* the_end
|
||||||
|
That was easy.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,26 @@
|
||||||
* 1 start
|
* 1 start
|
||||||
Demonstrating how to manage player inventory.
|
Demonstrating how to manage player inventory. You start
|
||||||
|
the book carrying a [take]sword[/take] and a [take]shield[/take].
|
||||||
|
Turn to [[continue]].
|
||||||
|
|
||||||
|
* continue
|
||||||
|
Here you find a [found]key[/found]. Go on to [[door]].
|
||||||
|
|
||||||
|
* door
|
||||||
|
There is a locked door here.
|
||||||
|
If you have a [has]key[/has] you can use that to
|
||||||
|
open the door, see [[inside]]. Being in the same sentence
|
||||||
|
should be enough for the formatter to figure out that the
|
||||||
|
key is required to be allowed to follow the link.
|
||||||
|
Else you can try to open with the [has]sword[/has],
|
||||||
|
if you have it, see [[attempt_break_door_with_sword]].
|
||||||
|
Hopefully the same-sentence magic is enough to pair
|
||||||
|
pre-conditions to links, or more markup must be added later.
|
||||||
|
You could also try to go back to pick up the key, see [[continue]].
|
||||||
|
|
||||||
|
* attempt_break_door_with_sword
|
||||||
|
OK. The door is broken, but so is the [drop]sword[/drop].
|
||||||
|
Turn to [[inside]].
|
||||||
|
|
||||||
|
* inside
|
||||||
|
Congratulations, you won.
|
|
@ -1,13 +1,13 @@
|
||||||
* 1 start
|
* 1 start
|
||||||
This is where the adventure begins. You can go on to the
|
This is where the adventure begins. You can go on to the
|
||||||
next section, see %(next)s or try the other instead, see %(other)s.
|
next section, see [[next]] or try the other instead, see [[other]].
|
||||||
|
|
||||||
* next
|
* next
|
||||||
This is the next section. Go on to the end at %(end)s.
|
This is the next section. Go on to the end at [[end]].
|
||||||
|
|
||||||
* other
|
* other
|
||||||
This is another section. You can try the next section now,
|
This is another section. You can try the next section now,
|
||||||
see %(next)s, or go on to the end, see %(end)s.
|
see [[next]], or go on to the end, see [[end]].
|
||||||
|
|
||||||
* end
|
* end
|
||||||
The end.
|
The end.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
* 1 start
|
* 1 start
|
||||||
It starts here. You can get to %(here)s.
|
It starts here. You can get to [[here]].
|
||||||
|
|
||||||
* here
|
* here
|
||||||
You can get here. Congratulations!
|
You can get here. Congratulations!
|
||||||
|
|
|
@ -150,7 +150,7 @@ if __name__ == '__main__':
|
||||||
ap = argparse.ArgumentParser(epilog=make_supported_formats_list_string(),
|
ap = argparse.ArgumentParser(epilog=make_supported_formats_list_string(),
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
ap.add_argument('inputfiles', metavar='inputfile', nargs='+',
|
ap.add_argument('inputfiles', metavar='inputfile', nargs='+',
|
||||||
help='input gamebook file (eg test.json)')
|
help='input gamebook file (eg test.gamebook)')
|
||||||
ap.add_argument('outputfile', metavar='outputfile',
|
ap.add_argument('outputfile', metavar='outputfile',
|
||||||
help='output file (eg test.tex or test.rtf)')
|
help='output file (eg test.tex or test.rtf)')
|
||||||
ap.add_argument('-M', '--no-default-map', action='store_false',
|
ap.add_argument('-M', '--no-default-map', action='store_false',
|
||||||
|
|
15
readme.org
15
readme.org
|
@ -7,13 +7,14 @@ gamebook on paper or a screen (or for debugging it).
|
||||||
: formatgamebook.py [-h] [-M] [-t D] inputfile [inputfile ...] outputfile
|
: formatgamebook.py [-h] [-M] [-t D] inputfile [inputfile ...] outputfile
|
||||||
:
|
:
|
||||||
: positional arguments:
|
: positional arguments:
|
||||||
: inputfile input gamebook file (eg test.json)
|
: inputfile input gamebook file (eg test.gamebook)
|
||||||
: outputfile output file (eg test.tex or test.rtf)
|
: outputfile output file (eg test.tex or test.rtf)
|
||||||
:
|
:
|
||||||
: optional arguments:
|
: optional arguments:
|
||||||
: -h, --help show this help message and exit
|
: -h, --help show this help message and exit
|
||||||
: -M, --no-default-map ignore default map file
|
: -M, --no-default-map ignore default map file
|
||||||
: -t D, --template D add custom template dir
|
: -t D, --template D add custom template dir
|
||||||
|
: -y, --verify verify gamebook structure
|
||||||
|
|
||||||
|
|
||||||
** Supported Output Formats
|
** Supported Output Formats
|
||||||
|
@ -33,13 +34,17 @@ More to be added.
|
||||||
The input file expected by the formatgamebook.py script must be in a
|
The input file expected by the formatgamebook.py script must be in a
|
||||||
format containing information about all sections in the book
|
format containing information about all sections in the book
|
||||||
plus some optional metadata. The format should (when TBD) be documented
|
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
|
here.
|
||||||
at the gamebook file, but rather use a higher level format or a
|
|
||||||
GUI tool.
|
By design the format is similar enough to [[http://orgmode.org][Emacs Org-Mode]]
|
||||||
|
that some edit shortcuts works in that mode without additional
|
||||||
|
configuration (eg /C-c C-q/ to edit section tags).
|
||||||
|
References to sections can be followed using
|
||||||
|
/C-c C-o/ while editing the book in org-mode.
|
||||||
|
|
||||||
** License
|
** License
|
||||||
|
|
||||||
Copyright (c) 2013, Pelle Nilsson
|
Copyright (c) 2013 Pelle Nilsson
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|
51
sections.py
51
sections.py
|
@ -18,7 +18,42 @@ class Section:
|
||||||
repr(self.tags))
|
repr(self.tags))
|
||||||
|
|
||||||
def format(self, references):
|
def format(self, references):
|
||||||
return self.text % references
|
i = 0
|
||||||
|
res = ""
|
||||||
|
while i < len(self.text):
|
||||||
|
ref_start = self.text.find('[[', i)
|
||||||
|
tag_start = self.text.find('[', i)
|
||||||
|
if ref_start >= 0 and ref_start <= tag_start:
|
||||||
|
res += self.text[i:ref_start]
|
||||||
|
ref_end = self.text.find(']]', ref_start)
|
||||||
|
if ref_end > ref_start:
|
||||||
|
ref = self.text[ref_start+2:ref_end]
|
||||||
|
res += references[ref]
|
||||||
|
i = ref_end + 2
|
||||||
|
else:
|
||||||
|
raise Exception('Mismatched ref start [[ in section %s' %
|
||||||
|
self.name)
|
||||||
|
elif tag_start >= 0:
|
||||||
|
res += self.text[i:tag_start]
|
||||||
|
tag_end = self.text.find(']', tag_start)
|
||||||
|
if tag_end < 0:
|
||||||
|
raise Exception('Mismatched tag start [ in section %s' %
|
||||||
|
self.name)
|
||||||
|
tag = self.text[tag_start+1:tag_end]
|
||||||
|
end_tag_start = self.text.find('[', tag_end)
|
||||||
|
if (not end_tag_start > tag_end
|
||||||
|
and self.text[end_tag_start].startswith('[/' + tag + ']')):
|
||||||
|
raise Exception('Bad format %s tag in %s.' % (
|
||||||
|
tag, self.name))
|
||||||
|
tagtext = self.text[tag_end+1:end_tag_start]
|
||||||
|
print tag, tagtext
|
||||||
|
#FIXME actually handle tags
|
||||||
|
res += tagtext
|
||||||
|
i = self.text.find(']', end_tag_start) + 1
|
||||||
|
else:
|
||||||
|
res += self.text[i:]
|
||||||
|
break
|
||||||
|
return res
|
||||||
|
|
||||||
class ShuffledSections:
|
class ShuffledSections:
|
||||||
def __init__(self, as_list, from_nr, to_nr, from_name):
|
def __init__(self, as_list, from_nr, to_nr, from_name):
|
||||||
|
@ -36,6 +71,7 @@ class Book:
|
||||||
self.from_name = {}
|
self.from_name = {}
|
||||||
self.nr_sections = {}
|
self.nr_sections = {}
|
||||||
self.max = 0
|
self.max = 0
|
||||||
|
self.codewords = set()
|
||||||
|
|
||||||
def add(self, section):
|
def add(self, section):
|
||||||
if section.name in self.from_name:
|
if section.name in self.from_name:
|
||||||
|
@ -46,6 +82,9 @@ class Book:
|
||||||
if len(self.sections) > self.max:
|
if len(self.sections) > self.max:
|
||||||
self.max = len(self.sections)
|
self.max = len(self.sections)
|
||||||
|
|
||||||
|
def add_codeword(self, word):
|
||||||
|
self.codewords.add(word)
|
||||||
|
|
||||||
def force_section_nr(self, name, nr):
|
def force_section_nr(self, name, nr):
|
||||||
self.nr_sections[nr] = name
|
self.nr_sections[nr] = name
|
||||||
if nr > self.max:
|
if nr > self.max:
|
||||||
|
@ -71,3 +110,13 @@ class Book:
|
||||||
if section:
|
if section:
|
||||||
to_nr[section] = nr
|
to_nr[section] = nr
|
||||||
return ShuffledSections(as_list, from_nr, to_nr, self.from_name.copy())
|
return ShuffledSections(as_list, from_nr, to_nr, self.from_name.copy())
|
||||||
|
|
||||||
|
class Item (object):
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
class Hero (object):
|
||||||
|
"The hero (player character) of a Book."
|
||||||
|
def __init__(self):
|
||||||
|
self.carrying_capacity = 10
|
||||||
|
self.skills = set()
|
||||||
|
|
|
@ -35,5 +35,13 @@ class TestBook(TestCase):
|
||||||
self.assertEqual(b.nr_sections, {})
|
self.assertEqual(b.nr_sections, {})
|
||||||
self.assertEqual(b.max, 0)
|
self.assertEqual(b.max, 0)
|
||||||
|
|
||||||
|
class TestItem(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_create(self):
|
||||||
|
i = sections.Item("nn")
|
||||||
|
self.assertEqual(i.name, "nn")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
2
todo.org
2
todo.org
|
@ -12,6 +12,8 @@
|
||||||
- [X] Add section links in LaTeX output.
|
- [X] Add section links in LaTeX output.
|
||||||
- [X] Prettier LaTeX output
|
- [X] Prettier LaTeX output
|
||||||
Look at how some existing gamebooks are formatted.
|
Look at how some existing gamebooks are formatted.
|
||||||
|
- [ ] Parse wiki-style tags used to mark up sections
|
||||||
|
- [ ] New text formatting style for section references
|
||||||
- [ ] Inventory pick up items
|
- [ ] Inventory pick up items
|
||||||
- [ ] Codewords set
|
- [ ] Codewords set
|
||||||
- [ ] Check if has inventory item
|
- [ ] Check if has inventory item
|
||||||
|
|
Loading…
Reference in a new issue