Wednesday, July 16, 2014

Rolling vs Role Playing Discovery of Traps and Secret Doors

Someone on G+ asked: "Mechanically, why were players expected to role play 'finding traps' but the X in 6 chance to find secret/hidden doors has been there since the get go?"

We need to distinguish between finding traps and disarming/circumventing traps. The accepted practice is to role play disarming/circumventing traps, but that's not the usual case for finding traps.

Characters find pit traps, for example, by falling in them, as determined with the roll of a die. The Underworld & Wilderness Adventures says on page 9:

"Traps are usually sprung by a roll of a 1 or a 2 when any character passes over or by them. Pits will open in the same manner."

Once players know the pit is there, it's easy to avoid in the future. We might be tempted to complain that dice rolling of this sort is unfair in its arbitrariness, but consider the alternative of role playing the examination every crack, hole, and loose stone in the dungeon.

Other kinds of traps — where the presence of a trap is obvious, but the way of avoiding it is not — we resolve through role playing. "You enter a room with a rotting bisected goblin corpse in its center. A few feet from the goblin's body, an overturned bucket spills grease onto the stone floor. Above the corpse, you notice a dark slot in the ceiling from one side wall to the other, and connecting grooves running down the side walls that seem to be greased. What do you do?" No dice roll required.

What about rolling for secret doors? Here's U&WA again:

"Secret passages will be located on the roll of a 1 or a 2 (on a six-sided die) by men, dwarves or hobbits. Elves will be able to locate them on a roll of 1-4. At the referee's option, Elves may be allowed the chance to sense any secret door they pass, a 1 or a 2 indicating that they become aware that something is there."

The text uses "located" rather than "opened", and draws a distinction between actively locating known/suspected secret doors and passively spotting unknown/unsuspected ones.

That suggests a procedure where, after a secret door is located by a roll, we role play opening the door. "I'm going to try pushing each edge of the door outline, and if that doesn't work I'll fiddle with the nearby sconce."

The mechanics for traps and doors are the same (with the obvious reversal that traps are meant to be found (triggered) and secret doors are not).

How to Open the Secret Door

  1. Push door edge to pivot door.
  2. Twist wall sconce near door.
  3. Pull out jutting stone near door edge to release latch.
  4. Replace missing wall stone lying among debris on floor (falls out after door closes again).
  5. Only opens for [1-2 Magic-users 3-4 Fighting-men 5-6 Clerics].
  6. Only opens for [1-2 Monsters 3-4 Undead 5-6 Puddings, jellies, etc.].
  7. Push two stones, one on either side of the door, simultaneously.
  8. Smear you hand with blood, and touch the faint brownish handprint in the middle of the door.
  9. Step on protruding flagstone on floor.
  10. Drain water from adjoining room to relieve pressure on door.
  11. Burn away wax facade.
  12. Opens when the other door to the room is locked.
  13. Hidden door is a decoy; entire wall rotates.
  14. Insert staff or rod in small hole to lever door open.
  15. A strong magnet raises a latch internal to the door.
  16. Opens in light of the moon (may require several mirrors).
  17. Circular door. It unscrews.
  18. Prying the base of the "door" unfolds a ladder — there's a trap door in the ceiling.
  19. Pull latch inside mouth of stone devil face.
  20. Rearming nearby trap causes door to open

"Somethings" Elves Sense Besides Secret Doors

  1. An elf died on this spot centuries ago. Clerics able to cast Speak with Dead may contact this elf regardless of their level and how long ago the elf died, although the spirit mostly wants to share the morbid elven verse its been composing to while away the years.
  2. Cold iron
  3. Flowing water
  4. Dwarves
  5. Pentangles
  6. Elf needs food

Saturday, July 5, 2014

Judges Guild style numbered hex paper

I made some Judges Guild style numbered hex paper, broken up into four US letter size pages. The zip file includes editable Inkscape SVG's and PDF's.

Thursday, July 3, 2014

Bookmark: A Framework for D&D Horror

John at Dreams in the Lich House nicely articulates a framework for D&D horror. It sounds like a good plan, and I look forward to hearing more details.

Thursday, June 12, 2014

B/X Combined and Expanded Index

I combined and expanded the indices for Moldvay Basic and Marsh/Cook Expert. Here's the B/X Index PDF (and the LaTeX file).

Monday, June 9, 2014

More Micro Generator Examples

(This is a follow-up to my previous post on the topic. To see all the examples in a slightly more readable format, click here.)

Magic Item Type Example

Here we have the classic Magic Item Type selection table from page 23 of Monsters & Treasure.

The Code for Magic Item Type

This script selects items from a table that has one result for a range of rolls. The list syntax is slightly different than we've seen. It's a list that contains lists.

<script>
function getMagicItemType() {
    var magicItemTypesTable = [
        [20, "Swords"],
        [15, "Armor"],
        [5, "Misc. Weapons"],
        [25, "Potions"],
        [20, "Scrolls"],
        [5, "Rings"],
        [5, "Wands/Staves"],
        [5, "Misc. Magic"]
    ];
    function randomTableValue(table) {
        // How large is this table? What's the maximum roll? d12, d100, or what?
        var max = 0;
        for (var i = 0; i < table.length; i++) {
            max = max + table[i][0];
        }
        var roll = Math.floor(Math.random() * max) + 1;
        // Find our roll result in the table:
        var countUpToRoll = 0;
        for (var i = 0; i < table.length; i++) {
            if (roll <= table[i][0] + countUpToRoll) {
                return "d" + max + " = " + roll + ": " + table[i][1];
            } else {
                countUpToRoll = countUpToRoll + table[i][0];
            }
        }
    }
    var itemType = document.getElementById("magicitemtype");
    itemType.innerHTML = randomTableValue(magicItemTypesTable);
}
</script>
<div>
<button onclick="getMagicItemType();">Roll Magic Item Type</button>
<span id="magicitemtype"></span>
</div>

Arena Fighter Name Generator

We can slightly vary the generated content with randomness and conditional execution.

Math.random() returns a value between 0 and 1.

<script>
function arenaFighterName() {
    function arnd(a) {
        // Return random element of array a.
        var i = Math.floor(Math.random() * (a.length));
        if (typeof a[i] === 'function') {
            return a[i]();
        }
        return a[i];
    }
    function namePart1() {
        return arnd([
            "Al", "En", "Ro", "Fel", "Ston", "Hal", "Jo", "Nel", "Ve", "Ga"
        ]) + arnd([
            "rick", "bert", "wick", "thor", "ky", "son", "frey", "sley", "gil"
        ]);
    }
    function namePart2() {
        var x = Math.random();
        if (x < 0.25) {
            return "the " + arnd([
                "Brave", "Bloody", "Bold", "Cruel", "Clever", "Cunning",
                "Indomitable", "Destroyer", "Quick", "Heartless", "Sly"
            ]);
        } else if (x < 0.5) {
            return "of " + arnd([
                "Green", "New", "River", "Dun", "Lun", "North", "Wolver",
                "Tam", "Chapel", "Wit", "Bran", "Mor", "Ep", "Grims", "Gos"
            ]) + arnd([
                "thorpe", "by", "ford", "bury", "ham", "shire", "ton", "don",
                "ly", "field", "beck", "gate", "well", "holme", "wick", "port"
            ]);
        } else if (x < 0.75) {
            return namePart1();
        } else {
            return "";
        }
    }
    var name = namePart1() + " " + namePart2();
    var outputSpan = document.getElementById("arenafightername");
    outputSpan.innerHTML = name;
}
</script>
<div>
<button onclick="arenaFighterName();">Arena Fighter Name</button>
<span id="arenafightername"></span>
</div>

Dynamically Chosen and Arranged Images (Geomorphs!)

We can play with images as well as text.


<script>
function shuffleGeomorphs() {
    function arnd(a) {
        // Return random element of array a.
        var i = Math.floor(Math.random() * (a.length));
        if (typeof a[i] === 'function') {
            return a[i]();
        }   
        return a[i];
    }
    var geomorphImages = [
        "img/g01.png",
        "img/g02.png",
        "img/g03.png",
        "img/g04.png",
        "img/g05.png",
        "img/g06.png",
        "img/g07.png",
        "img/g08.png",
    ];
    var imageOutputs = document.getElementById('geomorphgrid').childNodes;
    for(var i = 0; i < imageOutputs.length; i++) {
        imageOutputs[i].src = arnd(geomorphImages);
    }
}
</script>
<button onclick="shuffleGeomorphs();">Shuffle Geomorphs</button>
<div id="geomorphgrid">
<img src="img/g00.png">
<img src="img/g00.png">
<img src="img/g00.png">
<br>
<img src="img/g00.png">
<img src="img/g00.png">
<img src="img/g00.png">
</div>

Thursday, June 5, 2014

Embedded Micro Generators for Dungeons & Dragons Blogs

(If you want to read this post with a slightly more readable presentation, go here.)

JDJarvis over at Aeons & Augauries inspired me to write this with his little generators like the Foul Tomes of Carcosa.

You can include generated content in you blog posts by adding a script like the ones below. Put the code into your post using your blog editor's text/​HTML mode (on Blogger, click the "HTML" button next to the "Compose" button). Each example is entirely self-contained. Cut, paste, and tinker!

d20 Example

Here we click a button to generate a random number.


The Code for d20

<script>
function roll20() {
    var min = 1;
    var max = 20;
    var roll = Math.floor(Math.random() * (max - min + 1)) + min;
    var outputSpan = document.getElementById("d20result");
    outputSpan.innerHTML = roll;
}
</script>
<div>
<button onclick="roll20();">d20</button>
<span id="d20result"></span>
</div>

Magic Tower Example

Here we combine random selections from various lists, and do it without a button.

Click this paragraph to generate a Magic Tower (then click it again to generate another).

The Code for Magic Tower

<script>
function generateMagicTower() {
    function arnd(a) {
        // Return random element of array a.
        var i = Math.floor(Math.random() * (a.length));
        if (typeof a[i] === 'function') {
            return a[i]();
        }   
        return a[i];
    }
    var colors = ["Red", "Black", "White", "Gray", "Pearlescent", "Lurid", "Hoary"];
    var structures = ["Tower", "Spire", "Turret", "Belfry", "Citadel", "Seculsium"];
    var outputParagraph = document.getElementById("magictower");
    outputParagraph.innerHTML = "The " + arnd(colors) + " " + arnd(structures);
}
</script>
<p id="magictower" onclick="generateMagicTower();">Click this paragraph to generate a Magic Tower (then click it again to generate another).</p>

Dynamic Hit Points Example

In the paragraph below, the hit points are randomly generated each time the page loads. Reload this page to see the hit points change.

An Ogre (HP ; AC 5; Move 9"; HD 4+1) glowers from the cave entrance.

The Code for Dynamic Hit Points

<p>An Ogre (HP <span id="ogrehitpoints"></span>; AC 5; Move 9"; HD 4+1) glowers from the cave entrance.</p>
<script>
function rollHitPoints(hdNumber, hdPlus, hdSize) {
    hdNumber = hdNumber || 1;
    hdPlus = hdPlus || 0;
    hdSize = hdSize || 6;
    var hitPoints = 0;
    for (var i = 0; i < hdNumber; i++) {
        hitPoints = hitPoints + Math.floor(Math.random() * hdSize) + 1;
    }
    hitPoints = hitPoints + hdPlus;
    return hitPoints;
}
var ogreHitPoints = document.getElementById("ogrehitpoints");
ogreHitPoints.innerHTML = rollHitPoints(4, 1);
</script>

Learn More About JavaScript

You can learn a lot of JavaScript using free tutorials on the web.

Start a cheat sheet and keep track of what you learn. Refine it over time as your understanding increases. Here's my JavaScript cheat sheet, for example.

You may also want to keep a code clipping file to store useful and clever little bits of JavaScript to reuse.

Mozilla Developer Connection has a good JavaScript reference. It's a better than many of the alternatives that rank higher on Google results. (In fact, when I search for JavaScript reference info, I include "MDN" in my search terms.)

If you want to learn from books, these are good:

If you start writing scripts of more than a dozen lines, get yourself a good text editor. For Windows, try NotePad++. For Mac, try TextWrangler. If you're on Linux, you probably already have a favorite text editor, but if not try gEdit (or go all hardcore and learn vim).

Finally, you should at least be aware of JSLint and JSHint. They're alternative sites that find errors in JavaScript code. JSLint is more rigorous/harsher. If your JavaScript gets an error you can't solve, these tools may help you find it.

About These Micro Generators

This code was written by Paul Gorman. You may copy, reuse, redistribute, and modify the example code however you see fit.

Test

This is a test.