If statement triggering both options in <<for>> loop?

Hey there! I’m trying to send a player to a different passage based on an answer and play a “victory” sound. If a player enters an answer that is NOT one of the possible answers I want to play an “error” sound.

Everything is working fine except that for some reason this button will forward the player to the correct passage and play BOTH “victory” and “error” sounds.

<<button "->">>
	<<for _i to 0; _i lt _curAarray.length; _i++>>
		
		/*A CORRECT ANSWER!*/
			<<if _code is _curAarray[_i]>>	
			
				
				/* play choice sound*/													
					<<audio "victory" volume 1 play>>	
				
				/* send player to matching forwarding passage! */
					<<goto _forwardingPassages[_i]>>
				
				/* stops the loop cos you've found a correct answer! */
					<<break>>												

		/*NOT ONE OF THE POSSIBLE ANSWERS...*/	
			<<else>>
				<<audio "error" volume 1 play>>	
				<<shaketarget "#bottombar" .5s>>
			<</if>>	
	<</for>>																	
<</button>>

I included the <<break>> because I thought this glitch might be due to the <<for>> loop is going so fast it comes back around (to an incorrect value) before players are sent to the passage with the <<goto>> … but it doesn’t seem to help!

Anyway, I’m stumped! can anyone tell me what I’m doing wrong?

Thanks a million!

I think what is happening is that it’s playing the error sound because it fails the check up until it doesn’t. For example, if currArray[2] is equal to _code, your script will still play the error sound when _i equals 0 and 1, and then will move you to correct passage when it equals 2.

There are two ways you could probably handle this. One is the easy but hacky way, which is remove your else statement and place the check to just after the for loop. Then you can compare _i to _curAarray.length. If it’s equal, then that means it fell through the for loop without a match.

<<button "->">>
	<<for _i to 0; _i lt _curAarray.length; _i++>>
		
		/*A CORRECT ANSWER!*/
			<<if _code is _curAarray[_i]>>	
			
				/* play choice sound*/													
					<<audio "victory" volume 1 play>>	
				
				/* send player to matching forwarding passage! */
					<<goto _forwardingPassages[_i]>>
				
				/* stops the loop cos you've found a correct answer! */
					<<break>>									
			<</if>>	
	<</for>>	

	/*NOT ONE OF THE POSSIBLE ANSWERS...*/ 
	<<if _i eq _curAarray.length>>
			<<audio "error" volume 1 play>>	
			<<shaketarget "#bottombar" .5s>>
	<</if>>												
<</button>>

The other method is similar and is less hacky but requires an extra variable. Instead of abusing the iteration variable, we’ll create a match flag.

<<button "->">>
	<<set _match to false>>
	<<for _i to 0; _i lt _curAarray.length; _i++>>
		
		/*A CORRECT ANSWER!*/
			<<if _code is _curAarray[_i]>>
				<<set _match to true>>
			
				/* play choice sound*/													
					<<audio "victory" volume 1 play>>	
				
				/* send player to matching forwarding passage! */
					<<goto _forwardingPassages[_i]>>
				
				/* stops the loop cos you've found a correct answer! */
					<<break>>									
			<</if>>	
	<</for>>	

	/*NOT ONE OF THE POSSIBLE ANSWERS...*/ 
	<<if _match eq false>>
			<<audio "error" volume 1 play>>	
			<<shaketarget "#bottombar" .5s>>
	<</if>>												
<</button>>

Either option should fix your issue, I think.

Edit:
Actually, if I can rewrite your code for a minute, there’s a better way of doing this altogether.

<<button "->">>
	<<set _index to _curAarray.indexOf(_code)>>

	/*A CORRECT ANSWER!*/
	<<if _index gt -1>>	
			
		/* play choice sound*/													
		<<audio "victory" volume 1 play>>	
				
		/* send player to matching forwarding passage! */
		<<goto _forwardingPassages[_index]>>
				
	/*NOT ONE OF THE POSSIBLE ANSWERS...*/ 
	<<else>>
			<<audio "error" volume 1 play>>	
			<<shaketarget "#bottombar" .5s>>
	<</if>>									
<</button>>
2 Likes

Genius! Worked perfectly thanks so much!!! :stuck_out_tongue: :stuck_out_tongue:

And I didn’t even know I could abuse variables :confused: I suspect I’m doing this all the time whooooooops.

Haha. :grinning_face_with_smiling_eyes:

It’s technically bad code to do what I was suggesting. Stuff like iterator variables should stay within the loops that they were created for and local/temporary variables should be declared just before they’re used and only used for a specific purpose. It just makes for easier to read code and helps prevent errors and hard to track bugs.

That being said, I sometimes get lazy and create variables like temp and will use it three different ways before the function is over.

Anyway, be sure to check out my edited answer. Arrays have an indexOf function that will return the index of the first instance of a value, or -1 if it’s not found. You can completely avoid the for loop using that.

1 Like

Oh. My. Goodness.

This is going to change my #TwineLife

I can’t tell you how many times I’ve wanted to pull out the position of said variable from an array (without knowing its position beforehand).

Thanks! This is an even better solution for sure :slight_smile: :slight_smile:

1 Like

ahhh wait a sec… the only gotcha there is that the new code is still relying on that _i variable?

I think the indexOf solution would work perfectly EXCEPT that I actually need the _i so that it matches the forwarding passages etc…still super handy to know!

Yeah, my mistake. I didn’t see the _i there. I re-edited it with code to account for that now.

1 Like

Ahhh of course! Yea that’s clever. I’m so glad I saw this fix before I rewrote everything again lol.

Thanks so much this is PERFECT!

1 Like