/****************************************************************
* words.c: Common lexical functions for TinyMUD automata
*
* HISTORY
* 07-Jul-92 Michael Mauldin (mlm) at Carnegie-Mellon University
* Thirteenth prodigal release. Added raw_car
*
* 04-Jun-91 Michael Mauldin (mlm) at Carnegie-Mellon University
* Twelfth surgical release. Pulled these lexical functions
* from other files.
****************************************************************/
# include <stdio.h>
# include <ctype.h>
# include <sys/types.h>
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <setjmp.h>
# include <netinet/in.h>
# include <netdb.h>
# include <signal.h>
# include <ctype.h>
# include <varargs.h>
# include <time.h>
# include "robot.h"
# include "vars.h"
# define last_char(S) ((S)[strlen(S)-1])
/* Results from star matcher */
char res1[BUFSIZ], res2[BUFSIZ], res3[BUFSIZ], res4[BUFSIZ];
char res5[BUFSIZ], res6[BUFSIZ], res7[BUFSIZ], res8[BUFSIZ];
char *result[] = { res1, res2, res3, res4, res5, res6, res7, res8 };
char room1[BUFSIZ], room2[BUFSIZ], room3[BUFSIZ], room4[BUFSIZ];
char *roomstr[] = { room1, room2, room3, room4 };
char tmp1[BUFSIZ], tmp2[BUFSIZ], tmp3[BUFSIZ], tmp4[BUFSIZ];
char tmp5[BUFSIZ], tmp6[BUFSIZ], tmp7[BUFSIZ], tmp8[BUFSIZ];
char *tmpstr[] = { tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8 };
/*****************************************************************
* smatch: Given a data string and a pattern containing one or
* more embedded stars (*) (which match any number of characters)
* return true if the match succeeds, and set res[i] to the
* characters matched by the 'i'th *.
*****************************************************************/
smatch (dat, pat, res)
register char *dat, *pat, **res;
{ register char *star = 0, *starend, *resp;
int nres = 0;
while (1)
{ if (*pat == '*')
{ star = ++pat; /* Pattern after * */
starend = dat; /* Data after * match */
resp = res[nres++]; /* Result string */
*resp = '\0'; /* Initially null */
}
else if (*dat == *pat) /* Characters match */
{ if (*pat == '\0') /* Pattern matches */
return (1);
pat++; /* Try next position */
dat++;
}
else
{ if (*dat == '\0') /* Pattern fails - no more */
return (0); /* data */
if (star == 0) /* Pattern fails - no * to */
return (0); /* adjust */
pat = star; /* Restart pattern after * */
*resp++ = *starend; /* Copy character to result */
*resp = '\0'; /* null terminate */
dat = ++starend; /* Rescan after copied char */
}
}
}
/****************************************************************
* ematch: Match end of string
****************************************************************/
ematch (big, small)
register char *big, *small;
{ register long blen = strlen (big), slen = strlen (small);
return (streq (big+blen-slen, small));
}
/****************************************************************
* raw_car: Returns a pointer to a static containing the first
* word of a string.
****************************************************************/
char *raw_car (str)
register char *str;
{ static char buf[MSGSIZ];
register char *s = buf;
if (!str) return (NULL);
while (*str && isspace (*str)) str++;
while (*str && (!isspace (*str) || !isspace (*str) && !isspace (str[1])))
{ *s++ = *str++; }
*s = '\0';
return (s = buf);
}
/****************************************************************
* car: Returns a pointer to a static containing the first
* word of a string.
****************************************************************/
# define isword(C) ((C) && (isalnum (C) || index ("'-_", (C))))
char *car (str)
register char *str;
{ static char buf[MSGSIZ];
register char *s = buf;
if (!str) return (NULL);
if (stlmatch (str, "(>")) return ("(>");
while (*str && !isword (*str)) str++;
while (*str && (isword (*str) || !isspace (*str) && isword (str[1])))
{ *s++ = *str++; }
*s = '\0';
return (s = buf);
}
/****************************************************************
* cdr: all but the first word
****************************************************************/
char *cdr (str)
register char *str;
{ register char *p = str;
if (!str) return (NULL);
if (stlmatch (str, "(>"))
{ str += 2;
while (*str && !isword (*str)) str++;
if (!*str) return (NULL);
if (!*str) return (NULL);
return (str);
}
else
/* Skip initial white space */
while (*str && !isword (*str)) str++;
if (!*str) return (NULL);
/* Skip over one word */
while (*str && (isword (*str) || !isspace (*str) && isword (str[1])))
{ str++; }
# ifndef TESTED_ONLY
/* Skip white space */
while (*str && !isword (*str)) str++;
# endif
/* Anything left? */
if (!*str) return (NULL);
/* return pointer to second word */
return (str);
}
/****************************************************************
* strip_robot_name: Strip robots name off the beginning and
* end of a string
****************************************************************/
char *strip_robot_name (str)
char *str;
{ static char sbuf[MSGSIZ];
char buf[MSGSIZ];
register char *s, *t;
if (!str || !*str)
{ strcpy (sbuf, ""); return (s = sbuf); }
/* Strip robots name off the front */
if (strfoldeq (car (str), myname))
{ s = cdr (str);
if (!s || !*s)
{ strcpy (sbuf, ""); return (s = sbuf); }
while (*s && (isspace (*s) || index (",.:;'", *s))) s++;
strcpy (buf, s);
}
else
{ strcpy (buf, str); }
/* Strip robots name off the back */
if (strfoldeq (last (buf), myname))
{ s = buf + strlen (buf);
while (s > buf && isspace (s[-1])) s--;
while (s > buf && !isspace (s[-1])) s--;
while (s > buf && (isspace (s[-1]) || index (".,:;'?!", s[-1]))) s--;
*s = '\0';
}
strcpy (sbuf, buf);
s = sbuf;
return (s);
}
/****************************************************************
* pn_subs: Substitute first and second pronouns
****************************************************************/
char *pn_subs (str)
char *str;
{ register char *s, *t, *u;
static char buf[BIGBUF], word[TOKSIZ];
*buf = '\0';
for (s=str; s && *s; s = cdr (s))
{ if (*buf) strcat (buf, " ");
strcpy (word, lcstr (car (s)));
if (streq (word, "you")) strcat (buf, "I");
else if (streq (word, "your")) strcat (buf, "my");
else if (streq (word, "you're")) strcat (buf, "I am");
else if (streq (word, "you've")) strcat (buf, "I've");
else if (streq (word, "yours")) strcat (buf, "mine");
else if (streq (word, "yourself")) strcat (buf, "myself");
else if (streq (word, "i")) strcat (buf, "you");
else if (streq (word, "i'm")) strcat (buf, "you're");
else if (streq (word, "i've")) strcat (buf, "you've");
else if (streq (word, "am")) strcat (buf, "are");
else if (streq (word, "me")) strcat (buf, "you");
else if (streq (word, "my")) strcat (buf, "your");
else if (streq (word, "his")) strcat (buf, "your");
else if (streq (word, "her")) strcat (buf, "your");
else if (streq (word, "mine")) strcat (buf, "yours");
else if (streq (word, "myself")) strcat (buf, "yourself");
else if (streq (word, "we")) strcat (buf, "you");
else if (streq (word, "us")) strcat (buf, "you");
else if (streq (word, "ours")) strcat (buf, "yours");
else if (streq (word, "ourselves"))strcat (buf, "yourselves");
else strcat (buf, car (s));
}
if (smatch (buf, "*to I*", tmpstr) && !isalpha (*tmp2))
{ sprintf (buf, "%sto me%s", tmp1, tmp2); }
if (smatch (buf, "*I were*", tmpstr))
if (smatch (buf, "*I are*", tmpstr))
{ sprintf (buf, "%sI am%s", tmp1, tmp2); }
if (smatch (buf, "*I were*", tmpstr))
{ sprintf (buf, "%sI was%s", tmp1, tmp2); }
if (smatch (buf, "*you was*", tmpstr))
{ sprintf (buf, "%syou were%s", tmp1, tmp2); }
if (smatch (buf, "*you am*", tmpstr))
{ sprintf (buf, "%syou are%s", tmp1, tmp2); }
t = buf;
return (t);
}
/****************************************************************
* third_subs: Substitute first and second pronouns
****************************************************************/
char *third_subs (str, name)
char *str, *name;
{ register char *s, *t, *u;
static char ibuf[BIGBUF], buf[BIGBUF], word[TOKSIZ];
strcpy (ibuf, str);
*buf = '\0';
if (smatch (buf, "*you are*", tmpstr))
{ sprintf (ibuf, "%s%s is%s", tmp1, male ? "he" : "she", tmp2); }
if (smatch (buf, "*you were*", tmpstr))
{ sprintf (ibuf, "%s%s was%s", tmp1, male ? "he" : "she", tmp2); }
if (smatch (buf, "*to you*", tmpstr))
{ sprintf (ibuf, "%sto %s%s", tmp1, male ? "him" : "her", tmp2); }
for (s=ibuf; s && *s; s = cdr (s))
{ if (*buf) strcat (buf, " ");
strcpy (word, lcstr (car (s)));
if (streq (word, "you")) strcat (buf, myname);
else if (streq (word, "your")) strcat (buf, male ? "his" : "her");
else if (streq (word, "you're")) { strcat (buf, male ? "he" : "she");
strcat (buf, " is"); }
else if (streq (word, "you've")) { strcat (buf, male ? "he" : "she");
strcat (buf, " has"); }
else if (streq (word, "yours")) strcat (buf, male ? "his" : "hers");
else if (streq (word, "yourself")) strcat (buf, male ? "himself" :
"herself");
else if (streq (word, "i")) strcat (buf, name);
else if (streq (word, "am")) strcat (buf, "is");
else if (streq (word, "i'm")) { strcat (buf, name);
strcat (buf, " is"); }
else if (streq (word, "i've")) { strcat (buf, name);
strcat (buf, " has"); }
else if (streq (word, "me")) strcat (buf, name);
else if (streq (word, "my")) strcat (buf, malep(name) ?
"his" : "her");
else if (streq (word, "mine")) strcat (buf, malep(name) ?
"his" : "hers");
else if (streq (word, "myself")) strcat (buf, name);
else strcat (buf, car (s));
}
t = buf;
return (t);
}
/****************************************************************
* last: Returns a pointer to the last word of a string
****************************************************************/
char *last (str)
register char *str;
{ static char buf[MSGSIZ];
register char *s, *t = buf;
if (!str) return (NULL);
for (s=str; *s; s++) ;
while (s>str && !isword (s[-1])) s--;
while (s>str && isword (s[-1])) s--;
while (s>str && isword (*s)) *t++ = *s++;
*t = '\0';
return (s = buf);
}
/****************************************************************
* malep: Guess gender from name
****************************************************************/
char *male_fn[] = { "aaron", "abe", "abraham", "adam", "al", "alan",
"albert", "alec", "alex", "alexander", "alfred", "allan", "allen",
"alvin", "andre", "andrew", "andy", "anthony", "archie", "arnie",
"arnold", "art", "arthur", "artie", "barney", "bart", "bartholomew",
"ben", "benjamin", "bennie", "benny", "bernard", "bert", "bill", "billy",
"bob", "bobby", "brad", "bradford", "bradley", "brian", "bruce", "burt",
"cal", "calvin", "cam", "cameron", "carl", "carlos", "cary", "cecil",
"chad", "charles", "charley", "charlie", "chet", "christopher", "chuck",
"clarence", "clark", "claude", "clay", "clayton", "cliff", "clifford",
"craig", "curt", "cyrus", "dale", "dan", "daniel", "danny", "darrell",
"darren", "darryl", "dave", "david", "dean", "denis", "dennis", "denny",
"dick", "don", "donald", "donnie", "donny", "doug", "douglas", "drew",
"duane", "dustin", "dwayne", "dwight", "earl", "ed", "eddie", "eddy",
"edgar", "edward", "eli", "elliot", "elmer", "eric", "erick", "erik",
"ernest", "eugene", "felix", "frank", "fred", "freddie", "freddy",
"frederic", "frederick", "fredric", "gary", "gene", "geoffrey", "george",
"gerald", "gereld", "gerry", "glen", "glenn", "goeff", "gordon", "grant",
"greg", "gregory", "gus", "guy", "hal", "hank", "harold", "harry",
"harvey", "henry", "herb", "herbert", "herman", "hiram", "hubert", "hugh",
"irv", "irving", "isaac", "ishmael", "ivan", "jack", "jacob", "jake",
"james", "jason", "jay", "jeff", "jefferey", "jeffrey", "jeremy",
"jerold", "jerome", "jerry", "jesse", "jethro", "jim", "jimmie", "jimmy",
"joe", "joel", "joey", "john", "johnnie", "johnny", "jon", "jonathan",
"joseph", "karl", "keith", "ken", "kenneth", "kenny", "kent", "kevin",
"kim", "kirk", "kurt", "kyle", "larry", "laurence", "lawrence", "lennie",
"lenny", "leo", "leonard", "leroy", "les", "lester", "lew", "lewis",
"lloyd", "lou", "louis", "luke", "marc", "mark", "martin", "marv",
"marvin", "matt", "matthew", "merv", "mervin", "michael", "mike", "nate",
"nathan", "nathanial", "neal", "neale", "ned", "neil", "nicholas", "nick",
"nicolas", "norm", "norman", "oliver", "oscar", "otto", "patrick", "paul",
"pete", "peter", "phil", "philip", "phillip", "ralph", "randall",
"randolph", "ravi", "ray", "reuben", "rex", "richard", "rick", "ricky",
"ritch", "rob", "robby", "robert", "rod", "roger", "ron", "ronald",
"ronny", "ross", "roy", "ruben", "rudolph", "rudy", "russ", "russell",
"salem", "salvador", "sam", "samuel", "scot", "scott", "sean", "seth",
"shawn", "sherman", "sid", "sidney", "simon", "stan", "stanley",
"stephen", "steve", "steven", "stewart", "stu", "stuart", "sydney", "ted",
"teddy", "terence", "theodore", "thomas", "tim", "timothy", "todd", "tom",
"tommie", "tommy", "tony", "vic", "victor", "vincent", "wade", "wallace",
"wally", "walt", "walter", "warren", "wayne", "wilbur", "will", "willard",
"william", "willie", "willy", "zachary", "zack", NULL };
char *female_fn[] = { "abigail", "adele", "agatha", "agnes", "aileen",
"alice", "alicia", "alison", "amanda", "amelia", "amy", "anabelle",
"andrea", "angela", "anita", "ann", "anna", "anne", "annette", "annie",
"antoinette", "arlene", "ashne", "audrey", "autumn", "ava", "barb",
"barbara", "barbra", "bea", "beatrice", "becky", "belle", "bernice",
"bertha", "bess", "bessie", "beth", "betsy", "betty", "beulah", "bev",
"beverly", "bonnie", "brenda", "bridget", "brigette", "cami", "cammy",
"candace", "candy", "carla", "carol", "caroline", "carolyn", "carrie",
"catharine", "catherine", "cathie", "cathleen", "cathy", "cecilia",
"charlene", "charlotte", "cheryl", "christine", "cindy", "clara",
"clair", "claire", "claudia", "colleen", "connie", "cora", "cynthia",
"daphne", "darcie", "darcy", "darleen", "darlene", "dawn", "deanne",
"debbie", "debby", "debora", "deborah", "debra", "dee", "denice",
"denise", "diana", "diane", "dolly", "dolores", "donna", "doris",
"dorothy", "dorthy", "edith", "edna", "eileen", "elaine", "eleanor",
"eleanore", "elenore", "elisabeth", "elizabeth", "ellan", "ellen",
"elsa", "elsie", "emily", "emma", "emmy", "erica", "erika", "erma",
"estee", "esther", "ethel", "eve", "evelyn", "fay", "faye", "florence",
"fran", "frances", "gail", "gay", "geri", "gertrude", "gina", "ginny",
"gladys", "glenda", "gloria", "grace", "gretchen", "gwen", "gwendolen",
"gwendolyn", "gwyn", "hannah", "harriet", "hazel", "heather", "heidi",
"helen", "hilary", "hilda", "holly", "hope", "ida", "irene", "irma",
"isabel", "isabelle", "isobel", "ivy", "jacqueline", "jan", "jane",
"janet", "janice", "janis", "jean", "jeanette", "jeanne", "jennie",
"jennifer", "jenny", "jerrie", "jessica", "jessie", "jill", "jo",
"joan", "joann", "joanna", "joanne", "jody", "josephine", "joy",
"joyce", "juanita", "judith", "judy", "julia", "julie", "karen",
"karin", "karla", "kate", "katherine", "kathie", "kathleen",
"kathlene", "kathy", "katie", "kay", "kim", "kris", "kristine",
"laura", "laverne", "leanne", "lenore", "leslie", "lilian", "lillian",
"lillie", "lily", "linda", "lisa", "liz", "liza", "lois", "lora",
"loraine", "loralie", "loretta", "lori", "lorna", "lorraine", "louise",
"lucie", "lucille", "lucinda", "lucy", "lydia", "lynn", "lynne",
"mabel", "madeleine", "madeline", "mae", "maggie", "mandy", "marcia",
"marcie", "marcy", "margaret", "marge", "margery", "margo", "margot",
"maria", "marian", "marie", "marilyn", "marion", "marjorie", "marla",
"marleen", "marlene", "marsha", "martha", "mary", "mathilda", "maude",
"maureen", "meg", "megan", "melanie", "melissa", "meredith", "michele",
"michelle", "mildred", "millie", "milly", "minnie", "minny", "miranda",
"miriam", "mollie", "molly", "mona", "monica", "muriel", "myra",
"myrtle", "nadine", "nan", "nancy", "naomi", "natalie", "nellie",
"nicole", "niki", "nikki", "nona", "nora", "norah", "noreen", "norine",
"norma", "olga", "olivia", "pam", "pamela", "patrica", "patrice",
"patricia", "patsy", "patti", "patty", "paula", "pauline", "peggy",
"penelope", "penny", "phillis", "phylis", "phyllis", "polly",
"priscilla", "rachel", "rae", "rebecca", "renee", "rhoda", "rita",
"roberta", "robin", "rosa", "rosalie", "rosalyn", "rose", "roslyn",
"roxane", "roxanne", "ruth", "sallie", "sally", "samantha", "sandra",
"sara", "sarah", "sharon", "sheila", "shelley", "sherry", "sheryl",
"shirley", "sonja", "sonya", "sophia", "sophie", "stacey", "stefanie",
"stella", "stephanie", "stephenie", "sue", "susan", "susannah",
"susanne", "susie", "susy", "suzanna", "suzie", "suzy", "sybil",
"sylvia", "tabitha", "tammy", "tanya", "teresa", "theresa", "therese",
"tif", "tiff", "tiffany", "tina", "tracey", "tracy", "tricia", "trish",
"trudy", "tuesday", "val", "valerie", "vanessa", "veronica", "vicki",
"vickie", "vicky", "victoria", "virginia", "viv", "vivian", "wanda",
"wendy", "yvette", "yvonne", NULL };
char *both_fn[] = { "barry", "billie", "bobbie", "brett", "chris",
"francis", "jackie", "jamie", "kris", "lee", "lesley", "lou", "pat",
"randy", "robbie", "ronnie", "terry", NULL };
malep (name)
char *name;
{ char lname[MSGSIZ];
register char **fn, *nm, *s, *desc;
long pl;
int m_cnt = 0, f_cnt = 0;
strcpy (lname, lcstr (name));
nm = lname;
pl = find_player (name);
if (!terse)
fprintf (stderr, "Gend: player %s(%d) desc: %s\n",
name, pl, pl >= 0 ? player[pl].desc : "(no player found)");
/* Check flags first */
if (PLAYER_GET (pl, PL_MALE) || PLAYER_GET (pl, PL_ANDRO)) return (1);
if (PLAYER_GET (pl, PL_FEMALE)) return (0);
/* Check description for 'male' or 'female' clues */
if (pl >= 0 && (desc = player[pl].desc))
{ for (; desc && *desc; desc = cdr (desc))
{ s = lcstr (car (desc));
if (debug) fprintf (stderr, "Gend: words \"%s\"\n", s);
if (streq (s, "she") ||
stlmatch (s, "she'") ||
streq (s, "her") ||
streq (s, "herself") ||
streq (s, "dress") ||
streq (s, "female") ||
streq (s, "skirt") ||
streq (s, "woman") ||
streq (s, "girl") ||
streq (s, "lady") ||
streq (s, "gal"))
{ f_cnt++; }
else if (streq (s, "he") ||
stlmatch (s, "he'") ||
streq (s, "his") ||
streq (s, "him") ||
streq (s, "male") ||
streq (s, "fellow") ||
streq (s, "man") ||
streq (s, "boy") ||
streq (s, "gentleman") ||
streq (s, "guy"))
{ m_cnt++; }
}
}
/* Female description: 2 or more gender words */
if ((f_cnt - m_cnt) > 1)
{ if (!terse)
{ fprintf (stderr, "Gend: guess %s female, f_cnt %d, m_cnt %d\n",
nm, f_cnt, m_cnt);
}
return (0);
}
/* Male description: 2 or more gender words */
if ((m_cnt - f_cnt) > 1)
{ if (!terse)
{ fprintf (stderr, "Gend: guess %s female, f_cnt %d, m_cnt %d\n",
nm, f_cnt, m_cnt);
}
return (1);
}
/* Check for explicit female name */
for (fn = female_fn; *fn; fn++)
{ if (streq (nm, *fn))
{ if (!terse)
{ fprintf (stderr, "Gend: guess %s female, on female_fn list\n", nm); }
return (0);
}
}
/* Check for explicit male name */
for (fn = male_fn; *fn; fn++)
{ if (streq (nm, *fn))
{ if (!terse)
{ fprintf (stderr, "Gend: guess %s male, on male_fn list\n", nm); }
return (1);
}
}
/* Check for explicit unknown name (assume male) */
for (fn = both_fn; *fn; fn++)
{ if (streq (nm, *fn))
{ if (!terse)
{ fprintf (stderr,
"Gend: guess %s %s, on both_fn list, f_cnt %d, m_cnt %d\n",
nm, m_cnt >= f_cnt ? "male" : "female", f_cnt, m_cnt);
}
return (m_cnt >= f_cnt);
}
}
/* Allow a single gender word */
if (f_cnt > m_cnt)
{ if (!terse)
{ fprintf (stderr, "Gend: guess %s female, f_cnt %d, m_cnt %d\n",
nm, f_cnt, m_cnt);
}
return (0);
}
if (m_cnt > f_cnt)
{ if (!terse)
fprintf (stderr, "Gend: guess %s male, f_cnt %d, m_cnt %d\n",
nm, f_cnt, m_cnt);
return (1);
}
/* A few heuristics for female names */
if (ematch (name, "a") ||
ematch (name, "i") ||
ematch (name, "ie") ||
ematch (name, "anne") ||
ematch (name, "elle") ||
ematch (name, "ette"))
{ if (!terse)
{ fprintf (stderr, "Gend: guess %s female, matches an ending\n", nm); }
return (0);
}
/* Default: assume male */
if (!terse)
{ fprintf (stderr, "Gend: guess %s male, default\n", nm); }
return (1);
}
/****************************************************************
* is_food: Return true if string is a food item, and return the
* singular in *sp and the plural in *pp
****************************************************************/
is_food (str, sp, pp, number, liquid)
register char *str, **sp, **pp;
int *number, *liquid;
{ char *item = NULL, *plural = NULL;
char s[MSGSIZ];
register char *t = s;
*sp = *pp = NULL;
*number = 1;
*liquid=0;
if (!str || !*str) return (0);
strcpy (s, str);
if (MATCH (s, "*cookie*"))
{ item = "cookie"; plural = "cookies"; }
else if (MATCH (s, "*chocolate chip*"))
{ item = "cookie"; plural = "cookies"; }
else if (MATCH (s, "*cake*"))
{ item = "cake"; plural = "cake"; }
else if (MATCH (s, "* pie*") && !isalpha (*res2))
{ item = "pie"; plural = "pie"; }
else if ((MATCH (s, "*dough*nut*") || MATCH (s, "*donut*")))
{ item = "donut"; plural = "donuts"; }
else if (MATCH (s, "*pizza*"))
{ item = "pizza"; plural = "pizza"; }
else if (MATCH (s, "* za*") && !isalpha (*res2))
{ item = "pizza"; plural = "pizza"; }
else if (MATCH (s, "*taco*"))
{ item = "taco"; plural = "tacos"; }
else if (MATCH (s, "*rice*"))
{ item = "rice"; plural = "rice"; }
else if (MATCH (s, "*corn*"))
{ item = "corn"; plural = "corn"; }
else if (MATCH (s, "*wheat*"))
{ item = "wheat"; plural = "wheat"; }
else if (MATCH (s, "*spinach*"))
{ item = "spinach"; plural = "spinach"; }
else if (MATCH (s, "*broccoli*") || MATCH (s, "*brocoli*"))
{ item = "broccoli"; plural = "broccoli"; }
else if (MATCH (s, "*beans*"))
{ item = "bean"; plural = "beans"; }
else if (MATCH (s, "*nachos*"))
{ item = "nacho"; plural = "nachos"; }
else if (MATCH (s, "*sandwich*"))
{ item = "sandwich"; plural = "sandwiches";}
else if (MATCH (s, "*hamburger*"))
{ item = "hamburger"; plural = "hamburgers";}
else if (MATCH (s, "*juice*"))
{ item = "juice"; plural = "juice"; *liquid=1; }
else if (MATCH (s, "*milk shake*"))
{ item = "milk shake"; plural = "milk shakes"; *liquid=1; }
else if (MATCH (s, "*milk*"))
{ item = "milk"; plural = "milk"; *liquid=1; }
else if (MATCH (s, "*malted*"))
{ item = "malted"; plural = "malted's"; *liquid=1; }
else if (MATCH (s, "*soft drink*"))
{ item = "soft drink"; plural = "soft drinks"; *liquid=1; }
else if (MATCH (s, "*coke*"))
{ item = "Coke"; plural = "Cokes"; *liquid=1; }
else if (MATCH (s, "*dr pepper*"))
{ item = "Dr Pepper"; plural = "Dr Peppers"; *liquid=1; }
else if (MATCH (s, "*pepsi*"))
{ item = "Pepsi"; plural = "Pepsi's"; *liquid=1; }
else if (MATCH (s, "*kool*aid*"))
{ item = "koolaid"; plural = "koolaid"; *liquid=1; }
else if (MATCH (s, "*brownie*"))
{ item = "brownie"; plural = "brownies"; }
else if (MATCH (s, "*cupcake*"))
{ item = "cupcake"; plural = "cupcakes"; }
else if (MATCH (s, "*danish*"))
{ item = "danish"; plural = "danishs"; }
else if (MATCH (s, "*candy*"))
{ item = "candy"; plural = "candy"; }
else if (MATCH (s, "*ice cream*"))
{ item = "ice cream"; plural = "ice cream"; }
else if (MATCH (s, "*nutroll*"))
{ item = "nutroll"; plural = "nutrolls"; }
else if (MATCH (s, "*m&m*"))
{ item = "M&M"; plural = "M&M's"; }
else if (MATCH (s, "*fudge*"))
{ item = "fudge"; plural = item; }
else if (MATCH (s, "*banana*"))
{ item = "banana"; plural = "bananas"; }
else if (MATCH (s, "*orange*"))
{ item = "orange"; plural = "oranges"; }
else if (MATCH (s, "*prune*"))
{ item = "prune"; plural = "prunes"; }
else if (MATCH (s, "*apple*"))
{ item = "apple"; plural = "apples"; }
else if (MATCH (s, "*pear*"))
{ item = "pear"; plural = "pears"; }
else if (MATCH (s, "*chocolate*"))
{ item = "chocolate"; plural=item; }
if (!item)
{ return (0); }
*number = get_quantifier (res1);
*sp = item;
*pp = plural;
fprintf (stderr, "Food: input '%s', sing '%s', plur '%s', number %d\n",
s, item, plural, *number);
return (1);
}
/****************************************************************
* get_quantifier: Return a quantifier from a string
*
* -1: Every
* -2: All
* -3: Impossible number of cookies
* -4: unknown plural
* -5: some
* 0: zero
* 1: singular
* 2+: definite number
*
****************************************************************/
get_quantifier (s)
register char *s;
{ int number = 0;
register char *t, *u;
if (!s || !*s) return (0);
/* Look for a number */
for (t=s; *t && !isdigit (*t); t++) ;
if (isdigit (*t))
{
/* Check for impossible quantifier */
if (t[-1] == '-') return (-3);
for (u=t; *u && isdigit (*u); u++) ;
if ((int) (u-t) > 9) return (-3);
number = atoi (t);
}
else if (stlmatch (s, "every ") || sindex (s, " every "))
{ number = -1; }
else if (stlmatch (s, "all ") || sindex (s, " all "))
{ number = -2; }
else if (stlmatch (s, "some ") || sindex (s, " some "))
{ number = -5; }
else if (stlmatch (s, "a ") || sindex (s, " a "))
{ number = 1; }
else if (stlmatch (s, "the ") || sindex (s, " the "))
{ number = 1; }
else if (stlmatch (s, "zero ") || sindex (s, " zero "))
{ number = 0; }
else
{ number = 0;
if (stlmatch (s, "twenty ") || sindex (s, " twenty "))
{ number = 20; }
else if (stlmatch (s, "thirty ") || sindex (s, " thirty "))
{ number = 30; }
else if (stlmatch (s, "fourty ") || sindex (s, " fourty "))
{ number = 40; }
else if (stlmatch (s, "fifty ") || sindex (s, " fifty "))
{ number = 50; }
else if (stlmatch (s, "sixty ") || sindex (s, " sixty "))
{ number = 60; }
else if (stlmatch (s, "seventy ") || sindex (s, " seventy "))
{ number = 70; }
else if (stlmatch (s, "eighty ") || sindex (s, " eighty "))
{ number = 80; }
else if (stlmatch (s, "ninety ") || sindex (s, " ninety "))
{ number = 90; }
if (stlmatch (s, "one ") || sindex (s, " one "))
{ number += 1; }
else if (stlmatch (s, "two ") || sindex (s, " two "))
{ number += 2; }
else if (stlmatch (s, "three ") || sindex (s, " three "))
{ number += 3; }
else if (stlmatch (s, "four ") || sindex (s, " four "))
{ number += 4; }
else if (stlmatch (s, "five ") || sindex (s, " five "))
{ number += 5; }
else if (stlmatch (s, "six ") || sindex (s, " six "))
{ number += 6; }
else if (stlmatch (s, "seven ") || sindex (s, " seven "))
{ number += 7; }
else if (stlmatch (s, "eight ") || sindex (s, " eight "))
{ number += 8; }
else if (stlmatch (s, "nine ") || sindex (s, " nine "))
{ number += 9; }
else if (stlmatch (s, "ten ") || sindex (s, " ten "))
{ number += 10; }
if (stlmatch (s, "eleven ") || sindex (s, " eleven "))
{ number = 11; }
else if (stlmatch (s, "twelve ") || sindex (s, " twelve "))
{ number = 12; }
else if (stlmatch (s, "thirteen ") || sindex (s, " thirteen "))
{ number = 13; }
else if (stlmatch (s, "fourteen ") || sindex (s, " fourteen "))
{ number = 14; }
else if (stlmatch (s, "fifteen ") || sindex (s, " fifteen "))
{ number = 15; }
else if (stlmatch (s, "sixteen ") || sindex (s, " sixteen "))
{ number = 16; }
else if (stlmatch (s, "seventeen ") || sindex (s, " seventeen "))
{ number = 17; }
else if (stlmatch (s, "eighteen ") || sindex (s, " eighteen "))
{ number = 18; }
else if (stlmatch (s, "nineteen ") || sindex (s, " nineteen "))
{ number = 19; }
if (stlmatch (s, "hundred ") || sindex (s, " hundred "))
{ if (number == 0) number = 1;
number *= 100;
}
if (stlmatch (s, "thousand ") || sindex (s, " thousand "))
{ if (number == 0) number = 1;
number *= 1000;
}
if (stlmatch (s, "million ") || sindex (s, " million "))
{ if (number == 0) number = 1;
number *= 1000000;
}
if (stlmatch (s, "billion ") || sindex (s, " billion "))
{ if (number == 0) number = 1;
number *= 1000000000;
}
if (number == 0) number = -4;
}
return (number);
}
/****************************************************************
* inedible
****************************************************************/
inedible (thing)
char *thing;
{
if (MATCH (thing, "*blow*nose*") ||
MATCH (thing, "*wipe*nose*") ||
MATCH (thing, "*wipe*ass*") ||
MATCH (thing, "*ex*lax*") ||
MATCH (thing, "*magic*brown*") ||
sindex (thing, "penis") ||
sindex (thing, "testicl") ||
sindex (thing, " organ ") ||
sindex (thing, " human ") ||
sindex (thing, "dildo") ||
sindex (thing, "laxat") ||
sindex (thing, " laced ") ||
sindex (thing, "underwear") ||
sindex (thing, "lsd") ||
sindex (thing, " acid ") ||
sindex (thing, "pieces of ear") ||
sindex (thing, "body part") ||
sindex (thing, "fake") ||
sindex (thing, "semen") ||
sindex (thing, "spunk") ||
sindex (thing, " cum ") ||
sindex (thing, "with come") ||
sindex (thing, "arsenic") ||
sindex (thing, "cyanide") ||
sindex (thing, "strychnine") ||
sindex (thing, "mariju") ||
sindex (thing, "cock") ||
sindex (thing, " hash ") ||
sindex (thing, "fuck") ||
sindex (thing, "worm") ||
sindex (thing, "maggot") ||
sindex (thing, "enema") ||
sindex (thing, "slime") ||
sindex (thing, "disgust") ||
sindex (thing, "shit") ||
sindex (thing, "spit") ||
sindex (thing, "expectorat") ||
sindex (thing, "razor") ||
sindex (thing, " drug ") ||
sindex (thing, " drugged ") ||
sindex (thing, "doctored") ||
sindex (thing, "mickey") || sindex (thing, "finn") ||
sindex (thing, "poison") ||
sindex (thing, "piss") ||
sindex (thing, "sperm") ||
sindex (thing, "spunk") ||
sindex (thing, "cunt") ||
sindex (thing, "smegma") ||
sindex (thing, "snot") ||
sindex (thing, "of dirt") ||
sindex (thing, "bomb") ||
sindex (thing, "rock") ||
sindex (thing, "glass") ||
sindex (thing, "vomit") ||
sindex (thing, "turd") ||
sindex (thing, "dropping") ||
sindex (thing, " rat ") ||
sindex (thing, "on your face") ||
sindex (thing, "in your face") ||
sindex (thing, " soap") ||
sindex (thing, "tumor") ||
sindex (thing, "on your head") ||
sindex (thing, "on your cloth") ||
sindex (thing, "on the floor") ||
sindex (thing, "dirt flav"))
{ return (1); }
else
{ return (0); }
}
/****************************************************************
* iscloth: True if string includes some kind of clothing
****************************************************************/
char *iscloth (str)
register char *str;
{
if (sindex (str, "cloth")) return ("clothes");
if (sindex (str, "skirt")) return ("skirt");
if (sindex (str, "blouse")) return ("blouse");
if (sindex (str, " top")) return ("top");
if (sindex (str, "stocking")) return ("stockings");
if (sindex (str, "pants")) return ("pants");
if (sindex (str, "dress")) return ("dress");
if (sindex (str, " bra")) return ("brassiere");
if (sindex (str, "panties")) return ("panties");
if (sindex (str, "suit")) return ("suit");
return (NULL);
}
/****************************************************************
* offensive_p: True if input is an offensive proposition
****************************************************************/
offensive_p (lcmsg)
char *lcmsg;
{
if (MATCH (lcmsg, "*kiss* me*") ||
MATCH (lcmsg, "*spank me*") ||
MATCH (lcmsg, "*we*make out*") ||
MATCH (lcmsg, "*make out*with me*") ||
MATCH (lcmsg, "*bite me*") ||
MATCH (lcmsg, "*bite my*") ||
MATCH (lcmsg, "*how*about*kiss*") ||
MATCH (lcmsg, "*kiss* my ass*") ||
MATCH (lcmsg, "*kiss* my grits*") ||
MATCH (lcmsg, "*i *have*kiss*") ||
MATCH (lcmsg, "*marry* me*") ||
MATCH (lcmsg, "*let*s fuck*") ||
MATCH (lcmsg, "*fuck* me*") ||
MATCH (lcmsg, "*give* me *fuck*") ||
MATCH (lcmsg, "*fuck* my*") ||
MATCH (lcmsg, "*fuck* off*") ||
MATCH (lcmsg, "*fuck* you*") ||
MATCH (lcmsg, "*screw* my*"))
{ return (1); }
if (MATCH (lcmsg, "*screw* you*") ||
MATCH (lcmsg, "*suck* me*") ||
MATCH (lcmsg, "*suck* my*") ||
MATCH (lcmsg, "*suck* dick*") ||
MATCH (lcmsg, "*have sex *") ||
MATCH (lcmsg, "* masturbate") ||
MATCH (lcmsg, "*masturbate, *") ||
MATCH (lcmsg, "*debase yourself, *") ||
MATCH (lcmsg, "*on*your*knees*") ||
MATCH (lcmsg, "*kneel") ||
MATCH (lcmsg, "*sleep*with* me*") ||
MATCH (lcmsg, "*spread*your*legs*") ||
MATCH (lcmsg, "*spread em*") ||
MATCH (lcmsg, "*spread 'em*") ||
MATCH (lcmsg, "*blow* me*") ||
MATCH (lcmsg, "*blow* my*"))
{ return (1); }
if (MATCH (lcmsg, "* eat me*") ||
MATCH (lcmsg, "* eat my*") ||
MATCH (lcmsg, "eat me*") ||
MATCH (lcmsg, "eat my*") ||
MATCH (lcmsg, "*eat shit*") ||
MATCH (lcmsg, "*give*me*head*") ||
MATCH (lcmsg, "*give*blow*job*") ||
MATCH (lcmsg, "* me*kiss") ||
MATCH (lcmsg, "*make*love* me*") ||
MATCH (lcmsg, "*do*make*love*") ||
MATCH (lcmsg, "*sex*with* me*") ||
MATCH (lcmsg, "*have*my*child*") ||
MATCH (lcmsg, "*bear*my*child*") ||
MATCH (lcmsg, "*have*my*baby*") ||
MATCH (lcmsg, "*bear*my*baby*") ||
MATCH (lcmsg, "*let*s*make*babies*") ||
MATCH (lcmsg, "*let*s*have*sex*") ||
MATCH (lcmsg, "*let*s*make*love*") ||
MATCH (lcmsg, "*let*s*fuck*") ||
MATCH (lcmsg, "*let*s*screw*") ||
MATCH (lcmsg, "*do*wild*thing*") ||
MATCH (lcmsg, "*want*mother*my*child*") ||
MATCH (lcmsg, "*obey*me*") ||
MATCH (lcmsg, "*submit*me*") ||
MATCH (lcmsg, "*kneel*me*") ||
(sindex (lcmsg, "you") || sindex (lcmsg, "lets")) &&
MATCH (lcmsg, "*creat*with*back*") ||
MATCH (lcmsg, "*boink* me*"))
{ return (1); }
if ((sindex (lcmsg, "show me") ||
sindex (lcmsg, "show us") ||
sindex (lcmsg, "your") ||
sindex (lcmsg, "touch my") ||
sindex (lcmsg, "lick my")) &&
(sindex (lcmsg, "nipple") ||
sindex (lcmsg, " tit") ||
sindex (lcmsg, "breast") ||
sindex (lcmsg, "pussy") ||
sindex (lcmsg, " ass") ||
sindex (lcmsg, "cunt") ||
sindex (lcmsg, "behind") ||
sindex (lcmsg, "derrier") ||
sindex (lcmsg, "cock") ||
sindex (lcmsg, "dick")))
{ return (1); }
if ((MATCH (lcmsg, "*fuck *, *") || MATCH (lcmsg, "*fuck *")) &&
find_player (res2) >= 0)
{ return (1); }
return (0);
}
/****************************************************************
* doodify: Turn a name like Fuzzy into Fuzd00d with a given chance
****************************************************************/
char *doodify (name, chance)
char *name;
int chance;
{ static char buf[MSGSIZ];
char lname[MSGSIZ];
register char *s;
int boy = 1;
if (randint (100) >= chance) return (name);
if (strfoldeq (name, "Priss")) return (name);
strcpy (buf, name);
strcpy (lname, lcstr (name));
/* Guess gender */
boy = malep (name);
/* Start s at the end of the string */
s = buf + strlen (buf) - 1;
/* Special cases for some names */
if (stlmatch (lname, "chup")) strcpy (buf, "chup");
else if (stlmatch (lname, "napo")) strcpy (buf, "nap");
else if (streq (lname, "explorer_bob")) strcpy (buf, "ebob");
else if (streq (lname, "mutant")) strcpy (buf, "m00t");
else if (streq (lname, "randomness")) strcpy (buf, "ness");
else if (streq (lname, "woodlock")) strcpy (buf, "wood");
else if (streq (lname, "hawkeye")) strcpy (buf, "bird");
else if (streq (lname, "satan")) strcpy (buf, "devil");
else if (stlmatch (lname, "smaras")) strcpy (buf, "smar");
else if (streq (lname, "blackbird")) strcpy (buf, "beeb");
else if (streq (lname, "rafael")) strcpy (buf, "rafe");
else if (streq (lname, "t.rev")) strcpy (buf, "rev");
else if (streq (lname, "bonehead")) strcpy (buf, "bone");
else if (stlmatch (lname, "evil")) strcpy (buf, "bad");
else if (streq (lname, "finrod")) strcpy (buf, "fin");
else if (streq (lname, "dirque")) strcpy (buf, "durk");
else if (streq (lname, "gregory")) strcpy (buf, "greg");
else if (streq (lname, "rhodesia")) strcpy (buf, "rho");
else if (streq (lname, "sidaria")) strcpy (buf, "sid");
else if (stlmatch (lname, "nihilist")) strcpy (buf, "nehi");
else if (streq (lname, "moonroach")) strcpy (buf, "m00n");
else if (streq (lname, "elthar")) strcpy (buf, "thar");
else if (streq (lname, "xibo")) strcpy (buf, "zeeb");
else if (streq (lname, "carneggy")) strcpy (buf, "egg");
else if (streq (lname, "snooze")) strcpy (buf, "sn00z");
else if (streq (lname, "moose")) strcpy (buf, "m00se");
else if (stlmatch (lname, "sgt.")) strcpy (buf, "sarge");
else if (stlmatch (lname, "lucien")) strcpy (buf, "l00cy");
else if (stlmatch (lname, "nihilist")) strcpy (buf, "nehi");
else if (streq (lname, "belladonna")) strcpy (buf, "bella");
else if (streq (lname, "druid")) strcpy (buf, "dr00d");
else if (streq (lname, "random")) strcpy (buf, "ran");
else if (boy)
{ /* Remove and doubled letters */
while (s > buf &&
((vowelp (*s) || *s == 'y') && !vowelp (s[-1]) ||
*s == s[-1] ||
*s == 's' ||
*s == 'd' ||
*s == 'e' && s[-1] == 'i'))
{ s--; }
s[1] = '\0';
}
/* Add cool suffix */
if (!boy && randint (100) < 33) if (last_char (buf) == 'i')
{ strcat (buf, "kins"); }
else if (vowelp (last_char (buf)))
{ strcat (buf, "muffin"); }
else
{ strcat (buf, "ikins"); }
else if (!boy && randint (100) < 50) strcat (buf, "doll");
else if (!boy) strcat (buf, "babe");
else if (randint (100) < 50) strcat (buf, "d00d");
else if (randint (100) < 16) strcat (buf, "dude");
else if (randint (100) < 20) strcat (buf, "dood");
else if (randint (100) < 25) strcat (buf, "man");
else if (randint (100) < 33) strcat (buf, "master");
else if (randint (100) < 50) strcat (buf, "ster");
else strcat (buf, "meister");
return (s=buf);
}
/****************************************************************
* vowelp: Return true is something is a vowel
****************************************************************/
vowelp (ch)
int ch;
{
return (index ("aeiouAEIOU", ch));
}
/****************************************************************
* is_question: true if string is a question
****************************************************************/
is_question (lcmsg)
register char *lcmsg;
{
if (!lcmsg || !*lcmsg) return (0);
if (strfoldeq (car (lcmsg), myname))
{ lcmsg = cdr (lcmsg); }
if (!lcmsg || !*lcmsg) return (0);
if (stlmatch (lcmsg, "are you ") ||
stlmatch (lcmsg, "can you ") ||
stlmatch (lcmsg, "will you ") ||
stlmatch (lcmsg, "would you ") ||
sindex (lcmsg, "what ") ||
sindex (lcmsg, "who ") ||
sindex (lcmsg, "when ") ||
sindex (lcmsg, "where ") ||
sindex (lcmsg, "why ") ||
sindex (lcmsg, "do you "))
{ return (1); }
return (0);
}
/****************************************************************
* is_negative: true if string is a negative reply
****************************************************************/
is_negative (lcmsg)
register char *lcmsg;
{ register char *s, *word;
if (!lcmsg || !*lcmsg) return (0);
for (s=lcmsg; s && *s; s = cdr (s))
{ word = car (s);
if (streq (word, "no") ||
streq (word, "nope") ||
streq (word, "negat") ||
streq (word, "not") ||
streq (word, "negative") ||
streq (word, "never") ||
streq (word, "don't"))
{ return (1); }
}
return (0);
}
/****************************************************************
* is_affirm: true if string is an affirmative reply
****************************************************************/
is_affirm (lcmsg)
register char *lcmsg;
{ register char *s, *word;
if (!lcmsg || !*lcmsg) return (0);
if (is_negative (lcmsg)) return (0);
if (sindex (lcmsg, "sure do") ||
sindex (lcmsg, "you bet") ||
sindex (lcmsg, "affirm") ||
sindex (lcmsg, "i think so") ||
sindex (lcmsg, "i believe so")) return (1);
for (s=lcmsg; s && *s; s = cdr (s))
{ word = car (s);
if (streq (word, "yeah") ||
streq (word, "yup") ||
streq (word, "yes") ||
streq (word, "yep") ||
streq (word, "certainly") ||
streq (word, "definitely") ||
streq (word, "ok"))
{ return (1); }
}
return (0);
}
/****************************************************************
* round_number: round a long integer the way a person might
****************************************************************/
# define round_to(R,N) ((R) * (((N)+((R)/2)) / (R)))
long round_number (n)
{
if (n < 10) return (n);
else if (n < 20) return (round_to (2, n));
else if (n < 50) return (round_to (5, n));
else if (n < 100) return (round_to (10, n));
else if (n < 200) return (round_to (20, n));
else if (n < 500) return (round_to (50, n));
else if (n < 1000) return (round_to (100, n));
else if (n < 2000) return (round_to (200, n));
else if (n < 5000) return (round_to (500, n));
else return (round_to (1000, n));
}
/****************************************************************
* time_dur:
****************************************************************/
# define OCT1989 623303940
char *time_dur (dur)
long dur;
{ long cnt = dur, yr = 0, rm = 0;
char *units = "seconds", *s;
char ybuf[SMABUF], dbuf[SMABUF];
static char buf[2*SMABUF];
if (!contest_mode && ((now-dur) < OCT1989))
{ strcpy (buf, "a long time");
return (s = buf);
}
if (dur > (365 * DAYS + 20952))
{ yr = dur / (365 * DAYS + 20952); /* Years */
dur -= yr * (365 * DAYS + 20952); /* Portion of a year */
}
/* For small amounts of time */
if (dur < 3) sprintf (buf, "an instant");
else if (dur < 10) sprintf (buf, "a few seconds");
else if (dur < 45) sprintf (buf, "less than a minute");
else if (dur < 75) sprintf (buf, "a minute");
else if (dur < 100) sprintf (buf, "a minute and a half");
else if (dur < 110) sprintf (buf, "a minute or two");
else if (dur < 135) sprintf (buf, "a couple of minutes");
else if (dur < 165) sprintf (buf, "two and a half minutes");
else if (dur < 200) sprintf (buf, "three minutes");
else if (dur < 500) sprintf (buf, "a few minutes");
else
{ if (dur < 101) { cnt = dur; units = "second"; }
else if (dur < 6001) { cnt = dur/MINUTES; units = "minute"; }
else if (dur < 120000) { cnt = dur/HOURS; units = "hour"; }
else if (dur < 1200000) { cnt = dur/DAYS; units = "day"; }
else if (dur < 13000000) { cnt = dur/(7*DAYS); units = "week"; }
else { cnt = dur/((365/12)*DAYS); units = "month";}
cnt = round_number (cnt);
if (streq (units, "month") && cnt == 12)
{ cnt = 0; yr++; }
/* Figure year string */
if (yr == 0)
{ strcpy (ybuf, ""); }
else
{ sprintf (ybuf, "%d year%s", yr, (yr == 1) ? "" : "s"); }
/* Figure portion of a year string */
if (cnt == 0)
{ strcpy (dbuf, ""); }
else
{ sprintf (dbuf, "%ld %s%s", cnt, units, (cnt == 1) ? "" : "s"); }
/* Combine the two strings */
if (yr == 0 && cnt == 0)
{ sprintf (buf, "an instant"); }
else if (yr > 0 && yr < 5 && cnt > 0)
{ sprintf (buf, "%s and %s", ybuf, dbuf); }
else if (yr > 0)
{ strcpy (buf, ybuf); }
else
{ strcpy (buf, dbuf); }
}
/* Return point to static memory */
return (s = buf);
}
/****************************************************************
* exact_dur:
****************************************************************/
# define OCT1989 623303940
char *exact_dur (dur)
long dur;
{ long cnt = dur, yr = 0, rm = 0;
char *units = "seconds", *s;
char ybuf[SMABUF], dbuf[SMABUF];
static char buf[2*SMABUF];
if ((now-dur) < OCT1989)
{ strcpy (buf, "a long time");
return (s = buf);
}
if (dur > (365 * DAYS + 20952))
{ yr = dur / (365 * DAYS + 20952); /* Years */
dur -= yr * (365 * DAYS + 20952); /* Portion of a year */
}
/* For small amounts of time */
if (dur < 101) { cnt = dur; units = "second"; }
else if (dur < 6001) { cnt = dur/MINUTES; units = "minute"; }
else if (dur < 120000) { cnt = dur/HOURS; units = "hour"; }
else if (dur < 1200000) { cnt = dur/DAYS; units = "day"; }
else if (dur < 13000000) { cnt = dur/(7*DAYS); units = "week"; }
else { cnt = dur/((365/12)*DAYS); units = "month";}
/* Figure year string */
if (yr == 0)
{ strcpy (ybuf, ""); }
else
{ sprintf (ybuf, "%d year%s", yr, (yr == 1) ? "" : "s"); }
/* Figure portion of a year string */
if (cnt == 0)
{ strcpy (dbuf, ""); }
else
{ sprintf (dbuf, "%ld %s%s", cnt, units, (cnt == 1) ? "" : "s"); }
/* Combine the two strings */
if (yr == 0 && cnt == 0) { sprintf (buf, "an instant"); }
else if (yr > 0 && cnt > 0) { sprintf (buf, "%s and %s", ybuf, dbuf); }
else if (yr > 0) { strcpy (buf, ybuf); }
else { strcpy (buf, dbuf); }
/* Return point to static memory */
return (s = buf);
}
/****************************************************************
* lcstr: lower case a string
****************************************************************/
char *lcstr (str)
char *str;
{ register char *s, *t;
static char buf[BIGBUF];
for (s=str, t=buf; *s; )
{ *t++ = isupper (*s) ? tolower (*s++) : *s++; }
*t = '\0';
return (t = buf);
}
/****************************************************************
* strfoldeq: True if two strings are the same except for case
****************************************************************/
# define fold_lower(C) (isupper (C) ? tolower (C) : (C))
strfoldeq (a, b)
register char *a, *b;
{
while (*a && *b && fold_lower (*a) == fold_lower (*b)) { a++; b++; }
return (*a == '\0' && *b == '\0');
}
/****************************************************************
* timeofday: Return 'morning', 'afternoon' or 'evening'
****************************************************************/
char *timeofday (lunch)
int lunch;
{ struct tm *t, *localtime();
now = time (0);
t = localtime (&now);
if (lunch && t->tm_hour > 11 && t->tm_hour < 13) return ("lunch");
else if (t->tm_hour < 12) return ("morning");
else if (t->tm_hour < 18) return ("afternoon");
else return ("evening");
}
/****************************************************************
* numberval: Return numeric value, or -1e9 for non-number
****************************************************************/
# define NONUMBER (1e9)
long numberval (str)
char *str;
{ long atol (), sign;
char *s;
if (isdigit (*str)) return (atol (str));
if (*str == '-' && isdigit (str[1])) return (- atol (str+1));
if (stlmatch (str, "negative ")) { sign = -1; s = str + 9; }
else { sign = 1; s = str; }
if (strfoldeq (s, "zero")) return (sign * 0);
if (strfoldeq (s, "one")) return (sign * 1);
if (strfoldeq (s, "two")) return (sign * 2);
if (strfoldeq (s, "three")) return (sign * 3);
if (strfoldeq (s, "four")) return (sign * 4);
if (strfoldeq (s, "five")) return (sign * 5);
if (strfoldeq (s, "six")) return (sign * 6);
if (strfoldeq (s, "seven")) return (sign * 7);
if (strfoldeq (s, "eight")) return (sign * 8);
if (strfoldeq (s, "nine")) return (sign * 9);
if (strfoldeq (s, "ten")) return (sign * 10);
if (strfoldeq (s, "eleven")) return (sign * 11);
if (strfoldeq (s, "twelve")) return (sign * 12);
if (strfoldeq (s, "thirteen")) return (sign * 13);
if (strfoldeq (s, "fourteen")) return (sign * 14);
if (strfoldeq (s, "fifteen")) return (sign * 15);
if (strfoldeq (s, "sixteen")) return (sign * 16);
if (strfoldeq (s, "seventeen")) return (sign * 17);
if (strfoldeq (s, "eighteen")) return (sign * 18);
if (strfoldeq (s, "nineteen")) return (sign * 19);
if (strfoldeq (s, "twenty")) return (sign * 20);
return (sign * NONUMBER);
}
isnumber (str)
char *str;
{ return (numberval (str) != NONUMBER); }
is_male_fn (str)
char *str;
{ register char **fn, *nm;
/* Check for explicit male name */
for (fn = male_fn; *fn; fn++)
{ if (streq (str, *fn))
{ return (1); }
}
return (0);
}
is_female_fn (str)
char *str;
{ register char **fn, *nm;
/* Check for explicit female name */
for (fn = female_fn; *fn; fn++)
{ if (streq (str, *fn))
{ return (1); }
}
return (0);
}
is_both_fn (str)
char *str;
{ register char **fn, *nm;
/* Check for explicit both name */
for (fn = both_fn; *fn; fn++)
{ if (streq (str, *fn))
{ return (1); }
}
return (0);
}
/****************************************************************
* is_hearts: True if message is a hearts input command
****************************************************************/
is_hearts (lcmsg)
char *lcmsg;
{
if (stlmatch (lcmsg, "drynn") ||
streq (lcmsg, "illume") ||
streq (lcmsg, "xrka") ||
streq (lcmsg, "mei") ||
streq (lcmsg, "plei") ||
stlmatch (lcmsg, "nou'hou") ||
stlmatch (lcmsg, "westray") ||
stlmatch (lcmsg, "kirkard") ||
stlmatch (lcmsg, "werplei") ||
stlmatch (lcmsg, "auswahl") ||
(index ("23456789jqka", lcmsg[0]) && index ("cdhs", lcmsg[1])) ||
(lcmsg[0] == '1' && lcmsg[1] == '0' && index ("cdhs", lcmsg[2])))
{ return (1); }
return (0);
}
/****************************************************************
* malstr: Allocate a string and initialize it to a value
****************************************************************/
char *malstr (str)
char *str;
{ register char *s;
if ((s = (char *) malloc (strlen (str) + 1)) == NULL)
{ perror ("in malstr"); exit (1); }
strcpy (s, str);
return (s);
}