Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import proc
- import util.grammar
- import util.groups
- import things.items.item
- # Procs triggered when constructing names (primarily items)
- ## Default
- class DefaultItemNamer(proc.Proc):
- # \param item - The item we're getting the name for
- # \param modifyCallback - Callback function that can change
- # anything about the item's description. Called after all
- # other construction calculations are done, so it can tweak
- # just specific aspects of the final description.
- # Changes in state should be put in modAdj1.
- def trigger(self, item, modifyCallback = None):
- # \todo: depends on item.theme being a mapping for both name and position,
- # rather than just the string name.
- # Default values to use for the item. These may potentially
- # be changed by modifyCallback further down.
- baseNoun = item.type # item.nameInfo['baseNoun']
- modifierNoun = u"" # item.nameInfo['modifierNoun']
- itemName = u"" # item.nameInfo['properNoun']
- baseAdjectives = []
- modAdjectives = []
- suffixList = []
- # Cache the results of the calculations
- if item.cachedDescription:
- modAdjectives = item.cachedDescription['modAdjectives']
- baseAdjectives = item.cachedDescription['baseAdjectives']
- suffixList = item.cachedDescription['suffixList']
- #elif item.unknown:
- # # \todo - proper link in to how we determine player knowledge
- # # If player doesn't have knowledge of this item type, only provide
- # # base information and don't cache it (no need to if we're not doing
- # # the complicated construction).
- # # Clear the name since that shouldn't be visible.
- # itemName = u""
- else:
- # uncached, create from scratch
- # Affix types:
- # Affix type names are provided in a list of lists, with each
- # sub-list corresponding to a segment of name construction.
- # First list is for adjective types that go before the modifier noun
- # -- state, quality
- # Second list is for adjective types that go before the main noun
- # -- material, make
- # The third list is for suffix descriptors
- # -- combat, physical, mental, elemental, arcane, holy
- affixTypes = things.items.itemLoader.getAffixTypes()
- # If no theme or affixes, we don't have to check this section.
- if item.theme or item.affixes:
- # Themes get defined and placed according to the theme type and contents.
- # If item has a theme, pull out theme information.
- if item.theme and item.theme['position'] == 'prefix':
- # Get all prefix-based affixes that the theme generates, and use
- # that to determine the overall position the theme name should hold.
- themePrefixes = [a for a in item.affixes
- if a['themed'] == True and a['position'] == 'prefix']
- if themePrefixes:
- themePrefixType = [g for k, g in util.groups.groupby(themePrefixes, key=lambda a: a['affixType'])
- ][0][0]['affixType']
- else:
- # Default position for a prefix theme identifier if there are no
- # prefix affixes within it is the last of the affixes from the
- # first list.
- themePrefixType = affixTypes[0][-1]
- else:
- themePrefixType = None
- # Any remaining affixes in the prefix position can be pulled for other
- # adjective slots.
- nonThemePrefixes = [a for a in item.affixes
- if a['themed'] == False and a['position'] == 'prefix']
- # General correlation for default affix types:
- # mod adjectives: state, quality
- # base adjectives: material, make
- # State should only(?) be handled by a modifyCallback function.
- # There shouldn't exist any affixes that use that type, so generally
- # nothing should be generated in that part of the call.
- # modifier adjectives
- for affix in affixTypes[0]:
- adj = self.getAdjective(affix, themePrefixType, item.theme, nonThemePrefixes)
- if adj:
- modAdjectives.append(adj)
- # base adjectives
- for affix in affixTypes[1][:0]:
- # Flavor holds the same position as the first base adjective.
- # If no base adjective is generated, but we have a flavor, use that instead.
- adj = self.getAdjective(affix, themePrefixType, item.theme, nonThemePrefixes)
- if item.flavor and not adj:
- baseAdjectives.append(item.flavor)
- elif adj:
- baseAdjectives.append(adj)
- # remaining base adjectives
- for affix in affixTypes[1][1:]:
- adj = self.getAdjective(affix, themePrefixType, item.theme, nonThemePrefixes)
- if adj:
- baseAdjectives.append(adj)
- # prefix stuff done, now postfix
- # If item has a suffix theme, use that as the sole suffix.
- if item.theme and item.theme['position'] == 'suffix':
- suffixList.append(item.theme['name'])
- # Otherwise construct a list from the affixes available.
- # Don't need to construct suffix lists for named items.
- elif item.affixes and not itemName:
- nonThemeSuffixes = [a for a in item.affixes
- if a['themed'] == False and a['position'] == 'suffix']
- if nonThemeSuffixes:
- # Group the suffixes by affixType.
- # If there's only one affix for a type, use the affix name.
- # Otherwise use the genus name that has the highest number of occurances
- # within the group.
- suffixes = dict()
- for k, g in util.groups.groupby(nonThemeSuffixes, key=lambda a: a['affixType']):
- if len(g) == 1:
- suffixes[k] = g[0]['name']
- else:
- suffixes[k] = [g1 for k1, g1 in util.groups.groupby(g, key=lambda a: a['genus'])
- ][0][0]['genus']
- # Suffixes should be ordered by affixType.
- # (default: combat, physical, mental, elemental, arcane, holy)
- # These are pulled from the affixTypes list, using the third of
- # its sub-lists.
- # We're only interested in the ones that actually exist on the item.
- usedAffixTypes = [a for a in affixTypes[2]
- if a in suffixes.keys()]
- # \todo - determine if something other than subtype should be used for flavored items
- if item.flavor:
- suffixList.append(item.flavor)
- for suffix in usedAffixTypes:
- suffixList.append(suffixes[suffix])
- # Store construction results in item cache
- item.cachedDescription.update({'modAdjectives': modAdjectives,
- 'baseAdjectives': baseAdjectives,
- 'suffixList': suffixList})
- # Allow specification of a modifyCallback function that may modify
- # any aspect of the item's description. This occurs regardless of
- # what was determined above.
- # Modifications to state should adjust modAdj1.
- # \todo: Function call also needs to restrict based on player knowledge.
- if modifyCallback:
- # Store current values
- descriptors = dict({'modAdjectives': modAdjectives,
- 'modifierNoun': modifierNoun,
- 'baseAdjectives': baseAdjectives,
- 'baseNoun': baseNoun,
- 'nameSuffix': itemName,
- 'suffixList': suffixList})
- modifyCallback(descriptors)
- # Pull changes back in.
- modAdjectives = descriptors['modAdjectives']
- modifierNoun = descriptors['modifierNoun']
- baseAdjectives = descriptors['baseAdjectives']
- baseNoun = descriptors['baseNoun']
- useName = descriptors['itemName']
- suffixList = descriptors['suffixList']
- # All done figuring out the pieces of the item name.
- # Let grammar put it together, and return the value.
- return util.grammar.getFullItemName(baseNoun = baseNoun,
- baseAdjectives = baseAdjectives,
- modifierNoun = modifierNoun,
- modAdjectives = modAdjectives,
- itemName = itemName,
- suffixList = suffixList,
- quantity = item.quantity)
- # Get the adjective to use for the requested affix type
- # \param adjType - The affixType/adjectiveType that's being queried for
- # \param themePrefixType - The affixType/adjectiveType that's been
- # determined for the current theme.
- # \param theme - The current theme. Can get the name from it, if
- # a themePrefixType has been determined.
- # \param affixes - The list of affixes we can search to find the
- # affixType/adjectiveType to return. If there are multiple
- # affixes in the list, get the most common genus value instead.
- def getAdjective(self, adjType, themePrefixType, theme, affixes):
- if not adjType:
- return None
- if themePrefixType == adjType:
- return theme['name']
- adjectives = [a for a in affixes if a['affixType'] == adjType]
- if adjectives:
- if len(ajectives) == 1:
- return adjectives[0]['name']
- else:
- # return first genus in the groupby list of affixes, which will have the highest count
- return [g for k, g in util.groups.groupby(adjectives, key=lambda a: a['genus'])][0][0]['genus']
- else:
- return None
Advertisement
Add Comment
Please, Sign In to add comment