chris@hwcs.UUCP (Chris Miller) (09/26/85)
#!/bin/sh
#
# This is a distribution of "advgen", a compiler for adventures to be
# run by Chris Torek's "adv". To unpack the distribution, give each
# part as input to the (Bourne) shell.
# Then look at READ_ME.
#
echo 'Start of Advdist, part 03 of 03:'
echo 'x - Makefile'
sed 's/^X//' > Makefile << '/'
XINTERPRETER = /usr/games/lib/adv
XMAXCODE = 50000
XMAXVOCAB = 1000
XCDEFS = -DDEFINTERPRETER=\"$(INTERPRETER)\" -DMAXCODE=$(MAXCODE)\
X -DMAXVOCAB=$(MAXVOCAB)
XCOPTS = -O
XCFLAGS = $(COPTS) $(CDEFS)
XYFLAGS = -d
XLINTFLAGS = -achx $(CDEFS)
XLINT = /u1/staff/chris/bin/llint
XOBJS = advgen.o advgram.o advlex.o lookup.o error.o specials.o\
X vocab.o str.o rooms.o items.o vars.o msgs.o code.o
XSRCS = advgen.c advgram.c advlex.c lookup.c error.c specials.c\
X vocab.c str.c rooms.c items.c vars.c msgs.c code.c
XDIST = READ_ME TO_DO advgen.man advgen.c advgram.y advlex.l lookup.c\
X error.c specials.c vocab.c str.c rooms.c items.c vars.c\
X msgs.c code.c advgen.h extfuncs.h code.h Makefile Pirate.adv\
X Dist.hdr
X
Xadvgen: $(OBJS)
X cc $(COPTS) -o advgen $(OBJS)
X
Xlint: $(SRCS) tokens.h
X $(LINT) $(LINTFLAGS) $(SRCS)
X
X$(OBJS): advgen.h extfuncs.h
X
Xadvgram.o code.o: code.h
X
Xy.tab.h: advgram.c
X
Xlookup.o advlex.o: tokens.h
X
Xtokens.h: y.tab.h
X -cmp -s y.tab.h tokens.h || cp y.tab.h tokens.h
X
Xclean:
X rm -f *.o advgram.c advlex.c y.output y.tab.h tokens.h \
X core Advdist* adv.out advgen
X
Xdist:
X rm -f Advdist*
X packmail -hDist.hdr -oAdvdist $(DIST)
/
echo 'x - READ_ME'
sed 's/^X//' > READ_ME << '/'
XThis is an adventure-generator for the "adv" game by Chris Torek
X(chris@maryland.uucp).
X
XTo build it, check the Makefile and run "make". The most likely things
Xto be changed are:
X INTERPRETER The full pathname of "adv". A suitable #! header
X will be prepended to adventure files, making them
X directly executable (on BSD-derived systems). This
X only works if you have a version of "adv" patched to
X ignore any such initial header; if you don't, define
X INTERPRETER to be empty.
X MAXCODE The maximum size of the generated code; on small
X address-space systems cut this down to, say, 10000
X to reduce the size of "advgen".
X MAXVOCAB The maximum number of entries in the verb and noun
X tables; try MAXVOCAB=200 on small systems.
X
XThis has only been built and run on 4.2bsd on a VAX 11/750. I am
Xunaware of any machine or version dependencies, but they are probably
Xthere.
X
XIf your system doesn't have getopt(3) it should have! Several versions
Xhave been posted to Usenet recently, any of which will work correctly
Xfor "advgen".
X
XIf your system doesn't have adv(6) this program is useless to you. The
Xprogram was posted to the net by chris@maryland.uucp, and a version
Xpatched to use the curses library is available from chris@hwcs.uucp
X(no relation!).
X
XThe file Pirate.adv is an extended example of an input file, produced
Xby de-compiling and massaging the "p" adventure distributed with adv.
XI hope the author will forgive me for revealing his secrets; however,
Xthe cat was out of the bag in any case :-) as soon as the source of adv
Xwas distributed.
X
XComments and complaints to chris@hwcs.uucp, known to the world at large as:
X Chris Miller
X Department of Computer Science
X Heriot-Watt University
X Edinburgh
X Scotland
X +44 31 225 8432 Ext. 242
/
echo 'x - TO_DO'
sed 's/^X//' > TO_DO << '/'
X 1. Replace Message section by Constant section, allowing
X symbolic names for numeric constants.
X
X 2. Further extend by allowing constant expressions.
X
X 3. Allow general boolean expressions in LHS of Daemon and
X Action rules; parse as expression tree, transform tree to
X conjunctive normal form, and produce appropriate number of
X rules, one for each disjunct. NB for daemons, the percentage
X should be attached to setting a control variable, which is reset
X to false on each turn, and is added as a conjunct to the LHS of
X each disjunct.
X
X 4. Allow <, <=, != and >= in relations.
X
X 5. Allow "alphabeticiser" (e.g. ^) as prefix to characters to allow
X anything to appear there.
X [Done 16/9/85 - restricted to allowing ^ as initial character of
X identifiers starting with a digit, to avoid nastiness with ",",
X "*", newline or space in identifiers messing up the word declarations
X in the output file.]
/
echo 'x - advgen.c'
sed 's/^X//' > advgen.c << '/'
X#include "advgen.h"
X
Xvoid
Xmain(nargs, args)
X int nargs;
X char *args[];
X{
X char *envval();
X void print();
X void init_tabs();
X#ifdef lint
X char *optarg = CNULL;
X int optind = 0;
X#else lint
X extern char *optarg;
X extern int optind;
X#endif lint
X int opt;
X bool oflag = FALSE;
X bool wflag = FALSE;
X bool errflag = FALSE;
X char *outfilename = DEFOUTPUT;
X char *interpreter = envval("ADVINT", DEFINTERPRETER);
X static char badusage[] = "[-w] [-o output] [input]";
X FILE *inf = stdin;
X FILE *outf;
X
X setprogname(nargs, args);
X while ((opt = getopt(nargs, args, "wo:")) != EOF)
X {
X switch (opt)
X {
X case 'o':
X if (oflag)
X {
X errflag = TRUE;
X }
X else
X {
X oflag = TRUE;
X outfilename = optarg;
X }
X break;
X case 'w':
X if (wflag)
X {
X errflag = TRUE;
X }
X else
X {
X wflag = TRUE;
X novarwarnings();
X }
X break;
X default:
X errflag = TRUE;
X break;
X }
X }
X if (errflag)
X {
X usage(badusage);
X }
X nargs -= optind;
X args += optind;
X switch (nargs)
X {
X case 0:
X break;
X case 1:
X if ((inf = fopen(args[0], "r")) == NULL)
X {
X fatal("cannot open input file %s", args[0]);
X }
X setinfile(args[0]);
X break;
X default:
X usage(badusage);
X break;
X }
X init_tabs();
X
X if (parse(inf))
X {
X if ((outf = fopen(outfilename, "w")) == NULL)
X {
X fatal("cannot write output file %s", outfilename);
X }
X if (*interpreter != '\0')
X {
X if (chmod(outfilename, 0755) != 0)
X {
X warning("cannot set execute permission for %s", outfilename);
X }
X fprintf(outf, "#!%s\n", interpreter);
X }
X print(outf);
X exit(0);
X }
X else
X {
X exit(1);
X }
X /*NOTREACHED*/
X}
X
Xstatic void
Xprint(f)
X FILE *f;
X{
X printspecials(f);
X printrooms(f);
X printvocab(f);
X printitems(f);
X printmsgs(f);
X printcode(f);
X (void) fclose(f);
X}
X
Xstatic void
Xinit_tabs()
X{
X init_syms();
X (void) decl_room(lookup("Limbo"), 0, SPNULL, "", FALSE);
X decl_item(lookup("NilITEM"), SNULL, SNULL, "");
X}
X
Xstatic char *
Xenvval(var, deflt)
X char *var;
X char *deflt;
X{
X char *result = getenv(var);
X
X return result == CNULL ? deflt : result;
X}
/
echo 'x - advgen.h'
sed 's/^X//' > advgen.h << '/'
X#include <stdio.h>
X
Xtypedef int bool;
Xtypedef char smallbool;
Xtypedef unsigned short smallint;
X
X#define TRUE 1
X#define FALSE 0
X
X#ifndef DEFINTERPRETER
X#define DEFINTERPRETER "/usr/games/adv" /* Program to run output */
X#endif DEFINTERPRETER
X#define DEFWORDSIZE 3 /* Number of significant chars. in vocab. */
X#define DEFINVSIZE 5
X#define DEFLLIFE 240 /* Lamp life */
X#define DEFLWARN 25 /* Lamp warning */
X#define DEFOUTPUT "adv.out"
X
X#define MAXPARSEERRORS 40
X
X/* Most of the maxima below are imposed by the interpreter's use of
X * 1-byte integers for storing indices.
X */
X
X#ifndef MAXCODE
X#define MAXCODE 50000 /* Generated code for daemons and rules */
X#endif MAXCODE
X#ifndef MAXVOCAB
X#define MAXVOCAB 1000 /* Words in noun or verb table */
X#endif MAXVOCAB
X#define MAXROOMS 255 /* Rooms/Locations */
X#define MAXITEMS 255 /* Items */
X#define MAXVARS 255 /* Variable names */
X#define MAXMSGS 255 /* Strings */
X#define MAXWSIZE 20 /* Significant chars. in words (warning) */
X#define MAXINVSIZE 30 /* Maximum reasonable inventory size */
X#define MAXWORDLIST 25 /* Synonyms for special verbs */
X
X#define LIMBO 0
X
Xtypedef struct symbol
X{
X char *s_sym; /* symbol name */
X smallint s_type;
X# define S_UNKNOWN 0
X# define S_SYNTAX 1
X# define S_ROOM 2
X# define S_ITEM 3
X# define S_VAR 4
X# define S_MSG 5
X smallint s_value; /* meaning depends on type */
X smallint s_noun; /* index into noun table */
X smallint s_verb; /* index into verb table */
X} symbol;
X
Xtypedef struct room
X{
X char *r_name;
X char *r_desc;
X smallint r_neighbours[6];
X smallbool r_dark;
X smallbool r_declared; /* To cope forward references */
X} room;
X
Xtypedef struct item
X{
X char *i_name;
X char *i_desc;
X smallint i_noun; /* Word used for this, if any */
X smallint i_room; /* Where it starts */
X} item;
X
Xtypedef struct vocab
X{
X char *v_word;
X smallint v_value; /* Equal values for synonyms */
X smallbool v_dup; /* Flag for indistinguishable words */
X} vocab;
X
Xtypedef struct wordtable
X{
X smallint wt_size; /* Number of entries */
X smallint wt_wcount; /* Ditto, excluding duplicates */
X smallint wt_value; /* Ditto, excluding synonyms */
X vocab wt_vocab[MAXVOCAB];
X} wordtable;
X
Xtypedef struct wordlist /* Mini-wordtable for special verbs/nouns */
X{
X int wl_count;
X char *wl_word[MAXWORDLIST];
X} wordlist;
X
X#define streq(s, t) (*(s) == *(t) && strcmp((s), (t)) == 0)
X
X#define CNULL (char *) NULL
X#define SNULL (symbol *) NULL
X#define SPNULL (symbol **) NULL
X#define WNULL (wordtable *) NULL
X
X#define NOTFOUND 255
X
X#include "extfuncs.h"
/
echo 'x - code.h'
sed 's/^X//' > code.h << '/'
X#define C_ALWAYS NOTFOUND
X
X#define C_EMPTYHANDED 1
X#define C_ISDARK 3
X#define C_V0ZERO 5
X#define C_VnZERO 9
X#define C_V0TEST 13
X#define C_CARRYING 17
X#define C_SAMEROOM 19
X#define C_NEARTO 21
X#define C_INROOM 23
X#define C_INLIMBO 25
X#define C_LOCATION 27
X#define C_VnTEST 29
X
X#define A_WIN 1
X#define A_DIE 2
X#define A_QUIT 3
X#define A_INVENT 4
X#define A_DARKEN 5
X#define A_LIGHTEN 6
X#define A_REFILL 7
X#define A_SCORE 8
X#define A_V0ZERO 9
X#define A_V0ONE 10
X#define A_V0INCR 11
X#define A_V0PRINT 13
X#define A_SAY 14
X#define A_VnPRINT 15
X#define A_VnZERO 16
X#define A_VnONE 17
X#define A_VnINCR 18
X#define A_V0SET 20
X#define A_V0AUG 21
X#define A_MOVETO 22
X#define A_GET 23
X#define A_DROP 24
X#define A_ZAP 25
X#define A_FETCH 26
X#define A_VnSET 27
X#define A_VnAUG 28
X#define A_LOCATION 29
X#define A_SWAP 30
X
X#define R_EQ 0
X#define R_GT 2
X
X#define I_INCR 0
X#define I_DECR 1
/
echo 'x - error.c'
sed 's/^X//' > error.c << '/'
X/*
X * error.c: general-purpose error-handling
X */
X
X#include "advgen.h"
X
Xstatic char *progname = "no name"; /* Set-up by setprogname(argc,argv) */
Xstatic char *infilename = "standard input";
X
Xvoid
Xsetprogname(count,args)
X int count;
X char *args[];
X{
X char *p;
X
X progname = (count>0 ? args[0] : "anonymous program");
X if ((p = rindex(progname, '/')) != NULL)
X {
X progname = p + 1;
X }
X}
X
Xvoid
Xsetinfile(s)
X char *s;
X{
X infilename = s;
X}
X
X/*VARARGS3*/
Xstatic void
Xdoerror(exitcode, level, message, arg1, arg2, arg3, arg4)
X/*
X * if exitcode !=0, exit(exitcode).
X * if message != NULL, fprintf it to stderr (maximum of 4 arguments).
X */
X int exitcode;
X char *level;
X char *message;
X{
X if (message != NULL)
X {
X fprintf(stderr, "%s: ", progname);
X if (level != NULL)
X {
X fprintf(stderr, "%s - ", level);
X }
X fprintf(stderr, message, arg1, arg2, arg3, arg4);
X fprintf(stderr, "\n");
X }
X if (exitcode != 0)
X {
X exit(exitcode);
X /*NOTREACHED*/
X }
X}
X
X/*VARARGS1*/
Xvoid
Xfatal(message, arg1, arg2, arg3, arg4)
X char *message;
X{
X doerror(1, "fatal", message, arg1, arg2, arg3, arg4);
X}
X
X/*VARARGS1*/
Xvoid
Xwarning(message, arg1, arg2, arg3, arg4)
X char *message;
X{
X doerror(0, "warning", message, arg1, arg2, arg3, arg4);
X}
X
X/*VARARGS1*/
Xvoid
Xusage(use)
X char *use;
X{
X doerror(1, (char *) NULL, "usage: %s %s", progname, use);
X}
X
X/*VARARGS2*/
Xvoid
Xgramerror(dump, s, a1, a2, a3, a4)
X bool dump;
X char *s;
X{
X extern int yylineno;
X extern char *infilename;
X
X if (dump)
X {
X dumpline();
X }
X fprintf(stderr, "%s, line %d - ", infilename, yylineno);
X fprintf(stderr, s, a1, a2, a3, a4);
X (void) putc('\n', stderr);
X}
X
Xvoid
Xmuldecl(s, type)
X char *s;
X char *type;
X{
X gramerror(TRUE, "multiple declaration of %s %s", type, s);
X add_error();
X}
X
Xvoid
Xmuldef(s)
X char *s;
X{
X gramerror(TRUE, "warning: %s multiply defined", s);
X}
X
Xstatic char *typename[] =
X{
X "n unknown", " keyword", " room", "n item", " variable", " message"
X};
X
Xvoid
Xconfdecl(s, type, flag)
X char *s;
X char *type;
X smallint flag;
X{
X gramerror(TRUE, "conflicting declaration of (%s) %s as a%s",
X typename[flag], s, type);
X add_error();
X}
X
Xvoid
Xtypeerror(s, t)
X char *s;
X int t;
X{
X gramerror(TRUE, "%s is not a%s", s, typename[t]);
X add_error();
X}
/
echo 'x - extfuncs.h'
sed 's/^X//' > extfuncs.h << '/'
Xvoid add_error(); /* advgram.y */
Xvoid addspecialword(); /* specials.c */
Xvoid addsym(); /* lookup.c */
Xvoid add_treasure(); /* specials.c */
Xvoid addword(); /* vocab.c */
Xsymbol *anon_msg(); /* msgs.c */
Xvoid checkrooms(); /* rooms.c */
Xvoid checkspecials(); /* specials.c */
Xvoid codeassign(); /* code.c */
Xvoid codeaugment(); /* code.c */
Xvoid codebyte(); /* code.c */
Xvoid codeinc(); /* code.c */
Xvoid codeprint(); /* code.c */
Xint codereln(); /* code.c */
Xvoid confdecl(); /* error.c */
Xvoid decl_item(); /* items.c */
Xvoid decl_msg(); /* msgs.c */
Xint decl_room(); /* rooms.c */
Xvoid decl_var(); /* vars.c */
Xvoid dumpline(); /* advlex.l */
Xvoid endcond(); /* code.c */
Xvoid enddaemons(); /* code.c */
Xvoid endrule(); /* code.c */
Xvoid fatal(); /* error.c */
Xint findnoun(); /* vocab.c */
Xint findverb(); /* vocab.c */
Xint firstroom(); /* rooms.c */
Xchar *getenv(); /* C library */
Xvoid gramerror(); /* error.c */
Xvoid greetmsg(); /* msgs.c */
Xvoid init_nouns(); /* specials.c */
Xvoid init_syms(); /* lookup.c */
Xvoid init_verbs(); /* specials.c */
Xsymbol *lookup(); /* lookup.c */
Xvoid main(); /* advgen.c */
Xchar *malloc(); /* C library */
Xvoid muldecl(); /* error.c */
Xvoid muldef(); /* error.c */
Xvoid negate(); /* code.c */
Xchar *noun_name(); /* vocab.c */
Xvoid novarwarnings(); /* code.c */
Xbool parse(); /* advgram.y */
Xvoid printcode(); /* code.c */
Xvoid printitems(); /* items.c */
Xvoid printmsgs(); /* msgs.c */
Xvoid printrooms(); /* rooms.c */
Xvoid printspecials(); /* specials.c */
Xvoid printvocab(); /* vocab.c */
Xchar *rindex(); /* C library */
Xvoid set_dirs(); /* specials.c */
Xvoid set_drop_list(); /* specials.c */
Xvoid set_get_list(); /* specials.c */
Xvoid set_go_list(); /* specials.c */
Xvoid set_greeting(); /* specials.c */
Xvoid set_hell(); /* specials.c */
Xvoid setinfile(); /* error.c */
Xvoid setinput(); /* advlex.l */
Xvoid set_inventory(); /* specials.c */
Xvoid set_lamp(); /* specials.c */
Xvoid set_llife(); /* specials.c */
Xvoid set_lwarn(); /* specials.c */
Xvoid set_nouns(); /* vocab.c */
Xvoid setprogname(); /* error.c */
Xvoid set_start(); /* specials.c */
Xvoid set_treasury(); /* specials.c */
Xvoid set_verbs(); /* vocab.c */
Xvoid set_wsize(); /* specials.c */
Xchar *strcpy(); /* C library */
Xchar *strncpy(); /* C library */
Xchar *strsave(); /* str.c */
Xint typecheck(); /* code.c */
Xvoid typeerror(); /* error.c */
Xvoid usage(); /* error.c */
Xvoid warning(); /* error.c */
/
echo 'x - items.c'
sed 's/^X//' > items.c << '/'
X#include "advgen.h"
X
Xstatic int nitems = 0;
Xstatic item items[MAXITEMS];
X
Xvoid
Xdecl_item(sym, itemname, location, desc)
X symbol *sym;
X symbol *itemname;
X symbol *location;
X char *desc;
X{
X item *i;
X
X switch (sym -> s_type)
X {
X case S_ITEM:
X muldecl (sym -> s_sym, "item");
X break;
X case S_UNKNOWN:
X sym->s_value = newitem (sym -> s_sym);
X break;
X default:
X confdecl (sym -> s_sym, "item", sym -> s_type);
X break;
X }
X i = items + sym->s_value;
X sym->s_type = S_ITEM;
X if (itemname == SNULL)
X {
X i -> i_noun = 0;
X }
X else if (itemname->s_noun == 0)
X {
X gramerror(TRUE, "%s is not a noun", itemname->s_sym);
X add_error();
X }
X else
X {
X i->i_noun = itemname->s_noun;
X }
X i -> i_desc = desc;
X if (*desc == '*')
X {
X add_treasure();
X }
X if (location == SNULL)
X {
X i -> i_room = LIMBO;
X }
X else
X {
X switch (location -> s_type)
X {
X case S_ROOM:
X i -> i_room = location -> s_value;
X break;
X default:
X gramerror (TRUE, "%s is not a room", location -> s_sym);
X add_error ();
X break;
X }
X }
X}
X
Xstatic int
Xnewitem(s)
X char *s;
X{
X if (nitems == MAXITEMS)
X {
X fatal("too many items");
X }
X items[nitems].i_name = s;
X return nitems++;
X}
X
Xvoid
Xprintitems(f)
X FILE *f;
X{
X int i;
X extern int wsize;
X
X fprintf(f, "%d\n", nitems);
X for (i=0; i<nitems; i++)
X {
X fprintf(f, "%d", items[i].i_room);
X if (items[i].i_noun)
X {
X fprintf(f, "=%-.*s", wsize, noun_name(items[i].i_noun));
X }
X fprintf(f, ":%s\n", items[i].i_desc);
X }
X}
/
echo 'x - msgs.c'
sed 's/^X//' > msgs.c << '/'
X#include "advgen.h"
X
Xstatic int nmsgs = 1;
Xstatic char *msgs[MAXMSGS] = { "Enjoy your adventure!" };
X
Xvoid
Xdecl_msg(s, m)
X symbol *s;
X char *m;
X{
X switch (s->s_type)
X {
X case S_MSG:
X muldecl(s->s_sym, "message");
X break;
X case S_UNKNOWN:
X if (nmsgs == MAXMSGS)
X {
X fatal("too many messages");
X }
X msgs[nmsgs] = m;
X s->s_type = S_MSG;
X s->s_value = nmsgs++;
X break;
X default:
X confdecl(s->s_sym, "message", s->s_type);
X break;
X }
X}
X
Xsymbol *
Xanon_msg(m)
X char *m;
X{
X static symbol s;
X int i;
X
X for (i=0; i<nmsgs; i++)
X {
X if (streq(m, msgs[i]))
X {
X s.s_value = i;
X return &s;
X }
X }
X if (nmsgs == MAXMSGS)
X {
X fatal("too many messages");
X }
X msgs[nmsgs] = m;
X s.s_value = nmsgs++;
X s.s_type = S_MSG;
X return &s;
X}
X
Xvoid
Xgreetmsg(m)
X char *m;
X{
X msgs[0] = m;
X}
X
Xvoid
Xprintmsgs(f)
X FILE *f;
X{
X int i;
X
X fprintf(f, "%d\n", nmsgs);
X for (i=0; i<nmsgs; i++)
X {
X fprintf(f, "%s\n", msgs[i]);
X }
X}
/
echo 'x - rooms.c'
sed 's/^X//' > rooms.c << '/'
X#include "advgen.h"
X
Xstatic room rooms[MAXROOMS];
Xstatic int nrooms;
X
Xint
Xdecl_room(sym, darkness, nbrs, desc, flag)
X symbol *sym;
X bool darkness;
X symbol **nbrs;
X char *desc;
X bool flag;
X{
X room *r;
X int i;
X
X switch (sym->s_type)
X {
X case S_ROOM:
X if (flag && rooms[sym->s_value].r_declared)
X {
X muldecl(sym->s_sym, "room");
X }
X break;
X case S_UNKNOWN:
X sym->s_value = newroom(sym->s_sym);
X sym->s_type = S_ROOM;
X break;
X default:
X confdecl(sym->s_sym, "room", sym->s_type);
X break;
X }
X if (flag)
X {
X r = rooms+(sym->s_value);
X r->r_declared = 1;
X r->r_dark = darkness;
X r->r_desc = desc;
X for (i = 0; i < 6; i++)
X {
X r->r_neighbours[i] = (nbrs && nbrs[i]) ?
X decl_room(nbrs[i], FALSE, SPNULL, CNULL, FALSE) : 0;
X }
X }
X return sym->s_value;
X}
X
Xstatic int
Xnewroom(s)
X char *s;
X{
X if (nrooms == MAXROOMS)
X {
X fatal("too many rooms");
X }
X rooms[nrooms].r_name = s;
X return nrooms++;
X}
X
Xvoid
Xcheckrooms()
X{
X int i;
X
X for (i=1; i<nrooms; i++)
X {
X if (!rooms[i].r_declared)
X {
X gramerror(FALSE, "warning: undeclared room %s", rooms[i].r_name);
X }
X }
X}
X
Xvoid
Xprintrooms(f)
X FILE *f;
X{
X int i, d;
X
X fprintf(f, "%d\n", nrooms);
X for (i = 0; i < nrooms; i++)
X {
X for (d = 0; d < 6; d++)
X {
X if (rooms[i].r_neighbours[d])
X {
X fprintf(f, "%c%d", "NSEWUD"[d], rooms[i].r_neighbours[d]);
X }
X }
X if (rooms[i].r_dark)
X {
X (void) putc('%', f);
X }
X fprintf(f, ":%s\n", rooms[i].r_desc);
X }
X}
X
Xint
Xfirstroom()
X{
X return nrooms < 2 ? 0 : 1;
X}
/
echo 'Part 03 of Advdist complete.'
exit
--
Chris Miller, Heriot-Watt University, Edinburgh
...!ukc!hwcs!chris chris@hwcs.uucp chris@cs.hw.ac.uk