From f723ee0a9c425cea792ac5a6485401a8026fb3b0 Mon Sep 17 00:00:00 2001 From: Pelle Nilsson Date: Wed, 5 Jun 2013 00:19:57 +0200 Subject: [PATCH] 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). --- examples/codewords.gamebook | 28 ++++++++++++++++++- examples/items.gamebook | 26 +++++++++++++++++- examples/references.gamebook | 6 ++--- examples/unreachable.gamebook | 2 +- formatgamebook.py | 2 +- readme.org | 15 +++++++---- sections.py | 51 ++++++++++++++++++++++++++++++++++- test_sections.py | 8 ++++++ todo.org | 2 ++ 9 files changed, 127 insertions(+), 13 deletions(-) diff --git a/examples/codewords.gamebook b/examples/codewords.gamebook index bb0cd35..828dde7 100644 --- a/examples/codewords.gamebook +++ b/examples/codewords.gamebook @@ -1,2 +1,28 @@ * 1 start -Demonstrating how codewords (AKA sightings) can be used. \ No newline at end of file +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. + + + + diff --git a/examples/items.gamebook b/examples/items.gamebook index 05dc8e4..2dc7f6a 100644 --- a/examples/items.gamebook +++ b/examples/items.gamebook @@ -1,2 +1,26 @@ * 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. \ No newline at end of file diff --git a/examples/references.gamebook b/examples/references.gamebook index 495bdb7..abd7d82 100644 --- a/examples/references.gamebook +++ b/examples/references.gamebook @@ -1,13 +1,13 @@ * 1 start 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 -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 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 The end. diff --git a/examples/unreachable.gamebook b/examples/unreachable.gamebook index 37ec553..69062d6 100644 --- a/examples/unreachable.gamebook +++ b/examples/unreachable.gamebook @@ -1,5 +1,5 @@ * 1 start -It starts here. You can get to %(here)s. +It starts here. You can get to [[here]]. * here You can get here. Congratulations! diff --git a/formatgamebook.py b/formatgamebook.py index 681416e..8fc88c1 100755 --- a/formatgamebook.py +++ b/formatgamebook.py @@ -150,7 +150,7 @@ if __name__ == '__main__': ap = argparse.ArgumentParser(epilog=make_supported_formats_list_string(), formatter_class=argparse.RawDescriptionHelpFormatter) 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', help='output file (eg test.tex or test.rtf)') ap.add_argument('-M', '--no-default-map', action='store_false', diff --git a/readme.org b/readme.org index 2094689..b34a158 100644 --- a/readme.org +++ b/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 : : 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) : : optional arguments: : -h, --help show this help message and exit : -M, --no-default-map ignore default map file : -t D, --template D add custom template dir +: -y, --verify verify gamebook structure ** Supported Output Formats @@ -33,13 +34,17 @@ More to be added. The input file expected by the formatgamebook.py script must be in a 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 -GUI tool. +here. + +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 -Copyright (c) 2013, Pelle Nilsson +Copyright (c) 2013 Pelle Nilsson All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/sections.py b/sections.py index f6844ce..a2ac1ac 100644 --- a/sections.py +++ b/sections.py @@ -18,7 +18,42 @@ class Section: repr(self.tags)) 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: def __init__(self, as_list, from_nr, to_nr, from_name): @@ -36,6 +71,7 @@ class Book: self.from_name = {} self.nr_sections = {} self.max = 0 + self.codewords = set() def add(self, section): if section.name in self.from_name: @@ -46,6 +82,9 @@ class Book: if len(self.sections) > self.max: self.max = len(self.sections) + def add_codeword(self, word): + self.codewords.add(word) + def force_section_nr(self, name, nr): self.nr_sections[nr] = name if nr > self.max: @@ -71,3 +110,13 @@ class Book: if section: to_nr[section] = nr 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() diff --git a/test_sections.py b/test_sections.py index 0fe231c..c0ea0a9 100755 --- a/test_sections.py +++ b/test_sections.py @@ -35,5 +35,13 @@ class TestBook(TestCase): self.assertEqual(b.nr_sections, {}) 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__': unittest.main() diff --git a/todo.org b/todo.org index cf1d4f1..fd32004 100644 --- a/todo.org +++ b/todo.org @@ -12,6 +12,8 @@ - [X] Add section links in LaTeX output. - [X] Prettier LaTeX output 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 - [ ] Codewords set - [ ] Check if has inventory item