/***************************************************
This code allows IMP's to grant specific imm commands to mortals
or lower imms. They can also be revoked with the included revoke
command. The granted commands are saved with the player. Also in
this snippet is the viewgrant command, which can be used by imps
for finding a person's granted commands, or can be used by anyone
to view their own granted commands. The maximum number of granted
commands is defined as MAX_GRANT, so feel free to change it.
****************************************************/

-- act_wiz.c --

Place these functions anywhere:

void do_grant( CHAR_DATA *ch, char *argument )
{
   char arg1[MAX_INPUT_LENGTH];
   char arg2[MAX_INPUT_LENGTH];
   bool found = FALSE;
   CHAR_DATA *victim;
   int cmd = 0;
   int grant = 0;
   argument = one_argument( argument, arg1 );
   argument = one_argument( argument, arg2 );

    if (( arg1[0] == '\0' ) || ( arg2[0] == '\0' ))
    {
        send_to_char( "Syntax: grant <player> <command>\n\r", ch );
        return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }
    if ( IS_NPC(victim))
    {
	send_to_char( "Sorry, no NPC's.\n\r", ch );
	return;
    }

    for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
    {
	if ( !str_prefix( arg2, cmd_table[cmd].name ) )
	{
	    found = TRUE;
	    break;
	}
    }
    if ( !found )
    {
	send_to_char( "That isn't a command.\n\r", ch );
	return;
    }
    found = FALSE;
    for ( grant = 0; grant < MAX_GRANT; grant++ ) 
    {
	if (( victim->pcdata->grant[grant] == NULL ) || ( victim->pcdata->grant[grant][0] == '\0' ))
	{
	    found = TRUE;
	    break;
	}
    }
    if (!found)
    {
	send_to_char("They already have too many commands granted.\n\r", ch );
	return;
    }
    victim->pcdata->grant[grant] = str_dup( cmd_table[cmd].name );
    printf_to_char( ch, "%s has been granted the %s command.\n\r", victim->name, cmd_table[cmd].name);
    printf_to_char( victim, "You have been granted the %s command.\n\r", cmd_table[cmd].name);
    return;
}

void do_revoke( CHAR_DATA *ch, char *argument )
{
   char arg1[MAX_INPUT_LENGTH];
   char arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    int grant = 0;
   argument = one_argument( argument, arg1 );
   argument = one_argument( argument, arg2 );

    if (( arg1[0] == '\0' ) || ( arg2[0] == '\0' ))
    {
        send_to_char( "Syntax: revoke <player> <command>\n\r", ch );
        return;
    }

    if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }
    if ( IS_NPC(victim))
    {
	send_to_char( "Sorry, no NPC's.\n\r", ch );
	return;
    }

    for ( grant = 0; grant < MAX_GRANT; grant++ )
    {
	if ( victim->pcdata->grant[grant] == NULL)
		continue;
	if ( !str_prefix( victim->pcdata->grant[grant], arg2))
	{
	    victim->pcdata->grant[grant] = str_dup( "" );
	    printf_to_char( ch, "%s's %s command has been revoked.\n\r", victim->name, arg2);
	    printf_to_char( victim, "Your %s command has been revoked.\n\r", arg2);
	    return;
	}
    }
    send_to_char( "That player has not been granted that command.\n\r", ch );
    return;
}

void do_viewgrant( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA* victim;
    int i;
    bool match = FALSE;
        if ( IS_NPC(ch))
    {
	send_to_char( "Sorry, no NPC's.\n\r", ch );
	return;
    }
    if ( argument[0] == '\0' )
    {
	send_to_char( "These are your specifically granted commands:\n\r", ch );
	for ( i = 0; i < MAX_GRANT; i++ )
	{
	    if (( ch->pcdata->grant[i] != NULL ) && ( ch->pcdata->grant[i][0] != '\0' ))
	    {
		match = TRUE;
		printf_to_char( ch, "%s\n\r", ch->pcdata->grant[i] );
	    }
	}
	if ( !match )
	    send_to_char( "None.\n\r", ch );
	return;
    }

    if ( ( victim = get_char_world( ch, argument ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }
    if ( IS_NPC(victim))
    {
	send_to_char( "Sorry, no NPC's.\n\r", ch );
	return;
    }

    if ( ch->trust < victim->trust )
    {
	send_to_char( "Your powers aren't strong enough to find their granted commands.\n\r", ch );
	return;
    }

    printf_to_char( ch, "These are %s's specifically granted commands:\n\r", victim->name );
    for ( i = 0; i < MAX_GRANT; i++ )
    {
	if (( victim->pcdata->grant[i] != NULL ) && ( victim->pcdata->grant[i][0] != '\0' ))
	{
	    match = TRUE;
	    printf_to_char( ch, "%s\n\r", victim->pcdata->grant[i] );
        }
    }
    if ( !match )
	send_to_char( "None.\n\r", ch );
    return;
}

-- interp.c --
Add this under "Immortal Commands":

    { "grant",		do_grant,	POS_DEAD,	ML,  LOG_ALWAYS, 1 },
    { "revoke",		do_revoke,	POS_DEAD,	ML,  LOG_ALWAYS, 1 },

Add this under "Informational commands":

    { "viewgrant",	do_viewgrant,  POS_DEAD,	 0,  LOG_NORMAL, 1 },

At the top of the interpret function add, int i;
Then scroll down alittle bit and find this:

    for ( cmd = 0; cmd_table[cmd].name[0] != '\0'; cmd++ )
    {
	if ( command[0] == cmd_table[cmd].name[0]
	&&   !str_prefix( command, cmd_table[cmd].name )
	&&   cmd_table[cmd].level <= trust )

Remove the    cmd_table[cmd].level <= trust   condition.

Add this before the Log and Snoop comment in interpret:

    if ( cmd_table[cmd].level > trust )
    {
	found = FALSE;
	for ( i = 0; i < MAX_GRANT; i++ )
	{
	    if (( ch->pcdata->grant[i] == NULL ) || ( ch->pcdata->grant[i][0] == '\0' ))
		continue;
	    if ( !str_prefix( command, ch->pcdata->grant[i] ))
	    {
		found = TRUE;
		break;
	    }
	}
    }

-- interp.h --
Add these:
DECLARE_DO_FUN( do_grant	);
DECLARE_DO_FUN( do_revoke	);
DECLARE_DO_FUN( do_viewgrant	);

-- merc.h --
Define this somewhere in with the other MAX values:
#define MAX_GRANT		   10

Add this to the pc_data struct:
    char *		grant[MAX_GRANT];

-- save.c --
Add this to the top of fwrite_char:
	int gr;

Add after this block of code (toward the end of fwrite_char):
	for ( gn = 0; gn < MAX_GROUP; gn++ )
        {
            if ( group_table[gn].name != NULL && ch->pcdata->group_known[gn])
            {
                fprintf( fp, "Gr '%s'\n",group_table[gn].name);
            }
        }

This:
	for ( gr = 0; gr < MAX_GRANT; gr++ )
	{
	    if (( ch->pcdata->grant[gr] != NULL ) && ( ch->pcdata->grant[gr][0] != '\0' ))
	    {
		fprintf( fp, "Cmd %s~\n",ch->pcdata->grant[gr] );
	    }
	}

Add this at the top in fread_char:
	sh_int grcount;

Add this in the logical position in fread_char:
	    if (!str_cmp(word,"Cmd"))
	    {
		if (count >= MAX_GRANT)
		{
		    fread_to_eol(fp);
		    fMatch = TRUE;
		    break;
		}
		ch->pcdata->grant[grcount] = fread_string( fp );
		grcount++;
		fMatch = TRUE;
	    }