|
|
1.1 ! root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ ! 2: /* hack.main.c - version 1.0.3 */ ! 3: ! 4: #include <stdio.h> ! 5: #include <signal.h> ! 6: #include "hack.h" ! 7: ! 8: #ifdef QUEST ! 9: #define gamename "quest" ! 10: #else ! 11: #define gamename "hack" ! 12: #endif QUEST ! 13: ! 14: extern char *getlogin(), *getenv(); ! 15: extern char plname[PL_NSIZ], pl_character[PL_CSIZ]; ! 16: extern struct permonst mons[CMNUM+2]; ! 17: extern char genocided[], fut_geno[]; ! 18: ! 19: int (*afternmv)(); ! 20: int (*occupation)(); ! 21: char *occtxt; /* defined when occupation != NULL */ ! 22: ! 23: int done1(); ! 24: int hangup(); ! 25: ! 26: int hackpid; /* current pid */ ! 27: int locknum; /* max num of players */ ! 28: #ifdef DEF_PAGER ! 29: char *catmore; /* default pager */ ! 30: #endif DEF_PAGER ! 31: char SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */ ! 32: char *hname; /* name of the game (argv[0] of call) */ ! 33: char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ ! 34: ! 35: extern char *nomovemsg; ! 36: extern long wailmsg; ! 37: ! 38: main(argc,argv) ! 39: int argc; ! 40: char *argv[]; ! 41: { ! 42: register int fd; ! 43: #ifdef CHDIR ! 44: register char *dir; ! 45: #endif CHDIR ! 46: ! 47: hname = argv[0]; ! 48: hackpid = getpid(); ! 49: ! 50: #ifdef CHDIR /* otherwise no chdir() */ ! 51: /* ! 52: * See if we must change directory to the playground. ! 53: * (Perhaps hack runs suid and playground is inaccessible ! 54: * for the player.) ! 55: * The environment variable HACKDIR is overridden by a ! 56: * -d command line option (must be the first option given) ! 57: */ ! 58: ! 59: dir = getenv("HACKDIR"); ! 60: if(argc > 1 && !strncmp(argv[1], "-d", 2)) { ! 61: argc--; ! 62: argv++; ! 63: dir = argv[0]+2; ! 64: if(*dir == '=' || *dir == ':') dir++; ! 65: if(!*dir && argc > 1) { ! 66: argc--; ! 67: argv++; ! 68: dir = argv[0]; ! 69: } ! 70: if(!*dir) ! 71: error("Flag -d must be followed by a directory name."); ! 72: } ! 73: #endif CHDIR ! 74: ! 75: /* ! 76: * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS ! 77: * 2. Use $USER or $LOGNAME (if 1. fails) ! 78: * 3. Use getlogin() (if 2. fails) ! 79: * The resulting name is overridden by command line options. ! 80: * If everything fails, or if the resulting name is some generic ! 81: * account like "games", "play", "player", "hack" then eventually ! 82: * we'll ask him. ! 83: * Note that we trust him here; it is possible to play under ! 84: * somebody else's name. ! 85: */ ! 86: { register char *s; ! 87: ! 88: initoptions(); ! 89: if(!*plname && (s = getenv("USER"))) ! 90: (void) strncpy(plname, s, sizeof(plname)-1); ! 91: if(!*plname && (s = getenv("LOGNAME"))) ! 92: (void) strncpy(plname, s, sizeof(plname)-1); ! 93: if(!*plname && (s = getlogin())) ! 94: (void) strncpy(plname, s, sizeof(plname)-1); ! 95: } ! 96: ! 97: /* ! 98: * Now we know the directory containing 'record' and ! 99: * may do a prscore(). ! 100: */ ! 101: if(argc > 1 && !strncmp(argv[1], "-s", 2)) { ! 102: #ifdef CHDIR ! 103: chdirx(dir,0); ! 104: #endif CHDIR ! 105: prscore(argc, argv); ! 106: exit(0); ! 107: } ! 108: ! 109: /* ! 110: * It seems he really wants to play. ! 111: * Remember tty modes, to be restored on exit. ! 112: */ ! 113: gettty(); ! 114: setbuf(stdout,obuf); ! 115: setrandom(); ! 116: startup(); ! 117: cls(); ! 118: u.uhp = 1; /* prevent RIP on early quits */ ! 119: u.ux = FAR; /* prevent nscr() */ ! 120: (void) signal(SIGHUP, hangup); ! 121: ! 122: /* ! 123: * Find the creation date of this game, ! 124: * so as to avoid restoring outdated savefiles. ! 125: */ ! 126: gethdate(hname); ! 127: ! 128: /* ! 129: * We cannot do chdir earlier, otherwise gethdate will fail. ! 130: */ ! 131: #ifdef CHDIR ! 132: chdirx(dir,1); ! 133: #endif CHDIR ! 134: ! 135: /* ! 136: * Process options. ! 137: */ ! 138: while(argc > 1 && argv[1][0] == '-'){ ! 139: argv++; ! 140: argc--; ! 141: switch(argv[0][1]){ ! 142: #ifdef WIZARD ! 143: case 'D': ! 144: /* if(!strcmp(getlogin(), WIZARD)) */ ! 145: wizard = TRUE; ! 146: /* else ! 147: printf("Sorry.\n"); */ ! 148: break; ! 149: #endif WIZARD ! 150: #ifdef NEWS ! 151: case 'n': ! 152: flags.nonews = TRUE; ! 153: break; ! 154: #endif NEWS ! 155: case 'u': ! 156: if(argv[0][2]) ! 157: (void) strncpy(plname, argv[0]+2, sizeof(plname)-1); ! 158: else if(argc > 1) { ! 159: argc--; ! 160: argv++; ! 161: (void) strncpy(plname, argv[0], sizeof(plname)-1); ! 162: } else ! 163: printf("Player name expected after -u\n"); ! 164: break; ! 165: default: ! 166: /* allow -T for Tourist, etc. */ ! 167: (void) strncpy(pl_character, argv[0]+1, ! 168: sizeof(pl_character)-1); ! 169: ! 170: /* printf("Unknown option: %s\n", *argv); */ ! 171: } ! 172: } ! 173: ! 174: if(argc > 1) ! 175: locknum = atoi(argv[1]); ! 176: #ifdef MAX_NR_OF_PLAYERS ! 177: if(!locknum || locknum > MAX_NR_OF_PLAYERS) ! 178: locknum = MAX_NR_OF_PLAYERS; ! 179: #endif MAX_NR_OF_PLAYERS ! 180: #ifdef DEF_PAGER ! 181: if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER"))) ! 182: catmore = DEF_PAGER; ! 183: #endif DEF_PAGER ! 184: #ifdef MAIL ! 185: getmailstatus(); ! 186: #endif MAIL ! 187: #ifdef WIZARD ! 188: if(wizard) (void) strcpy(plname, "wizard"); else ! 189: #endif WIZARD ! 190: if(!*plname || !strncmp(plname, "player", 4) ! 191: || !strncmp(plname, "games", 4)) ! 192: askname(); ! 193: plnamesuffix(); /* strip suffix from name; calls askname() */ ! 194: /* again if suffix was whole name */ ! 195: /* accepts any suffix */ ! 196: #ifdef WIZARD ! 197: if(!wizard) { ! 198: #endif WIZARD ! 199: /* ! 200: * check for multiple games under the same name ! 201: * (if !locknum) or check max nr of players (otherwise) ! 202: */ ! 203: (void) signal(SIGQUIT,SIG_IGN); ! 204: (void) signal(SIGINT,SIG_IGN); ! 205: if(!locknum) ! 206: (void) strcpy(lock,plname); ! 207: getlock(); /* sets lock if locknum != 0 */ ! 208: #ifdef WIZARD ! 209: } else { ! 210: register char *sfoo; ! 211: (void) strcpy(lock,plname); ! 212: if(sfoo = getenv("MAGIC")) ! 213: while(*sfoo) { ! 214: switch(*sfoo++) { ! 215: case 'n': (void) srandom(*sfoo++); ! 216: break; ! 217: } ! 218: } ! 219: if(sfoo = getenv("GENOCIDED")){ ! 220: if(*sfoo == '!'){ ! 221: register struct permonst *pm = mons; ! 222: register char *gp = genocided; ! 223: ! 224: while(pm < mons+CMNUM+2){ ! 225: if(!index(sfoo, pm->mlet)) ! 226: *gp++ = pm->mlet; ! 227: pm++; ! 228: } ! 229: *gp = 0; ! 230: } else ! 231: (void) strcpy(genocided, sfoo); ! 232: (void) strcpy(fut_geno, genocided); ! 233: } ! 234: } ! 235: #endif WIZARD ! 236: setftty(); ! 237: (void) sprintf(SAVEF, "save/%d%s", getuid(), plname); ! 238: regularize(SAVEF+5); /* avoid . or / in name */ ! 239: if((fd = open(SAVEF,0)) >= 0 && ! 240: (uptodate(fd) || unlink(SAVEF) == 666)) { ! 241: (void) signal(SIGINT,done1); ! 242: pline("Restoring old save file..."); ! 243: (void) fflush(stdout); ! 244: if(!dorecover(fd)) ! 245: goto not_recovered; ! 246: pline("Hello %s, welcome to %s!", plname, gamename); ! 247: flags.move = 0; ! 248: } else { ! 249: not_recovered: ! 250: fobj = fcobj = invent = 0; ! 251: fmon = fallen_down = 0; ! 252: ftrap = 0; ! 253: fgold = 0; ! 254: flags.ident = 1; ! 255: init_objects(); ! 256: u_init(); ! 257: ! 258: (void) signal(SIGINT,done1); ! 259: mklev(); ! 260: u.ux = xupstair; ! 261: u.uy = yupstair; ! 262: (void) inshop(); ! 263: setsee(); ! 264: flags.botlx = 1; ! 265: makedog(); ! 266: { register struct monst *mtmp; ! 267: if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp); /* riv05!a3 */ ! 268: } ! 269: seemons(); ! 270: #ifdef NEWS ! 271: if(flags.nonews || !readnews()) ! 272: /* after reading news we did docrt() already */ ! 273: #endif NEWS ! 274: docrt(); ! 275: ! 276: /* give welcome message before pickup messages */ ! 277: pline("Hello %s, welcome to %s!", plname, gamename); ! 278: ! 279: pickup(1); ! 280: read_engr_at(u.ux,u.uy); ! 281: flags.move = 1; ! 282: } ! 283: ! 284: flags.moonphase = phase_of_the_moon(); ! 285: if(flags.moonphase == FULL_MOON) { ! 286: pline("You are lucky! Full moon tonight."); ! 287: u.uluck++; ! 288: } else if(flags.moonphase == NEW_MOON) { ! 289: pline("Be careful! New moon tonight."); ! 290: } ! 291: ! 292: initrack(); ! 293: ! 294: for(;;) { ! 295: if(flags.move) { /* actual time passed */ ! 296: ! 297: settrack(); ! 298: ! 299: if(moves%2 == 0 || ! 300: (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { ! 301: extern struct monst *makemon(); ! 302: movemon(); ! 303: if(!rn2(70)) ! 304: (void) makemon((struct permonst *)0, 0, 0); ! 305: } ! 306: if(Glib) glibr(); ! 307: timeout(); ! 308: ++moves; ! 309: if(flags.time) flags.botl = 1; ! 310: if(u.uhp < 1) { ! 311: pline("You die..."); ! 312: done("died"); ! 313: } ! 314: if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){ ! 315: wailmsg = moves; ! 316: if(u.uhp == 1) ! 317: pline("You hear the wailing of the Banshee..."); ! 318: else ! 319: pline("You hear the howling of the CwnAnnwn..."); ! 320: } ! 321: if(u.uhp < u.uhpmax) { ! 322: if(u.ulevel > 9) { ! 323: if(Regeneration || !(moves%3)) { ! 324: flags.botl = 1; ! 325: u.uhp += rnd((int) u.ulevel-9); ! 326: if(u.uhp > u.uhpmax) ! 327: u.uhp = u.uhpmax; ! 328: } ! 329: } else if(Regeneration || ! 330: (!(moves%(22-u.ulevel*2)))) { ! 331: flags.botl = 1; ! 332: u.uhp++; ! 333: } ! 334: } ! 335: if(Teleportation && !rn2(85)) tele(); ! 336: if(Searching && multi >= 0) (void) dosearch(); ! 337: gethungry(); ! 338: invault(); ! 339: amulet(); ! 340: } ! 341: if(multi < 0) { ! 342: if(!++multi){ ! 343: pline(nomovemsg ? nomovemsg : ! 344: "You can move again."); ! 345: nomovemsg = 0; ! 346: if(afternmv) (*afternmv)(); ! 347: afternmv = 0; ! 348: } ! 349: } ! 350: ! 351: find_ac(); ! 352: #ifndef QUEST ! 353: if(!flags.mv || Blind) ! 354: #endif QUEST ! 355: { ! 356: seeobjs(); ! 357: seemons(); ! 358: nscr(); ! 359: } ! 360: if(flags.botl || flags.botlx) bot(); ! 361: ! 362: flags.move = 1; ! 363: ! 364: if(multi >= 0 && occupation) { ! 365: if(monster_nearby()) ! 366: stop_occupation(); ! 367: else if ((*occupation)() == 0) ! 368: occupation = 0; ! 369: continue; ! 370: } ! 371: ! 372: if(multi > 0) { ! 373: #ifdef QUEST ! 374: if(flags.run >= 4) finddir(); ! 375: #endif QUEST ! 376: lookaround(); ! 377: if(!multi) { /* lookaround may clear multi */ ! 378: flags.move = 0; ! 379: continue; ! 380: } ! 381: if(flags.mv) { ! 382: if(multi < COLNO && !--multi) ! 383: flags.mv = flags.run = 0; ! 384: domove(); ! 385: } else { ! 386: --multi; ! 387: rhack(save_cm); ! 388: } ! 389: } else if(multi == 0) { ! 390: #ifdef MAIL ! 391: ckmailstatus(); ! 392: #endif MAIL ! 393: rhack((char *) 0); ! 394: } ! 395: if(multi && multi%7 == 0) ! 396: (void) fflush(stdout); ! 397: } ! 398: } ! 399: ! 400: glo(foo) ! 401: register foo; ! 402: { ! 403: /* construct the string xlock.n */ ! 404: register char *tf; ! 405: ! 406: tf = lock; ! 407: while(*tf && *tf != '.') tf++; ! 408: (void) sprintf(tf, ".%d", foo); ! 409: } ! 410: ! 411: /* ! 412: * plname is filled either by an option (-u Player or -uPlayer) or ! 413: * explicitly (-w implies wizard) or by askname. ! 414: * It may still contain a suffix denoting pl_character. ! 415: */ ! 416: askname(){ ! 417: register int c,ct; ! 418: printf("\nWho are you? "); ! 419: (void) fflush(stdout); ! 420: ct = 0; ! 421: while((c = getchar()) != '\n'){ ! 422: if(c == EOF) error("End of input\n"); ! 423: /* some people get confused when their erase char is not ^H */ ! 424: if(c == '\010') { ! 425: if(ct) ct--; ! 426: continue; ! 427: } ! 428: if(c != '-') ! 429: if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_'; ! 430: if(ct < sizeof(plname)-1) plname[ct++] = c; ! 431: } ! 432: plname[ct] = 0; ! 433: if(ct == 0) askname(); ! 434: } ! 435: ! 436: /*VARARGS1*/ ! 437: impossible(s,x1,x2) ! 438: register char *s; ! 439: { ! 440: pline(s,x1,x2); ! 441: pline("Program in disorder - perhaps you'd better Quit."); ! 442: } ! 443: ! 444: #ifdef CHDIR ! 445: static ! 446: chdirx(dir, wr) ! 447: char *dir; ! 448: boolean wr; ! 449: { ! 450: ! 451: #ifdef SECURE ! 452: if(dir /* User specified directory? */ ! 453: #ifdef HACKDIR ! 454: && strcmp(dir, HACKDIR) /* and not the default? */ ! 455: #endif HACKDIR ! 456: ) { ! 457: (void) setuid(getuid()); /* Ron Wessels */ ! 458: (void) setgid(getgid()); ! 459: } ! 460: #endif SECURE ! 461: ! 462: #ifdef HACKDIR ! 463: if(dir == NULL) ! 464: dir = HACKDIR; ! 465: #endif HACKDIR ! 466: ! 467: if(dir && chdir(dir) < 0) { ! 468: perror(dir); ! 469: error("Cannot chdir to %s.", dir); ! 470: } ! 471: ! 472: /* warn the player if he cannot write the record file */ ! 473: /* perhaps we should also test whether . is writable */ ! 474: /* unfortunately the access systemcall is worthless */ ! 475: if(wr) { ! 476: register fd; ! 477: ! 478: if(dir == NULL) ! 479: dir = "."; ! 480: if((fd = open(RECORD, 2)) < 0) { ! 481: printf("Warning: cannot write %s/%s", dir, RECORD); ! 482: getret(); ! 483: } else ! 484: (void) close(fd); ! 485: } ! 486: } ! 487: #endif CHDIR ! 488: ! 489: stop_occupation() ! 490: { ! 491: if(occupation) { ! 492: pline("You stop %s.", occtxt); ! 493: occupation = 0; ! 494: } ! 495: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.