Skip to content

Instantly share code, notes, and snippets.

@dsibilly
Created May 25, 2012 13:24
Show Gist options
  • Save dsibilly/2788148 to your computer and use it in GitHub Desktop.
Save dsibilly/2788148 to your computer and use it in GitHub Desktop.
D&D 4th Edition Encounter Level Calculator
/**
* 4e-xp.js
* D&D 4th Edition Encounter Level Calculator
*
* Copyright (C) 2012 Duane Sibilly <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Usage: node 4e-xp.js -pcs [4-6] -xp [total encounter XP]
*/
(function () {
'use strict';
var print = console.log,
// 4e XP tables don't cleanly map to smooth functions,so it is
// faster to store them as hashtables for quick lookup.
targetXP = {
four: [
0, 400, 500, 600, 700, 800, 1000, 1200, 1400, 1600, 2000, 2400, 2800, 3200, 4000, 4800, 5600, 6400, 8000, 9600, 11200, 12800, 16600, 20400, 24200, 28000, 36000, 44000, 52000, 60000, 76000],
five: [
0, 500, 625, 750, 875, 1000, 1250, 1500, 1750, 2000, 2500, 3000, 3500, 4000, 5000, 6000, 7000, 8000, 10000, 12000, 14000, 16000, 20750, 25500, 30250, 35000, 45000, 55000, 65000, 75000, 95000],
six: [
0, 600, 750, 900, 1050, 1200, 1500, 1800, 2100, 2400, 3000, 3600, 4200, 4800, 6000, 7200, 8400, 9600, 12000, 14400, 16800, 19200, 24900, 30600, 36300, 42000, 54000, 66000, 78000, 90000, 114000]
},
// What is the estimated encounter level based on the XP total
// for the encounter and the number of PCs?
calculateEncounterLevel = function (XP, players) {
var key, EL, found = false;
switch (players) {
case 5:
key = 'five';
break;
case 6:
key = 'six';
break;
default:
key = 'four';
}
EL = targetXP[key].reduce(function (prev, curr, idx, arr) {
if (! found) {
if (XP === curr) {
found = true;
return idx;
}
if (XP < curr) {
found = true;
return (idx - 1) + ((XP - arr[idx - 1]) / (curr - arr[idx - 1]));
}
}
return prev;
});
print('Encounter XP: ' + XP);
print('No. of Players: ' + players);
print('Encounter Level: ' + EL.toFixed(1));
},
parse = function (args) {
var opts = {},
curSwitch, i, len, arg;
args = args || process.argv;
for (i = 0, len = args.length; i < len; i += 1) {
arg = args[i];
// it's a switch
if (/^(-|--)/.test(arg) || !curSwitch) {
opts[arg] = true;
curSwitch = arg;
} else {
if ('false' === arg) {
arg = false;
} else if ('true' === arg) {
arg = true;
} else if (! isNaN(arg)) {
arg = Number(arg);
}
if (typeof opts[curSwitch] === 'boolean') {
opts[curSwitch] = arg;
} else if (Array.isArray(opts[curSwitch])) {
opts[curSwitch].push(arg);
} else {
opts[curSwitch] = [opts[curSwitch], arg];
}
}
}
return opts;
},
args = parse(),
xp = args['-xp'],
pcs = args['-pcs'];
if (! xp) {
print('You must provide an XP value with the -xp switch');
return;
}
if (pcs < 4 || pcs > 6) {
print('Party size is limited to 4, 5 or 6 PCs');
return;
}
if (pcs) {
calculateEncounterLevel(xp, pcs);
} else {
calculateEncounterLevel(xp);
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment