Check words position in a string

Status
Not open for further replies.

Mark91

Veteran
Veteran
Joined
May 19, 2017
Messages
112
Reaction score
10
First Language
Italian
Primarily Uses
RMMV
Hi,
I'm using in a conditional branch this script;

let text = $gameVariables.value(x).toLowerCase(); text.indexOf("word 1") < text.indexOf("word 2")

to check if "word 1" comes before "word 2" in a string stored in var(x) (using a free input text plugin).
This scripts works fine BUT how can I add other variants without using more Conditional Branches?
I.e. if "word 1" comes before "word 2" OR "word 3"?
I found out that in javascript || means "or" and I tried something like;

let text = $gameVariables.value(x).toLowerCase(); text.indexOf("word 1") < text.indexOf("word 2") || let text = $gameVariables.value(x).toLowerCase(); text.indexOf("word 1") < text.indexOf("word 3")

let text = $gameVariables.value(x).toLowerCase(); text.indexOf("word 1") < text.indexOf("word 2") || text.indexOf("word 1") < text.indexOf("word 3")

But none of the two works...
 

Miubot555

Warper
Member
Joined
Mar 16, 2020
Messages
4
Reaction score
3
First Language
English
Primarily Uses
RMMV
Would it be possible to store "word 1" "word 2" and "word 3" in an array? Then you could compare each words position in the array with Javascript.

EDIT
I'm very new to MV and scripting, so I'm not sure if this would work, but would it be something like the script below?

$gameVariables.setValue(1, []);
$gameVariables.value(1).push("word 1");
$gameVariables.value(1).push("word 2");
$gameVariables.value(1).push("word 3");

if ($gameVariables.value(1).indexOf("word 1") < $gameVariables.value(1).indexOf("word 2")) {
//do something
} else {
//do something else
}
 
Last edited by a moderator:

Mark91

Veteran
Veteran
Joined
May 19, 2017
Messages
112
Reaction score
10
First Language
Italian
Primarily Uses
RMMV
Would it be possible to store "word 1" "word 2" and "word 3" in an array? Then you could compare each words position in the array with Javascript.

EDIT
I'm very new to MV and scripting, so I'm not sure if this would work, but would it be something like the script below?

$gameVariables.setValue(1, []);
$gameVariables.value(1).push("word 1");
$gameVariables.value(1).push("word 2");
$gameVariables.value(1).push("word 3");

if ($gameVariables.value(1).indexOf("word 1") < $gameVariables.value(1).indexOf("word 2")) {
//do something
} else {
//do something else
}
I'm sorry I don't understand well what you mean. Since I don't really know javascript, maybe I missed something.
Your solution need a script call before the conditional branch? In your example it also seems that the script verifies only if "word 1" is before "word 2".
I mean; I can already do the

if "word 1" < "word 2" do stuff
Else do other stuff

the problem comes when I also have to check if there is "word 3" instead of "word 2".

If "Word 1" < "Word 2" or "word 3" or "word 4" do stuff.
Else do other stuff

I wanna do it in a single Conditional Branch script box (if possible)
 

NeptuneTron

The Salticid Scholar of the North
Veteran
Joined
Jan 13, 2018
Messages
40
Reaction score
25
First Language
English
Primarily Uses
RMMV
This issue with your code is probably related to order of operations. Excellent article here on how the operations work in Ruby (the language used by RPGMaker's scripting) https://www.tutorialspoint.com/ruby/ruby_operators.htm.

That said, there's a possible fix here.

Ruby:
text = $gameVariables.value(x).toLowerCase();
if ((text.indexOf("word 1") < text.indexOf("word 2")) || (text.indexOf("word 1") < text.indexOf("word 3")))
... <code goes here>
else
... <code goes here>
Firstly, attaching the condition by itself isn't necessarily helpful. Without an if statement (or storage in a variable or something), you're just checking if the condition evaluates to true, and as soon as that condition is evaluated, you immediately throw it away when you run the next line of code, whatever it may be. I assume you've already done this in the code you're actually using, and simply didn't include it here for the sake of brevity, but just in case, I thought it might be important to mention that.

Secondly, since every language is very particular about order of operations, it's important to make sure that the order of operations when evaluating your condition are correct. Here, much as in mathematics, brackets are your friend. Adding more brackets ensures that the computer is definitely 100% going to evaluate that condition or expression in the way you want it to.

Let's show how this might happen by looking at a simplified version of your code.
A < B || A < C

You want the computer to read the phrase as:
"If A is less than B, or if A is less than C, the condition is true."

But it's possible the computer might be reading the phrase as:
"If A is less than B or A, and B or A is less than C, the condition is true."
That shouldn't be the case with Ruby, but it's a possibility.

Adding brackets removes any kind of ambiguity in how the phrase is supposed to be read.
( A < B ) || ( A < C ) can only be read in one way:
"If (A is less than B is true) or if (A is less than C is true) then the condition is true."
 
Last edited:

Miubot555

Warper
Member
Joined
Mar 16, 2020
Messages
4
Reaction score
3
First Language
English
Primarily Uses
RMMV
the problem comes when I also have to check if there is "word 3" instead of "word 2".

If "Word 1" < "Word 2" or "word 3" or "word 4" do stuff.
Else do other stuff
Oops, sorry about that!

This answer might be way overboard and not useful (or wrong), but just as an experiment...

I think if the total number of words can change or you had a lot of them, I would add this to a script event before the conditional branch:

JavaScript:
$gameVariables.setValue(1, []); //assign one of your RPG variables to be an array
//you can set 1 to be any variable you aren't currently using for something else

//add your words to the array with .push
$gameVariables.value(1).push("word 1");
$gameVariables.value(1).push("word 2");
$gameVariables.value(1).push("word 3");
$gameVariables.value(1).push("word 4");

//this would make $gameVariables.value(1) = ["word 1","word 2","word 3","word 4"];

//then I would make a loop that checks if each item in the array is < "word 1"

var i; //define a temp variable for the loop

for (i = 0; i < $gameVariables.value(1).length; i++) {
  if ($gameVariables.value(1).indexOf("word 1") < $gameVariables.value(1).indexOf($gameVariables.value(1)[i])) {
    //do something
         $gameSwitches.setValue(2, true);
  } else if ($gameSwitches.Value(2) != true) {
   //do something else
    $gameSwitches.Value(2, false);
  }
}
In the example above, I used variable 001 as the array, and switch 002 as an output. Then we can use a conditional branch that tests if switch 002 is true of false.

I would only go with an array if you didn't know how many words you had, since the loop can handle infinite words.

I got the idea from this thread:

https://forums.rpgmakerweb.com/inde...to-add-values-to-a-gamevariables-array.86921/

And also:

https://www.w3schools.com/jsref/jsref_obj_array.asp

EDIT:

You could also use the .split(" ") command to split all the words into items in the array instead of adding them individually with .push().
 
Last edited:

ozubon

surströmming?
Veteran
Joined
Oct 16, 2018
Messages
178
Reaction score
168
First Language
English
Primarily Uses
RMMV
Unsure if you A. want to check if word 1, specifically, comes before any of the other words
or B. if you want to check if every word you list comes before the other, in the order you list them.

For a conditional branch I'd solve A like this:
JavaScript:
(function(){let text=arguments[0];let rtn;for(i=2;i<arguments.length;i++){rtn=(text.search(RegExp("\\b"+arguments[i]+"\\b"))>text.search(RegExp("\\b"+arguments[1]+"\\b")))?true:false;if(!rtn){break}}return rtn})( $gameVariables.value(x), "word 1", "word 2", "etc" )
It's the very last part you edit, starting with $gameVariables.value(x), you can put in however many words you want to check.


and B like this:
JavaScript:
(function(){let text=arguments[0];let rtn;for(i=2;i<arguments.length;i++){rtn=(text.search(RegExp("\\b"+arguments[i]+"\\b"))>text.search(RegExp("\\b"+arguments[i-1]+"\\b")))?true:false;if(!rtn){break}}return rtn})( $gameVariables.value(x), "word 1", "word 2", "etc" )
Both work essentially the same, the function searches every word you input and compares it with the previous word (or with word 1 for alternative A) to see if it comes after, if it doesn't it immediately returns false.


I've given you these looong conditional branch functions before but maybe it's time you make a .js file with functions and load it in the plugin manager so you can access and remember the functions a bit easier?

If you did, here's the two functions above that you'd paste into the .js file:
JavaScript:
function word1Before(){
    let text = arguments[0];
    let rtn;
    for (i = 2; i < arguments.length; i++) {
        rtn = (text.search(RegExp("\\b"+arguments[i]+"\\b")) > text.search(RegExp("\\b"+arguments[1]+"\\b"))) ? true : false;
        if (!rtn) {break}
    }
    return rtn
}

function allWordsBefore(){
    let text = arguments[0];
    let rtn;
    for (i = 2; i < arguments.length; i++) {
        rtn = (text.search(RegExp("\\b"+arguments[i]+"\\b")) > text.search(RegExp("\\b"+arguments[i-1]+"\\b"))) ? true : false;
        if (!rtn) {break}
    }
    return rtn
}
Then for to use in a conditional branch you would just do it like this:
JavaScript:
word1Before($gameVariables.value(x), "word1", "word2", "etc")
or for B
JavaScript:
allWordsBefore($gameVariables.value(x), "word1", "word2", "etc")

If anyone who's using older versions of MV want to use this you can replace every let with var

EDIT: Maybe my answer solves your problem but isn't so pedagogical if you want to learn how it works, so here's allWordsBefore explained:

JavaScript:
function allWordsBefore(){
    let text = arguments[0]; // 0 is the first input so it's the text you want to check, like a string stored in a game variable.
    let rtn; // just declares a return variable
    // i = 2 will correlate to the third input, but hang on and you'll understand why we start there!
    // the for loop loops until all argument inputs are checked
    for (i = 2; i < arguments.length; i++) {
        // in the first run, the third input (i) is checked if it comes after the second input (i-1 / the third input - 1):
        rtn = (text.search(RegExp("\\b"+arguments[i]+"\\b")) > text.search(RegExp("\\b"+arguments[i-1]+"\\b"))) ? true : false;
        // this goes on, the third input becomes the fourth, checks with fourth - 1, and so on, UNLESS:
        if (!rtn) {break} // if there's a discrepancy, abort!!
    }
    return rtn // returns true or false depending on the result
}
Hopefully that was helpful and not more confusing :kaoslp:
 
Last edited:

Mark91

Veteran
Veteran
Joined
May 19, 2017
Messages
112
Reaction score
10
First Language
Italian
Primarily Uses
RMMV
Unsure if you A. want to check if word 1, specifically, comes before any of the other words
or B. if you want to check if every word you list comes before the other, in the order you list them.

For a conditional branch I'd solve A like this:
JavaScript:
(function(){let text=arguments[0];let rtn;for(i=2;i<arguments.length;i++){rtn=(text.search(RegExp("\\b"+arguments[i]+"\\b"))>text.search(RegExp("\\b"+arguments[1]+"\\b")))?true:false;if(!rtn){break}}return rtn})( $gameVariables.value(x), "word 1", "word 2", "etc" )
It's the very last part you edit, starting with $gameVariables.value(x), you can put in however many words you want to check.


and B like this:
JavaScript:
(function(){let text=arguments[0];let rtn;for(i=2;i<arguments.length;i++){rtn=(text.search(RegExp("\\b"+arguments[i]+"\\b"))>text.search(RegExp("\\b"+arguments[i-1]+"\\b")))?true:false;if(!rtn){break}}return rtn})( $gameVariables.value(x), "word 1", "word 2", "etc" )
Both work essentially the same, the function searches every word you input and compares it with the previous word (or with word 1 for alternative A) to see if it comes after, if it doesn't it immediately returns false.


I've given you these looong conditional branch functions before but maybe it's time you make a .js file with functions and load it in the plugin manager so you can access and remember the functions a bit easier?

If you did, here's the two functions above that you'd paste into the .js file:
JavaScript:
function word1Before(){
    let text = arguments[0];
    let rtn;
    for (i = 2; i < arguments.length; i++) {
        rtn = (text.search(RegExp("\\b"+arguments[i]+"\\b")) > text.search(RegExp("\\b"+arguments[1]+"\\b"))) ? true : false;
        if (!rtn) {break}
    }
    return rtn
}

function allWordsBefore(){
    let text = arguments[0];
    let rtn;
    for (i = 2; i < arguments.length; i++) {
        rtn = (text.search(RegExp("\\b"+arguments[i]+"\\b")) > text.search(RegExp("\\b"+arguments[i-1]+"\\b"))) ? true : false;
        if (!rtn) {break}
    }
    return rtn
}
Then for to use in a conditional branch you would just do it like this:
JavaScript:
word1Before($gameVariables.value(x), "word1", "word2", "etc")
or for B
JavaScript:
allWordsBefore($gameVariables.value(x), "word1", "word2", "etc")

If anyone who's using older versions of MV want to use this you can replace every let with var

EDIT: Maybe my answer solves your problem but isn't so pedagogical if you want to learn how it works, so here's allWordsBefore explained:

JavaScript:
function allWordsBefore(){
    let text = arguments[0]; // 0 is the first input so it's the text you want to check, like a string stored in a game variable.
    let rtn; // just declares a return variable
    // i = 2 will correlate to the third input, but hang on and you'll understand why we start there!
    // the for loop loops until all argument inputs are checked
    for (i = 2; i < arguments.length; i++) {
        // in the first run, the third input (i) is checked if it comes after the second input (i-1 / the third input - 1):
        rtn = (text.search(RegExp("\\b"+arguments[i]+"\\b")) > text.search(RegExp("\\b"+arguments[i-1]+"\\b"))) ? true : false;
        // this goes on, the third input becomes the fourth, checks with fourth - 1, and so on, UNLESS:
        if (!rtn) {break} // if there's a discrepancy, abort!!
    }
    return rtn // returns true or false depending on the result
}
Hopefully that was helpful and not more confusing :kaoslp:
Sorry if i didn't explain well, it was A what I needed!

According to the scheme:
If "Word 1" < "Word 2" or "word 3" or "word 4" do stuff.
Else do other stuff

Well "word1", "word2" and "word3" aren't surely enough to thank you again!
I mean you didn't just solved this specifical problem but you also gave me a second variant (That surely could come in handy in future) and basically a plugin! o_O
 

slimmmeiske2

Little Red Riding Hood
Global Mod
Joined
Sep 6, 2012
Messages
7,867
Reaction score
5,240
First Language
Dutch
Primarily Uses
RMXP

This thread is being closed, due to being solved. If for some reason you would like this thread re-opened, please report this post and leave a message why. Thank you.

 
Status
Not open for further replies.

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Profile Posts

Don't forget, aspiring writers: Personality isn't what your characters do, it is WHY they do it.
Hello! I would like to know if there are any pluggings or any way to customize how battles look?
I was thinking that when you start the battle for it to appear the eyes of your characters and opponents sorta like Ace Attorney.
Sadly I don't know how that would be possible so I would be needing help! If you can help me in any way I would really apreciate it!
The biggest debate we need to complete on which is better, Waffles or Pancakes?
rux
How is it going? :D

Forum statistics

Threads
106,051
Messages
1,018,551
Members
137,837
Latest member
Dabi
Top