Jump to content

A simple random script with IF statement!


ZackCero
 Share

You are about to reply to a thread that has been inactive for 2014 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I'm sorry to ask this but I'm not that good at these program languages.

 

This is what I have so far.

 

default
{

    touch_start(integer total_number)
    {
        llPlaySound("UUID", 0.2);
    }
}

And it works right now for a single sound. When the object is clicked is plays one sound.

Can anyone help me turn this into a script that will run a random number. And play different sounds based on the number? I would like three sounds but I feel if I am given the code for three I will be able to make it more if needed anyhow.

 

So random number...

IF Statement to check random number

than play whatever sounds using llPlaySound("UUID", 0.2); etc...

Thanks.

Link to comment
Share on other sites

Try this:

default
{
    touch_start(integer total_number)
    {
        integer random = (integer) llFrand (3);
        if (random < 1) llPlaySound ("UUID_0", 0.2);
        else if (random < 2) llPlaySound ("UUID_1", 0.2);
        else llPlaySound ("UUID_2", 0.2);
    }
}
(*Other methods are also available.)
  • Like 1
Link to comment
Share on other sites

Lots of alternatives, like ....

list lSounds = [ "UUID of sound #1 goes here", "UUID of sound #2 goes here", "UUID of sound #3 goes here"];  // and so forth ...

default
{
    touch_start( integer num )
    {
        integer iWhichOne = (integer) llFrand( llGetListLength( lSounds ) );
        llPlaySound( llList2String(lSounds, iWhichOne), 1.0);
    }
}

 

Edited by Rolig Loon
Link to comment
Share on other sites

another way, which will not play the same sound twice in a row

list s = ["sound1", "sound2", "sound3"];

integer i;

default
{
   state entry
   {
      i = (integer)llFrand(3.0);
   }

   touch_start(integer num)
   {
      i = (i + 1 + (integer)llFrand(2.0)) % 3;
      llPlaySound(llList2String(s, i);
   }
}

 

 

Link to comment
Share on other sites

1 hour ago, ellestones said:

another way, which will not play the same sound twice in a row


code

 

Psst~ Examples given to beginners should probably have descriptive names for variables to not be unnecessarily confusing. Same with explaining what the calculations are for and what the heck % does.

Edited by Wulfie Reanimator
Link to comment
Share on other sites

Yet another way to do it (containing a check to see you don't play the same sound twice in succession)

list lSounds = ["FirstSoundUUID","SecondSoundUUID","ThirdSoundUUID"];//populate list with the uuids of your sounds, obviously
string strLastSound;
default
{
	state_entry()
	{
		//llSay(0, "Hello, Avatar!");
	}
	touch_start(integer total_number)
	{
		string str;
		do {
			str = llList2String(llListRandomize(lSounds,1),0);//randomise the order of lSounds, and select the first item in the new list
		}
		while(str == strLastSound);//and keep on doing this until the first item in the list is not the same as the last sound played.
		strLastSound = str;//make a note of the sound
		llPlaySound(str,0.2);//and play it.
	}
}

 

  • Like 1
Link to comment
Share on other sites

5 hours ago, Wulfie Reanimator said:

Same with explaining what the calculations are for and what the heck % does.

Since you have brought it up ....  ;)

For the OP's benefit .... The modulo operator ( % ) is a powerful part of the scripting arsenal, not as well appreciated as it ought to be.  Basically, it's doing what we all learned as we were taught about long division in grade school.  When you divide on number by another, you get a two-part answer: a "goes into" part and a "left over" part.  So, 2 "goes into" 3 once with 1 "left over".  The modulo operator tells you what the "left over" part is.  So, 3 % 2 = 1. 

That doesn't look all that powerful, but it can save you having to write more complicated conditional tests.  For example, if you have several sounds to play one after another in a loop, and their UUIDs  are all in a global list, you could keep track of a global integer counter and write
 

timer()
{
    integer iListLength = llGetListLength( lSounds ); 
    llPlaySound( llList2String(lSounds, iCount) , 1.0);
    ++iCount;
    if ( iCount == iListLength)  // we reached the end of the list
    {
        iCount = 0;   // so start over again
    }
}

or we can write
 

timer()
{
    integer iListLength = llGetListLength( lSounds );
    iCount = ++iCount%iListLength;  // that is, iCount is what's "left over" after you increase the previous value by one and divide by iListLength
    llPlaySound( llList2String( lSounds, iCount ), 1.0);
}

You can make this even more compact by writing
 

timer()
{
    integer iListLength = llGetlistLength( lSounds );
    llPlaySound( llList2String( lSounds, ++iCount%iListLength ), 1.0);
}

Every time the script plays the sound at the end of the list, the division ++iCount%iListLength throws away the "goes into" part and keeps only the "left over" part, which keeps going merrily around a loop 0, 1, 2, 3, ..., iListLength, 0, 1, 2, 3, ..., iListLength, 0,1, 2, 3 ....

(And yes, I know that we would really be smarter to make iListLength a global integer variable and put the line integer iListLength = llGetListLength( lSounds) in state_entry, but let's not get distracted in this example.  :) )

Edited by Rolig Loon
Typos, as usual
  • Like 3
Link to comment
Share on other sites

19 hours ago, Wulfie Reanimator said:

Psst~ Examples given to beginners should probably have descriptive names for variables to not be unnecessarily confusing. Same with explaining what the calculations are for and what the heck % does.

Rolig explained % much better than I ever could :)

i did originally write the snippet so that it read

 i = (++i + (integer)llFrand((float)(m - 1))) % m;

as this can work with any length list > 0. But I thought this was maybe a bit complicated. So I simplified it as Zack only asked about playing 3 sounds

am not sure that

indice = (++indice + (integer)llFrand((float)(magnitude - 1))) % magnitude;

makes what this code does any clearer really. Perhaps a textual explanation might be better. May be something like: will not play the same sound twice in a row

Link to comment
Share on other sites

59 minutes ago, ellestones said:

Perhaps a textual explanation might be better. May be something like: will not play the same sound twice in a row

I was thinking more like explaining what's going on, step by step, like..

Quote

// First you pick a random number between 0.0 and 1.99999..:
float rFloat = llFrand(2);

// Then you remove the fractional by changing its type to an integer:
integer rInteger = (integer)rFloat;

// Then you take the previous index value used for the list, add one (next sound) and the random value:
integer rIndex = i + 1 + rInteger;

// Finally, because the random index is probably higher than the actual list length, you divide it with the list length:
integer final = rIndex % 3;

i = final;

// Or you can do everything on one line:
i = (i + 1 + (integer)llFrand(2)) % 3;

So if the previous index (i) was 2 (last in the list) and the random value chosen is 1.8603 (becomes 1):
final = ((2 + 1 + 1) % 3)
final = (4 % 3)
final = 1

Because a comment like "won't do X" or "will do X" is meaningless when you're looking at plain code and can't understand it.

P.S. The value for llFrand doesn't need to be m-1, just m is fine.

Edited by Wulfie Reanimator
Link to comment
Share on other sites

12 minutes ago, ellestones said:

m is the list length

I understand that m(agnitude) is equal to the list length, but you don't seem to understand that llFrand will never return a given magnitude.
Wiki: ...the returned value can be any value in the range 0.0 to mag including 0.0, but not including the value of mag itself.
(And even if it did, the chances of it hitting exactly 2 is incredibly small when considering the range of possible values.)

Fortunately the code works exactly the same with llFrand(2), but this is why it's important to break your code down in smaller steps and explain what's going on. A complicated process stuffed into one statement is not a good example to someone who isn't familiar with the fundamentals. There's nothing to learn from it if you can't break it down yourself.

Edited by Wulfie Reanimator
Link to comment
Share on other sites

44 minutes ago, ellestones said:

is arithmetic

Isn't this? No matter which index you start from, llFrand(3) will give you what you want, because of.. the modulus operator.
That is to say, no matter what calculations or what ridiculously huge number you use for llFrand, %3 will guarantee the final number to be 0-2.

 ┌─ index
 │   ┌─ offset
 │   │   ┌─ llFrand(3) = 2.999..
(0 + 1 + 2) % 3 = 0
          3 % 3 = 0

(1 + 1 + 2) % 3 = 1
          4 % 3 = 1

(2 + 1 + 2) % 3 = 2
          5 % 3 = 2

 

Edited by Wulfie Reanimator
Link to comment
Share on other sites

the example I posted is different to the others posted.  I said here is a method that will give a random number not the same as the last, so that the same sound will not play twice in a row

as you show:

i = 0;

i = (0  + 1 + 2) % 3;

i == 0;

which is not an outcome of my example

the statement: i = (0  + 1 + rnd(3)) % 3 is functionally equivalent to: i = rnd(3) for all starting values of i

 

Link to comment
Share on other sites

4 minutes ago, ellestones said:

the example I posted is different to the others posted.  I said here is a method that will give a random number not the same as the last, so that the same sound will not play twice in a row

as you show:

i = 0;

i = (0  + 1 + 2) % 3;

i == 0;

which is not an outcome of my example

the statement: i = (0  + 1 + rnd(3)) % 3 is functionally equivalent to: i = rnd(3) for all starting values of i

Okay, I see my mistake and apologize. It was me with the brainfart all along.

But.. maybe use me as the case-study then instead?

Link to comment
Share on other sites

This thread reopens an old familiar debate: "Exactly how much detail is appropriate in our responses to LSL forum posts?"  For every well-reasoned answer to the question, there is always a counter example. 

As a new scripter, I was always excited to get a response from someone like Void Singer, who would dump a whole load of hay on me in technical language, complete with a barely comprehensible example.  I learned an incredible amount, quickly, from Void.  But I am weird. I actually wanted to learn how to script, and I wanted to know why things work the way they do.  My observation in the years since has been that I truly am the oddball, and I have become mildly cynical.  Most OPs really do only want a quick answer and couldn't possibly care less about the basic principles behind it. That doesn't stop me from posting explanations, especially if I sense something in the OP's question to suggest that s/he is really likely to care.  This forum is designed to foster conversations among scripters.  Regardless of my feeling that many OPs don't care, my baseline assumption is that anyone posting here is (or ought to be) a scripter and therefore deserving of some technical explanation. 

The real question is, how much explanation?  The bare minimum is a link to some relevant part of the LSL wiki or to a relevant example in the Library.  If nothing else, that points the OP to someone else's explanation.  It's also fair to copy out a portion of the OP's script (if one is provided) and add comments that suggest improvements or other ways to approach the same end, or to provide an example of my own along with a bit of text that outlines the basic points that the example is meant to illustrate. Personally, I usually draw the line at providing complete scripts or rewriting an OP's script from the ground up.  That's the OP's job if s/he's a real scripter (or a learning scripter).  This forum is not a resource for free scripting. 

I like threads like this one.  The OP is new to LSL but is clearly interested in learning how to write scripts.  A couple of us offered quick examples (even complete scripts, considering that the entire thing can be done in a few lines), and the OP responded with feedback to indicate that he understood and might be interested in digging deeper.  We've offered alternative approaches and debated the use of a basic mathematical function, giving the OP, each other, and any lurkers a better understanding of the nuances of the modulo operator.  It's been a nice mix of script examples and commentary, technical enough to get at real issues but not overwhelmingly geeky -- and not treating the OP as a grade schooler who needs words of one syllable. 

I can say from experience that it can be deadly discouraging to get a reply from an OP that says either "I don't have any idea what to do with that information, and I really don't care." or "I don't want an explanation.  I want an answer."   Or, almost as discouraging, no reply at all -- suggesting that the OP hasn't even bothered to come back and look.  Or to find that I have written out my stellar interpretation of how something works and yet no other scripter has apparently noticed either.  This thread is a nice relief from the norm. 

  • Like 4
Link to comment
Share on other sites

I agree. Discovering how to create non-repetitive random selections from a list using an incremental counter and the modulo operator has been a revelation. I've previously taken a random selection from all but the last item in the list and then moved that selection to the end of the list.

Link to comment
Share on other sites

j

1 hour ago, KT Kingsley said:

 non-repetitive random selections

adding on to this

is a number of situations where a delimited (not-the-same-as-the-last) combinatorics function can be useful. Sound playlists. Animation sequences like dance balls/huds. Prize giver where 2 random but different prizes from a pool is given. Pay-to-play devices like gacha/gumball. etc

a thing with using this kinda delimited combinatorics function is to factor in that the set of reachable combinations is significantly smaller than the set of all combinations within the range. Particularly factoring it in when used for competitive scoring/reward games and pay-to-play situations. Example:

a set of 3

using standard RND(3) then there are 27 unique combinations: 3 x 3 x 3 = 27. [000,001,002,010, ... , 221, 222]

using this kinda delimited combinatorics function then is only 3 x 2 x 2 = 12 combinations that can be reached

[010,012,020,021,101,102,120,121,201,202,210,212]

for sets of other magnitudes then the way to calculate it is the same:  Examples:

4 x 4 x 4 x 4.  [4 x 3 x 3 x 3]
5 x 5  x 5 x 5 x 5 .  [5 x 4 x 4 x 4 x 4]
10 x 10 x ... 10 x 10. [10 x 9 x ... 9 x 9]

 

  • Thanks 2
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 2014 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...