Skip to content

Instantly share code, notes, and snippets.

@victusfate
Created September 7, 2018 22:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save victusfate/057320fbef473b3d191910c2ffda72cb to your computer and use it in GitHub Desktop.
Save victusfate/057320fbef473b3d191910c2ffda72cb to your computer and use it in GitHub Desktop.
pathfinder playtest random encounter generator, to run node pathfinderEncounterGenerator <average_party_level> <party_size>
const aMonstersByLevel = [
[
"Animated broom",
"Beetle, fire",
"Bloodseeker",
"Boar, pig",
"Cat, bobcat",
"Centipede (giant)",
"Dog, guard",
"Goblin warrior",
"Halfling footpad",
"Homunculus",
"Horse, riding pony",
"Kobold warrior",
"Orc brute",
"Pack animal, donkey",
"Pack animal, ox",
"Rat (giant)",
"Skeleton guard",
"Snake, viper",
"Spider swarm",
"Unseen servant",
"Zombie shambler"
],
[
"Animated bureau",
"Bat swarm",
"Boggard scout",
"Camel",
"Cat, leopard",
"Demon, quasit",
"Devil, imp",
"Dog, riding dog",
"Drow fighter",
"Eel, electric",
"Elemental, air mephit",
"Elemental, earth mephit",
"Elemental, fire mephit",
"Elemental, water mephit",
"Ghoul",
"Goblin commando",
"Goblin dog",
"Goblin pyro",
"Goblin war chanter",
"Hobgoblin soldier",
"Horse, riding horse",
"Horse, war pony",
"Hyena",
"Kobold scout",
"Lizardfolk scout",
"Lizardfolk warrior",
"Orc warrior",
"Rat swarm",
"Reefclaw",
"Sewer ooze",
"Snake, ball python",
"Spider, hunting Wolf",
"Xulgath warrior",
"Zombie, plague"
],
[
"Animated armor",
"Bat, giant",
"Boar",
"Bugbear thug",
"Caligni creeper",
"Cat, panther",
"Choker",
"Crocodile",
"Demon, sloth",
"Devil, lemure",
"Dinosaur, deinonychus",
"Gnoll warrior",
"Gray ooze",
"Horse, war horse",
"Kobold dragon mage",
"Lizardfolk druid",
"Mummy guard",
"Orc warchief",
"Pterosaur, pteranodon",
"Sahuagin warrior",
"Serpentfolk",
"Shark, blue",
"Sinspawn",
"Skeleton, skeletal champion",
"Snake, viper (giant)",
"Vargouille",
"Warg",
"Werecreature, wererat rogue",
"Zombie brute"
],
[
"Animated statue",
"Ankhrav",
"Bear, grizzly",
"Bugbear fighter",
"Bunyip",
"Cat, lion",
"Cleric of Rovagug",
"Cockatrice",
"Doppelganger",
"Drow noble cleric",
"Dryad",
"Elemental, air (minor)",
"Elemental, earth (minor)",
"Elemental, fire (minor)",
"Elemental, water (minor)",
"Gelatinous cube",
"Ghoul, ghast",
"Hell hound",
"Hyena, hyaenodon",
"Mercenary scout",
"Ogre",
"Rust monster",
"Scorpion, giant",
"Serpentfolk, degenerate",
"Vile necromancer",
"Werecreature, werewolf fighter",
"Wight"
],
[
"Barghest",
"Caligni stalker",
"Cat, tiger",
"Gargoyle",
"Ghost commoner",
"Gnoll sergeant",
"Hag, green",
"Hobgoblin sniper",
"Genie, janni",
"Mimic",
"Minotaur",
"Otyugh",
"Owlbear",
"Sahuagin mutant",
"Shadow",
"Shark, great white",
"Vampire spawn rogue"
],
[
"Alchemical renegade",
"Cat, smilodon",
"Cyclops",
"Demonologist",
"Devil, bearded",
"Elemental, air (lesser)",
"Elemental, earth (lesser)",
"Elemental, fire (lesser)",
"Elemental, water (lesser)",
"Harpy",
"Ochre jelly",
"Poltergeist",
"Redcap",
"Troll",
"Warg, winter wolf",
"Yeti"
],
[
"Bear, cave",
"Demon, lust",
"Dinosaur, ankylosaurus",
"Dragon, white (young)",
"Drider",
"Ettin",
"Hydra",
"Manticore",
"Mummy retainer",
"Nightmare",
"Salamander",
"Shambler",
"Treant, animated tree",
"Vampire count",
"Will-o’-wisp",
"Wraith"
],
[
"Animated statue (giant)",
"Barghest (greater)",
"Black pudding",
"Cleric of Calistria",
"Demon, blood",
"Dragon, black (young)",
"Elemental, air (major)",
"Elemental, earth (major)",
"Elemental, fire (major)",
"Elemental, water (major)",
"Ghost soldier",
"Giant, hill",
"Medusa",
"Pterosaur, quetzalcoatlus",
"Shadow (greater)"
],
[
"Brain collector",
"Bulette",
"Chimera",
"Fury devil",
"Dragon, green (young)",
"Elephant, mastodon",
"Giant, stone",
"Golem, flesh",
"Oni, ogre mage",
"Sandpoint Devil",
"Snake, anaconda (giant)",
"Treant",
],
[
"Demon, wrath",
"Devil, bone",
"Dragon, blue (young)",
"Elemental, air (greater)",
"Elemental, earth (greater)",
"Elemental, fire (greater)",
"Elemental, water (greater)",
"Genie, efreeti",
"Giant, frost",
"Hag, night",
"Mummy pharaoh",
"Roc",
"Shark, megalodon",
"Vampire wizard",
"Wraith, dread",
],
[
"Demon, slaver",
"Devil, barbed",
"Dinosaur, tyrannosaurus",
"Dragon, red (young)",
"Dragon, white (adult)",
"Ghost mage",
"Giant, fire",
"Golem, clay",
"Masterful rogue",
"Rakshasa",
"Roper"
],
[
"Demon, toad",
"Dragon, black (adult)",
"Elemental, air (elder)",
"Elemental, earth (elder)",
"Elemental, fire (elder)",
"Elemental, water (elder)",
"Golem, stone",
"Spider, goliath"
],
[
"Demon, slime",
"Dragon, green (adult)",
"Lich",
"Rusalka",
"Sea serpent",
"Valkyrie"
],
[
"Banshee",
"Demon, treachery",
"Devil, ice",
"Dragon, blue (adult)",
"Golem, iron",
"Leng spider",
"Oni, ice yai",
"Purple worm"
],
[
"Dragon, red (adult)",
"Demon, boar",
"Deh-nolo",
"Oni, fire yai"
],
[
"Dragon, white (ancient)",
"Lich, demilich",
"Phoenix",
],
[
"Demon, mutilation",
"Devil, horned",
"Dragon, black (ancient)",
"Giant, rune",
"Warsworn"
],
[
"Demon, pride",
"Dragon, green (ancient)",
"Oni, water yai",
"Wendigo"
],
[
"Dragon, blue (ancient)",
"Golem, adamantine",
"Kraken",
"Norn",
"Saxra",
"Shoggoth"
],
[
"Dragon, red (ancient)",
"Grendel"
],
[
"Demon, fire",
"Devil, pit fiend",
"Star-spawn of Cthulhu"
],
[
"Grim reaper",
"Mu spore"
],
[
"Devastator",
"Titan, thanatotic"
],
[
"Jabberwock"
]
]
const args = process.argv.slice(2)
if (args.length < 2) {
console.log('required args average_party_level and party_size')
process.exit(0)
}
const apl = parseInt(args[0])
const party = parseInt(args[1])
const aSeverity = ['trivial','low','high','severe','extreme']
const aBudget = [
10 * party,
15 * party,
20 * party,
30 * party,
40 * party
]
const aLevels = [apl-4, apl-3, apl-2, apl-1, apl, apl+1, apl+2, apl+3, apl+4]
const aXp = [10,15,20,30,40,60,80,120,160]
const aCount = [10,8,6,6,3,2,1,1,1]
// returns 0 to val-1
const randomInteger = (val) => {
return Math.floor(Math.random()*val)
}
const generateEncounter = (iRandom,budget) => {
let xp = aXp[iRandom]
let level = aLevels[iRandom]
let testBudget = xp
let iTotal = 0
let sCreature = ''
// console.log({ testBudget: testBudget, budget: budget, iRandom: iRandom })
if (testBudget <= budget && level >= 0 && level < aMonstersByLevel.length) {
const iRandomCreature = randomInteger(aMonstersByLevel[level].length)
sCreature = aMonstersByLevel[level][iRandomCreature]
iTotal = 1
while ( (testBudget + xp) <= budget && iTotal < aCount[iRandom]) {
testBudget += xp
iTotal++
}
}
return { nFound: iTotal, level: level, testBudget: testBudget, budgetAllowed: budget, creature: sCreature }
}
console.log('average party level',apl)
console.log('party size',party)
for (let i in aSeverity) {
console.log(aSeverity[i])
const budget = aBudget[i]
let iRandom = randomInteger(aLevels.length)
let testBudget = 0
let iTrials = 0
let aEncounter = []
// console.log({ testBudget: testBudget, budget: budget, iRandom: iRandom, level: aLevels[iRandom], xp: aXp[iRandomLevel], iTrials: iTrials })
while (testBudget < budget && iTrials < 100) {
const oResults = generateEncounter(iRandom,budget - testBudget)
if (oResults.nFound > 0) {
testBudget += oResults.testBudget
aEncounter.push(oResults)
}
iRandom = randomInteger(aLevels.length)
iTrials++
}
console.log(aEncounter)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment