#pragma save_binary /* Code originaly by nimmox@igor. Modified for discworld by Pinkfish. This file is also put in /players/nimmox/generic/responsive_monster.c See for more information on how to use it /players/nimmox/open/resp_exam.c If you want to use it, you don't need to read all this, the example will do.... Nimmox (january 1993) */ mapping respond_to_with; int stop_responding; int match( string str, mixed str2 ); void create() { respond_to_with = ([ ]); } /* create() */ /* To toggle catch_tell, in case of sequence responding... See example */ void set_stop_responding( int i ) { stop_responding = i; } int query_stop_responding() { return stop_responding; } void set_respond_to_with( mapping map ) { respond_to_with = map; } mapping query_respond_to_with() { return respond_to_with; } void add_respond_to_with( mixed *trigger, mixed response ) { /* Added by Newstyle, 02/12/93, because of errors */ if( !respond_to_with ) respond_to_with = ([ ]); respond_to_with[ trigger ] = response; } /* add_response() */ /* Check_sub_sequence checks whether the array (words) contains a subsequence a specified in the indices of the respond_to_with mapping */ mixed * check_sub_sequence( string *words ) { int word_index; int format_index; /* what do you know....Meaningful names :-) */ mixed * format; int format_size; int word_size; int match_counter; int cu_format_size; format_index = 0; format = m_indices( respond_to_with ); word_size = sizeof( words ); format_size = sizeof( format ); while( format_index < format_size ) { word_index = 0; match_counter = 0; cu_format_size = sizeof( format[ format_index ] ); while( (word_index < word_size) && (match_counter < cu_format_size) ) { match_counter += match( words[ word_index ], format[ format_index ][ match_counter ] ); word_index++; } if( match_counter == (cu_format_size) ) return respond_to_with[ format[ format_index ] ]; format_index++; } return 0; } /* check_sub_sequence() */ /* match returns 1 if str matches the format.... see also the definitions in the example file... */ int match( string str, mixed format ) { if( str == format ) return 1; if( pointerp( format ) ) return( member_array( str, format ) != -1 ); return 0; } /* match() */ /* removing annoying readmarks.... Like .'s and ?'s */ string remove_read_marks( string str ) { int count; string result; int size; string temp; size = strlen( str ); count = 0; result = ""; while( count < size ) { temp = str[ count..count ]; if( ((temp >= "a") && (temp <= "z")) || (temp == " ") ) result += temp; else result += " "; count++; } return result; } /* remove_read_marks() */ void senddstr( string str, object per ) { if( environment( this_object() ) ) if( per ) command( replace( str, ({ "$hname$", per->query_name(), "$hcname$", per->query_cap_name() }) ) ); else command( str ); } /* sendstr() */ /* Take care not to send to other monsters.... Infinite recursion problem... */ /* Imagine two monsters chatting with each other...... */ void exec_response( mixed rep, object per ) { if( pointerp( rep ) ) return exec_response( rep[ random( sizeof( rep ) ) ], per ); if( stringp( rep ) ) if( rep[ 0..0 ] == "#" ) call_out( rep[ 1..strlen( rep ) - 1 ], 0, per ); else call_out( "senddstr", 0, rep, per ); } /* exec_response() */ /* respond as defined in respond_to_with mapping...See also the definitions in the example monster */ void event_person_say( object per, string start, string mess, string lang ) { mixed * response; /* Used to have a !interactive. People will just have to be careful with * their responses, so as to not set off other monsters. */ if( stop_responding || !sizeof( respond_to_with ) ) return; mess = lower_case( mess ); mess = remove_read_marks( mess ); if( mess && strlen( mess ) ) response = check_sub_sequence( ({ "@say" }) +explode( mess, " " ) ); if( response ) exec_response( response, per ); } /* event_person_say() */ /* no 'at' or 'avoid' exists, whoever screwed this, should fix it! -Bill. void event_person_tell( object ob, string start, string mess, string lang ) { mixed *response; string *bits; if( !interactive( per ) || stop_responding || member_array( this_object(), avoid ) != -1 || !sizeof( respond_to_with ) ) return ; mess = lower_case( mess ); mess = remove_read_marks( mess ); if( !mess ) return ; if( objectp( at ) ) response = check_sub_sequence( ({ "@tell", }) + explode( mess, " " ) ); if( response ) exec_response( response, per ); } *//* event_person_tell() */ void event_soul( object per, string mess, object *avoid, string verb, string last, mixed at ) { mixed * response; string *bits; if( !interactive( per ) || stop_responding || member_array( this_object(), avoid ) != -1 || !sizeof( respond_to_with ) ) return; mess = lower_case( mess ); mess = remove_read_marks( mess ); if( !mess ) return; if( objectp( at ) ) response = check_sub_sequence( ({ "@" + verb, "#" + last, at->query_name() })+ explode( mess, " " ) ); if( response ) exec_response( response, per ); } /* event_soul() */