/* -*-c,save-*- */ /* * rstory.c - random story generator * Robert Heller. Created: Sun Feb 23, 1986 15:50:57.96 * Last Mod: * * (c) Copyright 1986 by Robert Heller * All Rights Reserved * * */ #include #include "patdef.h" #define LOCAL static /* #define DEBUG /* debugging hacks */ /* #define ROFF4_STRIDE /* for roff4 hacks (output reformatting) */ #ifdef DEBUG #define LOCAL /* static */ #endif #define CHAR_RV 0 #define PET_RV 1 #define BAR_RV 2 #define LAST_RV 3 #define SUBJ_RV 4 #define VERB_RV 5 #define LIST_RV 6 LOCAL PATTERN_NODE *BB,*SB,*ph1,*ph2,*ph3,*ph4,*pat1,*pat2,*pat3,*wont,*comma; typedef struct { char *synname; char *synval; } SYNVAR; SYNVAR *rsen_lkp(); LOCAL STRING_DESCR SUBJ_VB,OBJS,VAR,OBJ,SUBJ,VERB; LOCAL char objs[4096],var[256]; LOCAL char temp[4096],obj[256]; ARG_DESCR *acons(); char *malloc(),*calloc(),*index(),*fgets(),*g_rsentv(); FILE *fopen(); SYNVAR *rsen_lkp(); #define MAXACT 256 LOCAL SYNVAR actions[MAXACT]; LOCAL int act_cnt = 0; LOCAL char rstory[30000]; main() { register FILE *actfile; char actline[256]; STRING_DESCR matched; register SYNVAR *rentry; register char *sv,*o,*last,*subj,*verb,*list; register int len,try; SYNVAR *act_lkp(); srand(gettime()); rsent_init("RSTORY.SYN"); BB = breakk_c(" \t"); SB = span_c(" \t"); pat1 = cassign(BB,acons(STRING,&SUBJ)); pat1 = concat(pat1,SB); pat1 = concat(pat1,cassign(REM,acons(STRING,&VERB))); pat2 = concat(c_lit_string(" "), concat(lit_string(&SUBJ),c_lit_string(" "))); pat3 = concat(c_lit_string(" "), concat(lit_string(&VERB),c_lit_string(" "))); wont = c_lit_string("won't"); comma = c_lit_string(","); ph1 = concat(BB,SB); ph1 = concat(ph1,BB); ph1 = cassign(ph1,acons(STRING,&SUBJ_VB)); ph1 = concat(ph1,SB); ph1 = concat(ph1,cassign(REM,acons(STRING,&OBJS))); ph2 = cassign(breakk_c(">"),acons(STRING,&VAR)); ph2 = concat(ph2,c_lit_string(">")); ph2 = concat(c_lit_string("<"),ph2); ph2 = concat(pos(0),ph2); ph3 = concat(pos(0),c_lit_string("|")); ph4 = concat(cassign(breakk_c("|"),acons(STRING,&OBJ)),c_lit_string("|")); actfile = fopen("RSTORY.ACT","r"); if (actfile == NULL) { perror("rstory (fopen(actions))"); abort(0); } for (;;) { if (fgets(actline,256,actfile) == NULL) break; trim(actline); #ifdef DEBUG printf("***actline = %s\n",actline); #endif if (strcmp(actline,"END") == 0) break; pmatch(actline,ph1,&matched); strncpy(objs,OBJS.base+OBJS.offset,OBJS.length); objs[OBJS.length] = '|'; objs[OBJS.length+1] = '\0'; for (;;) { #ifdef DEBUG printf("***objs = %s\n",objs); #endif if (pmatch(objs,ph2,&matched) == MATCH_SUCCESS) { strncpy(var,VAR.base+VAR.offset,VAR.length); var[VAR.length] = '\0'; rentry = rsen_lkp(var); if (rentry == NULL) strcpy(objs,objs+matched.length); else { strcpy(temp,rentry->synval); strcat(temp,objs+matched.length); strcpy(objs,temp); } } if (pmatch(objs,ph3,&matched) == MATCH_SUCCESS) { strcpy(objs,objs+1); continue; } if (pmatch(objs,ph4,&matched) != MATCH_SUCCESS) break; strncpy(obj,OBJ.base+OBJ.offset,OBJ.length); obj[OBJ.length] = '\0'; strcpy(objs,objs+matched.length); rentry = act_lkp(obj); if (rentry == NULL) { sv = malloc(SUBJ_VB.length+2); strncpy(sv+1,SUBJ_VB.base+SUBJ_VB.offset,SUBJ_VB.length); *sv = '|'; sv[SUBJ_VB.length+1] = '\0'; o = malloc(OBJ.length+1); strcpy(o,obj); act_ins(o,sv); } else { sv = malloc(strlen(rentry->synval)+SUBJ_VB.length+2); strcpy(sv,rentry->synval); strcat(sv,"|"); strncat(sv,SUBJ_VB.base+SUBJ_VB.offset,SUBJ_VB.length); sv[SUBJ_VB.length+strlen(rentry->synval)+1] = '\0'; free(rentry->synval); rentry->synval = sv; } } } rsentence("",rstory); o = g_rsentv(PET_RV); sv = g_rsentv(BAR_RV); len = strlen(o) + 2 + strlen(" won't jump over the ") + strlen(sv) + 1; list = malloc(len); strcpy(list," "); strcat(list,o); strcat(list," won't jump over the "); strcat(list,sv); s_rsentv(LIST_RV,list); last = malloc(strlen(o)+1); strcpy(last,o); s_rsentv(LAST_RV,last); while (strlen(list) < 175) { #ifdef DEBUG printf("***list = %s\n***rstory = %s\n",list,rstory); #endif rentry = act_lkp(last); #ifdef DEBUG printf("***rentry->synval = %s\n",rentry->synval); #endif for (try=0;try<10;try++) { rselect(rentry->synval,objs); #ifdef DEBUG printf("***try = %d; objs = %s\n",try,objs); #endif rsentence(objs,temp); #ifdef DEBUG printf("***temp = %s\n",temp); len = #endif pmatch(temp,pat1,&matched); #ifdef DEBUG printf("***pat1 match status %d\n",len); #endif if (pmatch(rstory,pat2,&matched) == MATCH_SUCCESS) continue; else if (pmatch(rstory,pat3,&matched) == MATCH_SUCCESS) continue; else break; } subj = g_rsentv(SUBJ_RV); verb = g_rsentv(VERB_RV); if (subj == NULL) { subj = malloc(SUBJ.length+1); strncpy(subj,SUBJ.base+SUBJ.offset,SUBJ.length); subj[SUBJ.length] = '\0'; s_rsentv(SUBJ_RV,subj); } else if (strlen(subj) > SUBJ.length) { strncpy(subj,SUBJ.base+SUBJ.offset,SUBJ.length); subj[SUBJ.length] = '\0'; } else { free(subj); subj = malloc(SUBJ.length+1); strncpy(subj,SUBJ.base+SUBJ.offset,SUBJ.length); subj[SUBJ.length] = '\0'; s_rsentv(SUBJ_RV,subj); } if (verb == NULL) { verb = malloc(VERB.length+1); strncpy(verb,VERB.base+VERB.offset,VERB.length); verb[VERB.length] = '\0'; s_rsentv(VERB_RV,verb); } else if (strlen(verb) > VERB.length) { strncpy(verb,VERB.base+VERB.offset,VERB.length); verb[VERB.length] = '\0'; } else { free(verb); verb = malloc(VERB.length+1); strncpy(verb,VERB.base+VERB.offset,VERB.length); verb[VERB.length] = '\0'; s_rsentv(VERB_RV,verb); } rsentence("",temp); strcat(rstory,temp); len = strlen(list) + 1 + SUBJ.length + 7 + VERB.length + 5 + strlen(last) + 2 + 1; o = malloc(len); strcpy(o," "); strcat(o,subj); strcat(o," won't "); strcat(o,verb); strcat(o," the "); strcat(o,last); strcat(o,", "); strcat(o,list); free(list); list = o; s_rsentv(LIST_RV,list); free(last); last = malloc(strlen(subj)+1); strcpy(last,subj); s_rsentv(LAST_RV,last); } strcpy(temp,list); free(list); while (pmatch(temp,wont,&matched) == MATCH_SUCCESS) { strncpy(objs,temp,matched.offset); strcpy(objs+matched.offset,"began to"); strcat(objs,temp+matched.offset+matched.length); strcpy(temp,objs); } while (pmatch(temp,comma,&matched) == MATCH_SUCCESS) { strncpy(objs,temp,matched.offset); strcpy(objs+matched.offset,"; the"); strcat(objs,temp+matched.offset+matched.length); strcpy(temp,objs); } s_rsentv(LIST_RV,temp); rsentence("",objs); strcat(rstory,objs); #ifdef ROFF4_STRIDE printf(".ow 80\n"); printf(".rm 70\n"); printf(".in 10\n"); printf(".sa Type in your name\n"); printf("..\\name\\\n"); printf(".ce 2\n"); printf("^BA Story for \\name\\\n"); printf("Generated on \\date\\ by a Stride 440^b\n"); printf(".sp 4\n"); printf(".ti +5\n"); #endif len = 0; o = rstory; while (*o != '\0') { if (*o == ' ' && len > 50) { putchar('\n'); while (*o == ' ') o++; len = 0; } putchar(*o); len++; o++; } printf("\n\n"); } SYNVAR *act_lkp(synn) register char *synn; { register first,last,indx,cmp; first = 0; last = act_cnt; while (first < last) { indx = ((last - first) >> 1) + first; cmp = strcmp(synn,actions[indx].synname); if (cmp == 0) return(&actions[indx]); else if (cmp < 0) last = indx; else first = indx+1; } return(NULL); } act_ins(name,val) register char *name,*val; { int syncmp(); actions[act_cnt].synname = name; actions[act_cnt].synval = val; act_cnt++; qsort(actions,act_cnt,sizeof(SYNVAR),syncmp); }