Command queue oddness.

4 views
Skip to first unread message

Ben Trafford

unread,
Dec 27, 2009, 12:00:08 PM12/27/09
to tin...@googlegroups.com

I've got an object running a simple set of commands, which are chained
together like so:

@force #118={@dig %1=[escape(%4)],[escape(%5)]};@wait #118={@force
#118={@parent [where([lastcreate(#118)])]=%2}};@notify #118;@wait
#118={@force #118={@set
[where([lastcreate(#118)])]=d.description:[escape(%3)]}};@notify #118

...and so on and so forth.

I'm doing it this way because I assumed that if I did so, it would queue
up the commands in order, not starting the next until the last was
complete. I -tried- putting the @dig command into a @wait, but then it
didn't work at all.

What I'm finding is that some commands are going out of queue, and it's
screwing everything else up.

I'm wholly confused as to why this would be so. Any advice would be
appreciated. I just want the object to run its commands, completely and
with all effects realized, in order.

--->Ben

Jerry Van Suchtelen

unread,
Dec 27, 2009, 1:11:12 PM12/27/09
to tin...@googlegroups.com
I know this is no help but, that looks like a code snippit from a room
digger. :)

Stephen Dennis

unread,
Dec 27, 2009, 2:01:15 PM12/27/09
to tin...@googlegroups.com
Use of @drain is usually important for this type of work, but I don't see one. If the object isn't @drained, that could indicate that your queue is holding onto a previous command and confusing your debugging.

Queue Cycle 1:

@force #118=
{
    @dig %1=[escape(%4)],[escape(%5)]  <<--- This is scheduled into queue cycle 2.
};
@wait #118=
{
    @force #118= <<--- This is scheduled into queue cycle 2 dependent on semaphore
    {
        @parent [where([lastcreate(#118)])]=%2
    }
};
@notify #118; <<--- Semaphore is notified before we even get to the end of this action list, so benefit of using it is dubious.
@wait #118=
{
    @force #118= <<--- This is scheduled into queue cycle 2 dependent on semaphore.
    {
        @set [where([lastcreate(#118)])]=d.description:[escape(%3)]
    }
};
@notify #118 <<--- Semaphore is notified before we even get to the end of this action list, so benefit of using it is dubious.


Queue Cycle 2:

@dig %1=[escape(%4)],[escape(%5)]
@force #118=
{
    @parent [where([lastcreate(#118)])]=%2  <<--- This is scheduled into queue cycle 3
}
@force #118=
{
    @set [where([lastcreate(#118)])]=d.description:[escape(%3)]  <<--- This is scheduled into queue cycle 3
}


Queue Cycle 3:

@parent [where([lastcreate(#118)])]=%2
@set [where([lastcreate(#118)])]=d.description:[escape(%3)]


When I create a test object and replace the @dig, @parent, and @set commands with @pemits:

&FOO #100=@force #100={@pemit %#=Dig emit.};@wait #100={@force #100={@pemit %#=Parent emit.}};@notify #100;@wait #100={@force #100={@pemit %#=Set emit.}};@notify #100

I get the following trace:

FooThing(#100)} '{@pemit %#=Dig emit.}' -> '@pemit #3=Dig emit.'
FooThing(#100)} '@pemit %#=Dig emit.' -> '@pemit #3=Dig emit.'
Dig emit.
FooThing(#100)} '{@pemit %#=Parent emit.}' -> '@pemit #3=Parent emit.'
FooThing(#100)} '@pemit %#=Parent emit.' -> '@pemit #3=Parent emit.'
FooThing(#100)} '{@pemit %#=Set emit.}' -> '@pemit #3=Set emit.'
FooThing(#100)} '@pemit %#=Set emit.' -> '@pemit #3=Set emit.'
Parent emit.
Set emit.


Brazil

Ben Trafford

unread,
Dec 27, 2009, 10:14:10 PM12/27/09
to tin...@googlegroups.com

Okay, I'm -wholly- confused.

Let me explain:

I'm finding that, without any sort of @wait going on, some commands
aren't being fully effected in order. For example, lastcreate() isn't
working reliably on following commands, I'm guessing because the @dig is
still digging.

So, let's say I want to have a bunch of commands be evaluated, and be
-definitely- complete before the next commands are evaluated.

How do I do that?

--->Ben

S. Holland

unread,
Dec 27, 2009, 11:06:38 PM12/27/09
to tin...@googlegroups.com
My usual method, which is crude and clumsy but seems to work, is to @wait each individual command a discrete amount. IE:
@wait 1=Command 1;@wait 3=command 2;@wait 5=command 3;...


You may need to fiddle with the timing, of course.

2009/12/27 Ben Trafford <b...@prodigal.ca>

Ben Trafford

unread,
Dec 27, 2009, 11:14:46 PM12/27/09
to tin...@googlegroups.com

So, something about @wait which is unclear to me -- in the example you
gave, does it time like this:

1 second: Command 1
3 seconds: Command 2
5 seconds: Command 3

...or...

1 second: Command 1
3 + 1 = 4 seconds: Command 2
5 + 3 + 1 = 9 seconds: Command 3

I'm very much hoping to avoid this solution, because it seems to me that
there must be -some- way to force commands to operate distinctly and
completely in the queue.

However, if I can't figure that out, I'll try your approach. Thank you!

--->Ben

Jerry Van Suchtelen

unread,
Dec 27, 2009, 11:52:31 PM12/27/09
to tin...@googlegroups.com
When you use @wait its N seconds from when you run it. So you want
command 1 to run 1 second from now, command 2 to wait 3 seconds,
command 3 to wait 5 seconds. Of course you might, depending on the
length of the command, extended it a little more. Then each command
is 'queued' by its time to wait.

Ben Trafford

unread,
Dec 27, 2009, 11:54:49 PM12/27/09
to tin...@googlegroups.com

So...does -anybody- know how to tell a command to execute completely,
and then move onto the next one? The @wait by seconds approach seems
horrifically clumsy and prone to trouble.

--->Ben

Amy Kretzer

unread,
Dec 28, 2009, 12:03:43 AM12/28/09
to tin...@googlegroups.com
The easiest way to help (for me) is by asking: What are you trying to
accomplish with the code? I'm assuming you want to dig a room and then
parent the results to the specified parent, and set the specified
description? Why not use the create() side-effect function triggered inside
a setq() which will allow you to have re-use the dbref#'s of the objects. I
use such code for my apartment renting and hotel room renting structures,
where it creates and teleports and describes and flags the apartment and
exits through triggering one command:

An example would be:

&CMD-DIG #123=$+dig */*=*,*=*:@switch/first 0=valid(roomname,%0),@pemit
%#=That's a silly name for a room!,valid(exitname,%2),That's a silly name
for an entry exit!,valid(exitname,%3),That's a silly name for a return
exit!,isdbref(%1),@pemit %#=I can't find that room parent!,{&NULL
me=[setq(1,create(eval(%0),10,r))][setq(2,create(%2,1,e))][setq(3,create(%3,1,e))];@parent
%q1=%1;@link %q2=%q1;@desc %1=%4;@link %q3=%l;@teleport %q2=%l;@teleport
%q3=%q1;@pemit %#=You dug a new room named "[eval(%0)]" %(%q1%) parented to
[name(%1)] %(%1%).}

@set #123/cmd-dig=no_parse

Usage: +dig <room name>/<parent db#>=<entrance>,<return>=<description>

That would dig the room and open the exits, link the exits, teleport them to
the correct place, and parent the room to the specified dbref#. The no_parse
flag means the exit names and room description will be set without being
evaluated, while the inclusion of the eval() function around the room name
segments of the code will allow people to use ANSI color in the room name.
Or you could remove that ability and just make the whole thing no_parse, in
which case the code would look like:

&CMD-DIG #123=$+dig */*=*,*=*:@switch/first 0=valid(roomname,%0),@pemit
%#=That's a silly name for a room!,valid(exitname,%2),That's a silly name
for an entry exit!,valid(exitname,%3),That's a silly name for a return
exit!,isdbref(%1),@pemit %#=I can't find that room parent!,{&NULL
me=[setq(1,create(%0,10,r))][setq(2,create(%2,1,e))][setq(3,create(%3,1,e))];@parent
%q1=%1;@link %q2=%q1;@desc %1=%4;@link %q3=%l;@teleport %q2=%l;@teleport
%q3=%q1;@pemit %#=You dug a new room named "%0" %(%q1%) parented to
[name(%1)] %(%1%).}

Hope this helps!

--------------------------------------------------
From: "Ben Trafford" <b...@prodigal.ca>
Sent: Sunday, December 27, 2009 11:00 AM
To: <tin...@googlegroups.com>
Subject: [TinyMUX] Command queue oddness.

>
> No virus found in this incoming message.
> Checked by AVG - www.avg.com
> Version: 9.0.722 / Virus Database: 270.14.121/2589 - Release Date:
> 12/27/09 03:18:00
>

Amy Kretzer

unread,
Dec 28, 2009, 12:08:28 AM12/28/09
to tin...@googlegroups.com
Sorry that should read:

&CMD-DIG me=$+dig */*=*,*=*:@switch/first 0=valid(roomname,%0),@pemit

%#=That's a silly name for a room!,valid(exitname,%2),That's a silly name
for an entry exit!,valid(exitname,%3),That's a silly name for a return
exit!,isdbref(%1),@pemit %#=I can't find that room parent!,{&NULL
me=[setq(1,create(eval(%0),10,r))][setq(2,create(%2,1,e))][setq(3,create(%3,1,e))];@parent

%q1=%1;@link %q2=%q1;@desc %q1=%4;@link %q3=%l;@teleport %q2=%l;@teleport
%q3=%q1;@pemit %#=You have dug a new room called "%0" %(%q1%) parented to
[name(%1)] %(%1%).}

(Previous version was setting the desc on the parent not the newly created
room.) So much for poorly watched test runs!

--------------------------------------------------
From: "Amy Kretzer" <ma...@stjoelive.com>
Sent: Sunday, December 27, 2009 11:03 PM
To: <tin...@googlegroups.com>
Subject: Re: [TinyMUX] Command queue oddness.

Ben Trafford

unread,
Dec 28, 2009, 12:10:40 AM12/28/09
to tin...@googlegroups.com

That'd certainly work for this specific issue, but I anticipate that
I'll encounter queuing issues again and again. I'd really like to
understand how to solve my initial question -- how can I setup lists of
commands, where each command is fully evaluated and effected before the
next?

Thank you for your help!

--->Ben

Robby Griffin

unread,
Dec 28, 2009, 1:18:27 AM12/28/09
to tin...@googlegroups.com
Um, put the commands one after another with semicolons between them? Avoid using queue-manipulating commands such as @force, @dolist, @switch or @wait if you don't want to consider queue issues. Simple non-queueing commands such as @dig and @pemit will execute completely before moving on to the next command in the semicolon-separated list.

Ben Trafford

unread,
Dec 28, 2009, 1:36:24 AM12/28/09
to tin...@googlegroups.com

That didn't work. I put the commands with the semicolons between them.
The next command in the list relies on the lastcreate() function, but
can't find it -- but it -does- find it later on down the queue. This
leads me to believe that @dig isn't finished doing its thing for some
time.

I've bug-tested the hell out of the code. It's really the only answer
I've come up with.

--->Ben

Robby Griffin

unread,
Dec 28, 2009, 2:12:49 AM12/28/09
to tin...@googlegroups.com
Also avoid extraneous square brackets -- you may be causing the lastcreate() function to evaluate before the entire semicolon-separated command list is interpreted.

Ben Trafford

unread,
Dec 28, 2009, 2:20:00 AM12/28/09
to tin...@googlegroups.com

The brackets are being used to indicate time to evaluate? That's pretty
clunky.

I'll give it a shot and tell you how it goes.

Thanks!

--->Ben

Ben Trafford

unread,
Dec 28, 2009, 2:36:11 AM12/28/09
to tin...@googlegroups.com

Nope, that didn't work, either. If anything, it screwed things up even
more.

So, back to my original question -- is there any way to force commands
to operate, completely, in sequence, including evaluating all internal
functions to said command (such as @parent where(lastcreate())), etc.)?

--->Ben


On Mon, 2009-12-28 at 01:12 -0600, Robby Griffin wrote:

Robby Griffin

unread,
Dec 28, 2009, 2:56:09 AM12/28/09
to tin...@googlegroups.com
Sort of -- there are historical quirks in the parser that mean square brackets are sometimes required in order for functions to be evaluated at all. One of those times is when you're passing the command argument to @force within curly braces. If you have square brackets in the command, the contents will be evaluated *before* the forced command is placed on the queue. If you were to escape the brackets with % or some number of backslashes, they'd be included literally in the queued command, so evaluation would be delayed until the queue entry runs.

Sometimes the brackets are just unnecessary line noise because you're already in a function-evaluating context, such as when creating an argument to pass to another function. When you really need brackets, like in the middle of a string, you can escape them, or just avoid @force and other queue-manipulating commands altogether.

I haven't tested this, but I'm guessing the following does what your original example intended:

@force #118={@dig %1=%4,%5; @parent where(lastcreate(me))=%2; &d.description where(lastcreate(me))=%3}

(and if this is already in a $-command on #118 itself, of course the @force is unnecessary as well).

--Alierak

Ben Trafford

unread,
Dec 28, 2009, 2:59:46 AM12/28/09
to tin...@googlegroups.com

Which would be great, except that losing @force pretty much negates the
entire purpose of the code.

I'll try work around the quirks. We'll see what happens.

It'd be -really- damned nice if there was some sort of command or
bracketing structure to force full evaluation of its contents. I keep
expecting softcode to act like Lisp...and then it doesn't, and I cry. :(

Thanks again!

--->Ben

Ben Trafford

unread,
Dec 28, 2009, 4:03:14 AM12/28/09
to tin...@googlegroups.com

Well, I got it fixed. It's an ugly hack, but it works around the bugs in
the parser.

Thanks for your help, everyone!

--->Ben


On Mon, 2009-12-28 at 01:56 -0600, Robby Griffin wrote:

Stephen Brewer

unread,
Dec 28, 2009, 10:27:24 AM12/28/09
to tin...@googlegroups.com
The parser is working as intended, you're just thinking about it wrong. :)

This is a typical reaction when coders are exposed to complexities of the queue for the first time. There is a code lecture out there on the queue, I think by Adam from Firan, but I can't find it for the life of me right now. If someone knows where it's hosted, please post a link? I'd like to add a few of these lectures to the wiki to centralize them, and I remember this one being a good intro to how to use the queue.

You have to keep track of not only what is being executed when in the queue, but also what's being evaluated when. To figure all this out it helps to make your initial structure as simple as possible, and replace commands with pemits to see what's executing when. You can also set the object your command is on as TRACE so that you can see what's being evaluated. In a lot of cases, if the answer is "manipulate the queue," then you need to rephrase the question. There's a ton of code out there that's pretty complex, but still runs in one queue cycle.

Using @force is what's throwing you off, because it delays execution of all commands inside the @force until everything else in the current command is done.

--Stephen/Soylent

Clotho Fate

unread,
Dec 28, 2009, 5:45:24 PM12/28/09
to tin...@googlegroups.com
What Stephen/Soylent said.  But I'll add these tips/tricks/caveats.

Firstly, see 'help @break' for a very basic explanation of how the queue works.

Secondly, study how @break and @assert (if you're using TinyMUX 2.7) work.  I, myself, make extensive use of them when I'm fiddling with things that depend on the queue working as I want it too.

Thirdly, look at side effect functions and how they can be combined (or not, your choice) with @break and @assert to make things work as you want them too.

Fourthly, I'll let you in on a fun hack with @force.  You have to be careful with it, because it can mess up if you're not careful with security and such.

When @force hits the queue and is run, any functions in it are parsed -BEFORE- it puts the command string to the queue stack.  An example of this nifty effect is this:

@force me=if(0,help @force,look)

And that's about all I have to say.  The @force trick works up to version: TinyMUX 2.7.4.30  but who knows what Brazil will do since I've released this trick to the wild. :P

~Clotho

Ben Trafford

unread,
Dec 29, 2009, 8:17:44 AM12/29/09
to tin...@googlegroups.com

Clotho, sorry I missed this one yesterday, and thanks for your reply!

--->Ben

Reply all
Reply to author
Forward
0 new messages