Adds support for else-ck attributes for x-present tag, a=chris

Chris Pollett [2023-03-24 17:Mar:th]
Adds support for else-ck attributes for x-present tag, a=chris
Filename
js/game.js
diff --git a/js/game.js b/js/game.js
index e5faacb..ba6238f 100644
--- a/js/game.js
+++ b/js/game.js
@@ -272,18 +272,24 @@ function makeGameObject(dom_object)
                 if (!game_object[attribute_name]) {
                     game_object[attribute_name] = [];
                 }
-                let check = child.getAttribute("ck");
-                if (!check) {
-                    let check = child.getAttribute("check");
-                    if (!check) {
-                        check = "";
+                let check = "";
+                let is_else = false;
+                for(let check_attr of ['ck', 'check', 'else-ck',
+                    'else-check', 'else']) {
+                    let tmp_check = child.getAttribute(check_attr);
+                    if (tmp_check) {
+                        check = tmp_check;
+                        if (['else-ck', 'else-check'].includes(check_attr)) {
+                            is_else = true;
+                        }
+                        break;
                     }
                 }
                 let stage = child.getAttribute("stage");
                 if (!stage) {
                     stage = "";
                 }
-                game_object[attribute_name].push([check, stage,
+                game_object[attribute_name].push([check, stage, is_else,
                 child.innerHTML]);
             } else {
                 if (attribute_name == 'position') {
@@ -530,14 +536,26 @@ function isHere()
 {
     return game['is_here'];
 }
+/**
+ * Returns whether the main character has ever been to the location
+ * given by location_id
+ *
+ * @param {string} location_id id of location checking if main character has
+ *  been to
+ * @return {boolean} whther the main chracter has been there
+ */
+function hasVisited(location_id)
+{
+    return (loc(location_id).visited > 0);
+}
 /**
  * Encapsulates one place that objects can be in a Game.
  */
 class Location
 {
     /**
-     * An array of [check_condition, staging, text_to_present] triples typically
-     * coming from the x-present-tag's in the HTML of a Location.
+     * An array of [check_condition, staging, is_else, text_to_present] tuples
+     * typically coming from the x-present-tag's in the HTML of a Location.
      * @type {Array}
      */
     present = [];
@@ -551,14 +569,15 @@ class Location
      * area. This description is based on the x-present tags that were
      * in the x-location tag from which the Location was parse. For
      * each such x-present tag in the order it was in the original HTML,
-     * the ck condition is first evaluated (this may contain a delay
-     * or clickProceed call or a boolean expression), once/if the condition is
-     * satisfied, then the HTML contents of the tag are shown. In the case,
-     * where the ck evaluates to false that x-present tag's contents are
-     * omitted. In addition to the usual HTML tags, an x-present tag can
-     * have x-speaker subtags. These allow one to present text from a speaker
-     * in bubbles. An x-present tag may also involve input tags to
-     * receive/update values for x-objects or x-locations.
+     * the ck/else-ck condition and staging is first evaluated
+     * once/if the condition is satisfied, staging is processed (this may
+     * contain a delay or a clickProceed call), then the HTML contents of the
+     * tag are shown. In the case where the ck or else-ck evaluates to false
+     * than the x-present tag's contents are omitted. In addition to the
+     * usual HTML tags, an x-present tag can have x-speaker subtags. These
+     * allow one to present text from a speaker in bubbles. An x-present tag
+     * may also involve input tags to receive/update values for x-objects or
+     * x-locations.
      */
     async renderPresentation()
     {
@@ -567,13 +586,20 @@ class Location
         game_content.innerHTML = "";
         game_content.scrollTop = 0;
         game_content.scrollLeft = 0;
+        let check, staging, is_else, section_html;
+        let check_result, proceed, pause;
+        check_result = false;
         for (let section of this.present) {
-            if (!section[2]) {
+            if (!section[3]) {
+                continue;
+            }
+            [check, staging, is_else, section_html] = section;
+            if (is_else && check_result) {
                 continue;
             }
-            let [check_result, proceed, pause] =
-                this.evaluateCheckConditionStaging(section[0], section[1]);
-            let prepared_section = this.prepareSection(section[2]);
+            [check_result, proceed, pause] =
+                this.evaluateCheckConditionStaging(check, staging);
+            let prepared_section = this.prepareSection(section_html);
             if (check_result) {
                 if (proceed) {
                     let old_inner_html = game_content.innerHTML;
@@ -688,11 +714,12 @@ class Location
         }
     }
     /**
-     * Evaluates the condition in a ck attribute of an x-present tag.
+     * Evaluates the condition in a ck or else-ck attribute of an x-present tag.
      *
-     * @param {string} condition contents from a ck or check attribute.
-     *      Conditions can be boolean conditions on game variables.
-     *      If an x-present tag did not have a ck attribute, condition is null.
+     * @param {string} condition contents from a ck, check, else-ck,
+     *      or else-check attribute.  Conditions can be boolean conditions
+     *      on game variables. If an x-present tag did not have a ck attribute,
+     *      condition is null.
      * @param {string} staging contents from a stage attribute.
      *      If no such attribute, this will be an empty string.
      *      Such an attribute could have a sequence of
ViewGit