<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient
[
  <!ENTITY speedwalk_alias "!*" > 
  <!ENTITY pause_speedwalk_alias "pause speedwalk" > 
  <!ENTITY resume_speedwalk_alias "resume speedwalk" > 
  <!ENTITY abort_speedwalk_alias "abort speedwalk" > 
  <!ENTITY help_speedwalk_alias "help speedwalk" > 
  <!ENTITY timeout_secs "10" > 
  <!ENTITY delay_secs "0.5" >
  <!ENTITY exits_trigger 
      "^((?P<exits>\\[Exits\\: .+\\])|(.*)Alas, you cannot go that way\\.)$" > 
]>

<!-- Saved on Monday, October 24, 2005, 7:21 AM -->
<!-- MuClient version 3.67 -->

<!-- Plugin "Slow_speedwalk" generated by Plugin Wizard -->

<!--
Customise the entities above to modify for the exact MUD output you get.

speedwalk_alias - the alias you want to invoke a speedwalk (eg. !*)

pause_speedwalk_alias - the alias you type to pause a speedwalk (eg. 'pause speedwalk')

resume_speedwalk_alias - the alias you type to resume a speedwalk (eg. 'resume speedwalk')

abort_speedwalk_alias - the alias you type to abort a speedwalk (eg. 'abort speedwalk')

timeout_secs - the time to wait for a new room "exits" line to arrive (eg. 10)

delay_secs - the time to wait after each speedwalk succeeds, before doing another one (eg. 0.5)

exits_trigger - this detects either that we have gone to a new room, or we can't move

In the exits_trigger any backslashes have to be doubled, as the first one is processed by Lua,
so we need two to reach the regular expression parser.

The named wildcard portion (?P<exits> ... ) is designed to be tested in the script
so that if it is not empty we know we hit an exits line, rather than "you cannot go that
way". eg. [Exits: North South]

-->

<!-- Version 2 uses wait.lua for extra compactness -->

<muclient>
<plugin
   name="Slow_speedwalk"
   author="Nick Gammon"
   id="56c9c5763d0c9c6ccf1e5b60"
   language="Lua"
   purpose="Speedwalks, waiting for each room to arrive"
   date_written="2005-10-24 07:16:09"
   date_modified="2008-06-4 06:56:09"
   requires="3.67"
   version="2.0"
   >
<description trim="y">

Usage
-----

! &lt;speedwalk&gt; - walks in that direction, eg. ! 5n 3w

&pause_speedwalk_alias; - pauses the speedwalk so you can do something else

&resume_speedwalk_alias; - resumes a paused speedwalk

&abort_speedwalk_alias; - aborts the current speedwalk

&help_speedwalk_alias; - this message


The speedwalk waits for the appropriate "Exits" message to appear so it knows it has reached a new room.

If it receives a "cannot go that way" message, the speedwalk is aborted.

If an "exits" message does not appear within 10 seconds the speedwalk is aborted.
</description>

</plugin>

<!--  Aliases  -->

<aliases>
  <alias
   match="&speedwalk_alias;"
   enabled="y"
   script="func_handle_speedwalk"
  >
  </alias>
  
  <alias
   match="&pause_speedwalk_alias;"
   enabled="y"
   script="func_pause_speedwalk"
  >
  </alias>
  
  <alias
   match="&resume_speedwalk_alias;"
   enabled="y"
   script="func_resume_speedwalk"
  >
  </alias>
  
  <alias
   match="&abort_speedwalk_alias;"
   enabled="y"
   script="func_abort_speedwalk"
  >
  </alias>

  <alias
   match="&help_speedwalk_alias;"
   enabled="y"
   script="func_help_speedwalk"
  >
  </alias>
    
</aliases>

<!--  Script  -->

<script>

require "tprint"
require "wait"
require "getlines"


-- main function called when you type a speedwalk

function func_handle_speedwalk (name, line, wildcards)
    
  wait.make (function ()  --- coroutine below here
  
  sw = EvaluateSpeedwalk (wildcards [1])
  
  if string.sub (sw, 1, 1) == "*" then
    ColourNote ("white", "red", string.sub (sw, 2))
    return
  end -- if
  
  
  pause_speedwalk = false  -- no pause yet
  abort_speedwalk = false  -- no abort yet
  speedwalk_thread = coroutine.running ()  -- remember this thread
  
  -- iterate the speedwalk string, line by line, sending each line to the MUD
  
  for walk_line in getlines (sw) do
    
    if string.match (walk_line, "^%s*$") then
      break
    end -- empty line - probably end of speedwalk
    
    -- 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 (walk_line) 
    
    -- now wait for an appropriate response
    
    line, wildcards = wait.regexp ("&exits_trigger;", &timeout_secs;)
    
    -- check for timeout
    
    if not line then
      ColourNote ("white", "red", "Speedwalk timed-out")
      speedwalk_thread = nil
      return  -- give up
    end -- if
    
    -- check we didn't get told it was impossible
    
    if wildcards.exits == "" then
      ColourNote ("white", "red", "Speedwalk cancelled")
      speedwalk_thread = nil
      return  -- give up
    end -- if
    
    -- pause before doing another if wanted
    
    if &delay_secs; &gt; 0 then
      wait.time (&delay_secs;)
    end -- if pause wanted
      
  end  -- of iterating through each speedwalk line
  
  -- all done!
  
  ColourNote ("white", "blue", "Speedwalk done.")
  
  speedwalk_thread = nil
  
  end) -- end of coroutine
end -- function func_handle_speedwalk

-- called to pause the current speedwalk
function func_pause_speedwalk ()
  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
end -- func_pause_speedwalk

-- called to resume after a pause
function func_resume_speedwalk ()
  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
end -- func_resume_speedwalk

-- called to abort the speedwalk  
function func_abort_speedwalk ()
  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
end -- func_abort_speedwalk

function func_help_speedwalk ()
  world.Note (world.GetPluginInfo (world.GetPluginID (), 3))
end

DoAfterSpecial (1, 'ColourNote ("white", "green", "Slow speedwalk plugin installed.")', 12);

</script>

</muclient>
