Author Topic: Finditem and maintaining the #findresults. Append concatenation for easy arrays.  (Read 2131 times)

0 Members and 1 Guest are viewing this topic.

Offline lydaanTopic starter

  • Jr. Member
  • **
  • Posts: 70
  • Activity:
    0%
  • Reputation Power: 3
  • lydaan has no influence.
  • Respect: +6
  • Referrals: 0
    • View Profile
I was discussing some things about finditem with Gaderian in another thread and thought I'd move the discussion to it's own thread.

Original thread where the conversation started:
http://www.scriptuo.com/index.php?action=post2;start=0;board=30

Quote
last post from Gaderian for some context
Quote
I use the 'for #findindex 1 #findcnt' all the time, but it doesn't work in the example I showed above, because #findcnt gets reset with each 'finditem' statement (when looking for the tools), and I had to keep track of how far through the list I was.

The ignoreitem method doesn't work when trying to see if I have enough tinker tools to craft more tinker tools to fill the bod; additionally this won't work when the item stacks.

Also when you issue the 'finditem TYPE Index location' method, #findcnt returns 1 each time because you said you wanted to search for only 1. (I expected it to give me back the same #FindCnt value as if I had looked for the whole list, but that was incorrect.)

So using a number value for the Index into the list behaves very differently from the other methods.

In another thread here, TrailMyx states that everyone gets the items back in the same order (suppose you stand in range of the same NPC's with me, we both get the same order of NPC's). I haven't tried to prove or disprove that, but take his word for it. It makes sense because the Index parameter allows subsequent execution of the 'finditem TYPE LOCATION' to actually iterate through the list. If this return was variable on each call, then the Index parameter would not really work.

Interesting nuances in the language that we can take advantage of in scripts...

;--------------------------------------------------------

Few things here. A big one is that you're conflating EUO system functions(finditem) and #return variables with script-local user-defined functions and variables. You can define just about anything you can think of, function or variable, as long as you define it and address it correctly for your intended use.

For those who may be unfamiliar, finditem is an EUO system function. When you call finditem, it returns an array of data that you may reference until you call finditem again. For each subsequent finditem call, EUO will delete all previously held data at each memory/array address, and then populate a new array.

Quote
... #findcnt gets reset with each 'finditem' [call] ... and I had to keep track of [a previous finditem_return index position] ...

Correct. This is why, if you need to reference the data again, after future finditem calls, or the worst case scenario, against THE NEXT or LAST finditem call, the best/only (if next or last) practice is to store the relevant data in a user-defined array for later reference. This can easily be done in EUO by using the append concatenator . (#dot).

In this particular case you may be able to get away with just doing a finditem call and then just using the first thing found before calling finditem again, but if you're wanting to reference values like #findiindex or #findcnt against the current data set, you will need to store all relevant data points in a referenceable manner if your flow requires another finditem call before that data is irrelevant. You're already doing half of this. Just take one more step and you've solved it.

If what TM was saying is correct (I would assume it is) then #findindex is more descriptive than I had previously assumed, but only when a finditem is called using the exact search_for parameter in the exact #charpos and/or container (and probably expecting the searched items having not been moved between searches, as it's likely a server propagation hierarchy). Only in that one special case could you consider #findindex to be descriptive for anything other than defining a position in the current finditem_result array.

#findindex holds no special relevance outside of the fact that for every #findindex = n, when and only when used in conjunction with any #findresult, it points to a specific position in the current finditem_return (and the extremely rare usage above).

#findcnt also holds no relevant information outside of the amount of indices that were returned when finditem was last called making it easier to parse the array. it's just a count-value that is system function defined, and cannot be defined with set.

Example of #findindex irrelevance:
Code: [Select]
for #findindex 1 5
   set %test . #findindex test . #findindex
;will produce identical results as
for %i 1 5
   set %test . %i test.%i
;both will produce a 1x5 array of %test1-5 = test1-5
You can easily test this by opening a fresh EUO tab, with no previous finditem calls, and running this:
Code: [Select]
for #findindex 1 5
   set %test . #findindex test . #findindex
for %i 1 5
   display %test . %i
halt

now #findindex relevance and #findcnt ir/relevance. This is a usable test/example:
Code: [Select]
finditem * c_ , #charid
for #findindex 1 #findcnt
   display Item #findid found at Index Position #findindex ,
        + ,$in the current finditem_result array$that has a total of
        + #findcnt unique indices.
;will produce identical results as
set %just_a_count #findcnt
for %i 1 %just_a_count
{
   set #findindex %i
   display Item #findid found at Index Position %i ,
        + ,$in the current finditem_result array$that has a total of
        + %just_a_count unique indices.
}
;this previous example also shows why we should be thankful we can shove #findindex in a for() call as parameter 1
;and finally, same with this one, and also why we should all be thankful for #findcnt as well as
;being able to shove it into the upper-bound parameter of our for() calls
;this also sets up a user-defined array, so you can reference the
;current finditem_results array permanently.
for %i 1 1000000
{
   set #findindex %i
   if #findid <> yc
      set %just_a_moniker . %i #findid
   if #findid = yc 2
      set %literally_just_a_count %i - 1
      set %i 1000000
}
set %from_1_to 1
for %any_old_numer %from_1_to %literally_just_a_count
   display Item %just_a_moniker . %any_old_numer found at Index Position %any_old_numer
        + ,$in the current finditem_result array$that has a total of
        + %literally_just_a_count unique indices.
halt

So when I:
Code: [Select]
finditem %sbod_types c_ , #backpackid
set %sbod_cnt #findcnt
for #findindex 1 %sbod_cnt
  ​set %sbodid . #findindex #findid
I create a user-defined 1xN array (IDxIndex|Indices) indexed to the data found in the finditem_result array that is permanently referenceable within the script until I manually delete it, overwrite it, or stop the script.

The sbodID array:
Code: [Select]
%sbodid1 = ;a unique #ObjectID found at index position 1 of the the previous finditem_sbods_results array
%sbodid2 = ;a unique #ObjectID found at index position 2 of the the previous finditem_sbods_results array
...
%sbodid . %sbod_cnt = ;a unique #ObjectID found at index position #findcnt of the the previous finditem_sbods_results array

A reference and pseudo-use-case for each index:
Code: [Select]
for %i 1 %sbod_cnt ;note, you could use %sbod_index in place of %i if that helps you,
{                  ;but what you name the counter is entirely irrelevant.
                   ;only the current count is relevant.
                   ;the second parameter 1, will always start the count at 1
                   ;and will continue to perform all actions below for each %sbodid . %i
                   ;until it has completed all actions below for %sbod . %sbod_cnt

   event property %sbodid . %i
   ;do sbod things
   ...
}

As a sort of aside, but on topic to the previous example use case, it would be best practice to delete all previous entries freeing the designated memory addresses, just the same as EOU does when you call finditem. The biggest concern is not really the memory usage (although that should always be a concern, even when it is minimal), but rather that the sbod count might be variable if/when you're calling this user-defined function/sub multiple times in the same script.

My recommended example:
Code: [Select]
;check for if %sbod_cnt is defined = #true. This will only pass after the first time through.
;alternatively you could use if %sbod_cnt > 0 if for some weird reason
;you are defining it in parallel somewhere else in the script.

if %sbod_cnt <> n/a 2
   for %i 1 %sbod_cnt
      deletevar %sbodid . %i
;someone will probably comment about deletevar. "set %variable  " does not delete the address. only the value.

;you don't need to delete %sbod_cnt as it will be overwritten before it is referenced again.
finditem %sbod_types c_ , #backpackid
set %sbod_cnt #findcnt
for #findindex 1 %sbod_cnt
  ​set %sbodid . #findindex #findid

I hope this helped to simplify arrays.

Quote
The ignoreitem method doesn't work when trying to see if I have enough tinker tools to craft more tinker tools to fill the bod

This is literally one of it's usages. you just have to ignoreitem by ID. But this doesn't solve the issue of crafting another tinker tool before this one runs out. But that's a conversation for another thread.

Test code:
Code: [Select]
;clear your backpack of Tinkering Tool Kits.
;put one in your backpack then press play:
finditem %tinkerToolTypes c_ , #backpackid
ignoreitem #findid
set %ignoredTool #findid ;set this so you can clean up the ignoreitem command later
pause

;now put as many tinker tools as you like in your backpack and press play again
finditem %tinkerToolTypes c_ , #backpackid
for #findindex 1 #findcnt
{
   if %ignoreditem = #findid 3
      set %ignoreitem = #false
      display Welp, ignoreitem doesn't work :(
      halt
}
if %ignoreitem <> #false
   display finditem found #findcnt Tinkering Tool Kits, but did not find the one that was ignored.
pause

;now if you still don't think it works we'll un-ignore that ID
ignore item %ignoreitem
finditem %tinkerToolTypes c_ , #backpackid
display finditem now found #findcnt Tinker Tool Kits in your backpack!
halt

there are other ways to do this as well, but this is the simplest. not necessarily the best option, but it is simple.

Quote
additionally this won't work when the item stacks

i don't know what else would be important to ignore except the items you normally keep in your backpack and a tinkerer's tool so you can craft more tinkerer's tools when needed. could you provide an example?

Quote
finditem TYPE Index location

I am unsure of what exactly you are expressing here. If this is still relevant, please post an example.


Offline Gaderian

  • Elite
  • *
  • *
  • Posts: 486
  • Activity:
    0%
  • Reputation Power: 10
  • Gaderian barely matters.Gaderian barely matters.
  • Respect: +50
  • Referrals: 3
    • View Profile
+1
Most often scripts will use finditem in conjunction with ignoreitem to work with a subset of data. So I said:
Quote
additionally this won't work when the item stacks

So you asked:
Quote
i don't know what else would be important to ignore except the items you normally keep in your backpack and a tinkerer's tool so you can craft more tinkerer's tools when needed. could you provide an example?

I have mentioned everything that is necessary, so I will be somewhat redundant now...

I spent the summer working on expanded the Bod filler project that I recently posted and shared with the community.
It's original logic would ignore crafted smith and tailor items and just increment a counter until it had satisfied the amount crafted. This would be non-stackable items as there are no armor or weapon pieces that fill smith and tailor BODs.

Upon expanding the Bodfiller to include potions (Alchemy), scrolls (Inscription), gears (Tinkering), pies (Cooking) and arrows (Fletching) it no longer worked on any of these item examples which stack. There are other BOD fill items that stack, but that is just an example from most of the craft skills. This is because ignoreitem on the item id and then adding to the stack ignores the newly created item because it's ID doesn't change, just the stack count.

The other statement you asked about stood on it's own, you just took it out of context.

« Last Edit: September 19, 2021, 07:54:16 PM by Gaderian »
"Go ahead ask me: 'Should I use hard waits or timers?'"
You say:"Should I"
Gaderian:"Timers!"
You Say:"use hard waits or timers?"

The serious side of timer use is illustrated here: http://www.scriptuo.com/index.php?topic=12094.msg101926#msg101926

However, every time I go back and look at this [AutoLooter] script, I realize I had wrote it in my zen state of EUO scripting - so it makes my brain hurt.

Offline lydaanTopic starter

  • Jr. Member
  • **
  • Posts: 70
  • Activity:
    0%
  • Reputation Power: 3
  • lydaan has no influence.
  • Respect: +6
  • Referrals: 0
    • View Profile
for anyone who actually bothers to read what I wrote, I was completely wrong about how the command deletevar works in EUO. while it does delete the specified variable, you cannot concatenate within the command parameter.

invalid code:
Code: [Select]
deletevar %sbodid . %i
there are a few options to delete these variables.
1. namespace management would be the simplest in terms of effort.
2. manually delete each entry made with a hardcode. This would be excruciatingly arduous.
3. settle for "set %variable   ," which stores the value " ," that's not #spc, it's literally a blank string, and the address remains active. this is fine in 99% of situations

Offline TrailMyx

  • Officially retired from UO
  • Administrator
  • *
  • *
  • Posts: 13301
  • Activity:
    0%
  • Reputation Power: 154
  • TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!TrailMyx is awe-inspiring!
  • Gender: Male
  • Viper!
  • Respect: +1349
  • Referrals: 33
    • View Profile
    • ScriptUO
Ah, the "kinda-parser" of EasyUO strikes again!  :)

The hardest part of writing my own EasyUO parser for ScriptUO back when I was doing that was dumbing down a classic infix parser to "not" handle what it should handle.
« Last Edit: September 20, 2021, 06:56:54 PM by TrailMyx »
Please read the ScriptUO site RULES
Come play RIFT with me!

Offline lydaanTopic starter

  • Jr. Member
  • **
  • Posts: 70
  • Activity:
    0%
  • Reputation Power: 3
  • lydaan has no influence.
  • Respect: +6
  • Referrals: 0
    • View Profile
Quote
Ah, the "kinda-parser" of EasyUO strikes again!  :)
You actually can concatenate in the deletevar parameter, but I've found it only works in specific cases, and even then it sometimes works how you would expect for specific concatenated variables, but sometimes it deletes an address, but not the one you expect/intended.

Basically it breaks down like this:
99% of the time you cannot concatenate within the command parameter, and it will do nothing.
.9% of the time it will work as intended with concatenation
.1% of the time it will delete an address, but not the one you were intending.

The .9% and .1% of cases I've found are when I've defined a *non-specific (as best you can in EUO) reference variable inside the parameter with #dot.

There actually may be a way to make that invalid code work if you concatenate in a specific order including outside of the parameter, but I doubt it. I could be wrong as EUO often makes you think you know how it works, but in reality you don't. I need to do a little more testing first.

I'll do a full write up on concatenation, nondescript-reference variables and deletevar once I have it all worked out in EUO.

edit added:
Quote
The hardest part of writing my own EasyUO parser for ScriptUO
I can't imagine the length of the migraine while building ScriptUO. This was about a 6 hour migraine for me... probably ~15 minutes of actually writing test code, and the rest of the 6 hours rubbing my brow (VERY intensely) with my head down and eyes closed while muttering nonsense.
« Last Edit: September 20, 2021, 09:10:10 PM by lydaan »

Tags: