|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Wed Feb 08, 2012 10:15 pm
Item Stacking |
Hey all.
I'm trying to find the best way to "stack" multiple items in a room inventory, to reduce screen-spam. Typical output might be:
Code: |
A dagger lies here.
A pair of trousers is tossed aside.
A dagger lies here.
A dagger lies here.
A red hat has been discarded here.
|
Which I'd like to turn into:
Code: |
A dagger lies here. (x3)
A pair of trousers is tossed aside.
A red hat has been discarded here.
|
I tried a few different searches but didn't come up with anything. If anyone has an idea of how to attack this best, or has a link of a relevant example to share, please post away. |
|
Last edited by form2function on Thu Feb 16, 2012 1:38 pm; edited 2 times in total |
|
|
|
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Thu Feb 09, 2012 12:59 am |
Collect the output into a stringlist, using %additem() so that you can have duplicate items in the list.
Let us say that the stringlist you create is named @itemlist.
Then execute the following:
Code: |
#LOOPDB %countlist(@itemlist) {
#IF (%val > 1) {#SHOW %key (x%val)} {#SHOW %key}
}
#var itemlist {}
|
|
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Thu Feb 09, 2012 9:44 pm |
Makes sense on paper. Now to figure out the actual code...
The items to be stacked will always follow after the exits of a room (and are ansi-colored if that matters). They're specific items I want stacking, not any random items, so theoretically their sdesc could be placed in an array.
For example:
Random Room Name
Random Room Desc
Obvious exits:
East - Random Room
West - Random Room
A crimson dagger lies here.
A crimson dagger lies here.
A corpse is here.
What I want to stack are only the crimson daggers, for example.
So, how should I go about the trigger's pattern? Is there a way to have it search against an array, right after the exits?
I don't mind poking around more on my own, but I think I'll need a bit more of a push in the right direction. :) |
|
|
|
shalimar GURU
Joined: 04 Aug 2002 Posts: 4704 Location: Pensacola, FL, USA
|
Posted: Thu Feb 09, 2012 10:18 pm |
I had something like this worked out once upon a time... but it wasn't consistant and i couldn't exactly figure out why.
Code: |
<trigger priority="10" id="21">
<pattern>*</pattern>
<value>$this=%trim(%line)
#IF ($this=@lastLine) {
#GAG -1
count=(@count+1)
#SAYADD {(x@count)}
} {count=1}
lastline=$this</value>
</trigger>
|
|
|
_________________ Discord: Shalimarwildcat |
|
|
|
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Fri Feb 10, 2012 1:18 am |
Yes, there is a way to have it watch only for specific objects, such as crimson daggers. What you do is create a stringlist which contains all of the lines you are watching for. Then create a class. Inside that class create a trigger that watches for the lines from the stringlist, gags the line, and adds the line to a different stringlist. Create another trigger in the class that watches for the mud prompt, displays the items, then disables the class. Outside the class, create another trigger that watches for your exit line and enables the class.
I think the following commands should create something that works. It assumes that your prompt is ">" so edit it if your prompt is something different. And of course, edit the CountItems variable so that it contains the strings you are actually looking for. Execute these commands on the command line to create the triggers you need.
Code: |
#VAR countitems {A crimson dagger lies here.|A magical hat lays on the ground.|A really splufty mace sits waiting for you.}
#VAR itemlist {}
#TRIGGER {Obvious exit{s|}:} {#T+ CountClass}
#CLASS CountClass
#TRIGGER {({@countitems})} {#GAG;#VAR itemlist %additem(%1,@itemlist)} CountClass
#TRIGGER {>} {
#LOOPDB %countlist(@itemlist) {
#IF (%val > 1) {#SHOW %key (x%val)} {#SHOW %key}
}
#var itemlist {}
#T- CountClass
} CountClass prompt
#T- CountClass
|
The key is the trigger "#TRIGGER {({@countitems})} ..." This will match any string in your @countitems stringlist. With this, you can specify which items you want piled together in your output. The #T+ and #T- ensures that the triggers only work while room contents are being listed. The #GAG prevents the matching line from being printed. When the room contents are done and you get a mud prompt, it prints out the tallied lines, empties the itemlist, and turns the class off until the next room contents come along.
Note: this code is untested, but should get you pretty close. |
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Tue Feb 14, 2012 6:57 pm |
Thanks, both of ya!
Rahab, I went with your frame and it works... mostly.
It's masking the right variables, it's carrying them over to the temp list in full, the triggers themselves work fine, however... There's a problem somewhere in the loop. For example in my testing room I have seven different string objects that are within my stringlist to compact. They're masked and placed in the temp list, but in the output, only three of those stringlists are counted. They're also cut.
The problem lies with commas in the object descriptions. Objects without commas in their description aren't printing at all (ex. "A red dagger lies here." doesn't print at all). Only objects with a comma are printing, but they're also only printing up until the comma (ex. "A blue dagger, not a red one, lies here." counts and prints but returns as "A red dagger x3").
Any thoughts on how to escape/deal with the comma issue?
Also, is there any easy way to insert the counted strings before the prompt instead of after it? Othan than some complex way of masking and re-printing it I mean. |
|
|
|
Daern Sorcerer
Joined: 15 Apr 2011 Posts: 809
|
Posted: Tue Feb 14, 2012 7:37 pm |
I can't reproduce the problem with the commas, no idea why that would happen. As for inserting the counted strings before the prompt, the easiest way would be to do exactly what you said, it wouldn't be complex at all. In your prompt trigger, just insert a #GAG at the top and a #SHOW %line at the bottom. If you have color in your prompt, you probably also want to check the ansi trigger box so it gets preserved.
|
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Tue Feb 14, 2012 7:57 pm |
Yep, ended up using a #GAG;#CR just now to gag the prompt and spit a new one afterwards. :)
The original text that's being gagged and counted has ansi color. I've reproduced that in the post-count output, but I'm wondering if that one of the reasons the loop is failing? Not sure what else might be the cause... The values are stored in full in the temp stringlist. |
|
|
|
Daern Sorcerer
Joined: 15 Apr 2011 Posts: 809
|
Posted: Tue Feb 14, 2012 8:13 pm |
Ah, that could definitely be the problem. If you're using an ansi trigger, all the ansi codes must be present in the pattern, or else it won't match.
|
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Tue Feb 14, 2012 8:58 pm |
Oh, the pattern matches fine... Everything is working, up until the actual loop. Which is:
Code: |
#LOOPDB %countlist(@stacklist) {
#IF (%val > 1) {
#SHOW %ansi(red)%key (x%val) %ansi(reset)} {#SHOW %ansi(red)%key %ansi(reset)}
} |
Something is happening in that loop. The variables in @stacklist are complete and accurate. It's either the #LOOPDB function or the #SHOW function that's having a hickup with the commas. |
|
|
|
Daern Sorcerer
Joined: 15 Apr 2011 Posts: 809
|
Posted: Wed Feb 15, 2012 12:21 am |
Actually, it looks like it's a bug in the %countlist function. I'll start a new bug report thread. Until it gets fixed, I suggest changing your stacklist variable to a database variable, and keeping track of how many of each item are in the room directly in it.
|
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Wed Feb 15, 2012 8:12 am |
Aha! I was going crazy trying to think of what might be wrong...
Any ideas on how to modify the script Rahab shared to work with a db variable instead of a stringlist? I've been trying to learn to use them lately (instead of a full-fledged db) but I'm still a ways from having a handle on them.
Also, would there be any way to maintain the original ansi colors of a line I'm gagging, without having to recolor it myself? The items I'm trying to stack are all one color, but inevitably there are rooms with objects in it aside from those I'm stacking that sometimes have complex ansi (ex. custom colored player objects). |
|
|
|
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Wed Feb 15, 2012 1:57 pm |
Bleh! Too bad %countlist has a bug; it was designed for exactly this type of thing. Here a a workaround using Daern's suggestion of a db variable. Note that this only uses @countitems, not @itemlist:
Code: |
#VAR countitems {"A crimson dagger lies here."=0|"A magical hat lays on the ground."=0|"A really splufty mace sits waiting for you."=0}
#TRIGGER {Obvious exit{s|}:} {#T+ CountClass}
#CLASS CountClass
#TRIGGER {({@countitems})} {#GAG;#ADDKEY countitems %1 (%db(@countitems,%1) + 1)} CountClass
#TRIGGER {>} {
#LOOPDB @countitems {
#IF (%val = 1) {#SHOW %key}
#IF (%val > 1) {#SHOW %key (x%val)}
#IF (%val > 0) {#ADDKEY countitems %key 0}
}
#T- CountClass
} CountClass prompt
#T- CountClass
|
|
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Wed Feb 15, 2012 3:56 pm |
Ok.. Implemented that. Now I'm not getting anything, besides lines not matching a var in the list.
The addkey trigger's fine, it adds to the db list. The loop trigger does fire fine, because it's doing the rest of what it's supposed to, like gagging the prompt and resetting the keys. But the #SHOW's are a no go.
Thoughts?
Also, scratch my last question about color. It occured to me those items wouldn't be gagged to begin with, so no worries. |
|
|
|
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Wed Feb 15, 2012 5:29 pm |
Is the ">" trigger firing on your prompt?
|
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Wed Feb 15, 2012 7:21 pm |
Yep, it is. I re-wrote to match my prompt and it matches fine. And the trigger itself fires fine, because it's going through the looped IF's and resetting the keys to 0. I disabled that line to check, and the count is accurate, and is being correctly set to 0 afterwards.
|
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Wed Feb 15, 2012 8:32 pm |
Are we sure %key is the right call and #SHOW the right function for this? I get that it -should- work. I mean the LOOPDB example is practically the same code. It just doesn't seem to working...
I tried a few different combinations with #SHOWDB, %dbvar, etc. but so far I haven't gotten far.
This:
Code: |
#LOOPDB @itemlist {
#IF (%val = 1) {#SHOW %ansi(brown)%dbkey %ansi(reset)}
#IF (%val > 1) {#SHOW %ansi(brown)%dbkey "("%val")" %ansi(reset)}
#IF (%val > 0) {#ADDKEY itemlist %key 0}
} |
Gets a step closer. I had to wrap the parenthesis of %val in quotes as it was affecting things, but it now displays a space, followed by the correct itemcount in parenthesis. It does not print the actual keys though, and for keys that only have one instance, it only posts a blank line. Meanwhile %key continues to post nothing. It works fine with #ADDKEY though... |
|
|
|
MattLofton GURU
Joined: 23 Dec 2000 Posts: 4834 Location: USA
|
Posted: Wed Feb 15, 2012 9:52 pm |
%dbkey is not a valid term in zscript. I presume you meant to use %key, which is a predefined variable that is defined only within the confines of a #LOOPDB structure.
|
|
_________________ EDIT: I didn't like my old signature |
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Wed Feb 15, 2012 11:54 pm |
MattLofton wrote: |
%dbkey is not a valid term in zscript. I presume you meant to use %key, which is a predefined variable that is defined only within the confines of a #LOOPDB structure. |
It's valid along with %item, just new in 3.21. I tried it because %key doesn't seem to be working as expected, as per the posts above. My use of it isn't valid because I'm not specifing its parameters. I tried that in case it utilized the db var identified in the loop itself, like %key would. The result might not work, but it at least indicated to me that the problem lies possibly with %key.
I'm basically stabbing in the dark here, as what should be working, isn't. |
|
|
|
Daern Sorcerer
Joined: 15 Apr 2011 Posts: 809
|
Posted: Thu Feb 16, 2012 2:42 am |
Actually, I believe that everything is displaying just fine. The problem is that when it displays the keys, the first trigger fires again, gagging your output and changing the variable - you just can't see that change because immediately after the display in your loop (when the first trigger fires and changes the variable) you're setting it back to zero. Changing the #SHOWs to #PRINT should fix the problem. #SHOW will fire triggers, #PRINT won't.
|
|
|
|
Rahab Wizard
Joined: 22 Mar 2007 Posts: 2320
|
Posted: Thu Feb 16, 2012 3:01 am |
Gah...good catch, Daern!
|
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Thu Feb 16, 2012 1:36 pm |
Yes! Nice work Daern! After the %countlist bug I was starting to second-guess every function. ;)
Works like a charm now, and I learned a bit more about db variables to boot! And we found a bug. And as a bonus, with the way its set up I can choose to apply it selectively with a #T+ in a room's script, so it's not running constantly and slowing things down.
Thanks a ton, both Daern and Rahab!
For bonus points, I'll ask one last question. Is there a way to indicate an end-of-line in the pattern or the db var key, so that "A red dagger." is matched but "A red dagger. (glowing)" isn't? |
|
|
|
Daern Sorcerer
Joined: 15 Apr 2011 Posts: 809
|
Posted: Thu Feb 16, 2012 2:31 pm |
In patterns, ^ matches the start of the line and $ matches the end of the line. You can't add it to individual keys in the variable though, it needs to go directly in the pattern, so it's all or nothing.
|
|
|
|
form2function Beginner
Joined: 30 Jun 2011 Posts: 23
|
Posted: Thu Feb 16, 2012 7:44 pm |
Hrm. Well, I wouldn't mind all or nothing as I'd like it to ignore every (glowing) item. However ({@itemlist$}) seems to ignore both types of objects, regular and glowing. All other entries count fine, but if there's a regular and glowing version of the item in the room, it won't stack either of them.
Something I'm doing wrong?
Update: Oddly it only does that with the first entry in the db variable list. However, that's also the only entry it effects. For rooms with say a normal and glowing item that's further down the variable list, it appears to ignore the $ and stacks them all together. |
|
|
|
Daern Sorcerer
Joined: 15 Apr 2011 Posts: 809
|
Posted: Thu Feb 16, 2012 10:39 pm |
You need to put the $ outside the }). You might want to read over the documentation on Pattern Matching at some point .
|
|
|
|
|
|