📄 mob_prog.c
字号:
/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
/***************************************************************************
* The MOBprograms have been contributed by N'Atas-ha. Any support for *
* these routines should not be expected from Merc Industries. However, *
* under no circumstances should the blame for bugs, etc be placed on *
* Merc Industries. They are not guaranteed to work on all systems due *
* to their frequent use of strxxx functions. They are also not the most *
* efficient way to perform their tasks, but hopefully should be in the *
* easiest possible way to install and begin using. Documentation for *
* such installation can be found in INSTALL. Enjoy... N'Atas-Ha *
***************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "merc.h"
/*
* Local function prototypes
*/
char * mprog_next_command args( ( char* clist ) );
bool mprog_seval args( ( char* lhs, char* opr, char* rhs ) );
bool mprog_veval args( ( int lhs, char* opr, int rhs ) );
bool mprog_do_ifchck args( ( char* ifchck, CHAR_DATA* mob,
CHAR_DATA* actor, OBJ_DATA* obj,
void* vo, CHAR_DATA* rndm ) );
char * mprog_process_if args( ( char* ifchck, char* com_list,
CHAR_DATA* mob, CHAR_DATA* actor,
OBJ_DATA* obj, void* vo,
CHAR_DATA* rndm ) );
void mprog_translate args( ( char ch, char* t, CHAR_DATA* mob,
CHAR_DATA* actor, OBJ_DATA* obj,
void* vo, CHAR_DATA* rndm ) );
void mprog_process_cmnd args( ( char* cmnd, CHAR_DATA* mob,
CHAR_DATA* actor, OBJ_DATA* obj,
void* vo, CHAR_DATA* rndm ) );
void mprog_driver args( ( char* com_list, CHAR_DATA* mob,
CHAR_DATA* actor, OBJ_DATA* obj,
void* vo ) );
/***************************************************************************
* Local function code and brief comments.
*/
/* if you dont have these functions, you damn well should... */
#ifdef DUNNO_STRSTR
char * strstr(s1,s2) const char *s1; const char *s2;
{
char *cp;
int i,j=strlen(s1)-strlen(s2),k=strlen(s2);
if(j<0)
return NULL;
for(i=0; i<=j && strncmp(s1++,s2, k)!=0; i++);
return (i>j) ? NULL : (s1-1);
}
#endif
/* Used to get sequential lines of a multi line string (separated by "\n\r")
* Thus its like one_argument(), but a trifle different. It is destructive
* to the multi line string argument, and thus clist must not be shared.
*/
char *mprog_next_command( char *clist )
{
char *pointer = clist;
while ( *pointer != '\n' && *pointer != '\0' )
pointer++;
if ( *pointer == '\n' )
*pointer++ = '\0';
if ( *pointer == '\r' )
*pointer++ = '\0';
return ( pointer );
}
/* These two functions do the basic evaluation of ifcheck operators.
* It is important to note that the string operations are not what
* you probably expect. Equality is exact and division is substring.
* remember that lhs has been stripped of leading space, but can
* still have trailing spaces so be careful when editing since:
* "guard" and "guard " are not equal.
*/
bool mprog_seval( char *lhs, char *opr, char *rhs )
{
if ( !str_cmp( opr, "==" ) )
return ( bool )( !str_cmp( lhs, rhs ) );
if ( !str_cmp( opr, "!=" ) )
return ( bool )( str_cmp( lhs, rhs ) );
if ( !str_cmp( opr, "/" ) )
return ( bool )( !str_infix( rhs, lhs ) );
if ( !str_cmp( opr, "!/" ) )
return ( bool )( str_infix( rhs, lhs ) );
bug ( "Improper MOBprog operator\n\r", 0 );
return 0;
}
bool mprog_veval( int lhs, char *opr, int rhs )
{
if ( !str_cmp( opr, "==" ) )
return ( lhs == rhs );
if ( !str_cmp( opr, "!=" ) )
return ( lhs != rhs );
if ( !str_cmp( opr, ">" ) )
return ( lhs > rhs );
if ( !str_cmp( opr, "<" ) )
return ( lhs < rhs );
if ( !str_cmp( opr, ">=" ) )
return ( lhs <= rhs );
if ( !str_cmp( opr, ">=" ) )
return ( lhs >= rhs );
if ( !str_cmp( opr, "&" ) )
return ( lhs & rhs );
if ( !str_cmp( opr, "|" ) )
return ( lhs | rhs );
bug ( "Improper MOBprog operator\n\r", 0 );
return 0;
}
/* This function performs the evaluation of the if checks. It is
* here that you can add any ifchecks which you so desire. Hopefully
* it is clear from what follows how one would go about adding your
* own. The syntax for an if check is: ifchck ( arg ) [opr val]
* where the parenthesis are required and the opr and val fields are
* optional but if one is there then both must be. The spaces are all
* optional. The evaluation of the opr expressions is farmed out
* to reduce the redundancy of the mammoth if statement list.
* If there are errors, then return -1 otherwise return boolean 1,0
*/
bool mprog_do_ifchck( char *ifchck, CHAR_DATA *mob, CHAR_DATA *actor,
OBJ_DATA *obj, void *vo, CHAR_DATA *rndm)
{
char buf[ MAX_INPUT_LENGTH ];
char arg[ MAX_INPUT_LENGTH ];
char opr[ MAX_INPUT_LENGTH ];
char val[ MAX_INPUT_LENGTH ];
CHAR_DATA *vict = (CHAR_DATA *) vo;
OBJ_DATA *v_obj = (OBJ_DATA *) vo;
char *bufpt = buf;
char *argpt = arg;
char *oprpt = opr;
char *valpt = val;
char *point = ifchck;
int lhsvl;
int rhsvl;
if ( *point == '\0' )
{
bug ( "Mob: %d null ifchck", mob->pIndexData->vnum );
return -1;
}
/* skip leading spaces */
while ( *point == ' ' )
point++;
/* get whatever comes before the left paren.. ignore spaces */
while ( *point != '(' )
if ( *point == '\0' )
{
bug ( "Mob: %d ifchck syntax error", mob->pIndexData->vnum );
return -1;
}
else
if ( *point == ' ' )
point++;
else
*bufpt++ = *point++;
*bufpt = '\0';
point++;
/* get whatever is in between the parens.. ignore spaces */
while ( *point != ')' )
if ( *point == '\0' )
{
bug ( "Mob: %d ifchck syntax error", mob->pIndexData->vnum );
return -1;
}
else
if ( *point == ' ' )
point++;
else
*argpt++ = *point++;
*argpt = '\0';
point++;
/* check to see if there is an operator */
while ( *point == ' ' )
point++;
if ( *point == '\0' )
{
*opr = '\0';
*val = '\0';
}
else /* there should be an operator and value, so get them */
{
while ( ( *point != ' ' ) && ( !isalnum( *point ) ) )
if ( *point == '\0' )
{
bug ( "Mob: %d ifchck operator without value",
mob->pIndexData->vnum );
return -1;
}
else
*oprpt++ = *point++;
*oprpt = '\0';
/* finished with operator, skip spaces and then get the value */
while ( *point == ' ' )
point++;
for( ; ; )
{
if ( ( *point != ' ' ) && ( *point == '\0' ) )
break;
else
*valpt++ = *point++;
}
*valpt = '\0';
}
bufpt = buf;
argpt = arg;
oprpt = opr;
valpt = val;
/* Ok... now buf contains the ifchck, arg contains the inside of the
* parentheses, opr contains an operator if one is present, and val
* has the value if an operator was present.
* So.. basically use if statements and run over all known ifchecks
* Once inside, use the argument and expand the lhs. Then if need be
* send the lhs,opr,rhs off to be evaluated.
*/
if ( !str_cmp( buf, "rand" ) )
{
return ( number_percent() <= atoi(arg) );
}
if ( !str_cmp( buf, "ispc" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return 0;
case 'n': if ( actor )
return ( !IS_NPC( actor ) );
else return -1;
case 't': if ( vict )
return ( !IS_NPC( vict ) );
else return -1;
case 'r': if ( rndm )
return ( !IS_NPC( rndm ) );
else return -1;
default:
bug ( "Mob: %d bad argument to 'ispc'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isnpc" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return 1;
case 'n': if ( actor )
return IS_NPC( actor );
else return -1;
case 't': if ( vict )
return IS_NPC( vict );
else return -1;
case 'r': if ( rndm )
return IS_NPC( rndm );
else return -1;
default:
bug ("Mob: %d bad argument to 'isnpc'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isgood" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return IS_GOOD( mob );
case 'n': if ( actor )
return IS_GOOD( actor );
else return -1;
case 't': if ( vict )
return IS_GOOD( vict );
else return -1;
case 'r': if ( rndm )
return IS_GOOD( rndm );
else return -1;
default:
bug ( "Mob: %d bad argument to 'isgood'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isfight" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return ( mob->fighting ) ? 1 : 0;
case 'n': if ( actor )
return ( actor->fighting ) ? 1 : 0;
else return -1;
case 't': if ( vict )
return ( vict->fighting ) ? 1 : 0;
else return -1;
case 'r': if ( rndm )
return ( rndm->fighting ) ? 1 : 0;
else return -1;
default:
bug ( "Mob: %d bad argument to 'isfight'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isimmort" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return ( get_trust( mob ) > LEVEL_IMMORTAL );
case 'n': if ( actor )
return ( get_trust( actor ) > LEVEL_IMMORTAL );
else return -1;
case 't': if ( vict )
return ( get_trust( vict ) > LEVEL_IMMORTAL );
else return -1;
case 'r': if ( rndm )
return ( get_trust( rndm ) > LEVEL_IMMORTAL );
else return -1;
default:
bug ( "Mob: %d bad argument to 'isimmort'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "ischarmed" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return IS_AFFECTED( mob, AFF_CHARM );
case 'n': if ( actor )
return IS_AFFECTED( actor, AFF_CHARM );
else return -1;
case 't': if ( vict )
return IS_AFFECTED( vict, AFF_CHARM );
else return -1;
case 'r': if ( rndm )
return IS_AFFECTED( rndm, AFF_CHARM );
else return -1;
default:
bug ( "Mob: %d bad argument to 'ischarmed'",
mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isfollow" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return ( mob->master != NULL
&& mob->master->in_room == mob->in_room );
case 'n': if ( actor )
return ( actor->master != NULL
&& actor->master->in_room == actor->in_room );
else return -1;
case 't': if ( vict )
return ( vict->master != NULL
&& vict->master->in_room == vict->in_room );
else return -1;
case 'r': if ( rndm )
return ( rndm->master != NULL
&& rndm->master->in_room == rndm->in_room );
else return -1;
default:
bug ( "Mob: %d bad argument to 'isfollow'", mob->pIndexData->vnum );
return -1;
}
}
if ( !str_cmp( buf, "isaffected" ) )
{
switch ( arg[1] ) /* arg should be "$*" so just get the letter */
{
case 'i': return ( mob->affected_by & atoi( arg ) );
case 'n': if ( actor )
return ( actor->affected_by & atoi( arg ) );
else return -1;
case 't': if ( vict )
return ( vict->affected_by & atoi( arg ) );
else return -1;
case 'r': if ( rndm )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -