From mipos3!omepd!littlei!uunet!tektronix!tekgen!tekred!games-request Sun Oct 25 10:00:08 PST 1987 Article 105 of comp.sources.games: Path: td2cad!mipos3!omepd!littlei!uunet!tektronix!tekgen!tekred!games-request From: games-request@tekred.TEK.COM Newsgroups: comp.sources.games Subject: v02i057: advsys - adventure writing system, Part03/03 Message-ID: <1733@tekred.TEK.COM> Date: 23 Oct 87 23:27:29 GMT Sender: billr@tekred.TEK.COM Lines: 2040 Approved: billr@tekred.TEK.COM Submitted by: Marc Russell Pawliger Comp.sources.games: Volume 2, Issue 57 Archive-name: advsys/Part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh Makefile <<'END_OF_Makefile' X #Makefile for adventure system XCC=cc XCFLAGS=-g XADVLIB=/cmu/misc/cl0x/lib/adventure X Xadvcom: advcom.h advavl.h advcom.o advfcn.o\ X advscn.o advexp.o advavl.o advfio.o X ${CC} -o advcom advcom.o advfcn.o advscn.o advexp.o\ X advavl.o advfio.o X Xadvint: advint.h advmsg.o advtrm.o advprs.o\ X advdbs.o advint.o advjunk.o advexe.o X ${CC} -o advint advmsg.o advtrm.o advprs.o\ X advdbs.o advint.o advjunk.o advexe.o X Xsample: osample.adv objects.adi X advcom osample X Xall: advcom advint install X Xinstall: advcom advint X $(INSTALL) advcom advint $(DESTDIR) X $(INSTALL) ../osample.adv ../objects.adi $(ADVLIB) X END_OF_Makefile if test 602 -ne `wc -c README2 <<'END_OF_README2' XThe file 'newadv.pch' contains a set of diffs to add smart articles Xto the adventure compiler system. They are being distributed in Xthis way because David Betz (the original author) wants his source Xdistributed *only* in unmodified form. If you make changes or Xadditions to the source, please distribute them as diffs rather Xthan modified files (or at least include the original source) when Xgiving it to your friends. X X -Bill Randle X Moderator, comp.sources.games X Tektronix, Inc. X games-request@tekred.TEK.COM END_OF_README2 if test 514 -ne `wc -c advavl.c <<'END_OF_advavl.c' X X/* advavl.c - avl tree manipulation routines */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X X#include "advavl.h" X#include "advdbs.h" X X#define TRUE 1 X#define FALSE 0 X#define NULL 0 X X/* external routines */ Xextern char *save(); Xextern char *malloc(); X X/* external variables */ Xextern char *data; Xextern int curwrd; Xextern int dptr; X X/* local variables */ Xstatic TREE *curtree; Xstatic char thiskey[WRDSIZE+1]; X X/* tnew - allocate a new avl tree */ XTREE *tnew() X{ X TREE *tree; X X /* allocate the tree structure */ X if ((tree = (TREE *)malloc(sizeof(TREE))) == NULL) X return (NULL); X X /* initialize the new tree */ X tree->tr_root = NULL; X tree->tr_cnt = 0; X X /* return the new tree */ X return (tree); X} X X/* tenter - add an entry to an avl tree */ Xint tenter(tree,key) X TREE *tree; char *key; X{ X int h; X curtree = tree; X strncpy(thiskey,key,WRDSIZE); thiskey[WRDSIZE] = 0; X return (tenter1(&tree->tr_root,&h)); X} X X/* tenter1 - internal insertion routine */ Xint tenter1(pnode,ph) X TNODE **pnode; int *ph; X{ X TNODE *p,*q,*r; X int val,c; X X /* check for the subtree being empty */ X if ((p = *pnode) == NULL) { X if (p = (TNODE *)malloc(sizeof(TNODE))) { X curtree->tr_cnt++; X KEY(p) = save(thiskey); X WORD(p) = curwrd; X LLINK(p) = RLINK(p) = NULL; X B(p) = 0; X *pnode = p; X *ph = TRUE; X return (WORD(p)); X } X else { X *ph = FALSE; X return (NIL); X } X } X X /* otherwise, check for a match at this node */ X else if ((c = strcmp(thiskey,KEY(p))) == 0) { X *ph = FALSE; X return (WORD(p)); X } X X /* otherwise, check the left subtree */ X else if (c < 0) { X val = tenter1(&LLINK(p),ph); X if (*ph) X switch (B(p)) { X case 1: X B(p) = 0; X *ph = FALSE; X break; X case 0: X B(p) = -1; X break; X case -1: X q = LLINK(p); X if (B(q) == -1) { X LLINK(p) = RLINK(q); X RLINK(q) = p; X B(p) = 0; X p = q; X } X else { X r = RLINK(q); X RLINK(q) = LLINK(r); X LLINK(r) = q; X LLINK(p) = RLINK(r); X RLINK(r) = p; X B(p) = (B(r) == -1 ? 1 : 0); X B(q) = (B(r) == 1 ? -1 : 0); X p = r; X } X B(p) = 0; X *pnode = p; X *ph = FALSE; X break; X } X } X X /* otherwise, check the right subtree */ X else { X val = tenter1(&RLINK(p),ph); X if (*ph) X switch (B(p)) { X case -1: X B(p) = 0; X *ph = FALSE; X break; X case 0: X B(p) = 1; X break; X case 1: X q = RLINK(p); X if (B(q) == 1) { X RLINK(p) = LLINK(q); X LLINK(q) = p; X B(p) = 0; X p = q; X } X else { X r = LLINK(q); X LLINK(q) = RLINK(r); X RLINK(r) = q; X RLINK(p) = LLINK(r); X LLINK(r) = p; X B(p) = (B(r) == 1 ? -1 : 0); X B(q) = (B(r) == -1 ? 1 : 0); X p = r; X } X B(p) = 0; X *pnode = p; X *ph = FALSE; X break; X } X } X X /* return the node found or inserted */ X return (val); X} X X/* tfind - find an entry in an avl tree */ Xint tfind(tree,key) X TREE *tree; char *key; X{ X strncpy(thiskey,key,WRDSIZE); thiskey[WRDSIZE] = 0; X return (tfind1(tree->tr_root)); X} X X/* tfind1 - internal lookup routine */ Xint tfind1(node) X TNODE *node; X{ X int c; X X /* check for the subtree being empty */ X if (node == NULL) X return (NIL); X X /* otherwise, check for a match at this node */ X else if ((c = strcmp(thiskey,KEY(node))) == 0) X return (WORD(node)); X X /* otherwise, check the left subtree */ X else if (c < 0) X return (tfind1(LLINK(node))); X X /* otherwise, check the right subtree */ X else X return (tfind1(RLINK(node))); X} END_OF_advavl.c if test 3548 -ne `wc -c advavl.h <<'END_OF_advavl.h' X/* avl.h - avl tree definitions */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X Xtypedef struct tree { X struct tnode *tr_root; /* root node */ X int tr_cnt; /* count of entries */ X} TREE; X Xtypedef struct tnode { X int tn_b; /* balance flag */ X struct tnode *tn_llink; /* left subtree */ X struct tnode *tn_rlink; /* right subtree */ X char *tn_key; /* word */ X int tn_word; /* word number */ X} TNODE; X X#define LLINK(n) ((n)->tn_llink) X#define RLINK(n) ((n)->tn_rlink) X#define KEY(n) ((n)->tn_key) X#define WORD(n) ((n)->tn_word) X#define B(n) ((n)->tn_b) X#define tentries(t) ((t)->tr_cnt) END_OF_advavl.h if test 638 -ne `wc -c advcom.h <<'END_OF_advcom.h' X X/* advcom.h - adventure compiler definitions */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X X#include X#include X X/* limits */ X#define TKNSIZE 50 /* maximum token size */ X#define OSIZE 104 /* maximum object size (O_SIZE/2 + OPMAX*2) */ X#define OPMAX 50 /* maximum # properties/object */ X#define WMAX 500 /* maximum number of words */ X#define OMAX 500 /* maximum number of objects */ X#define AMAX 200 /* maximum number of actions */ X#define DMAX 16384 /* maximum data space */ X#define CMAX 16384 /* maximum code space */ X#define FMAX 20 /* file name maximum */ X X/* useful definitions */ X#define TRUE 1 X#define FALSE 0 X#define EOS '\0' X X/* token definitions */ X#define T_OPEN 1 X#define T_CLOSE 2 X#define T_STRING 3 X#define T_IDENTIFIER 4 X#define T_NUMBER 5 X#define T_EOF 6 X X/* symbol types */ X#define ST_OBJECT 1 X#define ST_ACTION 2 X#define ST_VARIABLE 3 X#define ST_CONSTANT 4 X#define ST_PROPERTY 5 X X/* symbol structure */ Xtypedef struct symbol { X char *s_name; /* symbol name */ X int s_type; /* symbol type */ X int s_value; /* symbol value */ X struct symbol *s_next; /* next symbol in table */ X} SYMBOL; X X/* function argument structure */ Xtypedef struct argument { X char *arg_name; /* argument name */ X struct argument *arg_next; /* next argument */ X} ARGUMENT; X END_OF_advcom.h if test 1345 -ne `wc -c advdbs.h <<'END_OF_advdbs.h' X/* advdbs.h - adventure database definitions */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X X/* useful constants */ X#define T -1 X#define NIL 0 X#define WRDSIZE 6 X X/* data structure version number */ X#define VERSION 102 X X/* file header offsets */ X#define HDR_LENGTH 0 /* length of header in bytes */ X#define HDR_MAGIC 2 /* magic information (6 bytes) */ X#define HDR_VERSION 8 /* data structure version number */ X#define HDR_ANAME 10 /* adventure name (18 bytes) */ X#define HDR_AVERSION 28 /* adventure version number */ X#define HDR_WTABLE 30 /* offset to word table */ X#define HDR_WTYPES 32 /* offset to word type table */ X#define HDR_OTABLE 34 /* offset to object table */ X#define HDR_ATABLE 36 /* offset to action table */ X#define HDR_VTABLE 38 /* offset to variable table */ X#define HDR_DBASE 40 /* offset to base of data space */ X#define HDR_CBASE 42 /* offset to base of code space */ X#define HDR_DATBLK 44 /* first data block */ X#define HDR_MSGBLK 46 /* first message text block */ X#define HDR_INIT 48 /* initialization code */ X#define HDR_UPDATE 50 /* update code */ X#define HDR_BEFORE 52 /* code to execute before verb handler */ X#define HDR_AFTER 54 /* code to execute after verb handler */ X#define HDR_ERROR 56 /* error handler code */ X#define HDR_SAVE 58 /* save area offset */ X#define HDR_SLEN 60 /* save area length */ X#define HDR_SIZE 62 /* size of header */ X X/* word types */ X#define WT_UNKNOWN 0 X#define WT_VERB 1 X#define WT_NOUN 2 X#define WT_ADJECTIVE 3 X#define WT_PREPOSITION 4 X#define WT_CONJUNCTION 5 X#define WT_ARTICLE 6 X X/* object fields */ X#define O_CLASS 0 X#define O_NOUNS 2 X#define O_ADJECTIVES 4 X#define O_NPROPERTIES 6 X#define O_PROPERTIES 8 X#define O_SIZE 8 X X/* action fields */ X#define A_VERBS 0 X#define A_PREPOSITIONS 2 X#define A_FLAG 4 X#define A_MASK 5 X#define A_CODE 6 X#define A_SIZE 8 X X/* link fields */ X#define L_DATA 0 X#define L_NEXT 2 X#define L_SIZE 4 X X/* property flags */ X#define P_CLASS 0x8000 /* class property */ X X/* action flags */ X#define A_ACTOR 0x01 /* actor */ X#define A_DOBJECT 0x02 /* direct object */ X#define A_IOBJECT 0x04 /* indirect object */ X X/* opcodes */ X#define OP_BRT 0x01 /* branch on true */ X#define OP_BRF 0x02 /* branch on false */ X#define OP_BR 0x03 /* branch unconditionally */ X#define OP_T 0x04 /* load top of stack with t */ X#define OP_NIL 0x05 /* load top of stack with nil */ X#define OP_PUSH 0x06 /* push nil onto stack */ X#define OP_NOT 0x07 /* logical negate top of stack */ X#define OP_ADD 0x08 /* add two numeric expressions */ X#define OP_SUB 0x09 /* subtract two numeric expressions */ X#define OP_MUL 0x0A /* multiply two numeric expressions */ X#define OP_DIV 0x0B /* divide two numeric expressions */ X#define OP_REM 0x0C /* remainder of two numeric expressions */ X#define OP_BAND 0x0D /* bitwise and of two numeric expressions */ X#define OP_BOR 0x0E /* bitwise or of two numeric expressions */ X#define OP_BNOT 0x0F /* bitwise not of two numeric expressions */ X#define OP_LT 0x10 /* less than */ X#define OP_EQ 0x11 /* equal to */ X#define OP_GT 0x12 /* greater than */ X#define OP_LIT 0x13 /* load literal */ X#define OP_VAR 0x14 /* load a variable value */ X#define OP_GETP 0x15 /* get the value of an object property */ X#define OP_SETP 0x16 /* set the value of an object property */ X#define OP_SET 0x17 /* set the value of a variable */ X#define OP_PRINT 0x18 /* print messages */ X#define OP_TERPRI 0x19 /* terminate the print line */ X#define OP_PNUMBER 0x1A /* print a number */ X#define OP_FINISH 0x1B /* finish handling this command */ X#define OP_CHAIN 0x1C /* chain to the next handler */ X#define OP_ABORT 0x1D /* abort this command */ X#define OP_EXIT 0x1E /* exit the program */ X#define OP_RETURN 0x1F /* return from interpreter */ X#define OP_CALL 0x20 /* call a function */ X#define OP_SVAR 0x21 /* short load a variable */ X#define OP_SSET 0x22 /* short set a variable */ X#define OP_SPLIT 0x23 /* short load a positive literal */ X#define OP_SNLIT 0x24 /* short load a negative literal */ X#define OP_YORN 0x25 /* yes-or-no predicate */ X#define OP_SAVE 0x26 /* save data structures */ X#define OP_RESTORE 0x27 /* restore data structures */ X#define OP_ARG 0x28 /* load an argument value */ X#define OP_ASET 0x29 /* set an argument value */ X#define OP_TMP 0x2A /* load a temporary variable value */ X#define OP_TSET 0x2B /* set a temporary variable */ X#define OP_TSPACE 0x2C /* allocate temporary variable space */ X#define OP_CLASS 0x2D /* get the class of an object */ X#define OP_MATCH 0x2E /* match a noun phrase with an object */ X#define OP_PNOUN 0x2F /* print a noun phrase */ X#define OP_RESTART 0x30 /* restart the current game */ X#define OP_RAND 0x31 /* generate a random number */ X#define OP_RNDMIZE 0x32 /* seed the random number generator */ X#define OP_SEND 0x33 /* send a message to an object */ X#define OP_VOWEL 0x34 /* check for vowel beginning string */ X X#define OP_XVAR 0x40 /* extra short load a variable */ X#define OP_XSET 0x60 /* extra short set a variable */ X#define OP_XPLIT 0x80 /* extra short load a positive literal */ X#define OP_XNLIT 0xC0 /* extra short load a negative literal */ X X/* builtin variables */ X#define V_ACTOR 1 /* actor noun phrase number */ X#define V_ACTION 2 /* action from parse */ X#define V_DOBJECT 3 /* first direct object noun phrase number */ X#define V_NDOBJECTS 4 /* number of direct object noun phrases */ X#define V_IOBJECT 5 /* indirect object noun phrase number */ X#define V_OCOUNT 6 /* total object count */ X END_OF_advdbs.h if test 5502 -ne `wc -c advexe.c <<'END_OF_advexe.c' X X/* advexe.c - adventure code executer */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X X#include "advint.h" X#include "advdbs.h" X X/* external variables */ Xextern char line[]; Xextern int nouns[],*adjectives[]; X X/* local variables */ Xint pc,opcode,p2,p3,sts; Xint stack[STKSIZE],*sp,*fp,*top; Xlong rseed = 1L; X X/* external routines */ Xextern long time(); X X/* execute - execute adventure code */ Xint execute(code) X int code; X{ X /* setup initial program counter */ X if ((pc = code) == NIL) X return (CHAIN); X X /* initialize */ X sp = fp = top = stack + STKSIZE; X X /* execute the code */ X for (sts = 0; sts == 0; ) X exe_one(); X X return (sts); X} X X/* exe_one - execute one instruction */ Xexe_one() X{ X /* get the opcode */ X opcode = getcbyte(pc); pc++; X X /* execute the instruction */ X switch (opcode) { X case OP_CALL: X *--sp = getboperand(); X *--sp = pc; X *--sp = (int)(top - fp); X fp = sp; X pc = getafield(fp[fp[2]+3],A_CODE); X break; X case OP_SEND: X *--sp = getboperand(); X *--sp = pc; X *--sp = (int)(top - fp); X fp = sp; X if (p2 = fp[fp[2]+3]) X p2 = getofield(p2,O_CLASS); X else X p2 = fp[fp[2]+2]; X if (p2 && (p2 = getp(p2,fp[fp[2]+1]))) { X pc = getafield(p2,A_CODE); X break; X } X *sp = NIL; X /* return NIL if there is no method for this message */ X case OP_RETURN: X if (fp == top) X sts = CHAIN; X else { X p2 = *sp; X sp = fp; X fp = top - *sp++; X pc = *sp++; X p3 = *sp++; X sp += p3; X *sp = p2; X } X break; X case OP_TSPACE: X sp -= getboperand(); X break; X case OP_TMP: X p2 = getboperand(); X *sp = fp[-p2-1]; X break; X case OP_TSET: X p2 = getboperand(); X fp[-p2-1] = *sp; X break; X case OP_ARG: X p2 = getboperand(); X if (p2 >= fp[2]) X error("too few arguments"); X *sp = fp[p2+3]; X break; X case OP_ASET: X p2 = getboperand(); X if (p2 >= fp[2]) X error("too few arguments"); X fp[p2+3] = *sp; X break; X case OP_BRT: X pc = (*sp ? getwoperand() : pc+2); X break; X case OP_BRF: X pc = (*sp ? pc+2 : getwoperand()); X break; X case OP_BR: X pc = getwoperand(); X break; X case OP_T: X *sp = T; X break; X case OP_NIL: X *sp = NIL; X break; X case OP_PUSH: X *--sp = NIL; X break; X case OP_NOT: X *sp = (*sp ? NIL : T); X break; X case OP_ADD: X p2 = *sp++; X *sp += p2; X break; X case OP_SUB: X p2 = *sp++; X *sp -= p2; X break; X case OP_MUL: X p2 = *sp++; X *sp *= p2; X break; X case OP_DIV: X p2 = *sp++; X *sp = (p2 == 0 ? 0 : *sp / p2); X break; X case OP_REM: X p2 = *sp++; X *sp = (p2 == 0 ? 0 : *sp % p2); X break; X case OP_BAND: X p2 = *sp++; X *sp &= p2; X break; X case OP_BOR: X p2 = *sp++; X *sp |= p2; X break; X case OP_BNOT: X *sp = ~*sp; X break; X case OP_LT: X p2 = *sp++; X *sp = (*sp < p2 ? T : NIL); X break; X case OP_EQ: X p2 = *sp++; X *sp = (*sp == p2 ? T : NIL); X break; X case OP_GT: X p2 = *sp++; X *sp = (*sp > p2 ? T : NIL); X break; X case OP_LIT: X *sp = getwoperand(); X break; X case OP_SPLIT: X *sp = getboperand(); X break; X case OP_SNLIT: X *sp = -getboperand(); X break; X case OP_VAR: X *sp = getvalue(getwoperand()); X break; X case OP_SVAR: X *sp = getvalue(getboperand()); X break; X case OP_SET: X setvalue(getwoperand(),*sp); X break; X case OP_SSET: X setvalue(getboperand(),*sp); X break; X case OP_GETP: X p2 = *sp++; X *sp = getp(*sp,p2); X break; X case OP_SETP: X p3 = *sp++; X p2 = *sp++; X *sp = setp(*sp,p2,p3); X break; X case OP_PRINT: X print(*sp); X break; X case OP_PNUMBER: X pnumber(*sp); X break; X case OP_PNOUN: X show_noun(*sp); X break; X case OP_TERPRI: X trm_chr('\n'); X break; X case OP_FINISH: X sts = FINISH; X break; X case OP_CHAIN: X sts = CHAIN; X break; X case OP_ABORT: X sts = ABORT; X break; X case OP_EXIT: X#ifdef MAC X macpause(); X#endif X trm_done(); X exit(); X break; X case OP_YORN: X trm_get(line); X *sp = (line[0] == 'Y' || line[0] == 'y' ? T : NIL); X break; X case OP_CLASS: X *sp = getofield(*sp,O_CLASS); X break; X case OP_MATCH: X p2 = *sp++; X *sp = (match(*sp,nouns[p2-1],adjectives[p2-1]) ? T : NIL); X break; X case OP_SAVE: X *sp = db_save(); X break; X case OP_RESTORE: X *sp = db_restore(); X break; X case OP_RESTART: X *sp = db_restart(); X break; X case OP_RAND: X *sp = getrand(*sp); X break; X case OP_RNDMIZE: X setrand(time(0L)); X *sp = NIL; X break; X default: X if (opcode >= OP_XVAR && opcode < OP_XSET) X *sp = getvalue(opcode - OP_XVAR); X else if (opcode >= OP_XSET && opcode < OP_XPLIT) X setvalue(opcode - OP_XSET,*sp); X else if (opcode >= OP_XPLIT && opcode < OP_XNLIT) X *sp = opcode - OP_XPLIT; X else if (opcode >= OP_XNLIT && opcode < 256) X *sp = OP_XNLIT - opcode; X else X trm_str("Bad opcode\n"); X break; X } X} X X/* getboperand - get data byte */ Xint getboperand() X{ X int data; X data = getcbyte(pc); pc += 1; X return (data); X} X X/* getwoperand - get data word */ Xint getwoperand() X{ X int data; X data = getcword(pc); pc += 2; X return (data); X} X X/* print - print a message */ Xprint(msg) X int msg; X{ X int ch; X X msg_open(msg); X while (ch = msg_byte()) X trm_chr(ch); X} X X/* pnumber - print a number */ Xpnumber(n) X int n; X{ X char buf[10]; X X sprintf(buf,"%d",n); X trm_str(buf); X} X X/* getrand - get a random number between 0 and n-1 */ Xint getrand(n) X int n; X{ X long k1; X X /* make sure we don't get stuck at zero */ X if (rseed == 0L) rseed = 1L; X X /* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */ X k1 = rseed / 127773L; X if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L) X rseed += 2147483647L; X X /* return a random number between 0 and n-1 */ X return ((int)(rseed % (long)n)); X} X X/* setrand - set the random number seed */ Xsetrand(n) X long n; X{ X rseed = n; X} X END_OF_advexe.c if test 5871 -ne `wc -c advfio.c <<'END_OF_advfio.c' X X/* advfio.c - file i/o routines for the adventure compiler */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X X#define BSIZE 8192 X X/* global variables */ Xlong ad_foff; X X/* external routines */ Xextern long lseek(); X X/* local variables */ Xstatic char buf[BSIZE]; Xstatic int boff; Xstatic int fd; X Xad_create(name) X char *name; X{ X /* create the file */ X if ((fd = creat(name,0666)) < 0) X fail("can't create output file"); X X /* initialize the buffer and file offset */ X ad_foff = 0L; X boff = 0; X} X Xad_close() X{ X ad_flush(); X close(fd); X} X Xad_putc(ch) X int ch; X{ X buf[boff++] = ch; ad_foff++; X if (boff >= BSIZE) X ad_flush(); X} X Xad_seek(pos) X long pos; X{ X ad_flush(); X if (lseek(fd,pos,0) != pos) X fail("error positioning output file"); X ad_foff = pos; X} X Xad_flush() X{ X if (boff) { X if (write(fd,buf,boff) != boff) X fail("error writing to output file"); X boff = 0; X } X} END_OF_advfio.c if test 936 -ne `wc -c advint.c <<'END_OF_advint.c' X X/* advint.c - an interpreter for adventure games */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X X#include "advint.h" X#include "advdbs.h" X#ifndef MAC X#include X#endif X X/* global variables */ Xjmp_buf restart; X X/* external variables */ Xextern int h_init; Xextern int h_update; Xextern int h_before; Xextern int h_after; Xextern int h_error; X X/* main - the main routine */ Xmain(argc,argv) X int argc; char *argv[]; X{ X char *fname,*lname; X int rows,cols,i; X X#ifdef MAC X char name[50]; X macinit(name); X fname = name; X lname = NULL; X rows = 20; X cols = 80; X#else X printf("ADVINT v1.2 - Copyright (c) 1986, by David Betz\n"); X fname = NULL; X lname = NULL; X rows = 24; X cols = 80; X X /* parse the command line */ X for (i = 1; i < argc; i++) X if (argv[i][0] == '-') X switch (argv[i][1]) { X case 'r': X case 'R': X rows = atoi(&argv[i][2]); X break; X case 'c': X case 'C': X cols = atoi(&argv[i][2]); X break; X case 'l': X case 'L': X lname = &argv[i][2]; X break; X } X else X fname = argv[i]; X if (fname == NULL) { X printf("usage: advint [-r] [-c] [-l] \n"); X exit(); X } X#endif X X /* initialize terminal i/o */ X trm_init(rows,cols,lname); X X /* initialize the database */ X db_init(fname); X X /* play the game */ X play(); X} X X/* play - the main loop */ Xplay() X{ X /* establish the restart point */ X setjmp(restart); X X /* execute the initialization code */ X execute(h_init); X X /* turn handling loop */ X for (;;) { X X /* execute the update code */ X execute(h_update); X X /* parse the next input command */ X if (parse()) { X if (single()) X while (next() && single()) X ; X } X X /* parse error, call the error handling code */ X else X execute(h_error); X } X} X X/* single - handle a single action */ Xint single() X{ X /* execute the before code */ X switch (execute(h_before)) { X case ABORT: /* before handler aborted sequence */ X return (FALSE); X case CHAIN: /* execute the action handler */ X if (execute(getafield(getvalue(V_ACTION),A_CODE)) == ABORT) X return (FALSE); X case FINISH:/* execute the after code */ X if (execute(h_after) == ABORT) X return (FALSE); X break; X } X return (TRUE); X} X X/* error - print an error message and exit */ Xerror(msg) X char *msg; X{ X trm_str(msg); X trm_chr('\n'); X exit(); X} END_OF_advint.c if test 2437 -ne `wc -c advjunk.c <<'END_OF_advjunk.c' X#define UNIX X#include X Xlong _seed = 1L; X X#ifndef UNIX Xint rand() X{ X _seed *= 397204094L; X return (_seed & 0x7FFF); X} X Xsrand(n) X long n; X{ X _seed = n; X} X#endif X Xint getch() X{ X#ifdef UNIX X return getchar(); X#else X int ch; X if ((ch = bdos(1) & 0xFF) == '\r') { bdos(6,'\n'); ch = '\n'; } X return (ch); X#endif X} X Xwaitch() X{ X#ifndef UNIX X bdos(7); X#endif X} X Xputch(ch,fp) X int ch; FILE *fp; X{ X#ifdef UNIX X putc(ch,fp); X#else X aputc(ch,fp); X#endif X} X Xint advsave(hdr,hlen,save,slen) X char *hdr; int hlen; char *save; int slen; X{ X char fname[50]; X int fd; X X trm_str("File name? "); X trm_get(fname); X X /* add the extension */ X strcat(fname,".sav"); X X /* create the data file */ X if ((fd = creat(fname,0666)) == -1) X return (0); X X /* write the header */ X if (write(fd,hdr,hlen) != hlen) { X close(fd); X return (0); X } X X /* write the data */ X if (write(fd,save,slen) != slen) { X close(fd); X return (0); X } X X /* close the file and return successfully */ X close(fd); X return (1); X} X Xint advrestore(hdr,hlen,save,slen) X char *hdr; int hlen; char *save; int slen; X{ X char fname[50],hbuf[50],*p; X int fd; X X if (hlen > 50) X error("save file header buffer too small"); X X trm_str("File name? "); X trm_get(fname); X X /* add the extension */ X strcat(fname,".sav"); X X /* create the data file */ X if ((fd = open(fname,0)) == -1) X return (0); X X /* read the header */ X if (read(fd,hbuf,hlen) != hlen) { X close(fd); X return (0); X } X X /* compare the headers */ X for (p = hbuf; hlen--; ) X if (*hdr++ != *p++) { X trm_str("This save file does not match the adventure!\n"); X return (0); X } X X /* read the data */ X if (read(fd,save,slen) != slen) { X close(fd); X return (0); X } X X /* close the file and return successfully */ X close(fd); X return (1); X} X X END_OF_advjunk.c if test 1880 -ne `wc -c advmsg.c <<'END_OF_advmsg.c' X X/* advmsg.c - adventure interpreter message routines */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X X#include X X/* cache size */ X#define CSIZE 8 X X/* external routines */ Xextern char *malloc(); X X/* message block cache */ Xstatic char *mbuffer[CSIZE]; /* message text block cache buffers */ Xstatic int mblock[CSIZE]; /* message text block cache block numbers */ Xstatic int mnext[CSIZE]; /* next most recently used block */ Xstatic int mhead,mtail; /* head and tail of lru list */ X X/* message file variables */ Xstatic int mbase; /* message base block */ Xstatic int mfd; /* message file descriptor */ X X/* current message variables */ Xstatic int mblk; /* current block */ Xstatic char *mbuf; /* current buffer */ Xstatic int moff; /* current buffer offset */ X X/* msg_init - initialize the message routines */ Xmsg_init(fd,base) X int fd,base; X{ X char *p; X int i; X X /* remember the message file descriptor and base */ X mbase = base; X mfd = fd; X X /* initialize the cache */ X if ((p = malloc(CSIZE * 512)) == NULL) X error("insufficient memory"); X for (i = 0; i < CSIZE; i++) { X mbuffer[i] = p; p += 512; X mblock[i] = -1; X mnext[i] = i+1; X } X mhead = 0; mtail = CSIZE-1; mnext[mtail] = -1; X} X X/* msg_open - open a message */ Xint msg_open(msg) X unsigned int msg; X{ X /* save the current message block */ X mblk = msg >> 7; X X /* make sure the first block is in a buffer */ X get_block(mblk); X X /* setup the initial offset into the block */ X moff = (msg & 0x7F) << 2; X} X X/* msg_byte - get a byte from a message */ Xint msg_byte() X{ X /* check for end of block and get next block */ X if (moff >= 512) { X get_block(++mblk); X moff = 0; X } X X /* return the next message byte */ X return (decode(mbuf[moff++])); X} X X/* decode - decode a character */ Xint decode(ch) X int ch; X{ X return ((ch + 30) & 0xFF); X} X X/* get_block - get a block of message text */ Xget_block(blk) X unsigned int blk; X{ X int last,n; X long loff; X X /* first check the cache */ X for (n = mhead; n != -1; last = n, n = mnext[n]) X if (blk == mblock[n]) { X if (n != mhead) { X if ((mnext[last] = mnext[n]) == -1) X mtail = last; X mnext[n] = mhead; X mhead = n; X } X mbuf = mbuffer[n]; X return; X } X X /* overwrite the least recently used buffer */ X mblock[mtail] = blk; X loff = ((long) mbase + (long) blk) << 9; X lseek(mfd,loff,0); X if (read(mfd,mbuffer[mtail],512) != 512) X error("error reading message text"); X X /* get the block */ X get_block(blk); X} END_OF_advmsg.c if test 2549 -ne `wc -c advprs.c <<'END_OF_advprs.c' X X/* advprs.c - adventure parser */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X X#include "advint.h" X#include "advdbs.h" X X/* parser result variables */ Xint nouns[20]; Xint *adjectives[20]; Xstatic int actor,action,dobject,ndobjects,iobject; Xstatic int flag; X X/* external routines */ Xextern char *trm_get(); X X/* external variables */ Xextern char line[]; /* line buffer */ X X/* local variables */ Xstatic char *lptr; /* line pointer */ Xstatic int words[100]; /* word table */ Xstatic char *wtext[100];/* word text table */ Xstatic int *wptr; /* word pointer */ Xstatic int wcnt; /* word count */ X Xstatic int verbs[3]; /* words in the verb phrase */ Xstatic int nnums[20]; /* noun word numbers */ Xstatic int nptr; /* noun pointer (actually, an index) */ Xstatic int adjs[100]; /* adjective lists */ Xstatic int anums[100]; /* adjective word numbers */ Xstatic int aptr; /* adjective pointer (actually, an index) */ X X/* parse - read and parse an input line */ Xint parse() X{ X if (!parse1()) X return (FALSE); X setvalue(V_ACTOR,actor); X setvalue(V_ACTION,action); X setvalue(V_DOBJECT,dobject); X setvalue(V_NDOBJECTS,ndobjects); X setvalue(V_IOBJECT,iobject); X return (TRUE); X} X X/* next - get the next command (next direct object) */ Xint next() X{ X if (getvalue(V_NDOBJECTS) > 1) { X setvalue(V_ACTOR,actor); X setvalue(V_ACTION,action); X setvalue(V_DOBJECT,getvalue(V_DOBJECT) + 1); X setvalue(V_NDOBJECTS,getvalue(V_NDOBJECTS) - 1); X setvalue(V_IOBJECT,iobject); X return (TRUE); X } X else X return (FALSE); X} X X/* parse1 - the main parser */ Xint parse1() X{ X int noun1,cnt1,noun2,cnt2; X int preposition,flag; X X /* initialize */ X noun1 = noun2 = NIL; cnt1 = cnt2 = 0; X nptr = aptr = 0; X preposition = 0; X flag = 0; X X /* initialize the parser result variables */ X actor = action = dobject = iobject = NIL; X ndobjects = 0; X X /* get an input line */ X if (!get_line()) X return (FALSE); X X /* check for actor */ X if (wtype(*wptr) == WT_ADJECTIVE || wtype(*wptr) == WT_NOUN) { X if ((actor = getnoun()) == NIL) X return (FALSE); X flag |= A_ACTOR; X } X X /* get verb phrase */ X if (!getverb()) X return (FALSE); X X /* direct object, preposition and indirect object */ X if (*wptr) { X X /* get the first set of noun phrases (direct objects) */ X noun1 = nptr+1; X for (;;) { X X /* get the next direct object */ X if (getnoun() == NIL) X return (FALSE); X ++cnt1; X X /* check for more direct objects */ X if (*wptr == NIL || wtype(*wptr) != WT_CONJUNCTION) X break; X wptr++; X } X X /* get the preposition and indirect object */ X if (*wptr) { X X /* get the preposition */ X if (wtype(*wptr) == WT_PREPOSITION) X preposition = *wptr++; X X /* get the second set of noun phrases (indirect object) */ X noun2 = nptr+1; X for (;;) { X X /* get the next direct object */ X if (getnoun() == NIL) X return (FALSE); X ++cnt2; X X /* check for more direct objects */ X if (*wptr == NIL || wtype(*wptr) != WT_CONJUNCTION) X break; X wptr++; X } X } X X /* make sure this is the end of the sentence */ X if (*wptr) { X parse_error(); X return (FALSE); X } X } X X /* setup the direct and indirect objects */ X if (preposition) { X if (cnt2 > 1) { X parse_error(); X return (FALSE); X } X dobject = noun1; X ndobjects = cnt1; X iobject = noun2; X } X else if (noun2) { X if (cnt1 > 1) { X parse_error(); X return (FALSE); X } X preposition = findword("to"); X dobject = noun2; X ndobjects = cnt2; X iobject = noun1; X } X else { X dobject = noun1; X ndobjects = cnt1; X } X X /* setup the flags for the action lookup */ X if (dobject) flag |= A_DOBJECT; X if (iobject) flag |= A_IOBJECT; X X /* find the action */ X if ((action = findaction(verbs,preposition,flag)) == NIL) { X parse_error(); X return (FALSE); X } X X /* return successfully */ X return (TRUE); X} X X/* getverb - get a verb phrase and return the action it refers to */ Xint getverb() X{ X /* get the verb */ X if (*wptr == NIL || wtype(*wptr) != WT_VERB) { X parse_error(); X return (NIL); X } X verbs[0] = *wptr++; X verbs[1] = NIL; X X /* check for a word following the verb */ X if (*wptr) { X verbs[1] = *wptr; X verbs[2] = NIL; X if (checkverb(verbs)) X wptr++; X else { X verbs[1] = words[wcnt-1]; X if (checkverb(verbs)) X words[--wcnt] = NIL; X else { X verbs[1] = NIL; X if (!checkverb(verbs)) { X parse_error(); X return (NIL); X } X } X } X } X return (T); X} X X/* getnoun - get a noun phrase and return the object it refers to */ Xint getnoun() X{ X /* initialize the adjective list pointer */ X adjectives[nptr] = adjs + aptr; X X /* get the optional article */ X if (*wptr != NIL && wtype(*wptr) == WT_ARTICLE) X wptr++; X X /* get optional adjectives */ X while (*wptr != NIL && wtype(*wptr) == WT_ADJECTIVE) { X adjs[aptr] = *wptr++; X anums[aptr] = wptr - words - 1; X aptr++; X } X adjs[aptr++] = NULL; X X /* get the noun itself */ X if (*wptr == NIL || wtype(*wptr) != WT_NOUN) { X parse_error(); X return (NIL); X } X X /* save the noun */ X nouns[nptr] = *wptr++; X nnums[nptr] = wptr - words - 1; X return (++nptr); X} X X/* get_line - get the input line and lookup each word */ Xint get_line() X{ X /* read an input line */ X trm_chr(':'); X if ((lptr = trm_get(line)) == NULL) { X trm_str("Speak up! I can't hear you!\n"); X return (FALSE); X } X X /* get each word on the line */ X for (wcnt = 0; skip_spaces(); wcnt++) X if (get_word() == NIL) X return (FALSE); X words[wcnt] = NIL; X X /* check for a blank line */ X if (wcnt == 0) { X trm_str("Speak up! I can't hear you!\n"); X return (FALSE); X } X X /* point to the first word and return successfully */ X wptr = words; X return (TRUE); X} X X/* skip_spaces - skip leading spaces */ Xint skip_spaces() X{ X while (spacep(*lptr)) X lptr++; X return (*lptr != EOS); X} X X/* show_noun - show a noun phrase */ Xshow_noun(n) X int n; X{ X int adj,*p; X X /* print the adjectives */ X for (p = adjectives[n-1], adj = FALSE; *p; p++, adj = TRUE) { X if (adj) trm_chr(' '); X trm_str(wtext[anums[p-adjs]]); X } X X /* print the noun */ X if (adj) trm_chr(' '); X trm_str(wtext[nnums[n-1]]); X} X X/* get_word - get the next word */ Xint get_word() X{ X int ch; X X /* get the next word */ X for (wtext[wcnt] = lptr; (ch = *lptr) != EOS && !spacep(ch); ) X *lptr++ = (isupper(ch) ? tolower(ch) : ch); X if (*lptr != EOS) *lptr++ = EOS; X X /* look up the word */ X if (words[wcnt] = findword(wtext[wcnt])) X return (words[wcnt]); X else { X trm_str("I don't know the word \""); X trm_str(wtext[wcnt]); X trm_str("\".\n"); X return (NIL); X } X} X X/* spacep - is this character a space? */ Xint spacep(ch) X int ch; X{ X return (ch == ' ' || ch == ',' || ch == '.'); X} X X/* parse_error - announce a parsing error */ Xparse_error() X{ X trm_str("I don't understand.\n"); X} X END_OF_advprs.c if test 6939 -ne `wc -c advtrm.c <<'END_OF_advtrm.c' X X/* advtrm.c - terminal i/o routines */ X/* X Copyright (c) 1986, by David Michael Betz X All rights reserved X*/ X X#include X X/* useful definitions */ X#define TRUE 1 X#define FALSE 0 X#define EOS '\0' X#define LINEMAX 200 X#define WORDMAX 100 X X/* global variables */ Xchar line[LINEMAX+1]; X X/* local variables */ Xstatic int col,maxcol,row,maxrow; Xstatic int scnt,wcnt; Xstatic char word[WORDMAX+1],*wptr; Xstatic FILE *logfp = NULL; X X/* forward declarations */ Xchar *trm_line(); X X/* trm_init - initialize the terminal module */ Xtrm_init(rows,cols,name) X int rows,cols; char *name; X{ X /* initialize the terminal i/o variables */ X maxcol = cols-1; col = 0; X maxrow = rows-1; row = 0; X wptr = word; wcnt = 0; X scnt = 0; X X /* open the log file */ X if (name && (logfp = fopen(name,"w")) == NULL) X error("can't open log file"); X} X X/* trm_done - finish terminal i/o */ Xtrm_done() X{ X if (wcnt) trm_word(); X if (logfp) fclose(logfp); X} X X/* trm_get - get a line */ Xchar *trm_get(line) X char *line; X{ X if (wcnt) trm_word(); X while (scnt--) putchr(' '); X row = col = scnt = 0; X return (trm_line(line)); X} X X/* trm_str - output a string */ Xtrm_str(str) X char *str; X{ X while (*str) X trm_chr(*str++); X} X X/* trm_xstr - output a string without logging or word wrap */ Xtrm_xstr(str) X char *str; X{ X while (*str) X putch(*str++,stdout); X} X X/* trm_chr - output a character */ Xtrm_chr(ch) X int ch; X{ X switch (ch) { X case ' ': X if (wcnt) X trm_word(); X scnt++; X break; X case '\t': X if (wcnt) X trm_word(); X scnt = (col + 8) & ~7; X break; X case '\n': X if (wcnt) X trm_word(); X trm_eol(); X scnt = 0; X break; X default: X if (wcnt < WORDMAX) { X *wptr++ = ch; X wcnt++; X } X break; X } X} X X/* trm_word - output the current word */ Xtrm_word() X{ X if (col + scnt + wcnt > maxcol) X trm_eol(); X else X while (scnt--) X { putchr(' '); col++; } X for (wptr = word; wcnt--; col++) X putchr(*wptr++); X wptr = word; X wcnt = 0; X scnt = 0; X} X X/* trm_eol - end the current line */ Xtrm_eol() X{ X putchr('\n'); X if (++row >= maxrow) X { trm_wait(); row = 0; } X col = 0; X} X X/* trm_wait - wait for the user to type return */ Xtrm_wait() X{ X trm_xstr(" << MORE >>\r"); X waitch(); X trm_xstr(" \r"); X} X X/* trm_line - get an input line */ Xchar *trm_line(line) X char *line; X{ X char *p; X int ch; X X p = line; X while ((ch = getchr()) != EOF && ch != '\n') X switch (ch) { X case '\177': X case '\010': X if (p != line) { X if (ch != '\010') putchr('\010',stdout); X putchr(' ',stdout); X putchr('\010',stdout); X p--; X } X break; X default: X if ((p - line) < LINEMAX) X *p++ = ch; X break; X } X *p = 0; X return (ch == EOF ? NULL : line); X} X X/* getchr - input a single character */ Xint getchr() X{ X int ch; X X if ((ch = getch()) != EOF && logfp) X putch(ch,logfp); X return (ch); X} X X/* putchr - output a single character */ Xputchr(ch) X int ch; X{ X if (logfp) putch(ch,logfp); X putch(ch,stdout); X} END_OF_advtrm.c if test 3061 -ne `wc -c newadv.pch <<'END_OF_newadv.pch' XDate: 22 Sep 1987 09:35 EDT XFrom: Marc Russell Pawliger XTo: Bill Randle XSubject: Re: advcom submission XIn-Reply-To: <8709211623.AA29413@tekred.TEK.COM> X XOK, some of our enhancements haven't really been acid tested, so I'll Xsend you the tame one that is nice, but not wizzo fantastic. It adds a Xnew class called smarticles, for smart articles, that makes `a` and X`an` work correctly for nouns. Not great, but it did get us into the Xcode for a start. X X*** /cmu/misc/cl0x/src/test/advexe.c Tue Sep 22 09:26:26 1987 X--- /cmu/misc/cl0x/src/advsys/advexe.c Tue Jul 28 13:32:00 1987 X*************** X*** 253,258 **** X--- 253,263 ---- X setrand(time(0L)); X *sp = NIL; X break; X+ X+ case OP_VOWEL: X+ *sp = vowel(*sp); X+ break; X+ X default: X if (opcode >= OP_XVAR && opcode < OP_XSET) X *sp = getvalue(opcode - OP_XVAR); X*************** X*** 293,298 **** X--- 298,320 ---- X msg_open(msg); X while (ch = msg_byte()) X trm_chr(ch); X+ } X+ X+ /* vowel - check for vowel */ X+ vowel(msg) X+ int msg; X+ { X+ int ch,r; X+ X+ msg_open(msg); X+ ch = msg_byte(); X+ if (ch=='a'||ch=='e'||ch=='i'||ch=='o'||ch=='u') X+ r = T; X+ else X+ r = NIL; X+ while (ch) X+ ch = msg_byte(); X+ return (r); X } X X /* pnumber - print a number */ Xdiff -c /cmu/misc/cl0x/src/test/advexp.c /cmu/misc/cl0x/src/advsys/advexp.c X*** /cmu/misc/cl0x/src/test/advexp.c Tue Sep 22 09:25:53 1987 X--- /cmu/misc/cl0x/src/advsys/advexp.c Tue Jul 28 13:32:06 1987 X*************** X*** 54,59 **** X--- 54,60 ---- X "yes-or-no", OP_YORN, 0, X "rand", OP_RAND, 1, X "randomize", OP_RNDMIZE, 0, X+ "vowel", OP_VOWEL, 1, X 0 X }; X static struct { char *ft_name; int (*ft_fcn)(); } *fptr,ftab[] = { X X END_OF_newadv.pch if test 1768 -ne `wc -c readme.1st <<'END_OF_readme.1st' XFrom: Darren Leigh X XDocumentation X XREADME 1ST 860 3-08-87 11:49a XADVSYS DOC 30536 7-20-86 12:15p X XSample adventure source X XOSAMPLE ADV 4355 7-20-86 2:15p XOBJECTS ADI 13193 7-20-86 2:16p X XDefinitions (used by ADVCOM and ADVINT) X XADVDBS H 5584 7-20-86 12:48p X XCompiler source code (ADVCOM) X XADVCOM H 1399 7-20-86 12:48p XADVAVL H 782 7-20-86 12:49p XADVCOM C 15476 7-20-86 12:40p XADVFCN C 14285 7-20-86 12:41p XADVSCN C 6362 7-20-86 12:41p XADVEXP C 10829 7-20-86 12:42p XADVAVL C 3750 7-20-86 12:42p XADVFIO C 998 7-20-86 12:42p X XInterpreter source code (ADVINT) X XADVINT H 383 7-20-86 12:50p XADVMSG C 2682 7-20-86 12:43p XADVTRM C 3243 7-20-86 12:43p XADVPRS C 7269 7-20-86 12:43p XADVDBS C 11051 7-20-86 12:44p XADVINT C 2569 7-20-86 12:44p XADVJUNK C 1848 7-19-86 7:24p XADVEXE C 6202 7-20-86 12:44p X X END_OF_readme.1st if test 1043 -ne `wc -c