February 18th, 2004



Experience points, that is.

So I decided to code up an XP calculator in perl, to make it simpler than the addition and division I do currently. (Not that it's hard, but it is a little time-consuming.)

The code ended up being simple enough that I decided to share it with the world:

sub xp($@) {
    my ($level, @CRs) = @_;
    my $total_xp = 0;
    for (@CRs) {
	my $xp = 300 * $level * (2 ** (($_ - $level) / 2));
	$total_xp += $xp;
    return $total_xp;

for (@ARGV) {
    eval $_;

The syntax for using it is somewhat hairy, but useful for me as a Perl user. The last bit of the code is the user interface, which is just "take a hunk of perl code and execute it." So for me to calculate the XP that a 9th-level member of a party of 5 PCs gets for defeating 6 CR 3 monsters, 3 CR 5 monsters, and one CR 8 monster, I call:

perl xp.pl "print xp(9, ((3) x 6, (5) x 3, 8)) / 5;"

It's not super-clear, but for someone used to reading Perl, it's not too bad. And it's easier to see that the award is divided by 5 with this syntax than if the 5 were just one among many numeric arguments. (It is cryptic enough that I'm not trying hard to share this snippet of code with the world, though.)

This function matches the Dungeon Master's Guide's value for experience points when the difference between the PC level and the CR is even, but it yields less than the DMG value when the difference is odd. The reason is that the DMG doesn't use a precise value for the square root of 2; they approximate the geometric mean of x and 2x by 1.5x. This is the right thing to do for a table that people are going to be adding up by hand. But if the computer is doing all the math anyway, it simplifies the code to use the correct square root.