Пример #1
0
 def encounter(self):
     size = {0: 1, 1: d3(1), 3: d6(1),
             6: d6(2), 9: d6(3), 12: d6(4),
             15: d6(5)}
     for s, n in size.items():
         if self.stats.Pac <= s:
             return n
Пример #2
0
 def events_and_mishaps(self, n):
     r = (d6(1), d6(1))
     if not self.terms[n]['S']:
         self.terms[n]['EM'] = 'm[%d]' % r[0]
         self.history += [' Experienced a Mishap (Roll=%d).' % r[0]]
     else:
         self.terms[n]['EM'] = 'e[%d,%d]' % r
         self.history += [' Experienced an Event (Roll=%d,%d).' % r]
Пример #3
0
 def events_and_mishaps(self, n):
     r = (d6(1), d6(1))
     if not self.terms[n]['S']:
         self.terms[n]['EM'] = 'm[%d]' % r[0]
         self.history += [' Experienced a Mishap (Roll=%d).' % r[0]]
     else:
         self.terms[n]['EM'] = 'e[%d,%d]' % r
         self.history += [' Experienced an Event (Roll=%d,%d).' % r]
Пример #4
0
 def encounter(self):
     size = {
         0: 1,
         1: d3(1),
         3: d6(1),
         6: d6(2),
         9: d6(3),
         12: d6(4),
         15: d6(5)
     }
     for s, n in size.items():
         if self.stats.Pac <= s:
             return n
Пример #5
0
 def __init__(self, name):
     pt.Character.__init__(self,
                           name,
                           class_type='Sorcerer',
                           hitdice=dice.d6(),
                           prof_save={
                               'con': 1,
                               'cha': 1
                           },
                           cantrips_by_lvl=caster_cantrips,
                           spells_by_lvl=caster_spell_slots,
                           spells_slots={
                               1: 2,
                               2: 3,
                               3: 4,
                               4: 5,
                               5: 6,
                               6: 7,
                               7: 8,
                               8: 9,
                               9: 10,
                               10: 11,
                               11: 12,
                               12: 12,
                               13: 13,
                               14: 13,
                               15: 14,
                               16: 14,
                               17: 15,
                               18: 15,
                               19: 15,
                               20: 15
                           })
Пример #6
0
 def __new__(cls, method=None, value=None):
     if not value > -1:
         if method == "heroic":
             value = sum(sorted([d6(1) for i in range(3)])[-2:])
         elif method == "superheroic":
             value = d6(2)+3
         elif method == "mediocre":
             value = d3(4)
         elif method == "extreme":
             value = d16(1)-1
         elif method == "alternating":
             value = sum([d for j, d in enumerate(sorted([d6(1)
                          for i in range(4)])) if j % 2 == 1])
         else:
             value = d6(2)
     return super(Stat, cls).__new__(cls, value)
Пример #7
0
    def roll(self):
        """Roll the dice for this attack, returning a dict:
            hits: dict of hit results
            wounds: dict of wound results

            Also stores the results in self.hits and self.wounds
        """

        hits = dice.d6(self.number, self.hit).roll()

        self.hits = hits

        wounds = dice.d6(hits['passes'], self.wound).roll()

        self.wounds = wounds

        return {'hits': hits, 'wounds': wounds}
Пример #8
0
    def stat_wounds(self, attack):
        ''' calculate casualty statistics of this attack '''

        remaining_wounds = attack.stat()['wounds']
        model = self.models[0]
        save = model['profile'].best_save(attack)

        return remaining_wounds - dice.d6(remaining_wounds, save).stat()
Пример #9
0
 def determine_dwarf_type(self):
     roll = dice.d6()
     if roll == 1:
         self.star_type = "G"
     elif roll == 2:
         self.star_type = "K"
     else:
         self.star_type = "M"
Пример #10
0
    def shoot(self, target):
        roll = dice.d6()

        hit = dice.hit(self, self.dex)
        if hit == True:
            self.deal_dmg(roll, self.dex, target)
        elif hit == False:
            print(f"{self.name} shot, but missed!\nOh the humility!\n")
Пример #11
0
 def get_stats(self, sentient=False):
     self.stats = Stats(animal=True)
     s = cap(d6(2) + self.dms["size"], 1, len(SIZES)) - 1
     self.stats.Str = Stat(value=SIZES[s][1])
     self.stats.Dex = Stat(value=SIZES[s][2])
     self.stats.End = Stat(value=SIZES[s][3])
     if not sentient:
         i = choice([0, 1])
         self.stats.Int = Stat(value=i)
     self.size = SIZES[s][0]
Пример #12
0
 def get_terrain(self, terrain=None):
     if terrain:
         t = terrain
     else:
         t = choice(TERRAIN.keys())
     m = d6(1)-1
     self.movement = TERRAIN[t][2][m][0]
     self.dms["type"] += TERRAIN[t][0]
     self.dms["size"] += TERRAIN[t][1] + TERRAIN[t][2][m][1]
     self.terrain = t
Пример #13
0
 def get_terrain(self, terrain=None):
     if terrain:
         t = terrain
     else:
         t = choice(TERRAIN.keys())
     m = d6(1) - 1
     self.movement = TERRAIN[t][2][m][0]
     self.dms["type"] += TERRAIN[t][0]
     self.dms["size"] += TERRAIN[t][1] + TERRAIN[t][2][m][1]
     self.terrain = t
Пример #14
0
 def muster(self, n):
     ben = d6(1)
     career = self.terms[n]['Career'].replace(' Officer', '')
     self.terms[n]['Ben'] = ben
     if choice((0, 1)) == 1:
         self.benefit(ben, career)
     else:
         credits = CREDITS[career][ben - 1]
         self.credits += credits
         self.history += [' Acquired %d.' % credits]
Пример #15
0
 def muster(self, n):
     ben = d6(1)
     career = self.terms[n]['Career'].replace(' Officer', '')
     self.terms[n]['Ben'] = ben
     if choice((0, 1)) == 1:
         self.benefit(ben, career)
     else:
         credits = CREDITS[career][ben - 1]
         self.credits += credits
         self.history += [' Acquired %d.' % credits]
Пример #16
0
 def get_stats(self, sentient=False):
     self.stats = Stats(animal=True)
     s = cap(d6(2) + self.dms["size"], 1, len(SIZES)) - 1
     self.stats.Str = Stat(value=SIZES[s][1])
     self.stats.Dex = Stat(value=SIZES[s][2])
     self.stats.End = Stat(value=SIZES[s][3])
     if not sentient:
         i = choice([0, 1])
         self.stats.Int = Stat(value=i)
     self.size = SIZES[s][0]
Пример #17
0
    def take_wounds(self, attack):
        """ Take saves on inflicted wounds, apply wounds, and remove casualties

        Arguments:
            attack: a WoundingAttack object describing the attack

        Returns:
            the total number of unsaved wounds suffered by the unit
        """

        unsaved = 0
        remaining_wounds = attack.wounds['passes']

        while remaining_wounds and self.alive:
            # determine the number of wounds we can roll for now
            model = self.models[0]
            wounds_to_take = remaining_wounds
            wounds_characteristic = model['profile'].wounds
            max_wounds = model['count'] * wounds_characteristic - model['wounds'];
            if wounds_to_take > max_wounds:
                wounds_to_take = max_wounds
            remaining_wounds -= wounds_to_take

            save = model['profile'].best_save(attack)

            # roll the dice
            roll = dice.d6(wounds_to_take, save).roll()

            # inflict casualties
            casualties = roll['fails']
            unsaved += casualties
            # handle wounded models first
            if model['wounds']:
                to_go = wounds_characteristic - model['wounds']
                if casualties >= to_go:
                    model['wounds'] = 0
                    model['count'] -= 1
                else :
                    model['wounds'] += to_go

                casualties -= to_go

            # handle further casualties
            if casualties:
                model['count'] -= math.floor(casualties / model['profile'].wounds)

                # add leftover wounds
                model['wounds'] = casualties % model['profile'].wounds

            # remove eradicated models
            if model['count'] < 1:
                self.removeModel(model)

        return unsaved
Пример #18
0
 def __init__(self, name):
     pt.Character.__init__(self,
                           name,
                           class_type='Wizard',
                           hitdice=dice.d6(),
                           prof_saves={
                               'int': 1,
                               'wis': 1
                           },
                           cantrips_by_lvl=caster_cantrips,
                           spells_by_lvl=caster_spell_slots)
Пример #19
0
 def generate(self):
     roll = dice.d6(2)
     num_stars = 1
     if roll == 10:
         num_stars = 2
     elif roll == 11:
         num_stars = 3
     else:
         num_stars = 4
     for i in range(num_stars):
         star = (Star()).generate()
         self.stars.append(star)
Пример #20
0
 def determine_star_class(self):
     roll = dice.d6(3)
     if roll >= 3 and roll <= 5:
         self.star_class = "D"
     elif roll == 6:
         self.star_class = "VI"
     elif roll == 18:
         roll = dice.d6(3)
         if roll == 3:
             roll = dice.d100()
             if roll <= 33:
                self.star_class = "Ia"
             else:
                self.star_class = "Ib"
         elif roll == 4:
             self.star_class = "II"
         elif roll >= 5 and roll <= 12:
             self.star_class = "III"
         else:
             self.star_class = "IV"
     else:
         self.star_class = "V"
Пример #21
0
 def get_behavior(self, behavior=None):
     orders = {"Herbivore": 0, "Omnivore": 1,
               "Carnivore": 2, "Scavenger": 3}
     if not behavior:
         r = cap(d6(2) + self.dms["type"], 1, 12)
         for a in range(len(ANIMAL_TYPES)):
             if r - 1 <= a:
                 behavior = ANIMAL_TYPES[r][orders[self.order]]
                 break
     else:
         a = [y for x in ANIMAL_TYPES for y in x]
         self.order = ORDERS[divmod(a.index(behavior), 6)[1]][1]
     self.behavior = behavior
Пример #22
0
 def get_skills(self):
     self.skills = SkillSet()
     self.skills.update(STARTING_SKILLS)
     for b in BEHAVIORS[self.behavior]:
         attr, n = b
         if attr in STATS:
             self.stats[attr] = Stat(self.stats[attr] + n)
         elif attr in self.skills:
             self.skills[attr] += n
         else:
             self.skills[attr] = n
     for r in range(d6(1)):
         sk = choice(self.skills.keys())
         self.skills[sk] += 1
Пример #23
0
 def get_skills(self):
     self.skills = SkillSet()
     self.skills.update(STARTING_SKILLS)
     for b in BEHAVIORS[self.behavior]:
         attr, n = b
         if attr in STATS:
             self.stats[attr] = Stat(self.stats[attr] + n)
         elif attr in self.skills:
             self.skills[attr] += n
         else:
             self.skills[attr] = n
     for r in range(d6(1)):
         sk = choice(self.skills.keys())
         self.skills[sk] += 1
Пример #24
0
def main(argv):

    slack = slacker.Slacker(private.sixthWorld)

    charactername = argv[0]
    difficulty = argv[1]
    channelname = argv[2]

    modifiers = \
        {
            'sexy sleepwear': 4,
            'pheromone augmentation': 2
        }
    last = len(modifiers) - 1

    mod_bonus = 0
    for key, value in modifiers.items():
        mod_bonus += value

    character = get_data(charactername)

    die_pool = character['Charisma'] + character['Seduction'] + mod_bonus

    # create good looking description
    description = ''
    description += ('_' + character['Name'] + ' ' + __actionname__ + '_\n')

    description += (
        "Charisma(" + str(character['Charisma']) + ")  + " +
        "Seduction(" + str(character['Seduction']) + ") + ")

    for i, key in enumerate(modifiers):
        if i == last:
            operator = '= '
        else:
            operator = '+ '
        description += (
            str(key) + "(" + str(modifiers[key]) + ") " + operator)

    description += ("*" + str(die_pool) + "d6*")
    
    # perform the roll
    roll = d6(die_pool)

    # send results to slack
    output = check(difficulty, roll)
    slack.chat.post_message(channelname, description + '\n' + str(roll) + "\n" + output, username=character['Name'], icon_url=character['imageURL'])
Пример #25
0
def test_d6():
    # test object
    rolls = dice.d6(10, 3)

    # expected
    expected_roll = {'passes': 7, 'fails': 3, 2: 1, 3: 2, 4: 2, 5: 3, 6: 0, 1: 2}
    expected_stat = 6.6666666

    # roll test
    roll = rolls.roll()
    roll_result = roll == expected_roll

    # stat test
    stat = rolls.stat()
    stat_result = close_enough(stat, expected_stat)

    assert roll_result and stat_result
Пример #26
0
    def age(self, n):
        age = '-' if n < 3 else d6(2) - n + 1
        if age < 1:
            age = max(-6, age)
            pens = AGING[-age]
            for p, pen in enumerate(pens):
                if pen:
                    if p == 3:
                        a = choice(('Int', 'Edu', 'Soc'))
                    else:
                        a = choice(('Str', 'Dex', 'End'))
                    self.stats[a] -= pen
                    if self.stats[a] < 0:
                        self.stats[a] = Stat(value=0)
                    self.history += [' Lost %d %s due to aging.' % (pen, a)]

        self.terms[n]['Age'] = age
Пример #27
0
 def get_behavior(self, behavior=None):
     orders = {
         "Herbivore": 0,
         "Omnivore": 1,
         "Carnivore": 2,
         "Scavenger": 3
     }
     if not behavior:
         r = cap(d6(2) + self.dms["type"], 1, 12)
         for a in range(len(ANIMAL_TYPES)):
             if r - 1 <= a:
                 behavior = ANIMAL_TYPES[r][orders[self.order]]
                 break
     else:
         a = [y for x in ANIMAL_TYPES for y in x]
         self.order = ORDERS[divmod(a.index(behavior), 6)[1]][1]
     self.behavior = behavior
Пример #28
0
    def age(self, n):
        age = '-' if n < 3 else d6(2) - n + 1
        if age < 1:
            age = max(-6, age)
            pens = AGING[-age]
            for p, pen in enumerate(pens):
                if pen:
                    if p == 3:
                        a = choice(('Int', 'Edu', 'Soc'))
                    else:
                        a = choice(('Str', 'Dex', 'End'))
                    self.stats[a] -= pen
                    if self.stats[a] < 0:
                        self.stats[a] = Stat(value=0)
                    self.history += [' Lost %d %s due to aging.' % (pen, a)]

        self.terms[n]['Age'] = age
Пример #29
0
 def determine_mainseq_type(self):
     roll = dice.d6(3)
     if roll >= 9 and roll <= 18:
         self.star_type = "M"
     else:
         if roll == 3:
             self.star_type = "O"
         elif roll == 4:
             self.star_type = "B"
         elif roll == 5:
             self.star_type = "A"
         elif roll == 6:
             self.star_type = "F"
         elif roll == 7:
             self.star_type = "G"
         else:
             self.star_type = "K"
Пример #30
0
 def lightning_bolt(self, hit, evade, enemyMod):
     if ((hit > evade + enemyMod) and self.magic_slots > 0):
         damage = (dice.d6(1) + dice.d6(1) + dice.d6(1) +
                   dice.d6(1)) + self.intMod
         self.magic_slots -= 1
     elif ((hit <= evade + enemyMod) and self.magic_slots > 0):
         damage = (dice.d6(1) + dice.d6(1)) + self.intMod
         self.magic_slots -= 1
     elif (self.magic_slots <= 0):
         print("no magic left")
         damage = 0
     return damage
Пример #31
0
 def determine_giant_type(self):
     done = False
     while not done:
         roll = dice.d6(2)
         if roll == 2:
             self.star_type = "O"
         elif roll == 3:
             self.star_type = "M"
         elif roll == 4 or roll == 5:
             self.star_type = "B"
         elif roll >= 6 and roll <= 9:
             self.star_type = "K"
         else:
             self.star_type = "A"
         if self.star_type != "O" and self.star_type != "M":
             done = True
             
         # an excepttion is that if type O, class II, III, and IV do not exist, and type M, class IV as well. Reroll
         # 
         else:
             if self.star_type == "M" and self.star_class != "IV":
                 done = True
             elif self.star_type == "O" and (self.star_class == "Ia" or self.star_class == "Ib"):
                 done = True
Пример #32
0
from dice import d6

print(d6(),d6())
Пример #33
0
 def magic_missiles(self, attackee):
     dmg_amount = d6() + 1
     print(f"{self.name} attacks {attackee} doing {dmg_amount} damage")
     return dmg_amount
Пример #34
0
 def cure_wounds(self):
     heal_amount = d6() + 1
     print(f"{self.name} healed for {heal_amount} health")
     Creature.heal(self, heal_amount)
Пример #35
0
 def get_weap_arm(self):
     a = cap(d6(2) + self.dms['armor'], 1, 13)
     w = cap(d6(2) + self.dms['weapon'], 1, 13)
     self.armor = cap(a//2 - 1, 0, 5)
     self.weapon = WEAPONS[w-1][0]
     self.damage = 1 + self.stats.Str//10 + WEAPONS[w-1][1]
Пример #36
0
def runner(action_info):

    slack = slacker.Slacker(private.sixthWorld)

    # last is used in buiding the description, to use = at the end not +
    last = len(action_info['modifiers']) - 1 
    
    # caluclate total modifier bonus
    mod_bonus = 0
    for key, value in action_info['modifiers'].items():
        mod_bonus += value
    
    # get character dictionary
    character = get_data(action_info['character_name'])
    
    # create die pool based on Attribute, Skill, Skill Group
    die_pool = 0
    if (action_info['attribute'] and action_info['skill'] != ''):
        die_pool    += character[action_info['attribute']] 
        die_pool    += character[action_info['skill']] + mod_bonus
    elif (action_info['skill'] == ''):
        die_pool    += character[action_info['attribute']]
    else:
        print('Error, action_info must have an attribute defined')
        

    # create good looking description
    # Name, Action, Attribute and Skill information
    description = ''
    description += (
        '_' + character['Name'] + ' ' + action_info['action_name'] + '_\n' +
        action_info['attribute'] + 
        "(" + str(character[action_info['attribute']]) + ")  + " +
        action_info['skill'] + 
        "(" + str(character[action_info['skill']]) + ") + "
        )

    # Modifier information
    for i, key in enumerate(action_info['modifiers']):
        if i == last:
            operator = '= '
        else:
            operator = '+ '
        description += (
            str(key) + 
            "(" + str(action_info['modifiers'][key]) + ") "
            + operator
            )

    # Die pool
    description += ("*" + str(die_pool) + "d6*")
    
    # Perform the roll
    roll = d6(die_pool)
    
    # Send results to Slack
    output = check(5, roll)
    
    try:
        slack.chat.post_message(
            '#scratch', 
            description + '\n' + str(roll) + "\n" + output, 
            username=character['Name'], 
            icon_url=character['imageURL']
            )
    except:
        print('failure sending to slack')
Пример #37
0
    ("Intermittent", "Gatherer", "Pouncer", "Hijacker"),
    ("Intermittent", "Eater", "Brute Killer", "Carrion-Eater"),
    ("Intermittent", "Gatherer", "Trapper", "Intimidator"),
    ("Intermittent", "Hunter", "Pouncer", "Reducer"),
    ("Grazer", "Hunter", "Chaser", "Carrion-Eater"),
    ("Grazer", "Hunter", "Chaser", "Reducer"),
    ("Grazer", "Gatherer", "Chaser", "Hijacker"),
    ("Grazer", "Eater", "Swift Killer", "Intimidator"),
    ("Grazer", "Hunter", "Chaser", "Reducer"),
    ("Grazer", "Gatherer", "Siren", "Hijacker"),
    ("Grazer", "Gatherer", "Chaser", "Intimidator"),
)

SIZES = (
    # 2d6: (Weight (kg), Strength, Dexterity, Endurance)
    (1, 1, d6(1), 1),
    (3, 2, d6(1), 2),
    (6, d6(1), d6(2), d6(1)),
    (12, d6(1), d6(2), d6(1)),
    (25, d6(2), d6(3), d6(2)),
    (50, d6(2), d6(4), d6(2)),
    (100, d6(3), d6(3), d6(3)),
    (200, d6(3), d6(3), d6(3)),
    (400, d6(4), d6(2), d6(4)),
    (800, d6(4), d6(2), d6(4)),
    (1600, d6(5), d6(2), d6(5)),
    (3200, d6(6), d6(1), d6(6)),
    (5000, d6(7), d6(1), d6(7)),
    (6000, d6(8), d6(1), d6(8)),
    (7000, d6(9), d6(1), d6(9)),
    (8000, d6(10), d6(1), d6(10)),
Пример #38
0
 def roll(self, mods=0):
     return (d6(2) + self() + mods)
Пример #39
0
# using dnd character classes to practice python classes and (more importantly) class inheritance

# not sure what main will be used for, lol

import dice
import class_types
import armor

# testing Dice
d4 = dice.d4()
d6 = dice.d6()
d8 = dice.d8()
d10 = dice.d10()
d12 = dice.d12()
d20 = dice.d20()
"""
print(f"Rolling d4: {d4.roll()}")
print(f"Rolling d4: {d4.roll()}")
print(f"Rolling d4: {d4.roll()}")

print(f"Rolling d6: {d6.roll()}")
print(f"Rolling d8: {d8.roll()}")
print(f"Rolling d20: {d20.roll()}")

print(f"Rolling 4d6, indiv: {d6.roll_indiv(4)}")
print(f"Rolling 6d8, summed: {d8.roll_sum(4)}")
"""

Drat = class_types.Bard("Drat of Hithendale")

Drat.say_name()
Пример #40
0
 def levelUP(self):
     self.hp = self.hp + (dice.d6(1) + self.conMod)
     self.level += 1
Пример #41
0
 def get_quirks(self):
     Q = QUIRKS.items()
     sk = sample(range(len(Q) * 6), d6(1))
     cells = [divmod(x, len(Q)) for x in sk]
     self.quirks = [Q[x][1][y] for x, y in cells]
Пример #42
0
 def get_weap_arm(self):
     a = cap(d6(2) + self.dms['armor'], 1, 13)
     w = cap(d6(2) + self.dms['weapon'], 1, 13)
     self.armor = cap(a // 2 - 1, 0, 5)
     self.weapon = WEAPONS[w - 1][0]
     self.damage = 1 + self.stats.Str // 10 + WEAPONS[w - 1][1]
Пример #43
0
L4 = Label(text="Total Modifier:")
E4 = Entry(bd =3)
L5 = Label(text="Result:")
if (E1.get() == ""):
	E1.insert(END, "0")
	E2.insert(END, "0")
	E3.insert(END, "0")
	E4.insert(END, "0")
v=StringVar()
L6 = Label(textvariable=v)
B1 = Button(text="Roll!", command=lambda: v.set(E2.get() + "d(" + E1.get() + '{:+}'.format(int(E3.get())) + ") " + '{:+}'.format(int(E4.get())) + " = "
	'{:+}'.format(dice.roller(int(E1.get()), int(E2.get()), int(E3.get())) + int(E4.get()))))
B2 = Button(text='d2', command=lambda: v.set("d2: " + str(dice.d2())))
B3 = Button(text="d3", command=lambda: v.set("d3: " + str(dice.d3())))
B4 = Button(text="d4", command=lambda: v.set("d4: " + str(dice.d4())))
B6 = Button(text="d6", command=lambda: v.set("d6: " + str(dice.d6())))
B8 = Button(text="d8", command=lambda: v.set("d8: " + str(dice.d8())))
B10 = Button(text="d10", command=lambda: v.set("d10: " + str(dice.d10())))
B20 = Button(text="d20", command=lambda: v.set("d20: " + str(dice.d20())))
B100 = Button(text="d100", command=lambda: v.set("d100: " + str(dice.d100())))
L1.grid(row=0, column=0, columnspan=1)
E1.grid(row=1, column=0, columnspan=1)
L2.grid(row=2, column=0, columnspan=1)
E2.grid(row=3, column=0, columnspan=1)
L3.grid(row=4, column=0, columnspan=1)
E3.grid(row=5, column=0, columnspan=1)
L4.grid(row=6, column=0, columnspan=1)
E4.grid(row=7, column=0, columnspan=1)
L5.grid(row=8, column=0, columnspan=1, sticky=W)
L6.grid(row=9, column=0, columnspan=1, sticky=W)
B1.grid(row=0, column=1, columnspan=1, sticky=W, padx = 10)
Пример #44
0
 def test_6面ダイスを振る(self):
     self.assertIn(d6(), [1, 2, 3, 4, 5, 6])
Пример #45
0
 def get_quirks(self):
     Q = QUIRKS.items()
     sk = sample(range(len(Q)*6), d6(1))
     cells = [divmod(x, len(Q)) for x in sk]
     self.quirks = [Q[x][1][y] for x, y in cells]
Пример #46
0
    def stat(self):
        hits = dice.d6(self.number, self.hit).stat();
        wounds = dice.d6(hits, self.wound).stat();

        return {'hits': hits, 'wounds': wounds}
Пример #47
0
    ("Intermittent", "Gatherer", "Pouncer", "Hijacker"),
    ("Intermittent", "Eater", "Brute Killer", "Carrion-Eater"),
    ("Intermittent", "Gatherer", "Trapper", "Intimidator"),
    ("Intermittent", "Hunter", "Pouncer", "Reducer"),
    ("Grazer", "Hunter", "Chaser", "Carrion-Eater"),
    ("Grazer", "Hunter", "Chaser", "Reducer"),
    ("Grazer", "Gatherer", "Chaser", "Hijacker"),
    ("Grazer", "Eater", "Swift Killer", "Intimidator"),
    ("Grazer", "Hunter", "Chaser", "Reducer"),
    ("Grazer", "Gatherer", "Siren", "Hijacker"),
    ("Grazer", "Gatherer", "Chaser", "Intimidator"),
    )

SIZES = (
    # 2d6: (Weight (kg), Strength, Dexterity, Endurance)
    (1, 1, d6(1), 1),
    (3, 2, d6(1), 2),
    (6, d6(1), d6(2), d6(1)),
    (12, d6(1), d6(2), d6(1)),
    (25, d6(2), d6(3), d6(2)),
    (50, d6(2), d6(4), d6(2)),
    (100, d6(3), d6(3), d6(3)),
    (200, d6(3), d6(3), d6(3)),
    (400, d6(4), d6(2), d6(4)),
    (800, d6(4), d6(2), d6(4)),
    (1600, d6(5), d6(2), d6(5)),
    (3200, d6(6), d6(1), d6(6)),
    (5000, d6(7), d6(1), d6(7)),
    (6000, d6(8), d6(1), d6(8)),
    (7000, d6(9), d6(1), d6(9)),
    (8000, d6(10), d6(1), d6(10)),