/* The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See https://creativecommons.org/publicdomain/zero/1.0/ for details. */ "use strict"; var EVENTS = [ { name: "The Greenskins are mobilized.", effect: "Greenskins gain a bonus of +1 Strength." }, { name: "Big eye is watching you.", effect: "Bubbleyes gain a bonus of +1 Strength.", requires: ["bubbleyes"] }, { name: "General invocation.", effect: "Demons gain a bonus of +1 Strength.", requires: ["demons"] }, { name: "Stronger than ever.", effect: "Undead gain a bonus of +1 Strength.", requires: ["undead"] }, { name: "Meeting with Abunakkashi.", effect: "Abunakkashii and his Offspring gain a bonus of +2 Strength.", requires: ["abunakkashii"], unique: true }, { name: "Technological prowess.", effect: "Traps gain a bonus of +1 Strength.", requires: ["traps"] }, { name: "Mental combat.", effect: "Psi monsters gain a bonus of +1 Strength.", }, { name: "A cry in the night.", action: "An adventurer of your choice loses 1 Mana." }, { name: "It's an ambush!", action: "Place a Tenacity token on each monster that does not have one." }, { name: "The alarm is sounded.", action: "Place a Tenacity token on the weakest monster or monsters that do not already have one." }, { name: "Flank attack.", effect: "Cards on either side corridor gain a bonus of +1 Strength.", unique: true }, { name: "Battle formation.", effect: "Cards in the central corridor(s) gain a bonus of +1 Strength.", unique: true }, { name: "Last bastion.", effect: "All cards gain a bonus of +1 Strength.", unique: true }, { name: "Destruction.", action: "All equipment and items are destroyed.", unique: true }, { name: "Epic combat.", effect: "The Final Monster gains a bonus of +3 Strength.", unique: true }, { name: "Red herring.", action: "Shuffle the remaining corridors together and redistribute the cards as if you were setting up the game." }, // Events from Sean Allen's random scenario generator. // http://boardgamegeek.com/filepage/57107/random-scenario-generator { name: "Fire from above.", effect: "Dragons gain a bonus of +1 Strength.", requires: ["dragons", "noncanonical"], unique: true }, { name: "Bad dreams.", action: "Lose 1 extra Courage token. (The dungeon does not gain another Fear token.)", requires: ["noncanonical"], unique: true }, { name: "Backs against the wall.", effect: "Any monster with a Tenacity token is also Fierce.", requires: ["noncanonical"], unique: true }, { name: "Surrounded.", effect: "All monsters have Supremacy.", requires: ["noncanonical"], unique: true }, { name: "The torch has gone out.", action: "The next dungeon card is placed face-down.", }, // Events from Stephane Renard's scenario. // http://docfox.free.fr/spip.php?article129 { name: "Malediction.", action: "Discard all quests.", requires: ["noncanonical"], unique: true }, { name: "Reanimation.", action: "Return a random spent dungeon card to the smallest corridor and shuffle it. (If you haven't spent any cards, nothing happens.)", requires: ["noncanonical"] }, { name: "Zone of silence.", effect: "Temporary and Ultimate Powers cannot be used until you reveal a new card.", requires: ["noncanonical"] }, // Events of my own devising. { name: "Unwanted attention.", effect: "Unique monsters gain a bonus of +1 Strength.", requires: ["noncanonical"], unique: true }, { name: "Spiked the punch.", effect: "Greenskins have 1d8 Strength.", requires: ["noncanonical"], unique: true }, { name: "Lost in the fog.", effect: "After defeating a card, roll a die. On an odd number its replacement is placed face-down.", requires: ["noncanonical"], unique: true }, { name: "Closer than you think.", action: "The dungeon gains another Fear token, and a new event occurs.", requires: ["noncanonical"], another: true, unique: true }, { name: "I thought you had it.", action: "Randomly discard four of your defeated dungeon cards.", requires: ["noncanonical"] }, { name: "Adamantine armor.", effect: "All monsters gain Immunity 1.", requires: ["noncanonical"], unique: true }, { name: "Normative assumptions.", effect: "Effects concerning ♂ instead concern ♀, and vice versa.", requires: ["noncanonical"], unique: true }, { name: "Infighting.", effect: "Greenskins have Undead +1, Demons -1. Demons have Greenskins +1, Undead -1. Undead have Demons +1, Greenskins -1.", requires: ["noncanonical"], unique: true }, { name: "New moon.", effect: "Demons have Veil of Shadow.", requires: ["noncanonical", "demons"], unique: true }, { name: "Camouflage.", effect: "Greenskins have Veil of Shadow.", requires: ["noncanonical"], unique: true }, { name: "Cryptic shades.", effect: "Undead have Veil of Shadow.", requires: ["noncanonical", "undead"], unique: true }, { name: "Lingering smoke.", effect: "Dragons have Veil of Shadow.", requires: ["noncanonical", "dragons"], unique: true }, { name: "Hypnotizing gaze.", effect: "Bubbleyes have Veil of Shadow.", requires: ["noncanonical", "bubbleyes"], unique: true }, ]; var NOTHING = { name: "Nothing happens." }; var LOSE = { name: "Your adventuring party is defeated!" }; function randrange (a, b) { return a + (Math.random() * (b - a)) | 0; } function generate (flags, events, nop) { var chosen = []; var i; function canStillHappen (event) { return issubset(event.requires || [], flags) && !(event.unique && contains.call(chosen, event)); } for (i = 0; i < events; ++i) chosen.push(choice(EVENTS.filter(canStillHappen))); for (i = 0; i < nop; ++i) chosen.splice(randrange(0, chosen.length), 0, NOTHING); chosen.push(LOSE); return chosen; } function toHTML (event) { return ["" + event.name + "", event.action ? "" + event.action + "" : "", event.effect ? "" + event.effect + "" : "", ].join(" "); } var THEME = ("h1 { color: hsl(XXX, 25%, 75%); }\n\ h2, .button, select { border-color: hsl(XXX, 30%, 85%); }\n\ \n\ a:link, a:visited, a:active {\n\ color: hsl(XXX, 25%, 50%);\n\ }\n\ \n\ select, .button, tbody tr:nth-last-child(odd) {\n\ background-color: hsl(XXX, 30%, 85%);\n\ }\n\ \n\ h1,\n\ select:hover, select:focus,\n\ .button:hover, .button:focus {\n\ border-color: hsl(XXX, 25%, 50%);\n\ }"); function randomizeName () { var name = generateName(); document.getElementById("name").textContent = name; document.title = document.title.replace(/[^-]*-/, name + " -"); document.head.lastChild.textContent = THEME.replace( /XXX/g, (Math.random() * 256) | 0); } var events = []; var style; function generateScenario () { var parts = location.hash.slice(1).split(','); events = generate(parts, parts.shift() | 0, parts.shift() | 0); style = document.createElement("style"); document.head.appendChild(style); randomizeName(); } function getEvents (matcher) { return EVENTS.filter(matcher); } function wrapRow (row) { return "