Annotation of early-roguelike/arogue5/main.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * Rogue
! 3: *
! 4: * Advanced Rogue
! 5: * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 6: * All rights reserved.
! 7: *
! 8: * Based on "Rogue: Exploring the Dungeons of Doom"
! 9: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 10: * All rights reserved.
! 11: *
! 12: * See the file LICENSE.TXT for full copyright and licensing information.
! 13: */
! 14:
! 15: #include "curses.h"
! 16: #include <stdlib.h>
! 17: #include <string.h>
! 18: #include <fcntl.h>
! 19: #include <sys/stat.h>
! 20: #include <limits.h>
! 21: #include <signal.h>
! 22: #include <time.h>
! 23: #include <errno.h>
! 24: #include "mach_dep.h"
! 25: #include "network.h"
! 26: #include "rogue.h"
! 27:
! 28: #ifdef CHECKTIME
! 29: static int num_checks; /* times we've gone over in checkout() */
! 30: #endif
! 31:
! 32: /*
! 33: * fruits that you get at startup
! 34: */
! 35: static char *funfruit[] = {
! 36: "candleberry", "caprifig", "dewberry", "elderberry",
! 37: "gooseberry", "guanabana", "hagberry", "ilama",
! 38: "imbu", "jaboticaba", "jujube", "litchi",
! 39: "mombin", "pitanga", "prickly pear", "rambutan",
! 40: "sapodilla", "soursop", "sweetsop", "whortleberry",
! 41: "jellybean", "apple", "strawberry", "blueberry",
! 42: "peach", "banana"
! 43: };
! 44: #define NFRUIT (sizeof(funfruit) / sizeof (char *))
! 45:
! 46: void open_records(void);
! 47: bool holiday(void);
! 48:
! 49: int
! 50: main(int argc, char *argv[], char *envp[])
! 51: {
! 52: register char *env;
! 53: char *roguedir;
! 54:
! 55: roguedir = md_getroguedir();
! 56: md_init();
! 57:
! 58: /*
! 59: * get home and options from environment
! 60: */
! 61: strncpy(home,md_gethomedir(),LINELEN);
! 62:
! 63: #ifdef SAVEDIR
! 64: if (argc >= 3 && !strcmp(argv[1], "-n")) {
! 65: use_savedir = TRUE;
! 66: strncpy(whoami, argv[2], LINELEN);
! 67: whoami[LINELEN - 1] = '\0';
! 68: if (snprintf(file_name, 256, "%s/%d-%s.ar5sav", SAVEDIR,
! 69: md_getuid(), whoami) >= 256)
! 70: {
! 71: /* The name is too long */
! 72: use_savedir = FALSE;
! 73: }
! 74: }
! 75: #endif
! 76: /* Get default save file */
! 77: if (!use_savedir) {
! 78: strcpy(file_name, home);
! 79: strcat(file_name, "arogue58.sav");
! 80: }
! 81:
! 82: #ifdef SCOREFILE
! 83: strncpy(score_file, SCOREFILE, LINELEN);
! 84: score_file[LINELEN - 1] = '\0';
! 85: #else
! 86: /* Get default score file */
! 87: strcpy(score_file, roguedir);
! 88:
! 89: if (*score_file)
! 90: strcat(score_file,"/");
! 91:
! 92: strcat(score_file, "arogue58.scr");
! 93: #endif
! 94:
! 95: if ((env = getenv("ROGUEOPTS")) != NULL)
! 96: parse_opts(env);
! 97:
! 98: if (!use_savedir && whoami[0] == '\0')
! 99: strucpy(whoami, md_getusername(), strlen(md_getusername()));
! 100:
! 101: if (env == NULL || fruit[0] == '\0') {
! 102: md_srand(md_random_seed());
! 103: strcpy(fruit, funfruit[rnd(NFRUIT)]);
! 104: }
! 105:
! 106: open_records();
! 107: if (!use_savedir)
! 108: md_normaluser();
! 109:
! 110: /*
! 111: * check for print-score option
! 112: */
! 113: if (argc == 2 && strcmp(argv[1], "-s") == 0)
! 114: {
! 115: waswizard = TRUE;
! 116: score(0, SCOREIT, 0);
! 117: exit(0);
! 118: }
! 119:
! 120: #ifdef NUMNET
! 121: /*
! 122: * Check for a network update
! 123: */
! 124: if (argc == 2 && strcmp(argv[1], "-u") == 0) {
! 125: int errcheck, errors = 0;
! 126: unsigned long amount;
! 127: short monster;
! 128:
! 129: /* Read in the amount and monster values to pass to score */
! 130: amount = netread(&errcheck, sizeof(unsigned long), stdin);
! 131: if (errcheck) errors++;
! 132:
! 133: monster = (short) netread(&errcheck, sizeof(short), stdin);
! 134: if (errcheck) errors++;
! 135:
! 136: /* Now do the update if there were no errors */
! 137: if (errors) exit(1);
! 138: else {
! 139: score(amount, UPDATE, monster);
! 140: exit(0);
! 141: }
! 142: }
! 143: #endif
! 144:
! 145: #ifdef WIZARD
! 146: /*
! 147: * Check to see if he is a wizard
! 148: */
! 149: if (argc >= 2 && argv[1][0] == '\0')
! 150: if (strcmp(PASSWD, md_crypt(md_getpass("Wizard's password: "), "Si")) == 0)
! 151: {
! 152: printf("Hail Mighty Wizard\n");
! 153: wizard = TRUE;
! 154: argv++;
! 155: argc--;
! 156: }
! 157: #endif
! 158:
! 159: #if MAXLOAD|MAXUSERS
! 160: if (too_much() && !wizard && !author())
! 161: {
! 162: printf("Sorry, %s, but the system is too loaded now.\n", whoami);
! 163: printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",
! 164: vowelstr(fruit), fruit);
! 165: exit(1);
! 166: }
! 167: #endif
! 168: if (use_savedir)
! 169: {
! 170: /* Try to restore from file_name first. */
! 171: if (!restore(file_name, envp))
! 172: exit(1);
! 173: /* If restore() returns true, there is no such saved game.
! 174: So start a new one. */
! 175: }
! 176: else if (argc == 2)
! 177: if (!restore(argv[1], envp)) /* Note: restore will never return */
! 178: exit(1);
! 179: dnum = (wizard && getenv("SEED") != NULL ?
! 180: atoi(getenv("SEED")) :
! 181: md_random_seed());
! 182: if (wizard)
! 183: printf("Hello %s, welcome to dungeon #%d\n", whoami, dnum);
! 184: else
! 185: printf("Hello %s, just a moment while I dig the dungeon...\n", whoami);
! 186: fflush(stdout);
! 187: seed = dnum;
! 188: md_srand(seed);
! 189:
! 190: init_things(); /* Set up probabilities of things */
! 191: init_colors(); /* Set up colors of potions */
! 192: init_stones(); /* Set up stone settings of rings */
! 193: init_materials(); /* Set up materials of wands */
! 194: initscr(); /* Start up cursor package */
! 195: init_names(); /* Set up names of scrolls */
! 196: init_misc(); /* Set up miscellaneous magic */
! 197: if (LINES < 24 || COLS < 80) {
! 198: printf("\nERROR: screen size to small for rogue\n");
! 199: byebye(-1);
! 200: }
! 201:
! 202: if (!use_savedir) {
! 203: if ((*whoami == '\0') || (strcmp(whoami,"dosuser")==0))
! 204: {
! 205: echo();
! 206: mvaddstr(23,2,"Rogue's Name? ");
! 207: wgetnstr(stdscr,whoami,LINELEN);
! 208: noecho();
! 209: }
! 210:
! 211: if (*whoami == '\0')
! 212: strcpy(whoami,"Rodney");
! 213: }
! 214:
! 215: setup();
! 216: /*
! 217: * Set up windows
! 218: */
! 219: cw = newwin(LINES, COLS, 0, 0);
! 220: mw = newwin(LINES, COLS, 0, 0);
! 221: hw = newwin(LINES, COLS, 0, 0);
! 222: msgw = newwin(4, COLS, 0, 0);
! 223: keypad(cw,1);
! 224: keypad(msgw,1);
! 225:
! 226: init_player(); /* Roll up the rogue */
! 227: waswizard = wizard;
! 228: new_level(NORMLEV); /* Draw current level */
! 229: /*
! 230: * Start up daemons and fuses
! 231: */
! 232: start_daemon(doctor, &player, AFTER);
! 233: fuse(swander, 0, WANDERTIME, AFTER);
! 234: start_daemon(stomach, 0, AFTER);
! 235: start_daemon(runners, 0, AFTER);
! 236: if (player.t_ctype == C_THIEF)
! 237: start_daemon(trap_look, 0, AFTER);
! 238:
! 239: /* Choose a quest item */
! 240: quest_item = rnd(MAXRELIC);
! 241: msg("You have been quested to retrieve the %s....",
! 242: rel_magic[quest_item].mi_name);
! 243: mpos = 0;
! 244: playit();
! 245: }
! 246:
! 247: void
! 248: reopen_score(void)
! 249: {
! 250: if (scoreboard != NULL)
! 251: fclose(scoreboard);
! 252: scoreboard = fopen(score_file, "r+");
! 253: if (scoreboard == NULL && errno == ENOENT) {
! 254: scoreboard = fopen(score_file, "w+");
! 255: }
! 256: }
! 257:
! 258:
! 259: void
! 260: open_records(void)
! 261: {
! 262: if (scoreboard == NULL)
! 263: reopen_score();
! 264: #ifdef LOGFILE
! 265: if (logfile == NULL)
! 266: logfile = fopen(LOGFILE, "a");
! 267: #endif
! 268: return;
! 269: }
! 270:
! 271: /*
! 272: * endit:
! 273: * Exit the program abnormally.
! 274: */
! 275: void
! 276: endit(int sig)
! 277: {
! 278: NOOP(sig);
! 279:
! 280: fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
! 281: }
! 282:
! 283: /*
! 284: * fatal:
! 285: * Exit the program, printing a message.
! 286: */
! 287:
! 288: void
! 289: fatal(char *s)
! 290: {
! 291: clear();
! 292: move(LINES-2, 0);
! 293: printw("%s", s);
! 294: draw(stdscr);
! 295: endwin();
! 296: printf("\n"); /* So the cursor doesn't stop at the end of the line */
! 297: exit(0);
! 298: }
! 299:
! 300: /*
! 301: * rnd:
! 302: * Pick a very random number.
! 303: */
! 304:
! 305: int
! 306: rnd(int range)
! 307: {
! 308: return(range == 0 ? 0 : md_rand() % range);
! 309: }
! 310:
! 311: /*
! 312: * roll:
! 313: * roll a number of dice
! 314: */
! 315:
! 316: int
! 317: roll(int number, int sides)
! 318: {
! 319: register int dtotal = 0;
! 320:
! 321: while(number--)
! 322: dtotal += rnd(sides)+1;
! 323: return dtotal;
! 324: }
! 325: # ifdef SIGTSTP
! 326: /*
! 327: * handle stop and start signals
! 328: */
! 329: void
! 330: tstp(int a)
! 331: {
! 332: mvcur(0, COLS - 1, LINES - 1, 0);
! 333: endwin();
! 334: fflush(stdout);
! 335: kill(0, SIGTSTP);
! 336: signal(SIGTSTP, tstp);
! 337: raw();
! 338: noecho();
! 339: keypad(cw,1);
! 340: clearok(curscr, TRUE);
! 341: touchwin(cw);
! 342: draw(cw);
! 343: md_flushinp();
! 344: }
! 345: # endif
! 346:
! 347: void
! 348: setup(void)
! 349: {
! 350: #ifdef CHECKTIME
! 351: void checkout();
! 352: #endif
! 353:
! 354: #ifndef DUMP
! 355: #ifdef SIGHUP
! 356: signal(SIGHUP, auto_save);
! 357: #endif
! 358: signal(SIGILL, bugkill);
! 359: #ifdef SIGTRAP
! 360: signal(SIGTRAP, bugkill);
! 361: #endif
! 362: #ifdef SIGIOT
! 363: signal(SIGIOT, bugkill);
! 364: #endif
! 365: #if 0
! 366: signal(SIGEMT, bugkill);
! 367: signal(SIGFPE, bugkill);
! 368: signal(SIGBUS, bugkill);
! 369: signal(SIGSEGV, bugkill);
! 370: signal(SIGSYS, bugkill);
! 371: signal(SIGPIPE, bugkill);
! 372: #endif
! 373: signal(SIGTERM, auto_save);
! 374: #endif
! 375:
! 376: signal(SIGINT, quit);
! 377: #ifndef DUMP
! 378: #ifdef SIGQUIT
! 379: signal(SIGQUIT, endit);
! 380: #endif
! 381: #endif
! 382: #ifdef SIGTSTP
! 383: signal(SIGTSTP, tstp);
! 384: #endif
! 385: #ifdef CHECKTIME
! 386: if (!author())
! 387: {
! 388: signal(SIGALRM, checkout);
! 389: alarm(CHECKTIME * 60);
! 390: num_checks = 0;
! 391: }
! 392: #endif
! 393: nonl();
! 394: crmode(); /* Cbreak mode */
! 395: noecho(); /* Echo off */
! 396: }
! 397:
! 398: /*
! 399: * playit:
! 400: * The main loop of the program. Loop until the game is over,
! 401: * refreshing things and looking at the proper times.
! 402: */
! 403:
! 404: void
! 405: playit(void)
! 406: {
! 407: register char *opts;
! 408:
! 409:
! 410: /*
! 411: * parse environment declaration of options
! 412: */
! 413: if ((opts = getenv("ROGUEOPTS")) != NULL)
! 414: parse_opts(opts);
! 415:
! 416:
! 417: player.t_oldpos = hero;
! 418: oldrp = roomin(&hero);
! 419: after = TRUE;
! 420: while (playing)
! 421: command(); /* Command execution */
! 422: endit(0);
! 423: }
! 424:
! 425: #if MAXLOAD|MAXUSERS
! 426: /*
! 427: * see if the system is being used too much for this game
! 428: */
! 429: bool
! 430: too_much(void)
! 431: {
! 432: #ifdef MAXLOAD
! 433: double avec[3];
! 434: #endif
! 435:
! 436: #ifdef MAXLOAD
! 437: loadav(avec);
! 438: return (avec[2] > (MAXLOAD / 10.0));
! 439: #else
! 440: return (ucount() > MAXUSERS);
! 441: #endif
! 442: }
! 443: #endif
! 444:
! 445: /*
! 446: * author:
! 447: * See if a user is an author of the program
! 448: */
! 449: bool
! 450: author(void)
! 451: {
! 452: switch (md_getuid()) {
! 453: #if AUTHOR
! 454: case AUTHOR:
! 455: #endif
! 456: case 0:
! 457: return TRUE;
! 458: default:
! 459: return FALSE;
! 460: }
! 461: }
! 462:
! 463:
! 464: #ifdef CHECKTIME
! 465: /*
! 466: * checkout()'s version of msg. If we are in the middle of a shell, do a
! 467: * printf instead of a msg to avoid the refresh.
! 468: */
! 469: void
! 470: chmsg(char *fmt, int arg)
! 471: {
! 472: if (in_shell) {
! 473: printf(fmt, arg);
! 474: putchar('\n');
! 475: fflush(stdout);
! 476: }
! 477: else
! 478: msg(fmt, arg);
! 479: }
! 480:
! 481: void
! 482: checkout(void)
! 483: {
! 484: static char *msgs[] = {
! 485: "The system is too loaded for games. Please leave in %d minutes",
! 486: "Please save your game. You have %d minutes",
! 487: "This is your last chance. You had better leave in %d minutes",
! 488: };
! 489: int checktime;
! 490:
! 491: signal(SIGALRM, checkout);
! 492: if (!holiday() && !author()) {
! 493: wclear(cw);
! 494: mvwaddstr(cw, LINES / 2, 0,
! 495: "Game time is over. Your game is being saved.\n\n");
! 496: draw(cw);
! 497: auto_save(); /* NO RETURN */
! 498: }
! 499: if (too_much()) {
! 500: if (num_checks >= 3)
! 501: fatal("You didn't listen, so now you are DEAD !!\n");
! 502: checktime = CHECKTIME / (num_checks + 1);
! 503: chmsg(msgs[num_checks++], checktime);
! 504: alarm(checktime * 60);
! 505: }
! 506: else {
! 507: if (num_checks) {
! 508: chmsg("The load has dropped. You have a reprieve.");
! 509: num_checks = 0;
! 510: }
! 511: alarm(CHECKTIME * 60);
! 512: }
! 513: }
! 514: #endif
! 515:
! 516: #ifdef LOADAV
! 517:
! 518: #include <nlist.h>
! 519:
! 520: struct nlist avenrun =
! 521: {
! 522: "_avenrun"
! 523: };
! 524:
! 525: void
! 526: loadav(double *avg)
! 527: {
! 528: reg int kmem;
! 529:
! 530: if ((kmem = open("/dev/kmem", 0)) < 0)
! 531: goto bad;
! 532: nlist(NAMELIST, &avenrun);
! 533: if (avenrun.n_type == 0) {
! 534: bad:
! 535: avg[0] = avg[1] = avg[2] = 0.0;
! 536: return;
! 537: }
! 538: lseek(kmem, (long) avenrun.n_value, 0);
! 539: read(kmem, avg, 3 * sizeof (double));
! 540: }
! 541: #endif
! 542:
! 543: #ifdef UCOUNT
! 544: /*
! 545: * ucount:
! 546: * Count the number of people on the system
! 547: */
! 548: #include <sys/types.h>
! 549: #include <utmp.h>
! 550: struct utmp buf;
! 551: int
! 552: ucount(void)
! 553: {
! 554: reg struct utmp *up;
! 555: reg FILE *utmp;
! 556: reg int count;
! 557:
! 558: if ((utmp = fopen(UTMP, "r")) == NULL)
! 559: return 0;
! 560:
! 561: up = &buf;
! 562: count = 0;
! 563: while (fread(up, 1, sizeof (*up), utmp) > 0)
! 564: if (buf.ut_type == USER_PROCESS)
! 565: count++;
! 566: fclose(utmp);
! 567: return count;
! 568: }
! 569: #endif
! 570:
! 571: /*
! 572: * holiday:
! 573: * Returns TRUE when it is a good time to play rogue
! 574: */
! 575: bool
! 576: holiday(void)
! 577: {
! 578: time_t now;
! 579: struct tm *localtime();
! 580: reg struct tm *ntime;
! 581:
! 582: time(&now); /* get the current time */
! 583: ntime = localtime(&now);
! 584: if(ntime->tm_wday == 0 || ntime->tm_wday == 6)
! 585: return TRUE; /* OK on Sat & Sun */
! 586: if(ntime->tm_hour < 8 || ntime->tm_hour >= 17)
! 587: return TRUE; /* OK before 8AM & after 5PM */
! 588: if(ntime->tm_yday <= 7 || ntime->tm_yday >= 350)
! 589: return TRUE; /* OK during Christmas */
! 590: #if 0 /* not for now */
! 591: if (access("/usr/tmp/.ryes",0) == 0)
! 592: return TRUE; /* if author permission */
! 593: #endif
! 594:
! 595: return FALSE; /* All other times are bad */
! 596: }
CVSweb