Saurven
09-01-2014, 04:21 PM
I altered a spellbot script to do what I wanted it to do on Hell, and at one time I remember how all this worked. I'm not so sure anymore.
Could anyone take a minute to tell me what the individual commands in this code does? I'm a bit confused as to why all the ?'s and such are in these lines.
I understand that "person", "pervar", and "iwanter" are each used as variables. I'm having trouble remembering how the names of the individuals are captured from the script, and cannot remember why it was written in this dreadfully complicated manner.
person = matchwait /(?:^Speaking .*to )?(you, )?([A-Z][a-z]+).*(whispers,|asks,|exclaims,|says,).*?(?i)(disk| blurs|spells|haste).*?(?:\.|\!|\?)\"/i
pervar = person.scan(/(?:^Speaking .*?to )?(you, |[A-Z][a-z]+, )?([A-Z][a-z]+).*?(whispers,|asks,|exclaims,|says,)(?i).*?(?:di sk|blurs|spells|haste).*?(?:\.|\!|\?)\"/i)
iwanter = $2
Tillmen
09-01-2014, 09:43 PM
person = matchwait /(?:^Speaking .*to )?(you, )?([A-Z][a-z]+).*(whispers,|asks,|exclaims,|says,).*?(?i)(disk| blurs|spells|haste).*?(?:\.|\!|\?)\"/i
This line is checking each incoming game line against the regular expression. When a game line matches, it sets the person variable to be that game line.
pervar = person.scan(/(?:^Speaking .*?to )?(you, |[A-Z][a-z]+, )?([A-Z][a-z]+).*?(whispers,|asks,|exclaims,|says,)(?i).*?(?:di sk|blurs|spells|haste).*?(?:\.|\!|\?)\"/i)
This line is matches the previously found game line against the regex again, and sets the pervar variable to be an array of arrays of the captures of the regex.
iwanter = $2
This line sets the iwanter variable to be the second capture of the regex.
http://www.regular-expressions.info/ has all the info on.. regular expressions. There's three types of questions marks in this regex. The first one is making a group into a non-capturing group. Captures show up as $1, $2, etc after trying to match a regular expression.
For example, here's an exec script that's trying to find a number in a string, but it only wants a number if it comes after foo or bar:
;e "blah 349 foo 123 blah" =~ /(foo|bar) ([0-9]+)/; echo $1; echo $2
[exec1: foo]
[exec1: 123]
Here's the same script, but this one doesn't capture foo or bar, since we supposedly don't care which word comes before the number, as long as it's one of those two.
;e "blah foo 123 blah" =~ /(?:foo|bar) ([0-9]+)/; echo $1
[exec1: 123]
The next kind of question mark is the most common usage of it. It just makes the thing before it optional.
The other question mark comes after a .*
A dot in a regex matches any character. A star means that the thing before it can happen zero or more times. So, a .* will match even if there's nothing there, or if there's any amount of anything. That means that it's already pretty much optional, so a question mark after the .* makes it a lazy match, meaning while it tries to match the whole regular expression, the .*? will take up as few characters as possible while still making the whole thing match.
So here's the problems that I notice:
person.scan is the wrong thing to use in this case. It's useful when the regex matches a line multiple times. For example:
;e echo "foo 123 bar 456 something 789".scan(/[0-9]+/).inspect
[exec3: ["123", "456", "789"]]
In this case, someone could whisper to you like so:
>whisper to whoever disk." Someone whispers, "disk."
Noob whispers, "disk." Someone whispers, "disk."."
And pervar would be [[nil, "Noob", "whispers,"], [nil, "Someone", "whispers,"]]]
There's a nil in there because (you, |[A-Z][a-z]+, )? is an optional capture group, and it wasn't used.
The regex changes slightly from the first one to the second, and this group becomes a non-capture group so it's missing from the pervar variable: (?:disk|blurs|spells|haste)
iwantar would be set to "Someone", because that was the second capture group of the last matched regex.
This may seem like an unlikely problem, but it does happen that someone notices you running a bot and tries to screw with it. The most common way to try is to just copy/paste what they believe the script is looking for, and in this case it would work (with the exception that this script doesn't appear to work at all). The result could be 11 wasted mana, or it could be your bot spamming and harassing someone and you dieing a bunch because of it.
Here's more or less what Alfred uses. In Alfred's case, "do stuff" is just pushing the name and command into an array to be processed by another script, so that this loop won't miss any requests while it's processing a request.
loop {
line = get
if (line =~ /^(?:The ghost of )?([A-Z][a-z]+) whispers, "(.+)"/) || (line =~ /^Speaking.*? to you, (?:the ghostly voice of )?([A-Z][a-z]+) (?:says|exclaims|asks), "(.+)"/)
name = $1
command = $2
# do stuff
end
}
Saurven
09-01-2014, 10:31 PM
As always, you are the man. Thank you, Tillmen.
The $1 and $2 was seriously throwing me off, trying to figure out how it assigned which was 1 and which was 2. I could look at the line and tell which was which, just not why. Thanks, man.
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.