Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Problem in simple loop

Hi, all!
I'm using Twine 2.1.3 and SugarCube 2.18.0.

This doesn't work:
<<set _outcome to 0>>
<<for _outcome == 0>>
	Loop
	<<if _outcome == 1>>
		$victory
		<<goto $victory>>
	<</if>>
	<<set _outcome to 1>>
	_outcome
<</for>>

Apparently, _outcome is set to 1 at the end of the first iteration, but the condition "_outcome == 1" is not recognized. Ridiculous syntax problem, of course, but where ?

Thanks in advance.

Comments

  • edited July 2017
    Maybe writing out the program flow you've designed here will help:
    For -> as long as outcome is 0, loop. 
    If  -> outcome is 1, then goto... It isn't, so: 
    Set -> outcome to 1
    For -> outcome is not 0, so ignore this code
    

    So your output looks like this:
    Loop
    1
    

    ... But the for loop only iterates once. Depending on what you want to do, you can solve this a few different ways, for example:
    <<set _outcome to 0>>
    <<for>> /% equivalent to <<for true>> %/
    	Loop
    	<<if _outcome == 1>>
    		$victory
    		<<goto $victory>>
    	<</if>>
    	<<set _outcome to 1>>
    	_outcome
    <</for>>
    

    Will probably do what you want. There may be other syntax issues; I didn't test this code.

  • Thanks, Chapel. It worked, but with a very long response time (several seconds).
    Also, obviously I don't have the knack with SugarCube :-). But it will come...
  • edited July 2017
    Thanks, Chapel. It worked, but with a very long response time (several seconds).
    Also, obviously I don't have the knack with SugarCube :-). But it will come...

    Do you mean that this example code took several seconds? Or did you plug something like this into another chunk of code? If it's the latter and you're game, you can post the code if you want and maybe we can put our heads together and make it more efficient.
  • Got it, Chapel! For some obscure reason, it needed a <<break>> between <<goto $victory>> and <</if>>. I wonder why?

    Thanks for your help, anyway :-)
  • edited July 2017
    Oooooooh. Yeah I think that's probably a good idea. Glad you got it!

    I can't test it right now, but I guess since I didn't initially terminate the for loop it kept running through even after the goto call since the macro never actually terminated. I'd imagine it hit the limit and then was able to complete the goto. It might have even thrown an error, but the error wouldn't be visible because of the immediate passage change. I don't know for sure, though.
  • edited July 2017
    You need the <<break>> there because otherwise the infinite loop will continue to run, since <<goto>> does not terminate the rendering passage, nor does it end loops—its documentation contains a notice about the former, the latter being implied. Thus, it ended up invoking <<goto>> until it reached the maximum loop iteration safety limit—default: 1000. At which point, as surmised by Chapel, it attempted to output an error, which you likely never saw due to the thousand or so passage navigations that were piled on.

    Assuming this is a combat loop, or something similar, and _outcome will be 0 until victory (1) or defeat (2?) has been achieved, then I'd recommend something like the following:
    <<for _outcome to 0; _outcome is 0; /* empty */>>
    	[…]
    
    	/* Victorious */
    	<<set _outcome to 1>>
    
    	[…]
    
    	/* Defeated */
    	<<set _outcome to 2>>
    
    	[…]
    <</for>>
    <<if _outcome is 1>>
    	$victory
    	<<goto $victory>>
    <<else>>
    	$defeat
    	<<goto $defeat>>
    <</if>>
    
    A bit redundant perhaps, however, it keeps the <<goto>> out of the line of fire—loop.

    As an alternative. If $victory is simply the passage to send the player to, then I'd recommend simply using _outcome instead, as you only need one state variable in that case and you don't want to create story variables you don't need. For example:
    <<for _outcome to ""; _outcome is ""; /* empty */>>
    	[…]
    
    	/* Victorious */
    	<<set _outcome to "victory passage">>
    
    	[…]
    
    	/* Defeated */
    	<<set _outcome to "defeat passage">>
    
    	[…]
    <</for>>
    <<goto _outcome>>
    
    Again, the <<goto>> is kept separate from the loop.
Sign In or Register to comment.