Organizing contents of a container

Posted by Whisk3rz on Sun 24 Apr 2011 08:57 PM — 19 posts, 76,457 views.

#0
This is something someone posted that worked on ZMUD and I wanted to figure out how to make it work for MUSHClient...

This is what the game currently displays:

Inside the open large durable burlap travel pack you see: roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, half eaten roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf, roasted verbena leaf


I want it to display:

Inside the open large durable travel pack you see:
20 roasted verbena leaf(s)


I want this to work for all containers, though.

This is what he had for ZMUD:

#TRIGGER {Inside the (*) you see:(*)} {Item.Container=%1;Item.List=%2;#SUB {Inside the @Item.Container you see:};#LOOPDB %Countlist( %replace( %replace( %replace( @Item.List, ", ", "|"), " a ", " "), " an ", " ")) {#SHOW %Val %Key}}


How might this be worded for MUSHClient?
USA #1
<triggers>
  <trigger
   enabled="y"
   keep_evaluating="y"
   match="^(Inside the (?:.*?) you see:)( (?:.*))$"
   omit_from_log="y"
   omit_from_output="y"
   regexp="y"
   send_to="14"
   sequence="100"
  >
  <send>-- Display the container line
Note("%1")

-- Split the list into a table of items, and strip the leading space from each
local items = utils.split("%2", ",")
for i,v in ipairs(items) do
  items[i] = v:sub(2)
end

-- Tabulate a count of each item
local counts = {}
for _,v in ipairs(items) do
  counts[v] = (counts[v] or 0) + 1
end

-- Display each item with its count
for k,v in pairs(counts) do
  Note(("%i %s(s)"):format(v, k))
end</send>
  </trigger>
</triggers>


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


Output:
Inside the open large durable burlap travel pack you see:
1 half eaten roasted verbena leaf(s)
24 roasted verbena leaf(s)
Amended on Sun 24 Apr 2011 09:45 PM by Twisol
#2
Thank you.

One thing I did to change this was Checked Omit from Output, and changed "script" to "Script (after omit)" to avoid showing the inventory both ways.

Otherwise, this worked perfect. Much Appreciated.



EDIT! Oh, one more thing, when the container is empty, that space after what's in it is generally just empty. Any way to say if %2=nil, don't display 1 (s)?
Amended on Sun 24 Apr 2011 09:51 PM by Whisk3rz
USA #3
Yeah, you'll want to re-import the version from my post, I have a bad habit of editing things after the fact to polish them up. >_>

(The only difference right now is that I also checked Omit from Log and Keep Evaluating, so you could just do that yourself if you want.)
#4
Inside the open forged steel coffer you see:
1 (s)

How do i tell it to not say 1 (s) and maybe say "nothing" if nothing is in there? Normally when i look at a container with nothing it just says...

Inside the open forged steel coffer you see:
USA #5
Hmm. Change the match pattern to ^(Inside the (?:.*?) you see:)( (?:.+))$ . That makes the trigger not match at all if there's nothing inside.
#6
Perfect! Changed note to ColourNote and made it light gray, so it's not such a sore thumb. but other than that, it seems to work swimmingly.

Thank you once again!
USA #7
Yep, I just wanted to demonstrate the idea. Glad it works for you! :D
#8
Oh, is there any way to alter the format for when this is only 1 to leave off the count and (s), but still list it?
USA #9
for k,v in pairs(counts) do
  var plural = (v != 1 and "(s)" or "")
  Note(("%i %s%s"):format(v, k, plural)
end


This should work. Changes marked in bold.

The and/or trick there is almost (but not quite) identical to the traditional ?: ternary operator, if you have any experience with that. Otherwise, you can consider it similar to:

var plural
if v != 1 then
  plural = "(s)"
else
  plural = ""
end


[EDIT]: Oh, you also wanted to remove the count? I think that would make the output kind of ugly, but sure.
for k,v in pairs(counts) do
  if v == 1 then
    Note(k)
  else
    Note(("%i %s(s)"):format(v, k)
  end
end
Amended on Fri 29 Apr 2011 06:17 AM by Twisol
#10
I only wanted to remove the count on 1, since some items are worded as "a pair of boots" "some soft linens" "Some marks"

When i look in a container and see "1 some marks" i keep confusing it for it saying there is only 1 mark in that container. That's the equivalent of a penny... haha.
#11
Twisol said:

for k,v in pairs(counts) do
  var plural = (v != 1 and "(s)" or "")
  Note(("%i %s%s"):format(v, k, plural)
end




Only tried this part so far, getting an error.

Compile error
World: Isles of Aedin
Immediate execution
[string "Trigger: "]:18: '=' expected near 'plural'

Have it sending to script after omit... could that be causing this?
USA #12
Nope, I'm just an idiot. Change != to ~=.
#13
Twisol said:

Nope, I'm just an idiot. Change != to ~=.

<triggers>
  <trigger
   enabled="y"
   match="^(Inside the (?:.*?) you see:)( (?:.+))$"
   omit_from_output="y"
   regexp="y"
   send_to="14"
   sequence="100"
  >
  <send>-- Display the container line
ColourNote("lightgray", "black", "%1")

-- Split the list into a table of items, and strip the leading space from each
local items = utils.split("%2", ",")
for i,v in ipairs(items) do
  items = v:sub(2)
end

-- Tabulate a count of each item
local counts = {}
for _,v in ipairs(items) do
  counts[v] = (counts[v] or 0) + 1
end

-- Display each item with its count
for k,v in pairs(counts) do
 var plural = (v ~= 1 and "(s)" or "")
  ColourNote("lightgray", "black", ("%i %s(s)"):format(v, k, plural))
end</send>
  </trigger>
</triggers>


still getting the same error. The issue is with the = after "var plural", it would seem. :-/
USA #14
No, that's just the first place it noticed there was an error. The real problem is that I've been using Javascript far too much lately, and I used 'var' instead of 'local'. (Go ahead and change that. I promise it will work, or so help me...)
#15
Much better. I do appreciate all of your help. I was thinking var seemed like a different language, but I didn't want to say that, heh.

In regards to removing the count, is there any way to format this to just exclude some items from the count?
USA #16
Whisk3rz said:
Much better. I do appreciate all of your help.

Sure thing.

Whisk3rz said:
In regards to removing the count, is there any way to format this to just exclude some items from the count?

Hmm, do you have an example? I'm not sure what exactly you mean.
#17
Lets say I want a number and (s) beside all things except (some copper) (some gold) (a gold) (a copper)

Putting a number beside currency really throws me off. heh.
USA #18
Conceptually, you need to store a list of these exceptions somewhere. For each item you display, you need to check that list and do something different if it's in that list.


-- The list doesn't need to (and arguably shouldn't) be in
-- the trigger itself; you could put it in your script file
-- (minus the 'local' and probably changing the name) so
-- it's only created once.
local blacklist = {
  ["some copper"] = true,
  ["some gold"] = true,
  ["a copper"] = true,
  ["a gold"] = true,
}
-- blacklist["foobarbaz"] returns nil
-- blacklist["a gold"] returns true
-- This is perfect for an if condition.

for k,v in pairs(counts) do
  -- Check the blacklist
  if blacklist[k] then
    Note(k)
  else
    local plural = (v != 1 and "(s)" or "")
    Note(("%i %s%s"):format(v, k, plural)
  end
end