Beispiel #1
0
def generate_title(author):
    book = choice(books['books'])

    if flip():
        book = f"{choice(books['attributes'])} {book}"

    subjects = [s for c in spells['spells'].values() for s in c]
    subject = choice(subjects)

    if flip():
        subject = ' and '.join(
            (plural(subject), choice_without(subjects, subject.lower())))

    subject = plural(subject)

    if flip():
        subject = f"{choice(spells['attributes'])} {subject}"

    if flip():
        return titlecase(f"{author}'s {book} {subject}")

    if flip():
        return titlecase(f"{book} {name()}'s {subject}")

    return titlecase(f'{book} {subject}')
Beispiel #2
0
def generate_frame():
    gender = choice(list(figures['genders'].values()))
    figure = gender['noun']
    pronouns = gender['pronouns']
    attribute = choice(figures['attributes'])
    locale = choice(locales['locales'])

    # Prologue
    prologue = ' '.join(
        (indefinite(attribute).capitalize(), figure,
         choice(['crept into', 'strode into', 'stole into', 'entered']),
         indefinite(choice(locales['attributes'])), f'{locale}, '))

    companion = choice(figures['companions']['types']) if flip() else None

    if companion:
        prologue += ' '.join(
            ('accompanied by',
             indefinite(choice(figures['companions']['attributes'])),
             f'{companion}. '))
    else:
        prologue += f'{choice(figures["dress"])}. '

    prologue += (
        f'{pronouns[0].capitalize()} stopped as {pronouns[2]} eyes lit upon '
        f'the object of {pronouns[2]} quest. ')

    if flip():
        prologue += (
            f'The {figure} suddenly surged forward and grasped the tome '
            'eagerly. ')
    else:
        prologue += (
            f'The {figure} began to move again, approaching the tome warily. ')

    prologue += (
        f'{pronouns[0].capitalize()} lifted it from its resting place, then '
        'opened its cover and began to read.')

    # Epilogue
    epilogue = ' '.join(
        (f'The {attribute} {figure} closed the book.',
         f'Rising to {pronouns[2]} feet,',
         f'{pronouns[0]} beckoned to {pronouns[2]} {companion} and set out'
         if companion else f'{pronouns[0]} left the {locale}',
         f'in search of components.'))

    return prologue, epilogue
Beispiel #3
0
def name():
    first = word().capitalize()

    if flip():
        return first

    return f'{first} {"of " if maybe(0.25) else ""}{word().capitalize()}'
Beispiel #4
0
def pick_ingredient():
    # This is horrifyingly inefficient
    item = choice(list(components['ingredients'].items()))
    item[1]['name'] = item[0]
    item = item[1]

    part = (choice(list(components['parts'][item['type']].items()))
            if item['parts'] else None)

    # Item types: animal, plant, fungus, solid, liquid, intangible
    # Part types: solid, liquid, intangible
    type = part[1] if part else item['type']

    attributes = components['attributes']['general']

    if type != 'intangible':
        count, pluralize = choice(list(zip(counts, plurals)))
    else:
        count, pluralize = None, False

    if type in ('solid', 'liquid'):
        # Note no +=! For lists, += modifies the original list!
        attributes = attributes + components['attributes'][type]
        attribute = choice(attributes) if maybe(0.25) else None
        measure = choice(components['measures'][type])

        ingredient = f'{part[0]} of {item["name"]}' if part else item['name']

        item = {'item': ingredient, 'type': type}

        ingredient = ' '.join((
            str(count),
            plural(measure) if pluralize else measure,
            f'{attribute} {ingredient}' if attribute else ingredient,
        ))

        if maybe(0.2):
            ingredient += f', {choice(components["preparations"][type])}'

    else:
        ingredient = item['name']

        if part:
            ingredient = f'{part[0]} of {ingredient}'
        elif type == 'animal' and flip():
            ingredient = f'live {ingredient}'

        if pluralize:
            ingredient = plural(ingredient)

        item = {'item': ingredient, 'type': type}

        if maybe(0.25):
            ingredient = f'{choice(attributes)} {ingredient}'

        if count:
            ingredient = f'{count} {ingredient}'

    return item, ingredient
Beispiel #5
0
def generate_directions(items, spell, afflicted, authors, target):
    liquid = [i['item'] for i in items if i['type'] == 'liquid']
    solid = [i['item'] for i in items if i['type'] == 'solid']
    other = [i['item'] for i in items if i['type'] not in ('solid', 'liquid')]

    directions = initial(type, liquid) + '\n\n'

    if liquid and solid and flip():
        # Group liquids and solids, then add anything else
        directions += grouped_directions(liquid, solid, other)
    else:
        # Add each ingredient individually
        directions += individual_directions(items)

    if flip():
        directions += '\n\n' + final(spell, afflicted, liquid, authors, target)

    return directions
Beispiel #6
0
def grouped_directions(liquid, solid, other):
    directions = choice([
        f'Combine {oxford(liquid)}.',
        f'Add {oxford(liquid)}, stirring gently.',
        f'Beat together {oxford(liquid)} until frothy.',
        f'Pour {oxford(liquid)} into prepared vessel.',
    ])

    if maybe(0.33):
        directions += ' Bring to a boil, stirring ' + choice([
            'vigorously.', 'continuously.', 'occasionally.', 'intermittently.',
            'once.'
        ])
    elif flip():
        directions += (
            ' Lower the temperature until the mixture begins to congeal.')

    next_direction = choice([
        f'Stir in {oxford(solid)}, individually.',
        f'Blend in {oxford(solid)}, stirring until fully dissolved.',
        f'Add {oxford(solid)}.' + (' Do not overmix.' if flip() else ''),
        f'Beat in {oxford(solid)} until only a few chunks remain.',
    ])

    directions += '\n\n' + optional_action(next_direction)

    if other:
        next_direction = ' '.join([
            choice([
                f'Add {i}.',
                f'Carefully add {i}.',
                f'Cautiously add {i}.',
                f'Blend in {i}.',
                f'Fold in {i}.',
                f'Combine with {i}.',
                f'Add {i} and mix thoroughly.',
            ]) for i in other
        ])

        directions += '\n\n' + optional_action(next_direction)

    return directions
Beispiel #7
0
def generate_page(authors):
    # Generate spell title
    spell = choice(list(spells['spells'].keys()))
    title = choice(spells['spells'][spell])

    afflicted = choice(parts) if spell in ('blight', 'cure') else None
    target = plural(choice(summons))

    if flip():
        title = f'{choice(spells["attributes"])} {title}'

    if spell == 'cure':
        title += ' for '
    else:
        title += ' of '

    if spell == 'summoning':
        title += target
    elif spell in ('blight', 'cure'):
        title += f'{choice(spells["maladies"])} {afflicted}'
    else:
        title += choice(spells['subjects'])

    if maybe(0.2):
        title = f"{choice(authors).split()[0]}'s {title}"

    title = titlecase(title)

    # Generate list of ingredients
    items, ingredients = generate_ingredients()
    ingredients = f'\n* ' + '\n* '.join(ingredients)

    # Generate directions
    directions = generate_directions(items, spell, afflicted, authors, target)

    page = '\n\n'.join((
        f'## {title}',
        f'### Ingredients\n{ingredients}',
        f'### Directions\n\n{directions}',
    ))

    return page
Beispiel #8
0
def individual_directions(items):
    directions = choice([
        f'Start with {items[0]["item"]}.',
        f'To begin, add {items[0]["item"]}.',
        f'First, add {items[0]["item"]}.',
        f'Add {items[0]["item"]} to the prepared vessel.',
    ])

    for i in items[1:]:
        if i['type'] == 'liquid':
            next_direction = choice([
                f'Add {i["item"]}.',
                f'Pour in {i["item"]}.',
                f'Mix in {i["item"]}.',
            ]) + (f' Stir {choice(["vigorously", "gently", "once"])}.'
                  if flip() else '')

        elif i['type'] == 'solid':
            next_direction = choice([
                f'Add {i["item"]}.',
                f'Mix in {i["item"]}.',
                f'Fold in {i["item"]}.',
            ])

        else:
            next_direction = choice([
                f'Add {i["item"]}.',
                f'Carefully add {i["item"]}.',
                f'Cautiously add {i["item"]}.',
                f'Blend in {i["item"]}.',
                f'Fold in {i["item"]}.',
                f'Combine with {i["item"]}.',
                f'Add {i["item"]} and mix thoroughly.',
            ])

        directions += '\n\n' if maybe(0.2) else ' '
        directions += optional_action(next_direction, 0.2)

    return directions
Beispiel #9
0
def final(type, afflicted, liquid, authors, target):
    # Even though it's inefficient, build every possible set of directions,
    # then choose one, because otherwise the code becomes very bad
    options = [
        'Heat until all of the liquid has boiled away and the black fumes have'
        ' blotted out the great and minor lights of the sky.',
        'Take a handful and scatter it in a loose circle.',
        'Take a fistful and scatter it to the wind.',
        'Take a pinch between thumb and forefinger and inhale deeply.',
        'Paint face, arms, and chest with the compound. The spell will take '
        'hold within seconds.',
        'Hum softly as you scatter the contents.',
        'Move one forefinger through the mixture, making the approved sigils '
        'and signs, then discard.',
        f"Chant your preferred invocations over the compound ({authors[1]}'s" +
        (' Poem of Power' if flip() else ' Song of Sanctity') +
        ' recommended), then reserve for future use.',
        'The mixture should be shaken, then imbibed while making the '
        'appropriate runic gestures with the left hand.',
        f'Speak the seven forbidden words, then submerge one arm in the '
        'compound up to the elbow and withdraw.'
        if type not in ('curse', 'blight', 'cure') and liquid else None,
        'Bring to a rolling boil and have the subject inhale the vapours for '
        f'{srange()} hours, or until the illness passes.'
        if type == 'cure' and liquid else None,
        f'Bring to a rolling boil and steep a length of bandage for {srange()}'
        ' hours.' + ('Still hot, ' if flip() else 'Let cool, then ') +
        f'apply the bandages to {afflicted}, wrapping ' +
        ('tightly.' if flip() else 'loosely.')
        if type == 'cure' and liquid else None,
        f"Make a poultice using {authors[2]}'s standard method. Apply to "
        f'{afflicted} immediately.' if type == 'cure' and liquid else None,
        f'With {"gloved" if flip() else "bare"} hands, fold a small measure of'
        ' the curative into an equal amount of wax or tallow, the massage into'
        f" the subject's {afflicted}." if type == 'cure' else None,
        f'With {"gloved" if flip() else "bare"} hands, apply the curative to '
        f'the {afflicted} directly, then bandage.' if type == 'cure' else None,
        'Sprinkle a loose handful of the compound over the subject' +
        (f"'s {afflicted}," if type in ('cure', 'curse') else ',') +
        (' mouthing the standard invocations.'
         if flip() else ' forming the standard signs with the left hand.')
        if type not in ('general', 'summoning') else None,
        f'Ensure that the subject ingests the compound within {srange()} '
        'hours for maximum effectiveness.'
        if type not in ('general', 'summoning') else None,
        'Apply directly to the forehead.'
        if type not in ('general', 'summoning') else None,
        f"Following {authors[3]}'s three maxims, create a wax simulacrum of the"
        ' target. Submerge in the brew, and boil until all liquid has '
        'evaporated.' if type in ('curse', 'blight') and liquid else None,
        f"Following {authors[4]}'s four precepts, create a cloth manikin of the"
        ' target. Coat liberally with the compound, then burn. Scatter the '
        'ashes.' if type in ('curse', 'blight') else None,
        "Take a single strand of the target's hair, break it in two, and add "
        'it to the concoction, mixing thoroughly.'
        if type in ('curse', 'blight') else None,
        'Dig a hole six feet deep and bury. Excavate after the spring thaw.'
        if type == 'general' else None,
    ]

    direction = choice([o for o in options if o])

    if type == 'summoning':
        direction += (
            f' {srange()} {target} should begin to appear within ' +
            ('seconds.' if flip() else 'minutes.' if flip() else 'hours.'))

    return direction
Beispiel #10
0
def initial(type, liquid):
    stone = choice(materials['stone'])
    metal = choice(materials['metal'])
    fabric = choice(materials['fabric'])
    hard = choice(materials['hardwood'])
    soft = choice(materials['softwood'])

    if flip():
        wood, backup = hard, choice_without(materials['hardwood'], hard)
    else:
        wood, backup = soft, choice_without(materials['softwood'], soft)

    options = [
        'Prepare a ' + choice(['broad ', 'narrow ', 'shallow ', 'deep ']) +
        choice([
            f'{stone} mortar and pestle.',
            f'{metal} mortar and pestle.',
            f'{wood} mortar and pestle.',
            f'wooden mortar and pestle ({wood} preferred, though {backup} will'
            ' do).',
        ]),
        f'Heat a cauldron over a well-banked fire of {wood}' +
        (f' and {backup}.' if flip() else '.') if liquid else None,
        f'Place {indefinite(metal)} boiler over a brazier and etch with runes '
        'while it heats.' if liquid else None,
        'Array components on {indefinite(fabric)} sheet according to gestalt '
        'principles.' if not liquid else None,
        f'Ready {indefinite(fabric)} sack for mixing.' if not liquid else None,
        'Ready a vessel composed of a ' + choice(['non-', '']) +
        'ferromagnetic metal (if unsure of its composition, test with a '
        'lodestone).' if flip() else None,
        f'Ready {indefinite(choice([stone, metal, wood]))} vessel and ' +
        choice([
            'chill until frost is just visible.',
            'heat until the bottom begins to scorch.',
        ]),
    ]

    direction = choice([o for o in options if o])

    if flip():
        options = [
            'On a ' + choice(['misty', 'cloudy', 'rainy', 'dry', 'humid']) +
            choice([' morning', ' day', ' afternoon', ' evening', ' night']),
            'Facing ' + choice(['north', 'south', 'east', 'west']),
            'Under a ' + choice(
                ['waxing', 'waning', 'gibbous', 'crescent', 'full', 'new']) +
            ' moon', 'With a ' + choice(['rising ', 'setting ']) + choice([
                'sun',
                'moon',
                'Mercury',
                'Mars',
                'Venus',
            ]) + ' in the sky', 'Under the sign of ' + choice([
                'Capricorn', 'Gemini', 'Pisces', 'Virgo', 'Cancer', 'Leo',
                'Aquarius', 'Taurus', 'Libra', 'Scorpius', 'Aries',
                'Sagittarius', 'Ophiuchus', 'Cassiopeia', 'Orion'
            ]), 'After aligning yourself ' +
            choice(['parallel', 'perpendicular']) + ' to the ' +
            choice(['governing', 'major', 'minor']) + ' leyline'
        ]

        direction = f'{choice(options)}, {uncapitalize(direction)}'

    return direction