/* * Playground+ - dynatext.c * Code for converting dynatext (and slimepit style masks) v3.0 * --------------------------------------------------------------------------- * * Version 3.0 written by ekto * Version 2.0-2.4 written by Silver, Blimey and phypor. * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <ctype.h> #include <stdarg.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> #include <time.h> #include "include/fix.h" #include "include/config.h" #include "include/player.h" #include "include/proto.h" #include "include/masks.h" char talker_name[80]; char talker_email[80]; player *get_random_room_player(void); player *get_random_talker_player(void); char *the_time(int, int); char *my_rank(player *); char *my_partner(player *); int number_of(int); player *this_rand; #define M_SFX 0 #define M_THING 1 #define M_DESCRIBE 2 #define M_THINGS 3 #define M_MAX 4 static file mask_files[M_MAX]; static char **mask_list[M_MAX]; static int mask_count[M_MAX] = { -1, -1, -1, -1 }; static char *mask_xlist[M_MAX][64]; static int mask_next[M_MAX]; static int mask_max[M_MAX]; static int show_tag = 0; /* For <TARGET> */ extern player *targ; /* For <OBJECTNAME> */ char *item_name = NULL; /* For <STR> */ extern char social_str[128]; /* masks_genlist() * * Generate a list from the entries in a file. */ char **masks_genlist(file f) { size_t c; char *p, *q, **l; if(!f.length || !f.where) return NULL; /* Count the number of entries */ c=0; p=f.where; while(*p) { while((*p) && isspace(*p)) p++; if(!*p) continue; c++; q=strchr(p, '\n'); if(!q) { q=strchr(p, '\0'); } else { q++; } p=q; } if(!c) { return NULL; } c++; l=(char **)malloc(c*sizeof(char *)); memset(l, 0, c*sizeof(char *)); p=f.where; c=0; while(*p) { while((*p) && isspace(*p)) p++; if(!*p) continue; l[c]=p; c++; q=strchr(p, '\n'); if(!q) { q=strchr(p, '\0'); } else { *q=0; q++; } p=q; } return l; } /* masks_init() * * Load sfx/thing/describe lists from disk */ void masks_load(int id, char *fn) { mask_files[id]=load_file(fn); mask_list[id]=masks_genlist(mask_files[id]); } void masks_init(void) { masks_load(M_SFX, "files/sfx"); masks_load(M_THING, "files/things"); masks_load(M_DESCRIBE, "files/describe"); masks_load(M_THINGS, "files/pluralthings"); masks_reset(); } void masks_free(int id) { free(mask_files[id].where); mask_files[id].where = NULL; mask_files[id].length = 0; free(mask_list[id]); mask_list[id] = NULL; } void masks_done(void) { masks_free(M_SFX); masks_free(M_THING); masks_free(M_DESCRIBE); masks_free(M_THINGS); masks_reset(); } /* masks_reset() * * Re-randomise the random masks. */ void masks_recount(int id) { int c; if(!mask_list[id]) { mask_count[id]=0; } else if(mask_count[id]<0) { for(c=0; mask_list[id][c]; c++); mask_count[id]=c; } mask_next[id]=0; mask_max[id]=0; } void masks_reset(void) { social_str[0]=0; item_name = NULL; masks_recount(M_SFX); masks_recount(M_THING); masks_recount(M_DESCRIBE); masks_recount(M_THINGS); } /* a_an_thing() * * Return the given entry from thing[], prefixed by 'a' or 'an' as * appropriate. */ static char *a_an_thing(char *q) { char *p; static char buf[128]; p=q; if(isupper(p[0]) && !islower(p[1])) { if(strchr("AEFHILMNORSX", p[0])) { sprintf(buf, "an %s", q); return buf; } } if(strchr("aeiou", tolower(p[0]))) { sprintf(buf, "an %s", q); } else { sprintf(buf, "a %s", q); } return buf; } char *masks_player(player *p, player *t, char *mask) { static char buf[64]; if(!strcmp(mask, "name")) return t->name; if(!strcmp(mask, "fullname")) { if(!t->pretitle[0] || p->custom_flags & NOEPREFIX) { return t->name; } sprintf(buf, "%s %s", t->pretitle, t->name); return buf; } if(!strcmp(mask, "time")) return time_diff(t->jetlag); if(!strcmp(mask, "stime")) { strcpy(buf, the_time(t->jetlag, 1)); strcat(buf, ":"); strcat(buf, the_time(t->jetlag, 2)); strcat(buf, ":"); strcat(buf, the_time(t->jetlag, 3)); return buf; } if(!strcmp(mask, "hour")) return the_time(t->jetlag, 1); if(!strcmp(mask, "min")) return the_time(t->jetlag, 2); if(!strcmp(mask, "sec")) return the_time(t->jetlag, 3); if(!strcmp(mask, "day")) return the_time(t->jetlag, 4); if(!strcmp(mask, "month")) return the_time(t->jetlag, 5); if(!strcmp(mask, "date")) return the_time(t->jetlag, 6); if(!strcmp(mask, "year")) return the_time(t->jetlag, 7); if(!strcmp(mask, "rank")) return my_rank(t); if(!strcmp(mask, "cash")) { sprintf(buf, "%d", t->pennies); return buf; } if(!strcmp(mask, "gender")) return gstring_possessive(t); if(!strcmp(mask, "gender2")) return gstring(t); if(!strcmp(mask, "gender3")) return get_gender_string(t); if(!strcmp(mask, "hisher")) return gstring_possessive(t); if(!strcmp(mask, "heshe")) return gstring(t); if(!strcmp(mask, "himher")) return get_gender_string(t); if(!strcmp(mask, "partner")) return my_partner(t); if(!strcmp(mask, "lag")) { sprintf(buf, "%ld.%02ld", t->last_ping / 1000000, (t->last_ping / 10000) % 1000000); return buf; } if(!strcmp(mask, "lagstr")) return ping_string(t); return NULL; } char *masks_talker(player *p, char *mask) { static char buf[64]; if(!strcmp(mask, "addr")) { sprintf(buf, "%s %d", talker_alpha, active_port); return buf; } if(!strcmp(mask, "name")) return talker_name; if(!strcmp(mask, "email")) return talker_email; if(!strcmp(mask, "pot")) { sprintf(buf, "%d", pot); return buf; } if(!strcmp(mask, "online")) { sprintf(buf, "%d", current_players); return buf; } if(!strcmp(mask, "staff")) { sprintf(buf, "%d", count_su()); return buf; } if(!strcmp(mask, "count")) { sprintf(buf, "%d", number_of(0)); return buf; } if(!strcmp(mask, "countstaff")) { sprintf(buf, "%d", number_of(1)); return buf; } return NULL; } char *masks_entry(int id) { int c, d; if(mask_count[id]<1) { return NULL; } if(mask_next[id]<mask_max[id]) { c=mask_next[id]; mask_next[id]++; return mask_xlist[id][c]; } if(mask_max[id]<63) { c=mask_max[id]; d=mask_count[id]; mask_xlist[id][c]=mask_list[id][rand()%d]; mask_max[id]++; mask_next[id]=mask_max[id]; return mask_xlist[id][c]; } mask_next[id]=0; c=mask_next[id]; mask_next[id]++; return mask_xlist[id][c]; } char *masks_a_entry(int id) { char *p; p=masks_entry(id); if(p) { return a_an_thing(p); } return NULL; } char *masks_random(int id) { int c; if(mask_count[id]<1) { return NULL; } c=mask_count[id]; return mask_list[id][rand()%c]; } char *masks_reverse(player *p, char *str) { static char *s = NULL; char *t, *q; if(s) { free(s); } s = (char *)malloc (strlen(str) + 1); if (!s) { return NULL; } q = s; t = strchr(str, '\0'); while (t >= str+1) { t--; *q = *t; q++; } *q = 0; return s; } char *masks_replace(player *p, char *mask) { int c; char *x; c=0; show_tag = 0; while(static_masks[c]) { if(!strcmp(mask, static_masks[c])) { return static_masks[c+1]; } c+=2; } if(!(command_type & SOCIAL)) { show_tag = 1; } if(!strncmp(mask, "M:", 2)) { mask+=2; return masks_player(p, p, mask); } if(!strncmp(mask, "R:", 2)) { mask+=2; return masks_player(p, get_random_room_player(), mask); } if(!strncmp(mask, "A:", 2)) { mask+=2; return masks_player(p, get_random_talker_player(), mask); } if(!strncmp(mask, "T:", 2)) { mask+=2; return masks_talker(p, mask); } if(!strncmp(mask, "REV:", 4)) { mask+=4; return masks_reverse(p, mask); } if(current_player) { if(!strncmp(mask, "C:", 2)) { mask+=2; return masks_player(p, current_player, mask); } if(!strcmp(mask, "USERNAME")) return current_player->name; if(!strcmp(mask, "USERGENDER")) return gstring_possessive(current_player); if(!strcmp(mask, "USERGENDER1")) return gstring_possessive(current_player); if(!strcmp(mask, "USERGENDER2")) return gstring(current_player); if(!strcmp(mask, "USERGENDER3")) return get_gender_string(current_player); if(!strcmp(mask, "USERGENDER4")) return self_string(current_player); if(!strcmp(mask, "USERPREFIX")) return current_player->pretitle; if(current_player->location) { if(!strcmp(mask, "ROOMNAME")) return current_player->location->name; if(!strcmp(mask, "ROOMID")) return current_player->location->id; if(!strcmp(mask, "ROOMOWNER")) return current_player->location->owner->lower_name; } #ifndef ESOCIALS if(command_type & SOCIAL) { if(!strcmp(mask, "STR")) { return social_str; } } if(targ && (command_type & SOCIAL)) { if(targ!=current_player) { if(!strncmp(mask, "P:", 2)) { mask+=2; return masks_player(p, targ, mask); } if(!strcmp(mask, "TARGET")) return targ->name; if(!strcmp(mask, "TPREFIX")) return targ->pretitle; if(!strcmp(mask, "TGENDER")) return gstring_possessive(targ); if(!strcmp(mask, "TGENDER1")) return gstring_possessive(targ); if(!strcmp(mask, "TGENDER2")) return gstring(targ); if(!strcmp(mask, "TGENDER3")) return get_gender_string(targ); } } #endif } if(item_name && !strcmp(mask, "OBJECTNAME")) return item_name; if(!strcmp(mask, "SFX")) { return masks_entry(M_SFX); } if(!strcmp(mask, "XSFX")) { return masks_random(M_SFX); } if(!strcmp(mask, "THING")) { return masks_entry(M_THING); } if(!strcmp(mask, "THINGS")) { return masks_entry(M_THINGS); } if(!strcmp(mask, "ATHING")) { return masks_a_entry(M_THING); } if(!strcmp(mask, "XTHING")) { return masks_random(M_THING); } if(!strcmp(mask, "DESCRIBE")) { return masks_entry(M_DESCRIBE); } if(!strcmp(mask, "ADESCRIBE")) { return masks_a_entry(M_DESCRIBE); } if(!strcmp(mask, "XDESCRIBE")) { return masks_random(M_DESCRIBE); } for(x=mask; *x; x++) { if(!isalpha(*x)) continue; if(!isupper(*x)) break; } if(*x) { return NULL; } lower_case(mask); return masks_player(p, p, mask); } char *masks_process(player *p, char *str) { char *q, *t, *s, *oldstack; /* If the user muffles dynatext, just return 'str' */ if(p->custom_flags & NO_DYNATEXT && !(command_type & SOCIAL)) return str; /* Reset random masks */ mask_next[M_SFX]=0; mask_next[M_THING]=0; mask_next[M_DESCRIBE]=0; mask_next[M_THINGS]=0; oldstack=stack; while(*str) { if(*str=='<') { str++; t=str; while((*t) && *t != '>') t++; if(*t) { q=(char *)malloc((t-str)+1); strncpy(q, str, t-str); q[t-str]=0; t++; s=masks_replace(p, q); if(s) { if((p->tag_flags & TAG_DYNATEXT) && (show_tag)) { stack+=sprintf(stack, "{%s}", s); } else { stack+=sprintf(stack, "%s", s); } free(q); str=t; continue; } free(q); } *stack='<'; stack++; } *stack=*str; stack++; str++; } *stack++=0; return oldstack; } /* Loads of dynatext options :o) */ /* Time stuff */ char *the_time(int diff, int type) { time_t t; static char time_string[20]; t = time(0) + (3600 * diff); switch (type) { case 1: strftime(time_string, 19, "%H", localtime(&t)); break; case 2: strftime(time_string, 19, "%M", localtime(&t)); break; case 3: strftime(time_string, 19, "%S", localtime(&t)); break; case 4: strftime(time_string, 19, "%A", localtime(&t)); break; case 5: strftime(time_string, 19, "%B", localtime(&t)); break; case 6: strftime(time_string, 19, "%d", localtime(&t)); break; case 7: strftime(time_string, 19, "%Y", localtime(&t)); break; } return time_string; } /* Rank */ char *my_rank(player * p) { /* This isn't a case simply becuase it seemed to ignore the ranks and print "newbie" regardless - bad programing I know -sigh- */ /* tell the truth, unless you implemented an array to do it, this is the best way your gonna get ... -phy */ if (p->residency & CODER) return get_config_msg("coder_name"); else if (p->residency & HCADMIN) return get_config_msg("hc_name"); else if (p->residency & ADMIN) return get_config_msg("admin_name"); else if (p->residency & LOWER_ADMIN) return get_config_msg("la_name"); else if (p->residency & ASU) return get_config_msg("asu_name"); else if (p->residency & SU) return get_config_msg("su_name"); else if (p->residency & PSU) return get_config_msg("psu_name"); else if (p->residency) return "resident"; else return "newbie"; } /* Returns the players 'other-half' */ char *my_partner(player * p) { if (p->system_flags & (MARRIED | ENGAGED)) return (p->married_to); else return "no-one"; } player *get_random_room_player(void) { player *scan; int c = 0; if (this_rand) return this_rand; if (!current_player) return (player *) NULL; if (!current_player->location) return current_player; for (scan = current_player->location->players_top; scan; scan = scan->room_next, c++); c = rand() % c; for (scan = current_player->location->players_top; scan && c; scan = scan->room_next, c--); this_rand = scan; return scan; } player *get_random_talker_player(void) { player *scan; int i; if (this_rand) return this_rand; if (!current_player) return (player *) NULL; if (!current_players || !current_player->location) return current_player; i = (rand() % current_players); for (scan = flatlist_start; i; scan = scan->flat_next, i--); this_rand = scan; return scan; } int number_of(int only_su) { saved_player *scan, **hash; char c; int i, count = 0; for (c = 'a'; c <= 'z'; c++) { hash = saved_hash[((int) (tolower(c)) - (int) 'a')]; for (i = 0; i < HASH_SIZE; i++, hash++) { for (scan = *hash; scan; scan = scan->next) { if (scan->residency == BANISHD || scan->residency & ROBOT_PRIV || scan->residency & SYSTEM_ROOM) continue; if (only_su == 1) { if (scan->residency & (PSU | SU | ASU | LOWER_ADMIN | ADMIN | CODER | HCADMIN)) count++; } else count++; } } } return count; } void dynatext_version() { sprintf(stack, " -=*> Dynatext/Masks v3.0 (by ekto) enabled.\n"); stack = strchr(stack, 0); }