RMMV If an array object does not exist in an if statement, don't report error, just continue

Status
Not open for further replies.

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
4,977
Reaction score
4,591
First Language
English
Primarily Uses
RMMZ
What about this then? :p

JavaScript:
$gameParty.members().some(member => member.hasWeapon($dataWeapons[21]))

Edit:
Oops, apologies for double posting :(
I would have suggested that but I figured you had a reason for checking 8 specific actors and not just the party members. :p
 

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
278
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
I would have suggested that but I figured you had a reason for checking 8 specific actors and not just the party members. :p
Haha, yeah, I don't know why I didn't think of just doing this from the start. Well, I wouldn't have used some, so again thanks for that :p Considering just checking the battle members tbh, but I'll decide upon that later :)
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
4,977
Reaction score
4,591
First Language
English
Primarily Uses
RMMZ
Haha, yeah, I don't know why I didn't think of just doing this from the start. Well, I wouldn't have used some, so again thanks for that :p Considering just checking the battle members tbh, but I'll decide upon that later :)
The members() function returns battle members anyway if the party is in battle.

Game_Party.prototype.members = function() {
return this.inBattle() ? this.battleMembers() : this.allMembers();
};
 

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
278
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
The members() function returns battle members anyway if the party is in battle.

Game_Party.prototype.members = function() {
return this.inBattle() ? this.battleMembers() : this.allMembers();
};
Ah nice, but this is currently out of battle. Still, good to know.
 

KurayamiBlackheart

Phoenix of darkness.
Veteran
Joined
Sep 4, 2019
Messages
173
Reaction score
138
First Language
French
Primarily Uses
RMMV
What about this then? :p

JavaScript:
$gameParty.members().some(member => member.hasWeapon($dataWeapons[21]))

Edit:
Oops, apologies for double posting :(
pretty sure $gameParty.members() will check every actor inside the player's team (if not in battle). so if you do a game that allows the player to create his own teammates (like some Dragon Quest), or catch/tame enemies (like pokemon or dragon quest monster joker or shin megami tensei), it might not be the way to go. unless you want to check every party member (even the inactive one) inside the current party.
 

Arthran

Veteran
Veteran
Joined
Jun 25, 2021
Messages
318
Reaction score
264
First Language
English
Primarily Uses
RMMZ
This isn't an answer to your question (which you've already gotten answers to anyway), but I'm kinda confused about why you were trying to check for the existence of the name property of the filter result in the first place.

What I mean is, why did you have this:
JavaScript:
for (var i = 1; i < 8; i++) if ($gameActors.actor(i).weapons().filter(weapon => weapon.name == $dataWeapons[21].name)[0].name) {true} else {false}

Instead of this?:
JavaScript:
for (var i = 1; i < 8; i++) if ($gameActors.actor(i).weapons().filter(weapon => weapon.name == $dataWeapons[21].name)[0]) {true} else {false}

Unless I'm misunderstanding what your intentions were, it doesn't seem like there was really any purpose in checking for the existence of the name property of the result. Since you already compared the name property inside the filter, it stands to reason that the filtered result would also have a name property. Wouldn't it have sufficiently fulfilled your purpose just to verify that element 0 existed at all? Then you would have avoided the potential error in the first place.
 

KurayamiBlackheart

Phoenix of darkness.
Veteran
Joined
Sep 4, 2019
Messages
173
Reaction score
138
First Language
French
Primarily Uses
RMMV
This isn't an answer to your question (which you've already gotten answers to anyway), but I'm kinda confused about why you were trying to check for the existence of the name property of the filter result in the first place.

What I mean is, why did you have this:
JavaScript:
for (var i = 1; i < 8; i++) if ($gameActors.actor(i).weapons().filter(weapon => weapon.name == $dataWeapons[21].name)[0].name) {true} else {false}

Instead of this?:
JavaScript:
for (var i = 1; i < 8; i++) if ($gameActors.actor(i).weapons().filter(weapon => weapon.name == $dataWeapons[21].name)[0]) {true} else {false}

Unless I'm misunderstanding what your intentions were, it doesn't seem like there was really any purpose in checking for the existence of the name property of the result. Since you already compared the name property inside the filter, it stands to reason that the filtered result would also have a name property. Wouldn't it have sufficiently fulfilled your purpose just to verify that element 0 existed at all? Then you would have avoided the potential error in the first place.
He was checking for independent items. That's why he needed a variable to check. He uses the independent item plugin, which make them, all 'differents'
 

Arthran

Veteran
Veteran
Joined
Jun 25, 2021
Messages
318
Reaction score
264
First Language
English
Primarily Uses
RMMZ
He was checking for independent items. That's why he needed a variable to check. He uses the independent item plugin, which make them, all 'differents'
I get that, but I'm saying that the filter would have already determined that the item's names were the same, which in turn would mean that the item does in fact have a name. So unless I'm misunderstanding something, checking the name property a second time after that doesn't seem to serve any purpose. As long as the filter did return a result, it would mean that the test had succeeded.

What I mean is that, based on his particular filter function, any time filterResult[0].name is truthy, filterResult[0] would also be truthy. So he could have just dropped that final .name part, and his code would have worked fine. He was getting an error when the filter didn't return any results, and he tried to access the name property of a nonexistent object, but I don't see the need to have been checking the name property of the resulting object anyway. If that object exists at all, we already know that it has a name and that it matched the name that we were checking for.

Dunno if I'm explaining my thoughts well, but yeah.

He said that this worked for him:
JavaScript:
for (var i = 1; i < 8; i++) if ($gameActors.actor(i).weapons()?.filter(weapon => weapon.name == $dataWeapons[21].name)[0]) {console.log(true)} else {console.log(false)}

But it's not because of the ?., it's because he dropped that final .name property out of his if statement. The ?. is doing absolutely nothing here, because you can already call filter on an empty array without an error being thrown.
 
Last edited:

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
278
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
I get that, but I'm saying that the filter would have already determined that the item's names were the same, which in turn would mean that the item does in fact have a name. So unless I'm misunderstanding something, checking the name property a second time after that doesn't seem to serve any purpose. As long as the filter did return a result, it would mean that the test had succeeded.

What I mean is that, based on his particular filter function, any time filterResult[0].name is truthy, filterResult[0] would also be truthy. So he could have just dropped that final .name part, and his code would have worked fine. He was getting an error when the filter didn't return any results, and he tried to access the name property of a nonexistent object, but I don't see the need to have been checking the name property of the resulting object anyway. If that object exists at all, we already know that it has a name and that it matched the name that we were checking for.

Dunno if I'm explaining my thoughts well, but yeah.

He said that this worked for him:
JavaScript:
for (var i = 1; i < 8; i++) if ($gameActors.actor(i).weapons()?.filter(weapon => weapon.name == $dataWeapons[21].name)[0]) {console.log(true)} else {console.log(false)}

But it's not because of the ?., it's because he dropped that final .name property out of his if statement. The ?. is doing absolutely nothing here, because you can already call filter on an empty array without an error being thrown.
You're right, I missed that the result was truthy enough to validate the query. And yeah, it seems as if the solution was to drop the "name" at the end rather than adding the ?. Good catch mate :) It also seems like adding the .name property back in to it causes the same issue regardless of the "?", I haven't tested it enough as I am already doing it in a different way.
 

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
278
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
pretty sure $gameParty.members() will check every actor inside the player's team (if not in battle). so if you do a game that allows the player to create his own teammates (like some Dragon Quest), or catch/tame enemies (like pokemon or dragon quest monster joker or shin megami tensei), it might not be the way to go. unless you want to check every party member (even the inactive one) inside the current party.
As I wrote, I'll decide upon that later, I can just call $gameParty.battleMembers instead of members. But at the moment, I want it to check the entire party and not just the battlers. At the moment I have 7 total party members at the 15 hour mark.

Edit:
I clicked "edit" on my previous post and then I click on "reply" in Shaden's post, still became a separate response, I must've missed to place the "|" in the correct place :(
 

Arthran

Veteran
Veteran
Joined
Jun 25, 2021
Messages
318
Reaction score
264
First Language
English
Primarily Uses
RMMZ
I think .some is faster than a for loop, yes.
It depends on the size of the array, how deeply buried the first match is, and the complexity of the test that you're performing on each element. But using Chrome, with a small array like the OP is using (only 7 elements), .some is actually much slower than a for loop.

For example, take this code:
JavaScript:
(() => {
    const arr = [21, 53, 10, 19, 4, 7, 32];
    var result = false;

    console.time("For");
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] == 7) {
            result = true;
            break;
        }
    }
    console.timeEnd("For");
    console.log(result);
})();

vs this code:
JavaScript:
(() => {
    const arr = [21, 53, 10, 19, 4, 7, 32];

    console.time("Some");
    var result = arr.some(element => element == 7);
    console.timeEnd("Some");
    console.log(result);
})();

The first snippet uses a for loop to search a 7-element array for a value that is located 6 elements deep, and the second is a .some implementation that does the same thing. After testing each snippet 5 times on Chrome, and averaging the results, the .some snippet turned out to be 3.6x slower on my system.

However, when I performed the same test on a very large array ([...Array(50000).keys()]), things were a little different. The for loop was the still the winner up until the point where the first match was buried about 2000 elements deep. At that point, both implementations were tied. After that point, .some became increasingly superior. When there was no match, and the entire 50k elements had to be looped through, the for loop implementation was about 1.6x slower.

If I were to venture a guess, I'd say that under the hood, .some is probably using a multi-threaded approach to search the array. For small arrays, the extra overhead required to set that up outweighs the benefits. But for very large arrays, it is superior. But obviously, results will vary on different systems and in different browsers.

TLDR: A for loop is actually much faster in this situation, and probably most things that you'd be doing in a RPG Maker plugin. .some is faster with very large data sets, and probably scales better with better hardware.
 

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
278
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
It depends on the size of the array, how deeply buried the first match is, and the complexity of the test that you're performing on each element. But using Chrome, with a small array like the OP is using (only 7 elements), .some is actually much slower than a for loop.

For example, take this code:
JavaScript:
(() => {
    const arr = [21, 53, 10, 19, 4, 7, 32];
    var result = false;

    console.time("For");
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] == 7) {
            result = true;
            break;
        }
    }
    console.timeEnd("For");
    console.log(result);
})();

vs this code:
JavaScript:
(() => {
    const arr = [21, 53, 10, 19, 4, 7, 32];

    console.time("Some");
    var result = arr.some(element => element == 7);
    console.timeEnd("Some");
    console.log(result);
})();

The first snippet uses a for loop to search a 7-element array for a value that is located 6 elements deep, and the second is a .some implementation that does the same thing. After testing each snippet 5 times on Chrome, and averaging the results, the .some snippet turned out to be 3.6x slower on my system.

However, when I performed the same test on a very large array ([...Array(50000).keys()]), things were a little different. The for loop was the still the winner up until the point where the first match was buried about 2000 elements deep. At that point, both implementations were tied. After that point, .some became increasingly superior. When there was no match, and the entire 50k elements had to be looped through, the for loop implementation was about 1.6x slower.

If I were to venture a guess, I'd say that under the hood, .some is probably using a multi-threaded approach to search the array. For small arrays, the extra overhead required to set that up outweighs the benefits. But for very large arrays, it is superior. But obviously, results will vary on different systems and in different browsers.

TLDR: A for loop is actually much faster in this situation, and probably most things that you'd be doing in a RPG Maker plugin. .some is faster with very large data sets, and probably scales better with better hardware.
Thanks for this in depth walk through. This is so useful and important in my opinion. I also want to pat myself on the shoulder just a tad, I actually thought that it was a possibility that .some for small arrays would be slower. Your testing and effort truly verified this though, so you don't get a pat on the shoulder, you get standing ovations! :)

But, in the end, the .some function looks cleaner and more easily understood, perhaps I am mistaken, perhaps it is just me. And when we are talking about these small sizes that that only when requested by the user, i.e. not part of "update()", the methods for reaching the desired results will never be slow to a degree that is relevant. So therefore, the .some function is what I'll be using :)

Hell, I just want to show, so people aren't scared of tiny, user requested functions a test I did some three months ago, since my friend said some game was slow because the developer used so many IF statements. I told him it's probably just because he uses the game interpreter for if statements. But just remember that this test is super small, and only made to blow his mind about the speed. It will scale in time considerably depending on what is checked within the if statement and what is performed if true or false.

The code:
1642688619714.png
The results:
1642688601854.png
I.e. it performed 200,000,000 million IF statements in about 4 seconds. Whilst also performing something within each statement, and I was not considering efficacy for the operations within, they're simple though. But, at this point, adding another 0 does, naturally, keep increasing the time consumed exponentially. Just 20,000,000 IF statements took 400 milliseconds.

Test was done in either Chrome of Firefox, I believe it was Chrome as I feel the console is better positioned by default.
 
Last edited:

Arthran

Veteran
Veteran
Joined
Jun 25, 2021
Messages
318
Reaction score
264
First Language
English
Primarily Uses
RMMZ
@bishiba

Yeah, there's certainly nothing wrong with prioritizing code concision and/or readability when the situation allows for it. And the common rule of thumb is to not focus on performance optimization too much unless the situation calls for it. But when coding parts of a game engine, there are certainly many situations that do call for it, so it's handy to know what type of performance impact various methods and operations have.

Now as far as if statements go, they actually have much less impact on performance than what your example demonstrates. In your example, what's actually taking most of that 4 seconds are the function calls that you're doing, followed by the memory writes (incrementing the variables), followed by reading memory, followed by the loop itself. I don't know if I'm explaining it well, but take a look at these examples:

JavaScript:
(() => {
    var stuff = 0;

    console.time("if test");

    for (let i = 0; i < 100000000; i++) {
        if (Math.floor(29.2) == Math.ceil(28.2))
            stuff++;
        if (Math.round(20.6) == Math.floor(21.6))
            stuff++;
    }

    console.timeEnd("if test");
    console.log("stuff = " + stuff);
})();
This code will perform 200,000,000 if statements, and in the process of doing so, it will be calling 4 functions and incrementing two variables (not counting i) each loop. On my system, this took 198.6 ms.

JavaScript:
(() => {
    var stuff = 0;

    console.time("if test");

    for (let i = 0; i < 100000000; i++) {
        if (100 == 200)
            stuff++;
        if (200 == 100)
            stuff++;
    }

    console.timeEnd("if test");
    console.log("stuff = " + stuff);
})();
This code will do the same number of if statements, but it will call no functions and it will not write to memory at all (other than incrementing i), since they will never evaluate to true. This code only took 39.5 ms on my system.

JavaScript:
(() => {
    var stuff = 0;

    console.time("if test");

    for (let i = 0; i < 100000000; i++) {
    }

    console.timeEnd("if test");
    console.log("stuff = " + stuff);
})();
This code is just an empty loop. It also only took 39.5 ms on my system.

So basically, in these examples, the "if" portion of the if statements is practically free. It's 100% about what you're doing both in the test portion of the if statement, and also in the body of the if statement.
 
Last edited:

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
278
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
@bishiba

Yeah, there's certainly nothing wrong with prioritizing code concision and/or readability when the situation allows for it. And the common rule of thumb is to not focus on performance optimization too much unless the situation calls for it. But when coding parts of a game engine, there are certainly many situations that do call for it, so it's handy to know what type of performance impact various methods and operations have.

Now as far as if statements go, they actually have much less impact on performance than what your example demonstrates. In your example, what's actually taking most of that 4 seconds are the function calls that you're doing, followed by the memory writes (incrementing the variables), followed by reading memory, followed by the loop itself. I don't know if I'm explaining it well, but take a look at these examples:

JavaScript:
(() => {
    var stuff = 0;

    console.time("if test");

    for (let i = 0; i < 100000000; i++) {
        if (Math.floor(29.2) == Math.ceil(28.2))
            stuff++;
        if (Math.round(20.6) == Math.floor(21.6))
            stuff++;
    }

    console.timeEnd("if test");
    console.log("stuff = " + stuff);
})();
This code will perform 200,000,000 if statements, and in the process of doing so, it will be calling 4 functions and incrementing two variables (not counting i) each loop. On my system, this took 198.6 ms.

JavaScript:
(() => {
    var stuff = 0;

    console.time("if test");

    for (let i = 0; i < 100000000; i++) {
        if (100 == 200)
            stuff++;
        if (200 == 100)
            stuff++;
    }

    console.timeEnd("if test");
    console.log("stuff = " + stuff);
})();
This code will do the same number of if statements, but it will call no functions and it will not write to memory at all (other than incrementing i), since they will never evaluate to true. This code only took 39.5 ms on my system.

JavaScript:
(() => {
    var stuff = 0;

    console.time("if test");

    for (let i = 0; i < 100000000; i++) {
    }

    console.timeEnd("if test");
    console.log("stuff = " + stuff);
})();
This code is just an empty loop. It also only took 39.5 ms on my system.

So basically, in these examples, the "if" portion of the if statements is practically free. It's 100% about what you're doing both in the test portion of the if statement, and also in the body of the if statement.
Indeed, in regards to the if statements, I think my main consideration for displaying the example isn't to display effective code, if anything I went a bit out of my way to add functions that did pull a bit of processing power in order to simply prove the speed of if statements. It's not uncommon to see people claiming that if statements are slow and should try to be avoided in different way.

The only thing I agree on in that situation would be human readability, a nested and complex if statement only creates confusion and it is much preferred to either refactor such code in some way - and almost certainly, such optimization should be relatively easily implemented.

I must ask if you'd be willing to add eachother on discord? Having someone with your level of understanding for programming seems not just useful, but essential, considering my desire for improvement along with my current educational courses. Big questions would still be posted here though, so I won't be incessant... I think :p
 

Arthran

Veteran
Veteran
Joined
Jun 25, 2021
Messages
318
Reaction score
264
First Language
English
Primarily Uses
RMMZ
Indeed, in regards to the if statements, I think my main consideration for displaying the example isn't to display effective code, if anything I went a bit out of my way to add functions that did pull a bit of processing power in order to simply prove the speed of if statements. It's not uncommon to see people claiming that if statements are slow and should try to be avoided in different way.

The only thing I agree on in that situation would be human readability, a nested and complex if statement only creates confusion and it is much preferred to either refactor such code in some way - and almost certainly, such optimization should be relatively easily implemented.

I must ask if you'd be willing to add eachother on discord? Having someone with your level of understanding for programming seems not just useful, but essential, considering my desire for improvement along with my current educational courses. Big questions would still be posted here though, so I won't be incessant... I think :p
I wouldn't say that I'm unwilling, but I suspect that you'd be a bit disappointed by the outcome, because I usually only log into Discord like once or twice every few weeks. I'm kind of a hermit who prefers to cut myself off from the outside world and remain buried in my own endeavors most of the time, and I only really like to come up for air and be social at times of my own choosing. It's selfish, but it's just kinda how I am. So it's not that I mind adding you, but you actually would have better luck contacting me here than on Discord.

And as much as I hate to admit it, I think you might be overestimating my expertise a bit. I do have decent knowledge about certain things, but my experience tends to lean more towards lower level programming. My JavaScript experience is pretty minimal, and my current knowledge of RPG Maker's engine is pretty limited as well. Of course, I don't mind trying to answer any questions you might have, and if you ever want someone to bounce ideas off of or whatnot, I'm happy to listen. I'm just telling you this to make sure that you know to treat any of my advice with an appropriate amount of skepticism, and so that you don't get your hopes up too much.
 
Last edited:

bishiba

Adept
Veteran
Joined
Apr 6, 2016
Messages
278
Reaction score
161
First Language
Swedish
Primarily Uses
N/A
I wouldn't say that I'm unwilling, but I suspect that you'd be a bit disappointed by the outcome, because I usually only log into Discord like once or twice every few weeks. I'm kind of a hermit who prefers to cut myself off from the outside world and remain buried in my own endeavors most of the time, and I only really like to come up for air and be social at times of my own choosing. It's selfish, but it's just kinda how I am. So it's not that I mind adding you, but you actually would have better luck contacting me here than on Discord.

And as much as I hate to admit it, I think you might be overestimating my expertise a bit. I do have decent knowledge about certain things, but my experience tends to lean more towards lower level programming. My JavaScript experience is pretty minimal, and my current knowledge of RPG Maker's engine is pretty limited as well. Of course, I don't mind trying to answer any questions you might have, and if you ever want someone to bounce ideas off of or whatnot, I'm happy to listen. I'm just telling you this to make sure that you know to treat any of my advice with an appropriate amount of skepticism, and so that you don't get your hopes up too much.
Certainly understandable, and I don't know your programming expertise but as you said, you're willing to bounce ideas, which in all honesty is the best way to get better in my opinion :p Just discussing something your interested in will advance your skill, and this holds true even for the greats. And to be fair, I am the most incessant sceptic of this generation.

I swear to you, if anyone comes up to me and starts talking to me about science or whatever, I demand sources or just go away. I'm similar with programming, only issue is that I haven't reached the same experience in sifting through code as I have with scientific papers. But, I guess my point is that I know full well that even the best programmers will do fundamental errors :)

I'm gonna request a solve for this thread as it has divulged into conversation rather than anything related :)
 

slimmmeiske2

Little Red Riding Hood
Global Mod
Joined
Sep 6, 2012
Messages
9,715
Reaction score
6,169
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.

Latest Threads

Latest Posts

Latest Profile Posts

Messing around with fragment shaders (filters). This thing is HUGE and I'm surprised almost no one makes good use of. Even the number of plugins that do this stuff are limited.
ScreenShot_6_28_2022_3_2_40.png

There's 7 main areas in the game that are all connected. This train get's you from an underground lab to the center of someone's subconscious. inside the train you can talk to some of the passengers. but going to the top of it, there's battles.
Speedrunning all character portraits just so they all have the same quality. Not sure if this was a good idea, but now I'm almost done.
We now have a gameplay video!
DrBuni wrote on Akiritas's profile.
That is a cute Link picture, reminds me of the Samurai Jack artstyle.

Forum statistics

Threads
123,146
Messages
1,154,383
Members
161,494
Latest member
EnceladusSnow
Top