// /bin/soul/atmos.c // from the Nightmare Mudlib // everyone's soul commands // created by Jubal@TMI 0.8 910120 #include <databases.h> mapping atmos; int line; void create() { atmos = allocate_mapping(250); line = 1; message("broadcast", "Atmos shouts: A new reality has begun!", users()); set_heart_beat(1); } /********************************************************************** Define the flags we need for various types of cmds. */ /* the default adverb for the cmd is overridden by an environment variable */ #define ENVIRONMENT 0x0001 /* use the optional verb instead of the query_verb() one */ #define OVERB 0x0002 /* apostrophize the target's name */ #define APOSTROPHE 0x0004 /* always use the adverb */ #define FORCEADVERB 0x0008 /* definitions for non-standard formats */ #define FORMAT0 0x0100 #define FORMAT1 0x0200 #define FORMAT2 0x0400 #define FORMAT (FORMAT0|FORMAT1|FORMAT2) /* special variables used by the messages */ #define OBJECTIVE 0x0010 #define POSSESSIVE 0x0020 #define SUBJECTIVE 0x0040 #define VARIABLE (OBJECTIVE|POSSESSIVE|SUBJECTIVE) /********************************************************************** Some simple support functions to make things easier later. These are pretty much self documenting. */ private int ghost() { return (int) previous_object() -> query_ghost(); } private string subjective() { return (string) previous_object() -> query_subjective(); } private string objective() { return (string) previous_object() -> query_objective(); } private string possessive() { return (string) previous_object() -> query_possessive(); } /********************************************************************** expand_macro() expands the $ variables. */ private string expand_macro( string msg, int flags, int personal ) { string s1, s2; if( flags & OBJECTIVE ) while( sscanf( msg, "%s$O%s", s1, s2 ) == 2 ) msg = s1 + ( personal ? "your" : objective() ) + s2; if( flags & POSSESSIVE ) while( sscanf( msg, "%s$P%s", s1, s2 ) == 2 ) msg = s1 + ( personal ? "your" : possessive() ) + s2; if( flags & SUBJECTIVE ) while( sscanf( msg, "%s$S%s", s1, s2 ) == 2 ) msg = s1 + ( personal ? "you" : subjective() ) + s2; return msg; } /********************************************************************** describe_action() takes the pieces of cmd outputs and puts them together into messages, and displays them to the appropriate people. */ static int describe_action( string verb, object victim, string pre, string post, int flags ) { object pob; string src_name, victim_name, v_ext, msg; int i; if( ! verb || ghost() || ( i = strlen( verb ) ) < 2 ) return 0; if( verb[i-1] == 's' || verb[i-1] == 'x' || verb[i-1] == 'z' || verb[i-1] == 'o' || verb[i-1] == 'h' && ( verb[i-2] == 't' || verb[i-2] == 'c' || verb[i-2] == 's' ) ) v_ext = "es"; else v_ext = "s"; verb = " " + verb; post = ( post ? " " + post + "." : "." ); pob = previous_object(); src_name = (string) pob -> query_cap_name(); if( ! src_name ) src_name = src_name = (string) pob -> query_short(); if( victim ) { pre = ( pre ? " " + pre + " " : " " ); victim_name = (string) victim -> query_cap_name(); if( ! victim_name ) victim_name = (string) victim -> query_short(); if( ! victim_name ) victim_name = "Someone"; if( flags & APOSTROPHE ) victim_name += "'" + ( victim_name[ strlen( victim_name ) - 1 ] != 's' ? "s" : "" ); } else { victim_name = ""; pre = ( pre ? " " + pre : "" ); } /* tell the commander */ msg = sprintf("You%s%s%s%s", verb, pre, victim_name, post); if( flags & VARIABLE ) msg = expand_macro( msg, flags, 1 ); message("emote", msg, this_player()); /* tell the commandee */ if( victim ) { msg = sprintf("%s%s%s%syou%s%s", src_name, verb, v_ext, pre, (flags & APOSTROPHE ? "r" : ""), post); if( flags & VARIABLE ) msg = expand_macro( msg, flags, 0 ); message("emote", msg, victim); } else victim = this_object(); /* tell the innocent bystanders */ msg = sprintf("%s%s%s%s%s%s", src_name, verb, v_ext, pre, victim_name, post); if( flags & VARIABLE ) msg = expand_macro( msg, flags, 0 ); message("emote", msg, environment(this_player()), ({ this_player(), victim })); return 1; } /********************************************************************** extract_args() splits a string into a name and adjective. If there is an object around the player which responds to the first word of the string, and is living (and is not the player herself), then the first element in the return array will be the living object. The second argument will either be the rest of the argument string, or the entire string if no match is found. If the found object is not living, or is the player herself, then extract_args() returns 0. */ static mixed * extract_args( string arg ) { string name, adj; object victim; if( ! arg || arg == "" ) return ({ 0, 0 }); if( sscanf( arg, "%s %s", name, adj ) < 2 ) { name = arg; } victim = present( name, environment( previous_object() ) ); if( ! victim ) adj = arg; else if( ! living( victim ) || victim == previous_object() ) return 0; return ({ victim, adj }); } /********************************************************************** do_soul() is the command hook which receives control from the player object to determine if a soul command has been called, and take appropriate action if this is the case. */ int do_cmd( string verb, string args ) { mixed *dat, *argv; string adverb; /* check if the command exists */ #ifdef MUDOS if( ! ( dat = atmos[ verb ] ) ) return 0; #else if( ! ( dat = assoc( verb, atmos ) ) ) return 0; #endif /* parse the argument string */ if( ! ( argv = extract_args( args ) ) ) return 0; /* check if we need an environment override */ if( argv[1] ) adverb = argv[1]; if( ! adverb && ( dat[0] & ENVIRONMENT ) ) adverb = (string) previous_object() -> getenv( verb ); if( adverb && ( dat[0] & FORCEADVERB ) && dat[2] ) adverb = dat[2] + " " + adverb; else if( ! adverb ) adverb = dat[2]; if( adverb && ! strlen( adverb ) ) adverb = 0; if( ! ( dat[0] & FORMAT ) ) describe_action( dat[0] & OVERB ? dat[4] : verb, argv[0], argv[0] ? dat[1] : 0, adverb ? adverb : 0, dat[0] ); else if( dat[0] & FORMAT0 ) describe_action( dat[0] & OVERB ? dat[4] : verb, 0, adverb ? adverb : 0, 0, dat[0] ); else if( dat[0] & FORMAT1 ) describe_action( dat[0] & OVERB ? dat[4] : verb, argv[0], ( dat[3] ? dat[3] : "" ) + ( dat[3] && argv[0] ? " " : "" ) + ( argv[0] ? dat[1] : "" ), adverb ? adverb : 0, dat[0] ); else if( dat[0] & FORMAT2 ) describe_action( dat[0] & OVERB ? dat[4] : verb, argv[0], argv[0] ? dat[1] : dat[3], adverb ? adverb : 0, dat[0] ); return 1; } /********************************************************************** The heart_beat() is used when the object is first loaded to read in the command data file 10 lines at a time so that a heavy initial load is not placed on the system to set up soul commands. */ heart_beat() { string *dat; int i; dat = read_file(SOUL_DB, line, 10); if( dat ) dat = explode( dat, "\n" ); if( dat ) for( i=0 ; i<sizeof(dat) ; i++, line++ ) { string *expl; int j, flags; if(!dat[i] || dat[i] == "") continue; if(dat[i][0] == '#') continue; expl = explode( dat[i] + ":", ":" ); if( ! expl || sizeof( expl ) < 6 ) continue; if( strlen( expl[0] ) == 0 ) continue; /* clean up the data */ if( ! strlen( expl[2] ) ) expl[2] = 0; if( ! strlen( expl[3] ) ) expl[3] = 0; if( ! strlen( expl[4] ) ) expl[4] = 0; if( ! strlen( expl[5] ) ) expl[5] = 0; /* parse flags */ flags = 0; for( j=0 ; j<strlen( expl[1] ) ; j++ ) switch( expl[1][j] ) { case 'E': flags |= ENVIRONMENT; break; case 'V': if( expl[5] ) flags |= OVERB; break; case 'A': flags |= APOSTROPHE; break; case 'F': flags |= FORCEADVERB; break; case '0': flags |= FORMAT0; break; case '1': flags |= FORMAT1; break; case '2': flags |= FORMAT2; break; case 'O': flags |= OBJECTIVE; break; case 'P': flags |= POSSESSIVE; break; case 'S': flags |= SUBJECTIVE; break; } /* insert the command into the atmos alist */ #ifdef MUDOS atmos[expl[0]] = ({ flags, expl[2], expl[3], expl[4], expl[5] }); #else atmos = insert_alist( expl[0], ({ flags, expl[2], expl[3], expl[4], expl[5] }), atmos ); #endif } if( i < 10 ) { set_heart_beat( 0 ); message("broadcast", "Atmos shouts: Our souls are " "now complete.", users()); line = -1; } } mixed * query_atmos( string verb ) { return atmos[ verb ]; } string *query_feelings() { return keys(atmos); }