neverending.
[heroik.git] / scenarios.js
index 035d492..a9188aa 100644 (file)
@@ -23,12 +23,12 @@ var EVENTS = [
     { 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.",
+    { name: "Encounter with Abunakkashi.",
+      effect: "Abunakkashii and his offspring gain a bonus of +2 Strength.",
       requires: ["abunakkashii"],
       unique: true },
     { name: "The start of a legend.",
-      effect: "Abunakkashii and his Offspring gain a bonus of +1 Strength.",
+      effect: "Abunakkashii and his offspring gain a bonus of +1 Strength.",
       requires: ["abunakkashii"],
       unique: true },
     { name: "Technological prowess.",
@@ -39,7 +39,7 @@ var EVENTS = [
       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: "Vague psi.",
+    { name: "Psi wave.",
       action: "Lose all your Mana tokens." },
     { name: "It's an ambush!",
       action: "Place a Tenacity token on each monster that does not have one." },
@@ -56,7 +56,7 @@ var EVENTS = [
       unique: true },
 
     { name: "Destruction.",
-      action: "All equipment and items are destroyed.",
+      action: "All of your weapons and armor are destroyed.",
       unique: true },
     { name: "Epic combat.",
       effect: "The Final Monster gains a bonus of +3 Strength.",
@@ -76,7 +76,7 @@ var EVENTS = [
       action: "Return a random defeated dungeon card to the highest corridor and shuffle it." },
 
     { name: "Malediction.",
-      action: "Discard a quest or a magic item." },
+      action: "Discard a quest or a magic object." },
 
     { name: "False brethren.",
       effect: "All Demons gain Immunity 5 and Immunity 7.",
@@ -85,26 +85,23 @@ var EVENTS = [
 
     { name: "Psi assault.",
       effect: "You cannot use ultimate powers.",
+      lock: ["ultimates"],
       unique: true },
-/*  TODO: Figure out how to implement this well.
     { name: "Entering an anti-magic zone.",
       effect: "You cannot use ultimate powers.",
-      unique: true,
+      lock: ["ultimates"],
       duration: 3,
       later: { name: "Leaving the anti-magic zone.",
-               effect: "You may use ultimate powers again." }
+               effect: "You may use ultimate powers again.",
+               clear: ["ultimates"] }
     },
-*/
+
     // 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: "Overwhelming fear.",
-      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 <strong>Fierce</strong>.",
       requires: ["noncanonical"],
@@ -113,9 +110,6 @@ var EVENTS = [
       effect: "All monsters have <strong>Supremacy</strong>.",
       requires: ["noncanonical"],
       unique: true },
-    { name: "Lost.",
-      action: "Shuffle the remaining corridors together and redistribute the cards as if you were setting up the game.",
-      requires: ["noncanonical"] },
     { name: "Into the darkness.",
       effect: "Choose one corridor. Its cards are now always placed face-down.",
       requires: ["noncanonical"] },
@@ -150,26 +144,26 @@ var EVENTS = [
       unique: true },
     { name: "Infighting.",
       effect: "Greenskins have <strong>Undead&nbsp;+1</strong>, <strong>Demons&nbsp;-1</strong>. Demons have <strong>Greenskins&nbsp;+1</strong>, <strong>Undead&nbsp;-1</strong>. Undead have <strong>Demons&nbsp;+1</strong>, <strong>Greenskins&nbsp;-1</strong>.",
-      requires: ["noncanonical"],
+      requires: ["noncanonical", "demons", "undead"],
       unique: true },
     { name: "New moon.",
-      effect: "Demons have <strong>Veil of Shadow</strong>.",
+      effect: "Demons have <strong>Shrouded</strong>.",
       requires: ["noncanonical", "demons"],
       unique: true },
     { name: "Camouflage.",
-      effect: "Greenskins have <strong>Veil of Shadow</strong>.",
+      effect: "Greenskins have <strong>Shrouded</strong>.",
       requires: ["noncanonical"],
       unique: true },
     { name: "Cryptic shades.",
-      effect: "Undead have <strong>Veil of Shadow</strong>.",
+      effect: "Undead have <strong>Shrouded</strong>.",
       requires: ["noncanonical", "undead"],
       unique: true },
     { name: "Lingering smoke.",
-      effect: "Dragons have <strong>Veil of Shadow</strong>.",
+      effect: "Dragons have <strong>Shrouded</strong>.",
       requires: ["noncanonical", "dragons"],
       unique: true },
     { name: "Hypnotizing gaze.",
-      effect: "Bubbleyes have <strong>Veil of Shadow</strong>.",
+      effect: "Bubbleyes have <strong>Shrouded</strong>.",
       requires: ["noncanonical", "bubbleyes"],
       unique: true },
     { name: "Leeched power.",
@@ -181,11 +175,15 @@ var EVENTS = [
 var NOP = [
     { name: "Nothing happens." },
     { name: "A draft blows down the hallway.",
-      requires: ["noncanonical"] },
+      unique: true, requires: ["noncanonical"] },
     { name: "You sneeze.",
-      requires: ["noncanonical"] },
+      unique: true, requires: ["noncanonical"] },
     { name: "There's a skittering in the distance.",
-      requires: ["noncanonical"] },
+      unique: true,  requires: ["noncanonical"] },
+    { name: "The torch flickers.",
+      unique: true, requires: ["noncanonical"] },
+    { name: "Shadows dance across the walls.",
+      unique: true, requires: ["noncanonical"] },
 ];
 
 var HELPFUL = [
@@ -210,13 +208,34 @@ function generate (flags, events, nop) {
     var chosen = [];
     var i;
 
+    var pending = [];
+    var locks = [];
+    var event;
+
+    function pend (event, i) {
+        while (pending[i]) ++i
+        pending[i] = event;
+    }
+
     function canStillHappen (event) {
         return issubset(event.requires || [], flags)
-            && !(event.unique && contains.call(chosen, event));
+            && !(event.unique && contains.call(chosen, event))
+            && !(event.lock && intersects(event.lock || [], locks));
+    }
+
+    for (i = 0; i < events; ++i) {
+        event = pending.shift()
+            || choice(EVENTS.filter(canStillHappen));
+        chosen.push(event);
+        if (event.later)
+            pend(event.later, (Math.random() * chosen[i].duration) | 0);
+        locks = locks.concat(event.lock || [])
+            .filter(not(contains), event.clear || []);
     }
 
-    for (i = 0; i < events; ++i)
-        chosen.push(choice(EVENTS.filter(canStillHappen)));
+    for (i = 0; i < pending.length; ++i)
+        if (pending[i])
+            chosen.push(pending[i]);
 
     
     for (i = 0; i < nop / 2; ++i) {