def get_character_class(self, classname=None):
     """
     We determine character class based on your prime attribute.
     """
     if classname:
         return characterclass.CLASS_BY_NAME[classname]
     if self.demihumans and d(100) < 50:
         # sorted attributes (excluding charisma)
         attributes = sorted(self.attributes[:5], reverse=True,
                             key=operator.itemgetter(1))
         if not (self.thieves and 'DEX' == attributes[0][0] and d(100) < 80):
             # We randomly test because there is overlap in what could
             # succeed and we want each to be equally likely in the long
             # run.
             tests = [_is_dwarf, _is_halfling, _is_elf]
             random.shuffle(tests)
             for t in tests:
                 result, c = t(self.INT, self.CON, self.DEX, self.STR)
                 if result:
                     return c
     # You're playing a human!
     index = 4 if self.thieves else 3
     prime_attribute, _ = sorted(self.attributes[:index],
                                 reverse=True, key=operator.itemgetter(1))[0]
     return characterclass.PRIME_REQUISITE[prime_attribute]
    def get_background(self):
        backgrounds = [
            ("Poulticer", "mortar and pestle, dagger, mystery potion (you know what it doesn't do), oil flask, chalk"),
            ("Slaughterer", "heavy cleaver, half-chain, a string of fine sausage, twine"),
            ("Fungus Picker", "two different kinds of mushrooms, club, sling, rabbuck-hide gloves, lamp, oil flask"),
            ("Pickler", "pickle cask with delicious pickles, spice-rack, trident, wading boots"),
            ("Charcoal Burner", "Iron-banded broom, knife, sooty rags, mastic, crampons"),
            ("Purloiner", "hammer and spike, off-hand daggers, 50' rope, clothes with hidden pockets, a golden ring (stolen)"),
            ("Hunter", "crossbow OR bow, quiver, skinning-knife, leather jack, axe, brace of smoked frog"),
            ("Noble", "sword and shield and full chain OR pistolet and powderhorn and chain shirt, off-hand dagger, map to 'inheritance', a fine cape and mantle, laudanum OR signet ring"),
            ("Mendicant", "begging bowl, smart pet, reed flute, staff OR club"),
            ("Scribe", "mace, robes, runestones, oil-lamp, lard-pot, vellum, brush and ink"),
            ("Porter", "fists, club, auroch-hide armour, a porter's basket"),
            ("Timberfeller", "great-axe, knife, raspberry aquavit, sling, 50' rope"),
            ("Plumber", "gluepot, throwing hammer, weather-proof overalls"),
            ("Hayseed", "axe OR pitchfork OR threshing flail, dirk, harmonium OR great-kazoo, chewing weed, three torches"),
            ("House-guard", "shield, spear, misericorde, half-chain, club, 50' rope"),
            ("Fisher", "fishing pole and hook, gutting knife, 2 throwing spears, eel-hide armour, 3 torches, a smoked eel"),
            ("Barber", "bonesaw, steggar, clamps, bloody rags, leechjar OR pendulum"),
            ("Scroll-Runner", "running shoes, jerky, 50' rope, emberhorn, dagger, news-scroll, farseeing glass"),
            ("Paramour", "woodblock erotica OR book of poems, sword, perfume (as lamp-oil), locket OR prophylactics, bow and quiver"),
            ("Guild-Partisan", "great-weapon, mancatcher, dagger, hauberk with party armband, guild news-scroll, a set of trade tools (dyer, tanner, weaver, napier, builder, etc.)"),
            ("Bondsman", "waraxe OR crossbow and quiver and club, mail shirt, shield, saexe, gift-ring"),
            ("Apiarist", "chainmail, goggles, club, bellows, smokebomb, honeycomb"),
            ("Sailor", "axe OR cat, off-hand marlinspike, scrimshaw, shield OR leather armour, lodestone"),
            ("Bellman", "hookspear, chainmail shirt, shield, handbell, truncheon, 3 torches"),
            ("Smith", "warhammer OR sword, off-hand hammer, chainmail OR leather armour and shield, anvil, crucible"),
            ("Janissary", "harquebus, powderhorn, chainmail shirt, sword, shield, contract"),
            ("Seer", "silver dagger, cage of finches, brazier"),
            ("Ursar", "mancatcher, 20' chain, club, hide armour, hand drum"),
            ("Merchant", "fine clothes, guilder's chain, mace OR axe, a servant with a bale of trade goods"),
            ("Wolfs-head", "waraxe, caltrops, leather armour, crossbow, quiver, writ of blood price"),
            ("Therapist", "flail, shield, pendulum, meditation cushion, oil-lamp, oil-pot"),
            ("Skald", "harp OR scroll of epic poetry, off-hand dagger, sword OR bow and quiver, collection plate"),
            ("Drover", "studded leather, whip, club, brand, firehorn, heavy gloves, throwing axe"),
            ("Judicial Functionary", "great-weapon, leather jack, hooded cloak, hanging rope OR tongs, manacles and keys"),
            ("Wildling", "fists, moss and furs, 'lucky' stone, shillelagh"),
            ("Mercenary", "great-weapon OR waraxe and shield, dirk, ringed leathers, bow and quiver, totem"),
        ]
        background, equipment = random.choice(backgrounds)
        equipment = equipment.split(', ')

        bonus_equipment, silver = random.choice([
            (["fists", "a half-empty bottle", "a turnip"], lambda: dice.d(6)),
            (["nullwater", "a white conch"], lambda: dice.xdy(3, 6)),
            (["3 flasks of oil", "a hammer", "iron spikes"], lambda: 0),
            (["quill and ink", "incense"], lambda: 0),
            (["a hex scroll", "a pine sprig"], lambda: dice.d(6) * 10),
            (["sword and scabbard OR waraxe OR warhammer"], lambda: 0),
        ])
        equipment += bonus_equipment
        equipment.append("%d SP" % silver())

        # process the equipment list down to a finite list of stuff
        final_equipment = []
        for e in equipment:
            items = random.choice(e.split(' OR ')).split(' and ')
            final_equipment.append(items)

        return background, ", ".join(list(itertools.chain(*final_equipment)))
Exemple #3
0
 def get_character_class(self, classname=None):
     """
     We determine character class based on your prime attribute.
     """
     if classname:
         return characterclass.CLASS_BY_NAME[classname]
     if self.demihumans and d(100) < 50:
         # sorted attributes (excluding charisma)
         attributes = sorted(self.attributes[:5],
                             reverse=True,
                             key=operator.itemgetter(1))
         if not (self.thieves and 'DEX' == attributes[0][0]
                 and d(100) < 80):
             # We randomly test because there is overlap in what could
             # succeed and we want each to be equally likely in the long
             # run.
             tests = [_is_dwarf, _is_halfling, _is_elf]
             random.shuffle(tests)
             for t in tests:
                 result, c = t(self.INT, self.CON, self.DEX, self.STR)
                 if result:
                     return c
     # You're playing a human!
     index = 4 if self.thieves else 3
     prime_attribute, _ = sorted(self.attributes[:index],
                                 reverse=True,
                                 key=operator.itemgetter(1))[0]
     return characterclass.PRIME_REQUISITE[prime_attribute]
Exemple #4
0
    def get_name(self, colour):
        roll = d(100)
        if roll > 65:
            return None

        adjective = random.choice(Leader.ADJECTIVES)
        noun = random.choice(Leader.NOUNS)
        description = random.choice(Leader.DESCRIPTIONS)

        used_adjective = False
        try:
            description = description.format(adjective=adjective)
            used_adjective = True
        except KeyError:
            pass
        try:
            description = description.format(colour=colour)
        except KeyError:
            pass

        roll = d(12)
        if roll <= 3:
            name = [adjective, noun]
        elif roll <= 7:
            if not used_adjective:
                name = [adjective, noun, description]
            else:
                name = [noun, description]
        else:
            name = [noun, description]
        if not name[0] in ['He', 'Her', 'It', 'She', 'Lady']:
            name = ['the'] + name
        return ' '. join(name)
Exemple #5
0
def scorching_ray(caster, slot, *targets):
    assert slot > 1
    assert caster.slots[slot] > 0
    assert len(targets) <= slot + 1
    for target in targets:
        target.HP -= d(6) + d(6)
    caster.slots[slot] -= 1
Exemple #6
0
 def __init__(self, wizard_name: str, school_name: str):
     self.name = wizard_name
     self.school = MagicSchool(school_name)
     self.offense = d(6) + self.school.modifiers["Offense"]
     self.defense = d(6) + self.school.modifiers["Defense"]
     self.accuracy = d(6) + self.school.modifiers["Accuracy"]
     self.health = dice(3, 6)
     self.wand = Wand()
Exemple #7
0
 def get_population(self, kind):
     # TODO: Figure out actual distribution. These are pretty close.
     if kind == 'Village':
         return xdy(5,95) + 25
     elif kind == 'Castle':
         return xdy(2,50)
     elif kind == 'Citadel':
         return d(100) + d(50)
     else:
         return xdy(5,16) + d(10) + 10
 def initialize_equipment(self):
     """
     Every starts with 3 items, and 3 slots for more items. You can also
     start with weapons and armour (combat equipment) that will increase
     your burden.
     """
     self.equipment = list(random.choice(self.BACKPACKS)) + ['...', '...', '...']
     self.weapons = random.sample(self.WEAPONS, dice.d(3) - 1)
     self.armour = random.sample(self.ARMOUR, dice.d(3) - 1)
     self.burden += len(self.weapons) + len(self.armour)
Exemple #9
0
 def get_wild_talent(self):
     # TODO: what frequency do I actually want here?
     if d(6) != 1:
         return
     talent_roll = self.WIS - d(20)
     if talent_roll < 0:
         save_bonus = abs(talent_roll) / 2
         if save_bonus:
             return "+%d to saves vs. psionic attacks" % save_bonus
         else:
             return None
     else:
         return characterclass.WILD_TALENTS[talent_roll]
Exemple #10
0
 def get_wild_talent(self):
     # TODO: what frequency do I actually want here?
     if d(6) != 1:
         return
     talent_roll = self.WIS - d(20)
     if talent_roll < 0:
         save_bonus = abs(talent_roll) / 2
         if save_bonus:
             return "+%d to saves vs. psionic attacks" % save_bonus
         else:
             return None
     else:
         return characterclass.WILD_TALENTS[talent_roll]
 def initialize_rituals(self):
     """
     Players start play with upto 3 rituals. Each ritual you know increases
     your ruin by 1.
     """
     self.rituals = random.sample(self.RITUALS, dice.d(4) - 1)
     self.ruin += len(self.rituals)
Exemple #12
0
 def get_hp(self):
     """
     LotFP characters have a minimum number of HP.
     """
     hp = d(self.hit_die) + self.get_bonus(*self.attributes[characterclass.CON])
     hp = max(hp, characterclass.LOTFP['min_hp'][self.character_class['name']])
     return hp
 def get_hp(self):
     """
     LotFP characters have a minimum number of HP.
     """
     hp = d(self.hit_die) + self.get_bonus(*self.attributes[characterclass.CON])
     hp = max(hp, characterclass.LOTFP['min_hp'][self.character_class['name']])
     return hp
Exemple #14
0
 def get_hp(self):
     """
     Determine HP based on hit dice and CON modifiers. Note: this value may
     be negative and that is handled by the caller.
     """
     return d(self.hit_die) + self.get_bonus(
         *self.attributes[characterclass.CON])
Exemple #15
0
 def _get_features(self):
     self.body = random.choice(Spawn.FORMS)
     roll = d(16)
     if roll >= 15:
         colours = random.sample(colour.COLOURS[1:], d(3) + 1)
         colours = ', '.join(colours[:-1]) + ' and ' + colours[-1]
         self.colour = colours
     else:
         self.colour = colour.colour()
     self.hide = random.choice(Spawn.HIDES)
     self.eyes = d(8) - 1
     if self.eyes == 0:
         self.eyes = 'no'
     elif self.eyes == 7:
         self.eyes = 'multiple/insectile'
     self.mouth = random.choice(Spawn.MOUTHS)
Exemple #16
0
 def get_level(self):
     roll = d(100)
     if roll <= 1:
         return "1st"
     elif roll <= 5:
         return "2nd"
     elif roll <= 13:
         return "3rd"
     elif roll <= 26:
         return "4th"
     elif roll <= 42:
         return "5th"
     elif roll <= 58:
         return "6th"
     elif roll <= 73:
         return "7th"
     elif roll <= 83:
         return "8th"
     elif roll <= 91:
         return "9th"
     elif roll <= 96:
         return "10th"
     elif roll <= 99:
         return "11th"
     else:
         return random.choice(["12th", "12th", "12th", "13th", "13th",
                               "14th", "15th", "16th"])
Exemple #17
0
def magic_missile(caster, slot, *targets):
    assert caster.slots[slot] > 0
    assert len(targets) <= slot + 2
    assert slot > 0
    for target in targets:
        target.HP -= d(4) + 1
    caster.slots[slot] -= 1
Exemple #18
0
 def __init__(self, d, n=1):
     self.d = d
     self.n = n
     self.original = dice.d(d, n, total=False)
     self.rolls = list(
         self.original
     )  # the `list()` ensures that the list is copied and it's not a reference
Exemple #19
0
    def _get_features(self):
        roll = d(10)
        if roll > 7:
            self.eyes = d(8) - 1
            if self.eyes == 0:
                self.eyes = 'no'
            elif self.eyes == 7:
                self.eyes = 'multiple/insectile'
        elif roll > 4:
            self.eyes = 'glowing',
        else:
            self.eyes = 2

        if d(10) > 7:
            self.mouth = random.choice(Dinosaur.MOUTHS)
            if self.eyes == 2:
                self.mouth = self.mouth.capitalize()
Exemple #20
0
 def _get_powers(self):
     roll = d(100)
     if roll <= 84:
         return []
     if roll == 100:
         return random.sample(Spawn.POWERS, 2)
     else:
         return [random.choice(Spawn.POWERS)]
Exemple #21
0
 def _get_powers(self):
     roll = d(100)
     if roll <= 25:
         return []
     if roll == 100:
         return random.sample(Dinosaur.POWERS, 2)
     else:
         return [random.choice(Dinosaur.POWERS)]
Exemple #22
0
 def _get_alignment(self):
     roll = d(8)
     if roll <= 6:
         return 'Chaotic'
     elif roll == 7:
         return 'Neutral [intelligent]'
     else:
         return 'Neutral [unintelligent]'
Exemple #23
0
 def get_alignment(self):
     roll = d(100)
     if roll <= 50:
         return "Neutral"
     elif roll <= 80:
         return "Chaotic"
     else:
         return "Lawful"
Exemple #24
0
 def get_class(self, kind):
     roll = d(100)
     if roll <= 1:
         return "Spawn of Shub-Niggurath"
     elif roll <= 77:
         return "Fighter" if kind != "Monastery" else "Sorcerer"
     else:
         return "Sorcerer" if kind != "Monastery" else "Fighter"
Exemple #25
0
 def _get_immunities(self):
     roll = d(20)
     if roll <= 10:
         return []
     elif roll == 20:
         return random.sample(Spawn.IMMUNITIES, 2)
     else:
         return [random.choice(Spawn.IMMUNITIES)]
Exemple #26
0
    def __init__(self, *args, **kwargs):
        super(Character, self).__init__(*args, **kwargs)

        # Attributes
        self.skill = dice.d(3) + 3
        self.stamina = dice.xdy(2, 6) + 12
        self.luck = dice.d(6) + 6
        self.appearance = self.get_appearance()

        # Pick a Background
        background = random.choice(self.BACKGROUNDS)

        self.background = background['name'][3:]
        self.description = background['description']
        self.special = background['special']

        # Pick one of the "ORs" for possessions when picking equipment
        self.equipment = [
            random.choice(equipment.split(' OR '))
            for equipment in background['possessions']
        ] + [
            # Add default equipment
            'Knife',
            'Lantern and a flask of oil',
            'Rucksack',
            '6 provisions',
            '%d silver pennies' % dice.xdy(2,6),
        ]

        # Turn random spells into actual spells when picking skills
        self.skills = [
            skill.replace('Random (Table 5)', random.choice(self.MAGIC_SPELLS))
            for skill in background['skills']
        ]

        # Fix some gender issues
        if 'Female' in self.appearance and self.background == 'Lonesome King':
            self.background = 'Lonesome Queen'
        elif self.background == 'Rhino-Man':
            self.appearance = self.appearance.replace('Female, ', '')
            self.appearance = self.appearance.replace('Male, ', '')
        elif self.background == 'Parchment Witch':
            self.appearance = self.appearance.replace('Male', 'Female')
Exemple #27
0
 def get_kind(self):
     roll = d(100)
     if roll <= 2:
         return "Monastery"
     elif roll <= 20:
         return "Castle"
     elif roll <= 43:
         return "Citadel"
     else:
         return "Village"
Exemple #28
0
 def racechoice(self):
     i = d(1,4)
     if i[0] == 1:
         return "Human"
     elif i[0] == 2:
         return "Wood Elf"
     elif i[0] == 3:
         return "Dwarf"
     elif i[0] == 4:
         return "Halfling"
    def __init__(self, *args, **kwargs):
        super(Character, self).__init__(*args, **kwargs)

        # Attributes
        self.skill = dice.d(3) + 3
        self.stamina = dice.xdy(2, 6) + 12
        self.luck = dice.d(6) + 6
        self.appearance = self.get_appearance()

        # Pick a Background
        background = random.choice(self.BACKGROUNDS)

        self.background = background['name'][3:]
        self.description = background['description']
        self.special = background['special']

        # Pick one of the "ORs" for possessions when picking equipment
        self.equipment = [
            random.choice(equipment.split(' OR '))
            for equipment in background['possessions']
        ] + [
            # Add default equipment
            'Knife',
            'Lantern and a flask of oil',
            'Rucksack',
            '6 provisions',
            '%d silver pennies' % dice.xdy(2, 6),
        ]

        # Turn random spells into actual spells when picking skills
        self.skills = [
            skill.replace('Random (Table 5)', random.choice(self.MAGIC_SPELLS))
            for skill in background['skills']
        ]

        # Fix some gender issues
        if 'Female' in self.appearance and self.background == 'Lonesome King':
            self.background = 'Lonesome Queen'
        elif self.background == 'Rhino-Man':
            self.appearance = self.appearance.replace('Female, ', '')
            self.appearance = self.appearance.replace('Male, ', '')
        elif self.background == 'Parchment Witch':
            self.appearance = self.appearance.replace('Male', 'Female')
Exemple #30
0
    def test(self):
        """
        ПРОВЕРКА УДАЧИ: в некоторых местах тебе будет предложено ИСПЫТАТЬ УДАЧУ. Кинь один кубик: если полученное число
                        будет меньше твоей или равно УДАЧЕ, значит тебе повезло, если больше – не повезло. После каждой
                        проверки удача уменьшается на 1.

        :return:
        """
        result = d(1, 6) <= self.value
        return result
Exemple #31
0
 def __init__(self):
     self.unique = d(20) != 20
     if not self.unique:
         self.number = self._get_number_appearing()
     self.ac = self._get_armor_class()
     self.move = self._get_movement()
     self.hd = self._get_hd()
     self.alignment = self._get_alignment()
     self._get_features()
     self.powers = self._get_powers()
     self.immunities = self._get_immunities()
Exemple #32
0
    def fight(self, enemy):
        """
        БИТВЫ:

        1. Во время битвы кинь один кубик и прибавь полученное число к своей СИЛЕ. Это твоя СИЛА УДАРА.
        2. Кинь кубик, и выпавшее число прибавь к СИЛЕ противника. Это его СИЛА УДАРА.
        3. Сравнит значения. Если твоя сила удара больше, ты отнимаешь от ВЫНОСЛИВОСТИ противника число, равное твоему
           УРОНУ.
        4. Повторяй пункты 1 – 3 до полной победы или поражения.

        :param enemy:
        :return:
        """
        while self.stamina.value > 0 and enemy.stamina.value > 0:
            player_attack = d(1, 6) + self.strength.value
            enemy_attack = d(1, 6) + enemy.strength.value
            if player_attack > enemy_attack:
                enemy.get_wound(self.damage)
            elif enemy_attack > player_attack:
                self.get_wound(enemy.damage)
Exemple #33
0
def improvement(message):
    match = re.match(r"^\s*(?P<skill>\d+)\s*(?:!?\s*(?P<reason>.*))?$",
                     message)
    if match:
        skill = int(match.group('skill'))
        reason = match.group('reason') or ""

        try:
            total, tens, units = dice.coc.d100()

            # skill_desc = f"\"{reason}\" with value of {skill}" if reason else f"{skill}"
            # description = f"Improving {skill_desc}:\n\n"
            title = f"Improving: {reason}" if reason else None
            description = ""
            color = None
            if total > skill or total > 95:
                description += f"**Improvement succeeded!** *(rolled {total})*\n"
                color = C_CRITICAL_SUCCESS
                increase = dice.d(10)
                new_skill = skill + increase
                description += f"New skill value: **{new_skill}** *(increased by {increase})*\n"

                # check for sanity gain
                if new_skill >= 90 and skill < 90:
                    sanity_gain = dice.d(6, times=2)
                    description += f"\nYou also **gained {sanity_gain} sanity** from increasing your skill beyond 90%!"

            else:
                description += f"**Improvement failed** *({total})*\n"
                color = C_FAILURE

            return {'title': title, 'description': description, 'color': color}

        except dice.DiceError as error:
            return error.message

    else:
        return {
            'title': "Improvement Command Usage:",
            'description': mini_help_message
        }
Exemple #34
0
def attrib():
    all_dice = []

    for index in range(0, 4):
        all_dice += [dice.d(6)]

    print(f"Dice:   {all_dice}")
    print(f"Min:    {min(all_dice)}")
    print(f"Sum:    {sum(all_dice)}")
    print(f"Actual: {sum(all_dice) - min(all_dice)}")

    return sum(all_dice) - min(all_dice)
Exemple #35
0
 def monster_description(self):
     desc = []
     if self.eyes != 2:
         desc.append('%s eyes, ' % self.eyes.capitalize())
     desc.append('%s' % self.mouth)
     if d(10) > 5:
         desc.append(', ')
         desc.append(random.choice(Dinosaur.BODY_FEATURES))
     desc = ''.join(desc)
     if desc.strip():
         desc = desc + '.'
     return desc
Exemple #36
0
def getChance(wildernessType, hours=1):
    import dice
    try:
        for h in range(hours):
            w = WILDERNESS[wildernessType]
            r = dice.d(1, 100)
            enc = (r <= w["chance"])
            logging.debug("Hour: %d\tChance: %d\tRoll: %d\t%s" % (h, w["chance"], r, ["No encounter", "Encounter!"][enc]))
            if enc:
                break
        return h, enc
    except (IndexError):
        raise ValueError
Exemple #37
0
 def __init__(self):
     roll = d(20)
     if 1 <= roll <= 7:
         weapon = 'Pistol'
     elif 8 <= roll <= 13:
         weapon = 'Rifle'
     elif 14 <= roll <= 17:
         weapon = 'Bazooka'
     elif 18 <= roll <= 19:
         weapon = 'Canon'
     else:
         weapon = 'Tank'
         
     self.weapon = weapon
     self.range = Weapon.TYPE[weapon]['range']
     self.damage = Weapon.TYPE[weapon]['damage']
     self.charges = Weapon.TYPE[weapon]['charges']
 
     self.pattern = random.choice(Weapon.PROJECTION_PATTERN)
     
     roll = d(10)
     if 1 <= roll <= 6:
         self.projection_type = random.choice(Weapon.ELECTROMAGNETIC)
     elif 7 <= roll <= 9:
         self.projection_type = random.choice(Weapon.SPECTRAL) + " spectral energy"
     else:
         self.projection_type = None
         self.special = random.choice(Weapon.SPECIAL)
         if '/' in self.special:
             self.special = random.choice(self.special.split('/'))
     
     if self.projection_type == 'Cosmic Radiation':
         self.damage += 2
     elif self.projection_type == 'Gamma Radiation':
         self.damage += 1
     
     self.element = random.choice(Weapon.ELEMENT)
Exemple #38
0
def make_random(count):
    weird_gen = weird.WierdGenerator()
    random_hexes = []
    for i in range(count):
        roll = dice.d(100)
        if roll <= 40:
            random_hexes.append(weird_gen.weird())
        elif roll <= 70:
            random_hexes.append(settlement.Settlement())
        elif roll <= 83:
            random_hexes.append(spawn.Spawn())
        elif roll <= 88:
            random_hexes.append(dinosaur.Dinosaur())
        else:
            random_hexes.append(monster.Monster())
    return render_template("random.html", hexes=random_hexes,
                           count=int(len(random_hexes)/2))
Exemple #39
0
    def generate_attributes(self):
        attributes = {
            a.lower(): int(math.ceil(1.0 * dice.d(10) / 2.0))
            for a in self.ATTRIBUTES
        }

        if self.role == "Victim":
            attributes["calm"] = max(attributes["calm"], 4)
        elif self.role == "Problem":
            attributes["calm"] = max(attributes["calm"], 3)
        elif self.role == "Investigator":
            attributes["cash"] = max(attributes["cash"], 3)
        elif self.role == "Friend":
            attribute = random.choice(["perception", "calm"])
            attributes[attribute] = attributes[attribute] + 1

        self.attributes = attributes
Exemple #40
0
 def _get_number_appearing(self):
     roll = d(20)
     if roll <= 5:
         return d(2)
     elif roll <= 9:
         return d(3)
     elif roll <= 12:
         return d(4)
     elif roll <= 15:
         return d(6)
     elif roll <= 17:
         return d(8)
     elif roll <= 19:
         return d(10)
     else:
         return xdy(2,6)
Exemple #41
0
 def _get_hd(self):
     roll = d(20)
     if roll <= 3:
         return 1
     elif roll <= 6:
         return 2
     elif roll <= 9:
         return 3
     elif roll <= 11:
         return 4
     elif roll <= 13:
         return 5
     elif roll <= 15:
         return 6
     elif roll <= 17:
         return 7
     else:
         return roll - 10
Exemple #42
0
 def _get_armor_class(self):
     roll = d(20)
     if roll <= 4:
         return 12
     elif roll <= 8:
         return 13
     elif roll <= 11:
         return 14
     elif roll <= 13:
         return 15
     elif roll <= 15:
         return 16
     elif roll <= 17:
         return 17
     elif roll <= 19:
         return 19
     else:
         return 20
Exemple #43
0
 def get_character_class(self, classname=None):
     """
     We randomly check for demihuman status, which needs to reroll stats, then determine character class based on your prime attribute.
     """
     classNum = d(20)
     if classname:
         return characterclass.CLASS_BY_NAME[classname]
     if classNum < 5:
         # sorted attributes (excluding charisma)
         attributes = sorted(self.attributes[:5], reverse=True,
                             key=operator.itemgetter(1))
         # You're playing a human!
         index = 4 if self.thieves else 3
         prime_attribute, _ = sorted(self.attributes[:index],
                                 reverse=True, key=operator.itemgetter(1))[0]
         return characterclass.PRIME_REQUISITE[prime_attribute]
     elif classNum=5 return characterclass.FROGLING
     elif classNum=4 return characterclass.FLYINGMONKEY
     elif classNum=3 return characterclass.MERROWMAN
     elif classNum=2 return characterclass.DRAUGR
     elif classNum=1 return characterclass.PASSENGER
Exemple #44
0
 def _get_movement_rate(self):
     """
     Return movement rate in feet.
     """
     roll = d(20)
     if roll == 1:
         return 30
     elif roll <= 3:
         return 60
     elif roll <= 7:
         return 90
     elif roll <= 12:
         return 120
     elif roll <= 15:
         return 150
     elif roll <= 17:
         return 180
     elif roll <= 19:
         return 210
     else:
         return 240
Exemple #45
0
 def _get_movement(self):
     """
     Determine type of movement: flying, swimming, etc.
     """
     roll = d(20)
     if roll <= 9:
         move_type = ['land']
     elif roll <= 12:
         move_type = ['land', 'fly']
     elif roll <= 15:
         move_type = ['land', 'swim']
     elif roll <= 17:
         move_type = ['swimming only']
     elif roll <= 19:
         move_type = ['land', 'fly', 'swim']
     else:
         move_type = []
     moves = [(mt, self._get_movement_rate()) for mt in move_type]
     if not moves:
         return "None"
     elif len(moves) == 1 and moves[0][0] == 'land':
         return "%s" % moves[0][1]
     else:
         return " / ".join("%s [%s]" % (d, m) for m, d in moves)
Exemple #46
0
 def __call__(self):
     return d(6) + self.bonus
Exemple #47
0
    def get_background(self):
        backgrounds = [
            ("Poulticer",
             "mortar and pestle, dagger, mystery potion (you know what it doesn't do), oil flask, chalk"
             ),
            ("Slaughterer",
             "heavy cleaver, half-chain, a string of fine sausage, twine"),
            ("Fungus Picker",
             "two different kinds of mushrooms, club, sling, rabbuck-hide gloves, lamp, oil flask"
             ),
            ("Pickler",
             "pickle cask with delicious pickles, spice-rack, trident, wading boots"
             ),
            ("Charcoal Burner",
             "Iron-banded broom, knife, sooty rags, mastic, crampons"),
            ("Purloiner",
             "hammer and spike, off-hand daggers, 50' rope, clothes with hidden pockets, a golden ring (stolen)"
             ),
            ("Hunter",
             "crossbow OR bow, quiver, skinning-knife, leather jack, axe, brace of smoked frog"
             ),
            ("Noble",
             "sword and shield and full chain OR pistolet and powderhorn and chain shirt, off-hand dagger, map to 'inheritance', a fine cape and mantle, laudanum OR signet ring"
             ),
            ("Mendicant",
             "begging bowl, smart pet, reed flute, staff OR club"),
            ("Scribe",
             "mace, robes, runestones, oil-lamp, lard-pot, vellum, brush and ink"
             ),
            ("Porter", "fists, club, auroch-hide armour, a porter's basket"),
            ("Timberfeller",
             "great-axe, knife, raspberry aquavit, sling, 50' rope"),
            ("Plumber", "gluepot, throwing hammer, weather-proof overalls"),
            ("Hayseed",
             "axe OR pitchfork OR threshing flail, dirk, harmonium OR great-kazoo, chewing weed, three torches"
             ),
            ("House-guard",
             "shield, spear, misericorde, half-chain, club, 50' rope"),
            ("Fisher",
             "fishing pole and hook, gutting knife, 2 throwing spears, eel-hide armour, 3 torches, a smoked eel"
             ),
            ("Barber",
             "bonesaw, steggar, clamps, bloody rags, leechjar OR pendulum"),
            ("Scroll-Runner",
             "running shoes, jerky, 50' rope, emberhorn, dagger, news-scroll, farseeing glass"
             ),
            ("Paramour",
             "woodblock erotica OR book of poems, sword, perfume (as lamp-oil), locket OR prophylactics, bow and quiver"
             ),
            ("Guild-Partisan",
             "great-weapon, mancatcher, dagger, hauberk with party armband, guild news-scroll, a set of trade tools (dyer, tanner, weaver, napier, builder, etc.)"
             ),
            ("Bondsman",
             "waraxe OR crossbow and quiver and club, mail shirt, shield, saexe, gift-ring"
             ),
            ("Apiarist",
             "chainmail, goggles, club, bellows, smokebomb, honeycomb"),
            ("Sailor",
             "axe OR cat, off-hand marlinspike, scrimshaw, shield OR leather armour, lodestone"
             ),
            ("Bellman",
             "hookspear, chainmail shirt, shield, handbell, truncheon, 3 torches"
             ),
            ("Smith",
             "warhammer OR sword, off-hand hammer, chainmail OR leather armour and shield, anvil, crucible"
             ),
            ("Janissary",
             "harquebus, powderhorn, chainmail shirt, sword, shield, contract"
             ),
            ("Seer", "silver dagger, cage of finches, brazier"),
            ("Ursar", "mancatcher, 20' chain, club, hide armour, hand drum"),
            ("Merchant",
             "fine clothes, guilder's chain, mace OR axe, a servant with a bale of trade goods"
             ),
            ("Wolfs-head",
             "waraxe, caltrops, leather armour, crossbow, quiver, writ of blood price"
             ),
            ("Therapist",
             "flail, shield, pendulum, meditation cushion, oil-lamp, oil-pot"),
            ("Skald",
             "harp OR scroll of epic poetry, off-hand dagger, sword OR bow and quiver, collection plate"
             ),
            ("Drover",
             "studded leather, whip, club, brand, firehorn, heavy gloves, throwing axe"
             ),
            ("Judicial Functionary",
             "great-weapon, leather jack, hooded cloak, hanging rope OR tongs, manacles and keys"
             ),
            ("Wildling", "fists, moss and furs, 'lucky' stone, shillelagh"),
            ("Mercenary",
             "great-weapon OR waraxe and shield, dirk, ringed leathers, bow and quiver, totem"
             ),
        ]
        background, equipment = random.choice(backgrounds)
        equipment = equipment.split(', ')

        bonus_equipment, silver = random.choice([
            (["fists", "a half-empty bottle", "a turnip"], lambda: dice.d(6)),
            (["nullwater", "a white conch"], lambda: dice.xdy(3, 6)),
            (["3 flasks of oil", "a hammer", "iron spikes"], lambda: 0),
            (["quill and ink", "incense"], lambda: 0),
            (["a hex scroll", "a pine sprig"], lambda: dice.d(6) * 10),
            (["sword and scabbard OR waraxe OR warhammer"], lambda: 0),
        ])
        equipment += bonus_equipment
        equipment.append("%d SP" % silver())

        # process the equipment list down to a finite list of stuff
        final_equipment = []
        for e in equipment:
            items = random.choice(e.split(' OR ')).split(' and ')
            final_equipment.append(items)

        return background, ", ".join(list(itertools.chain(*final_equipment)))
Exemple #48
0
 def roll(cls):
     return d(1, 6)
Exemple #49
0
def roll(message):
    dice_pattern = r"(white|w|green|g|red|r|yellow|y|blue|b|human|h|occupation|o|insight|insanity|i|failure|f|\s+)"
    match = re.match(
        r"^\s*(?P<dice>" + dice_pattern + r"*)(?:!\s*(?P<reason>.*))?$",
        message)
    match_insight = re.match(r"^\s*(?P<insight>\d)\s*(?:!\s*(?P<reason>.*))?$",
                             message)

    if match_insight:
        target = int(match_insight.group('insight'))
        roll = dice.d(6)
        print(roll)
        if roll > target:
            if target == 5:
                title = "You understand... *everything*"
                description = "You understand the full horror behind the Universe and leave everyday life behind."
            else:
                title = "Increase Insight by one"
                description = f"You rolled a {roll}"
        else:
            title = "No change"
            description = f"You rolled a {roll}"
        color = 0x9947eb

        return {'title': title, 'description': description, 'color': color}

    elif match and match.group('dice') and len(message.strip()) > 0:
        split = list(filter(None, re.split(dice_pattern, match.group('dice'))))
        print(split)

        #for brevity
        def count(data, l):
            return sum([data.count(s) for s in l])

        white_n = count(split, ['white', 'w', 'human', 'h', 'occupation', 'o'])
        green_n = count(split, ['green', 'g', 'insight', 'insanity', 'i'])
        red_n = count(split, ['red', 'r', 'failure', 'f'])
        yellow_n = count(split, ['yellow', 'y'])
        blue_n = count(split, ['blue', 'b'])

        try:
            # don't do success level checks and just output a dice roll number
            white_d6 = dice.d(6, times=white_n, total=False)
            green_d6 = dice.d(6, times=green_n, total=False)
            red_d6 = dice.d(6, times=red_n, total=False)
            yellow_d6 = dice.d(6, times=yellow_n, total=False)
            blue_d6 = dice.d(6, times=blue_n, total=False)

            if white_n > 20 or green_n > 20 or red_n > 20 or yellow_n > 20 or blue_n > 20:
                raise dice.DiceError(
                    "Azathoth curses you for using too many dice!")

            # Interpretation
            # quick helper function
            def highest(l):
                return max(l) if len(l) > 0 else 0

            if yellow_n > 0 or blue_n > 0:
                title = "Custom"
                color = 0x202225

            elif highest(red_d6) > highest(white_d6 + green_d6):
                title = "Failure!"
                color = C_FAILURE_DISADV

            else:
                title, color = {
                    6: ("More than you wanted!", C_CRITICAL_SUCCESS),
                    5: ("Success, and...", C_SUCCESS_ADV),
                    4: ("Success", C_SUCCESS),
                    3: ("Partial Success", C_SUCCESS_DISADV),
                    2: ("Partial Success, but...", C_FAILURE_ADV),
                    1: ("*Juuuust* Barely", C_FAILURE),
                }[highest(white_d6 + green_d6)]

            def format_dice_list(l):
                if len(l) == 0:
                    return ""
                elif len(l) == 1:
                    return f"**{l[0]}**"
                else:
                    return f"**{l[0]}**, {', '.join(map(str, l[1:]))}"

            description = ""
            if white_n > 0:
                description += f":white_circle: {format_dice_list(sorted(white_d6, reverse=True))}\n"
            if green_n > 0:
                description += f":green_circle: {format_dice_list(sorted(green_d6, reverse=True))}\n"
            if red_n > 0:
                description += f":red_circle: {format_dice_list(sorted(red_d6, reverse=True))}\n"
            if yellow_n > 0 or blue_n > 0:
                description += "\n"
            if yellow_n > 0:
                description += f":yellow_circle: {format_dice_list(sorted(yellow_d6, reverse=True))}\n"
            if blue_n > 0:
                description += f":blue_circle: {format_dice_list(sorted(blue_d6, reverse=True))}\n"

            if highest(green_d6) > highest(white_d6):
                description += f"\n**!Please make an Insight Roll!**\n"

            if match.group('reason'):
                description += f"\n**Reason**: {match.group('reason')}"

            return {'title': title, 'description': description, 'color': color}

        except dice.DiceError as error:
            return error.message

    else:
        return "Incorrect syntax"
Exemple #50
0
def fire_bolt(caster, target):
    target.HP -= sum(d(10) for i in range(floor(caster.level / 5) + 1))
Exemple #51
0
def ray_of_frost(caster, target):
    if d(20) + caster.spellattack >= target.AC:
        target.HP -= d(8)
        target.speed -= 10
Exemple #52
0
def four_dee_six():
    roll = [sum(sorted(dice.d(6) for _ in xrange(4))[1:]) for _ in range(6)]
    return render_template("4d6.html", roll=roll)
 def get_hp(self):
     """
     Determine HP based on hit dice and CON modifiers. Note: this value may
     be negative and that is handled by the caller.
     """
     return d(self.hit_die) + self.get_bonus(*self.attributes[characterclass.CON])
Exemple #54
0
def poison_spray(caster, target):
    target.HP -= d(10)
    target.poisoned = True
Exemple #55
0
def false_life(caster, slot):
    assert caster.slots[slot] > 0
    assert slot > 0
    caster.THP += d(4) + 4 + 5 * (slot - 1)
Exemple #56
0
 def roll_attribute(self):
     """ 4d6 drop the lowest """
     return sum(sorted(d(6) for _ in range(4))[1:])
Exemple #57
0
    def __init__(self, name=None):
        self.gender = random.choice(["male", "female"])
        self.name = name if name else Character.generate_name(
            gender=self.gender)
        self.STR = dice.d(6, 3) * 5
        self.CON = dice.d(6, 3) * 5
        self.DEX = dice.d(6, 3) * 5
        self.SIZ = (dice.d(6, 2) + 6) * 5
        self.INT = (dice.d(6, 2) + 6) * 5
        self.POW = dice.d(6, 3) * 5
        self.APP = dice.d(6, 3) * 5
        self.EDU = (dice.d(6, 2) + 6) * 5
        self.age = 15 + dice.d(6, 2) + min(dice.d(30, 3, total=False))
        self.luck = dice.d(6, 3) * 5
        self.sanity = self.POW

        self.hp = math.floor((self.SIZ + self.CON) / 10)

        if self.DEX < self.SIZ and self.STR < self.SIZ:
            self.move_rate = 7
        elif self.DEX > self.SIZ and self.STR > self.SIZ:
            self.move_rate = 9
        else:
            self.move_rate = 8

        if self.STR + self.SIZ < 65:
            self.damage_bonus = "-2"
            self.build = -2
        elif self.STR + self.SIZ < 85:
            self.damage_bonus = "-1"
            self.build = -1
        elif self.STR + self.SIZ < 125:
            self.damage_bonus = "0"
            self.build = 0
        elif self.STR + self.SIZ < 165:
            self.damage_bonus = "+1d4"
            self.build = 1
        else:
            self.damage_bonus = "+1d6"
            self.build = 2

        self.occupation = self.generate_occupation()
        #TODO: calculate credit reating based on occupation
        self.credit_rating = 0
Exemple #58
0
 def __init__(self):
     self.core = choice(self.cores)
     self.wood = choice(self.woods)
     self.bonus = d(6)
Exemple #59
0
def four_dee_six():
    roll = [sum(sorted(dice.d(6) for _ in xrange(4))[1:]) for _ in range(6)]
    return render_template("4d6.html", roll=roll)