Pre-release
AdventureJS Docs Downloads
Score: 0 Moves: 0
// sanitizeInput.js

(function () {
  /*global adventurejs A*/

  var p = adventurejs.Parser.prototype;

  /**
   * <ul>
   * <li>toLowerCase(), excluding quoted text</li>
   * <li>strip trailing "."</li>
   * <li>replace tabs with spaces</li>
   * <li>trim()</li>
   * <li>reduce multiple spaces to single</li>
   * <li>replace " and then " with " then "</li>
   * <li>split by periods</li>
   * <li>split by "then"</li>
   * <li>check for "again"</li>
   * </ul>
   * @memberOf adventurejs.Parser
   * @method adventurejs.Parser#sanitizeInput
   * @param {String} parsed_input
   * @param {String} unparsed_input
   * @returns {Array} [string, string]
   */
  p.sanitizeInput = function Parser_sanitizeInput(
    parsed_input,
    unparsed_input
  ) {
    //this.game.log( "log", "high", "sanitizeInput.js > receive: " + parsed_input , 'Parser' );

    // we're going to convert to lower case, but exempt quoted substrings
    // ie 'Yell "WILHELM!"'

    let quoted = false;
    let cased_input = "";

    for (let i = 0; i < parsed_input.length; i++) {
      const char = parsed_input[i];

      if (char === '"') {
        quoted = !quoted; // Toggle the flag when encountering quotes
      }

      if (quoted) {
        cased_input += char; // Keep the characters inside quotes unchanged
      } else {
        cased_input += char.toLowerCase(); // Convert characters outside quotes to lowercase
      }
    }
    parsed_input = cased_input;

    if (parsed_input[parsed_input.length - 1] === ".") {
      // strip trailing period
      parsed_input = parsed_input.slice(0, -1);
    }

    // convert tabs to spaces
    parsed_input = parsed_input.replace(/\t/g, " ");

    parsed_input = parsed_input.trim();

    // replace multiple spaces with single
    parsed_input = parsed_input.replace(/\s+/g, " ");

    // replace " and then " with " then "
    parsed_input = parsed_input.replace(/ and then /g, " then ");

    var periodArray = this.splitByPeriods(parsed_input);
    var thenArray = this.splitByThens(parsed_input);
    var pushArray = [];

    /**
     * We're assuming that phrases
     * ending in periods might include 'then',
     * but that phrases joined by 'then'
     * don't have internal periods.
     *
     * Ex:
     * Go north then take thing then drop thing.
     * vs:
     * Go North. Take thing then drop thing.
     *
     * splitByPeriods recursively tries splitByThens,
     * but splitByThens doesn't try splitByPeriods.
     */
    if (periodArray.length > 1) {
      pushArray = periodArray;
    } else if (thenArray.length > 1) {
      pushArray = thenArray;
    }

    if (0 === pushArray.length) {
      // single clause found, use input as is

      // did player enter "again" ?
      // if so, copy last turn into this turn
      if (this.game.dictionary.testVerbSynonyms(parsed_input, "again")) {
        //   var msg = "$(We) haven't done anything that bears repeating. ";
        //   if(msg) this.game.print( msg, "" );
        //   return null;
        parsed_input = unparsed_input = this.game.parser.input_history[0].input;
      }
    } else if (pushArray.length > 0) {
      // player entered multiple clauses

      // is first item in queue "again"?
      // replace with last turn
      if (this.game.dictionary.testVerbSynonyms(pushArray[0], "again")) {
        pushArray[0] = this.game.parser.input_history[0].input;
      }

      // is any other item in queue "again"?
      // replace with the turn preceding it in the queue
      for (var i = 1; i < pushArray.length; i++) {
        if (this.game.dictionary.testVerbSynonyms(pushArray[i], "again")) {
          pushArray[i] = pushArray[i - 1];
        }
      }

      // use the first one now
      parsed_input = unparsed_input = pushArray.shift();

      // queue up the rest for subsequent turns
      for (var i = 0; i < pushArray.length; i++) {
        this.input_queue.push({
          input: pushArray[i],
          printInput: true,
        });
      }
    }

    this.game.log(
      "L1092",
      "log",
      "high",
      `sanitizeInput.js > return parsed: ${parsed_input}, unparsed: ${unparsed_input}`,
      "Parser"
    );
    return [parsed_input, unparsed_input];
  };
})();