Random verb selection on a MUCK

On SpinDizzy MUCK there are a bunch of “hug” verbs which are a bit whimsical and a bit nonsensical, and for reasons that are too silly to get into, I have been locked in an eternal battle with Austin in which I am constantly creating more.

A while back I ran into an issue with a few miscellaneous world scripts breaking around me, and it turned out to be that one of the global scripts, for reasons I’m still unclear on, attempts to parse every verb attached to a character object, and for other reasons I am also unclear on, it ends up attempting to push every name for the verb onto the stack.

The stack has a limit of 1024 entries, so when I exceeded 1024 names on my hug-verb action, things started to break, badly.

So to fix this I ended up splitting my hug-verb action into multiple actions, basically just creating a new one whenever my main one is nearing 1024 entries.

I also have a script, randomverb, which selects a verb at random from my hug-verb action, by using MPI’s lrand function, namely, it was:

{lrand:{fullname:plaid},;}

(plaid being the primary name of the hug-verb action, for Reasons) but when I split it into two I needed to concatenate them together:

{lrand:{fullname:plaid};{fullname:patpetpot},;}

Tonight I thought I was nearing another verb-count limit, so I split it out into a third list. (This is very important, you see.)

But then in investigating that, I discovered that MPI also has a parameter length limit of 8191 bytes, and the concatenated list was always quite a lot longer than 8191 bytes — so it actually wasn’t selecting from all of my verbs! And after splitting things out, it was even worse at selecting from my complete set of verbs! The horrors!

Anyway, it turns out that I didn’t actually need to make a third list, I just needed to fix my script to not assume that it can shovel arbitrarily-long strings around. So, now it looks like this:

{null:{with:verbs,#36532\r#22013,
    {with:total,0,
        {foreach:l,{&verbs},
            {inc:total,{count:{fullname:{&l}},;}}
            {if:{gt:{strlen:{fullname:{&l}}},8000},
                {tell:WARNING: length of {name:{&l}} is {strlen:{fullname:{&l}}} bytes - consider splitting it}
            }
        }
        {tell:Total verbs: {&total}}

        {with:choice,{dice:{&total}},
            {foreach:l,{&verbs},
                {with:items,{fullname:{&l}},
                    {with:count,{count:{&items},;},
                        {if:{and:{le:{&choice},{&count}},{ge:{&choice},1}},
                            {tell:{sublist:{&items},{&choice},{&choice},;}},
                        }
                        {dec:choice,{&count}}
                    }
                }
            }
        }
    }
}}

(#36532 and #22013 are the database references of my two increasingly-ridiculous hug-verb actions.)

MPI is a pretty crappy language with all sorts of little gotchas, but hopefully this will prevent things from going wonky again. At least until I find some other arbitrary string-processing limit due to totally reasonable assumptions made 30+ years ago.

There’s also probably some clever mathy way to avoid the first foreach (that sums up the total number of verbs) but given how difficult it is to keep MPI code clear to begin with, I’m fine with this two-pass solution.