Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10 5/3/83; site cmu-cs-cad.ARPA Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!godot!harvard!seismo!rochester!cmu-cs-pt!cmu-cs-cad!mlm From: mlm@cmu-cs-cad.ARPA (Michael Mauldin) Newsgroups: net.sources Subject: Rog-O-Matic XIV (part 10 of 10) Message-ID: <273@cmu-cs-cad.ARPA> Date: Fri, 1-Feb-85 11:34:08 EST Article-I.D.: cmu-cs-c.273 Posted: Fri Feb 1 11:34:08 1985 Date-Received: Sun, 3-Feb-85 09:41:13 EST Organization: Carnegie-Mellon University, CS/RI Lines: 1403 #!/bin/sh # # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ # @ Here is part of your new automatic Rogue player, Rog-O-Matic XIV! @ # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ # # [Note: this is a Beta-Test release of version XIV, and almost # certainly contains bugs. A new version will be made available # soon. If you experience any problems with this version, please # contact Michael Mauldin as soon as possible, so your input can be # included in the new release] # # Rog-O-Matic XIV is shipped via mail in pieces, files rgm14.01, rgm14.02, # ..., rgm14.nn. Each piece contains some number of smaller files. To # retrieve them, run each file through the shell 'sh', as follows: # # sh database.c << '/' X/* X * database.c: Rog-O-Matic XIV (CMU) Fri Dec 28 23:26:25 1984 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * This file contains the code which handles the database of objects which X * have been used, and what the real names of the items are. There are X * five functions: X * X * useobj (oldname) enter the object type into the database X * infername (oldname, name) make the real name of obj be name X * used (oldname) returns TRUE if we have entered obj X * know (name) returns TRUE if we have inferred name X * realname (oldname) returns the inferred name of obj X */ X X# include X# include "types.h" X# include "globals.h" X X# define TABLESIZE 101 X# define NOTFOUND (-1) X Xstruct { char fakename[64]; X char roguenam[64]; } dbase[TABLESIZE]; X Xint datalen = 0; X X/* X * findentry: find the database entry for 'string' X */ X Xfindentry (string) Xchar *string; X{ register int i; X X for (i = 0; i < datalen; i++) X if (streq (dbase[i].fakename, string) || X *dbase[i].roguenam && streq (dbase[i].roguenam, string)) X return (i); X X return (NOTFOUND); X} X X/* X * useobj: Indicate that we have used (i.e. read, quaffed, or zapped) an X * object with name 'oldname'. X */ X Xuseobj (oldname) Xchar *oldname; X{ if (findentry (oldname) == NOTFOUND) X { strcpy (dbase[datalen].fakename, oldname); X strcpy (dbase[datalen++].roguenam, ""); X } X} X X/* X * infername: Note that we now think that the object named 'oldname' is X * really named 'name' (e.g. scroll 'google plex' is really a scroll of X * light). X */ X Xinfername (oldname, name) Xchar *oldname; Xchar *name; X{ register int i; X X i = findentry (oldname); X X if (i == NOTFOUND) X { strcpy (dbase[datalen].fakename, oldname); X strcpy (dbase[datalen++].roguenam, name); X } X else X { if (*dbase[i].roguenam && strcmp (dbase[i].roguenam, name)) X dwait (D_ERROR, "Inconsistent inference '%s', '%s'", X dbase[i].roguenam, name); X else X strcpy (dbase[i].roguenam, name); X } X} X X/* X * used: Return true if we have marked 'oldname' as used. X */ X Xint used (oldname) Xchar *oldname; X{ register int i; X X for (i = 0; i < datalen; i++) X if (streq (dbase[i].fakename, oldname)) X return (TRUE); X X return (FALSE); X} X X/* X * know: Return true if we know what the fake name for 'name' is. X */ X Xint know (name) Xchar *name; X{ register int i; X X for (i = 0; i < datalen; i++) X if (*dbase[i].roguenam && streq (dbase[i].roguenam, name)) X return (TRUE); X X return (FALSE); X} X X/* X * realname: Returns the real name of an object nmed 'oldname'. X */ X Xchar *realname (oldname) Xchar *oldname; X{ register int i; X X for (i = 0; i < datalen; i++) X if (*dbase[i].roguenam && streq (dbase[i].fakename, oldname)) X return (dbase[i].roguenam); X X return (""); X} X X/* X * dumpdatabase: Debugging, dump the database one the screen. X */ X Xdumpdatabase () X{ register int i; X X for (i = 0; i < datalen; i++) X { at (i+1, 0); X printw ("%-32s '%s'", dbase[i].roguenam, dbase[i].fakename); X } X} / echo 'x - findscore.c' sed 's/^X//' > findscore.c << '/' X/* X * findscore.c: Rog-O-Matic XIV (CMU) Fri Dec 28 23:27:10 1984 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * Read the Rogue scoreboard to determine a goal score. X */ X X# include X# include "install.h" X# define TEMPFL "/tmp/RscoreXXXXXX" X# define ISDIGIT(c) ((c) >= '0' && (c) <= '9') X Xfindscore (rogue, roguename) Xregister char *rogue, *roguename; X{ register int score, best = -1; X char cmd[100], buffer[BUFSIZ]; X register char *s, *tmpfname = TEMPFL; X FILE *tmpfil; X X /* Run 'rogue -s', and put the scores into a temp file */ X sprintf (cmd, "%s -s >%s", rogue, mktemp (tmpfname)); X system (cmd); X X /* If no temp file created, return default score */ X if ((tmpfil = fopen (tmpfname, "r")) == NULL) X return (best); X X /* Skip to the line starting with 'Rank...'. */ X while (fgets (buffer, BUFSIZ, tmpfil) != NULL) X if (stlmatch (buffer, "Rank")) break; X X if (! feof (tmpfil)) X { best = BOGUS; X while (fgets (buffer, BUFSIZ, tmpfil) != NULL) X { s = buffer; /* point s at buffer */ X while (ISDIGIT (*s)) s++; /* Skip over rank */ X while (*s == ' ' || *s == '\t') s++; /* Skip to score */ X score = atoi (s); /* Read score */ X while (ISDIGIT (*s)) s++; /* Skip over score */ X while (*s == ' ' || *s == '\t') s++; /* Skip to player */ X X if (score < best) /* Save smallest score */ X best = score; X if (stlmatch (s, roguename)) /* Found our heros name */ X break; X } X } X X unlink (tmpfname); X return (best); X} / echo 'x - gene.c' sed 's/^X//' > gene.c << '/' X/* X * gene.c: Rog-O-Matic XIV (CMU) Mon Jan 28 20:51:32 1985 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * Initialize and summarize the gene pool X */ X X# include X# include "types.h" X# include "install.h" X Xint knob[MAXKNOB]; Xchar genelock[100]; Xchar genelog[100]; Xchar genepool[100]; X Xmain (argc, argv) Xint argc; Xchar *argv[]; X{ int m=10, init=0, seed=0, version=RV53A, full=0; X X /* Get the options */ X while (--argc > 0 && (*++argv)[0] == '-') X { while (*++(*argv)) X { switch (**argv) X { when 'i': init++; X when 'f': full++; X when 'm': m = atoi(*argv+1); SKIPARG; X printf ("Gene pool size %d.\n", m); X when 's': seed = atoi(*argv+1); SKIPARG; X printf ("Random seed %d.\n", m); X when 'v': version = atoi(*argv+1); SKIPARG; X printf ("Rogue version %d.\n", version); X otherwise: quit (1, "Usage: gene [-i] [-msv]\n"); X } X } X } X X /* Assign the gene log and pool file names */ X sprintf (genelock, "%s/GeneLock%d", RGMDIR, version); X sprintf (genelog, "%s/GeneLog%d", RGMDIR, version); X sprintf (genepool, "%s/GenePool%d", RGMDIR, version); X X critical (); /* Disable interrupts */ X if (lock_file (genelock, MAXLOCK)) X { if (init) X { srand (seed); /* Set the random number generator */ X openlog (genelog); /* Open the gene log file */ X initpool (MAXKNOB, m); /* Random starting point */ X writegenes (genepool); /* Write out the gene pool */ X closelog (); /* Close the log file */ X } X else if (! readgenes (genepool)) /* Read the gene pool */ X quit (1, "Cannot read file '%s'\n", genepool); X X unlock_file (genelock); X } X else X quit (1, "Cannot access file '%s'\n", genepool); X X uncritical (); /* Re-enable interrupts */ X analyzepool (full); /* Print a summary */ X} / echo 'x - install.h' sed 's/^X//' > install.h << '/' X/* X * install.h: Rog-O-Matic XIV (CMU) Wed Jan 30 17:39:50 1985 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * This file contains (hopefully) all system dependent defines X * This version of Rog-O-Matic runs with Rogue version 5.2. X */ X X/* X * BSD41: Defined for 4.1bsd Unix systems (Undefined means 4.2bsd) X */ X X# define BSD41 X X/* X * Rog-O-Matic's best score against Rogue 5.3 (UTexas, Feb 1984) X * Printed when no score file is available in dumpscore() X */ X X# define BEST (11316) X X/* X * Rog-O-Matic will not try to beat scores higher than BOGUS which X * appear on the Rogue scoreboard. X */ X X# define BOGUS (50000) X X/* X * This variable defines the version of Rogue we are assumed to be playing X * if the getrogueversion() routine can't figure it out. This must be X * defined, and can be either "5.2", "3.6", or "5.3" X */ X X# define DEFVER "5.3" X X/* X * This file is created whenever the Rog-O-Matic score file is accessed to X * prevent simulatneous accesses. This variable must be defined, but will X * not be used unless RGMDIR is also defined. X */ X X# define LOCKFILE "/tmp/Rgm Lock" X X/* X * This variable is the level at which we always start logging the game X */ X X# define GOODGAME (16) X X/* X * This variable is the number of seconds after which a LOCKFILE is X * considered to be invalid. This is necessary to avoid requiring manual X * intervention when Rog-O-Matic dies while the score file is open. X * This variable must be defined, but will not be used unless RGMDIR X * is also defined. X */ X X# define MAXLOCK (120 /* seconds */) X X/* X * This variable defines the "local" copy of Rogue, which may have only X * intermittent access. This is useful at CMU, since Rogue 5.2 is not X * supported on all machines. First Rog-O-Matic looks for "rogue" in the X * current directory, then this file is used. This variable need not be X * defined. X */ X X# define NEWROGUE "/usr/mlm/bin/rogue" X X/* X * This is the location of the player executable, which is the main X * process for Rog-O-Matic. If "player" does not exist in the current X * directory, then this file is used. This variable need not be defined X * (but in that case there must be a "player" binary in the current X * directory). X */ X X# define PLAYER "/usr/mlm/bin/player" X X/* X * This is the version of the "current" Rog-O-Matic, and is an uppercase X * Roman numeral. It must be defined. X */ X X# define RGMVER "XIV" X X/* X * This is the standard system version of Rogue, and is used if "rogue" X * and NEWROGUE are not available. It need not be defined, but if it is X * not, and NEWROGUE is not defined, then there must be a "rogue" in the X * current directory. X */ X X# define ROGUE "/usr/games/rogue" X X/* X * This file is created in the current directory if the logging option is X * enabled. If the game terminates normally, this file is renamed to X * ... This variable must be defined. X */ X X# define ROGUELOG "roguelog" X X/* X * This directory must be defined. It will contain logs of Rogomatic's X * scores, an error.log file, and the long term memory file. It must X * be writeable by everyone, since score files must be created and X * destroyed by anyone running the program. Alternatively, the X * player process could be made setuid, with that uid owning this X * directory. X */ X X# define RGMDIR "/usr/mlm/src/rog/ver14/rlog" X X/* X * This file is created in the current directory if the snapshot command X * is typed during a Rogue game. It must be defined. X */ X X# define SNAPSHOT "rgm.snapshot" / echo 'x - makefile' sed 's/^X//' > makefile << '/' X# makefile: Rog-O-Matic XIV (CMU) Thu Jan 31 18:23:25 1985 - mlm X# Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X# XBINARIES= rogomatic player rgmplot datesub histplot gene XBINDIR= /usr/mlm/bin/test XPUBDIR= /usr/mlm/rgm/src14 XCCFLAGS= -g XLDFLAGS= XOBJS= arms.o command.o database.o debug.o explore.o io.o learn.o\ X ltm.o main.o mess.o monsters.o pack.o rand.o replay.o rooms.o\ X scorefile.o search.o stats.o strategy.o survival.o tactics.o\ X things.o titlepage.o utility.o worth.o XSRCS= arms.c command.c database.c debug.c explore.c io.c learn.c\ X ltm.c main.c mess.c monsters.c pack.c rand.c replay.c rooms.c\ X scorefile.c search.c stats.c strategy.c survival.c tactics.c\ X things.c titlepage.c utility.c worth.c XHDRS= types.h globals.h install.h termtokens.h XOTHERS= setup.c findscore.c datesub.l histplot.c rgmplot.c gene.c\ X rplot Bugreport X# X# The following commands are declared: X# Xall: $(BINARIES) X echo -n "" >/dev/tty X# X# X# General makefile stuff: X# Xarms.o: types.h globals.h X cc -c $(CCFLAGS) arms.c Xcommand.o: types.h globals.h X cc -c $(CCFLAGS) command.c Xdatabase.o: types.h globals.h X cc -c $(CCFLAGS) database.c Xdatesub.c: datesub.l X lex datesub.l X mv lex.yy.c datesub.c Xdatesub.o: datesub.c X cc -c $(CCFLAGS) datesub.c Xdatesub: datesub.o X cc $(LDFLAGS) -o datesub datesub.o Xdebug.o: types.h globals.h install.h X cc -c $(CCFLAGS) debug.c Xexplore.o: types.h globals.h X cc -c $(CCFLAGS) explore.c Xfindscore.o: install.h X cc -c $(CCFLAGS) findscore.c Xgene: gene.c rand.o learn.o stats.o utility.o types.h install.h X cc $(CCFLAGS) $(LDFLAGS) -o gene gene.c \ X rand.o learn.o stats.o utility.o -lm Xhistplot: histplot.o utility.o X cc $(LDFLAGS) -o histplot histplot.o utility.o Xhistplot.o: X cc -c histplot.c Xio.o: types.h globals.h termtokens.h X cc -c $(CCFLAGS) io.c Xmess.o: types.h globals.h X cc -c $(CCFLAGS) mess.c Xlearn.o: types.h install.h X cc -c $(CCFLAGS) learn.c Xltm.o: types.h globals.h X cc -c $(CCFLAGS) ltm.c Xmain.o: install.h termtokens.h types.h globals.h X cc -c $(CCFLAGS) main.c Xmonsters.o: types.h globals.h X cc -c $(CCFLAGS) monsters.c Xpack.o: types.h globals.h X cc -c $(CCFLAGS) pack.c Xplayer: $(OBJS) X cc $(LDFLAGS) -o player $(OBJS) -lm -lcurses -ltermcap X size player Xrand.o: rand.c X cc -c $(CCFLAGS) rand.c Xreplay.o: types.h globals.h X cc -c $(CCFLAGS) replay.c Xrgmplot.o: rgmplot.c X cc -c $(CCFLAGS) rgmplot.c Xrgmplot: rgmplot.o utility.o X cc $(LDFLAGS) -o rgmplot rgmplot.o utility.o Xrogomatic: setup.o findscore.o scorefile.o utility.o X cc $(LDFLAGS) -o rogomatic setup.o findscore.o scorefile.o utility.o X size rogomatic Xrooms.o: types.h globals.h X cc -c $(CCFLAGS) rooms.c Xscorefile.o: types.h globals.h install.h X cc -c $(CCFLAGS) scorefile.c Xsearch.o: types.h globals.h X cc -c $(CCFLAGS) search.c Xsetup.o: install.h X cc -c $(CCFLAGS) setup.c Xstats.o: types.h X cc -c $(CCFLAGS) stats.c Xstrategy.o: types.h globals.h install.h X cc -c $(CCFLAGS) strategy.c Xsurvival.o: types.h globals.h X cc -c $(CCFLAGS) survival.c Xtactics.o: types.h globals.h X cc -c $(CCFLAGS) tactics.c Xtestfind: testfind.o findscore.o utility.o X cc $(LDFLAGS) -o testfind testfind.o findscore.o utility.o Xthings.o: types.h globals.h X cc -c $(CCFLAGS) things.c Xtitlepage.o: titlepage.c X cc -c $(CCFLAGS) titlepage.c Xtitler.o: titler.c X cc -c titler.c Xutility.o: X cc -c $(CCFLAGS) utility.c Xworth.o: types.h globals.h X cc -c $(CCFLAGS) worth.c X# X# Miscellaneous useful pseduo-makes X# Xbackup: X rm -f backup.tar X tar cvf backup.tar *.c *.h *.l rogomatic.6 makefile X chmod ugo-w backup.tar Xclean: X rm -f *.CKP *.o datesub.c core X strip $(BINARIES) Xinstall: X rm -f $(BINDIR)/player X ln player $(BINDIR)/player X rm -f $(BINDIR)/rogomatic X ln rogomatic $(BINDIR)/rogomatic Xtitler: titler.c X cc -o titler titler.c -lcurses -ltermcap Xanim: anim.c utility.o X cc -o anim anim.c utility.o -lcurses -ltermcap Xindex: $(SRCS) X ctags -x $(SRCS) > index Xfluff: $(SRCS) X lint *.c | grep -v 'variable # of args' \ X | grep -v 'unused in function' \ X | grep -v 'used inconsistently' \ X | grep -v 'declared inconsistently' \ X | grep -v 'multiply declared' \ X > fluff Xprint: $(SRCS) $(HDRS) X @echo $? > printit Xdist: $(SRCS) $(HDRS) $(OTHERS) makefile rogomatic.6 README X rm -rf $(PUBDIR) X mkdir $(PUBDIR) X cp $(SRCS) $(HDRS) $(OTHERS) makefile rogomatic.6 README $(PUBDIR) X chmod 0444 $(PUBDIR)/* X du $(PUBDIR) X Xgenetest: genetest.o learn.o rand.o stats.o utility.o types.h X cc -g -o genetest genetest.o learn.o rand.o stats.o utility.o -lm X Xgplot: gplot.c X cc -g -o gplot gplot.c -lm / echo 'x - replay.c' sed 's/^X//' > replay.c << '/' X/* X * replay.c: Rog-O-Matic XIV (CMU) Fri Dec 28 22:43:54 1984 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * Make a table of offsets to the beginning of each level of a X * Rog-O-Matic log file. X */ X X# include X# include X# include "types.h" X# include "globals.h" X X# define MAXNUMLEV 50 X# define FIRSTLEVSTR "\nR: " X# define NEWLEVSTR "\nR: {ff}" X# define POSITAT "{ff}" X Xstruct levstruct { X long pos; X int level, gold, hp, hpmax, str, strmax, ac, explev, exp; X} levpos[MAXNUMLEV]; Xint numlev = 0; X X/* X * positionreplay: Called when user has typed the 'R' command, it fills X * the level table by calling findlevel if necessary, and then positions X * the log file to the level requested by the user. X */ X Xpositionreplay () X{ int curlev; X long curpos; X char cmd; X X /* Prompt user for a command character, read it, and lower case it */ X saynow ("Which level (f=first, p=previous, c=current, n=next, l=last): "); X if (isupper ((cmd = getch ()))) cmd = tolower (cmd); X X /* Clear the prompt */ X saynow (""); X X /* If command is not in the list, clear the prompt and exit. */ X switch (cmd) X { case 'f': case 'p': case 'c': case 'n': case 'l': break; X default: return; X } X X /* Save the current position in the file */ X curpos = ftell (logfile); X X /* Read the log file, if we have not already done so */ X if (!logdigested) X { saynow ("Reading whole log file to find levels..."); X X if (!findlevel (logfile, levpos, &numlev, MAXNUMLEV)) X { saynow ("Findlevel failed! Let's try to get back to where we were..."); X fseek (logfile, curpos, 0); X return; X } X logdigested++; X } X X /* Now figure out the current level (so relative commands will work) */ X for (curlev = 0; curlev < numlev-1; curlev++) X if (levpos[curlev+1].pos > curpos) break; X X /* Now clear the screen, position the log file, and return */ X switch (cmd) X { case 'f': fseek (logfile, levpos[0].pos, 0); break; X case 'p': if (curlev > 0) fseek (logfile, levpos[curlev-1].pos); X else fseek (logfile, levpos[0].pos, 0); break; X break; X case 'c': fseek (logfile, levpos[curlev].pos); break; X case 'n': if (curlev < numlev-1) fseek (logfile, levpos[curlev+1].pos); X else fseek (logfile, levpos[curlev].pos, 0); break; X break; X case 'l': fseek (logfile, levpos[numlev-1].pos); X break; X default: fseek (logfile, 0L, 0); X } X X clearscreen (); /* Clear the screen */ X Level = -1; /* Force a newlevel() call */ X} X X/* X * findlevel: Make a table of offsets to the various levels of a X * Rog-O-Matic log file. X */ X Xfindlevel (f, levpos, numlev, maxnum) XFILE *f; Xstruct levstruct *levpos; Xint *numlev, maxnum; X{ char ch; X X int l=0; X *numlev = 0; X X /* Position file after first newline */ X rewind (f); X while ((ch = getc (f)) != '\n' && (int) ch != EOF); X X /* This is that start of level one */ X levpos[l].pos = ftell (f); X X if (!findmatch (f, FIRSTLEVSTR)) X { rewind (f); X return (FAILURE); X } X X fillstruct (f, &levpos[l]); X X while (++l <= maxnum && findmatch (f, NEWLEVSTR)) X { fseek (f, (long) -strlen (POSITAT), 1); X levpos[l].pos = ftell (f); X fillstruct (f, &levpos[l]); X } X X *numlev = l; X rewind (f); X return (SUCCESS); X} X X/* X * fillstruct: scan the logfile from the current point, and fill in the X * fields of a levstruct. X */ X Xfillstruct (f, lev) XFILE *f; Xstruct levstruct *lev; X{ X lev->level = 0; X lev->gold = 0; X lev->hp = 0; X lev->hpmax = 0; X lev->str = 0; X lev->strmax = 0; X lev->ac = 0; X lev->explev = 0; X lev->exp = 0; X X if (!findmatch (f, "Level:")) return; X fscanf (f, "%d", &lev->level); X X if (!findmatch (f, "Gold:")) return; X fscanf (f, "%d", &lev->gold); X X if (!findmatch (f, "Hp:")) return; X fscanf (f, "%d(%d)", &lev->hp, &lev->hpmax); X X if (!findmatch (f, "Str:")) return; X fscanf (f, "%d(%d)", &lev->str, &lev->strmax); X X if (!findmatch (f, ":")) return; /* Armor class */ X fscanf (f, "%d", &lev->ac); X X if (!findmatch (f, "Exp:")) return; X fscanf (f, "%d/%d", &lev->explev, &lev->exp); X X saynow ("Found level %d, has %d gold...", lev->level, lev->gold); X} X X/* X * findmatch: read from a stream until string 's' has been read. Returns 0 X * if EOF is read, and 1 if the match is found. The stream is left X * immediately after the matched string. X * X * Restriction: 's' must not contain prefix of itself as a substring. X */ X Xint findmatch (f, s) XFILE *f; Xchar *s; X{ char *m = s, ch; X X while (*m && (int) (ch = fgetc (f)) != EOF) X if (ch != *(m++)) m = s; X X if (*m) return (0); X else return (1); X} / echo 'x - rgmplot.c' sed 's/^X//' > rgmplot.c << '/' X/* X * rgmplot.c: Rog-O-Matic XIV (CMU) Thu Jan 31 20:04:11 1985 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * This program takes a Rog-O-Matic score file sorted by date and score, X * and produces a scatter plot of the scores. X */ X X# include X# define WIDTH 50 X# define AVLEN 7 X# define SCALE(n) (((n)+100)/200) X# define isdigit(c) ((c) >= '0' && (c) <= '9') X Xchar *month[] = X{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; X Xint doavg = 0, cheat = 0, min = -1; X Xmain (argc, argv) Xint argc; Xchar *argv[]; X{ int mm, dd, yy, score = 0, lastday = -1, lastmon = -1, h; X int sumscores = 0, numscores = 0, i; X int sum[AVLEN], num[AVLEN], rsum, rnum, davg, ravg; X char player[100], plot[128], cheated; X X /* Clear out the rolling average statistics */ X for (i = 0; i < AVLEN; i++) X sum[i] = num[i] = 0; X X /* Get the options */ X while (--argc > 0 && (*++argv)[0] == '-') X while (*++(*argv)) X { switch (**argv) X { case 'c': cheat++; break; /* List cheat games */ X case 'a': doavg++; break; /* Print average */ X default: printf ("Usage: rgmplot [-ac] [mininum]\n"); X exit (1); X } X } X X if (argc > 0) min = atoi (argv[0]); X X /* Print out the header */ X printf (" Scatter Plot of Rog-O-Matic Scores versus time\n\n"); X if (min > 0) X printf (" Scores greater than %d\n\n", min); X printf (" 0 2000 4000 6000 8000 10000\n"); X printf (" |----+----|----+----|----+----|----+----|----+----|\n"); X X X /* Build an empty plot line */ X strcpy (plot, "| |"); X X /* While more scores do action for each score */ X while (getscore (&mm, &dd, &yy, player, &score, &cheated) != EOF) X { X /* Change days, overprint the average for day, rolling avg */ X if ((dd != lastday || mm != lastmon) && lastday > 0) X { if (doavg) X { rsum = *sum; rnum = *num; X for (i = 1; i < AVLEN; i++) X { rsum += sum[i]; rnum += num[i]; } X X davg = SCALE ((*num > 0) ? (*sum / *num) : 0); X ravg = SCALE ((rnum > 0) ? (rsum / rnum) : 0); X X /* Roll the daily average statistics */ X for (i = AVLEN-1; i > 0; i--) X { sum[i] = sum[i-1]; num[i] = num[i-1]; } X *sum = *num = 0; X X /* Print a '*' for the daily average */ X if (davg > 0 && davg < WIDTH) X plot[davg] = '*'; X X /* Print a '###' for the rolling average */ X if (ravg > 0 && ravg < WIDTH-1) X plot[ravg-1] = plot[ravg] = plot[ravg+1] = '#'; X } X X printf ("%3s %2d %s\n", month[lastmon-1], lastday, plot); X strcpy (plot, "| |"); X X } X X if (score > EOF) X { if ((h = SCALE(score)) >= WIDTH) sprintf (plot, "%s %d", plot, score); X else if (plot[h] == '9') ; X else if (isdigit(plot[h])) plot[h]++; X else plot[h] = '1'; X X *sum += score; X ++*num; X X sumscores += score; X ++numscores; X X lastday = dd; lastmon = mm; X } X } X X printf (" |----+----|----+----|----+----|----+----|----+----|\n"); X printf (" 0 2000 4000 6000 8000 10000\n"); X X X if (numscores > 0) X printf ("\nAverage score %d, total games %d.\n\n", X sumscores/numscores, numscores); X X printf ("1-9 Number of games in range.\n"); X X if (doavg) X { printf (" * Average of day's scores.\n"); X printf ("### Rolling %d day average.\n", AVLEN); X } X} X X Xgetlin (s) Xchar *s; X{ int ch, i; X static int endfile = 0; X X if (endfile) return (EOF); X X for (i=0; (ch = getchar()) != EOF && ch != '\n'; i++) X s[i] = ch; X X s[i] = '\0'; X X if (ch == EOF) X { endfile = 1; X strcpy (s, "-1 -1, -1 string -1 "); X return (20); X } X X return (i); X} X Xgetscore (mm, dd, yy, player, score, cheated) Xint *mm, *dd, *yy, *score; Xchar *player, *cheated; X{ char line[128], reason[32]; X while (getlin (line) != EOF) X { sscanf (line, "%d %d, %d %10s%d%c%17s", X mm, dd, yy, player, score, cheated, reason); X if ((*score >= min || *score < 0) && X (*cheated != '*' || cheat) && X !stlmatch (reason, "saved") && X (*score > 2000 || !stlmatch (reason, "user"))) X return (1); X } X return (EOF); X} / echo 'x - scorefile.c' sed 's/^X//' > scorefile.c << '/' X/* X * scorefile.c: Rog-O-Matic XIV (CMU) Mon Jan 7 17:20:52 1985 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * This file contains the functions which update the rogomatic scorefile, X * which lives in /rgmscore. LOCKFILE is used to X * prevent simultaneous accesses to the file. rgmdelta X * contains new scores, and whenever the score file is printed the delta X * file is sorted and merged into the rgmscore file. X */ X X# include X# include X# include X# include "types.h" X# include "globals.h" X# include "install.h" X X# define LINESIZE 2048 X# define SCORE(s,p) (atoi (s+p)) X Xstatic char lokfil[100]; X X/* X * add_score: Write a new score line out to the correct rogomatic score X * file by creating a temporary copy and inserting the new line in the X * proper place. Be tense about preventing simultaneous access to the X * score file and catching interrupts and things. X */ X Xadd_score (new_line, version, noterm) Xchar *new_line, *version; Xint noterm; X{ X int wantscore = 1; X char ch; X char newfil[100]; X FILE *newlog; X X sprintf (lokfil, "%s %s", LOCKFILE, version); X sprintf (newfil, "%s/rgmdelta%s", RGMDIR, version); X X /* Defer interrupts while mucking with the score file */ X critical (); X X /* X * Lock the score file. If lock_file fails, asks the user whether he X * wishes to wait. If so, then try lock_file five times and then ask X * again. X */ X X while (lock_file (lokfil, MAXLOCK) == 0) X if (--wantscore < 1 && !noterm) X { printf ("The score file is busy, do you wish to wait? [y/n] "); X while ((ch = getchar ()) != 'y' && ch != 'n'); X if (ch == 'y') X wantscore = 5; X else X { uncritical (); return; } X } X X /* Now create a temporary to copy into */ X if ((newlog = wopen (newfil, "a")) == NULL) X { printf ("\nUnable to write %s\n", newfil); } X else X { fprintf (newlog, "%s\n", new_line); X fclose (newlog); X } X X /* Write the score to the end of the delta file */ X X /* Now close the file, relinquish control of scorefile, and exit */ X unlock_file (lokfil); X uncritical (); X} X X/* X * dumpscore: Print out the scoreboard. X */ X Xdumpscore (version) Xchar *version; X{ X char ch, scrfil[100], delfil[100], newfil[100], allfil[100], cmd[256]; X FILE *scoref, *deltaf; X int oldmask, intrupscore (); X X sprintf (lokfil, "%s %s", LOCKFILE, version); X sprintf (scrfil, "%s/rgmscore%s", RGMDIR, version); X sprintf (delfil, "%s/rgmdelta%s", RGMDIR, version); X sprintf (newfil, "%s/NewScore%s", RGMDIR, version); X sprintf (allfil, "%s/AllScore%s", RGMDIR, version); X X /* On interrupts we must relinquish control of the score file */ X int_exit (intrupscore); X X if (lock_file (lokfil, MAXLOCK) == 0) X { printf ("Score file busy.\n"); X exit (1); X } X X deltaf = fopen (delfil, "r"); X scoref = fopen (scrfil, "r"); X X /* If there are new scores, sort and merge them into the score file */ X if (deltaf != NULL) X { fclose (deltaf); X X /* Defer interrupts while mucking with the score file */ X critical (); X X /* Make certain any new files are world writeable */ X oldmask = umask (0); X X /* If we have an old file and a delta file, merge them */ X if (scoref != NULL) X { fclose (scoref); X sprintf (cmd, "sort +4nr -o %s %s; sort -m +4nr -o %s %s %s", X newfil, delfil, allfil, newfil, scrfil); X system (cmd); X if (filelength (allfil) != filelength (delfil) + filelength (scrfil)) X { fprintf (stderr, "Error, new file is wrong length!\n"); X unlink (newfil); unlink (allfil); X unlock_file (lokfil); X exit (1); X } X else X { /* New file is okay, unlink old files and pointer swap score file */ X unlink (delfil); unlink (newfil); X unlink (scrfil); link (allfil, scrfil); unlink (allfil); X } X scoref = fopen (scrfil, "r"); X } X else X /* Only have delta file, sort into scorefile and unlink delta */ X { sprintf (cmd, "sort +4nr -o %s %s", scrfil, delfil); X system (cmd); X unlink (delfil); X scoref = fopen (scrfil, "r"); X } X X /* Restore umask */ X umask (oldmask); X X /* Restore interrupt status after score file stable */ X uncritical (); X } X X /* Now any new scores have been put into scrfil, read it */ X if (scoref == NULL) X { printf ("Can't find %s\nBest score was %d.\n", scrfil, BEST); X unlock_file (lokfil); X exit (1); X } X X printf ("Rog-O-Matic Scores against version %s:\n\n", version); X printf ("%s%s", "Date User Gold Killed by", X " Lvl Hp Str Ac Exp\n\n"); X X while ((int) (ch = fgetc (scoref)) != EOF) X putchar (ch); X X fclose (scoref); X unlock_file (lokfil); X X exit (0); X} X X/* X * intrupscore: We have an interrupt, clean up and unlock the score file. X */ X Xintrupscore () X{ unlock_file (lokfil); X exit (1); X} X / echo 'x - stats.c' sed 's/^X//' > stats.c << '/' X/* X * stats.c: Rog-O-Matic XIV (CMU) Fri Dec 28 23:28:59 1984 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * A package for maintaining probabilities and statistics. X * X * Functions: X * X * A probability is a simple count of Bernoulli trials. X * X * clearprob: Clear a probability. X * addprob: Add success/failure to a probability. X * prob: Calculate p(success) of a statistic. X * parseprob: Parse a probability from a string. X * writeprob: Write a probability to a file. X * X * A statistic is a random variable with a mean and stdev. X * X * clearstat: Clear a statistic. X * addstat: Add a data point to a statistic. X * mean: Calculate the mean of a statistic. X * stdev: Calculate the std. dev. of a statistic. X * parsestat: Parse a statistic from a string. X * writestat: Write a statistic to a file. X */ X X# include X# include X# include "types.h" X X/* X * clearprob: zero a probability structure. X */ X Xclearprob (p) Xregister probability *p; X{ p->fail = p->win = 0; X} X X/* X * addprob: Add a data point to a probability X */ X Xaddprob (p, success) Xregister probability *p; Xregister int success; X{ X if (success) p->win++; X else p->fail++; X} X X/* X * prob: Calculate a probability X */ X Xdouble prob (p) Xregister probability *p; X{ register int trials = p->fail + p->win; X X if (trials < 1) return (0.0); X else return ((double) p->win / trials); X} X X/* X * parseprob: Parse a probability structure from buffer 'buf' X */ X Xparseprob (buf, p) Xregister char *buf; Xregister probability *p; X{ p->win = p->fail = 0; X sscanf (buf, "%d %d", &p->fail, &p->win); X} X X/* X * writeprob. Write the value of a probability structure to file 'f'. X */ X Xwriteprob (f, p) Xregister FILE *f; Xregister probability *p; X{ fprintf (f, "%d %d", p->fail, p->win); X} X X/* X * clearstat: zero a statistic structure. X */ X Xclearstat (s) Xregister statistic * s; X{ s->count = 0; X s->sum = s->sumsq = s->low = s->high = 0.0; X} X X/* X * addstat: Add a data point to a statistic X */ X Xaddstat (s, datum) Xregister statistic *s; Xregister int datum; X{ double d = (double) datum; X X s->count++; X s->sum += d; X s->sumsq += d*d; X X if (s->count < 2) s->low = s->high = d; X else if (d < s->low) s->low = d; X else if (d > s->high) s->high = d; X} X X/* X * mean: Return the mean of a statistic X */ X Xdouble mean (s) Xregister statistic *s; X{ X if (s->count < 1) return (0.0); X else return (s->sum / s->count); X} X X/* X * stdev: Return the standard deviation of a statistic X */ X Xdouble stdev (s) Xregister statistic *s; X{ register n = s->count; X X if (n < 2) return (0.0); X else return (sqrt ((n * s->sumsq - s->sum * s->sum) / (n * (n-1)))); X} X X/* X * parsestat: Parse a statistic structure from buffer 'buf' X */ X Xparsestat (buf, s) Xregister char *buf; Xregister statistic *s; X{ s->count = 0; X s->sum = s->sumsq = s->low = s->high = 0.0; X sscanf (buf, "%d %lf %lf %lf %lf", X &s->count, &s->sum, &s->sumsq, &s->low, &s->high); X} X X/* X * writestat. Write the value of a statistic structure to file 'f'. X */ X Xwritestat (f, s) Xregister FILE *f; Xregister statistic *s; X{ fprintf (f, "%d %lg %lg %lg %lg", X s->count, s->sum, s->sumsq, s->low, s->high); X} / echo 'x - titlepage.c' sed 's/^X//' > titlepage.c << '/' X/* X * titlepage.c: Rog-O-Matic XIV (CMU) Tue Jan 1 14:32:17 1985 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * This file contains the functions which display the animated copyright X * notice on the screen. A general movie facility is used to animate X * the screen. X */ X X# include X# include X# include "types.h" X# include "globals.h" X Xstatic char *titlepage[]={ X/* The static part of the display */ X" @ !@ \"@ #@ K@! @!$@!K@!P@\" @\"$@\"(@\")@\"*@\"/@\"0@\"1@\"6@\"7@\"8@", X"\"=@\"?@\"C@\"D@\"E@\"I@\"J@\"K@\"L@\"M@\"U@\"V@\"W@\"X@\"]@\"a@\"c@\"e@", X"\"i@# @#!@#\"@##@#'@#+@#.@#2@#5@#9@#<@#>@#@@#F@#K@#P@#T@#^@#`@#c@#e@#i@$", X" @$$@$'@$+@$.@$2@$5@$9@$<@$@@$C@$D@$E@$F@$K@$P@$T@$_@$c@$e@$i@% @%$@%'@%", X"+@%.@%2@%5@%9@%<@%@@%C@%F@%K@%P@%T@%^@%`@%c@%f@%h@& @&%@&(@&)@&*@&/@&0@&", X"1@&2@&6@&7@&8@&<@&@@&D@&E@&G@&L@&Q@&U@&V@&W@&X@&]@&a@&c@&g@'2@(.@(/@(0@(", X"1@);C)y)?r)@i)Ag)Bh)Ct)E()Fc)G))I1)J9)K8)L5)Nb)Oy*'A*(n*)d**r*+e*", X",w*.A*/p*0p*1e*2l*3,*5L*6e*7o*8n*9a*:r*;d*=H*>a*?m*@e*Ay*B,*DG*Eu*Fy*HJ*", X"Ia*Jc*Ko*Lb*Ms*No*On*P,*Ra*Sn*Td*VM*Wi*Xc*Yh*Za*[e*\\l*^M*_a*`u*al*bd*ci", X"*dn,)@,*@,+@,,@,[D,\\D,]D,^D,_D-(@-+@--@-[D-`D.(@.*@.-@.[D.`D/(@/*@/+@/,", X"@/-@/[D/`D0)@0*@0+@0,@0[D0\\D0]D0^D0_D2 H2!o2\"n2#o2$r2%a2&b2'l2(e2*m2+e", X"2,m2-b2.e2/r21o22f24t25h26e28F29i2:g2;h2r2?'2@s2BG2Cu2Di2El2Fd3 T", X"3!o3\"t3#a3$l3&w3'i3(n3)n3*e3+r3-a3.g3/a30i31n32s33t35R36o37g38u39e3;33<", X".3=63>,3@S3Ae3Bp3Ct3De3Em3Fb3Ge3Hr3J23K63L,3N13O93P83Q24 T4!o4\"t4#a4$l4", X"&w4'i4(n4)n4*e4+r4-a4.g4/a40i41n42s43t45R46o47g48u49e4;54<.4=24>,4@O4Ac4", X"Bt4Co4Db4Ee4Fr4H14I04J,4L14M94N84O35 T5!o5\"t5#a5$l5&w5'i5(n5)n5*e5+r5-a", X"5.g5/a50i51n52s53t55R56o57g58u59e5;55<.5=35>,5@F5Ae5Bb5Cr5Du5Ea5Fr5Gy5I1", X"5J65K,5M15N95O85P4", X X/* The dynamic part of the display */ X"~~~~~~~~~~00/~/1/~.2)~-1\\~,0\\~~~.3>~.4=~.5=~.6=~.7=~.8=~.9>~~~.2>.3=.8", X">.9 ~~~.1>.2=.7>.8 ~~~.0>.1=.6>.7 ~~~./>.0=.5>.6 ~~~..>./=.4>.5 ~~~~~~~~", X"~~~~~.. ./>.4 .4=.5>~./ .0>.5=.6>~.0 .1>.6=.7>~.1 .2>.7=.8>~.2).3>.8=.9>", X"~.3 .4>.9=.:>~.4 .5>.:=.;>~.5 .6>.;=.<>~.6 .7>.<=.=>~.7 .8>.==.>>~.8 .9>", X".>=.?>~.9 .:>.?=.@>~.: .;>.@=.A>~.; .<>.A=.B>~.< .=>.B=.C>~.= .>>.C=.D>~", X".> .?>.D=.E>~.? .@>.E=.F>~.@ .A>.F=.G>~.A .B>.G=.H>~.B .C>.H=.I>~.C .D>.", X"I=.J>~.D .E>.J=.K>~.E .F>.K=.L>~.F .G>.L=.M>~.G .H>.M=.N>~.H .I>.N=.O>~.", X"I .J>.O=.P>~.J .K>.P=.Q>~.K .L>.Q=.R>~.L .M>.R=.S>~.M .N>.S=.T>~.N .O>.T", X"=.U>~.O .P>.U=.V>~.P .Q>.V=.W>~.Q .R>.W=.X>~.R .S>.X=.Y>~.S .T>.Y=.Z>~.T", X" .U>.Z=.[>~.U .V>.[=.\\>~.V .W>.\\=.]>~.W .X>.]=.^>~.X .Y>.^=._>~.Y .Z>.", X"_=.`>~.Z .[>.`=.a>~.[ .\\>.a=.b>~.\\ .]>.b=.c>~.] .^>.c=.d>~.^ ._>.d=.e>", X"~._ .`>.e=.f>~.` .a>.f=.g>~.a .b>.g=.h>~.b .c>.h=.i>~.c .d>.i ~.d .e>~.e", X" .f>~.f .g>~.g .h>~.h ~~~~~.[D,[ ,\\j,\\ -\\D-]d-]D-^D-_D,_ ,^ ,] ,]j,] ", X"~-[ .ZD/ZD.[ .[L.[ .\\D.]S.]D.^D._D.`D/aD-\\ -\\L-\\ -] -^ -_ -` ~/YD.Z ", X"/\\D/]D/^D/_D.\\ .] .^ ._ .` 0`D0aD/a ~0XD0YD0ZD/Y /Z /` ~0VD0WD/[ /\\ /", X"^ /_ 0bD0cD/] 0UD0dD~~~~~~~~~~,0 ~~-1 ~~.2 ~~/1 ~~00 ~~~~~~~~~~~~~~~~~~~", X"~~.5S~.6t~.7u~.8p~.9i~.:d~.a~.?g~.@o~.An~.C!~.D!~.E!~~~~~~~~~~~", X"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.5 .6 .7 .8 .9 .: .; .", X"< .= .> .? .@ .A .B .C .D .E .F 6 ~~~~~~~~~~~~~~~~~~", XNULL}; X X# define NEXTCHAR (*cbf?*cbf++:(cbf=1+ *movie++)[-1]) X X/* X * animate: Display a movie on the screen. A movie is a list of strings X * wherein each character is either a bell command '}', a synchronize X * command '~', or a triplet indicating a character X * to be placed at a specific place on the screen. X * X * Movies run the same speed regardless of baudrate (if the baud rate X * greater than 2400). X */ X Xanimate (movie) Xchar *movie[]; X{ register int r, c, count = 0, delaychars = (baudrate () / 200); X register char *cbf = ""; X X if (emacs || terse) return; /* No screen ==> no movie */ X X clear (); /* Clear the screen */ X while (*movie || *cbf) /* While more animate commands */ X { r = NEXTCHAR; /* Get command character */ X X /* Ring the Bell */ X if (r == '}') putchar (ctrl('G')); X X /* Update the screen and delay until one timestep is gone */ X else if (r == '~') X { refresh (); /* Write out screen */ X for (; count < delaychars; count++) /* Pad with nulls */ X putchar (0); X count = 0; /* Reset char count */ X } X X /* Write out a single character and bump the character count */ X else X { r -= 32; /* Get screen row */ X c = NEXTCHAR - 32; /* Get screen col */ X mvaddch (r, c, NEXTCHAR); /* Write out character */ X if (count++ < 4) count += 4; /* Assume one cursor move */ X } X } X} X X/* X * halftimeshow: If its time for a halftime show, call movie. Variable X * 'nohalf' is true if the user does not want to see a halftime show. X */ X Xhalftimeshow (level) Xint level; X{ static int nextshow = 1; X X /* If terminal is too slow, dont bother */ X if (baudrate () < 1200) X return; X X if (!nohalf && level >= nextshow) X { if (nextshow == 1) X { nextshow = 9999; animate (titlepage); } X } X} / echo 'Part 10 of Rog-O-Matic XIV complete.' exit