While loop that loops until the user types the right thing?
herb191
27 Apr 2013, 21:40I am playing around with well loops and I can't get it to work right with a get input. It keeps giving an error that says: "Error running script: Only one 'get input' can be in progress at a time". Then it seems to kick me out of the loop. I have attached my test code. To test type start loop. If it was working right typing exit into the input would exit the loop.
Thanks in advance for the help.
Thanks in advance for the help.

jaynabonne
27 Apr 2013, 22:37The problem is that "get input" is not blocking. In other words, "get input" just sets up conditions for the input to be gotten, but it then returns right away, with the associated script being executed once the input has been entered. It all happens asynchronously. Also, the player code won't be able to actually get the input until your script has returned. So blocking "while" loops are bad in Quest.
In other words, you can't do it the way you're trying to do it. Your script must exit. You can't block on input. It will grind things to a halt.
In other words, you can't do it the way you're trying to do it. Your script must exit. You can't block on input. It will grind things to a halt.
herb191
27 Apr 2013, 23:11jaynabonne wrote:The problem is that "get input" is not blocking.
I see. Thank you for the explanation Jaynabonne. I will find a workaround for what I am trying to do.
Sora574
29 Apr 2013, 01:44If you still haven't gotten what you're looking for, you could try something along the lines of this
This puts it in an endless loop until the player types the word 'blah'.
this.inputscript => {
get input {
if (result = "blah") {
this.inputscript = null
// Run script
}
else {
do (this, "inputscript")
}
}
}
do (this, "inputscript")
This puts it in an endless loop until the player types the word 'blah'.

jaynabonne
29 Apr 2013, 09:32Slick!
One thing to keep in mind, though: if you have any code after the outer "do" (e.g. a msg or anything), then it will be executed right away, not after the input is gotten (I'm not sure if that's what the OP was trying to do.)

Sora574
29 Apr 2013, 16:02Hmm...
I guess if you really wanted to keep it separate, you could just put something like 'this.boolean=true' in the 'Run script' place.
Then, you could make an endless loop that checks for the boolean. And then continues the script outside.
I'm not sure if that would throw any errors or not, though, and it seems to stack up complication, but you could do it.
I guess if you really wanted to keep it separate, you could just put something like 'this.boolean=true' in the 'Run script' place.
Then, you could make an endless loop that checks for the boolean. And then continues the script outside.
I'm not sure if that would throw any errors or not, though, and it seems to stack up complication, but you could do it.

jaynabonne
29 Apr 2013, 16:08That's what I was trying to say in my responses above - you can't do that. There is no way in Quest to block. As a test, I put an endless while loop in a command script, and not only did the game freeze, but the entire Quest UI locked up. Your scripts must complete, and you have to process things asynchronously, as painful as that is (and believe me, I know - I'm going through it right now in my own code).
Sora574
29 Apr 2013, 16:35Okay, so I tried it a few different ways, and you're absolutely right...
Each time, I successfully managed to crash Quest completely.
I wonder if there's a way around this
EDIT: It seems that no matter what you do, or how you change it, everything has to run at the same time.
I don't know if this would be considered a flaw, but I think there should definitely be a way to stop all scripts until a variable is found. I tried doing this myself with JavaScript, but I'm just not that good of a programmer.
Each time, I successfully managed to crash Quest completely.
I wonder if there's a way around this
EDIT: It seems that no matter what you do, or how you change it, everything has to run at the same time.
I don't know if this would be considered a flaw, but I think there should definitely be a way to stop all scripts until a variable is found. I tried doing this myself with JavaScript, but I'm just not that good of a programmer.
HegemonKhan
30 Apr 2013, 02:33Can't you use "on ready" ??? http://quest5.net/wiki/On_ready
or, does on ready not work for this situation that you're discussing ???
or, does on ready not work for this situation that you're discussing ???
this.inputscript => {
get input {
if (result = "blah") {
this.inputscript = null
// Run script
}
else {
do (this, "inputscript")
}
}
}
on ready {
do (this, "inputscript")
}
OR
this.inputscript => {
get input {
if (result = "blah") {
this.inputscript = null
// Run script
}
else {
do (this, "inputscript")
}
}
}
do (this, "inputscript")
on ready {
(whatever)
}
OR
on ready {
this.inputscript => {
get input {
if (result = "blah") {
this.inputscript = null
// Run script
}
else {
do (this, "inputscript")
}
}
}
}
do (this, "inputscript")
OR
on ready {
this.inputscript => {
get input {
if (result = "blah") {
this.inputscript = null
// Run script
}
else {
do (this, "inputscript")
}
}
}
do (this, "inputscript")
}
~I can't remember and always get confused off the top of my head on the correct format~syntax for how to use "on ready", lol

jaynabonne
30 Apr 2013, 08:38"on ready" holds off scripts while a get input, wait, etc is in progress. You can't use it as a general purpose blocking mechanism. Basically, the code inside the "on ready" won't trigger until a pending input call is complete. So in the example you gave, the "on ready" would fire after the first "get input" was completed, whether the result met your conditions or not.
If you want it to be based on conditions you set, then you have to do it yourself. The most straightforward is to put the subsequent code in the "if (result = "blah")" block. The alternative is set up a script variable somewhere and then invoke it when done (but still within that block). I did that in some menu code I wrote, which was similar to what Alex has with the new ShowMenu except it actually required a valid response. For that, I passed in an object and an attribute name, and when the option chosen was valid, it did "do(object, attribute") after setting up the result param to let the object know things were done.
If you want it to be based on conditions you set, then you have to do it yourself. The most straightforward is to put the subsequent code in the "if (result = "blah")" block. The alternative is set up a script variable somewhere and then invoke it when done (but still within that block). I did that in some menu code I wrote, which was similar to what Alex has with the new ShowMenu except it actually required a valid response. For that, I passed in an object and an attribute name, and when the option chosen was valid, it did "do(object, attribute") after setting up the result param to let the object know things were done.

jaynabonne
30 Apr 2013, 08:48Here's a useless example (but shows a possible form):
And call with:
(Note: the above code has not been tested and might not run due to any number of typos or oversights.
)
<function name="Expect" parameters="expected,postscript">
get input {
if (result = expected) {
params = NewDictionary()
dictionary add(params, "result", result)
do(postscript, params)
} else {
msg("Try again...")
Expect(expected, postscript)
}
}
</function>
And call with:
Expect("Hello") {
msg("You typed Hello!")
msg("See: the result is " + result)
}
(Note: the above code has not been tested and might not run due to any number of typos or oversights.

herb191
01 May 2013, 06:43I didn't realize people were still commenting on this thread. The workaround I came up with was using a turn script to keep calling a function. It work well for what I needed in my game. I have attached an example for anyone who might find it useful.

jaynabonne
01 May 2013, 08:00Actually, since you're invoking loop1 in the default of the switch statement, you don't need the turn script at all as far as I can see. I deleted it, and your code worked fine without it.
What you have in your code without the turn script is the basic pattern - call get input, and if it's not the right input, invoke the input function again.
(And as far as people still commenting - some threads take on lives of their own!)

(And as far as people still commenting - some threads take on lives of their own!)
herb191
01 May 2013, 21:59jaynabonne wrote:Actually, since you're invoking loop1 in the default of the switch statement, you don't need the turn script at all as far as I can see.
Good call. I took another looked at the code and your are right.


jaynabonne
01 May 2013, 23:07Looks good! 
One thing you might be interested to know (and I mention since it's not obvious): you can replace something like this
with this:
It's a handy thing in Quest.

One thing you might be interested to know (and I mention since it's not obvious): you can replace something like this
case ("exit loop") {
msg ("You have left the loop.")
}
case ("leave loop") {
msg ("You have left the loop.")
}
with this:
case ("exit loop", "leave loop") {
msg ("You have left the loop.")
}
It's a handy thing in Quest.