/** * These are some simul efuns converted to efuns. * @author Reio Remma aka Sandoz, 2002. */ #ifdef LATTICE #include "/lpc_incl.h" #include "/file.h" #include "/simul_efun.h" #include "/sprintf.h" #include "/port.h" #else #include "../lpc_incl.h" #include "../file.h" #include "../simul_efun.h" #include "../sprintf.h" #include "../port.h" #include "../efun_protos.h" #endif #ifdef F_REAL_TIME void f_real_time PROT((void)) { push_number(time(NULL)); } /* f_real_time() */ #endif #ifdef F_VOWEL static int vowel P1( int, i ) { switch( i ) { case 'a': case 'e': case 'i': case 'o': case 'u': case 'A': case 'E': case 'I': case 'O': case 'U': return 1; default: return 0; } } /* vowel() */ void f_vowel PROT((void)) { sp->u.number = vowel(sp->u.number); } /* f_vowel() */ #endif #ifdef F_ADD_A void f_add_a PROT((void)) { char *ret; int i = 0, len, sz = SVALUE_STRLEN(sp); while( sp->u.string[i] == ' ') i++; len = sz - i; if( vowel( sp->u.string[ i ] ) ) { ret = new_string( len + 3, "f_add_a: ret"); ret[len+3] = 0; strcpy( ret, "an "); if( len ) strncpy( ret + 3, sp->u.string + i, len ); } else { ret = new_string( len + 2, "f_add_a: ret"); ret[len+2] = 0; strcpy( ret, "a "); if( len ) strncpy( ret + 2, sp->u.string + i, len ); } free_string_svalue(sp); put_malloced_string(ret); } /* f_add_a() */ #endif #ifdef F_BASE_NAME void f_base_name PROT((void)) { char *name, *tmp; int i; if( sp->type == T_OBJECT ) { if( sp->u.ob->flags & O_DESTRUCTED ) { free_object( sp->u.ob, "f_base_name"); *sp = const0u; return; } name = (char *)add_slash(sp->u.ob->name); free_object( sp->u.ob, "f_base_name"); } else { name = string_copy( sp->u.string, "f_base_name: name"); free_string_svalue(sp); } if( ( tmp = strchr( name, '#') ) != NULL ) { char *ret; i = tmp - name; ret = new_string( i, "f_base_name: ret"); ret[i] = 0; strncpy( ret, name, i ); FREE_MSTR(name); put_malloced_string(ret); } else { put_malloced_string(name); } } /* f_base_name() */ #endif #ifdef F_ORDINAL static char *ordinal P1( int, number ) { int i, num_l, nve, num; char *ret; if( number < 0 ) { number *= -1; num = number & 0x7fffffff; nve = 1; } else { num = number; nve = 0; } for( i = num / 10, num_l = nve + 1; i; i /= 10, num_l++ ); ret = new_string( num_l+2, "ordinal: ret"); ret[num_l+2] = 0; i = num_l; while( num_l-- ) { ret[num_l] = ( num % 10 ) + '0'; num /= 10; } if( nve ) ret[0] = '-'; if( ( number % 100 > 10 ) && ( number % 100 < 14 ) ) { strcpy( ret + i, "th"); } else { switch( number % 10 ) { case 1: strcpy( ret + i, "st"); break; case 2: strcpy( ret + i, "nd"); break; case 3: strcpy( ret + i, "rd"); break; default: strcpy( ret + i, "th"); } } return ret; } /* ordinal */ void f_ordinal PROT((void)) { char *ret; ret = ordinal(sp->u.number); if( !ret ) put_number(0); else put_malloced_string(ret); } /* f_ordinal */ #endif #ifdef F_SHUFFLE void f_shuffle PROT((void)) { if( sp->type == T_ARRAY && sp->u.arr ) { array_t *arr = sp->u.arr; if( arr->size > 1 ) { svalue_t sv; int i, j; for( i = 0; i < arr->size; i++ ) { if( i == ( j = random_number( i + 1 ) ) ) continue; sv = arr->item[i]; arr->item[i] = arr->item[j]; arr->item[j] = sv; } } } else { pop_stack(); push_refed_array(&the_null_array); } } /* f_shuffle() */ #endif #ifdef F_CHOICE static void choose_from_array P2( svalue_t *, ret, array_t *, arr ) { int i; if( !( i = arr->size ) ) { assign_svalue_no_free( ret, &const0 ); } else { i = random_number( i ); if( arr->item[i].type == T_OBJECT && ( arr->item[i].u.ob->flags & O_DESTRUCTED ) ) { assign_svalue( &arr->item[i], &const0u ); } assign_svalue_no_free( ret, &arr->item[i] ); } free_array(arr); } /* choose_from_array() */ void f_choice PROT((void)) { int i; svalue_t ret; switch( sp->type ) { case T_ARRAY : choose_from_array( &ret, sp->u.arr ); *sp = ret; break; case T_STRING : if( !( i = SVALUE_STRLEN(sp) ) ) { assign_svalue( sp, &const0 ); } else { i = sp->u.string[ random_number( i ) ]; free_string_svalue(sp); put_number(i); } break; case T_MAPPING : choose_from_array( &ret, mapping_values( sp->u.map ) ); free_mapping( sp->u.map ); *sp = ret; break; default: bad_argument( sp, T_ARRAY | T_STRING | T_MAPPING, 1, F_CHOICE ); } } /* f_choice() */ #endif #if defined(F_UNIQ_ARRAY) || defined(F_DISTINCT_ARRAY) || defined(F_FIND_MEMBER) static int test_member P3( array_t *, arr, svalue_t *, find, int, size ) { int flen, ret = 0; svalue_t *sv; if( find->type == T_STRING ) { if( find->subtype & STRING_COUNTED ) flen = MSTR_SIZE(find->u.string); else flen = 0; } while( size-- ) { switch( find->type | ( sv = arr->item + size )->type ) { case T_STRING: if( flen && ( sv->subtype & STRING_COUNTED ) && flen != MSTR_SIZE(sv->u.string) ) continue; if( strcmp( find->u.string, sv->u.string ) ) continue; break; case T_NUMBER: if( find->u.number == sv->u.number ) break; continue; case T_REAL: if( find->u.real == sv->u.real ) break; continue; case T_ARRAY: if( find->u.arr == sv->u.arr ) break; continue; case T_OBJECT: if( sv->u.ob->flags & O_DESTRUCTED ) { assign_svalue( sv, &const0u ); continue; } if( find->u.ob == sv->u.ob ) break; continue; case T_MAPPING: if( find->u.map == sv->u.map ) break; continue; case T_FUNCTION: if( find->u.fp == sv->u.fp ) break; continue; #ifndef NO_BUFFER_TYPE case T_BUFFER: if( find->u.buf == sv->u.buf ) break; continue; #endif default: if( sv->type == T_OBJECT && (sv->u.ob->flags & O_DESTRUCTED) ) { assign_svalue( sv, &const0u ); if( find->type == T_NUMBER && !find->u.number ) break; } continue; } ret = 1; break; } return ret; } /* test_member() */ static void distinct_array P1( svalue_t *, sv ) { array_t *tmp, *ret; int i, j = 0, size = sv->u.arr->size; if( !size ) return; tmp = allocate_empty_array( size ); for( i = 0; i < size; i++ ) if( !test_member( tmp, &sv->u.arr->item[i], j ) ) assign_svalue_no_free( &tmp->item[j++], &sv->u.arr->item[i] ); while( size-- > j ) assign_svalue_no_free( &tmp->item[size], &const0u ); ret = allocate_empty_array( j ); while( j-- ) assign_svalue_no_free( &ret->item[j], &tmp->item[j] ); free_array( sv->u.arr ); free_array( tmp ); put_array( ret ); } /* distinct_array() */ #endif #ifdef F_UNIQ_ARRAY void f_uniq_array PROT((void)) { distinct_array( sp ); } /* f_uniq_array() */ #endif #ifdef F_DISTINCT_ARRAY void f_distinct_array PROT((void)) { distinct_array( sp ); } /* f_distinct_array() */ #endif #ifdef F_ROLL_MDN void f_roll_MdN PROT((void)) { int dice, sides, roll = 0; sides = sp->u.number; pop_stack(); dice = sp->u.number; if( dice > 0 && sides > 0 ) { while( dice-- ) roll += 1 + random_number( sides ); } sp->u.number = roll; } /* f_roll_MdN() */ #endif #ifdef F_QUERY_GROUP static int query_group( object_t *ob ) { svalue_t *ret; if( ob->flags & O_DESTRUCTED ) return 0; if( !( ret = apply("group_object", ob, 0, ORIGIN_EFUN ) ) ) { char *str = "group object"; copy_and_push_string(str); ret = apply("query_property", ob, 1, ORIGIN_EFUN ); } return ( ret && ret->type == T_NUMBER && ret->u.number > 0 ); } /* query_group() */ void f_query_group PROT((void)) { int ret = 0; if( sp->type == T_OBJECT ) { ret = query_group( sp->u.ob ); free_object( sp->u.ob, "f_query_group"); } else { if( ( ret = sp->u.arr->size ) > 0 ) { if( ret == 1 ) { if( sp->u.arr->item[0].type == T_OBJECT ) ret = query_group( sp->u.arr->item[0].u.ob ); else ret = 0; } else { ret = 1; } } free_array( sp->u.arr ); } put_number( ret ); } /* f_query_group() */ #endif #ifdef F_FILE_EXISTS void f_file_exists PROT((void)) { int i = file_size(sp->u.string); free_string_svalue(sp); put_number( i > -1 ); } /* f_file_exists() */ #endif #ifdef F_DIR_EXISTS void f_dir_exists PROT((void)) { int i = file_size(sp->u.string); free_string_svalue(sp); put_number( i == -2 ); } /* f_dir_exists() */ #endif #ifdef F_DELETE void f_delete PROT((void)) { int i, start = (sp-1)->u.number, len = sp->u.number, size; pop_n_elems( 2 ); if( start < 0 ) error("Bad argument 2 to delete() (negative starting index).\n"); if( len < 1 ) error("Bad argument 3 to delete() (invalid length).\n"); if( sp->type == T_ARRAY ) { array_t *ret; if( !( size = sp->u.arr->size ) ) return; if( start > size - 1 ) error("Bad argument 2 to delete() (index out of bounds).\n"); if( start + len > size ) len = size - start; size -= len; ret = allocate_empty_array( size ); for( i = 0; i < start; i++ ) assign_svalue_no_free( &ret->item[i], &sp->u.arr->item[i] ); for( ; i < size; i++ ) assign_svalue_no_free( &ret->item[i], &sp->u.arr->item[i+len] ); free_array( sp->u.arr ); put_array( ret ); } else { char *ret; if( !( size = SVALUE_STRLEN(sp) ) ) return; if( start > size - 1 ) error("Bad argument 2 to delete() (index out of bounds).\n"); if( start + len > size ) len = size - start; size -= len; ret = new_string( size, "delete: ret"); ret[size] = 0; if( start ) strncpy( ret, sp->u.string, start ); strncpy( ret + start, sp->u.string + start + len, size - start ); free_string_svalue(sp); put_malloced_string(ret); } } /* delete() */ #endif #ifdef F_INSERT void f_insert PROT((void)) { svalue_t *sv; int pos, size, i; if( ( pos = sp->u.number ) < 0 ) pos = 0; pop_stack(); sv = sp - 1; if( sv->type == T_ARRAY ) { array_t *ret; if( pos > ( size = sv->u.arr->size ) ) pos = size; ret = allocate_empty_array( ++size ); for( i = 0; i < pos; i++ ) assign_svalue_no_free( &ret->item[i], &sv->u.arr->item[i] ); assign_svalue_no_free( &ret->item[i++], sp ); for( ; i < size; i++ ) assign_svalue_no_free( &ret->item[i], &sv->u.arr->item[i-1] ); pop_stack(); free_array( sp->u.arr ); put_array(ret); } else if( sv->type == T_STRING ) { char *ret; CHECK_TYPES( sp, T_STRING, 2, F_INSERT ); if( pos > ( size = SVALUE_STRLEN(sv) ) ) pos = size; if( !( i = SVALUE_STRLEN(sp) ) ) { ret = string_copy( sp->u.string, "insert: ret"); } else { ret = new_string( size + i, "insert: ret"); ret[size+i] = 0; if( pos > 0 ) strncpy( ret, sv->u.string, pos ); strncpy( ret + pos, sp->u.string, i ); if( size -= pos ) strncpy( ret + pos + i, sv->u.string + pos, size ); } free_string_svalue(sp--); free_string_svalue(sp); put_malloced_string(ret); } else { bad_argument( sv, T_STRING | T_ARRAY, 1, F_INSERT ); } } /* f_insert() */ #endif #ifdef F_INDENT void f_indent PROT((void)) { int cols, indent; char *str; cols = sp->u.number; indent = (sp-1)->u.number; str = string_copy( (sp-2)->u.string, "f_indent: str"); pop_n_elems(3); push_number( indent ); copy_and_push_string(""); push_number( cols - indent - 1 ); push_malloced_string( str ); str = (char *)string_print_formatted("%*=s%-=*s", 4, sp - 3 ); pop_n_elems(4); push_malloced_string(str); } /* indent() */ #endif #ifdef F_QUERY_SHADOWS void f_query_shadows PROT((void)) { object_t *obj, *tmp; int i = 0; tmp = obj = sp->u.ob; while( ( tmp = obj->shadowed ) ) { obj = tmp; i++; } if( i ) { array_t *arr; arr = allocate_empty_array( i ); i = 0; tmp = obj = sp->u.ob; while( ( tmp = obj->shadowed ) ) { arr->item[i].type = T_OBJECT; arr->item[i].u.ob = tmp; add_ref( arr->item[i].u.ob, "f_query_shadows"); obj = tmp; i++; } free_object( sp->u.ob, "f_query_shadows"); put_array( arr ); } else { free_object( sp->u.ob, "f_query_shadows"); put_number(0); } } /* f_query_shadows() */ #endif #ifdef F_QUERY_MULTIPLE_SHORT static void qms_type_error PROT((void)) { error("Bad argument 2 to query_multiple_short() - must be one of " "\"a\", \"the\", \"one\", \"poss\" or zero.\n"); } /* qms_type_error() */ #define QMS_FREE FREE(lens); \ free_array(arr); void f_query_multiple_short PROT((void)) { svalue_t *val, *sv; array_t *obs, *arr; char *type = NULL, *ret, *tmp; int no_dollars = 0, flag = 0, j = 0, total = 0, i, sz, real; int *lens; switch( st_num_arg ) { case 4: flag = sp->u.number; pop_stack(); case 3: no_dollars = sp->u.number; pop_stack(); case 2: switch( sp->type ) { case T_STRING: if( !( i = SVALUE_STRLEN(sp) ) ) qms_type_error(); type = new_string( i + 6, "f_query_multiple_short: type"); type[i+6] = 0; strncpy( type, sp->u.string, i ); strncpy( type + i, "_short", 6 ); break; case T_NUMBER: if( !sp->u.number ) break; default: qms_type_error(); } pop_stack(); case 1: if( !( sz = ( obs = sp->u.arr )->size ) ) { if( type ) FREE_MSTR(type); free_empty_array( sp->u.arr ); put_constant_string(""); return; } if( !type ) type = string_copy("a_short", "f_query_multiple_short: type"); arr = allocate_empty_array( sz ); lens = CALLOCATE( sz, int, TAG_TEMPORARY, "f_query_multiple_short: lens"); for( i = 0, real = 0; i < sz; i++ ) { svalue_t *retval; sv = &obs->item[i]; if( sv->type == T_OBJECT ) { if( sv->u.ob->flags & O_DESTRUCTED ) { assign_svalue( sv, &const0u ); } else { push_number(flag); if( ( retval = apply( type, sv->u.ob, 1, ORIGIN_EFUN ) ) && ( retval->type == T_STRING ) ) { val = &arr->item[real]; assign_svalue_no_free( val, retval ); total += ( lens[real++] = SVALUE_STRLEN( val ) ); } } } else { j = 1; if( sv->type == T_STRING ) { val = &arr->item[real]; assign_svalue_no_free( val, sv ); total += ( lens[real++] = SVALUE_STRLEN( val ) ); } } } for( i = real; i < sz; i++ ) assign_svalue_no_free( &arr->item[i], &const0u ); FREE_MSTR(type); free_array( sp->u.arr ); if( !( sz = real ) ) { QMS_FREE; put_constant_string(""); return; } } /* Only objects and no conversion. */ if( !j && !no_dollars ) { total += 6; if( total > MAX_STRING_LENGTH ) { QMS_FREE; error("Maximum string length exceeded in " "query_multiple_short().\n"); } tmp = ( ret = new_string( total, "f_query_multiple_short: tmp") ); ret[total] = 0; strncpy( tmp, "$M$", 3 ); tmp += 3; for( i = 0; i < sz; i++ ) { sv = &arr->item[i]; strncpy( tmp, sv->u.string, lens[i] ); tmp += lens[i]; } strncpy( tmp, "$M$", 3 ); goto end_qms; } switch( sz ) { case 1: ret = string_copy( arr->item[0].u.string, "f_query_multiple_short: ret"); break; case 2: total += 5; if( total > MAX_STRING_LENGTH ) { QMS_FREE; error("Maximum string length exceeded in " "query_multiple_short().\n"); } tmp = ( ret = new_string( total, "f_query_multiple_short: ret") ); ret[total] = 0; strncpy( tmp, arr->item[0].u.string, lens[0] ); strncpy( tmp += lens[0], " and ", 5 ); strncpy( tmp += 5, arr->item[1].u.string, lens[1] ); break; default: total += ( sz - 2 ) * 2 + 5; if( total > MAX_STRING_LENGTH ) { QMS_FREE; error("Maximum string length exceeded in " "query_multiple_short().\n"); } tmp = ( ret = new_string( total, "f_query_multiple_short: ret") ); ret[total] = 0; total = sz - 2; for( i = 0; i < total; i++ ) { sv = &arr->item[i]; strncpy( tmp, sv->u.string, lens[i] ); strncpy( tmp += lens[i], ", ", 2 ); tmp += 2; } sv = &arr->item[i]; strncpy( tmp, sv->u.string, lens[i] ); strncpy( tmp += lens[i], " and ", 5 ); sv = &arr->item[++i]; strncpy( tmp += 5, sv->u.string, lens[i] ); } if( no_dollars ) { object_t *ob; if( ( ob = command_giver ) || ( ob = find_object("/global/player") ) ) { push_malloced_string(ret); if( ( val = apply("convert_message", ob, 1, ORIGIN_EFUN ) ) && ( val->type == T_STRING ) ) { QMS_FREE; assign_svalue_no_free( sp, val ); return; } } else { FREE_MSTR(ret); } QMS_FREE; put_constant_string(""); return; } end_qms: QMS_FREE; put_malloced_string(ret); } /* f_query_multiple_short() */ #endif #ifdef F_REFERENCE_ALLOWED int in_reference_allowed = 0; void f_reference_allowed PROT((void)) { int invis, len, ret = 0, sz; svalue_t *sv; object_t *ob; char *referrer; if( in_reference_allowed ) { pop_2_elems(); push_number(1); return; } if( ( ob = (sp-1)->u.ob )->flags & O_DESTRUCTED ) { free_object( ob, "f_reference_allowed"); *(sp-1) = const0u; pop_2_elems(); push_number(0); return; } if( !( sv = apply("query_invis", ob, 0, ORIGIN_EFUN ) ) || ( sv->type == T_NUMBER && !( invis = sv->u.number ) ) ) { pop_2_elems(); push_number(1); return; } switch( sp->type ) { case T_OBJECT: if( sp->u.ob == ob ) { pop_2_elems(); push_number(1); return; } if( !( sv = apply("query_name", sp->u.ob, 0, ORIGIN_EFUN ) ) || sv->type != T_STRING ) { pop_2_elems(); push_number(0); return; } break; case T_STRING: sv = sp; break; case T_NUMBER: if( sp->u.number ) bad_argument( sp, T_OBJECT | T_STRING, 2, F_REFERENCE_ALLOWED ); pop_2_elems(); push_number(0); return; default: bad_argument( sp, T_OBJECT | T_STRING, 2, F_REFERENCE_ALLOWED ); } if( !( len = SVALUE_STRLEN(sv) ) ) { pop_2_elems(); push_number(0); return; } referrer = new_string( len, "f_reference_allowed: referrer"); referrer[len] = 0; strncpy( referrer, sv->u.string, len ); in_reference_allowed = 1; if( ( sv = apply("query_allowed", ob, 0, ORIGIN_EFUN ) ) && sv->type == T_ARRAY && ( sz = sv->u.arr->size ) ) { int i, pt = 0, fr = 0; array_t *arr = sv->u.arr; while( sz-- ) { sv = arr->item + sz; if( sv->type == T_STRING && ( i = SVALUE_STRLEN(sv) ) ) { if( i == len && ( ret = !strcmp( sv->u.string, referrer ) ) ) { goto end_ref_allowed; } else { if( !fr && i == 7 ) fr = !strcmp( sv->u.string, "friends"); if( !pt && i == 11 ) pt = !strcmp( sv->u.string, "playtesters"); } } } if( fr ) { copy_and_push_string( referrer ); if( ( sv = apply("query_friend", ob, 1, ORIGIN_EFUN ) ) && sv->type == T_NUMBER && ( ret = ( sv->u.number > 0 ) ) ) { goto end_ref_allowed; } } if( pt && simul_efun_ob ) { copy_and_push_string( referrer ); if( ( sv = apply("playtesterp", simul_efun_ob, 1, ORIGIN_EFUN ) ) && sv->type == T_NUMBER && ( ret = ( sv->u.number > 0 ) ) ) { goto end_ref_allowed; } } } if( simul_efun_ob ) { switch( invis ) { case 3 : copy_and_push_string( referrer ); ret = ( ( sv = apply("adminp", simul_efun_ob, 1, ORIGIN_EFUN ) ) && sv->type == T_NUMBER && sv->u.number > 0 ); break; case 2 : copy_and_push_string( referrer ); ret = ( ( sv = apply("lordp", simul_efun_ob, 1, ORIGIN_EFUN ) ) && sv->type == T_NUMBER && sv->u.number > 0 ); break; case 1 : copy_and_push_string( referrer ); ret = ( ( sv = apply("creatorp", simul_efun_ob, 1, ORIGIN_EFUN ) ) && sv->type == T_NUMBER && sv->u.number > 0 ); break; default : ret = 1; } } end_ref_allowed: in_reference_allowed = 0; FREE_MSTR(referrer); pop_2_elems(); push_number(ret); } /* f_reference_allowed() */ #endif #ifdef F_FIND_MEMBER void f_find_member PROT((void)) { int i = 0, sz = 0, len, *arr; svalue_t *sv; array_t *ret; switch( sp->type ) { case T_STRING : { char *tmp; int what; CHECK_TYPES( sp-1, T_NUMBER, 1, F_FIND_MEMBER ); if( !( len = SVALUE_STRLEN(sp) ) ) { free_string_svalue(sp--); put_array( &the_null_array ); return; } arr = CALLOCATE( len, int, TAG_TEMPORARY, "f_find_member: arr"); what = (sp-1)->u.number; while( ( tmp = strchr( sp->u.string + i, what ) ) ) { i = tmp - sp->u.string; arr[sz++] = i++; } free_string_svalue(sp--); } break; case T_ARRAY : { svalue_t *what; int slen = 0; if( !( len = sp->u.arr->size ) ) { pop_2_elems(); push_array( &the_null_array ); return; } arr = CALLOCATE( len, int, TAG_TEMPORARY, "f_find_member: arr"); what = sp-1; if( what->type == T_STRING && ( what->subtype & STRING_COUNTED ) ) slen = MSTR_SIZE( what->u.string ); for( i = 0; i < len; i++ ) { switch( what->type | ( sv = sp->u.arr->item + i )->type ) { case T_STRING: if( slen && ( sv->subtype & STRING_COUNTED ) && slen != MSTR_SIZE( sv->u.string ) ) continue; if( strcmp( what->u.string, sv->u.string ) ) continue; break; case T_NUMBER: if( what->u.number == sv->u.number ) break; continue; case T_REAL: if( what->u.real == sv->u.real ) break; continue; case T_ARRAY: if( what->u.arr == sv->u.arr ) break; continue; case T_OBJECT: if( sv->u.ob->flags & O_DESTRUCTED ) { assign_svalue( sv, &const0u ); continue; } if( what->u.ob == sv->u.ob ) break; continue; case T_MAPPING: if( what->u.map == sv->u.map ) break; continue; case T_FUNCTION: if( what->u.fp == sv->u.fp ) break; continue; #ifndef NO_BUFFER_TYPE case T_BUFFER: if( what->u.buf == sv->u.buf ) break; continue; #endif default: if( sv->type == T_OBJECT && ( sv->u.ob->flags & O_DESTRUCTED ) ) { assign_svalue( sv, &const0u ); if( what->type == T_NUMBER && !what->u.number ) break; } continue; } arr[sz++] = i; } free_array( (sp--)->u.arr ); } break; default: bad_argument( sp, T_STRING | T_ARRAY, 2, F_FIND_MEMBER ); } ret = allocate_empty_array( sz ); while( sz-- ) { sv = ret->item + sz; sv->type = T_NUMBER; sv->u.number = arr[sz]; } pop_stack(); FREE(arr); push_refed_array(ret); } /* f_find_member() */ #endif #ifdef F_EVENT /* EVENTS! * Okay. This is pretty simple. * Calls the function "event_"+event_name in the object specified. * If the object is an array, calls it in each. * If the object is a room, call it on its inventory. * [Incorrect: actually calls it on all_inventory() of any object but * only if addressed uniquely] * Passes all the parameters too. * --- * From FluffOS. * Made it a wee little faster and changed to clean up destructed objects. * - Sandoz. */ static void event P4( svalue_t *, event_ob, svalue_t *, event_fun, int, numparam, svalue_t *, event_param ) { int i = SVALUE_STRLEN(event_fun); object_t *ob, *origin; svalue_t *sv; char *name; origin = current_object; name = new_string( i + 6, "newmoon.c: au_event"); name[i+6] = 0; strncpy( name, "event_", 6 ); strncpy( name + 6, event_fun->u.string, i ); switch( event_ob->type ) { case T_ARRAY : for( i = 0; i < event_ob->u.arr->size; i++ ) { sv = event_ob->u.arr->item + i; if( sv->type == T_OBJECT ) { if( !( sv->u.ob->flags & O_DESTRUCTED ) ) { push_object(origin); push_some_svalues( event_param, numparam ); apply( name, sv->u.ob, numparam + 1, ORIGIN_EFUN ); } else { free_object( sv->u.ob, "event"); *sv = const0u; } } } break; case T_OBJECT : if( !( event_ob->u.ob->flags & O_DESTRUCTED ) ) { /* First we call the event on the object itself */ push_object(origin); push_some_svalues( event_param, numparam ); apply( name, event_ob->u.ob, numparam + 1, ORIGIN_EFUN ); /* And then call it on it's inventory... */ for( ob = event_ob->u.ob->contains; ob; ob = ob->next_inv ) { if( ob != origin && !( ob->flags & O_DESTRUCTED ) ) { push_object(origin); push_some_svalues( event_param, numparam ); apply( name, ob, numparam + 1, ORIGIN_EFUN ); } } } else { free_object( event_ob->u.ob, "event"); *event_ob = const0u; } break; default: FREE_MSTR(name); bad_argument( event_ob, T_OBJECT | T_ARRAY, 1, F_EVENT ); } FREE_MSTR(name); } /* event() */ void f_event PROT ((void)) { int num = st_num_arg; svalue_t *start = sp - num; event( start + 1, start + 2, num - 2, start + 3 ); pop_n_elems(num); } /* f_event() */ #endif #ifdef F_QUERY_PRIME void f_query_prime PROT((void)) { int num = sp->u.number, div = 2; for( ; div <= num / 2; div++ ) if( !( num % div ) ) { put_number( 0 ); return; } put_number( 1 ); } /* f_query_prime() */ #endif #ifdef F_MUD_NAME void f_mud_name PROT((void)) { #ifdef MUD_NAME copy_and_push_string(MUD_NAME); #else copy_and_push_string("Broken Mud Name"); #endif } /* f_mud_name() */ #endif