My personal Meat farming script

I noticed that myself after G Lover, when I use this script for the rest of the last day before diving through the gap. My workaround is to simply go to Barrrney's Barrr for a combat. I suppose if I'd not gotten the swashbuckling getup during the run (which I always do, so I can get a bridge), the script could go to Obligatory Pirate Cove.

I'll be freeing the king in a few minutes. I'll look into improving the "get a pirate costume" function.

(By the way - the reason for the pirate fledges is because BelowDecks has no non-combats and you can therefore get the costume with at most one turn of combat, modulo time pranks or other wanderers.)
 
Last edited:
Revision 102 will fight a pirate Belowdecks if you have pirate fledges, in Barrrney's Barrr if you have Swashbuckling Getup, or at the Obligatory Pirate Cove if you have none of those.

I suppose it could/should go to the Poop Deck with pirate fledges, in case you haven't unlocked Belowdecks, although if I have pirate fledges, it is because I took the pirate path to the Palindome.
 
Interesting. Finished a G-Lover Normal (since I have all the g-points I need and want to make sure I finish my in-season G-Lover runs while I can still upgrade my Garland, just in case you can only do that in-season) run.

Made lots of mistakes, since day one was running as if I were Hardcore, rather than Normal, since it had been so long since I'd thought about "pulling" things.

But, had 50+ turns left after freeing the King.

Got my facsimile dictionary and went to the script to burn the remainder of my turns.

Since I had the Swashbuckling Getup and no pirate Fledges, it went to Barrrney's Barrr - and very first adventure was a choiceadv which changes based on your class - and it took the option that gave me 3 drunk and stats, leaving me overdrunk.

Perhaps I didn't have my choice options set correctly - but this script should not do that to you.

If we adventure in the Barrr to get the li'l pirate costume, I'll make it set the choice option, based on mainstat, to NOT get you overdrunk.

(I know there is code to make the Relay Browser spoilers show you what you'll really get, but since I normally never automate, I had no idea how we handle that setting. It's time to learn...)

(Little harm done; I ascended and started day one of my next G-Lover run - and made decent use of my day one pulls, in my opinion, given that I wasn't actually going to run all the turns for day one.)
 
Revision 107 soups up food consumption.

- If you have Spaghetti Breakfast and have not used it today, eat one of those first
- If you have jumping horseradishes in inventory, eat up to 5 of them (the number per day you can generate with a Witchess Set)
- If you have access to Dinseylandfill, eat as many Dinsey food-cones as you can afford
- Fill up remaining fullness using one of two strategies:

boolean calculate_optimal_consumables = define_property( "VMF.OptimalConsumables", "boolean", "false" ).to_boolean();

If VMF.OptimalConsumables is false (the default)

- Eat as many 3-full foods from (an expanded) list as possible
- Fill up the rest of the way from (an expanded) list of 1-full foods

By and by, I will make those lists configurable.

If VMF.OptimalConsumables is true:

- Use vcon's calculations of "most profitable" (expected meat gain - cost) foods to fill up with a decent approximation of maximum expected profit

xKiv has a real optimal approach. I'll look at it, by and by.
 
I keep getting an error of "Don't know how to retrieve a (unknown item -1)" after it searches through all the various drinks with 1 drunkenness left.

I poked through the code a bit, I have no robortender.
 
Last edited:
You don't need a robortender; you just need to be able to buy a robortender drink in the mall, since those are the most cost-effective 1-drunk drink.

I guess if your expected "profit" per adventure is lower than that price - in which case you are expected to LOSE money if you buy and drink the drink - we won't find a cost effective drink.

Hmm. We currently only get prices for "awesome" and "EPIC" drinks. if your MPA is too low, maybe we need to look even lower?

I'll investigate.
 
I don't see how that could happen unless you have value of adventure set really low.

Revision 108 will assume that your expected Meat Per Adventure is at least 500, regardless of the value of various properties.

That is plenty high enough to be able to afford a robortender drink.
 
That would probably happen if I forgot to set it, right? Oops.

...out of curiosity, where would I set that?
 
Last edited:
Well, the default KoLmafia setting "valueOfAdventure" is 500. If you have never run this script before, that is what it would use.
If you have run this script before, it will calculate expected earnings based on actual values: what it spent vs. what it earned.

Now, even my characters who have no IOTMs and have never ascended are getting ~1700 or so Meat per Adventure, calculated as (total Meat found - total costs). That is plenty good enough to eat and drink awesome or EPIC things which give you lots of adventures.

It is a very recent change to have your expected profit actually be a factor; there used to be a hardcoded list of things it would consider looking at. In particular, if it wanted a robortender drink, it chose the cheapest in the mall - which is still what it does, but now it's going through my new vcon library, which does take expected profit into account. I'm not sure how you could end up with a very low meat per adventure value unless you let it eat & drink - spending Meat - and then aborted it after just a few turns. That could give you a NEGATIVE expected yield. I did not consider that possibility.

You let the script run to completion over the course of several days, and you'll end up with a reasonably accurate expected profit value.

In the mean time, it assumes you'll get at least 500 meat per adventure, on average, and should be able to get you good things to eat and drink within that constraint.

You didn't "forget to do" anything. I very recently changed the code to look at different values which were, perhaps, not suitable for brand new users of the script - but which are giving all of my characters a whole lot more Meat per day.

Sorry for the inconvenience. Hope it works well for you now!
 
Revision 109 has an experimental feature: semirare farming using Lucky Lindys.

Looks to me like there are a variety of semirares which are cost effective to farm. Probably not if you are using fortune cookies; that is a crappy food that yields a single adventure and it could give you up to 3 numbers to test. Lucky Lindys, perhaps. You have to be in a clan whose VIP room has a speakeasy with that drink.

I might be persuadable to add fortune cookie support, although I wouldn't use it; the new code goes after the "first Fortune Cookie Counter" and only consumes something if there is no longer a "first Fortune Cookie counter" active, so it should just work even if there are multiple counters.

Code:
// *** Semirare hunting ***
//
// There are two ways to predict when a semirare is available:
// - eating a fortune cookie (a crappy 1-fullness food) will give you 3 lucky numbers. One of them will be the semirare number
// - drinking a Lucky Lindy (a good 1-drunk booze) will burp out the exact number of adventures to the next semirare
//
// It is not cost-effective to use fortune cookies; their adventure yield is too low and they are not guaranteed to give exactly one valid number
// Lucky Lindy may or may not be cost-effective; they give from 2-4 turns and give the required number.
//
// This script will optionally farm semirares using Lucky Lindys

boolean should_hunt_semirares = define_property( "VMF.HuntSemirares", "boolean", "false" ).to_boolean();

// In order to hunt semirares, you must specify at least two locations
// to visit; since you cannot collect the same semirare twice in a row,
// we must alternate.
//
// There are a many locations to choose from. This script is very
// simple-minded in how it handles them: it assumes that you have access
// to all configured locations, that there are no special requirements
// to adventure there (such as visiting The Sea, for example), and if
// the semirare leads to a choice adventure, you have configured the
// desired choice.

location_list semirare_locations = define_property( "VMF.SemirareLocations", "location", "", "list" ).to_list_of_location();
So, this would work:

Code:
set VMF.HuntSemirares=true
set VMF.SemirareLocations="The Sleazy Back Alley|The Outskirts of Cobb's Knob|Cobb's Knob Harem"
to cycle through those three locations collecting semirares.

As noted in the comment, the script will not suit up to go to The Sea or the 8-Bit-Realm, nor will it verify that you even have access to a location. I could easily enough do the former, but am not interested in writing (or even importing) code to do the latter.

I tested this today and it collected 2 semirares (and got the counter for the first one tomorrow) as well as busting every ghost, so my code to have multiple timed things going on seems to work.

Let me know if you see glitches, whether or not you using this feature.
 
You did it! Thank you! :)

Note the new commit where, if we bulk-update 1000 items of mall prices via mall_prices(), it writes mallprices.txt once, rather than 1000 times.

Yes! I had previously noticed a pause after the mall search, but even with the pause it was a marked speed improvement. Now it's lightning-fast! The time could be halved again for my case by somehow sharing the price cache across mafia instances (I usually run two at once), but that years-old feature wish of mine would no longer save the hundreds of server hits that it once would have, thanks to this latest reduction.

Things I could do:

- do it with fortune cookies (not too hard)
- suit up appropriately for The Sea, The 8-bit Realm, etc. (easy)
- full "can adventure" type stuff for semirare locations. (annoying, medium hardness)
- full support for "which choice to take for semirares" (annoying, not necessary, since you can specify that in KoLmafia GUI)

Let me know which things are critical for your use cases.

  • Fortune cookies are not necessary for my case since I don't automate consumption during a run.
  • Though it is outside your scriptcosm, CanAdv is pretty comprehensive these days! It could handle steps 2 and 3 for you without excessive annoyance on your part.
  • Speaking of outside your scriptcosm, I (and probably many others who want to farm/have been farming semirares in aftercore) are already using a counterScript that handles things like location selection, gearing up, etc. Perhaps you could check if counterScript is already set, and if so, let that script assume responsibility for farming semirares.
Thanks for this nifty new feature.
 
Last edited:
First off: I very much appreciate the work you're putting in to this script and it's ancillary parts. They've been a huge improvement in "quality of life" for aftercore meat farming.

I realize that what I'm about to mention may be an edge-case and I can work around it but...

When the script adventures in the Gingerbread City, if a Hallowiener Dog choice adventure hits, the script errors out.

Code:
[13964] Gingerbread Upscale Retail District
Encounter: Your Dog Found Something Again
> Expected choice/option 1209/2 is unavailable; submitting 1108/0
choice.php?pwd&whichchoice=1108&option=0
Encounter: Your Dog Found Something Again
> Expected choice/option 0/0 is unavailable; submitting 1108/0
choice.php?pwd&whichchoice=1108&option=0
Encounter: Your Dog Found Something Again
> Gained 1,574 sprinkles in 18 turns. Sprinkles/Adventure = 87
> Cumulative = 480,317 sprinkles in 6,886 turns. Sprinkles/Adventure = 69
> Spent 0 sprinkles. Cumulative = 0
> Net income = 350 Meat in 21 turns. Meat/Adventure = 16
> Cumulative income = 278,452,585 Meat in 79,471 turns. Meat/Adventure = 3,503

I've only seen this happen in Gingerbread City and it's happened more than once. Even though the choiceAdventure in question has a default set. It's almost as if the script is confused about which choiceAdventure is the current one.

Any thoughts?
 
I could have sworn that it used to handle it because, if I recall, the Hallowiener Dog used to be excluded from the Gingerbread City.
I'll take another look.

Edit:

Maybe not. If it encounters a choice when it wasn't expecting one, it will tame turtles for you (and understand that a KoL bug makes that advance time in the city, even though it don't take a turn). For any other unexpected it will take what you have configured, so it should do the Hallowiener Dog choices - and will not advance the City clock.

However, if it expects Noon or Midnight, it does not handle either turtles of the Hallowiener Dog.
Since turtle taming advances time, I sure hope it never interrupts Noon or Midnight.
But a Hallowiener Dog adventure SHOULD be safe.

I'll see what I can do.

(According to the Wiki, the dog will appear 5, 20, and 50 turns in a zone, and then every 50 turns. It will take a number of days to be able to force the dog adventure to be Noon or Midnight. But I will optimistically code for it, and perhaps you'll test it for me. ;) )
 
Last edited:
Revision 111 of Gingerbread City.ash should do that.

I ran the script and used my daily turns in the Gingerbread City. The dog showed up - not at Noon or Midnight - it took the configured choice, which did not use a turn nor advance the clock., and then proceeded to get the Midnight choice a few turns later.

Obviously, did not test the dog appearing at Noon or Midnight because he didn't.

You tell me how it works next time it happens to you. It SHOULD take the dog choice and then try again to do your Noon or Midnight choice - and succeed at it.
 
And, by the way, Revision 110 of VeracityMeatFarm should work correctly if you need to look for paranormal activity exactly when the choice adventure in Barf Mountain appears. I broke that when I introduced semirare hunting, but it works again now.
 
The current revision of VMF just overdrank a Lucky Lindy with 238 turns left and then aborted due to being too drunk to continue. Ouch! Nothing a cuppa Sobrie tea can't fix, but probably not intended behavior.

Also, did you see my edit above?
 
Last edited:
The current revision of VMF just overdrank a Lucky Lindy with 238 turns left and then aborted due to being too drunk to continue. Ouch! Nothing a cuppa Sobrie tea can't fix, but probably not intended behavior.
Oops. Sorry!

Hard to understand why; I thought I coded it to reserve enough inebriety for all (up to 3) available Lucky Lindys.

I assume it did this after finding a semi-rare? What-all did it drink, in order, before doing that? I'll compare that to the drink_up logic and see if I can discern the error.

Also, did you see my edit above?
I did. I'll think more on it, by and by.
 
Revision 112 will not drink Lucky Lindys if you have no inebriety left. It is also less stringent at validating speakeasy availability if you've already drunk 3 drinks - which will show Lucky Lindy as unavailable - since you won't be drinking them anyway.

I'm still wondering how my "leave enough space to buy and consume 3 speakeasy drinks" code got fooled, such that it drank to max inebriety while there was still another Lindy expected to be drunk. So, I'm still curious about when and what was drunk in the case when it overdrank.
 
Ah, the initial consumption was performed by my login script, so your code remains unfooled. I don't run VMF on all characters, and I like to do other things (at the moment, Neverending Party quests) before using VMF as a "finish out my turns" sort of thing, so I haven't switched over to using VMF as my food-eater and drink-drinker yet. I'm going to have to import your script and call the necessary consumption functions (heh) in my login script, I think.


EDIT: Ran into another issue due to handling consumption separately beforehand. VMF will enter an infinite loop if you just got a semirare and need a new counter, but are already at your inebriety limit. My understanding of the cause is tentative, but I appear to have solved it by changing line 1853 to:

Code:
 	will_hunt_semirares = speakeasy_drinks_available && my_inebriety() < inebriety_limit();

Remaining suggestions:

if (get_property("betweenBattleScript") == "BestBetweenBattle.ash"), skip hunting for ghosts. Presently BBB's code will fire first anyway, killstealing the ghost from under VMF's nose.

if (get_property("counterScript") != ""), let that script actually go get the semirares when the counters come up. Unlike the previous, in this case VMF goes first (or rather, the counterScript goes first but is then interrupted by VMF...?), and then it seems that if you don't get a semirare from your counter the counterScript jumps in and also tries to get your semirare after VMF does, wasting a turn somewhere.

If you want to keep VMF more self-contained, the above two could just be validation issues, but I'd love if VMF could recognize the existence of my other scripts and politely allow them to keep their jobs.
 
Last edited:
Back
Top