Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/src/nobilis/game_data.py b/src/nobilis/game_data.py
- --- a/src/nobilis/game_data.py
- +++ b/src/nobilis/game_data.py
- @@ -244,18 +244,18 @@
- SPECIAL_CONTACT_TEMPLATES += GeneralTemplate('Mystery Cult', ()),
- -AFFLIATION_TEMPLATES = ()
- -AFFLIATION_TEMPLATES += GeneralTemplate(
- +AFFILIATION_TEMPLATES = ()
- +AFFILIATION_TEMPLATES += GeneralTemplate(
- '(The Song of) Heaven', (1, 2, 3)),
- -AFFLIATION_TEMPLATES += GeneralTemplate(
- +AFFILIATION_TEMPLATES += GeneralTemplate(
- '(The Song of) Hell', (4, 5, 6)),
- -AFFLIATION_TEMPLATES += GeneralTemplate(
- +AFFILIATION_TEMPLATES += GeneralTemplate(
- '(The Song of) The Light', (7, 8)),
- -AFFLIATION_TEMPLATES += GeneralTemplate(
- +AFFILIATION_TEMPLATES += GeneralTemplate(
- '(The Song of) The Dark', (9, 10)),
- -AFFLIATION_TEMPLATES += GeneralTemplate(
- +AFFILIATION_TEMPLATES += GeneralTemplate(
- '(The Song of) The Wild', (11, 12, 13)),
- -AFFLIATION_TEMPLATES += GeneralTemplate(
- +AFFILIATION_TEMPLATES += GeneralTemplate(
- 'An Independent Song', (14, 15, 16)),
- diff --git a/src/nobilis/lifepath.py b/src/nobilis/lifepath.py
- --- a/src/nobilis/lifepath.py
- +++ b/src/nobilis/lifepath.py
- @@ -12,6 +12,7 @@
- def key(item):
- + """Return a type-based key for the given item."""
- return type(item), item
- @@ -19,6 +20,7 @@
- # now. Basically, it needs to be used as a mixin AHEAD OF a namedtuple class
- # with a first field of "hash".
- class QuickHash:
- + """Base class for namedtuples that store their hash in the first field."""
- __slots__ = ()
- @@ -28,6 +30,7 @@
- @classmethod
- def _pre_hash(cls, *args, **kwargs):
- + """Return the hash the instance will use."""
- args = tuple(args)
- fields = getattr(cls, '_fields', ('hash',))[1:]
- keywords = fields[len(args):]
- @@ -42,10 +45,12 @@
- class Child(Business):
- + """Purely structural child visitor."""
- __slots__ = ()
- def default_visit(self, node):
- + """Yield zero times."""
- yield from ()
- @@ -53,6 +58,7 @@
- class Tree(QH, nt('Tree', 'hash root reverse_mapping')):
- + """Purely structural tree structure, for determining parents."""
- __slots__ = ()
- @@ -71,77 +77,64 @@
- return super().__new__(cls, root, mapping.Map(reverse_mapping))
- def parent(self, node):
- + """Return the parent of the given node."""
- return self.reverse_mapping.get(key(node))
- @Business.mark
- class Choice(QH, nt('Choice', 'hash template')):
- -
- - __slots__ = ()
- -
- -
- -@Business.mark
- -class ChoiceDisplay(QH, nt('ChoiceDisplay', 'hash choice')):
- + """An underlying choice for tracking state."""
- __slots__ = ()
- +# First to test in rewrite.
- @Business.mark
- -class ChoiceTaken(QH, nt('ChoiceTaken', 'hash choice')):
- +class Tab(QH, nt('Tab', 'hash name node')):
- __slots__ = ()
- -@Business.mark
- -class ChoiceListed(QH, nt('ChoiceListed', 'hash choice')):
- -
- - __slots__ = ()
- -
- -
- +# First to test in rewrite.
- @Business.mark
- -class ChoiceList(QH, nt('ChoiceList', 'hash choices initial_min initial_max')):
- -
- - __slots__ = ()
- -
- -
- -@Business.mark
- -class DisplayList(QH, nt('DisplayList', 'hash factory choices_ sections_')):
- +class TabList(QH, nt('TabList', 'hash tabs')):
- __slots__ = ()
- @property
- - def choices(self):
- - return map_tuple.MapTuple(self.factory, self.choices_)
- -
- - @property
- - def sections(self):
- - return map_tuple.MapTuple(
- - functools.partial(Section, self), range(len(self.sections_)))
- + def enumerated_names(self):
- + return tuple(enumerate(tab.name for tab in self.tabs))
- +# Second to test in rewrite, may need rename.
- @Business.mark
- -class Section(QH, nt('Section', 'hash display_list index')):
- +class Table(QH, nt('Table', 'hash heading node')):
- +
- + __slots__ = ()
- +
- +
- +# Second to test in rewrite, may need rename.
- +@Business.mark
- +class TableList(QH, nt('TableList', 'hash items')):
- __slots__ = ()
- - @property
- - def _data(self):
- - return self.display_list.sections_[self.index]
- - @property
- - def name(self):
- - return self._data[0]
- -
- - @property
- - def predicate(self):
- - return self._data[1]
- +@Child.bind(Tab)
- +def Child(self, node, next_visitor):
- + yield node.node
- -@Child.bind(ChoiceList)
- +@Child.bind(TabList)
- def Child(self, node, next_visitor):
- - yield from node.choices
- + yield from node.tabs
- -@Child.bind(DisplayList)
- +@Child.bind(Table)
- def Child(self, node, next_visitor):
- - yield from node.choices
- + yield node.node
- +
- +
- +@Child.bind(TableList)
- +def Child(self, node, next_visitor):
- + yield from node.items
- diff --git a/tests/nobilis/test_lifepath.py b/tests/nobilis/test_lifepath.py
- --- a/tests/nobilis/test_lifepath.py
- +++ b/tests/nobilis/test_lifepath.py
- @@ -7,7 +7,7 @@
- def test_key(lifepath):
- assert lifepath.key(lifepath.Choice(None)) != lifepath.key(
- - lifepath.ChoiceDisplay(None))
- + lifepath.TabList(None))
- def test_hash_amortization(lifepath):
- @@ -61,55 +61,133 @@
- def test_children(lifepath):
- child = lifepath.Child()
- - leaf = lifepath.Choice(None)
- + tab = lifepath.Tab('name', None)
- - assert tuple(child.visit(leaf)) == ()
- + tab_list = lifepath.TabList((tab,))
- +
- + assert tuple(child.visit(tab_list)) == (tab,)
- + assert tuple(child.visit(tab)) == (None,)
- - for wrapper in (lifepath.ChoiceDisplay, lifepath.ChoiceTaken,
- - lifepath.ChoiceListed):
- - assert tuple(child.visit(wrapper(leaf))) == ()
- + item = lifepath.Table('heading', None)
- - assert tuple(child.visit(lifepath.ChoiceList((leaf,), 0, None))) == (leaf,)
- + item_list = lifepath.TableList((item,))
- - display_list = lifepath.DisplayList(
- - lifepath.ChoiceDisplay, (leaf,), (('name', None),))
- -
- - assert tuple(child.visit(display_list)) == (lifepath.ChoiceDisplay(leaf),)
- + assert tuple(child.visit(item_list)) == (item,)
- + assert tuple(child.visit(item)) == (None,)
- def test_tree(lifepath):
- - leaf = lifepath.Choice(None)
- - root = lifepath.ChoiceList((leaf,), 0, None)
- + leaf = lifepath.Tab('test1', None)
- + root = lifepath.TabList((leaf,))
- tree = lifepath.Tree(root)
- assert tree.parent(leaf) == root
- - rooter = lifepath.ChoiceList((root,), 0, None)
- + rooter = lifepath.TabList((root,))
- treeer = lifepath.Tree(rooter)
- assert treeer.parent(root) == rooter
- assert treeer.parent(leaf) == root
- - dag = lifepath.ChoiceList((leaf, leaf), 0, None)
- + dag = lifepath.TabList((leaf, leaf))
- with pytest.raises(ValueError):
- print(lifepath.Tree(dag))
- -def test_section(lifepath):
- - leaf = lifepath.Choice(None)
- - sentinel = object()
- -
- - display_list = lifepath.DisplayList(
- - lifepath.ChoiceDisplay, (leaf,), (('name', sentinel),))
- -
- - section, = display_list.sections
- -
- - assert section.name == 'name'
- - assert section.predicate is sentinel
- -
- -
- def test_state(lifepath):
- # Okay, so, let's think how this has to go.
- # Ideally, I wouldn't be relying on mutable state, so...
- # state = lifepath.State()
- pass
- +
- +
- +# Okay, let's start over. At the current way of thinking of things, a character
- +# sheet is going to have multiple tabs.
- +
- +def test_power_tabs(lifepath):
- + placeholder = object()
- +
- + # Must be selected before the others.
- + key_tab = lifepath.Tab('Keys', placeholder)
- + # No additional dependencies.
- + foundation_tab = lifepath.Tab('Foundation', placeholder)
- + # No additional dependencies.
- + estate_tab = lifepath.Tab('Estate', placeholder)
- + # Internal dependencies.
- + origins_tab = lifepath.Tab('Origins', placeholder)
- + # Some interaction with Origins.
- + contacts_tab = lifepath.Tab('Contacts', placeholder)
- + # No additional dependencies.
- + affiliation_tab = lifepath.Tab('Affiliation', placeholder)
- + # No additional dependencies.
- + background_tab = lifepath.Tab('Background', placeholder)
- +
- + tab_list = lifepath.TabList((
- + key_tab,
- + foundation_tab,
- + estate_tab,
- + origins_tab,
- + contacts_tab,
- + affiliation_tab,
- + background_tab))
- +
- + # Now that we have the tab_list, we need to reason about it...
- + # Would be good to get an enumerated list of names.
- +
- + assert tab_list.enumerated_names == (
- + (0, 'Keys'),
- + (1, 'Foundation'),
- + (2, 'Estate'),
- + (3, 'Origins'),
- + (4, 'Contacts'),
- + (5, 'Affiliation'),
- + (6, 'Background'),)
- +
- +
- +# Actually, what if I do both kinds of character sheet?
- +
- +def test_deceiver_tabs(lifepath):
- + placeholder = object()
- +
- + # Must be selected before the others.
- + key_tab = lifepath.Tab('Keys', placeholder)
- + # The Foundation tab seems the most mix-and-matchable.
- + # No additional dependencies.
- + foundation_tab = lifepath.Tab('Foundation', placeholder)
- + # No additional dependencies.
- + p_state_tab = lifepath.Tab('pState', placeholder)
- + # No internal dependencies.
- + breakthrough_tab = lifepath.Tab('Breakthrough', placeholder)
- + # May end up with 2 plan tabs
- + # No internal dependencies.
- + plans_tab = lifepath.Tab('Plans', placeholder)
- + # Contacts divided into typical and rare, both sorted, which implies some
- + # way of marking them outside of a section label.
- + # Of note: no dependency on other sections. Just pick "up to three"
- + # Not sure if that REQUIRES at least 1, it's probably a good idea though.
- + # No internal dependencies.
- + contacts_tab = lifepath.Tab('Contacts', placeholder)
- + # No internal dependencies.
- + justification_tab = lifepath.Tab('Justification', placeholder)
- + # No internal dependencies.
- + territory_tab = lifepath.Tab('Territory', placeholder)
- +
- + tab_list = lifepath.TabList((
- + key_tab,
- + foundation_tab,
- + p_state_tab,
- + breakthrough_tab,
- + plans_tab,
- + contacts_tab,
- + justification_tab,
- + territory_tab))
- +
- + assert tab_list.enumerated_names == (
- + (0, 'Keys'),
- + (1, 'Foundation'),
- + (2, 'pState'),
- + (3, 'Breakthrough'),
- + (4, 'Plans'),
- + (5, 'Contacts'),
- + (6, 'Justification'),
- + (7, 'Territory'),)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement