Ok, say there's a line like this: Yuna Concordia, The Archsummoner is here. She wields an elemental staff in her right hand.
Now, my problem is that that line can have a line break where ever there's a space (I am not sure if it replaces the space or it's put right after it but that's not too important). For example it could look like any of these:
Yuna
Concordia, The Archsummoner is here. She wields an elemental staff in her right hand.
Yuna Concordia,
The Archsummoner is here. She wields an elemental staff in her right hand.
Yuna Concordia, The Archsummoner is here.
She wields an elemental staff in her right hand.
Yuna Concordia, The Archsummoner is here. She wields an elemental staff in her
right hand.
And so on.
I tried to make a regex pattern for it and failed miserably. I had two triggers, one for the one line version, and one for the two line version (because Mushclient doesn't like it when I make a two line trigger that's caught in one). But I can't figure out how to make the two line version work properly.
What I have so far is something like ^She( |\n)wields( |\n)(.*\n?)+( |\n)in( |\n)her( |\n)right|left hand\.$
But it still catches the one line version unfortunantly and that makes Mushclient cry. So I was wondering if anyone new some clever way of catching something like this.
Basically I made each space into ( |\n) which then matches on the space *or* the newline. This works for me provided I don't have a space before the newline. If so, you would have to modify it a bit.
I also used the "dotall" feature ( which is (?s) at ths start) which lets the dot match on newlines, in case the line break comes inside the name of the weapon.
Ooer, I'll try that. Also, I say Mushclient doesn't like it because if it is on one line but it's a two line trigger, well, Mushclient fires the same trigger twice on the same line. It's really annoying.
If \Z is supposed to be an endline I can't use that
Why can't you use it?
From the regular expression documentation:
\Z matches at end of subject or before newline at end
\z matches at end of subject
Using \z at the end guarantees a "tail match". This stops it matching on the same line twice. Without it, if you matched over (say) 10 lines, and the line appeared twice in the 10 lines, you would get 2 matches.
Quote:
Yours is still firing multiple times on one line
It isn't firing multiple times for me. Did you change it? Using mine, it fires once per matching line. What are you testing it with? In my case I sent:
Yuna Concordia, The Archsummoner is here. She wields an elemental staff in her right hand.
I don't see how it can match multiple times, unless you have put the trigger in twice.
Well, it will do that. You expect it. If you have a regexp that might match one line, and tell it to match over 10 lines, and don't "anchor" it to the start or end of those 10 lines, then potentially you will get 10 matches, as the matching line "ripples" back through the batch of 10.
You need to find a way of anchoring it, either to the start or end of the multi-line expression.
*sigh* There's no way to anchor it. Oh well, I guess I'll just have to live with it.
I was hoping for some way to specify in the regex at at least one new line should be caught or something. It'd be nice if Mushclient itself did that so a 2 line trigger must be on two lines. But, I guess I can live with it. :p
I'm not quite sure what you mean by that. If you specify a multi-line trigger as matching over 2 lines, and have a newline in the regexp, then it will indeed match exactly 2 lines.
Like in your trigger example, every \n is in parentheses and a space can replace it. Therefore, if I set it as two line, I wanted it to only match if there was at least one \n in the actual matching text, not just if the regex matched.
Like say I have this trigger: Hide\n?you\n?thief
And I put it in a multiline trigger and set it to catch on two lines.
Well, it'd be nice if it did catch on two lines only.
Ie:
Hide
youthief
Why doesn't that work? OK, it's easy for the simple case and would be very long for the longer case, but something similar probably would work for you.
I am trying to extract the name of every person in the room (which comes with the title sadly), and what they're wielding.
Then there are also items that are in the room that show up in the description and I want to get all those too.
Then there are NPCs that show up in the room description.
Basically, I want to grab everything useful from a big block of text.
See, when you look in Achaea it gives you something like this:
Postal Office of Hashan.
A runic totem is planted solidly in the ground. A mottled Mhojave desert falcon glides effortlessly to and fro. A sigil in the shape of a small, rectangular monolith is on the ground.
You see a single exit leading northwest.
Except when there's people in there it's more complicated, like:
The Crossroads.
Occasional drops of rain fall to the ground from a sky grey with pregnant clouds. A runic totem is planted solidly in the ground. There are 10 fierce viragos here. This shrine is crafted into the form of three tall women standing back to
back in a tight circle, hands clasped together at their sides. A sewer grate looms darkly beneath your feet. An emaciated and skeletal dracolich lurks in the shadows. Shimmering an opalescent, milky white, this iridescent pearl bears the
words "Suggestion Box" painted in flowing silver script upon its smooth surface. There are 7 mounted tsalmaveths here. A sigil in the shape of a small, rectangular monolith is on the ground. There are 4 hooded nocturnis here. A ludicrously
bright green blanket has been placed here to clash with everything. Flapping its massive wings, a dire bat flies overhead. A hefty glass mug has been left here. A flame-charred chariot pulled by demonic goats stands here. Spreading its
majestic golden wings, a giant eagle searches the ground with piercing eyes. A mottled Mhojave desert falcon glides effortlessly to and fro. A blue marble bench with a covering of dark blue satin is here. Standing on a pedestal of silver,
an Orb of Confinement has been carefully constructed here. Flaze is here, sprawled on the floor. Brother of the Red Lotus, Jasato Kuriskagi is here. He wields a steel Theran broadsword in each hand.
You see exits leading north, east, southeast, south, southwest, and northwest.
As you can see, Achaea preparses the description into a big paragraph, that's why I can't assume there's an end line at the end of a sentence, and I must assume any space can be replaced with a newline.
Although I haven't 100% checked this, I think to be accurate that Achaea does not replace spaces with newlines, but inserts newlines after spaces when its wrapping.
Yeah, Im going to use UDP to send it to a C++ program and have it parse it into sentences. Then start splitting the sentences to pieces one at a time. Im worried about the speed penalties of doing this though.
I wouldn't worry about the speed consequences of this. All you're doing is moving some bytes to a running program, which will split into sentences. All of this is quite cheap, computationally.
I'm curious though why you're sending this to an external program, and why you chose UDP. Why not just have a running Lua script that takes care of this for you?
C++ classes, OOP design for my combat system. Also, GUI components that I can't create inside of MUSHClient. And it's faster for processing complex tasks. I chose UDP because I know nothing about COM objects and UDP was the only other method that people have mentioned to send data to a third (second?) program. I also could have written DLLs for Lua in C but frankly I felt this was also unnecessary considering I could just use a full blown executable with gauges, buttons, and the works.
Also, less logical, but I know C++ is fast and I feel more comfortable writing complex and computationally expensive functions in it than I would in any scripting language.
Oh, I didn't know you were doing all that other stuff. In that case it makes sense to have C++, especially if you've already written all this other code for it.
I was surprised to hear you say UDP, and not just plain old normal TCP sockets, examples of which abound for Winsock. UDP seems to be a slightly more unusual route to me.
FWIW, Lua is an extremely fast scripting language. It is more than sufficient for any kind of processing people would be doing for a MUD. People can render 640x480 images at hundreds of frames per second with Lua doing the grunt-work; surely that is sufficiently fast for a measly little text parser? :-)
(Don't forget that text parsing is really a very inexpensive task in general. If you don't believe me, write some perl scripts that chunk over megabytes of data and do something (un)interesting. You might be surprised by the speed results.)
I use UDP because of the MUSHClient supplied functions for sending and receiving UDP packets. Otherwise, I have no idea how I would establish a connection between MUSHClient and my program. :(
And I distrust string operations because of my experience in Java. It was...incredibly slow with the strings. Concatenating, and everything else really ate up my memory and while I found the string buffers in Lua to be exceedingly simple to use I have since distrusted string operations.
Do you mean Java or Javascript? I've not had problems you describe using strings in Java. There are some gotchas, especially if you're building very large strings a few characters at a time, in which case you actually want to use a StringBuffer (or StringBuilder in 1.5 I think it's called). That way, you allocate a chunk of memory once, and then fill it up. But, this also applies to C++ strings.
But again, I'd be quite surprised if you had problems with strings in Java. I wrote a program for work that takes several hundred session logs, reads them all in, does black magic on them involving very many string operations per session, and the blocking part is disk access, not string manipulation.
Yeah, Im going to use UDP to send it to a C++ program and have it parse it into sentences
Personally I wouldn't use UDP in this application. A UDP packet is limited in size (something around 512 bytes) so a long description would need to be split between packets, reassembled at the receiving end, and so on.
... I did 200,000 string.find operations (that is, the Lua regexp) in one second, so I don't think speed will be an issue. Also, I recently wrote an application in Lua that read in all my old email messages, parsed the headers, and added them to an SQL database. The whole thing ran really fast, processing something like 5,000 emails in a minute or so. There was no problem with string management.
Might I suggest a way to make this easier? (wouldn't want to take away from your project though Nexes, hehe)
CONFIG SCREENWIDTH 250
and set MushClient to do your wrapping for you... It won't be perfect, since descriptions are often longer than 250 characters, but it might make things a bit easier.
Hmm, I guess I would have to figure out the max length of a UDP packet, and figure out how many charachters that translates into. If it's above 240 then it shouldn't be a problem, otherwise maybe your method would be better Nick.
Well now. Achaea now allows you to CONFIG SCREENWIDTH 0, so try that if you'd like. However I'd think it'd be much simpler to target a person IE 'set summoner Yuna/<person>', and have a trigger match on the line that the name is in. In Cyan or whatever you use for a 'player' color. Thus, when the trigger matched you could make the REGEX '(She|he) is wielding (a|an) (.*?) in (his|her) (right|left) hand
.' I don't know how you'd account for a newline in the description however, maybe use the REGEX to do a few ( |\n) ??
Good Luck
I read about the screenwidth 0 thing the moment the put it in and I love it.
Actually that brings Nick's point even more relevant since I definitely will run into that limit on packet size now, at least if I send it all in one packet.
Anyways, the reason I don't want to do it your way, Rakon, is because that's not quite what I wanted to do. The trigger pattern you mentioned is exactly what I wanted to avoid, since it fires multiple times if it comes in less lines than I set the trigger to capture. Also I don't want to limit the capture to only my target.
Quote: The trigger pattern you mentioned is exactly what I wanted to avoid, since it fires multiple times if it comes in less lines than I set the trigger to capture. Also I don't want to limit the capture to only my target.
The reason for setting a target is so that it only matches the line the targets name is in. Thus, it should not fire multiple times unless you QL more then once. Really, without defining a target for the system to look for, won't you in essence, overwrite the variables everytime it makes a match???
Or am I utterly confused as to what you are trying to do??
Meh, it's not really important any more since the screenwidth 0 option is in, but before, if you had a regex pattern set to multiple lines, say 3, and it was caught on one line, it would fire 3 times anyways for that single line. The reason I posted here was to figure out if there was a way around this and there isn't so I decided to simply start parsing the text in a big block.