MPI for Sizeshifters and Shapeshifters



One of the neat things about being on a muck versus a chat client is that you can play with the text of your description and have it do some pretty amazing things automatically. One way to do that is with a built-in language called MPI (Message Parsing Interpreter). There are a great many tutorials and reference sites on the Web for MPI, most notably the official MPI Manual. The following page is not meant to be instructive about MPI itself, and a basic knowledge of how to get around on a muck, how to write simple descriptions is assumed, as is some basic knowledge of MPI. This is a page of some things that I've used MPI for that I think others might find handy and draw ideas from. If you have any questions or better ideas on how to do things, you can certainly e-mail me. I'd love to hear them!

I share this code mainly because there's not a whole lot of information about this specific type of thing on web, at least not that I've found. If you understand it and want to use or adapt parts of it, go for it. The only thing I ask in return is that if someone asks you how you did what you did, that you point them here or give credit where it's due. And if I've helped you out or given you an idea of something new to do, I'd love to hear about it as well!

One word of warning. I have taken out many of the safeguards I have in my code for the sake of the examples here, mainly because they had my dbref # in them. For this reason, strange things may happen should someone with props named the same things as yours look at you. It would be wise to adjust your {prop:} commands accordingly. ;)

And finally, I know there are better and worse ways to do what I've done here. This is simply how my system evolved. At some point, I may overhaul it and make it all concise and elegant, but right now it meets the main criterion I have for such things: It works. I started with the grow and shrink commands a long time ago, then branched into the species settings, then branched into my size-specific lists, then my clothing, and only recently added the part that sets my height in whospe. In other words, none of this was planned from the beginning, but rather put together as inspiration struck, and the code definitely shows that in some places. Take it as an object lesson in legacy programming. :)

Enough babbling! Enjoy!


Modular Desc

A good habit to get into on a muck is writing what can be called a modular description. Instead of writing all of your description as a single unit, you split it up into parts. For example, let's say I set up a simple description like this:

@desc me = Mataki is a tall, brown wolf, around seven feet in height. She is dressed in a blue, loose-fitting T-shirt and a pair of old, worn blue jeans.

While this is nice, if I want to change any part of it, I end up having to change the whole thing at once. If I want to change my height to 100 feet, I have to redesc myself with "100" in the place of the "seven". If I want to wear different clothes, I have to rewrite my desc with different clothing and resend it to the muck. This may not be much of a problem for small descs like this one, but it gets very problematic for larger ones. Here, then, is an example of my brown wolf form desc, and the code that generates it.

Description:

     Mataki is a brown-furred wolf femme, 10' 0" in height. She is lean and powerful, taking pride in her body, working out frequently to keep it in shape. Speaking of shapes, hers is curvy, her feminine hips wide and toned, her chest showing off her two largish brown-furred orbs. Her arms and legs are long and muscular, also well-toned and smooth. As you look over her body, you hear her giggling and are drawn to her smiling face. Her intelligent yellow eyes look at you warmly, her dark brown muzzle smiling with contrasting white teeth. As she smiles at you, her long, brown tail wags lazily behind her, showing her carefree spirit. Her current size puts her much taller than normal, more than twice her original height. Her smile widens a bit as she considers her new stature, her bigger muscles flexing and relaxing when she moves around.
     Today, Mataki wears a navy blue tank top cut off just below her breasts with the letters ZQI in yellow reading rather distorted across its front. She also wears a matching pair of blue denim shorts.

Code:

{eval:{list:{prop:species}_form}} {if:{lt:{prop:height},18000},{eval:{list:size_out}}}{if:{ge:{prop:height},18000},{eval:{list:size_out2}}}
Today, Mataki wears {eval:{list:{prop:clothing}_out}}

You can see that the code to generate the desc is much shorter than the desc itself. This is done by using lists. A list is just a bunch of text that's stored on a player or an object. I use lists to hold all my different forms, my different outfits, and my different size descriptions. Everything in magenta, for example, is generated by the appropriate species list. Everything in red is generated by the appropriate size list, and everything in blue is generated by the appropriate clothing list. The next sections of the page will show how each of the lists works.

By the way, knowing how to make a list is something you'll definitely need to know. The program to do this is called lsedit. Here's a good lsedit tutorial.


Changing Species

On FurryMuck, as on must furry mucks, there is a species property for every player. People set this property to show what species they currently are. My description uses that property to determine which list it should display, and it uses the code {eval:{list:{prop:species}_form}} to do this. Here's how:

If you look at my Background page, you'll see a list of all my different forms at the bottom. I have each of these forms in a different list. The hyena form is stored in a list called hyena_form, the lioness is stored in a list called lioness_form, and so on. I basically just named the lists the same as the species they represent, plus a _form on the end. This allows me to do a neat trick with my desc that keeps me from having to have a lot of {if:} statements cluttering up the code. I could, for example, do this:

{if:{eq:{prop:species},wolf},{eval:{list:wolf_form}}}{if:{eq:{prop:species},hyena},{eval:{list:hyena_form}}}...etc.

And this is, in fact, how my species part of the desc looked until I got too many forms to deal with and had {if:} statements overrunning the thing. Using the {eval:{list:{prop:species}_form}} instead has the following effect. The {prop:species} is evaluated first, so if I'm currently a wolf, the code gets replaced with {eval:{list:wolf_form}}. If I'm a hyena, it gets replaced with {eval:{list:hyena_form}}. Pretty neat! If you plan out your names for your lists carefully like this, you can save yourself a lot of work typing all those blasted {if:}s!

Another handy hint: I always use {eval:}s along with my {list:}s because I never know when I might want to embed more MPI in a list further down the way. If you don't put an {eval:} before a {list:}, any MPI in the list you're calling won't get parsed, but instead will just be spewed out as code. That's not something that looks really good in a description. ;)


Size-Specific Descriptions

One thing I realized after being on FurryMuck for a while was that being different sizes often meant writing completely different descriptions for each "level" of size. Let's face it, a 150' wolf should look a bit more menacing than a 6' one! There should at least be something to give a sense of scale in a macro desc, as simply replacing a height prop in an existing desc doesn't always work. So, I came up with the idea of having a specific portion of my description tailored to match my current size. This kept me from having to rewrite everything completely for every level; instead, I could simply write a sentence or two and insert them in the appropriate place. This is done with the above portion of the description:

{if:{lt:{prop:height},18000},{eval:{list:size_out}}}{if:{ge:{prop:height},18000},{eval:{list:size_out2}}}

This code checks my height against 18,000 inches (1500 feet). If it's less than that, it looks in the list size_out. If it's greater, it looks in the list size_out2. I had to do this because I got a bit carried away with writing the size level sentences, and I wrote 17 of them. The if statement to do this was too big to fit in one line of code, so I had to split it up into two lists. (By the way, I know I could combine these into one if statement; I'm just too lazy to change it. ;) ) To see what each list does, let's look at what's in the size_out list:

{if:{and:{ge:{prop:height},90},{lt:{prop:height},120}},{eval:{list:size01}}}
{if:{and:{ge:{prop:height},120},{lt:{prop:height},240}},{eval:{list:size02}}}
{if:{and:{ge:{prop:height},240},{lt:{prop:height},480}},{eval:{list:size03}}}...

There are about seven more if's in the list, but they're all very similar to these. The first line of code there checks to see if my height is between 90 inches and 120 inches (about 7' 6" to 10 feet). If it is, it puts the list size01 in my desc, which looks like this:

Her current size puts her a bit taller than normal, and the smile on her face gives evidence that she enjoys it quite a bit, standing head and shoulders above the average furry populace.

The next line checks to see if I'm 120 inches to 240 inches (10 to 20 feet), and if so, puts the following text, located in the list size02 in my desc:

Her current size puts her much taller than normal, more than twice her original height. Her smile widens a bit as she considers her new stature, her bigger muscles flexing and relaxing when she moves around.

And finally, the last line of code checks to see if I'm between 240 inches and 480 inches (20 to 40 feet), and if so, puts the following text from size03 in my desc:

Her current size gives her a bit of difficulty getting around in a normal-sized world, as she would be a tight fit in most rooms, assuming she could crawl through the door. Outdoors, where she probably belongs at this height, she would be taller than most small houses and trees.

That last sentence is a good example of what I mean by giving scale in a description, and most of my remaining size sentences are like that. You'll just have to catch me online to see the rest of them. ;) By the way, there's nothing stopping you from putting even more MPI in these little sentences. For example, here's my size05 list:

Her current size definitely puts her in the giant range, as she could currently look on the roof of a {div:{prop:height},150}-story building without even having to stand on the tiptoes of her {div:{prop:height},72}-foot long feet, and her {div:{prop:height},144}-foot long muzzle might look fairly scary to anyone that might happen to be there.

This inserts some numbers to tell how many stories tall I am (assuming a story is 150 inches), and how long my feet and muzzle are, which are of more than passing interest to some people. ;) So, if I were 100 feet tall, the appropriate part of the desc would look like this:

Her current size definitely puts her in the giant range, as she could currently look on the roof of a 8-story building without even having to stand on the tiptoes of her 16-foot long feet, and her 8-foot long muzzle might look fairly scary to anyone that might happen to be there.

Pretty neat! This is the part of my desc that could probably be tweaked and refined quite a bit. I know some ways to do this, and as I've said, I've just been too lazy. If you have any ideas, though, I'd be glad to get some e-mail from you.


Changing Clothing

This last part of my desc works very much like the code in the Changing Species section above. Rather than rehash the explanation, here's the bit of code:

Today, Mataki wears {eval:{list:{prop:clothing}_out}}

So, once again, if I name my clothing lists carefully, I can simply set the prop called clothing to be whatever I'm wearing, and the appropriate clothing list will be displayed.


Putting A Height In The Species Prop

In the past couple of years, I've noticed some people have their height listed along with their species whenever a whospe is done on the room. I thought that was a neat idea, and after several failed attempts (you can't just stick MPI in the species prop and expect it to work), I figured out a way to do it. There is a prop you can set on yourself called species_prop. It holds the name of the prop that will be displayed for your species whenever someone does a whospe. So, I made a prop on myself called ws_prop, and I pointed species_prop to it. Ex: @set me=species_prop:ws_prop.

I have commands that change my size called grow and shrink, respectively. (Duh!) Whenever I do one of these, I simply make sure to store the size and my species over to ws_prop. So, if I grow to 100' tall hyena, the grow command itself sends 100' and hyena over to ws_prop, and since my species_prop points to ws_prop, 100' hyena will get displayed for my species. This is explained a bit more in the next section.

Confusing? It can be. It reminds me of pointer variables, which can cause a lot of headaches. The whole reason I did things this way was that I already based my species descs off my species prop, so if I started messing with the species prop directly, I'd have to change the way I did my Changing Species code. Yet another example of working around what you've already done. ;)

The docs for what I've tried to explain here can be found by doing a whospe #help on FurryMuck, by the way.


Grow And Shrink

The last part of my MPI system that I haven't covered is the one at the heart of it all, the commands I use to actually change my size. I use two easy-to-remember commands. Grow makes me bigger, and shrink makes me smaller. For the MPI of the command, I use the @fail prop, just because it's how I learned to do things. Here's the code:

You grow to {store:{add:{prop:height},{dice:{div:{prop:height},{&arg}}}},height} inches. ({store:{if:{lt:{prop:height},360000},{div:{prop:height},12},{div:{prop:height},63360}}{if:{lt:{prop:height},360000},',-mile} {if:{lt:{prop:height},120},{mod:{prop:height},12}"} {prop:species},ws_species,me})

The green code above is the part that actually changes my size. I like an element of randomness, so I use the dice command to randomly determine how much I'll grow. The &arg is an argument I pass to the command. It basically sets a limit on how much bigger I'll get, on the order of my height divided by x, where x is the argument. For example, if I'm 72 inches tall, and I type grow 1, I have a possibility of growing anywhere from 1 to 72 inches. If I type grow 2, I have a possibility of growing anywhere from 1 to 72/2 (or 36) inches. If I type grow 3, I have a possibilty of growing anywhere from 1 to 72/3 (or 24) inches, and so on.

The red code above is the part that stores my height and species in my ws_species prop. If I'm taller than 10 feet, it leaves out the inches. If I'm taller than 30,000 feet, it measures me in miles rather than feet.

Shrink works almost exactly the same as grow, except the random height it rolls is subtracted instead of added to my current height.

 


No comments:

Post a Comment