[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  General
. . -> [Subject]  pausing speedwalk

pausing speedwalk

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Pages: 1 2  

Posted by David B   USA  (80 posts)  [Biography] bio
Date Sun 02 Mar 2003 02:32 PM (UTC)
Message
Ok I know it can be done, I haven't yet searched for it because before I try to find it, I need to know if it can be used with scripting and spamming

I have my script to cast a spell 40 some odd times.

Can you "pause" those buffered commands like with speedwalk?

My code(with a LOT of Nicks help) to fame:

sub OnAutoCombo (TriggerName, TriggerLine, arrWildCards)
dim AutoCombo
AutoCombo = split (arrWildCards (1))
Dim i, attack
for i=lbound (AutoCombo ) to ubound (AutoCombo )
Select Case AutoCombo (i)
case "rp" attack = "punch right"
case "lp" attack = "punch left"
case "s" attack = "sweep"
case "r" attack = "roundhouse"
case else attack = "" ' unknown attack type
End Select
if i = ubound (AutoCombo ) then
world.send "throw " + world.getvariable ("attacker") + " down"
else
world.send attack + " " + world.GetVariable ("attacker")
end if
next
end sub
[Go to top] top

Posted by 1of10   Canada  (54 posts)  [Biography] bio
Date Reply #1 on Mon 03 Mar 2003 02:57 AM (UTC)

Amended on Mon 03 Mar 2003 02:58 AM (UTC) by 1of10

Message
Do you mean like sending each command with a delay, to avoid flooding?

If so, that would be world.queue(command,1) or world.queue(command,0) if you don't want to see the output echoed.

The delay for the queue is set with the speedwalk delay in the Input configuration page.

One of Ten
Secondary Adjunct of Unimatrix Z03
[Go to top] top

Posted by David B   USA  (80 posts)  [Biography] bio
Date Reply #2 on Mon 03 Mar 2003 07:15 AM (UTC)
Message
Nope, Basically from what I've seen you can pause a speedwalk if you have a certain script and trigger setup.

My script looks like this:

sub SpamCast(name, output, wilds)
dim count
for count = 1 to world.getvariable ("SpellCount")
world.send "c " & world.getvariable("SpellName")
next
world.send world.getvariable ("Sleeper")
world.send "inventory"
end sub

If someone sends me a tell, I'd like to beable to pause the script, I know that pause just pauses the entire program, but I was thinking about that speedwalk thing, and how you could setup a trigger to make you stop speedwalking, I thought maybe it would also work for something like this.
If it doesn't then add as a suggestion please.

My code(with a LOT of Nicks help) to fame:

sub OnAutoCombo (TriggerName, TriggerLine, arrWildCards)
dim AutoCombo
AutoCombo = split (arrWildCards (1))
Dim i, attack
for i=lbound (AutoCombo ) to ubound (AutoCombo )
Select Case AutoCombo (i)
case "rp" attack = "punch right"
case "lp" attack = "punch left"
case "s" attack = "sweep"
case "r" attack = "roundhouse"
case else attack = "" ' unknown attack type
End Select
if i = ubound (AutoCombo ) then
world.send "throw " + world.getvariable ("attacker") + " down"
else
world.send attack + " " + world.GetVariable ("attacker")
end if
next
end sub
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #3 on Tue 04 Mar 2003 02:22 AM (UTC)
Message
You can queue the commands, as 1of10 said, which makes them come out at the speedwalk delay period, whatever that is for you. However, anything you type then goes to the end of the queue. You can discard the queue with world.DiscardQueue, effectively pausing it (getting rid of it, really).

eg.


dim count
for count = 1 to world.getvariable ("SpellCount")
  world.queue "c " & world.getvariable("SpellName"), 1
next


Alternatively you could use timers, for instance world.DoAfter, or world.AddTimer, to make things happen every second or so. The timers could be in a group, and you could use world.DeleteTimerGroup to get rid of a group of timers.

This has the advantage that you can still type other commands while the timers are lined up to fire.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Neva   USA  (117 posts)  [Biography] bio
Date Reply #4 on Tue 04 Mar 2003 01:24 PM (UTC)
Message
That doesn't sound like it actually provides a way to *pause*, though; it provides a way to stop it entirely, but not to pause it. Pausing implies that you can then resume afterwards. It *would* be a nice feature to see, to be able to tell MUSHclient to essentially save whatever's in the queue, delete it, and then restore it when you un-pause.
[Go to top] top

Posted by David B   USA  (80 posts)  [Biography] bio
Date Reply #5 on Tue 04 Mar 2003 04:37 PM (UTC)

Amended on Wed 05 Mar 2003 04:32 PM (UTC) by David B

Message
It would be very nice... perhaps:

world.savequeue "blah blah"

and:

world.loadqueue "blah blah "

Deleting the queue works for my purposes.

Also could someone tell me if this is correct:

sub DiscardQueue (name, line, wilds)
world.discardqueue
world.colournote "White", "black", "I'm discarding the queue"
end sub

I have looked at the world.discardqueue command in the website, and what not, I just can't get it to work.

When the trigger calls the sub it works fine, but it just keeps on going... untill the 40 commands I put in the queue go through.
Could it be because of the amount of time I have as the delay?
Meaning if I have a delay as 0ms then it can't clear the queue because they have all been entered to the mud?


My code(with a LOT of Nicks help) to fame:

sub OnAutoCombo (TriggerName, TriggerLine, arrWildCards)
dim AutoCombo
AutoCombo = split (arrWildCards (1))
Dim i, attack
for i=lbound (AutoCombo ) to ubound (AutoCombo )
Select Case AutoCombo (i)
case "rp" attack = "punch right"
case "lp" attack = "punch left"
case "s" attack = "sweep"
case "r" attack = "roundhouse"
case else attack = "" ' unknown attack type
End Select
if i = ubound (AutoCombo ) then
world.send "throw " + world.getvariable ("attacker") + " down"
else
world.send attack + " " + world.GetVariable ("attacker")
end if
next
end sub
[Go to top] top

Posted by Peeka   (5 posts)  [Biography] bio
Date Reply #6 on Thu 13 Oct 2005 10:22 PM (UTC)
Message
*bump*

So, has anyone figured out a way to pause and then resume speedwalking?
[Go to top] top

Posted by Flannel   USA  (1,230 posts)  [Biography] bio
Date Reply #7 on Fri 14 Oct 2005 05:21 AM (UTC)
Message
http://www.gammon.com.au/scripts/function.php?name=GetQueue

Use getQueue to return the queue to a variable (save the variable and then DiscardQueue), and then later you can Queue the commands again (cycle through the variable, and queue them in order again).

~Flannel

Messiah of Rose
Eternity's Trials.

Clones are people two.
[Go to top] top

Posted by Ekerim   Sweden  (18 posts)  [Biography] bio
Date Reply #8 on Fri 14 Oct 2005 04:35 PM (UTC)
Message
You could do it The Flannel-Gammon-way(tm) ;) with GetQueue and DiscardQueue OR you could do it my way...weird and kinda kinky :)

What I would do is that I would, instead of pushing the spell casting commands on the speedwalking queue, is to set up a timer with a nice delay that would pop the commands of a global array and use $world->SendImmediate( "<command>" ) to send them to the mu* bypassing the the speedwalking queue. The poping and sending would be done in a function that is called by the timer.

Now you think, "Hey! He reinvented the speedwalk queue"...Yupp sure did! but with an important difference.
If you have to react to things in the mu* (I play PK muds..it's weird I know ;) for example if a potential threat walks into the room, there is no way to send commands to the mud until the queue is emptied if you use the speedwalking queue.

My way, you would set the client up to cast your 40-or-so spells and then forget about it...still beeing able to send commands to the mud while the client handles casting the spells...or doing any other commands you tell it to.
All it would take is a global array, a timer that calls a function every time it triggers and a function that checks a global variable if it should run and if it should it pops a command of the queue and send it.
To this you could add the above suggested tigger on tells and all the trigger would have to do is to set the global variable and the function described above would not pop any command.

// Fredrik
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #9 on Fri 14 Oct 2005 11:01 PM (UTC)
Message
Well now I recommend the Gammon-Lua-Coroutine-Yield-Resume (tm) method, which is more flexible than the earlier methods, and allows the entire logic for what you are trying to achieve be presented in a single linear script, with the timers kicking in "in the background" to do the actual work.

See this post:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=4956

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Peeka   (5 posts)  [Biography] bio
Date Reply #10 on Sat 15 Oct 2005 01:14 AM (UTC)
Message
Okay, I read that thread... now that I've stopped giggling at myself, I can admit that all of that just looked like gobbilygook to me. Sniff.
[Go to top] top

Posted by Ekerim   Sweden  (18 posts)  [Biography] bio
Date Reply #11 on Sat 15 Oct 2005 04:18 PM (UTC)

Amended on Sat 15 Oct 2005 05:14 PM (UTC) by Ekerim

Message
*chuckle Peeka*

Great stuff Nick, but not really applicable to the problem that started this thread. Sure it could be modified to work but that would require a good knowledge of Lua. The problem is that he wants to queue a couple of commands and then either work his way through the whole queue or pause the queue and later resume it but not efter a fixed time but rather starting it again with a command.
What would really be needed is a command/alias to queue something, a command/alias to start processing the queue and one to pause it.
The way I would do it is...


I would put this in my Perl script file...

# Command queue variables
@cmdQueue = ();
$pauseQueue = 0;

# Command queue code
sub processQueue() {
    my $cmd;
    
    # If we should not pause the queue and if the queue contains some commands...
    if ( ! $pauseQueue && scalar @cmdQueue ) {
        # Shift a command from the queue...
        # Since what we want is a FIFO queue we shift commands OFF the queue and push them ON.
        $cmd = shift @cmdQueue;
        
        # Use this if you want to be able to queue MUSHClient aliases and/or speedwalks etc...
        $world->Execute( $cmd );
        # ...or use this if you just want to send stuff to the MU*, this is quicker
        # coz it bypasses any command queues and speedwalk queues.
        # $world->SendImmediate( $cmd );
    }
}

sub queueCmds( $$$ ) {
    # We are just interested in the arguments so discard the other stuff.
    shift; shift;

    # Get the array reference from the call stack.
    my $arefArgs = shift;
    
    # Get the count from the args...
    my $count = shift @{$arefArgs};
    # ...and get the command string.
    my $cmdStr = shift @{$arefArgs};

    # Turn this on if you like confirmation msgs.
    #$world->note( "#Queueing ${count} x \'${cmdStr}\'." );

    while ( $count ) {
        push @cmdQueue, $cmdStr;
        $count--;
    }
}

...and then have this timer...

<timers>
  <timer script="processQueue" enabled="y" second="0.50" >

  </timer>
</timers>

...and this alias...

<aliases>
  <alias
   script="queueCmds"
   match="queue ([\d]+)\s(.+)"
   enabled="y"
   regexp="y"
   sequence="100"
  >
  </alias>
</aliases>

...Oppps! Forgot a speedwalk alias...

<aliases>
  <alias
   match="speedwalk (.+)"
   enabled="y"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>{
  my $arg = "%1";
  $arg =~ s/ //g;

  my @cmds = split //, $arg;
  my $count = undef;

  foreach my $cmd ( @cmds ) {
    if ( $cmd =~ /[0-9]/ ) {
      if ( $count == undef ) {
        $count = $cmd;
      } else {
        $count .= $cmd;
      }
    } else {
      $count = 1 if ( $count == undef);

      queueCmds( 0, 0, [ $count, $cmd ] );

      $count = undef;
    }
  }
}</send>
  </alias>
</aliases>



The trigger ALLWAYS runs, but does not trigger when you are not connected so if you disconnect and then reconnect again without restarting the client, the client will just take up where it left off processing the queue on a FIFO basis.

Now you can either do:

queue 10 smile

...or...

speedwalk 2s3e15nued

...or...

speedwalk 2s 3e 15n u e d

Hmmm...I wish I would think things through and test them before posting...almost forgot (this is my 10th or so edit of this post :) to mention how to PAUSE the speedwalk/command queue.
The speedwalk reuses the command queue and that means that the only thing needed to pause the speedwalk is to set the global variable pauseQueue to a non-zero value. To resume the processing of the queue, just set the variable back to zero.

// Fredrik
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #12 on Sat 15 Oct 2005 09:34 PM (UTC)

Amended on Sat 15 Oct 2005 09:39 PM (UTC) by Nick Gammon

Message
Yes, well I was really responding to Peeka, who seemed to want a method to pause a speedwalk temporarily, until the "exits" line arrived to indicate s/he had moved to the next room.

However on re-reading the original post, I see that what this thread is really about is pausing on command (perhaps to chat, or eat/drink etc.).

A modified form of my proposed solution is below. The main alias "! <speedwalk>" now checks a global variable pause_speedwalk and also abort_speedwalk, to see if pausing/aborting the speedwalk is wanted.

If pausing is wanted, it remembers its own thread address in speedwalk_thread, and then calls coroutine.yield to yield execution indefinitely, effectively pausing itself.

Then we have three aliases, which do the following:

  • pause speedwalk - this sets the pause_speedwalk flag.

    This flag is tested next time "through the loop" by the main speedwalk alias, to pause itself.

  • resume speedwalk - this calls coroutine.resume to make the speedwalk thread resume.

  • abort speedwalk - if the speewalk is paused it calls coroutine.resume to make the speedwalk thread resume, however sending the "abort" argument to make it wrap itself up.

    If the speedwalk is not paused it simply sets the abort_speedwalk flag to cause the speedwalk thread to stop executing.


I took out the bit about checking for the "exits" line, however that was really only for simplicity. By adding that back in you have a quite powerful speedwalk system, one that:


  • Sends speedwalks with a time-delay you choose between them

  • Waits until you have changed rooms until it sends the next speedwalk direction

  • Checks for message like "You cannot go that way" to stop uselessly spamming the MUD with directions that won't work

  • Can be paused

  • Can be resumed

  • Can be abandoned



<aliases>
  <alias
   match="!*"
   enabled="y"
   send_to="12"
   sequence="100"
  >
  <send>do local t = coroutine.create (function (t)

local lines = {}

sw = EvaluateSpeedwalk ("%1")

if string.sub (sw, 1, 1) == "*" then
  ColourNote ("white", "red", string.sub (sw, 2))
  return
end -- if

rex.new ("(.+)"):gmatch (sw, 

-- build speedwalk lines into a table

function (m) 
  table.insert (lines, m)
end)


  pause_speedwalk = false  -- no pause yet
  abort_speedwalk = false  -- no abort yet
  speedwalk_thread = t     -- remember this thread

 -- iterate the table, sending each line to the MUD

 for i, line in ipairs (lines) do

 -- see if pausing wanted (global variable set)

  if pause_speedwalk then
    ColourNote ("white", "green", "Speedwalk paused.")
    ret = coroutine.yield ()
    if ret == "abort" then
      ColourNote ("black", "yellow", "Speedwalk abandoned.")
      speedwalk_thread = nil
      return
    end -- abort speedwalk wanted
    ColourNote ("white", "green", "Speedwalk resumed.")
    pause_speedwalk = false
  end -- if

 -- see if aborting wanted

  if abort_speedwalk then
    ColourNote ("black", "yellow", "Speedwalk abandoned.")
    speedwalk_thread = nil
    return
  end -- if

  -- send the speedwalk

   Send (line) 

  -- wait 1.5 seconds

  wait (t, 1.5)

  end  -- of iterating through each speedwalk line

  -- all done!

  ColourNote ("white", "blue", "Speedwalk done.")

  speedwalk_thread = nil

end) assert (coroutine.resume (t, t)) end

</send>
  </alias>

  <alias
   match="pause speedwalk"
   enabled="y"
   send_to="12"
   sequence="100"
  >
  <send>if speedwalk_thread then
  if pause_speedwalk then
    ColourNote ("black", "yellow", "The speedwalk is already paused.")
  else
    pause_speedwalk = true
  end  
else
  ColourNote ("black", "yellow", "No speedwalk is active.")
end


</send>
  </alias>
  <alias
   match="resume speedwalk"
   enabled="y"
   send_to="12"
   sequence="100"
  >
  <send>if speedwalk_thread then
  if pause_speedwalk then
    assert (coroutine.resume (speedwalk_thread, "resume"))
  else
    ColourNote ("black", "yellow", "The speedwalk is not paused.")
  end  
else
  ColourNote ("black", "yellow", "No speedwalk is active.")
end</send>
  </alias>

  <alias
   match="abort speedwalk"
   enabled="y"
   send_to="12"
   sequence="100"
  >
  <send>if speedwalk_thread then
  if pause_speedwalk then
    assert (coroutine.resume (speedwalk_thread, "abort"))
  else
    abort_speedwalk = true
  end  
else
  ColourNote ("black", "yellow", "No speedwalk is active.")
end</send>
  </alias>
</aliases>



- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Ekerim   Sweden  (18 posts)  [Biography] bio
Date Reply #13 on Tue 18 Oct 2005 04:32 PM (UTC)
Message
Ok, I'll add those aliases to my code too for completeness.
They were so simple to do that I left them out.

pausequeue
resumequeue
abortqueue

Ohh...and my code doesn't just handle speedwalking but any commands could be handled (like the spellcasting in the original post :) The speedwalking alias just reuses the queue.



<aliases>
  <alias
   match="pausequeue"
   enabled="y"
   send_to="12"
   sequence="500"
  >
  <send>$pauseQueue = 1;
$world-&gt;note( "#Queue: Paused." );</send>
  </alias>
</aliases>


<aliases>
  <alias
   match="resumequeue"
   enabled="y"
   send_to="12"
   sequence="500"
  >
  <send>$pauseQueue = 0;
$world-&gt;note( "#Queue: Resumed." );</send>
  </alias>
</aliases>


<aliases>
  <alias
   match="abortqueue"
   enabled="y"
   send_to="12"
   sequence="500"
  >
  <send>$pauseQueue = 1;
@cmdQueue = ();
$pauseQueue = 0;
$world-&gt;note( "#Queue: Aborted." );</send>
  </alias>
</aliases>
[Go to top] top

Posted by Peeka   (5 posts)  [Biography] bio
Date Reply #14 on Sun 23 Oct 2005 06:21 PM (UTC)
Message
Okay, so will these scripts work for paths too, which is what I normally use? Usually my paths are aliased as "startinglocation-endingloation".
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


53,285 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]