EMOTIONS in Commandsouls (Guildsouls).
======================================

Until now, the whole manipulation of emotions and adverbs was left completely
to the wizards who wanted to use them in treir souls. There was a nice system
for easy emotions and there was a large set of possible adverbs, but they
were only available in the default soul. That has changed now. All functions
for easy emotions and easy adverb manipulation are in the basic file for all
souls now: /cmd/std/command_driver.c

Also, the system did not allow you to use an adverb when doing an emotion on
a target. That has also changed, so every combination of emote, adverb and
target is possible now. This file describes the functions that can be used
for easy adverb and emotion manupulation. For more details, see the actual
code in /sys/adverbs.h /sys/global/adverbs.c and /cmd/std/command_driver.c
for the code and /cmd/std/soul_cmd.c for a lot of examples.

There are manual pages on each of the of the functions described in this
file. Do 'man <function name>' to get it.

Have fun,
         /Mercade

ADVERB MANIPULATION

Adverbs can be used separately and on a target. The only adverbs regonized by
the system are the adverbs that are accepted as defined in /sys/adverbs.h and
adverbs always consist of only one word. This system does not allow free
emotes by players.
The system allows players to specify the adverb only partial. 'help adverbs' 
will give you more information on adverbs in general.

string check_adverb_with_space(string str, string default_adverb)

    string str;
    str = check_adverb_with_space(str, "completely");

    This function will return the default adverb if (!strlen(str)), it will
    return the adverb if str is only a part of an existing adverb and if
    the player specified a non-existant adverb, NO_ADVERB_WITH_SPACE will be
    returned.

string *parse_adverb_with_space(string str, string default, int trail)

    string *how;
    how = parse_adverb_with_space(str, "happily", 0);

    In this function, str is the string to parse, default is the default
    adverb in case no adverb is specified and trail determines whether the
    adverb comes before of behind the target (1 if behind). This means that
    the player has to type "wave sadly at mercade" and "kick mercade enthu",
    just like it is done in English.

    This function returns an array of two strings. The first string in the
    array how[0] specifies the substring with targets on which the player
    wants to perform his action and the second string how[1] is the adverb
    the player wants to use or the default adverb if the player omitted the
    adverb or specified the wrong adverb. how[0] can be used to get the
    targets using parse_this(how[0], "pattern"). Note that if the player
    specifies an illegal adverb, how[0] will include that illegal adverb and
    probably cause parse_this to return an empty array therewith causing
    a notify_fail and return 0. If the player only specifies an adverb,
    how[0] will contain an empty string (meaning no targets). For examples,
    see 'man parse_adverb_with_space'.

Both functions mentioned above will return the wanted adverb preceded by a
space or will return an empty string if the player explicitly specified that
he didn't want to use an adverb (using the adverb "." (period)). If the
function fails to return an adverb NO_ADVERB_WITH_SPACE will be returned.
NO_ADVERB_WITH_SPACE is defined in the include file adverbs.h

The same functions also exist without this space-manupulation. Their names
are check_adverb() and parse_adverb() and have the same format and result as
the functions described above. However, they will return the adverb without
a preceding space, NO_ADVERB is no match was found and BLANK_ADVERB if the
player does not want to use an adverb. These functions are merely meant for
people who want to do their own adverb manupulation and can be used to make
emotions that have the adverb before the verb of the emotion. Note that you
can also use BLANK_ADVERB as a default adverb. (See for instance the emotion
'hug' in /cmd/std/soul_cmd.c)

TARGET MANIPULATION

This function will give you a list with all the living objects that a player
wants. It is a parse_command with some additional checks about visibility
and such. Please do always add [the] optional to the scan pattern to allow
players to specify 'the dwarf' and don't forget to allow people to use
additional prepositions if the emotions could be used with them.
The function allows you to specify the following examplary descriptions (when
the search pattern is "[at] [the] %l"):
"mercade", "at Mercade", "the dwarf", "friendly dwarfs", "at dwarf" ... 

object *parse_this(string str, string pattern)

    object *oblist;
    oblist = parse_this(str, "[at] [the] %l");

MESSAGE MANIPULATION

All functions below will handle met/nonmet and seen/unseen. Note that you do
not have to add \n to the varargs defined functions and that you do not have
to add the period if you omit the third parameter. Do note the places that
you need to specify the preceding/trailing space yourself and the places you
do not have to add the space.

varargs void actor(string s1, object *oblist, string s2)

    actor("You hug", oblist); or
    actor("You hug", oblist, " lovingly.");

    This will send a message to the player who performs the emotion

void all(string s)

    all(" goes duh...");

    This will send a message to all other players in the room if there is no
    target for this emotion.

void allbb(string s)

    Same as all, except players that cannot see you don't get a message.

varargs void target(string s, object *oblist)

    target(" hugs you.", oblist);

    This will send a message to the target of the emotion.

varargs void targetbb(string s, object *oblist)

    Same as target, except players that cannot see you don't get a message.

varargs void all2act(string s1, object *oblist, string s2)

    all2act("hugs", oblist); or
    all2act("hugs", oblist, " lovingly");

    This will send a message to all others watching the actor performing his
    emote on the target.

varargs void all2actbb(string s1, object *oblist, string s2)

    Same as all2act, except players that cannot see you don't get a message.

SUBLOC SOULDESCRIPTION

If the emote is visible on the player for a longer time, you might want to
add it to his long description with a subloc. To do this, it is handy to
define the following macro in your soul:

#define SOULDESC(x) (this_player()->add_prop(LIVE_S_SOULEXTRA, x))

    SOULDESC("smiling happily");
    SOULDESC("blushing");
    but not SOULDESC("kicking");

    If you do this, the long description of the player will be extended
    with the following line:
    "You are (He/She/It is) smiling happily."

EXAMPLES OF EMOTIONS

Below are four examples of all possible combinations of possible adverbs
and targets. Ack is an emotion without adverb and target. You can only go
ack and nothing else. Blush is an emotion that uses an adverb, but cannot
be performed on a target. Slap can only be performed on a target, but you
cannot use an adverb with it and finally wave allows you do specify an
adverb and a target. Note that there is a special "if" that handles the
situation if you only specify an adverb (or use the default adverb) without
waving at someone in particular. More examples of these default emotions and
of some other forms can be found in /cmd/std/soul_cmd.c

int
ack(string str)
{
/*
 * No use in giving any command line parameter.
 */
    if (strlen(str))
    {
	notify_fail("Ack what?\n");
	return 0;
    }

/*
 * Everyone in the room will see/hear you go ack.
 */
    write("Ack!\n");
    all(" goes ack!");
    return 1;
}

int
blush(string str)
{
/*
 * Str can only be an adverb, if str is empty "profusely" will be returned.
 * If a false adverb is given NO_ADVERB_WITH_SPACE will be returned.
 */
    str = check_adverb_with_space(str, "profusely");

/*
 * Only if a false adverb is given a fail message will be printed.
 */
    if (str == NO_ADVERB_WITH_SPACE)
    {
	notify_fail("Blush how?\n");
	return 0;
    }

/*
 * Only people that can see you can see that you start to blush. People who
 * will examine you will get the additional message that you are blushing.
 */
    write("Your cheeks are burning.\n");
    SOULDESC("blushing" + str);
    allbb(" blushes" + str + ".");
    return 1;
}

int
slap(string str)
{
    object *oblist;

/*
 * No adverbs are possible, just check for targets
 */
    oblist = parse_this(str, "[the] %l");

/*
 * No targets cause a fail message.
 */
    if (!sizeof(oblist))
    {
	notify_fail("Slap whom?\n");
	return 0;
    }

/*
 * Send a message to the target and to all the bystanders.
 */
    target(" slaps you!", oblist);
    actor("You slap", oblist);
    all2act("slaps", oblist);
    return 1;
}

int
wave(string str)
{
    object *oblist;
    string *how;

/*
 * Check whether the player also added an adverb. Trail is 0, so the adverb
 * should come before the target(s). If no adverb was added, "happily" will
 * be returned. Note that if you specify an illegal adverb, this adverb will
 * be added to how[0] and probably cause a fail message (as expected) for
 * no targets could be found.
 */
    how = parse_adverb_with_space(str, "happily", 0);

/*
 * If no targets were specified, you will just wave. Players who cannot see
 * see you will not get a message.
 */
    if (!strlen(how[0]))
    {
	write("You wave" + how[1] + ".\n");
	allbb(" waves" + how[1] + ".");
	return 1;
    }

/*
 * Check for the target to wave to.
 */
    oblist = parse_this(how[0], "[to] [the] %l");

/*
 * No targets could be found causes a fail message. Specifying an illegal
 * adverb will also give you a fail message in this if-statement.
 */
    if (!sizeof(oblist))
    {
	notify_fail("Wave to whom?\n");
	return 0;
    }

/*
 * Targets and adverb were correct, lets give everyone a message that you
 * are waving in the direction of the target, but only if they can see you.
 */
    targetbb(" waves" + how[1] + " in your direction.", oblist);
    actor("You wave" + how[1] + " in", oblist, "'s direction.");
    all2actbb("waves" + how[1] + " in", oblist, "'s direction.");
    return 1;
}
