Kinematics

nameProc

Mar 2nd, 2013
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.80 KB | None | 0 0
  1. import proc
  2. import util.grammar
  3. import util.groups
  4. import things.items.item
  5.  
  6. # Procs triggered when constructing names (primarily items)
  7.  
  8.  
  9. ## Default
  10. class DefaultItemNamer(proc.Proc):
  11.     # \param item - The item we're getting the name for
  12.     # \param modifyCallback - Callback function that can change
  13.     #       anything about the item's description.  Called after all
  14.     #       other construction calculations are done, so it can tweak
  15.     #       just specific aspects of the final description.
  16.     #       Changes in state should be put in modAdj1.
  17.     def trigger(self, item, modifyCallback = None):
  18.         # \todo: depends on item.theme being a mapping for both name and position,
  19.         #        rather than just the string name.
  20.  
  21.         # Default values to use for the item.  These may potentially
  22.         # be changed by modifyCallback further down.
  23.         baseNoun = item.type # item.nameInfo['baseNoun']
  24.         modifierNoun = u"" # item.nameInfo['modifierNoun']
  25.         itemName = u"" # item.nameInfo['properNoun']
  26.  
  27.         baseAdjectives = []
  28.         modAdjectives = []
  29.         suffixList = []
  30.  
  31.         # Cache the results of the calculations
  32.  
  33.         if item.cachedDescription:
  34.             modAdjectives = item.cachedDescription['modAdjectives']
  35.             baseAdjectives = item.cachedDescription['baseAdjectives']
  36.             suffixList = item.cachedDescription['suffixList']
  37.         #elif item.unknown:
  38.         #    # \todo - proper link in to how we determine player knowledge
  39.         #    # If player doesn't have knowledge of this item type, only provide
  40.         #    # base information and don't cache it (no need to if we're not doing
  41.         #    # the complicated construction).
  42.         #    # Clear the name since that shouldn't be visible.
  43.         #    itemName = u""
  44.         else:
  45.             # uncached, create from scratch
  46.  
  47.             # Affix types:
  48.             # Affix type names are provided in a list of lists, with each
  49.             # sub-list corresponding to a segment of name construction.
  50.             # First list is for adjective types that go before the modifier noun
  51.             # -- state, quality
  52.             # Second list is for adjective types that go before the main noun
  53.             # -- material, make
  54.             # The third list is for suffix descriptors
  55.             # -- combat, physical, mental, elemental, arcane, holy
  56.             affixTypes = things.items.itemLoader.getAffixTypes()
  57.  
  58.             # If no theme or affixes, we don't have to check this section.
  59.             if item.theme or item.affixes:
  60.                 # Themes get defined and placed according to the theme type and contents.
  61.                 # If item has a theme, pull out theme information.
  62.                 if item.theme and item.theme['position'] == 'prefix':
  63.                     # Get all prefix-based affixes that the theme generates, and use
  64.                     # that to determine the overall position the theme name should hold.
  65.                     themePrefixes = [a for a in item.affixes
  66.                                      if a['themed'] == True and a['position'] == 'prefix']
  67.                     if themePrefixes:
  68.                         themePrefixType = [g for k, g in util.groups.groupby(themePrefixes, key=lambda a: a['affixType'])
  69.                                            ][0][0]['affixType']
  70.                     else:
  71.                         # Default position for a prefix theme identifier if there are no
  72.                         # prefix affixes within it is the last of the affixes from the
  73.                         # first list.
  74.                         themePrefixType = affixTypes[0][-1]
  75.                 else:
  76.                     themePrefixType = None
  77.  
  78.                 # Any remaining affixes in the prefix position can be pulled for other
  79.                 # adjective slots.
  80.                 nonThemePrefixes = [a for a in item.affixes
  81.                                     if a['themed'] == False and a['position'] == 'prefix']
  82.  
  83.                 # General correlation for default affix types:
  84.                 # mod adjectives: state, quality
  85.                 # base adjectives: material, make
  86.  
  87.                 # State should only(?) be handled by a modifyCallback function.
  88.                 # There shouldn't exist any affixes that use that type, so generally
  89.                 # nothing should be generated in that part of the call.
  90.  
  91.                 # modifier adjectives
  92.                 for affix in affixTypes[0]:
  93.                     adj = self.getAdjective(affix, themePrefixType, item.theme, nonThemePrefixes)
  94.                     if adj:
  95.                         modAdjectives.append(adj)
  96.  
  97.                 # base adjectives
  98.                 for affix in affixTypes[1][:0]:
  99.                     # Flavor holds the same position as the first base adjective.
  100.                     # If no base adjective is generated, but we have a flavor, use that instead.
  101.                     adj = self.getAdjective(affix, themePrefixType, item.theme, nonThemePrefixes)
  102.                     if item.flavor and not adj:
  103.                         baseAdjectives.append(item.flavor)
  104.                     elif adj:
  105.                         baseAdjectives.append(adj)
  106.  
  107.                 # remaining base adjectives
  108.                 for affix in affixTypes[1][1:]:
  109.                     adj = self.getAdjective(affix, themePrefixType, item.theme, nonThemePrefixes)
  110.                     if adj:
  111.                         baseAdjectives.append(adj)
  112.  
  113.             # prefix stuff done, now postfix
  114.  
  115.             # If item has a suffix theme, use that as the sole suffix.
  116.             if item.theme and item.theme['position'] == 'suffix':
  117.                 suffixList.append(item.theme['name'])
  118.             # Otherwise construct a list from the affixes available.
  119.             # Don't need to construct suffix lists for named items.
  120.             elif item.affixes and not itemName:
  121.                 nonThemeSuffixes = [a for a in item.affixes
  122.                                     if a['themed'] == False and a['position'] == 'suffix']
  123.  
  124.                 if nonThemeSuffixes:
  125.                     # Group the suffixes by affixType.
  126.                     # If there's only one affix for a type, use the affix name.
  127.                     # Otherwise use the genus name that has the highest number of occurances
  128.                     # within the group.
  129.                     suffixes = dict()
  130.                     for k, g in util.groups.groupby(nonThemeSuffixes, key=lambda a: a['affixType']):
  131.                         if len(g) == 1:
  132.                             suffixes[k] = g[0]['name']
  133.                         else:
  134.                             suffixes[k] = [g1 for k1, g1 in util.groups.groupby(g, key=lambda a: a['genus'])
  135.                                            ][0][0]['genus']
  136.  
  137.                     # Suffixes should be ordered by affixType.
  138.                     # (default: combat, physical, mental, elemental, arcane, holy)
  139.                     # These are pulled from the affixTypes list, using the third of
  140.                     # its sub-lists.
  141.                     # We're only interested in the ones that actually exist on the item.
  142.                     usedAffixTypes = [a for a in affixTypes[2]
  143.                                       if a in suffixes.keys()]
  144.  
  145.                     # \todo - determine if something other than subtype should be used for flavored items
  146.                     if item.flavor:
  147.                         suffixList.append(item.flavor)
  148.  
  149.                     for suffix in usedAffixTypes:
  150.                         suffixList.append(suffixes[suffix])
  151.  
  152.             # Store construction results in item cache
  153.             item.cachedDescription.update({'modAdjectives': modAdjectives,
  154.                                            'baseAdjectives': baseAdjectives,
  155.                                            'suffixList': suffixList})
  156.  
  157.         # Allow specification of a modifyCallback function that may modify
  158.         # any aspect of the item's description.  This occurs regardless of
  159.         # what was determined above.
  160.         # Modifications to state should adjust modAdj1.
  161.         # \todo: Function call also needs to restrict based on player knowledge.
  162.         if modifyCallback:
  163.             # Store current values
  164.             descriptors = dict({'modAdjectives': modAdjectives,
  165.                                 'modifierNoun': modifierNoun,
  166.                                 'baseAdjectives': baseAdjectives,
  167.                                 'baseNoun': baseNoun,
  168.                                 'nameSuffix': itemName,
  169.                                 'suffixList': suffixList})
  170.  
  171.             modifyCallback(descriptors)
  172.  
  173.             # Pull changes back in.
  174.             modAdjectives = descriptors['modAdjectives']
  175.             modifierNoun = descriptors['modifierNoun']
  176.             baseAdjectives = descriptors['baseAdjectives']
  177.             baseNoun = descriptors['baseNoun']
  178.             useName = descriptors['itemName']
  179.             suffixList = descriptors['suffixList']
  180.  
  181.  
  182.         # All done figuring out the pieces of the item name.
  183.         # Let grammar put it together, and return the value.
  184.         return util.grammar.getFullItemName(baseNoun = baseNoun,
  185.                                             baseAdjectives = baseAdjectives,
  186.                                             modifierNoun = modifierNoun,
  187.                                             modAdjectives = modAdjectives,
  188.                                             itemName = itemName,
  189.                                             suffixList = suffixList,
  190.                                             quantity = item.quantity)
  191.  
  192.  
  193.     # Get the adjective to use for the requested affix type
  194.     # \param adjType - The affixType/adjectiveType that's being queried for
  195.     # \param themePrefixType - The affixType/adjectiveType that's been
  196.     #       determined for the current theme.
  197.     # \param theme - The current theme.  Can get the name from it, if
  198.     #       a themePrefixType has been determined.
  199.     # \param affixes - The list of affixes we can search to find the
  200.     #       affixType/adjectiveType to return.  If there are multiple
  201.     #       affixes in the list, get the most common genus value instead.
  202.     def getAdjective(self, adjType, themePrefixType, theme, affixes):
  203.         if not adjType:
  204.             return None
  205.  
  206.         if themePrefixType == adjType:
  207.             return theme['name']
  208.  
  209.         adjectives = [a for a in affixes if a['affixType'] == adjType]
  210.  
  211.         if adjectives:
  212.             if len(ajectives) == 1:
  213.                 return adjectives[0]['name']
  214.             else:
  215.                 # return first genus in the groupby list of affixes, which will have the highest count
  216.                 return [g for k, g in util.groups.groupby(adjectives, key=lambda a: a['genus'])][0][0]['genus']
  217.         else:
  218.             return None
Advertisement
Add Comment
Please, Sign In to add comment