[SOLVED] I am PERPLEXED by this WEIRD RNG problem.

N

Nathan Archer

Guest
I have a problem with the random number generator only working some of the time and I can't understand why.

Background: I have an algorithm that generates a bunch of building objects which also generates window objects for each building. So it looks like this:



When you click the switch on the left, the algorithm illuminates the dark windows randomly, with a 1/20 chance every step.

Code:
//obj_lightswitch

if(on){
    with(obj_window_light){
        if(irandom(20) == 1){
            on = true;
            if(obj_window_light.on == false){
                //show_debug_message("There are unactivated lights")
                exit
            }else{
                end_level();
            }
        }
    }
}


This works as intended the first time if the obj_window creation code looks like this (assigning a random value so 1/3 of the lights are already turned on):

Code:
on = choose(false, true, false)
//on = false;
my_scale = 1
Upon entering the room the second time (after each room does a little visual thing, they choose a random room), flipping the switch doesn't appear to work at first, but then you see the two buildings in the upper right hand corner (I presume the ones generated last) have windows that light up very slowly and only for the buildings in the upper right hand corner. After about a minute a dozen or so lights turn on. When it works correctly they turn on in about a second.

This also happens when entering the room the first time if the creation code looks like this (lights turned off by default):

Code:
//on = choose(false, true, false)
on = false;
my_scale = 1


I'm hoping someone with more insight as to how the Game Maker RNG engine works because I have no idea why it will only work correctly some of the time and work DIFFERENTLY/SLOWLY the rest of the time.

Note: The lights don't come on starting in the upper right hand corner when it's working correctly, they all just come on randomly. I don't know why Game Maker is choosing the upper right hand corner.
 
Why are you referencing obj_window_light.on inside obj_window_light? That will only ever trigger for any of the instances if the first obj_window_light instance created in the room has on set to true...
 

NightFrost

Member
When you do this:
Code:
if(obj_window_light.on == false){
You are always checking the same window. Since it is an object reference, GM picks the first instance it comes across and checks with that. There might be other problems but this will cause them too: it always returns false as long as the first window is unlit, then always returns true when the first window is lit.
 
N

Nathan Archer

Guest
Why are you referencing obj_window_light.on inside obj_window_light? That will only ever trigger for any of the instances if the first obj_window_light instance created in the room has on set to true...
Correct. If 0 lights are turned off, then the room will end. That is what I want. That is not the issue here, that part of it works correctly. When all lights are on, the room ends. My problem is that the lights aren't turning on in the first place.

When you do this:
Code:
if(obj_window_light.on == false){
You are always checking the same window. Since it is an object reference, GM picks the first instance it comes across and checks with that. There might be other problems but this will cause them too: it always returns false as long as the first window is unlit, then always returns true when the first window is lit.
You appear to have a different interpretation. I think RefresherTowel is right in that it checks ALL windows. I want it to check ALL windows. If ALL windows are lit up, then the room ends.

The problem I'm dealing with isn't related to that though, for some reason the lights are taking a long time to turn on.
 
No, I was saying what NightFrost was saying. It only triggers for the first instance in the room.

Also, use the debugger and watch the values of those variable's...See what line they change on and what is getting triggered when.
 

TsukaYuriko

☄️
Forum Staff
Moderator
You appear to have a different interpretation. I think RefresherTowel is right in that it checks ALL windows. I want it to check ALL windows. If ALL windows are lit up, then the room ends.
The problem I'm dealing with isn't related to that though, for some reason the lights are taking a long time to turn on.
The problem you're dealing with is by all means related to that, and only that. The phenomenon you're experiencing has nothing to do with the RNG.

First of all, to make this clear:
  • Writing to a variable in an object context writes to all instances of that object.
  • Reading from a variable in an object context reads from the first instance of that object.

What you're doing is looping through each instance sequentially, giving them a chance to turn on and, if they do, performing a check.

What you think this check does is to check if all lights are turned on. However, keeping in mind how variable operations on objects work, you're really only checking the first one.

Therefore, you're exiting the event at that point if the first light is on. As this code iterates over the instances sequentially, they will always be checked in the same order, exiting as soon as a light turns on because you're exiting out if the first light is turned on. The first light is the one in the upper right corner - hence why your code works correctly if its light is not turned on. If it is, the lights with lower IDs will have a higher probability of being checked in the first place due to the code exiting after turning one light on and thus have a higher probability of turning on.

(Edit: Clarity.)
 
Last edited:
N

Nathan Archer

Guest
The problem you're dealing with is by all means related to that, and only that. The phenomenon you're experiencing has nothing to do with the RNG.

First of all, to make this clear:
  • Writing to a variable in an object context writes to all instances of that object.
  • Reading from a variable in an object context reads from the first instance of that object.
Maybe I'm not getting it, but it very much appears to be changing individual values rather than all values at once.

And this appears to be performing the check correctly as intended, but only the first time

https://i.imgur.com/m71dlaP.mp4

What you're doing is looping through each instance sequentially, giving them a chance to turn on and, if they do, performing a check.
That is my intent.

What you think this check does is to check if all lights are turned on. However, keeping in mind how variable operations on objects work, you're really only checking the first one.
Be that as it may, that's not my issue. My issue is that they are not turning on, not that they aren't checking correctly.

I think there is some miscommunication, please watch the video: https://i.imgur.com/m71dlaP.mp4
 

TsukaYuriko

☄️
Forum Staff
Moderator
Maybe I'm not getting it, but it very much appears to be changing individual values rather than all values at once.
Code:
on = true;
This line indeed affects an individual instance's value (the value of the instance the with statement is currently iterating through).

So far, so good.

Code:
if(obj_window_light.on == false)
Before, you said that you intend for this line to check whether ALL lights are off.
However, this line exhibits the characteristics of reading (you're comparing it to another value, so it has to be read) and using an object context (obj_window_light).
According to what I've said before:
Reading from a variable in an object context reads from the first instance of that object.
... this checks whether the first light is off, and only the first light. (I misread the code as checking whether it's on before... whoops, but the end result is roughly the same, just inverted.)

This results in this line of code not doing what you want it to do, leading to unexpected behavior which seems to be the source of another problem you are experiencing.


Be that as it may, that's not my issue. My issue is that they are not turning on, not that they aren't checking correctly.
According to what you've posted so far, it seems to me like the lights are not turning on correctly under specific circumstances specifically because they're not checking correctly, as the check is directly involved in the process that turns them on and cancels it prematurely, presumably being the cause of "Game Maker is choosing the upper right hand corner".
If they don't turn on at all, that would probably be a different problem - if this is the case, it seems like I have indeed misunderstood this before.

Is the code you posted all code that is relevant to the lights, or is there something else that may be changing something related to the lights or the switch?

However, please try to resolve the problem with the "all lights on" check first and let us know if any other problems persist. Not eliminating apparent problems may complicate finding the source of potential other problems through interference, or may outright be their cause as well.
 

FrostyCat

Redemption Seeker
You seem to have a much bigger issue with flaky GML fundamentals than the random number generator.

To actually check whether at least one light is off, you would need to use the with block pattern for "if at least one instance satisfies a condition". if(obj_window_light.on == false) doesn't actually do what you think it does.
Code:
var some_light_off = false;
with (obj_window_light) {
  if (!on) {
    some_light_off = true;
    break;
  }
}
if(some_light_off) {
  //show_debug_message("There are unactivated lights");
  exit;
} else {
  end_level();
}
I have also reiterated time and time again about NEVER referencing instance variables by object ID in a multi-instance scenario:
NEVER access a single instance by object ID if multiple instances of the object exist. This includes attempts to reference or set object.variable (which is inconsistent across exports) and using with (object) to apply actions to it (this encompasses all instances of the object instead of just the one you want). Verbally, "Dog's colour" makes sense with one dog, but not with multiple dogs.

Corollary: NEVER set or use an instance's own variables with object.variable. An instance's own variables can be referenced as-is without dot prefixes. DO NOT use self. If multiple instances of the object exists, you might end up setting the value for all instances or for some other instance (depending on the export).
You need to rule out your misconceptions and bad habits before pointing the blame on the engine.
 
N

Nathan Archer

Guest
You need to rule out your misconceptions and bad habits before pointing the blame on the engine.
No one is placing blame on the engine. My code just isn't working.

I have also reiterated time and time again about NEVER referencing instance variables by object ID in a multi-instance scenario:
You really should drop your smug attitude. The others seem like they're trying to help but you're acting like I'm someone who hasn't learned a lesson despite you already teaching it to me 20 times and I'm *just not getting it*. The users of YoYoGames forums aren't a collective consciousness. Just because there may be a common misunderstanding doesn't mean the entire community should know every time you've explained it. It's like getting frustrated that someone is spelling or pronouncing your uniquely spelled/pronounced name wrong after hearing it for the first time, despite you correcting people time and time again.

Another example: all three if you have misinterpreted the issue; the checking-to-end-the-level part of the code is not the issue. The issue is whether or not the lights turn on. Should I get increasingly frustrated? No, since 100% of the people viewing this thread have interpreted it the wrong way, I should explain it better, as its a common misconception.

To everyone else, thanks for your help. I figured it out. Commenting the "exit" line out solved it. Not entirely sure why it solves it, but it does! It might be related to what TsukaYuriko was saying regarding it exiting after the "first" object.
 
...I can't believe you're going on about a 'smug' attitude when literally EVERY person who answered in the thread pointed out exactly what the problem was and yet you repeatedly told people they didn't understand. Sheesh.
 
N

Nathan Archer

Guest
...I can't believe you're going on about a 'smug' attitude when literally EVERY person who answered in the thread pointed out exactly what the problem was and yet you repeatedly told people they didn't understand. Sheesh.
One guy admitted he misinterpreted the problem. I found the solution which wasn't related to what everyone was talking about. You are an additional person that has misinterpreted it if you still don't understand.

There is a seperate issue where the level can end slightly earlier based on whether or not the first window is activated. And that gave me insight to that problem which I hadn't noticed until it was pointed out, but that is, again, not related to what the issue was. Ending the room wasn't the problem, getting the lights to illuminate was.
 

TsukaYuriko

☄️
Forum Staff
Moderator
One guy admitted he misinterpreted the problem.
It seems a bit unintentionally hilarious that you take my word for granted when I say that I might have been wrong, but try everything you can to prove us wrong when we're stating what we believe to be the source of the problem. :D
Not that critical thinking is bad or anything - by all means, it's a good thing to question what others are telling you.

I found the solution which wasn't related to what everyone was talking about.
However, I didn't say that I misinterpreted the problem. I said that I may have misinterpreted the problem in case there is an additional problem after the first one was solved.
This was not the case, as the problem you originally explained is the problem that was fixed by fixing the level exit code.
Therefore, I did not misinterpret it after all and my first post was spot-on, as my and everyone else's suggested solution for the problem I thought was the case (which it was indeed) fixed the problem you thought you had for different reasons, which you didn't.

There is a seperate issue where the level can end slightly earlier based on whether or not the first window is activated. And that gave me insight to that problem which I hadn't noticed until it was pointed out, but that is, again, not related to what the issue was. Ending the room wasn't the problem, getting the lights to illuminate was.
It is related in all the ways. You may not have noticed a problem with ending the room, but that doesn't mean that that's not where the problem was. It's what the program is actually doing that counts, not what you can or can't see it doing.

This is a classic case of trying to solve problems forwards, starting from the symptoms - the symptom is the lights not turning on, the action is commenting out the exit. By solving this problem forwards, the thought process stops there and you declared the action as the solution for the symptom.

Solving this problem backwards, one would start by checking the condition of the exit, which was faulty. This condition is a part of the level finishing code, which therefore is faulty too. By correcting the level completing code, the lights now turn on. Therefore the actual required action to fix the lights is to fix the level finishing code, which by definition makes the level finishing code the problem, not the lights. The lights are merely a side effect of the faulty level finishing which is easy to mistake. It may be the problem you perceive as the end-user, but it's not the problem with the code.


I hope that clears up the cause-and-effect confusion and misinterpretation chain.
 
N

Nathan Archer

Guest
It is related in all the ways. You may not have noticed a problem with ending the room, but that doesn't mean that that's not where the problem was. It's what the program is actually doing that counts, not what you can or can't see it doing.
No, that literally was not the problem. The room ended correctly, when lights were illuminated. The lights did not illuminate correctly. You're right that it was a different non-consequential problem, but trying to act as if you were right this whole time just isn't correct. The room ended correctly, the lights didn't illuminated as expected. You are welcome to watch the videos if you are still confused.
 

TsukaYuriko

☄️
Forum Staff
Moderator
The point isn't whether I was right or not, it's to ensure that you fully understand what the source of the problem was and how what you did contributed to resolving it.

A classic example of this is the metaphor of giving someone a fish vs. teaching them how to fish. As a forum moderator, my purpose is to do the latter, so I can't stand by and watch as a problem gets solved but the topic author doesn't understand why what they did fixed it.

The core reason why I'm explaining what was wrong and why your change solved the issue is because you were "Not entirely sure why it solves it", which, to me, is a prompt for further explanation, as a solution to a problem which is not understood will just lead to additional issues of the same kind further down the line.

In the metaphor, the person who was given a fish will not have any more fish the next day, while the one who was taught how to fish will be able to catch fish on their own.
The GameMaker Community's spirit (which matches that of just about any developer community) is that any programming help should be in the form of capacity building, aiming to help the topic author identify and thus be able to resolve similar issues on their own in the future, which is not a given when the solution is not fully understood.


In some cases, this may come across as acting like I'm right and you're wrong, or even hostility. However, the former is not the point, and there are no negative intentions from my side at all. As far as I'm concerned, my point is to help you - not only now, but also in the future - and while I can't speak for anyone else who has posted in this topic, all I can see are three other people writing good-willed posts with the intention to help you understand and solve the problem you are/were facing.


To assist with illustrating what I'm talking about, I've created a live sample of the code you have posted, taking the liberty of replacing some parts with functionally equivalent ones according to the limitations of the medium. I chose this medium because videos are static in nature and thus can neither be interacted with nor reproduced.

A functionally equivalent copy and paste of the code you posted in the first post into an empty project followed by creating a similar layout of multiple lights and the switch permanently running its code (with the exit line commented out) shows that the switch is instructing the game to move to the next level before all lights are turned on in most cases (the case where the first instance is the last light to be turned on is the exception here). Specifically, it does so whenever the first instance of obj_window_light has its on variable set to true, which is what all four posters in this topic have pointed out.

I went an extra step to create an additional version of this sample. This one includes options to "enable" certain problems you were facing. You can turn them on and off in the Create code. For example, set lights_not_turning_on_bug to true to cause the problem you declared as the main problem, then check where in the code this variable is being used and how it changes the flow of the code. Hopefully, this will allow you to understand why all four of us are going on and on about the code that ends the level while you insist that's not what the problem is about - because it's the cause, as this sample hopefully demonstrates.

Finally, here's a working sample. In this one, I applied the changes that were suggested by everyone who posted in this topic.


If what's happening in your local project is somehow different from these given the indicated changes, it is highly likely that there is other code which somehow interferes with the code you have posted (which is why I asked whether that's the case before).

That would be outside of our control, though, as we can only go by what has been posted - and according to that, both your problem and its solution can be pinpointed down accurately, as I have illustrated in the samples.


I hope that the lengths I've gone to for this post will clear up all remaining uncertainties and disagreements. If there's anything else I should explain, or if I should stop attempting to explain, please let me know.
 
Last edited:

Dog Slobber

Member
No one is placing blame on the engine. My code just isn't working.
Someone was placing blame on the Engine, specifically the pRNG part of the engine.

I have a problem with the random number generator only working some of the time and I can't understand why.
I'm hoping someone with more insight as to how the Game Maker RNG engine works because I have no idea why it will only work correctly some of the time and work DIFFERENTLY/SLOWLY the rest of the time.
Claiming the RNG isn't working correctly, is blaming the engine.
 
Top