My personal Meat farming script

Veracity

Developer
Staff member
Heh. My To Do list says:

"Write note about combat filters taking round index (0 - x) rather than round number (1 - x)."

We are not talking about consult scripts, except insofar as combat filters are an alternative approach.

I think the original idea was that a combat filter would let you replace "line x" of a CCS - which is useless, since the combat filter has no idea of what the lines in the CCS section say.
 

Veracity

Developer
Staff member
Ah. Except, that doesn't actually take a "round". It takes an "index".

Code:
	public static Value get_ccs_action( Interpreter interpreter, final Value index )
	{
		return new Value(
			CombatActionManager.getCombatAction(
				FightRequest.getCurrentKey(), (int) index.intValue(), true ) );
	}
The more I study it, the more I see that the whole CCS handling code really depends on line indices. I'm not sure I want to touch it.
 

Theraze

Active member
Yeah, which is actually why people complain about BCA pulling a specific line out of their CCS. Oh well. It is what it is.
 

Veracity

Developer
Staff member
Time pranks:

Code:
static
{
    string [int] PRANK_GREETINGS;

    void add_prank_greeting( string message )
    {
	PRANK_GREETINGS[ count( PRANK_GREETINGS ) ] = message;
    }

    add_prank_greeting( "Booga booga!" );
    add_prank_greeting( "Tag! You're it!" );
    add_prank_greeting( "Didn't I just see you?" );
    add_prank_greeting( "Why are there so many %FRIEND%s in my timestream?" );
    add_prank_greeting( "Now that you have found me, I must kill you. Sorry." );
    add_prank_greeting( "Our tentacled masters demand I implant this tentacle in your head. Just hold still now..." );
}

void time_pranks( int minutes_left )
{
    if ( minutes_left <= 0 ) {
	return;
    }

    // load the set of prankees
    boolean [string] prankees;
    file_to_map( me + ".prankees.txt", prankees );

    int friends = count( prankees );

    string nth_friend( int n )
    {
	if ( n >= 0 && n < count( prankees ) ) {
	    foreach friend in prankees {
		if ( n-- == 0 ) {
		    return friend;
		}
	    }
	}
	return "";
    }

    int greetings = count( PRANK_GREETINGS );

    while ( minutes_left > 0 && friends > 0 ) {
	// Pick a random friend
	int n = friends == 1 ? 0 : random( friends );
	string friend = nth_friend( n );
	boolean enabled = remove prankees[ friend ];
	friends--;

	// You can enable/disable specific friends
	if ( !enabled ) {
	    continue;
	}

	string msg = PRANK_GREETINGS[ random( greetings ) ];
	msg = replace_string( msg, "%FRIEND%", friend );

	print( "Pranking " + friend + ": " + msg );
	cli_execute("timespinner prank " + friend + " msg=" + msg);

	minutes_left = 10 - get_property( "_timeSpinnerMinutesUsed" ).to_int();
    }
}

void time_pranks()
{
    // Use up all remaining minutes pranking friends
    time_pranks( 10 - get_property( "_timeSpinnerMinutesUsed" ).to_int() );
}
Veracity.prankees.txt has lines like this:

Code:
Bale	true
The boolean says whether this name is enabled or disabled.

Revision 17490 exits the Time Prank choice if the prank failed.
 

Bale

Minion
That's really nice. Now just to be perverse I'm going to throw this abomination at you...

Code:
for ( int n = friends-- == 1 ? 0 : random( friends ) , string friend = nth_friend( n ) , boolean enabled = remove prankees[ friend ], boolean enabled = remove prankees[ friend ] ;
   minutes_left > 0 && friends > 0 ; 
   n = friends-- == 1 ? 0 : random( friends ) , friend = nth_friend( n ) , boolean remove prankees[ friend ] , minutes_left = 10 - get_property( "_timeSpinnerMinutesUsed" ).to_int())

:D
 

Bale

Minion
I know, right? I've always assumed that's the reason ash didn't have java or c styled for loops. they're incredibly powerful, but capable of becoming so horrific in the wrong hands. I can't wait to see what zarqon gets up to with them, but I intend to be somewhat more careful since while I am fascinated with obfuscated code, I like to write code I can maintain.

I could probably write some entire scripts tucked into one of those for loops with an empty loop
 

Veracity

Developer
Staff member
Well, I figure that if people write code that even they can't maintain, that's their problem. One would hope that if they intend to share it, they will strive for clarity, though.

All styles of loop have their place. Just because Java for loops can replace any of them (except for repeat until), doesn't mean that your code will be maintainable if you misuse them.
 

Veracity

Developer
Staff member
I just updated the file on the initial post with the current version.

It is heavily commented up top to describe how it uses each IOTM - although it works fine for accounts that don't have them, like most of my multis - and for everything that different characters might want to do differently, the "configuration" section lets you specify what to do.

A lot of my previous "to do" list is done - the previously discussed Time Pranks, for example.

Bug fixes. Lots of little things showed up over the last 10 days on one character or another. No issues in the last several, so, this release.

Current to-do list:

// ****** To Do **************
//
// Secondary buffbot for when primary is offline
// When cheating deck, don't ask for unavailable cards
// Allow five distinct Witchess combats
// Better use of Dinsey foodcone and jumping horseradish
// If clip art is unconfigured, choose most expensive item(s)?

The first one is the only one that has bothered me; Testudinada has been off-line twice. The first time, so was Noblesse Oblige, so a backup buffbot would not have helped. The second time, N.O. was online. In both cases, restarting the script just picked up where it left off, and, Testudinada having come online, it worked fine.

I only have one character who doesn't know Ode, otherwise, I might feel more motivation to finish that feature.
 

Bale

Minion
The first one is the only one that has bothered me; Testudinada has been off-line twice. The first time, so was Noblesse Oblige, so a backup buffbot would not have helped. The second time, N.O. was online. In both cases, restarting the script just picked up where it left off, and, Testudinada having come online, it worked fine.

I only have one character who doesn't know Ode, otherwise, I might feel more motivation to finish that feature.

I use buffy. Buffy doesn't even need meat to know which buff to cast. Here's a snippet from my farming script.

Code:
	if(!have_skill($skill[The Ode to Booze]) && have_effect($effect[Ode to Booze]) < inebriety_limit() - my_inebriety()) {
		cli_execute("send to buffy || The Ode to Booze");
		cli_execute("wait 30; refresh status");
	}

I assume that you're already planning to use is_online() to choose between buffbots.
 

Veracity

Developer
Staff member
I already use is_online() to detect that my chosen buffbot is not available. I'll just need to have all three - Buffy, Testudinata, and Noblesse Oblige - ranked (presumably with Buffy first since she is free. Always? Once a day?) and go to the best one which is currently online before aborting.
 

Bale

Minion
(presumably with Buffy first since she is free. Always? Once a day?)

Buffy runs on a point system. You get 3000 MP worth of buffs a day. Casting Ode to Booze costs 42 MP (for 25 turns) out of the 3000 MP available to you. So... well, if you do nothing else with buffy other than Ode to Booze it is basically unlimited. She also has a web interface HERE.
 

Veracity

Developer
Staff member
Now that I'm done with Chakras, I'm back to this script. I uploaded a new version to the first post. Lots of little fixes and a few new features:

- Flush out wanders in a Hidden City shrine before going into the DMT, as suggested.
- Initial support for Sweet Synthesis.

Spleening is more complicated, now, since it involves both Sweet Synthesis and Numberology, but it works nicely. Since it's an interesting function, I insert it here for your amusement, no need to download the script.

Code:
void spleen_up()
{
    void use_spleen( int spleen )
    {
	item candy1;
	item candy2;

	void choose_candy( effect target )
	{
	    if ( target == SYNTHESIS_GREED ) {
		candy1 = $item[ bag of W&Ws ];
		candy2 = $item[ bag of W&Ws ];
	    } else if ( target == SYNTHESIS_COLLECTION ) {
		candy1 = $item[ Milk Studs ];
		candy2 = $item[ Milk Studs ];
	    }
	}

	// Synthesize to get configured farming effect
	if ( can_synthesize && synthesis_target != NO_EFFECT ) {
	    int turns_remaining = my_adventures();
	    int current_effect = have_effect( synthesis_target );
	    // Fudge factor: +25 to accomodate extra turns from wads or Pantsgiving
	    int synthesis_casts = min( spleen, ( turns_remaining - current_effect + 29 + 25 ) / 30 );
	    choose_candy( synthesis_target );
	    while ( synthesis_casts-- > 0 ) {
		if ( !sweet_synthesis( candy1, candy2 ) ) {
		    break;
		}
		spleen--;
	    }
	}

	// Chew wads for rest of spleen
	if ( spleen > 0 ) {
	    chew( spleen, TWINKLY_WAD );
	}
    }

    int current_spleen = my_spleen_use();
    int max_spleen = spleen_limit();

    if ( current_spleen >= max_spleen ) {
	return;
    }

    print( "Poisoning your spleen" );

    // We can combine spleen with Numberology

    int calculations_used = get_property( "_universeCalculated" ).to_int();
    int calculations_available = get_property( "skillLevel144" ).to_int();

    while ( current_spleen < max_spleen ) {
	int spleen = max_spleen - current_spleen;
	if ( numberology_available && calculations_available > calculations_used ) {
	    for i from 0 to spleen {
		if ( reverse_numberology( 0, i ) contains numberology_goal ) {
		    spleen = i;
		    break;
		}
	    }
	    if ( spleen == 0 ) {
		cli_execute( "numberology " + numberology_goal );
		calculations_used += 1;
		continue;
	    }
	}
	use_spleen( spleen );
	current_spleen = my_spleen_use();
    }
}
This will be better once Sweet Synthesis Phase 5 is done, but even with just this, the Meat/adventure yield of this script is much improved. Even with its suboptimal choice of consumables. :)
 

ckb

Minion
Staff member
This is interesting reading. Gets me thinking more about my own scripts and what they do, or could do. Thanks.

On a side note, Looking at various scripts and scriptors is fascinating with regard to syntax. Veracity and Ezandora write long and very spaced code. zarqon avoids white-space like its a danger to his existence. Bale and I seem to fall somewhere in between.
 

heeheehee

Developer
Staff member
Veracity's style looks like the same as the Mafia codebase, which isn't a surprise. I suspect a lot of Ezandora's code is generated, but it does follow Allman (BSD) style. I personally tend toward K&R style, myself. I suspect Bale / Zarqon are self-taught (and don't do this sort of thing for a living), so their individual styles are more organic (and not as easily attributable to a particular style).
 

Veracity

Developer
Staff member
Well, I do cuddle braces, which is not the KoLmafia standard. But that's how I write C, so I do it in Java - and ASH - too.
 

Veracity

Developer
Staff member
By the way - use_spleen() is simplified, now that ASH can pick candies and synthesize for you.

Code:
    void use_spleen( int spleen )
    {
	// Synthesize to get configured farming effect
	if ( can_synthesize && synthesis_target != NO_EFFECT ) {
	    int turns_remaining = my_adventures();
	    int current_effect = have_effect( synthesis_target );
	    // Fudge factor: +25 to accomodate extra turns from wads or Pantsgiving
	    int synthesis_casts = min( spleen, ( turns_remaining - current_effect + 29 + 25 ) / 30 );
	    while ( synthesis_casts-- > 0 ) {
		// Flags = 1 to choose "available" candies vs. "cheap" candies
		if ( !sweet_synthesis( synthesis_target, 1 ) ) {
		    break;
		}
		spleen--;
	    }
	}

	// Chew wads for rest of spleen
	if ( spleen > 0 ) {
	    chew( spleen, TWINKLY_WAD );
	}
    }
I chose to use candy in inventory because all of my characters have a years worth of cheap candies and are thus immune to market swings.

There is also the issue that disabled player stores show up in mall searches and artificially lower the "expected" price you'll pay for some candies. I think that is a KoL bug: why does a mall search even show you the stores of disabled players, since there is no indication you can't buy it before trying and being told "nope"?

I'll submit a bug report...
 

Veracity

Developer
Staff member
How heavy is your hobo monkey? Because a tot with the pirate outfit is +300% Meat Drop. According to the Wiki page for the Hobo Monkey, it looks like you'd need something more than 65 lbs. to beat that.

Of course, the script also stasises with a Hobo Monkey to get a little more meat each combat.

I'll make a configuration option. I have other fixes to share, anyway.

In the mean time, you can change the following line:

Code:
familiar farm_familiar = have_tot ? TOT : HOBO_MONKEY;
to:

Code:
familiar farm_familiar = HOBO_MONKEY;
 
Last edited:
Top