From: Keith Bostic Date: Sun, 27 Dec 1987 05:24:09 +0000 (-0800) Subject: date and time created 87/12/26 13:24:09 by bostic X-Git-Tag: BSD-4_3_Net_1-Snapshot-Development~2854 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/06e1630d42b7f36f082c72b268e13839f229a698 date and time created 87/12/26 13:24:09 by bostic SCCS-vsn: games/hack/hack.main.c 1.1 --- diff --git a/usr/src/games/hack/hack.main.c b/usr/src/games/hack/hack.main.c new file mode 100644 index 0000000000..d91ccbfe04 --- /dev/null +++ b/usr/src/games/hack/hack.main.c @@ -0,0 +1,495 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.main.c - version 1.0.3 */ + +#include +#include +#include "hack.h" + +#ifdef QUEST +#define gamename "quest" +#else +#define gamename "hack" +#endif QUEST + +extern char *getlogin(), *getenv(); +extern char plname[PL_NSIZ], pl_character[PL_CSIZ]; + +int (*afternmv)(); +int (*occupation)(); +char *occtxt; /* defined when occupation != NULL */ + +int done1(); +int hangup(); + +int hackpid; /* current pid */ +int locknum; /* max num of players */ +#ifdef DEF_PAGER +char *catmore; /* default pager */ +#endif DEF_PAGER +char SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */ +char *hname; /* name of the game (argv[0] of call) */ +char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ + +extern char *nomovemsg; +extern long wailmsg; + +main(argc,argv) +int argc; +char *argv[]; +{ + register int fd; +#ifdef CHDIR + register char *dir; +#endif CHDIR + + hname = argv[0]; + hackpid = getpid(); + +#ifdef CHDIR /* otherwise no chdir() */ + /* + * See if we must change directory to the playground. + * (Perhaps hack runs suid and playground is inaccessible + * for the player.) + * The environment variable HACKDIR is overridden by a + * -d command line option (must be the first option given) + */ + + dir = getenv("HACKDIR"); + if(argc > 1 && !strncmp(argv[1], "-d", 2)) { + argc--; + argv++; + dir = argv[0]+2; + if(*dir == '=' || *dir == ':') dir++; + if(!*dir && argc > 1) { + argc--; + argv++; + dir = argv[0]; + } + if(!*dir) + error("Flag -d must be followed by a directory name."); + } +#endif CHDIR + + /* + * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS + * 2. Use $USER or $LOGNAME (if 1. fails) + * 3. Use getlogin() (if 2. fails) + * The resulting name is overridden by command line options. + * If everything fails, or if the resulting name is some generic + * account like "games", "play", "player", "hack" then eventually + * we'll ask him. + * Note that we trust him here; it is possible to play under + * somebody else's name. + */ + { register char *s; + + initoptions(); + if(!*plname && (s = getenv("USER"))) + (void) strncpy(plname, s, sizeof(plname)-1); + if(!*plname && (s = getenv("LOGNAME"))) + (void) strncpy(plname, s, sizeof(plname)-1); + if(!*plname && (s = getlogin())) + (void) strncpy(plname, s, sizeof(plname)-1); + } + + /* + * Now we know the directory containing 'record' and + * may do a prscore(). + */ + if(argc > 1 && !strncmp(argv[1], "-s", 2)) { +#ifdef CHDIR + chdirx(dir,0); +#endif CHDIR + prscore(argc, argv); + exit(0); + } + + /* + * It seems he really wants to play. + * Remember tty modes, to be restored on exit. + */ + gettty(); + setbuf(stdout,obuf); + setrandom(); + startup(); + cls(); + u.uhp = 1; /* prevent RIP on early quits */ + u.ux = FAR; /* prevent nscr() */ + (void) signal(SIGHUP, hangup); + + /* + * Find the creation date of this game, + * so as to avoid restoring outdated savefiles. + */ + gethdate(hname); + + /* + * We cannot do chdir earlier, otherwise gethdate will fail. + */ +#ifdef CHDIR + chdirx(dir,1); +#endif CHDIR + + /* + * Process options. + */ + while(argc > 1 && argv[1][0] == '-'){ + argv++; + argc--; + switch(argv[0][1]){ +#ifdef WIZARD + case 'D': +/* if(!strcmp(getlogin(), WIZARD)) */ + wizard = TRUE; +/* else + printf("Sorry.\n"); */ + break; +#endif WIZARD +#ifdef NEWS + case 'n': + flags.nonews = TRUE; + break; +#endif NEWS + case 'u': + if(argv[0][2]) + (void) strncpy(plname, argv[0]+2, sizeof(plname)-1); + else if(argc > 1) { + argc--; + argv++; + (void) strncpy(plname, argv[0], sizeof(plname)-1); + } else + printf("Player name expected after -u\n"); + break; + default: + /* allow -T for Tourist, etc. */ + (void) strncpy(pl_character, argv[0]+1, + sizeof(pl_character)-1); + + /* printf("Unknown option: %s\n", *argv); */ + } + } + + if(argc > 1) + locknum = atoi(argv[1]); +#ifdef MAX_NR_OF_PLAYERS + if(!locknum || locknum > MAX_NR_OF_PLAYERS) + locknum = MAX_NR_OF_PLAYERS; +#endif MAX_NR_OF_PLAYERS +#ifdef DEF_PAGER + if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER"))) + catmore = DEF_PAGER; +#endif DEF_PAGER +#ifdef MAIL + getmailstatus(); +#endif MAIL +#ifdef WIZARD + if(wizard) (void) strcpy(plname, "wizard"); else +#endif WIZARD + if(!*plname || !strncmp(plname, "player", 4) + || !strncmp(plname, "games", 4)) + askname(); + plnamesuffix(); /* strip suffix from name; calls askname() */ + /* again if suffix was whole name */ + /* accepts any suffix */ +#ifdef WIZARD + if(!wizard) { +#endif WIZARD + /* + * check for multiple games under the same name + * (if !locknum) or check max nr of players (otherwise) + */ + (void) signal(SIGQUIT,SIG_IGN); + (void) signal(SIGINT,SIG_IGN); + if(!locknum) + (void) strcpy(lock,plname); + getlock(); /* sets lock if locknum != 0 */ +#ifdef WIZARD + } else { + register char *sfoo; + (void) strcpy(lock,plname); + if(sfoo = getenv("MAGIC")) + while(*sfoo) { + switch(*sfoo++) { + case 'n': (void) srandom(*sfoo++); + break; + } + } + if(sfoo = getenv("GENOCIDED")){ + if(*sfoo == '!'){ + extern struct permonst mons[CMNUM+2]; + extern char genocided[], fut_geno[]; + register struct permonst *pm = mons; + register char *gp = genocided; + + while(pm < mons+CMNUM+2){ + if(!index(sfoo, pm->mlet)) + *gp++ = pm->mlet; + pm++; + } + *gp = 0; + } else + (void) strcpy(genocided, sfoo); + (void) strcpy(fut_geno, genocided); + } + } +#endif WIZARD + setftty(); + (void) sprintf(SAVEF, "save/%d%s", getuid(), plname); + regularize(SAVEF+5); /* avoid . or / in name */ + if((fd = open(SAVEF,0)) >= 0 && + (uptodate(fd) || unlink(SAVEF) == 666)) { + (void) signal(SIGINT,done1); + pline("Restoring old save file..."); + (void) fflush(stdout); + if(!dorecover(fd)) + goto not_recovered; + pline("Hello %s, welcome to %s!", plname, gamename); + flags.move = 0; + } else { +not_recovered: + fobj = fcobj = invent = 0; + fmon = fallen_down = 0; + ftrap = 0; + fgold = 0; + flags.ident = 1; + init_objects(); + u_init(); + + (void) signal(SIGINT,done1); + mklev(); + u.ux = xupstair; + u.uy = yupstair; + (void) inshop(); + setsee(); + flags.botlx = 1; + makedog(); + { register struct monst *mtmp; + if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp); /* riv05!a3 */ + } + seemons(); +#ifdef NEWS + if(flags.nonews || !readnews()) + /* after reading news we did docrt() already */ +#endif NEWS + docrt(); + + /* give welcome message before pickup messages */ + pline("Hello %s, welcome to %s!", plname, gamename); + + pickup(1); + read_engr_at(u.ux,u.uy); + flags.move = 1; + } + + flags.moonphase = phase_of_the_moon(); + if(flags.moonphase == FULL_MOON) { + pline("You are lucky! Full moon tonight."); + u.uluck++; + } else if(flags.moonphase == NEW_MOON) { + pline("Be careful! New moon tonight."); + } + + initrack(); + + for(;;) { + if(flags.move) { /* actual time passed */ + + settrack(); + + if(moves%2 == 0 || + (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { + extern struct monst *makemon(); + movemon(); + if(!rn2(70)) + (void) makemon((struct permonst *)0, 0, 0); + } + if(Glib) glibr(); + timeout(); + ++moves; + if(flags.time) flags.botl = 1; + if(u.uhp < 1) { + pline("You die..."); + done("died"); + } + if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){ + wailmsg = moves; + if(u.uhp == 1) + pline("You hear the wailing of the Banshee..."); + else + pline("You hear the howling of the CwnAnnwn..."); + } + if(u.uhp < u.uhpmax) { + if(u.ulevel > 9) { + if(Regeneration || !(moves%3)) { + flags.botl = 1; + u.uhp += rnd((int) u.ulevel-9); + if(u.uhp > u.uhpmax) + u.uhp = u.uhpmax; + } + } else if(Regeneration || + (!(moves%(22-u.ulevel*2)))) { + flags.botl = 1; + u.uhp++; + } + } + if(Teleportation && !rn2(85)) tele(); + if(Searching && multi >= 0) (void) dosearch(); + gethungry(); + invault(); + amulet(); + } + if(multi < 0) { + if(!++multi){ + pline(nomovemsg ? nomovemsg : + "You can move again."); + nomovemsg = 0; + if(afternmv) (*afternmv)(); + afternmv = 0; + } + } + + find_ac(); +#ifndef QUEST + if(!flags.mv || Blind) +#endif QUEST + { + seeobjs(); + seemons(); + nscr(); + } + if(flags.botl || flags.botlx) bot(); + + flags.move = 1; + + if(multi >= 0 && occupation) { + if(monster_nearby()) + stop_occupation(); + else if ((*occupation)() == 0) + occupation = 0; + continue; + } + + if(multi > 0) { +#ifdef QUEST + if(flags.run >= 4) finddir(); +#endif QUEST + lookaround(); + if(!multi) { /* lookaround may clear multi */ + flags.move = 0; + continue; + } + if(flags.mv) { + if(multi < COLNO && !--multi) + flags.mv = flags.run = 0; + domove(); + } else { + --multi; + rhack(save_cm); + } + } else if(multi == 0) { +#ifdef MAIL + ckmailstatus(); +#endif MAIL + rhack((char *) 0); + } + if(multi && multi%7 == 0) + (void) fflush(stdout); + } +} + +glo(foo) +register foo; +{ + /* construct the string xlock.n */ + register char *tf; + + tf = lock; + while(*tf && *tf != '.') tf++; + (void) sprintf(tf, ".%d", foo); +} + +/* + * plname is filled either by an option (-u Player or -uPlayer) or + * explicitly (-w implies wizard) or by askname. + * It may still contain a suffix denoting pl_character. + */ +askname(){ +register int c,ct; + printf("\nWho are you? "); + (void) fflush(stdout); + ct = 0; + while((c = getchar()) != '\n'){ + if(c == EOF) error("End of input\n"); + /* some people get confused when their erase char is not ^H */ + if(c == '\010') { + if(ct) ct--; + continue; + } + if(c != '-') + if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_'; + if(ct < sizeof(plname)-1) plname[ct++] = c; + } + plname[ct] = 0; + if(ct == 0) askname(); +} + +/*VARARGS1*/ +impossible(s,x1,x2) +register char *s; +{ + pline(s,x1,x2); + pline("Program in disorder - perhaps you'd better Quit."); +} + +#ifdef CHDIR +static +chdirx(dir, wr) +char *dir; +boolean wr; +{ + +#ifdef SECURE + if(dir /* User specified directory? */ +#ifdef HACKDIR + && strcmp(dir, HACKDIR) /* and not the default? */ +#endif HACKDIR + ) { + (void) setuid(getuid()); /* Ron Wessels */ + (void) setgid(getgid()); + } +#endif SECURE + +#ifdef HACKDIR + if(dir == NULL) + dir = HACKDIR; +#endif HACKDIR + + if(dir && chdir(dir) < 0) { + perror(dir); + error("Cannot chdir to %s.", dir); + } + + /* warn the player if he cannot write the record file */ + /* perhaps we should also test whether . is writable */ + /* unfortunately the access systemcall is worthless */ + if(wr) { + register fd; + + if(dir == NULL) + dir = "."; + if((fd = open(RECORD, 2)) < 0) { + printf("Warning: cannot write %s/%s", dir, RECORD); + getret(); + } else + (void) close(fd); + } +} +#endif CHDIR + +stop_occupation() +{ + if(occupation) { + pline("You stop %s.", occtxt); + occupation = 0; + } +}