You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
7.8 KiB

  1. from random import randint
  2. def number_encountered():
  3. return (randint(1, 4) + 2)
  4. def npc_class():
  5. roll = (randint(1, 6) + randint(1, 6) + randint(1, 6))
  6. if roll == 3 or roll == 4:
  7. return 'Elven Nightblade'
  8. elif roll == 5:
  9. return 'Elven Spellsword'
  10. elif roll == 6:
  11. return 'Explorer'
  12. elif roll == 7:
  13. return 'Bladedancer'
  14. elif roll == 8:
  15. return 'Cleric'
  16. elif roll == 9 or roll == 10 or roll == 11:
  17. return 'Fighter'
  18. elif roll == 12:
  19. return 'Thief'
  20. elif roll == 13:
  21. return 'Mage'
  22. elif roll == 14:
  23. return 'Assassin'
  24. elif roll == 15:
  25. return 'Bard'
  26. elif roll == 16:
  27. return 'Dwarven Vaultguard'
  28. elif roll == 17 or roll == 18:
  29. return 'Dwarven Craftpriest'
  30. def npc_alignment():
  31. roll = randint(1, 6)
  32. if roll == 1 or roll == 2:
  33. return 'Lawful'
  34. elif roll == 3 or roll == 4 or roll == 5:
  35. return 'Neutral'
  36. elif roll == 6:
  37. return 'Chaotic'
  38. def npc_baselevel(base_level):
  39. roll = randint(1, 6)
  40. mod = 0
  41. if roll == 1:
  42. mod = -2
  43. elif roll == 2:
  44. mod = -1
  45. elif roll == 3 or roll == 4:
  46. mod = 0
  47. elif roll == 5:
  48. mod = 1
  49. elif roll == 6:
  50. mod = 2
  51. base_level += mod
  52. if base_level < 1:
  53. base_level = 1
  54. return base_level
  55. def npc_abilities():
  56. return [(randint(1, 6) + randint(1, 6) + randint(1, 6)) for x in range(0,6)]
  57. def attribute_mod(atr):
  58. mod = 0
  59. if atr <= 3: mod = -3
  60. if atr >= 4 and atr <= 5: mod = -2
  61. if atr >= 6 and atr <= 8: mod = -1
  62. if atr >= 9 and atr <= 12: mod = 0
  63. if atr >= 13 and atr <= 15: mod = 1
  64. if atr >= 16 and atr <= 17: mod = 2
  65. if atr >= 18: mod = 3
  66. return mod
  67. npc_class_data = {
  68. 'Elven Nightblade': {
  69. 'hd': [1, 6],
  70. 'armour': -4,
  71. 'melee': [0, 2, 1],
  72. 'ranged': [0, 0, 1]
  73. },
  74. 'Elven Spellsword': {
  75. 'hd': [1, 6],
  76. 'armour': -4,
  77. 'melee': [0, 1, 0],
  78. 'ranged': [0, 0, 1]
  79. },
  80. 'Explorer': {
  81. 'hd': [1, 6],
  82. 'armour': -3,
  83. 'melee': [0, 1, 1],
  84. 'ranged': [0, 1, 2]
  85. },
  86. 'Bladedancer': {
  87. 'hd': [1, 6],
  88. 'armour': -2,
  89. 'melee': [0, 1, 0],
  90. 'ranged': [0, 0, 1]
  91. },
  92. 'Cleric': {
  93. 'hd': [1, 6],
  94. 'armour': 0,
  95. 'melee': [1, 3, 1],
  96. 'ranged': [1, 3, 4]
  97. },
  98. 'Fighter': {
  99. 'hd': [1, 8],
  100. 'armour': 1,
  101. 'melee': [1, 4, 1],
  102. 'ranged': [1, 1, 4],
  103. },
  104. 'Thief': {
  105. 'hd': [1, 4],
  106. 'armour': -6,
  107. 'melee': [0, 1, 1],
  108. 'ranged': [1, 0, 6]
  109. },
  110. 'Mage': {
  111. 'hd': [1, 4],
  112. 'armour': -8,
  113. 'melee': [0, 0, 1],
  114. 'ranged': [0, 0, 1]
  115. },
  116. 'Assassin': {
  117. 'hd': [1, 6],
  118. 'armour': -6,
  119. 'melee': [0, 2, 1],
  120. 'ranged': [1, 0, 5]
  121. },
  122. 'Bard': {
  123. 'hd': [1, 6],
  124. 'armour': -3,
  125. 'melee': [0, 2, 1],
  126. 'ranged': [1, 0, 4]
  127. },
  128. 'Dwarven Vaultguard': {
  129. 'hd': [1, 8],
  130. 'armour': -1,
  131. 'melee': [1, 3, 0],
  132. 'ranged': [1, 1, 6]
  133. },
  134. 'Dwarven Craftpriest': {
  135. 'hd': [1, 6],
  136. 'armour': -2,
  137. 'melee': [0, 1, 0],
  138. 'ranged': [1, 0, 5]
  139. }
  140. }
  141. npc_armour_list = [
  142. ['Clothing Only', 0, 0],
  143. ['Hide and Fur Armour', 10, 1],
  144. ['Leather Armour', 20, 2],
  145. ['Ring Mail Armour', 30, 3],
  146. ['Scale Mail Armour', 30, 3],
  147. ['Chain Mail Armour', 40, 4],
  148. ['Banded Plate', 50, 5],
  149. ['Lamellar Armour', 50, 5],
  150. ['Plate Armour', 60, 6],
  151. ]
  152. npc_melee_weapons_data = {
  153. 'light': [
  154. ['Club', 1, '1d4'],
  155. ['Dagger', 3, '1d4'],
  156. ['Sap', 1, '1d4'],
  157. ['Staff (1h)', 1, '1d4'],
  158. ['Staff (2h)', 1, '1d6'],
  159. ['Whip', 5, '1d2']
  160. ],
  161. 'medium': [
  162. ['Battle Axe (1h)', 7, '1d6'],
  163. ['Battle Axe (2h)', 7, '1d8'],
  164. ['Hand Axe', 4, '1d6'],
  165. ['Flail (1h)', 5, '1d6'],
  166. ['Flail (2h)', 5, '1d8'],
  167. ['Mace (1h)', 5, '1d6'],
  168. ['Mace (2h)', 5, '1d8'],
  169. ['War Hammer (1h)', 5, '1d6'],
  170. ['War Hammer (2h)', 5, '1d8'],
  171. ['Spear (1h)', 3, '1d6'],
  172. ['Spear (2h)', 3, '1d8'],
  173. ['Short Sword', 7, '1d6'],
  174. ['Sword (1h)', 10, '1d6'],
  175. ['Sword (2h)', 10, '1d8']
  176. ],
  177. 'heavy': [
  178. ['Great Axe (2h)', 10, '1d10'],
  179. ['Morning Star (2h)', 10, '1d10'],
  180. ['Pole Arm (2h)', 7, '1d10'],
  181. ['Two-Handed Sword (2h)', 15, '1d10']
  182. ]
  183. }
  184. npc_ranged_weapons_data = {
  185. 'light': [
  186. ['Crossbow', 30, '1d6'],
  187. ['Shortbow', 3, '1d6'],
  188. ['Javelin', 1, '1d6'],
  189. ],
  190. 'heavy': [
  191. ['Arbalest', 50, '1d8'],
  192. ['Composite Bow', 40, '1d6'],
  193. ['Longbow', 7, '1d6'],
  194. ]
  195. }
  196. def select_melee_weapon(guild):
  197. melee = npc_class_data[guild]['melee']
  198. weapons = []
  199. for x in range(0, melee[0]):
  200. weapons.extend(npc_melee_weapons_data['heavy'])
  201. for x in range(0, melee[1]):
  202. weapons.extend(npc_melee_weapons_data['medium'])
  203. for x in range(0, melee[2]):
  204. weapons.extend(npc_melee_weapons_data['light'])
  205. selection = randint(0, len(weapons) - 1)
  206. return weapons[selection]
  207. def select_ranged_weapon(guild):
  208. ranged = npc_class_data[guild]['ranged']
  209. weapons = []
  210. for x in range(0, ranged[0]):
  211. weapons.extend(npc_ranged_weapons_data['light'])
  212. for x in range(0, ranged[1]):
  213. weapons.extend(npc_ranged_weapons_data['heavy'])
  214. for x in range(0, ranged[2]):
  215. weapons.append(None)
  216. selection = randint(0, len(weapons) - 1)
  217. return weapons[selection]
  218. def generate_npc(base_level):
  219. attributes = npc_abilities()
  220. npc = {}
  221. npc['guild'] = npc_class()
  222. npc['level'] = npc_baselevel(base_level)
  223. npc['str'] = attributes[0]
  224. npc['int'] = attributes[1]
  225. npc['wis'] = attributes[2]
  226. npc['dex'] = attributes[3]
  227. npc['con'] = attributes[4]
  228. npc['chr'] = attributes[5]
  229. npc['hp'] = 0
  230. conmod = attribute_mod(npc['con'])
  231. for x in range(0, npc['level']):
  232. hitdice = [randint(1, npc_class_data[npc['guild']]['hd'][1]) for x in range(0, npc_class_data[npc['guild']]['hd'][0])]
  233. for die in hitdice:
  234. die += conmod
  235. if die < 1:
  236. die = 1
  237. npc['hp'] += die
  238. armourval = randint(0, len(npc_armour_list) - 1) + npc_class_data[npc['guild']]['armour']
  239. if armourval < 0:
  240. armourval = 0
  241. if armourval > len(npc_armour_list) - 1:
  242. armourval = len(npc_armour_list) - 1
  243. npc['armour'] = npc_armour_list[armourval]
  244. npc['melee'] = select_melee_weapon(npc['guild'])
  245. npc['ranged'] = select_ranged_weapon(npc['guild'])
  246. return npc
  247. def create_party(base_level):
  248. party_size = number_encountered()
  249. return [generate_npc(base_level) for x in range(0, party_size)]
  250. def print_party(party):
  251. def print_npc(npc):
  252. print('Level {0} NPC, {1}, {2} HP'.format(npc['level'], npc['guild'], npc['hp']))
  253. print('{0} Str, {1} Int, {2} Wis, {3} Dex, {4} Con, {5} Chr'.format(
  254. npc['str'], npc['int'], npc['wis'],
  255. npc['dex'], npc['con'], npc['chr']
  256. ))
  257. print('Armour Class: {0} - {1}, {2}gp'.format(npc['armour'][2], npc['armour'][0], npc['armour'][1]))
  258. print('{:^16} - {:^10} - {:^10} - {:^10}'.format('Weapon', 'Gold', 'Throw Mod', 'Damage'))
  259. print('-------------------------------------------------------')
  260. print('{:^16} | {:^10} | {:^10} | {:^10}'.format(npc['melee'][0], npc['melee'][1], 0, npc['melee'][2]))
  261. if npc['ranged']:
  262. print('{:^16} | {:^10} | {:^10} | {:^10}'.format(npc['ranged'][0], npc['ranged'][1], 0, npc['ranged'][2]))
  263. print('\n')
  264. for npc in party:
  265. print_npc(npc)
  266. if __name__ == '__main__':
  267. party = create_party(2)
  268. print_party(party)