Feature - Implemented hermit(int, item) returns true on failure to buy clover

taltamir

Member
using the hermit command returns true on failure to buy a clover (due to having reached the limit of 3 a day)
Code:
> ash hermit(1, $item[11-leaf clover])
Returned: true

it should only be returning true if it actually bought a clover
 

fronobulax

Developer
Staff member
The hermit command returns RuntimeLibrary.continueValue() which, in general, means the command succeeded from the standpoint of parsing and executing. The return value was not intended to tell the scripter that the command succeeded. Indeed it is somewhat idiomatic in ash to ignore the return value of the command and explicitly confirm that the desired action occurred.

So I am first going to mark this as a feature request since the code is working as designed.

The next step is probably some discussion. This problem can clearly be addressed by editing https://wiki.kolmafia.us/index.php/Hermit so that scripter expectations are properly managed. The use case would be of interest. If the goal is to determine whether (or how many) clovers are available then perhaps a daily preference is called for. If the goal is to "get them all" then a script can be wrapped with a clover counter and if hermit returns true but the clover count doesn't change then it means there are no more to be gotten.

It may be that this is the first of many ash commands that needs to have a Boolean returned that makes sense in a script and not to the script interpreter but that starts looking like a major project.
 

Veracity

Developer
Staff member
The hermit() function calls the "hermit" command, which makes a HermitRequest, which is a CoinMasterRequest.

A HermitRequest is an unusual Coinmaster in that it is one of a tiny handful which can run out of an item. (The SwaggerShopRequest is another; the seasonal reward is usually limited to a single purchase per season, regardless of how much Swagger you have.)

Looking at HermitRequest.run - which is where you'd expect KoLmafia to go into an error state and display an error message, and thereby make the continueValue false, and thereby make the request/command/function return a failure - I don't see any checking for quantity requested vs. available for 11-leaf clovers in particular.

Seems like a little check in that method for that particular requirement would fix this.
 

Veracity

Developer
Staff member
Additional investigation:

When you invoke the "hermit" command, its first action is to get the number of currently available clovers.
Then, it "min"s the number of clovers you asked for with the number available.
If that becomes zero, it "succeeds" silently.

The logic in the command says if you ask for "*" of an item, for clovers, that is how many are available. But that "min" occurs for all clover requests, not just "*". That's not right; if you ask for 1, it should try for 1 rather than pretending you asked for 0.
 

Veracity

Developer
Staff member
> hermit

Visiting Hermit...
The Hermit has 0 clovers available today.

> hermit * clover

> hermit clover


Asking for 1 11-leaf clover, but 0 left today.

> ash hermit( 1, $item[11-leaf clover] )

Asking for 1 11-leaf clover, but 0 left today.
Returned: false
One small change to HermitCommand and one to HermitRequest.
 

taltamir

Member
The fix is incorrectly throwing an abort instead of just returning false.
Code:
> ash hermit(1, $item[11-leaf clover]); print("test works");

Asking for 1 11-leaf clover, but 0 left today.
Returned: false
Code:
> ash hermit(1, $item[ketchup]); print("test works");

Visiting    the Hermit...
You acquire an item: ketchup
Hermit successfully    looted!
test works
Returned: void
It does not print "test works" when it returns false, because instead of returning false it is actually aborting.
 

heeheehee

Developer
Staff member
That's just how ASH works. If you want to avoid the abort caused by a function that updates Mafia's status line, then you should do something with the return value; the best expression of intent is to catch it.
 

Irrat

Member
Adding to this discussion, if we're going to throw errors when attempting to buy clovers from the hermit. We really should give some way to tell if there's clovers at the hermit.

Currently there's no way from a script, outside of catching the error or parsing the result of executing the CLI command "hermit" to tell how many clovers there are in stock.

Not even a preference, which would make sense I believe.
 

Irrat

Member
Oh, this should actually be opened as a bug report.

It's not normal for "acquire 11-leaf clover" to throw an abort error is it?
The normal acquire error should be that it returns 0 as it couldn't acquire?
 
No, retrieve item always aborts unless you capture the return value. Which is really not that hard to do. The command/script just wants you to acknowledge that you're ok with it failing, and you'll handle it.
Code:
> ash retrieve_item(1,$item[mu cap]); print("test");

You need 1 more Mu cap to continue.
Returned: false

> ash boolean dummy= hermit(1, $item[11-leaf clover]); print("test");

Asking for 1 11-leaf clover, but 0 left today.
test
Returned: void

> ash boolean dummy= retrieve_item(85, $item[11-leaf clover]); print("test");

You need 1 more 11-leaf clover to continue.
test
Returned: void

> ash retrieve_item(85,$item[11-leaf clover]);    print("test");

You need 1 more 11-leaf clover to continue.
Returned: false

> ash hermit(1, $item[11-leaf clover]); print("test");

Asking for 1 11-leaf clover, but 0 left today.
Returned: false

> ash if ( hermit(1,$item[11-leaf clover]) ) print("success"); else print("failure");

Asking for 1 11-leaf clover, but 0 left today.
failure
Returned: true
 
Top