Comparing multiple variables to find the greatest variable

Hello there,

I’m creating a fan made Digimon visual novel, where your choices impact the type of Digimon you receive. I’m in the early testing stage where I’m seeing what’s possible. What I’m trying to figure out is how to compare multiple variables to see which is greatest and then return a different result. ChatGPT was no help and clearly doesn’t actually know how code works in Narrat. Here is the code it helped me to create:

if $virusPoints > $vaccinePoints && $virusPoints > $dataPoints && $virusPoints > $freePoints
set data.partnerType = “Virus”
“Your rebellious streak resonates strongest. A Virus-type Digimon will become your partner.”
if $vaccinePoints > $virusPoints && $vaccinePoints > $dataPoints && $vaccinePoints > $freePoints
set data.partnerType = “Vaccine”
“Your moral compass is clear. A Vaccine-type Digimon will become your partner.”
if $dataPoints > $virusPoints && $dataPoints > $vaccinePoints && $dataPoints > $freePoints
set data.partnerType = “Data”
“Your intellect leads the way. A Data-type Digimon will become your partner.”
if $freePoints > $virusPoints && $freePoints > $vaccinePoints && $freePoints > $dataPoints
set data.partnerType = “Free”
“You go with the flow. A Free-type Digimon will become your partner.”
else
“Your values are too balanced to choose one path just yet…”

Which technically works (it returns the right text when I run it) but I get multiple errors when I load the game (command if: expected 1 to 1 arguments but got 11, and command if: expected 2 to 2 arguments but got 3)

I’m confused what I’ve done wrong and why it’s still returning the right text.

Thanks,
Josh

1 Like

An if statement expects only one big boolean proposition, which can be a variable or an expression; so if A > B gives an error but if (A > B) will be evaluated to see if the code indented underneath should be executed.

Taking your first line, just nest each proposition like this:

if ((> $virusPoints $vaccinePoints) && ((> $virusPoints $dataPoints) && (> $virusPoints $freePoints)))
set data.partnerType = “Virus”
“Your rebellious streak resonates strongest. A Virus-type Digimon will become your partner.”

Don’t forget that the syntax for operators is to put them at the start of the proposition and you’re good :+1:

1 Like

This could be a good candidate for a small plugin. You want a function that takes n inputs and finds out which one is greater, probably returning the index of that greater one.

You can have a plugin adding a custom command for finding the maximum, here’s two different ways you could do it, one where it looks in an array, one where you pass the numbers directly. Up to you which one you prefer:

/**
 * Takes an array of numbers as input, returns the index of the largest one
 * usage:
 * var myArray (new Array)
 * push $myArray 10
 * push $myArray 5
 * push $myArray 20
 * push $myArray 15
 * 
 * var index (find_greatest_in_array $myArray)
 * // index should be 2
 */
export const findGreatestInArrayIndex = CommandPlugin.FromOptions<{ array: any[] }>({
  keyword: 'find_greatest_in_array_index',
  argTypes: [{ name: 'array', type: 'any' }],
  runner: async (cmd) => {
    const { array } = cmd.options;
    if (!Array.isArray(array)) {
      console.error(cmd, 'expected an array');
      return 0;
    }
    let largestIndex = 0;
    for (let i = 0; i < array.length; i++) {
      if (typeof array[i] !== 'number') {
        console.error(cmd, `Array element ${i} is not a number: ${array[i]}.`);
        continue;
      }
      if (array[i] > array[largestIndex]) {
        largestIndex = i;
      }
    }
    return largestIndex;
  }
});

/**
 * Takes any amount of numbers as arguments, returns the index of the greatest one.
 * Usage:
 * var myVariable1 10
 * var myVariable2 5
 * var index (find_greatest_in_array $myVariable1 $myVariable2 20 15)
 * // index should be 2
 */
export const findGreatestInArgsIndex = CommandPlugin.FromOptions<{ }>({
  keyword: 'find_greatest_in_args_index',
  argTypes: [{ name: 'rest', type: 'rest' }],
  runner: async (cmd) => {
    const array = cmd.args as any[];
    if (!Array.isArray(array)) {
      console.error(cmd, 'expected an array');
      return 0;
    }
    let largestIndex = 0;
    for (let i = 0; i < array.length; i++) {
      if (typeof array[i] !== 'number') {
        console.error(cmd, `Array element ${i} is not a number: ${array[i]}.`);
        continue;
      }
      if (array[i] > array[largestIndex]) {
        largestIndex = i;
      }
    }
    return largestIndex;
  }
});

put that in your index.ts, and then before startApp at the bottom of the file, register the plugin:

window.addEventListener("load", () => {
  registerPlugin(new findGreatestInArrayIndex());
  registerPlugin(new findGreatestInArgsIndex());
  startApp({
    debug,
    logging: false,
    scripts,
    config,
  });
});

Then using it in narrat:

var greatestIndex (find_greatest_in_args_index $vaccinePoints $virusPoints $freePoints)
if (== $greatestIndex 0):
  // vaccinePoints is higher
elseif (== $greatestIndex 1):
  // virusPoints is higher
elseif (== $greatestIndex 2):
  // freePoints is higher

You can also have a different version of this function which instead of returning the index returns the value, in which case then you’d do conditions like if (== $greatestValue $vaccinePoints):

Also I love Digimon so I hope it goes well :grinning_face_with_smiling_eyes: