Need help creating a speedwalk system

Post Reply
Bounces
Posts: 18
Joined: Sat Dec 26, 2009 5:44 am

Need help creating a speedwalk system

Post by Bounces »

Hello,

For the mud I play there is a online guide that gives a series of speedwalk directions to locations in the mud. The format of these directions are {# of steps}<cardinal dir> repeat.

So for example, one path might be:

15e5s2e2s
representing go 15 east, 5 south, 2 east, and 2 south

While another might be:

9sws3ws2w2s2w3sws5w2sws2w3s6wswn3ws4wnwsw2n3w3nw5n2wn7w2nwsws3wndn2e4n8ws
which is a chain I will not expand for you, since it's long, but you get the point.

I need an alias or script of some time that can recognize this speed dirs (maybe by a special character I put in front of them, I am partial to the tilda (~) and then expand them into a chain that the mud will accept. Might need a char at the end to let the script know the dirs are done to...not sure

For example, that first speed walk I gave would need to output as:
e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;s;s;s;s;s;e;e;s;s

I am figuring probably a while loop that concatenates the directions into a long string and then sends that string as an output, but I am not skilled enough in lua code or regular expressions to be able to build it myself.

Can a script kiddie out there help me? It would be super keen.

Thanks!

-The Bouncy One.

User avatar
Heiko
Site Admin
Posts: 1548
Joined: Wed Mar 11, 2009 6:26 pm

Re: Need help creating a speedwalk system

Post by Heiko »

1. You need a command queue that's get called by a timer that schedules your next move. The time will depend on how fast your MUD allows you to walk. Technically, this queue consists of a simple function that gets called by a timer object when the timer fires and a table that holds your direction commands as single elements.
2. You make an alias that parses the speed walk command and translates it into single direction commands and stores them in the above command queue table. If you get 15e you insert 15 east commands into your queue. When the parsing is done and the queue has been updated, enable the speedwalk timer. When the queue is empty, disable the speedwalk timer.
3. When your script is finished, you should post it in the package section as there have been similar requests in the past.
4. You can store your speed walks as text files on harddisc and load them according to where you want to walk - or you could store them in an sql database. You can turn this concept into a complex autowalker bot.

User avatar
Heiko
Site Admin
Posts: 1548
Joined: Wed Mar 11, 2009 6:26 pm

Re: Need help creating a speedwalk system

Post by Heiko »

Personnally, I would use a simpler and much more powerful approach. Simply record your commands in a macro recorder while playing and write your commands to disc as a simple text file containing one command per line as entered in the keyboard/keypad etc.. The advantage is that it also includes other commands such as buy xy, ask xyz, wait 5 etc.. You can expand your command queue to include tempTriggers and Lua code to do such things as wait for a ferry to arrive or act on some npc's actions.
This goes in the direction of writing bot scripts.

To make a simple command recorder you make an alias that writes your last command to a text file. Your last command is stored in the variable "command". To write text files see the Lua io library -> sticky Lua tutorial topic in the forum.

Iocun
Posts: 174
Joined: Wed Dec 02, 2009 1:45 am

Re: Need help creating a speedwalk system

Post by Iocun »

It depends a lot on the exact specifics of your mud.
Specifically we don't know the following:

- What kind of directions can appear in such a string? Do only n/e/s/w/d (and presumably u) exist? Or are there also ne/se/sw/nw or any kind of other directions? And if so, how would in such a string "walk northeast once" be separated from "walk north once then walk east once"?

- Does your mud allow speedwalking without any tempo limits (which would make it very simple), or, as Heiko mentioned, is there a speed limit that you need to take into account?


For now, based on what you posted, I just assumed that there is no speed limit and that the only directions are n/e/s/w/d/u, and that, if a direction -doesn't- have a number in front of it, that means you walk that direction once.

In this case, there's a rather simple solution:

Alias: Speedwalk
Pattern: ^~([0-9neswdu]+)$
Script:

Code: Select all

for count, direction in string.gmatch(matches[2], "([0-9]*)([neswdu])") do		
	count = (count == "" and 1 or count)
	for i=1, count do send(direction) end
end
This will go through every combination of numbers (or no number) followed by a single one of the letters n, e, s, w, d or up, then send the letter as often to the mud as the number in front of it specifies, or once if there's no number.

If you'd rather have this script concatenate the commands to a single string and then send this string to the mud, this would be a simple fix as well, but I don't really see any advantage in that.


If your mud does have a tempo limit on how fast you can walk:

In this case, you'll have to change the alias somewhat. Leave the pattern as it is. Create a script that defines the variable "speedwalklist = {}". You don't -have- to do this, but I like having all my variable definitions in separate scripts.

Then make your speedwalk alias execute this script:

Code: Select all

speedwalklist = {}
local delay = 0.5

function speedwalktimer()
	send(speedwalklist[1])
	table.remove(speedwalklist, 1)
	if #speedwalklist>0 then
		tempTimer(delay, [[speedwalktimer()]])
	end
end

for count, direction in string.gmatch(matches[2], "([0-9]*)([neswdu])") do      
   count = (count == "" and 1 or count)
   for i=1, count do speedwalklist[#speedwalklist+1] = direction end
end

speedwalktimer()
This will first reset your speedwalklist, then define a delaying function you'll need later. (You can also put this function in a separate script, if you prefer.) The local variable "delay" contains the number of seconds you have to wait before moving. Change this to what is appropriate for your mud.

The for loop has stayed almost the same, with the difference that now, instead of sending the directions directly to the mud, you are writing them to the table "speedwalklist".

Then the alias starts the speedwalktimer() function, which executes the first direction from the list, removes this direction from the list, checks whether there are any more directions, and if so, calls itself again recursively with a delay.

Bounces
Posts: 18
Joined: Sat Dec 26, 2009 5:44 am

Re: Need help creating a speedwalk system

Post by Bounces »

Iocun wrote:It depends a lot on the exact specifics of your mud.
Specifically we don't know the following:

In this case, there's a rather simple solution:

Alias: Speedwalk
Pattern: ^~([0-9neswdu]+)$
Script:

Code: Select all

for count, direction in string.gmatch(matches[2], "([0-9]*)([neswdu])") do		
	count = (count == "" and 1 or count)
	for i=1, count do send(direction) end
end
This will go through every combination of numbers (or no number) followed by a single one of the letters n, e, s, w, d or up, then send the letter as often to the mud as the number in front of it specifies, or once if there's no number.
My mud does not have a tempo limit, and it only has the prime cardinals plus up and down.

Plugged it into mudlet and it works perfectly...thanks!

Bounces
Posts: 18
Joined: Sat Dec 26, 2009 5:44 am

Re: Need help creating a speedwalk system

Post by Bounces »

This script we built works great! Iocun thanks so much for the help.

Question now, I need to build a reverse script as well. Essentially where it starts from the end and interprets the reverse path and sends it. I would need a special character to denote the beginning of a path to reverse...maybe just a double tilda ~~?

Anyways, is there an easy way to do that?

Iocun
Posts: 174
Joined: Wed Dec 02, 2009 1:45 am

Re: Need help creating a speedwalk system

Post by Iocun »

Sure, that's relatively simple.

There are mainly two steps involved in that: First, reversing the directions string. Second, exchanging each individual direction with their opposite (so that "n" becomes "s", "d" becomes "u" etc.).

Pattern: ^~~([0-9neswdu]+)$
(This is the same as before, just with an additional tilde.)
Script:

Code: Select all

local reversedir =	{
						n = "s",
						e = "w",
						s = "n",
						w = "e",
						u = "d",
						d = "u"
						}

for direction, count in string.gmatch(matches[2]:reverse(), "([neswdu])([0-9]*)") do      
   count = (count == "" and 1 or count)
   for i=1, count do send(reversedir[direction]) end
end
Here, we first define a list of reverse directions, so we can look up which direction we have to exchange for which.
Then we again iterate through the string, this time reversed with the "reverse()" function. We also have to exchange the pattern we're looking for to look for the directions before the number of steps now.
Finally, instead of sending the direction directly, we look up the direction in the "reversedir" table and send its value.

Bounces
Posts: 18
Joined: Sat Dec 26, 2009 5:44 am

Re: Need help creating a speedwalk system

Post by Bounces »

Works great...wow...you are really good at this.

I had no idea there was a reverse function to flip the string...that is excellent.

Okay, one final question, and then speedwalking will be done...is there a way to call an alias from another alias? For example, if I wanted to actually save in the profile my most often used speedwalk paths by the zone name and then pass that path to the speedwalk alias is that possible? And if so how?

I will give an actual example. One of the paths I posted above is to Meadowcreek. It is a long walk but I go there often. The path 9sws3ws2w2s2w3sws5w2sws2w3s6wswn3ws4wnwsw2n3w3nw5n2wn7w2nwsws3wndn2e4n5ws2e.

Is there a way to save an alias (say like ^~meadowcreek$) and that alias passes the the speedwalk alias we built the string ~9sws3ws2w2s2w3sws5w2sws2w3s6wswn3ws4wnwsw2n3w3nw5n2wn7w2nwsws3wndn2e4n5ws2e?

Iocun
Posts: 174
Joined: Wed Dec 02, 2009 1:45 am

Re: Need help creating a speedwalk system

Post by Iocun »

It is possible, with the expandAlias() function, but that's not the recommended approach. Aliases are primarily meant to be called from commands you enter manually, and not from other aliases/triggers/scripts, because the latter would be relatively inefficient in comparison to calling functions.

So that's what I would do here: Turn our speedwalk alias into a function within a script and then use aliases to call that function. This is done rather easily. Just copy and paste the alias contents to a separate script, and add "function speedwalk(walkstring)" on top, and an "end" on the bottom. Then replace all occurences of "matches[2]" within the script with "walkstring".
E.g., the first function would then look like this:

Code: Select all

function speedwalk(walkstring)
	for count, direction in string.gmatch(walkstring, "([0-9]*)([neswdu])") do      
		count = (count == "" and 1 or count)
		for i=1, count do send(direction) end
	end
end
Do the same with the reverse speedwalk, giving it another name (e.g. "reversespeedwalk()").

Then you can simply call these functions with your alias.
E.g. make one alias ^~([0-9neswdu]+)$ to execute speedwalk(matches[2]), and an alias ^~~([0-9neswdu]+)$ to execute reversespeedwalk(matches[2]). This will allow you to use patterns such as ~2nen3w or ~~e3n3e as speedwalk aliases like before.
Then you can make more aliases such as ^~meadowcreek$ to execute:
speedwalk("9sws3ws2w2s2w3sws5w2sws2w3s6wswn3ws4wnwsw2n3w3nw5n2wn7w2nwsws3wndn2e4n5ws2e").

You could even create a table to contain your speedwalks to make it even neater.
E.g.: Make a script that contains something like:

Code: Select all

speedwalktable =	{
			meadowcreek = "9sws3ws2w2s2w3sws5w2sws2w3s6wswn3ws4wnwsw2n3w3nw5n2wn7w2nwsws3wndn2e4n5ws2e",
			someotherplace = "15n2ese",
			thirdplace = "w2n3en4e2w3s"
			}
Then you can create an alias with the pattern ^~(\w+)$ to execute: speedwalk(speedwalktable[matches[2]])
So when you type ~meadowcreek, it will look up the speedwalk in the table and execute it, likewise for ~someotherplace, or ~thirdplace. And you can make an alias called ^~~(\w+)$ to execute reversespeedwalk(speedwalktable[matches[2]]), for the reverse paths.

Post Reply