Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <h1>Gygaxian Demon Generator</h1>
<div id="content">
  <select id="number" onChange = "changeText()">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>
  </select>
  <button id="button" onclick="makeDemon()" value="New Demon">New Demon</button>
</div>

              
            
!

CSS

              
                .demon{
  background-color:#cccccc;
  margin:10px;
  padding:10px;
  border-radius:2px;
}
li{
  list-style-type:none;
}
ul{
  margin-bottom:10px;
}
h3{
  border-bottom:1px solid black;
}
li span{
  font-weight:bold;
}
              
            
!

JS

              
                /****************************
All info taken from the original DMG
Thanks Gary
****************************/
//array holds created demons
var demons = [];
/*********
function to roll on the tables
@param index which table to roll on
@param attributes master set to use
@param times how many times to roll
**********/
function roll(index, attributes, times){
  //check if times is set
  if(!times || times===null){
    times = 1;
  }
  //set the resu;lt
  var result = "";
  //roll given number or times
  for(i = 0; i < times; i++){
    var randomNum = Math.floor(Math.random() * attributes[index].length);
    //get the entry
    var entry = attributes[index][randomNum];
    //remove entry from the array
    attributes[index].splice(randomNum, 1);
    //add to the result
    result += entry;
    //add comma unless last roll
    if(times>1 && i < times-1){
      result+= ", ";
    }
  }
  //return the result
  return result;
}
/***************
function to generate random number
@param sides how many sides to roll for the die
***************/
function die(sides){
  return Math.ceil(Math.random() * sides);
}
/**
Demon Object
**/
function Demon(){
//attributes array for general demon abilities
var attributes = [];
//each sub array for the tables
var heads = 0;
attributes[0] = ["bat-like", "bird-like", "crocodillian", "horse-like", "human-like", "monkey-like", "snake-like", "weasel-like", "goat-like", "bovine", "rams", "insectile", "spider-like", "horrific and indescribable"];
var headAdornments = 1;
attributes[1] = ["antlers", " a crest", "horns", "knobs", "ridges", "a tattered ruff of bloody flesh", "spines", "oozing sores", "warts", "fleshy growths", "tiny writhing tentacles", "crystaline growths", "shards of glass", "palpating mounds of putrid flesh", "none"];
var visages = 2; 
attributes[2] = ["gibbering", "drooling", "glaring", "rotting", "skeletal", "twitching", "wrinkled", "maggot-riddled", "disgusting", "horrific", "twisted", "deranged"];
var ears = 3;
attributes[3] = ["dog-like", "elephant-like", "tiny human-like", "huge human-like", "trumpet-like", "no"];
var eyes = 4;
attributes[4] = ["small, multi-faceted", "small, slitted", "swivel-socketed", "stalked", "huge, flat", "huge, protruding", "sunken empty holes instead of", "bloody", "psychedelic, swirling", "crab-like", "soulless black"];
var noses = 5;
attributes[5] = ["flat, misshapen", "huge, bulbous", "slits only", "tiny", "hole of a", "trunk-like", "horrible insect-like proboscis", "bloody gash for a", "completely non-existent", "writhing, maggot-like"];
var mouths = 6;
attributes[6] = ["fanged", "mandibled", "sucker-like", "small, toothed", "rigid, toothed", "large, toothed", "tusked", "festering, toothless", "duck-billed", "canine", "fishy", "wet, dripping", "blood spewing sore surrounded"];
var torsos =7;
attributes[7] = ["ape-like", "bear-like", "bird-like", "human-like", "pig-like", "rat-like", "amoeba-like", "bison-like", "cat-like", "crab-like", "horse-like", "insect-like", "serpent-like", "spider-like"];
var characteristics = 8;
attributes[8] = ["fat", "long", "short", "thin", "broad", "muscled", "narrow", "rubbery"];
var tails = 9;
attributes[9] = ["barbed", "dog-like", "goat-like", "horse-like", "lion-like", "pig-like", "prehensile", "stingered", "pathetic squirrel", "writhing maggot"];
var bodyOdors = 10;
attributes[10] = ["bloody", "fishy", "fecal", "gangrenous", "moldy", "sweaty", "urine", "vomit", "death", "brimstone"];
var skins = 11;
attributes[11] = ["bald", "smooth", "furred", "hairy", "bristled", "leathery", "leprous", "scaled", "slimy", "warted", "wrinkled", "chitinous", "bony", "rhino-like", "maggoty", "pus-dripping", "oozing", "crystalline", "feathered"];
var colors = 12;
attributes[12] = ["blackish", "bluish", "brownish", "grayish", "whitish", "greenish", "orange", "pinkish", "purplish", "reddish", "yellowish", "festering", "translucent"];
var backs = 13;
attributes[13] = ["humped", "hunched", "maned", "sore-covered", "spiked", "spined", "ridged", "twisted", "broken", "constantly writhing"];
var wings = 14;
attributes[14] = ["bat-like", "bird-like", "insect-like", "membranous", "skeletal", "wretched flesh"];
var arms = 15;
attributes[15] = ["animal-like", "human-like", "insect-like", "tentacled", "rubbery", "variegated ", "twisted"];
var hands = 16;
attributes[16] = ["clawed", "human-nailed", "pincered", "taloned", "tentacle-fingered", "withered and bony"];
var legs = 17;
attributes[17] = ["duck-like", "hawk-like", "clawed", "hoofed", "human-like", "insect-like", "serpentine", "suctioned", "rubbery", "taloned", "webbed", "flipper-like", "skeletal", "tiny"]
var specialAttacks = 18;
attributes[18] = ["Strength Drain", "Constitution Drain", "Intelligence Drain", "Energy Drain (cold)", "Generates Heat (+2 to damage)", "Level Drain", "Charm Person as spell", "Dancing Lights as Spell", "Darkness 15' Radius as spell", "Invisibility as spell", "Spider Climb as spell", "Polymorph Self as spell"];
var specialDefenses = 19;
attributes[19]=["Immune to Cold", "Immune to Fire/Heat", "Immune to Electrical Attacks", "Only hit by +1 Weapons", "+4 to save vs. Magic", "Can only be hit by non-metal weapons", "Regenerate "+die(3)+" HP/round", "Immune to Surprise", "See Invisible", "Dark Vision"];  
  var a = attributes;
  //randomly set each of the values for the demon
  this.head = roll(heads, a);
  this.headAdornment = roll(headAdornments, a);
  this.visage = roll(visages, a);
  this.ears = roll(ears, a);
  this.numEyes = die(2) * 2;
  this.eyes = roll(eyes, a);
  this.nose = roll(noses, a);
  this.numMouths = die(4);
  this.mouth = roll(mouths, a);
  this.torso = roll(torsos, a);
  this.characteristics = roll(characteristics, a, 2);
  this.tail = roll(tails, a);
  this.bodyOdor = roll(bodyOdors, a);
  this.skin = roll(skins, a);
  this.color = roll(colors, a);
  this.back = roll(backs, a);
  this.wings = roll(wings, a);
  this.numArms = die(6) * 2;
  this.arms = roll(arms, a);
  this.hands = roll(hands, a);
  this.legs = roll(legs, a);
  this.hitDice = die(8);
  this.hitPoints = 0;
  //get the hit points based on hit die
  for(i = 0; i < this.hitDice; i++){
    this.hitPoints += die(8);
  }
  this.numAttacks = Math.ceil(this.numArms/2);
  //get damage range: min-max
  this.minDamage = 1;
  this.damage = die(8)+2;
  //make sure that it works for dice
  if(this.damage%2 != 0 && this.damage>3){
      this.minDamage++;
  }
  this.armorClass = die(10);
  this.canFly = false;
  if(die(6)<=2){
    this.canFly = true;
  }
  if(!this.canFly){
    this.wings = "vestigial "+this.wings;
  }
  //check for specials from attributes
  this.specials = "";
  if(this.tail=="stingered"){
    this.specials+="Tail attack: 2-7 damage + poison; ";
    this.numAttacks+= " +1 by tail";
  }
  if(this.headAdornment == "horns" || this.headAdornment=="antlers"){
    this.specials+="Gore attack: 1-8 damage; ";
    this.numAttacks+=" +1 by gore";
  }
  if(this.mouth == "fanged" || this.mouth=="mandibled"){
    this.specials+="Bite: "+this.numMouths+"-"+(3+this.numMouths)+" damage; ";
    this.numAttacks+=" +1 by bite; ";
  }
  if(this.mouth=="tusked"){
    this.specials+="Tusk attack: "+this.numMouths+"-"+(5+this.numMouths)+" damage; ";
    this.numAttacks+=" +1 by tusks";
  }
  //add special attacks
  this.specialAttacks = roll(specialAttacks, a, die(3)-1);
  this.specials += this.specialAttacks+"; ";
  //add special defenses
  this.specialDefenses = roll(specialDefenses, a, die(4)-1);
  this.specials += this.specialDefenses+"; ";
  this.move = 10 + die(10);
  if(this.canFly){
    this.move+="; Fly: "+(this.move+die(10)+2);
  }
  this.str = die(6)+14;
  //add to demons array
  demons.push(this);
  //output the results
  this.getResults();
}
//function to get results for demon output
Demon.prototype.getResults = function(){
  //get the number from the array
  var num = demons.indexOf(this)+1;
  //initialize the output
  var output = $("<div class='demon'></div>"); 
  //add the title
  output.append('<h3>Demon '+ num + '</h3>');
  //begin list for stats
  var list = output.append("<ul></ul>");
  //add the stats
  list.append("<li><span>No. Appearing:</span> "+die(8)+"</li>");
  list.append("<li><span>Hit Dice:</span> "+this.hitDice+" ("+this.hitPoints+" hit points)</li>");
  list.append("<li><span>Armor Class:</span> "+ (11+this.armorClass) +" (" + (9 - this.armorClass) + ")</li>");
  list.append("<li><span>No Attacks:</span> "+this.numAttacks+"</li>");
  list.append("<li><span>Damage:</span> "+this.minDamage+"-"+this.damage+"</li>");
  list.append("<li><span>Special:</span> "+this.specials+"</li>");
  list.append("<li><span>Move:</span> "+this.move+"</li>");
  list.append("<li><span>Strength:</span> "+this.str+"</li>");
  //some formatting for language
  var mouth = "mouth";;
  if(this.numMouths>1){
    mouth = "mouths";
  }
  var covering = " a horrible mockery of nature";
  if(this.headAdornment != "none"){
    covering = " covered with "+this.headAdornment+"";
  }
  //set the description paragraph
  var description = "<p>A "+this.visage+" creature whose "+this.head+" head is "+covering+". It has "+this.ears+" ears, "+this.numEyes+" "+this.eyes+" eyes, a "+this.nose+" nose, and "+this.numMouths+" "+this.mouth+" "+mouth+". Its "+this.characteristics+" "+ this.torso+" torso is covered in " +this.bodyOdor+"-smelling "+this.color+" "+this.skin+" skin. Its grotesque "+this.back+" back is met by "+this.wings+" wings and extends down to a horrible "+this.tail+" tail. The beast has "+this.numArms+" "+this.arms+" arms, each of which end in "+this.hands+" hands and it stands upon "+die(4)+" pair(s) of "+this.legs+" legs.</p>"
  //add description to output
  output.append(description);
  //add output to the page
  $("#content").append(output);
}
$(document).ready(function(){
  //jquery calls here
});
/****
function to generate demons
****/
function makeDemon(){
  //get the value from the select box for number to make
  var numDemons = parseInt(document.getElementById('number').value);
  //make all of them
  for(var l=0; l < numDemons; l++){
    new Demon();
  }
}
/****
function to change text on button
*****/
function changeText(){
   var numDemons = parseInt(document.getElementById('number').value);
   if(numDemons>1){
     text = "New Demons";
   }else{
     text = "New Demon";
   }
   document.getElementById('button').innerHTML = text;
}
              
            
!
999px

Console