Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD Beta Forum Goto page 1, 2  Next
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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.
Reply with quote
Guinn
Wizard


Joined: 03 Mar 2001
Posts: 1127
Location: London

PostPosted: 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... ;)
Reply with quote
MattLofton
GURU


Joined: 23 Dec 2000
Posts: 4834
Location: USA

PostPosted: 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
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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.
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: 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 :)
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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?
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: 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 :)
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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.
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: 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 :)
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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.
Reply with quote
Zhiroc
Adept


Joined: 04 Feb 2005
Posts: 246

PostPosted: 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.
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: 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 :)
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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?
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: 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 :)
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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. Smile
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: 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 :)
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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.
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: 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 :)
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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.
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: 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 :)
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: Sun Feb 10, 2008 1:36 am   
 
Nope, #WAITSIGNAL is main thread... Smile
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: Sun Feb 10, 2008 1:44 am   
 
I just checked, a new thread is definitely created!
_________________
Taz :)
Reply with quote
kjaerhus
Magician


Joined: 18 Dec 2006
Posts: 317
Location: Denmark

PostPosted: 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.
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: 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 :)
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD Beta Forum All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net