|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sat Feb 09, 2008 7:52 pm
Blocking command |
You may recognize this request from previous threads but I still need a solution. I hope someone can tell me a great way to do this in CMUD. What I want is what I ask for so please don't suggest alternatives like queues and such. They are not what I am looking for.
I need an alias that sends a command to the mud and await a certain response line from the mud before proceeding. I must be able to stop the command if for some reason the line of text I expect to see is not received.
I expect to use it like this perhaps:
Code: |
command "pick up rock" "You pick up"
command "throw rock at monster" "You throw your rock"
...
|
What I need here is the blocking effect so I won't try to throw the rock before I have picked it up.
I hope to see some good suggestions because I'm on the verge of giving up CMUD and mudding all together. I've tried other clients but they simply don't live up to what I have gotten used to since shifting to zMUD years ago. On the other hand I haven't been playing my mud since CMUD was upgraded to v2 - simply because the thread changes killed my scripts. |
|
|
|
Guinn Wizard
Joined: 03 Mar 2001 Posts: 1127 Location: London
|
Posted: Sat Feb 09, 2008 9:11 pm |
#WAITFOR seems to do exactly what you ask
|
|
_________________ CMUD Pro, Windows Vista x64
Core2 Q6600, 4GB RAM, GeForce 8800GT
Because you need it for text... ;) |
|
|
|
MattLofton GURU
Joined: 23 Dec 2000 Posts: 4834 Location: USA
|
Posted: Sat Feb 09, 2008 9:44 pm |
Use a multistate trigger:
#oninput {pick up rock} {}
#condition {You pick up} {throw rock}
#condition {You throw your rock} {pick up rock}
That's the basic outline, at least. The multi-state trigger stuff will make sure nothing executes out of order. |
|
_________________ EDIT: I didn't like my old signature |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sat Feb 09, 2008 9:53 pm |
Guinn wrote: |
#WAITFOR seems to do exactly what you ask |
To my knowledge you cannot cancel a #WAITFOR command unless you set some timeout which I am not interested in. I need to be able to cancel if something unexpected happens (like if there is no rock to pick up). |
|
Last edited by kjaerhus on Sat Feb 09, 2008 10:01 pm; edited 1 time in total |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sat Feb 09, 2008 10:01 pm |
MattLofton wrote: |
Use a multistate trigger:
#oninput {pick up rock} {}
#condition {You pick up} {throw rock}
#condition {You throw your rock} {pick up rock}
That's the basic outline, at least. The multi-state trigger stuff will make sure nothing executes out of order. |
But it is not blocking, is it? I might have too many commands to make conditions for all of them. Besides I might want to wrap triggers around my command (create them before sending the command and removing them when feedback is received from the mud). I think the weakness of those conditions is that the next command need to know of what you did just before. |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sat Feb 09, 2008 11:00 pm |
kjaerhus wrote: |
Guinn wrote: |
#WAITFOR seems to do exactly what you ask |
To my knowledge you cannot cancel a #WAITFOR command unless you set some timeout which I am not interested in. I need to be able to cancel if something unexpected happens (like if there is no rock to pick up). |
If there is no rock to pick up #WAITFOR will never match and will sit there waiting forever, that pretty much sounds like the command that #WAITFOR would have sent if it matched has been blocked which is exactly what you asked for. |
|
_________________ Taz :) |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sat Feb 09, 2008 11:09 pm |
Taz wrote: |
If there is no rock to pick up #WAITFOR will never match and will sit there waiting forever, that pretty much sounds like the command that #WAITFOR would have sent if it matched has been blocked which is exactly what you asked for. |
Not sure I understand what you mean. I want the alias to block but I still need to be able to cancel the waiting.
Anyway, I've been working a bit on it and perhaps I can use the construction below. I did scratch this solution earlier because I have problems using #EXECUTE calling aliases (see earlier thread) but now that I don't use this construction any more as Zugg don't care to fix it I might be able to use it. In this solution I use signals.
Alias "feedbackCommand" taking parameters $command, $feedback and $hideoption:
Code: |
// If $hideOption is set a temporary trigger which removes command from screen is created
#IF ($hideoption == "hide") {
$commandTrigger = %exec($command) // In this situation %exec() just returns what it WOULD have sent
#TEMP {$commandTrigger} {filterCommands $commandTrigger} "" input
}
// Creates a trigger to detect feedback
#IF ($feedback == "") {
#TRIGGER {myprompt>} {#SIGNAL feedback} "" "nocr|prompt"
} {
#VAR feedback $feedback
#TRIGGER {{@feedback}} {#SIGNAL feedback}
}
// Execute command and wait for feedback
#EXEC $command
#WAITSIGNAL feedback
// Remove trigger
#IF ($feedback == "") {
#UNTRIGGER {myprompt>}
} {
#UNTRIGGER {{@feedback}}
#UNVAR feedback
}
|
Any comments on it? |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sat Feb 09, 2008 11:24 pm |
kjaerhus wrote: |
Taz wrote: |
If there is no rock to pick up #WAITFOR will never match and will sit there waiting forever, that pretty much sounds like the command that #WAITFOR would have sent if it matched has been blocked which is exactly what you asked for. |
Not sure I understand what you mean. I want the alias to block but I still need to be able to cancel the waiting. |
kjaerhus wrote: |
Guinn wrote: |
#WAITFOR seems to do exactly what you ask |
To my knowledge you cannot cancel a #WAITFOR command unless you set some timeout which I am not interested in. I need to be able to cancel if something unexpected happens (like if there is no rock to pick up). |
You are contradicting yourself. Do you want to be able to cancel or not? You say you are not interested in a timeout which is exactly what cancels a #WAITFOR. You say you want to be able to cancel if there is no rock to pick up which means #WAITFOR didn't match which means you need to use a timeout. |
|
_________________ Taz :) |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sat Feb 09, 2008 11:36 pm |
Taz wrote: |
You are contradicting yourself. Do you want to be able to cancel or not? You say you are not interested in a timeout which is exactly what cancels a #WAITFOR. You say you want to be able to cancel if there is no rock to pick up which means #WAITFOR didn't match which means you need to use a timeout. |
Did you have any constructive comments, Taz? If you read the original post a bit closer than you obviously have already you would notice that I wrote that I need to be able to cancel. A timeout is NOT a cancel but a deadline for the expected text to arrive from the mud. A cancel is when I don't want to wait anymore and press a cancel button or something like that. Let's not fight any more over words, please. |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sat Feb 09, 2008 11:47 pm |
My comments have been constructive comments, I'm not sure how you can have construed them otherwise, perhaps there is a language barrier occurring. I think you are misunderstanding what I am saying. Forget that the way to cancel a #WAITFOR was called timeout and just rename it in your head to cancel since that is exactly what it does it cancels the #WAITFOR, you no longer want to wait and it stops you waiting, the bonus is you didn't have to press a button to achieve your not waiting any more.
|
|
_________________ Taz :) |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sat Feb 09, 2008 11:56 pm |
Well, perhaps there IS a language barrier here. In my world being constructive means that you help solving the problem. Until now you have only thrown short comments on my answer to Guinn's suggestion.
Well, bring on the solution if you have it, Taz. Show me how I can cancel a #WAITFOR. Do remember that I want to cancel it when I want on runtime. Setting a hardcoded timeout is no good. |
|
|
|
Zhiroc Adept
Joined: 04 Feb 2005 Posts: 246
|
Posted: Sun Feb 10, 2008 12:05 am |
If the "cancel" situation is simple, as in "not getting the response you expect within some number of lines" I use "within lines" #COND trigger. That cancels the entire trigger when you don't get it fast enough.
If the situation is more complicated, like canceling on command, I'm more prone to use a class I enable and disable. I know I could do that with #STATE commands too, but I just usually don't.
There are problems using #WAIT* to do this. A thread that is waiting uses resources. I imagine that if you #WAIT* enough where the response never comes, you'll start to chew up memory. Worse, if you ever trigger the condition, you'll then let all N threads go at once. For example, if you say "pick up rock" where there wasn't one, you might still be waiting. Say it again, and now you have two waiting. Go to a room minutes later, do "pick up rock" and when the correct response comes, you'll have 3 commands trigger on the response.
With your feedbackcommand, you will run into the problem I outlined in another thread. You'll be waiting on a response that isn't coming. If you try another feedbackcommand for a different (or same) command, you'll have two concurrent feedbackcommands pending, and that isn't thread-safe. |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sun Feb 10, 2008 12:07 am |
kjaerhus wrote: |
Well, bring on the solution if you have it, Taz. Show me how I can cancel a #WAITFOR. Do remember that I want to cancel it when I want on runtime. Setting a hardcoded timeout is no good. |
What do you perceive to be the difference to you cancelling it yourself and it cancelling itself. I can tell you there is no difference but if you really do want to cancel it yourself you can cancel the thread that it creates rather than letting it cancel itself, to cancel it yourself use #STOP. |
|
_________________ Taz :) |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sun Feb 10, 2008 12:15 am |
Zhiroc wrote: |
If the "cancel" situation is simple, as in "not getting the response you expect within some number of lines" I use "within lines" #COND trigger. That cancels the entire trigger when you don't get it fast enough.
If the situation is more complicated, like canceling on command, I'm more prone to use a class I enable and disable. I know I could do that with #STATE commands too, but I just usually don't.
There are problems using #WAIT* to do this. A thread that is waiting uses resources. I imagine that if you #WAIT* enough where the response never comes, you'll start to chew up memory. Worse, if you ever trigger the condition, you'll then let all N threads go at once. For example, if you say "pick up rock" where there wasn't one, you might still be waiting. Say it again, and now you have two waiting. Go to a room minutes later, do "pick up rock" and when the correct response comes, you'll have 3 commands trigger on the response.
With your feedbackcommand, you will run into the problem I outlined in another thread. You'll be waiting on a response that isn't coming. If you try another feedbackcommand for a different (or same) command, you'll have two concurrent feedbackcommands pending, and that isn't thread-safe. |
In my suggested solution a few posts above I use signals to determine whether the script can continue. If I cancel the alias will not wait anymore and there should not be more than one feedbackCommand waiting at a time. Do you see potential problems with this solution too? |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sun Feb 10, 2008 12:23 am |
As long as there isn't more than one feedbackCommand waiting at a time it will work fine. If you wanted to extend it to allow that you would need to start using trigger ids and pass the id in as $id to your alias.
|
|
_________________ Taz :) |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sun Feb 10, 2008 12:30 am |
Taz wrote: |
What do you perceive to be the difference to you cancelling it yourself and it cancelling itself. I can tell you there is no difference but if you really do want to cancel it yourself you can cancel the thread that it creates rather than letting it cancel itself, to cancel it yourself use #STOP. |
Timing out automatically after a certain amount of time is not the same as when I decide to cancel. Basically I want it to run forever but I need the backdoor to be able to cancel the command. A timeout is no good because it doesn't take things like lag into consideration and because the script cannot tell what went wrong. I as a person can guess what to do and then act and cancel the waiting to let the script continue.
#STOP might work. I must admit that I until just now thought this was for speedwalking only. Now THAT was constructive input. |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sun Feb 10, 2008 12:44 am |
#ALIAS feedbackCommand($id, $command, $feedback) {#THREAD $id {#WAITFOR {$feedback} {$command}}}
#ALIAS cancelFeedback($id) {#STOP $id}
feedbackCommand "pr" "throw rock at monster" "You pick up"
cancelFeedback pr |
|
_________________ Taz :) |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sun Feb 10, 2008 12:52 am |
Taz wrote: |
#ALIAS feedbackCommand($id, $command, $feedback) {#THREAD $id {#WAITFOR {$feedback} {$command}}}
#ALIAS cancelFeedback($id) {#STOP $id}
feedbackCommand "pr" "throw rock at monster" "You pick up"
cancelFeedback pr |
Not sure that would work (where's the blocking when you create a thread?) but I get the idea. |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sun Feb 10, 2008 1:04 am |
The client will never send the command "throw rock at monster" to the mud if it never receives the feedback "You pick up" from the mud, that is your blocking.
|
|
_________________ Taz :) |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sun Feb 10, 2008 1:20 am |
Taz wrote: |
The client will never send the command "throw rock at monster" to the mud if it never receives the feedback "You pick up" from the mud, that is your blocking. |
Uhm, no it won't work and I've tried it to prove it. If you create a thread the main thread will continue and thus not block. If you look at my suggestion some posts above you will see that I block the main thread until the signal is coming. But I have understood your point. I am not sure if it's a better way than signals but it's a nice alternative now that I know how to kill a thread when I don't care to wait for it to complete. |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sun Feb 10, 2008 1:31 am |
I was under the impression that it isn't possible to block the main thread, that is why threads were put in to start off with so that the client continues to respond to your input no matter what you've told it to do.
I think you're saying that you block the main thread when you do #WAITSIGNAL but I'm fairly certain this creates a new thread. |
|
_________________ Taz :) |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sun Feb 10, 2008 1:36 am |
Nope, #WAITSIGNAL is main thread...
|
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sun Feb 10, 2008 1:44 am |
I just checked, a new thread is definitely created!
|
|
_________________ Taz :) |
|
|
|
kjaerhus Magician
Joined: 18 Dec 2006 Posts: 317 Location: Denmark
|
Posted: Sun Feb 10, 2008 1:51 am |
How can you tell?
Anyway, the documentation says that it's suspending the current thread and it works that way too. Try it out - the working alias is somewhere in this thread. You just need to change "myprompt>" to hwo your own prompt looks. |
|
|
|
Taz GURU
Joined: 28 Sep 2000 Posts: 1395 Location: United Kingdom
|
Posted: Sun Feb 10, 2008 1:55 am |
#thread lists the current threads.
I have your alias created by copying and pasting from earlier in this set of posts. It is what I used in order to check about the threads. If you type #thread in a new session you will see only 1 thread is listed, after using your alias you will see there are 2 threads listed. |
|
_________________ Taz :) |
|
|
|
|
|