Feature Add Muffin Command

Add a GCLI command to pick up and/or order a new muffin from the monorail breakfast counter. Currently this requires a scripter to navigate an NC chain that changes depending on your current # of adventures, your # of earthenware muffin tins in inventory, and whether you've ordered/picked up a muffin already today.

Suggest something like "muffin ( collect | order ) [ blueberry | chocolate chip | bran ]"
 

Veracity

Developer
Staff member
It is a tricky situation. VMF supports eating (and ordering) one muffin a day, assuming that you own exactly one earthenware muffin tin and it is either holding a muffin or is retrievable.

Your proposed command seems intended to be used like this:

muffin collect
(if succeed, eat whichever muffin was collected)
muffin order (new muffin)

or maybe

(maybe eat current muffin)
(if have muffin on order, muffin collect)
muffin order [new muffin]

There is a property - muffinOnOrder - which tells you if you can try to collect - if KoLmafia saw you order and you didn't order today.

Please describe your use case(s) and how you expect this to work.

FYI, here is VMF's support for this. This was not easy to get right, so I feel your pain.

Code:
boolean eat_muffin()
{
    item available_muffin()
    {
        foreach muffin in valid_muffins {
            if ( available_amount( muffin ) > 0 ) {
                retrieve_item( 1, muffin );
                return muffin;
            }
        }
        return NO_ITEM;
    }

    int monorail_index( string text )
    {
        foreach n, button in available_choice_options() {
            if ( button == text ) {
                return n;
            }
        }
        return 0;
    }

    void visit_breakfast_counter()
    {
        int index = monorail_index( "Visit the Breakfast Counter" );
        run_choice( index );
    }

    void order_next_muffin( item previous )
    {
        item next_muffin = muffin_to_order;
        if ( next_muffin == NO_ITEM ) {
            switch ( previous ) {
            case BLUEBERRY_MUFFIN:
                next_muffin = BRAN_MUFFIN;
                break;
            case BRAN_MUFFIN:
                next_muffin = CHOCOLATE_CHIP_MUFFIN;
                break;
            case CHOCOLATE_CHIP_MUFFIN:
            case NO_ITEM:
                next_muffin = BLUEBERRY_MUFFIN;
                break;
            }
        }

        // We have to search for the correct option; apparently, some
        // times you are also offered the chance to buy another muffin tin.

        int index = monorail_index( "Order a " + next_muffin );
        run_choice( index );
    }

    void return_to_platform()
    {
        int index = monorail_index( "Back to the Platform!" );
        run_choice( index );
    }

    void leave_platform()
    {
        int index = monorail_index( "Nevermind" );
        run_choice( index );
    }

    item last_muffin = NO_ITEM;

    item available = available_muffin();
    // Eat a muffin
    while ( true ) {
        // If we have a muffin, eat it now
        if ( available != NO_ITEM ) {
            eat_food( 1, available );
            last_muffin = available;
            break;
        }

        // No muffin in inventory. Make sure we have a muffin tin in
        // inventory, if possible, in case we need to order a muffin.
        if ( available_amount( MUFFIN_TIN ) > 0 ) {
            retrieve_item( 1, MUFFIN_TIN );
        }

        // Visit Breakfast Counter to pick up our order, if any.
        visit_url( "place.php?whichplace=monorail&action=monorail_downtown" );
        visit_breakfast_counter();

        // If we got a muffin, exit the breakfast counter and eat it.
        available = available_muffin();
        if ( available != NO_ITEM ) {
            return_to_platform();
            leave_platform();
            continue;
        }

        // We did not have a muffin waiting. We can't eat today.
        if ( available_amount( MUFFIN_TIN ) > 0 &&
             get_property( "muffinOnOrder" ) == "none" ) {
            // Order a muffin for tomorrow
            order_next_muffin( NO_ITEM );
        }

        // Exit the Breakfast Counter. We're done here.
        return_to_platform();
        leave_platform();
        return false;
    }

    // We've eaten a muffin and have a muffin tin in inventory.
    // Order a new muffin

    visit_url( "place.php?whichplace=monorail&action=monorail_downtown" );
    visit_breakfast_counter();
    // We might have already ordered a muffin today
    if ( get_property( "muffinOnOrder" ) == "none" ) {
        order_next_muffin( last_muffin );
    }
    return_to_platform();
    leave_platform();

    return true;
}
 
My current daily plan is to collect a muffin, eat it, and then order a new muffin for the next day. I am looping, so after ascending when I go to pick up a muffin, it will only provide an empty earthenware muffin tin, but on d2 it will provide the muffin I ordered.

I realize that this is something that can be scripted, and I am making plans to do so. I expect that other people would gain benefit from having native support for muffins, probably for their pre-ascension and post-ascension scripts, but also possibly for other uses.

I also occasionally access KoL outside of kolmafia, so a solution that doesn't rely on always knowing which muffin is available would be preferred. (i.e. allowing "muffin collect" to access the breakfast counter even if kolmafia doesn't think there is a muffin on order).
 
Top