Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ General ➜ Word count in string/string manipulation question

Word count in string/string manipulation question

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Chaosmstr   (21 posts)  Bio
Date Fri 05 Sep 2014 06:53 PM (UTC)
Message
Mushclient 4.94 with LUA

So, I'm an old time Wintin user and it's time to move to something new, and Mushclient seems to offer quite a lot.

Having some growing pains trying to convert the programming language (Wintin is very Basic-like and easy)

I'm trying to make a trigger that will grab specific items from a corpse.

I'm on an old DIKU based game (mud.finalchallenge.net 4000 if your interested) and I get lists like this:

The corpse contains:
(Moderate magic) a sickle
(Moderate magic) a bright white potion with purple swirls
(Potent magic) a pair of hardened leather breeches
an axe
a mushroom
80 coins

I want the magic items and the gold (the gold has already been figured out, that's an easy one) while leaving the rest.

The problem comes in the form of the item names.
They can be 2-12 words long and the last word in the name isn't always a usable keyword.
For instance, typing 'get swirls' for the potion wont work, but bright, white, purple and potion are valid. Hardened won't work, but leather and breeches will.

In Wintin, my thought was to try and count the # of words in the name (if 6 words, 'get %5 corpse', if 2 words 'get %2 corpse') but I've hit programming limits with that.

Seems that
(Moderate magic) %1 %2 (no space after %2)
will catch the sickle ok, but on the breeches will turn %2 into the rest of the string ('pair of hardened leather breeches') which I cant use in the 'get %2 corpse' command (more than a single keyword).

But if I put a space after %2 then it won't recognize the sickle, as there is an EOL char that I cannot read/process.

So far all I have is:
<triggers>
<trigger
enabled="y"
match="(Moderate magic) *"
send_to="9"
sequence="1"
variable="modtxt"
>
<send>%1</send>
</trigger>
</triggers>

So, I have a string of varying length that I need to be able to process in some fashion to pull out a word or two that could be used as a keyword, ignoring obvious non-keyword words (a, the, pair, etc).

And the REALLY tricky part is that I could also find:
(Moderate magic) a pair of hardened leather pants
in the same corpse, meaning there is a HUGE list of keywords for these items.

So I know WHAT I want to do, I don't know to finagle the programs to do what I want.

Anyone have suggestions for a Mushclient newbie?


CM
Top

Posted by Nick Gammon   Australia  (23,165 posts)  Bio   Forum Administrator
Date Reply #1 on Fri 05 Sep 2014 10:47 PM (UTC)

Amended on Sat 06 Sep 2014 12:09 AM (UTC) by Nick Gammon

Message
Fortunately you have Lua now, and you should love Lua. String manipulation is one of its strengths.

Your problem is pretty simple. Let's take your trigger and modify it a bit:


<triggers>
  <trigger
   enabled="y"
   match="(Moderate magic) *"
   send_to="12"
   sequence="1"
   variable="modtxt"
  >
  <send>
itemDescription = "%1"

-- get rid of multiple spaces
itemDescription = string.gsub (itemDescription, "%%s+", " ")

-- break up on spaces
itemNames = utils.split (itemDescription, " ")

require "tprint"

tprint (itemNames)
</send>
  </trigger>
</triggers>


Template:pasting For advice on how to copy the above, and paste it into MUSHclient, please see Pasting XML.


I am scripting rather than sending to a variable.

The output of this first attempt is:


(Moderate magic) a sickle
1="a"
2="sickle"
(Moderate magic) a bright white potion with purple swirls
1="a"
2="bright"
3="white"
4="potion"
5="with"
6="purple"
7="swirls"


So you can see straight away that we have the individual words, as well as knowing how many there are.

A bit of work now with that table of words, and you can probably work out what to take. For example, discard "a" and "the". Then if you have more than one word, take the next one following a colour (eg. potion).

The number of items in the table is #tableName, in this case:


count = #itemNames



A slightly more complex example:


<triggers>
  <trigger
   enabled="y"
   match="(Moderate magic) *"
   send_to="12"
   sequence="1"
   variable="modtxt"
  >
  <send>

itemDescription = "%1"

-- get rid of multiple spaces
itemDescription = string.gsub (itemDescription, "%%s+", " ")

-- get rid of "a xxxx"
itemDescription = string.gsub (itemDescription, "^an? ", "")

-- get rid of "the xxxx"
itemDescription = string.gsub (itemDescription, "^the ", "")

-- break up on spaces
itemNames = utils.split (itemDescription, " ")

require "tprint"

-- debugging
tprint (itemNames)

print ("Number of words = ", #itemNames)

</send>
  </trigger>
</triggers>



Output:


(Moderate magic) a sickle
1="sickle"
Number of words =  1
(Moderate magic) a bright white potion with purple swirls
1="bright"
2="white"
3="potion"
4="with"
5="purple"
6="swirls"
Number of words =  6

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,165 posts)  Bio   Forum Administrator
Date Reply #2 on Sat 06 Sep 2014 12:13 AM (UTC)

Amended on Sat 06 Sep 2014 12:15 AM (UTC) by Nick Gammon

Message
Modifying a bit more:


<triggers>
  <trigger
   enabled="y"
   match="(Moderate magic) *"
   send_to="12"
   sequence="1"
   variable="modtxt"
  >
  <send>

itemDescription = "%1"

-- get rid of multiple spaces
itemDescription = string.gsub (itemDescription, "%%s+", " ")

-- get rid of "a xxxx" or "an xxxx"
itemDescription = string.gsub (itemDescription, "^an? ", "")

-- get rid of "the xxxx"
itemDescription = string.gsub (itemDescription, "^the ", "")

-- get rid of "with purple swirls" or similar
itemDescription = string.gsub (itemDescription, " with .*$", "")

-- break up on spaces
itemNames = utils.split (itemDescription, " ")

-- debugging
require "tprint"
tprint (itemNames)
print ("Number of words = ", #itemNames)

-- pick up the last word (if there is one)
if #itemNames &gt; 0 then
  Send ("get " .. itemNames [#itemNames] )
end -- if

 </send>
  </trigger>
</triggers>



Template:pasting For advice on how to copy the above, and paste it into MUSHclient, please see Pasting XML.


This discards " with xxx" from the description, and then assumes that the last word is the thing to pick up.

eg.


(Moderate magic) a sickle
1="sickle"
Number of words =  1
get sickle

(Moderate magic) a bright white potion with purple swirls
1="bright"
2="white"
3="potion"
Number of words =  3
get potion

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,165 posts)  Bio   Forum Administrator
Date Reply #3 on Sat 06 Sep 2014 12:40 AM (UTC)
Message
One more attempt. This time I put the noise words into a table, so you can just add others easily.


<triggers>
  <trigger
   enabled="y"
   match="(* magic) *"
   send_to="12"
   sequence="1"
   variable="modtxt"
  >
  <send>

itemDescription = "%2"

-- get rid of multiple spaces
itemDescription = string.gsub (itemDescription, "%%s+", " ")

-- get rid of "with purple swirls" or similar
itemDescription = string.gsub (itemDescription, " with .*$", "")

-- break up on spaces
itemNames = utils.split (itemDescription, " ")

-- make table of noise words (keyed by word)
noiseWords = { }
for k, v in ipairs { "a", "an", "the", "of", "pair" } do
  noiseWords [v] = true
end -- for

-- go through words, removing noise words
i = 1  -- first one
while i &lt;= #itemNames do
  -- if in noise words table, delete it
  if noiseWords [itemNames [i]] then
     table.remove (itemNames, i)
  else
    i = i + 1
  end -- if
end -- for

-- pick up the last word (if there is one)
if #itemNames &gt; 0 then
  Send ("get " .. itemNames [#itemNames] )
end -- if
 </send>
  </trigger>
</triggers>


This also has the type of magic as a wildcard (so now the item description is wildcard %2).

Output:


The corpse contains:
(Moderate magic) a sickle
get sickle
(Moderate magic) a bright white potion with purple swirls
get potion
(Potent magic) a pair of hardened leather breeches
get breeches
an axe
a mushroom
80 coins

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Chaosmstr   (21 posts)  Bio
Date Reply #4 on Sat 06 Sep 2014 05:27 PM (UTC)
Message
Nick, yer totally awesome.
I saw the first post and had some additional questions, but by the time I got done with my commute home, you had already answered them.
*laugh*

Thank you Sir!

CM
Top

Posted by Vic   (2 posts)  Bio
Date Reply #5 on Mon 08 Sep 2014 05:45 PM (UTC)
Message
I'm from the same realm as Chaosmstr. I tried this, but it's not pulling from the corpse only from the room/floor. Command for getting with in a corpse is, get item corpse. I had failed in trying to input 'corpse' into the line, so that it would pull from corpse.

V
Top

Posted by Chaosmstr   (21 posts)  Bio
Date Reply #6 on Mon 08 Sep 2014 06:28 PM (UTC)
Message
Hey Vic.. I had to change the get line as well.

if #itemNames &gt; 0 then
Send ("get " .. itemNames [#itemNames] .. " corpse")

I'm also working on adding in turning this on and off, so that I don't try to get stuff from a corpse that doesn't exist whenever I look into a bag.

Still experimenting with it, difficult to do when I have all the time in the world to program at work, but no connection to test any of it... and while at home, people want my attention instead of being lost in programming land.

BUT, that change above will at least change the get location.

CM
Top

Posted by Vic   (2 posts)  Bio
Date Reply #7 on Mon 08 Sep 2014 07:40 PM (UTC)
Message
Thanks CM, i was missing the ..
I just now started to use Mush, so getting used to it.

V
Top

Posted by Nick Gammon   Australia  (23,165 posts)  Bio   Forum Administrator
Date Reply #8 on Mon 08 Sep 2014 08:44 PM (UTC)
Message
You can test with the Game -> Test Trigger feature (Shift+Ctrl+F12).

Make sure you put a newline at each side of the text (Ctrl+Enter).

I just copied your examples and used that for my testing. Then you can test without even needing to connect (unless you want the response to work, of course).

To stop accidentally trying to get stuff from your inventory, try making the trigger disabled initially, and then match on:


The corpse contains:


When you get that line enable the trigger.

Template:function=EnableTrigger EnableTrigger

The documentation for the EnableTrigger script function is available online. It is also in the MUSHclient help file.



Then disable it when you get something that is not from the corpse (eg. a prompt line).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


27,788 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.