/**************************************************************** * 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); }