/*------------------------------------------------------------------------\\ || || || File: script.c || || Purpose: Handling of Program Scripts for Tapestries || || Author: (c) 1996 Ant Whitehead (ant@solace.mh.se) || || Credits: Some portions of code have been adapted from the MobProgs || || Released in the Merc2.2 distribution. || || || \\------------------------------------------------------------------------*/ char *next_line( char *script ) { char *pointer = script; while( *pointer != '\n' && *pointer != '\0' ) pointer++; if( *pointer == '\n' ) *pointer++ = '\0'; if( *pointer == '\r' ) *pointer++ = '\0'; return( pointer ); } bool string_eval( char *lhs, char *opr, char *rhs ) { if( !str_cmp( opr, "==" ) ) /* exact match */ return( bool )( !str_cmp( lhs, rhs ) ); if( !str_cmp( opr, "!=" ) ) /* NOT exact match */ return( bool )( str_cmp( lhs, rhs ) ); if( !str_cmp( opr, "/" ) ) /* exact substring */ return ( bool )( !str_infix( rhs, lhs ) ); if( !str_cmp( opr, "!/" ) ) /* NOT exact substring */ return( bool )( str_infix( rhs, lhs ) ); bug( "Unknown scripting operator(strings)\n\r", 0 ); return 0; } bool value_eval( 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( "Unknown scripting operator(values)\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 ) ) ? 1 : 0; case 'n': if ( actor ) return ( IS_AFFECTED( actor, AFF_CHARM ) ) ? 1 : 0; else return -1; case 't': if ( vict ) return ( IS_AFFECTED( vict, AFF_CHARM ) ) ? 1 : 0; else return -1; case 'r': if ( rndm ) return ( IS_AFFECTED( rndm, AFF_CHARM ) ) ? 1 : 0; 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 ) return ( rndm->affected_by & atoi( arg ) ); else return -1; default: bug ( "Mob: %d bad argument to 'isaffected'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "hitprcnt" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'i': lhsvl = mob->hit / mob->max_hit; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); case 'n': if ( actor ) { lhsvl = actor->hit / actor->max_hit; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 't': if ( vict ) { lhsvl = vict->hit / vict->max_hit; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 'r': if ( rndm ) { lhsvl = rndm->hit / rndm->max_hit; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; default: bug ( "Mob: %d bad argument to 'hitprcnt'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "inroom" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'i': lhsvl = mob->in_room->vnum; rhsvl = atoi(val); return mprog_veval( lhsvl, opr, rhsvl ); case 'n': if ( actor ) { lhsvl = actor->in_room->vnum; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 't': if ( vict ) { lhsvl = vict->in_room->vnum; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 'r': if ( rndm ) { lhsvl = rndm->in_room->vnum; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; default: bug ( "Mob: %d bad argument to 'inroom'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "sex" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'i': lhsvl = mob->sex; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); case 'n': if ( actor ) { lhsvl = actor->sex; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 't': if ( vict ) { lhsvl = vict->sex; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 'r': if ( rndm ) { lhsvl = rndm->sex; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; default: bug ( "Mob: %d bad argument to 'sex'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "position" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'i': lhsvl = mob->position; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); case 'n': if ( actor ) { lhsvl = actor->position; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 't': if ( vict ) { lhsvl = vict->position; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 'r': if ( rndm ) { lhsvl = rndm->position; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; default: bug ( "Mob: %d bad argument to 'position'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "level" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'i': lhsvl = get_trust( mob ); rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); case 'n': if ( actor ) { lhsvl = get_trust( actor ); rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 't': if ( vict ) { lhsvl = get_trust( vict ); rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 'r': if ( rndm ) { lhsvl = get_trust( rndm ); rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; default: bug ( "Mob: %d bad argument to 'level'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "class" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'i': lhsvl = mob->class->number; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); case 'n': if ( actor ) { lhsvl = actor->class->number; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 't': if ( vict ) { lhsvl = vict->class->number; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 'r': if ( rndm ) { lhsvl = rndm->class->number; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; default: bug ( "Mob: %d bad argument to 'class'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "goldamt" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'i': lhsvl = mob->gold; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); case 'n': if ( actor ) { lhsvl = actor->gold; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 't': if ( vict ) { lhsvl = vict->gold; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 'r': if ( rndm ) { lhsvl = rndm->gold; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; default: bug ( "Mob: %d bad argument to 'goldamt'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "objtype" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'o': if ( obj ) { lhsvl = obj->item_type; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 'p': if ( v_obj ) { lhsvl = v_obj->item_type; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; default: bug ( "Mob: %d bad argument to 'objtype'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "number" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'i': lhsvl = mob->gold; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); case 'n': if ( actor ) { if IS_NPC( actor ) { lhsvl = actor->pIndexData->vnum; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } } else return -1; case 't': if ( vict ) { if IS_NPC( actor ) { lhsvl = vict->pIndexData->vnum; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } } else return -1; case 'r': if ( rndm ) { if IS_NPC( actor ) { lhsvl = rndm->pIndexData->vnum; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } } else return -1; case 'o': if ( obj ) { lhsvl = obj->pIndexData->vnum; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; case 'p': if ( v_obj ) { lhsvl = v_obj->pIndexData->vnum; rhsvl = atoi( val ); return mprog_veval( lhsvl, opr, rhsvl ); } else return -1; default: bug ( "Mob: %d bad argument to 'number'", mob->pIndexData->vnum ); return -1; } } if ( !str_cmp( buf, "name" ) ) { switch ( arg[1] ) /* arg should be "$*" so just get the letter */ { case 'i': return mprog_seval( mob->name, opr, val ); case 'n': if ( actor ) return mprog_seval( actor->name, opr, val ); else return -1; case 't': if ( vict ) return mprog_seval( vict->name, opr, val ); else return -1; case 'r': if ( rndm ) return mprog_seval( rndm->name, opr, val ); else return -1; case 'o': if ( obj ) return mprog_seval( obj->name, opr, val ); else return -1; case 'p': if ( v_obj ) return mprog_seval( v_obj->name, opr, val ); else return -1; default: bug ( "Mob: %d bad argument to 'name'", mob->pIndexData->vnum ); return -1; } } /* Ok... all the ifchcks are done, so if we didnt find ours then something * odd happened. So report the bug and abort the MOBprogram (return error) */ bug ( "Mob: %d unknown ifchck", mob->pIndexData->vnum ); return -1; }