Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD General Discussion
Loftaris
Adept


Joined: 24 Aug 2004
Posts: 277

PostPosted: Sat Apr 30, 2022 9:24 pm   

Please help with a complex(to me) trigger.
 
<trigger priority="430" id="186">
<pattern>^There is {a|an|two|three|four|five|six|seven|eight|nine} (*){, | h}ere.$</pattern>
<value>

#var currentEnemy %db(@monsterList, %1)
#var @arenaMobPres 1

</trigger>

This works, but only crudely, and only in specific moment..

I'm having a problem with the pattern matching problem. It only works when 1 monster is present, sometimes there could be several. The game output changes too much and I can't figure it out.

There is nobody here. (no mob present)
There is an orc here.
There is a cave bear here.
There is a dog and a fox here.
There is an orc, a female hobgoblin, a lizard woman, two hobgoblins, and a female kobold here.

I really only need to match the first creature and ignore everything else, but I have so many different options I simply don't know how to narrow it down and ignore everything else.

The reason I have to be complicated is because the game is very old, hasn't been updated in probably 25 years (think abandonware) and it doesn't have intelligent input, I can't simply attack female or attack skeleton. I have a full database set up of all the monsters with a value, so if it finds "a female skeleton lord" it will have a value of "lord" so that my attack macro will attack @currentEnemy and output "attack lord"

Please help?

Thank you
Reply with quote
mikeC130
Apprentice


Joined: 03 Jul 2006
Posts: 108

PostPosted: Sun May 01, 2022 5:39 pm   
 
Your trigger will always capture text up to the word "here" because that is the only way the end of the pattern can match - if it found a comma, it would have to be followed immediately by "ere." to match the pattern, so the only thing that CAN match is everything up to the final word here. Unfortunately, it will be tough to fix that with a single pattern because * is "greedy." Although * can match a string length of zero - the pattern A*B will match the text AB with nothing there, it will ALWAYS match the largest string that can be matched, starting from the beginning of the pattern. So even if you added another * to capture everything after that comma, the trigger will still pack everything into the first * and the second one will be null. All you are doing then is stripping off the text for how many and the final word "here," capturing everything else. There may be a way to avoid this, however.

Two questions. The first and most important one is this - Does each monster have a unique "attack" identifier that does not appear in another monster's description? That is, in your example of "female skeleton lord," the word "lord" is the "attack" identifier. Does that word appear in other monster descriptions, where it is NOT also used as the attack identifier (that is, the command "attack lord" would not work to attack that other monster)? In this case, this could be problematic because the word "skeleton" is probably a word used to attack something else as well.

If the attack words ARE unique, then the answer may be relatively simple. You can use a trigger that only looks for that unique identifier. Create a variable as a stringlist, in this case we'll use @monsterlist, and it will hold your names orc|bear|hobgoblin|lizard|kiobold

The pattern:
^There is {a|an|two|three...}*({@monsterlist})*here.$
Will match if any word from your list appears in the sentence. It will, however, capture the LAST monster name in the sentence rather than the first. This leads to the second question - do you HAVE to attack the first monster listed, or is that just a convenient order? If you don't really care about the order in which you attack, then you might start out with this. In a way, this might actually be helpful. In the case of your skeleton lord, it would capture "lord" even if "skeleton" was also a separate monster. The pattern can fail in other cases however, if the name of a monster has more than one "attack name" in it, and the last such name is not the one used for that particular monster (example - skeleton and wolf are both monsters. A wolf skeleton that was attacked using the command "attack skeleton" would work, but if you needed "attack wolf," it would not.)

Mike
Reply with quote
Loftaris
Adept


Joined: 24 Aug 2004
Posts: 277

PostPosted: Mon May 02, 2022 1:18 pm   
 
There are other monsters in the game that re-use words, however it doesn't matter, because they are all just variations of each other, so a female skeleton lord, I've got manually set to lord, but a skeleton warrior lord will also ID to lord. It also doesn't matter what order I attack them in, so matching the last one is absolutely perfectly fine!

And yes, I'm aware of the problem using * and it's greediness, however it was the only way I could make it work. I added the {,| } to force it to only match the first monster and everything else would just be ignored as it would match whatever up to "ere" on purpose, but it was still failing sometimes, however I think I figured that part out because I didn't realized it changed from There is, to there are. But I will try yours, because mine is still not working some of the time.

Thank you very much for your response, it is greatly appreciated!

How do I pull the value from the matched @monsterList in your example? I'm currently using #var testEnemy2 %db(@monsterList, %1) I'm not sure if that's causing it to fail sometimes or it was the pattern matching that was causing my grief.
Reply with quote
mikeC130
Apprentice


Joined: 03 Jul 2006
Posts: 108

PostPosted: Mon May 02, 2022 7:45 pm   
 
The trigger uses () to capture the actual word from {@monsterlist} that is triggered on, so if it triggers on "lord" then the %1 variable will hold "lord". From there you can assign it to another named variable or use it directly. So your monster list will not contain the full monster name, only that part of the name you use to attack it. So, you would use the word "lord" in your monsterlist variable and it will work for your skeleton lord and warrior lord. This way you don't need a database - you capture the name and use it directly for your attack command.

If you haven't already addressed the is/are issue, you can use another stringlist there as well {is|are} will trigger on either, so you can just replace the word "is" and that should take care of it.

Mike
Reply with quote
Loftaris
Adept


Joined: 24 Aug 2004
Posts: 277

PostPosted: Wed May 04, 2022 6:32 pm   
 
mikeC130 wrote:

The pattern:
^There is {a|an|two|three...}*({@monsterlist})*here.$
Will match if any word from your list appears in the sentence. It will, however, capture the LAST monster name in the sentence rather than the first. This leads to the second question - do you HAVE to attack the first monster listed, or is that just a convenient order? If you don't really care about the order in which you attack, then you might start out with this. In a way, this might actually be helpful. In the case of your skeleton lord, it would capture "lord" even if "skeleton" was also a separate monster. The pattern can fail in other cases however, if the name of a monster has more than one "attack name" in it, and the last such name is not the one used for that particular monster (example - skeleton and wolf are both monsters. A wolf skeleton that was attacked using the command "attack skeleton" would work, but if you needed "attack wolf," it would not.)

Mike


So this was fine until I encountered many different monsters which spilled over onto a new line and it couldn't recognize a giant(cr)bat .. Is it difficult to have it stop match after the first one?
Reply with quote
mikeC130
Apprentice


Joined: 03 Jul 2006
Posts: 108

PostPosted: Thu May 05, 2022 12:35 pm   
 
I believe that capturing the first monster is going to be a pain. I have read that you can use regex to combine multiple lines into a single line to capture into a variable, but you'd have to have a trigger checking every line to do that, and I know very little about regex triggers. The easiest thing to try would be to just eliminate everything after capturing the attack word from the monsterlist. Depending on how the room descriptions, etc., work, there might be a risk of false positives, however, as your trigger is less specific.

^There is {a|an|two|three...}*({@monsterlist})

This will still capture the last monster on the line, but so long as at least one appears in the first line, you should be good.

Alternatively, the trigger
({@monsterlist}}*here.$
Would trigger on the first monster on the last line - it will not fire if the line break is between the monster and the word 'here', however. It also seems much more likely to make false matches.

Mike
Reply with quote
Loftaris
Adept


Joined: 24 Aug 2004
Posts: 277

PostPosted: Fri May 06, 2022 12:44 am   
 
mikeC130 wrote:
I believe that capturing the first monster is going to be a pain. I have read that you can use regex to combine multiple lines into a single line to capture into a variable, but you'd have to have a trigger checking every line to do that, and I know very little about regex triggers. The easiest thing to try would be to just eliminate everything after capturing the attack word from the monsterlist. Depending on how the room descriptions, etc., work, there might be a risk of false positives, however, as your trigger is less specific.

^There is {a|an|two|three...}*({@monsterlist})

This will still capture the last monster on the line, but so long as at least one appears in the first line, you should be good.

Alternatively, the trigger
({@monsterlist}}*here.$
Would trigger on the first monster on the last line - it will not fire if the line break is between the monster and the word 'here', however. It also seems much more likely to make false matches.

Mike


Yeah, it was breaking in the middle so I'd see a skeleton
warlord shaman
or some such junk. I found a way to extend the display to 130 characters, I think it was 80, so I'm HOPING this solves my problem. Otherwise, I'll try your example.

Thank you for all your help, it's greatly appreciate!
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD General Discussion All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net