Example #1
0
def permitobject(df,
                 type=None,
                 id=None,
                 permit_entities=None,
                 item_rarity=None):
    # Decide what tokens need to be added to the entities based on the object type
    if type == 'REACTION':
        tokens = raws.token(value='PERMITTED_REACTION', args=[id])
    elif type.startswith('BUILDING_'):
        tokens = raws.token(value='PERMITTED_BUILDING', args=[id])
    elif type.startswith('ITEM_'):
        value = type.split('_')[1]
        args = [id, item_rarity] if item_rarity else [id]
        tokens = raws.token(value=value, args=args)
    else:
        tokens = None

    pydwarf.log.debug('Permitting object [%s:%s] for %d entities.' %
                      (type, id, len(permit_entities)))

    # Actually add those tokens
    if tokens is None:
        return pydwarf.success(
            'Didn\'t actually permit object [%s:%s] because objects of this type cannot be permitted.'
            % (type, id))
    elif not permit_entities:
        return pydwarf.failure('No entities were given for permitting.')
    else:
        response = addtoentity(df, entities=permit_entities, tokens=tokens)
        if not response:
            return response
        else:
            return pydwarf.success(
                'Permitted object [%s:%s] for %d entities.' %
                (type, id, len(permit_entities)))
Example #2
0
def orientation(df,
                creatures=default_creatures,
                mode='hetero',
                lover_chance=default_lover_chance):
    if isinstance(mode, basestring):
        if mode not in mode_info:
            return pydwarf.failure(
                'Invalid mode %s. Recognized modes are these: %s.' %
                (mode, ', '.join(mode_tokens.keys())))
        usemode = mode_info[mode]
    else:
        usemode = mode

    # Unpack variables for convenience
    disinterestsame, loversame, commitsame, disinterestother, loverother, commitother = usemode

    # Get tokens for all the specified creatures
    creatures = df.allobj(type='CREATURE', id_in=creatures)
    pydwarf.log.debug('Found %d applicable creatures.' % len(creatures))

    # Add tokens after [FEMALE] and [MALE] tokens
    added = 0
    for creature in creatures:
        pydwarf.log.debug('Applying ORIENTATION changes to %s.' % creature)

        # Remove any existing ORIENTATION tokens
        removetokens = creature.allprop(exact_value='ORIENTATION')
        if len(removetokens):
            pydwarf.log.debug(
                'Removing %d existing ORIENTATION tokens from token %s.' %
                (len(removetokens), gendertoken))
            for removetoken in removetokens:
                removetoken.remove()

        # Add the new orientation tokens
        gendertokens = creature.allprop(value_in=('FEMALE', 'MALE'),
                                        args_count=0)
        for gendertoken in gendertokens:
            othergender = 'FEMALE' if gendertoken.value == 'MALE' else 'MALE'
            gendertoken.add(
                raws.token(value='ORIENTATION',
                           args=[
                               othergender, disinterestother, loverother,
                               commitother
                           ]))
            gendertoken.add(
                raws.token(value='ORIENTATION',
                           args=[
                               gendertoken.value, disinterestsame, loversame,
                               commitsame
                           ]))
            added += 1

    # All done!
    if added > 0:
        return pydwarf.success(
            'Appended ORIENTATION tokens after %d gender tokens.' % added)
    else:
        return pydwarf.failure('Found no gender tokens to add ORIENTATION to.')
Example #3
0
def maxage(df,
           ages=default_ages,
           apply_default_age=None,
           output_needs_age=False):
    added = []
    modified = []

    # Handle each creature
    for creaturetoken in df.allobj('CREATURE'):
        creaturename = creaturetoken.args[0]
        maxage = creaturetoken.getprop('MAXAGE')

        # Creature is in the ages dict, give it the age specified
        if creaturename in ages:
            agetuple = ages.get(creaturename)
            if agetuple is not None:
                pydwarf.log.debug('Applying MAXAGE %s to %s...' %
                                  (agetuple, creaturetoken))
                if maxage:
                    modified.append(creaturename)
                    maxage.args = list(agetuple)
                else:
                    added.append(creaturename)
                    creaturetoken.addprop(
                        raws.token(value='MAXAGE', args=list(agetuple)))

        # Creature isn't in the ages dict, check about applying a default or simply outputting its existence
        elif (not maxage) and (output_needs_age or apply_default_age):
            props = creaturetoken.propdict()
            if not ('COPY_TAGS_FROM' in props or 'EQUIPMENT_WAGON' in props
                    or 'MEGABEAST' in props or 'DOES_NOT_EXIST' in props
                    or 'NOT_LIVING' in props):
                if apply_default_age is not None:
                    pydwarf.log.debug('Applying default MAXAGE %s to %s...' %
                                      (apply_default_age, creaturetoken))
                    creaturetoken.addprop(
                        raws.token(value='MAXAGE',
                                   args=list(apply_default_age)))
                    added.append(creaturename)
                else:
                    pydwarf.log.info('Creature %s has no MAXAGE.')

    # All done!
    pydwarf.log.debug('Modified MAXAGE tokens of creatures: %s.' % modified)
    pydwarf.log.debug('Added MAXAGE tokens to creatures: %s.' % added)
    if len(added) or len(modified):
        return pydwarf.success(
            'Added %d MAXAGE tokens and modified %d existing ones.' %
            (len(added), len(modified)))
    else:
        return pydwarf.failure('No MAXAGE tokens affected.')
Example #4
0
def addobject(df,
              add_to_file,
              tokens,
              type=None,
              id=None,
              permit_entities=None,
              item_rarity=None,
              object_header=None):
    # If type and id weren't explicitly given then assume the first given token is the TYPE:ID header and get the info from there.
    header_in_tokens = type is None and id is None
    header = None
    if header_in_tokens:
        if isinstance(tokens, basestring): tokens = raws.parseplural(tokens)
        header = tokens[0]
        type = header.value
        id = header.arg()
        pydwarf.log.debug(
            'Extracted object type %s and id %s from given tokens.' %
            (type, id))

    # Get the applicable object dict which knows how to map TYPE:ID to its corresponding OBJECT:TYPE header.
    if object_header is None:
        object_header = raws.objects.headerforobject(type)

    # If add_to_file already exists, fetch it. Otherwise add it to the raws.
    add_to_file = add_to_file % {'type': object_header.lower()}
    if add_to_file in df:
        file = df.getfile(add_to_file)
    else:
        file = df.add(add_to_file)
        file.add(raws.token(value='OBJECT', args=[object_header]))
        pydwarf.log.debug('Added new file %s to dir.' % add_to_file)

    # Add the object itself to the raws.
    if not header_in_tokens:
        header = file.add(raws.token(value=type, args=[id]))
    file.add(tokens)

    # Add tokens to entities to permit the use of this object.
    if permit_entities:
        response = permitobject(df,
                                type=type,
                                id=id,
                                permit_entities=permit_entities,
                                item_rarity=item_rarity)
        if not response: return response

    # All done!
    return pydwarf.success('Added object %s to file %s.' % (header, file))
Example #5
0
def engraving(df):
    if 'descriptor_shape_umiman' in df:
        return pydwarf.failure('File descriptor_shape_umiman already exists.')

    # Get the smallthings ModBase raws, which is where this data will be coming from
    smallraws = getsmallraws()
    if not smallraws:
        return pydwarf.failure('Failed to read smallthings raws.')

    # Get existing words and shapes
    dfwordsdict = df.objdict('WORD')
    dfshapesdict = df.objdict('SHAPE')

    # Add a new file for the new shapes
    dfshapesfile = df.add('raw/objects/descriptor_shape_umiman.txt')
    dfshapesfile.add('OBJECT:DESCRIPTOR_SHAPE')
    shapesadded = 0

    # Add each shape
    smallshapes = smallraws['descriptor_shape_standard']
    if smallshapes is None:
        return pydwarf.failure(
            'Failed to find smallthings raws file named descriptor_shape_standard.'
        )
    for smallshape in smallshapes.all(exact_value='SHAPE'):
        if smallshape.args[
                0] not in dfshapesdict:  # Verify that the shape isn't already in the raws
            pydwarf.log.debug('Adding shape %s...' % smallshape)

            # Get the tokens describing this shape
            smallshapetokens = smallshape.all(until_exact_value='SHAPE')

            # Shapes in DF's descriptor_shape_standard all have a [WORD:X] token but these do not
            # To compensate, let's do our best to map each shape to a word automatically
            smallshapename = smallshape.get(exact_value='NAME', args_count=2)
            if smallshapename:
                useshapename = smallshapename.args[0].upper()
                if useshapename in shapenamedict:
                    useshapename = shapenamedict[useshapename]
                shapeword = dfwordsdict.get(useshapename)
            else:
                pydwarf.log.error('Found no names for %s.' % shallshape)

            # Actually add the new shape to the raws
            dfshapesfile.add(smallshape.copy())
            dfshapesfile.add(smallshapetokens.copy())

            # And also add the word, provided one was found
            if shapeword:
                dfshapesfile.add(
                    raws.token(value='WORD', args=(shapeword.args[0], )))
            else:
                pydwarf.log.info('Found no word for %s, named %s.' %
                                 (smallshape, smallshapename))

            # And on to the next iteration
            shapesadded += 1

    # All done!
    return pydwarf.success('Added %s new shapes.' % shapesadded)
def butcherinorganic(df, templates=default_templates):
    added = 0

    # Apply BUTCHER_SPECIAL tokens to material templates
    for templatename, butcherspecial in templates.iteritems():
        template = df.getobj(type='MATERIAL_TEMPLATE', exact_id=templatename)
        if template:
            pydwarf.log.debug(
                'Adding BUTCHER_SPECIAL item %s to material template %s.' %
                (butcherspecial, templatename))
            template.addprop(
                raws.token(value='BUTCHER_SPECIAL',
                           args=[butcherspecial, 'NONE']))
            added += 1
        else:
            pydwarf.log.error('Unable to find template %s, skipping.' %
                              templatename)

    # All done!
    if added > 0:
        return pydwarf.success(
            'Added BUTCHER_SPECIAL to %d material templates.' % added)
    else:
        return pydwarf.failure(
            'Added BUTCHER_SPECIAL to no material templates.')
Example #7
0
def addraws(pydwarf, dfraws, rawsdir, entities, extratokens=None):
    # Get the entities that need to have permitted things added to them.
    entitytokens = getentities(dfraws, entities)
    if len(entitytokens) != len(entities):
        if len(entitytokens):
            pydwarf.log.error(
                'Of entities %s passed by argument, only %s were found.' %
                (entities, entitytokens))
        else:
            return pydwarf.failure(
                'Found none of entities %s to which to add permitted buildings and reactions.'
                % entities)

    # Read the raws
    try:
        shukaroraws = raws.dir(path=rawsdir, log=pydwarf.log)
    except:
        pydwarf.log.exception('Failed to load raws from %s.' % rawsdir)
        return pydwarf.failure('Failed to load raws from %s.' % rawsdir)

    # Add new buildings and reactions to entities, and whatever else needs adding
    buildings = shukaroraws.all(exact_value='BUILDING_WORKSHOP', args_count=1)
    reactions = shukaroraws.all(exact_value='REACTION', args_count=1)
    for entity in entitytokens:
        if extratokens: entity.add(extratokens)
        for building in buildings:
            entity.add(
                raws.token(value='PERMITTED_BUILDING',
                           args=(building.args[0], )))
        for reaction in reactions:
            entity.add(
                raws.token(value='PERMITTED_REACTION',
                           args=(reaction.args[0], )))
    pydwarf.log.info(
        'Added %d permitted buildings and %d permitted reactions to %d entities.'
        % (len(buildings), len(reactions), len(entitytokens)))

    # Add new files
    for filename, rfile in shukaroraws.files.iteritems():
        if filename not in dfraws: dfraws.addfile(rfile=rfile)

    # All done!
    return pydwarf.success()
Example #8
0
def microreduce(dfraws):
    mountain = dfraws.get('ENTITY:MOUNTAIN')
    if mountain:
        # Add files
        genericpath = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   'Microreduce', '%s.txt')
        for filename in ('building_macro_fantastic', 'item_macro_fantastic',
                         'reaction_macro_fantastic'):
            rfile = dfraws.addfile(path=genericpath % filename)
            # Add PERMITTED_BUILDING and PERMITTED_REACTION tokens to ENTITY:MOUNTAIN
            for building in rfile.all(re_value='BUILDING.*', args_count=1):
                mountain.add(
                    raws.token(value='PERMITTED_BUILDING',
                               args=[building.args[0]]))
            for reaction in rfile.all(exact_value='REACTION', args_count=1):
                mountain.add(
                    raws.token(value='REACTION', args=[reaction.args[0]]))
        return pydwarf.success()
    else:
        return pydwarf.failure('Couldn\'t find ENTITY:MOUNTAIN.')
Example #9
0
def metalitems(df, metals=default_metals, items=default_item_tokens):
    # Turn the item names into a list of tokens
    itemtokens = [raws.token(value=item) for item in items]

    # Apply to each metal
    affected = df.allobj(type='INORGANIC', id_in=metals).each(lambda token: (
        # Remove existing tokens first to prevent duplicates when adding
        token.removeallprop(value_in=items),
        # And now add the specified tokens
        token.addprop(raws.helpers.copytokens(itemtokens))))

    # All done!
    if affected:
        return pydwarf.success('Affected %d metals.' % len(affected))
    else:
        return pydwarf.failure('Affected no metals.')
Example #10
0
def subterraneanplants(dfraws):
    subplants = []
    for plant in dfraws.allobj('PLANT'):
        if plant.getuntil(pretty='BIOME:SUBTERRANEAN_WATER',
                          until_exact_value='PLANT'):
            subplants.append(plant)
    if not len(subplants):
        return pydwarf.failure('Found no subterranean plants.')
    pydwarf.log.info('Found %d subterranean plants. Modifying...' %
                     len(subplants))
    for subplant in subplants:
        pydwarf.log.debug('Handling %s...' % subplant)
        for seasontoken in subplant.alluntil(value_in=seasons,
                                             until_exact_value='PLANT'):
            seasontoken.remove()
        for season in seasons:
            subplant.add(raws.token(value=season))
    return pydwarf.success('Made %d subterranean plants grow year-round.' %
                           len(subplants))
Example #11
0
def discipline(df, discipline_bonus=default_discipline_bonus, entity_bonus=default_entity_bonus, badger_bonus=default_badger_bonus):
    creaturedict = df.objdict('CREATURE')
    discbonusdict = {}
    
    # Add bonuses for badgers and for creatures with given properties
    pydwarf.log.info('Determining bonuses based on misc properties...')
    for creaturename, creaturetoken in creaturedict.iteritems():
        discbonusdict[creaturename] = badger_bonus if 'BADGER' in creaturename else 0.0
        for prop in creaturetoken.allprop(value_in=discipline_bonus):
            discbonusdict[creaturename] += discipline_bonus[prop.value]
            
    # Add bonus for creatures which are part of a civilization
    pydwarf.log.info('Determining bonuses for civilization membership...')
    for entitytoken in df.allobj('ENTITY'):
        for entitycreature in entitytoken.allprop(exact_value='CREATURE', args_count=1):
            if entitycreature.value not in discbonusdict: discbonusdict[entitycreature.arg()] = 0.0
            discbonusdict[entitycreature.arg()] += entity_bonus
        
    # Apply the discipline bonuses
    applied = 0
    for creaturename, discbonus in discbonusdict.iteritems():
        creaturetoken = creaturedict[creaturename]
        if creaturetoken.getprop(exact_value='NATURAL_SKILL', exact_arg=((0, 'DISCIPLINE'),)):
            pydwarf.log.debug('Creature %s already has natural discipline skill, skipping.' % creaturename)
        elif discbonus < 0:
            pydwarf.log.debug('Creature %s would receive a negative bonus %f, skipping.' % (creaturename, discbonus))
        elif discbonus > 0:
            roundedbonus = int(math.ceil(discbonus))
            pydwarf.log.debug('Applying bonus of %f (Rounded up to %d) to creature %s...' % (discbonus, roundedbonus, creaturename))
            creaturetoken.add(raws.token(value='NATURAL_SKILL', args=['DISCIPLINE', str(roundedbonus)]))
            applied += 1
            
    # All done!
    if applied > 0:
        return pydwarf.success('Gave natural discipline skill bonuses to %d creatures.' % applied)
    else:
        return pydwarf.failure('Gave natural discipline skill bonuses to no creatures.')
Example #12
0
def subterraneanplants(df):
    # Get subterranean plants
    subplants = []
    for plant in df.allobj('PLANT'):
        if plant.getprop('BIOME:SUBTERRANEAN_WATER'):
            subplants.append(plant)
    if not len(subplants):
        return pydwarf.failure('Found no subterranean plants.')

    # Ensure each has all four seasons
    pydwarf.log.info('Found %d subterranean plants. Modifying...' %
                     len(subplants))
    modified = 0
    for subplant in subplants:
        seasontokens = subplant.allprop(value_in=seasons)
        if len(seasontokens) > 0 and len(seasontokens) < len(seasons):
            pydwarf.log.debug('Adding season tokens to %s...' % subplant)
            # First remove the existing tokens (To avoid making duplicates)
            for seasontoken in seasontokens:
                seasontoken.remove()
            # Then add all four anew
            for season in seasons:
                subplant.add(raws.token(value=season))
            modified += 1
        else:
            pydwarf.log.debug(
                'Plant %s either has no seasonal tokens or already has all of them, skipping.'
                % subplant)

    # All done
    if modified > 0:
        return pydwarf.success('Made %d subterranean plants grow year-round.' %
                               modified)
    else:
        return pydwarf.failure(
            'All subterranean plants already grew year-round.')
Example #13
0
def trans(dfraws, species=default_species, beards=True, frequency=500):
    # Add new interaction
    pydwarf.log.debug('Adding sterility interaction...')
    objinteraction = dfraws.get('OBJECT:INTERACTION')
    if objinteraction:
        objinteraction.add(pretty=add_sterile_interaction)
    else:
        return pydwarf.failure('Unable to add sterility interaction.')

    # Add new castes
    creaturetokendict = dfraws.objdict('CREATURE')
    castefailures = []
    for creature in species:
        pydwarf.log.debug('Handling creature %s...' % creature)
        creaturetoken = creaturetokendict.get(creature)
        if creaturetoken:
            castes = creaturetoken.alluntil(exact_value='CASTE',
                                            args_count=1,
                                            until_exact_value='CREATURE')
            if len(castes) == 2 and ((castes[0].args[0] == 'MALE'
                                      and castes[1].args[0] == 'FEMALE') or
                                     (castes[1].args[0] == 'MALE'
                                      and castes[0].args[0] == 'FEMALE')):

                # Remove DESCRIPTION token from the creature and add it to each caste
                descriptiontoken = creaturetoken.get(exact_value='DESCRIPTION',
                                                     args_count=1)
                if descriptiontoken:
                    descriptiontoken.remove()
                    for castetoken in castes:
                        castetoken.add(token=raws.token.copy(descriptiontoken))

                # Handle existing castes
                for caste in castes:
                    # Add beards to dwarven women
                    if beards and caste.args[0] == 'FEMALE':
                        caste.add(pretty=add_beard_tokens)
                    # Add population ratio token
                    caste.add(
                        raws.token(value='POP_RATIO', args=[str(frequency)]))

                # Add each new caste
                for castename, castedict in additional_castes.iteritems():
                    castetoken = castes[0].add(raws.token(value='CASTE',
                                                          args=[castename]),
                                               reverse=True)
                    # Every new caste gets these tokens
                    castetoken.add(pretty=add_trans_tokens)
                    # Add beards to new dwarf castes
                    if beards and creature == 'DWARF':
                        castetoken.add(pretty=add_beard_tokens)
                    # Tokens unique to each new caste
                    if 'addtokens' in castedict:
                        castetoken.add(pretty=castedict['addtokens'])
                    # Add the caste-specific description
                    description = ' '.join(
                        (descriptiontoken.args[0], castedict['description']
                         )) if descriptiontoken else castedict['description']
                    castetoken.add(
                        raws.token(value='DESCRIPTION', args=[description]))

            else:
                pydwarf.log.error('Unexpected castes for creature %s: %s.' %
                                  (creature, castes))
                castefailures.append(creature)

        else:
            pydwarf.log.error('Failed to find token for creature %s.' %
                              creature)
            castefailures.append(creature)

    if len(castefailures) == 0:
        return pydwarf.success('Added new castes to %d creatures.' %
                               len(species))
    else:
        return pydwarf.failure(
            'Added new castes to %d creatures, but failed to add castes to %s.'
            % (len(species) - len(castefailures), castefailures))
Example #14
0
def additemstoents(dfraws, armouryraws, remove_entity_items):
    # Screw around with which items are allowed for which entities
    for entityname, aentity in armoury_entities.iteritems():
        dfentity = dfraws.get(exact_value='ENTITY', exact_args=[entityname])
        entityitems = {}
        if dfentity:
            pydwarf.log.debug('Handling entity %s...' % dfentity)

            # Maintain this dict because it makes ammo easier to add
            weapons = {}

            # If we're removing items, just remove all the present ones in one go before adding things back
            if remove_entity_items:
                for itemtoken in dfentity.alluntil(value_in=armoury_entities,
                                                   args_count=1,
                                                   until_exact_value='ENTITY'):
                    itemtoken.remove()

            # Time to add the items!
            for itemtype, items in aentity.iteritems():
                if itemtype != 'AMMO':
                    for itemname in items:
                        # Account for names that were changed from the normal DF raws
                        if itemname in weird_armoury_names:
                            itemname = weird_armoury_names[itemname]
                        # Add the token if it isn't there already
                        dftoken = None if remove_entity_items else dfentity.getuntil(
                            exact_value=itemtype,
                            exact_args=[itemname],
                            until_exact_value='ENTITY')
                        if remove_entity_items or not dftoken:
                            dftoken = dfentity.add(
                                raws.token(value=itemtype, args=[itemname]))
                        if itemtype == 'WEAPON': weapons[itemname] = dftoken

            # Now add the ammunition
            if 'AMMO' in aentity:
                for weaponname, ammos in aentity['AMMO'].iteritems():
                    weapontoken = weapons.get(weaponname)
                    if not weapontoken:
                        weapontoken = dfentity.get(exact_value='WEAPON',
                                                   exact_args=[weaponname])
                    if weapontoken:
                        ammotokens = {
                            token.args[0]: token
                            for token in weapontoken.alluntil(
                                exact_value='AMMO',
                                args_count=1,
                                until_except_value='AMMO')
                        }
                        for addammo in ammos:
                            if addammo not in ammotokens:
                                weapontoken.add(
                                    raws.token(value='AMMO', args=[addammo]))
                    else:
                        pydwarf.log.error(
                            'Failed to add ammo %s to weapon %s.' % ammos,
                            weaponname)

        else:
            pydwarf.log.error('Failed to find entity %s for editing.' %
                              entityname)
Example #15
0
def trans(df, species=default_species, beards=True, frequency=500):
    # Add new interaction
    response = pydwarf.scripts.pineapple.utils.addobject(
        df,
        add_to_file='raw/objects/smeeprocket_transgender_interaction.txt',
        tokens=add_sterile_interaction)
    if response:
        pydwarf.log.debug('Added sterility interaction.')
    else:
        return pydwarf.failure('Unable to add sterility interaction.')

    # Add new castes
    castefailures = []
    creaturetokens = df.allobj(type='CREATURE', id_in=species)
    for creaturetoken in creaturetokens:
        pydwarf.log.debug('Handling creature %s...' % creaturetoken)

        castes = creaturetoken.allprop(exact_value='CASTE', args_count=1)
        if (len(castes) == 2 and
            ((castes[0].args[0] == 'MALE' and castes[1].args[0] == 'FEMALE') or
             (castes[1].args[0] == 'MALE' and castes[0].args[0] == 'FEMALE'))):

            # Remove DESCRIPTION token from the creature and add it to each caste
            descriptiontoken = creaturetoken.get(exact_value='DESCRIPTION',
                                                 args_count=1)
            if descriptiontoken:
                descriptiontoken.remove()
                for castetoken in castes:
                    castetoken.add(token=descriptiontoken.copy())

            # Handle existing castes
            for caste in castes:
                # Add beards to dwarven women
                if beards and caste.args[0] == 'FEMALE':
                    caste.add(pretty=add_beard_tokens)
                # Add population ratio token
                caste.add(raws.token(value='POP_RATIO', args=[str(frequency)]))

            # Add each new caste
            for castename, castedict in additional_castes.iteritems():
                castetoken = castes[0].add(raws.token(value='CASTE',
                                                      args=[castename]),
                                           reverse=True)
                # Every new caste gets these tokens
                castetoken.add(pretty=add_trans_tokens)
                # Add beards to new dwarf castes
                if beards and creaturetoken.arg() == 'DWARF':
                    castetoken.add(pretty=add_beard_tokens)
                # Tokens unique to each new caste
                if 'addtokens' in castedict:
                    castetoken.add(pretty=castedict['addtokens'])
                # Add the caste-specific description
                description = ' '.join(
                    (descriptiontoken.args[0], castedict['description']
                     )) if descriptiontoken else castedict['description']
                castetoken.add(
                    raws.token(value='DESCRIPTION', args=[description]))

        else:
            pydwarf.log.error(
                'Unexpected castes for creature %s: %s.' %
                (creaturetoken, ', '.join(str(caste) for caste in castes)))
            castefailures.append(creaturetoken)

    if len(castefailures) == 0:
        return pydwarf.success('Added new castes to %d creatures.' %
                               len(species))
    else:
        return pydwarf.failure(
            'Added new castes to %d creatures, but failed to add castes to %s.'
            % (len(species) - len(castefailures), ', '.join(
                str(token) for token in castefailures)))
Example #16
0
def armoury(df, remove_entity_items=True):
    try:
        pydwarf.log.debug('Loading armoury raws from %s.' % armoury_dir)
        armouryraws = raws.dir(root=armoury_dir, log=pydwarf.log)
    except:
        return pydwarf.failure('Unable to load armoury raws.')

    # Persist a list of armoury item tokens because we're going to be needing them for a few things
    armouryitemtokens = armouryraws.allobj(type_in=armoury_item_objects)

    # Rename items in the armoury raws in accordance with a manually compiled list of naming oddities
    for item in armouryitemtokens.all(arg_in=(0, weird_armoury_names)):
        item.args[0] = weird_armoury_names[item.args[0]]

    # Remove any existing items in the raws which share an id with the items about to be added
    pydwarf.log.debug('Removing obsolete items.')
    df.removeallobj(type_in=armoury_item_objects,
                    id_in=[token.arg() for token in armouryitemtokens])

    # Look for files made empty as a result (of which there should be a few) and remove them
    removedfiles = []
    for file in df.files.values():
        if isinstance(file, raws.rawfile) and len(file) <= 1:
            pydwarf.log.debug('Removing emptied file %s.' % file)
            file.remove()
            removedfiles.append(file)

    # Get a list of entity tokens corresponding to the relevant names
    entitytokens = [df.getobj('ENTITY', entity) for entity in armoury_entities]

    # If remove_entity_items is set to True, remove all existing tokens which permit relevant items
    # Otherwise, just remove the ones with conflict with those about to be added
    for entitytoken in entitytokens:
        pydwarf.log.debug('Removing permission tokens from %s.' % entitytoken)
        entitytoken.removeallprop(
            value_in=armoury_items,
            arg_in=(None if remove_entity_items else
                    (0, [token.args[0] for token in armouryitemtokens])))

    # Now add all the armoury raw files that have items in them
    try:
        for file in armouryraws.iterfiles():
            if file.kind == 'raw' and file.name.startswith('item_'):
                pydwarf.log.debug('Adding file %s to raws.' % file)
                copy = file.copy()
                copy.loc = 'raw/objects'
                copy.name += '_armoury_stal'
                df.add(copy)
    except:
        pydwarf.log.exception('Encountered exception.')
        return pydwarf.failure('Failed to add armoury item raws.')

    # Add new permitted item tokens
    try:
        for entitytoken in entitytokens:
            pydwarf.log.debug('Permitting items for %s.' % entitytoken)
            for itemtype, items in armoury_entities[
                    entitytoken.arg()].iteritems():
                for item in items:
                    entitytoken.add(
                        raws.token(
                            value=itemtype,
                            args=[weird_armoury_names.get(item[0], item[0])] +
                            item[1:]))
    except:
        pydwarf.log.exception('Encountered exception.')
        return pydwarf.failure('Failed to permit items for entities.')

    # And add the new reactions
    try:
        pydwarf.log.debug('Adding new reactions.')
        reactions = armouryraws['reaction_armoury'].copy()
        reactions.loc = 'raw/objects'
        reactions.name = 'reaction_armoury_stal'
        response = pydwarf.urist.getfn('pineapple.easypatch')(
            df, reactions, permit_entities=armoury_entities.keys())
        if not response: return response
    except:
        pydwarf.log.exception('Encountered exception.')
        return pydwarf.failure('Failed to add new reactions.')

    # All done!
    return pydwarf.success()
Example #17
0
def cavegrass(df,
              grasses=default_grasses,
              add_file='plant_grasses_cavegrass_pineapple'):
    # Add the new file for new grasses
    grassfile = None
    if add_file:
        try:
            grassfile = df.add(add_file)
            grassfile.add('OBJECT:PLANT')
        except:
            pydwarf.log.exception('Failed to add file %s.' % add_file)
            return pydwarf.failure('Failed to add file %s.' % add_file)

    # Handle each grass
    failures = 0
    added = 0
    changed = 0
    grasstokens = df.objdict(type='PLANT')
    for grassname, grassdict in grasses.iteritems():
        pydwarf.log.debug('Handling grass %s.' % grassname)
        grasstoken = grasstokens.get(grassname)

        # Some extra handling for new grasses
        if not grasstoken:
            pydwarf.log.debug('Grass %s isn\'t defined yet, adding.' %
                              grassname)
            grasstoken = grassfile.add(
                raws.token(value='PLANT', args=[grassname], prefix='\n\n'))
            if 'template' in grassdict:
                templatetoken = grasstokens.get(grassdict['template'])
                if not templatetoken:
                    pydwarf.log.error(
                        'Couldn\'t find template %s to apply to grass %s.' %
                        (grassdict['template'], grassname))
                    failures += 1
                else:
                    props = templatetoken.allprop(value_not_in=('ALL_NAMES',
                                                                'NAME',
                                                                'NAME_PLURAL',
                                                                'ADJ'))
                    grasstoken.add(props.copy())
            added += 1
        else:
            changed += 1

        # Handling for both new and existing grasses
        if 'add_tokens' in grassdict:
            grasstoken.add(grassdict['add_tokens'])
        if 'remove_tokens' in grassdict:
            tokens = raws.tokenparse.parseplural(grassdict['remove_tokens'])
            for token in tokens:
                removetoken = grasstoken.getprop(match_token=token)
                if removetoken:
                    removetoken.remove()
                else:
                    pydwarf.log.error(
                        'Attempted to remove token %s from %s but the token wasn\'t present.'
                        % (removetoken, grassname))
        if 'colors' in grassdict:
            grasscolors = grasstoken.getprop('GRASS_COLORS')
            if grasscolors:
                grasscolors.args = list(grassdict['colors'])
            else:
                grasstoken.add(
                    raws.token(value='GRASS_COLORS',
                               args=list(grassdict['colors'])))
        if 'depth' in grassdict:
            grassdepth = grasstoken.getprop('UNDERGROUND_DEPTH')
            if grassdepth:
                grassdepth.args = list(grassdict['depth'])
            else:
                grasstoken.add(
                    raws.token(value='UNDERGROUND_DEPTH',
                               args=list(grassdict['depth'])))

    # All done!
    if failures == 0:
        return pydwarf.success('Changed %d grasses and added %d new ones.' %
                               (changed, added))
    else:
        return pydwarf.failure()
Example #18
0
def materialsplus(dfraws):
    exceptions = 0
    addedreactions = []

    try:
        for zircon in dfraws.all(exact_value='INORGANIC',
                                 re_args=['.* ZIRCON']):
            addaftertemplate(
                zircon,
                'MATERIAL_REACTION_PRODUCT:KROLL_PROCESS:INORGANIC:ZIRCONIUM_PUTNAM'
            )
        pydwarf.log.debug('Added reaction to zircons.')
    except:
        pydwarf.log.exception('Failed to add reaction to zircons.')
        exceptions += 1

    try:
        for beryl in dfraws.all(
                exact_value='INORGANIC',
                re_args=['.* BERYL|HELIODOR|MORGANITE|GOSHENITE|EMERALD']):
            addaftertemplate(beryl, 'REACTION_CLASS:BERYLLIUM')
        pydwarf.log.debug('Added reaction to beryls.')
    except:
        pydwarf.log.exception('Failed to add reaction to beryls.')
        exceptions += 1

    try:
        chromite = dfraws.get('INORGANIC:CHROMITE')
        pyrolusite = dfraws.get('INORGANIC:PYROLUSITE')
        addaftertemplate(chromite,
                         '[METAL_ORE:CHROMIUM_PUTNAM:100][METAL_ORE:IRON:50]')
        addaftertemplate(pyrolusite, 'METAL_ORE:MANGANESE_PUTNAM:100')
        pydwarf.log.debug('Added titanium ores.')
    except:
        pydwarf.log.exception('Failed to add titanium ores.')
        exceptions += 1

    try:
        for silicon in dfraws.all(
                exact_value='INORGANIC',
                re_args=
            [
                'ANDESITE|OLIVINE|HORNBLENDE|SERPENTINE|ORTHOCLASE|MICROCLINE|MICA'
            ]):
            addaftertemplate(silicon, 'REACTION_CLASS:SILICON')
        pydwarf.log.debug('Added silicon reactions.')
    except:
        pydwarf.log.exception('Failed to add silicon reactions.')
        exceptions += 1

    try:
        dolomite = dfraws.get('INORGANIC:DOLOMITE')
        addaftertemplate(dolomite, 'REACTION_CLASS:PIDGEON_PROCESS')
        pydwarf.log.debug('Added reaction to dolomite.')
    except:
        pydwarf.log.exception('Failed to add reaction to dolomite.')
        exceptions += 1

    for root, dirs, files in os.walk(
            os.path.join(os.path.dirname(os.path.abspath(__file__)),
                         'Materials Plus')):
        for filename in files:
            suffix = '_mat_plus.txt'
            if filename.endswith(suffix):
                path = os.path.join(root, filename)
                destname = 'putnam_%s' % filename[:-len(suffix)]
                rfile = dfraws.getfile(destname)
                if rfile:
                    pydwarf.log.debug('Appending data to file %s from %s...' %
                                      (destname, path))
                    with open(path, 'rb') as matplusfile:
                        rfile.add(pretty=matplusfile)
                else:
                    with open(path, 'rb') as matplusfile:
                        rfile = dfraws.addfile(rfile=raws.file(
                            header=destname, rfile=matplusfile))
                    pydwarf.log.debug('Adding data to new file %s.' % destname)
                    addedreactions += rfile.all(exact_value='REACTION',
                                                args_count=1)

    try:
        mountain = dfraws.get('ENTITY:MOUNTAIN')
        for reaction in addedreactions:
            mountain.add(
                raws.token(value='PERMITTED_REACTION',
                           args=[reaction.args[0]]))
        pydwarf.log.debug('Added %d permitted reactions.' %
                          len(addedreactions))
    except:
        pydwarf.log.exception('Failed to add permitted reactions.')
        exceptions += 1

    if exceptions == 0:
        return pydwarf.success()
    else:
        return pydwarf.failure('Failed to complete %d operations.' %
                               exceptions)