from random import randint def number_encountered(): return (randint(1, 4) + 2) def npc_class(): roll = (randint(1, 6) + randint(1, 6) + randint(1, 6)) if roll == 3 or roll == 4: return 'Elven Nightblade' elif roll == 5: return 'Elven Spellsword' elif roll == 6: return 'Explorer' elif roll == 7: return 'Bladedancer' elif roll == 8: return 'Cleric' elif roll == 9 or roll == 10 or roll == 11: return 'Fighter' elif roll == 12: return 'Thief' elif roll == 13: return 'Mage' elif roll == 14: return 'Assassin' elif roll == 15: return 'Bard' elif roll == 16: return 'Dwarven Vaultguard' elif roll == 17 or roll == 18: return 'Dwarven Craftpriest' def npc_alignment(): roll = randint(1, 6) if roll == 1 or roll == 2: return 'Lawful' elif roll == 3 or roll == 4 or roll == 5: return 'Neutral' elif roll == 6: return 'Chaotic' def npc_baselevel(base_level): roll = randint(1, 6) mod = 0 if roll == 1: mod = -2 elif roll == 2: mod = -1 elif roll == 3 or roll == 4: mod = 0 elif roll == 5: mod = 1 elif roll == 6: mod = 2 base_level += mod if base_level < 1: base_level = 1 return base_level def npc_abilities(): return [(randint(1, 6) + randint(1, 6) + randint(1, 6)) for x in range(0,6)] def attribute_mod(atr): mod = 0 if atr <= 3: mod = -3 if atr >= 4 and atr <= 5: mod = -2 if atr >= 6 and atr <= 8: mod = -1 if atr >= 9 and atr <= 12: mod = 0 if atr >= 13 and atr <= 15: mod = 1 if atr >= 16 and atr <= 17: mod = 2 if atr >= 18: mod = 3 return mod npc_class_data = { 'Elven Nightblade': { 'hd': [1, 6], 'armour': -4, 'melee': [0, 2, 1], 'ranged': [0, 0, 1] }, 'Elven Spellsword': { 'hd': [1, 6], 'armour': -4, 'melee': [0, 1, 0], 'ranged': [0, 0, 1] }, 'Explorer': { 'hd': [1, 6], 'armour': -3, 'melee': [0, 1, 1], 'ranged': [0, 1, 2] }, 'Bladedancer': { 'hd': [1, 6], 'armour': -2, 'melee': [0, 1, 0], 'ranged': [0, 0, 1] }, 'Cleric': { 'hd': [1, 6], 'armour': 0, 'melee': [1, 3, 1], 'ranged': [1, 3, 4] }, 'Fighter': { 'hd': [1, 8], 'armour': 1, 'melee': [1, 4, 1], 'ranged': [1, 1, 4], }, 'Thief': { 'hd': [1, 4], 'armour': -6, 'melee': [0, 1, 1], 'ranged': [1, 0, 6] }, 'Mage': { 'hd': [1, 4], 'armour': -8, 'melee': [0, 0, 1], 'ranged': [0, 0, 1] }, 'Assassin': { 'hd': [1, 6], 'armour': -6, 'melee': [0, 2, 1], 'ranged': [1, 0, 5] }, 'Bard': { 'hd': [1, 6], 'armour': -3, 'melee': [0, 2, 1], 'ranged': [1, 0, 4] }, 'Dwarven Vaultguard': { 'hd': [1, 8], 'armour': -1, 'melee': [1, 3, 0], 'ranged': [1, 1, 6] }, 'Dwarven Craftpriest': { 'hd': [1, 6], 'armour': -2, 'melee': [0, 1, 0], 'ranged': [1, 0, 5] } } npc_armour_list = [ ['Clothing Only', 0, 0], ['Hide and Fur Armour', 10, 1], ['Leather Armour', 20, 2], ['Ring Mail Armour', 30, 3], ['Scale Mail Armour', 30, 3], ['Chain Mail Armour', 40, 4], ['Banded Plate', 50, 5], ['Lamellar Armour', 50, 5], ['Plate Armour', 60, 6], ] npc_melee_weapons_data = { 'light': [ ['Club', 1, '1d4'], ['Dagger', 3, '1d4'], ['Sap', 1, '1d4'], ['Staff (1h)', 1, '1d4'], ['Staff (2h)', 1, '1d6'], ['Whip', 5, '1d2'] ], 'medium': [ ['Battle Axe (1h)', 7, '1d6'], ['Battle Axe (2h)', 7, '1d8'], ['Hand Axe', 4, '1d6'], ['Flail (1h)', 5, '1d6'], ['Flail (2h)', 5, '1d8'], ['Mace (1h)', 5, '1d6'], ['Mace (2h)', 5, '1d8'], ['War Hammer (1h)', 5, '1d6'], ['War Hammer (2h)', 5, '1d8'], ['Spear (1h)', 3, '1d6'], ['Spear (2h)', 3, '1d8'], ['Short Sword', 7, '1d6'], ['Sword (1h)', 10, '1d6'], ['Sword (2h)', 10, '1d8'] ], 'heavy': [ ['Great Axe (2h)', 10, '1d10'], ['Morning Star (2h)', 10, '1d10'], ['Pole Arm (2h)', 7, '1d10'], ['Two-Handed Sword (2h)', 15, '1d10'] ] } npc_ranged_weapons_data = { 'light': [ ['Crossbow', 30, '1d6'], ['Shortbow', 3, '1d6'], ['Javelin', 1, '1d6'], ], 'heavy': [ ['Arbalest', 50, '1d8'], ['Composite Bow', 40, '1d6'], ['Longbow', 7, '1d6'], ] } def select_melee_weapon(guild): melee = npc_class_data[guild]['melee'] weapons = [] for x in range(0, melee[0]): weapons.extend(npc_melee_weapons_data['heavy']) for x in range(0, melee[1]): weapons.extend(npc_melee_weapons_data['medium']) for x in range(0, melee[2]): weapons.extend(npc_melee_weapons_data['light']) selection = randint(0, len(weapons) - 1) return weapons[selection] def select_ranged_weapon(guild): ranged = npc_class_data[guild]['ranged'] weapons = [] for x in range(0, ranged[0]): weapons.extend(npc_ranged_weapons_data['light']) for x in range(0, ranged[1]): weapons.extend(npc_ranged_weapons_data['heavy']) for x in range(0, ranged[2]): weapons.append(None) selection = randint(0, len(weapons) - 1) return weapons[selection] def generate_npc(base_level): attributes = npc_abilities() npc = {} npc['guild'] = npc_class() npc['level'] = npc_baselevel(base_level) npc['str'] = attributes[0] npc['int'] = attributes[1] npc['wis'] = attributes[2] npc['dex'] = attributes[3] npc['con'] = attributes[4] npc['chr'] = attributes[5] npc['hp'] = 0 conmod = attribute_mod(npc['con']) for x in range(0, npc['level']): hitdice = [randint(1, npc_class_data[npc['guild']]['hd'][1]) for x in range(0, npc_class_data[npc['guild']]['hd'][0])] for die in hitdice: die += conmod if die < 1: die = 1 npc['hp'] += die armourval = randint(0, len(npc_armour_list) - 1) + npc_class_data[npc['guild']]['armour'] if armourval < 0: armourval = 0 if armourval > len(npc_armour_list) - 1: armourval = len(npc_armour_list) - 1 npc['armour'] = npc_armour_list[armourval] npc['melee'] = select_melee_weapon(npc['guild']) npc['ranged'] = select_ranged_weapon(npc['guild']) return npc def create_party(base_level): party_size = number_encountered() return [generate_npc(base_level) for x in range(0, party_size)] def print_party(party): def print_npc(npc): print('Level {0} NPC, {1}, {2} HP'.format(npc['level'], npc['guild'], npc['hp'])) print('{0} Str, {1} Int, {2} Wis, {3} Dex, {4} Con, {5} Chr'.format( npc['str'], npc['int'], npc['wis'], npc['dex'], npc['con'], npc['chr'] )) print('Armour Class: {0} - {1}, {2}gp'.format(npc['armour'][2], npc['armour'][0], npc['armour'][1])) print('{:^16} - {:^10} - {:^10} - {:^10}'.format('Weapon', 'Gold', 'Throw Mod', 'Damage')) print('-------------------------------------------------------') print('{:^16} | {:^10} | {:^10} | {:^10}'.format(npc['melee'][0], npc['melee'][1], 0, npc['melee'][2])) if npc['ranged']: print('{:^16} | {:^10} | {:^10} | {:^10}'.format(npc['ranged'][0], npc['ranged'][1], 0, npc['ranged'][2])) print('\n') for npc in party: print_npc(npc) if __name__ == '__main__': party = create_party(2) print_party(party)