/* * Rogue * Exploring the dungeons of doom * Copyright (C) 1980 by Michael Toy and Glenn Wichman * All rights reserved * * @(#)main.c 3.27 (Berkeley) 6/15/81 */ #include <curses.h> #include <signal.h> #include <pwd.h> #include "mach_dep.h" #include "rogue.h" #ifdef CHECKTIME static int num_checks; /* times we've gone over in checkout() */ #endif char _sobuf[BUFSIZ]; main(argc, argv, envp) char **argv; char **envp; { register char *env; register struct passwd *pw; register struct linked_list *item; register struct object *obj; struct passwd *getpwuid(); char *getpass(), *crypt(); int quit(), lowtime; long now; setbuf (stdout, _sobuf); /* * check for print-score option */ if (argc == 2 && strcmp(argv[1], "-s") == 0) { waswizard = TRUE; score(0, -1); exit(0); } /* * Allow nondeterministic cheating */ if (argc >= 2 && strcmp(argv[1], "-c") == 0) { cheating = TRUE; argv++; argc--; } /* * Check to see if he is a wizard */ if (argc >= 2 && argv[1][0] == '\0') if (strcmp(PASSWD, crypt(getpass("Wizard's password: "), "C4")) == 0) { wizard = TRUE; argv++; argc--; } /* * get home and options from environment */ if ((env = getenv("HOME")) != NULL) strcpy(home, env); else if ((pw = getpwuid(getuid())) != NULL) strcpy(home, pw->pw_dir); else home[0] = '\0'; strcat(home, "/"); strcpy(file_name, home); strcat(file_name, "rogue.save"); if ((env = getenv("ROGUEOPTS")) != NULL) parse_opts(env); if (env == NULL || whoami[0] == '\0') if ((pw = getpwuid(getuid())) == NULL) { printf("Say, who the hell are you?\n"); exit(1); } else strucpy(whoami, pw->pw_name, strlen(pw->pw_name)); if (env == NULL || fruit[0] == '\0') strcpy(fruit, "slime-mold"); #if MAXLOAD|MAXUSERS if (too_much() && !wizard && !author()) { printf("Sorry, %s, but the system is too loaded now.\n", whoami); printf("Try again later. Meanwhile, why not enjoy a%s %s?\n", vowelstr(fruit), fruit); exit(1); } #endif if (argc == 2) if (!restore(argv[1], envp)) /* Note: restore will never return */ exit(1); time(&now); lowtime = (int) now; dnum = (wizard && getenv("SEED") != NULL ? atoi(getenv("SEED")) : lowtime + getpid()); if (wizard) printf("Hello %s, welcome to dungeon #%d", whoami, dnum); else printf("Hello %s, just a moment while I dig the dungeon...", whoami); fflush(stdout); seed = dnum; init_player(); /* Roll up the rogue */ init_things(); /* Set up probabilities of things */ init_names(); /* Set up names of scrolls */ init_colors(); /* Set up colors of potions */ init_stones(); /* Set up stone settings of rings */ init_materials(); /* Set up materials of wands */ initscr(); /* Start up cursor package */ setup(); /* * Set up windows */ cw = newwin(LINES, COLS, 0, 0); mw = newwin(LINES, COLS, 0, 0); hw = newwin(LINES, COLS, 0, 0); waswizard = wizard; new_level(); /* Draw current level */ /* * Start up daemons and fuses */ daemon(doctor, 0, AFTER); fuse(swander, 0, WANDERTIME, AFTER); daemon(stomach, 0, AFTER); daemon(runners, 0, AFTER); /* * Give the rogue his weaponry. First a mace. */ item = new_item(sizeof *obj); obj = (struct object *) ldata(item); obj->o_type = WEAPON; obj->o_which = MACE; init_weapon(obj, MACE); obj->o_hplus = 1; obj->o_dplus = 1; obj->o_flags |= ISKNOW; add_pack(item, TRUE); cur_weapon = obj; /* * Now a +1 bow */ item = new_item(sizeof *obj); obj = (struct object *) ldata(item); obj->o_type = WEAPON; obj->o_which = BOW; init_weapon(obj, BOW); obj->o_hplus = 1; obj->o_dplus = 0; obj->o_flags |= ISKNOW; add_pack(item, TRUE); /* * Now some arrows */ item = new_item(sizeof *obj); obj = (struct object *) ldata(item); obj->o_type = WEAPON; obj->o_which = ARROW; init_weapon(obj, ARROW); obj->o_count = 25+rnd(15); obj->o_hplus = obj->o_dplus = 0; obj->o_flags |= ISKNOW; add_pack(item, TRUE); /* * And his suit of armor */ item = new_item(sizeof *obj); obj = (struct object *) ldata(item); obj->o_type = ARMOR; obj->o_which = RING_MAIL; obj->o_ac = a_class[RING_MAIL] - 1; obj->o_flags |= ISKNOW; cur_armor = obj; add_pack(item, TRUE); /* * Give him some food too */ item = new_item(sizeof *obj); obj = (struct object *) ldata(item); obj->o_type = FOOD; obj->o_count = 1; obj->o_which = 0; add_pack(item, TRUE); playit(); } /* * endit: * Exit the program abnormally. */ endit() { fatal("Ok, if you want to exit that badly, I'll have to allow it\n"); } /* * fatal: * Exit the program, printing a message. */ fatal(s) char *s; { clear(); move(LINES-2, 0); printw("%s", s); draw(stdscr); endwin(); exit(0); } /* * rnd: * Pick a very random number. */ rnd(range) register int range; { return range == 0 ? 0 : abs(RN) % range; } /* * roll: * roll a number of dice */ roll(number, sides) register int number, sides; { register int dtotal = 0; while(number--) dtotal += rnd(sides)+1; return dtotal; } # ifdef SIGTSTP /* * handle stop and start signals */ tstp() { mvcur(0, COLS - 1, LINES - 1, 0); endwin(); fflush(stdout); kill(0, SIGTSTP); signal(SIGTSTP, tstp); crmode(); noecho(); clearok(curscr, TRUE); touchwin(cw); draw(cw); raw(); /* flush input */ noraw(); } # endif setup() { #ifdef CHECKTIME int checkout(); #endif #ifndef DUMP signal(SIGHUP, auto_save); signal(SIGILL, auto_save); signal(SIGTRAP, auto_save); signal(SIGIOT, auto_save); signal(SIGEMT, auto_save); signal(SIGFPE, auto_save); signal(SIGBUS, auto_save); signal(SIGSEGV, auto_save); signal(SIGSYS, auto_save); signal(SIGPIPE, auto_save); signal(SIGTERM, auto_save); #endif signal(SIGINT, quit); #ifndef DUMP signal(SIGQUIT, endit); #endif #ifdef SIGTSTP signal(SIGTSTP, tstp); #endif #ifdef CHECKTIME if (!author()) { signal(SIGALRM, checkout); alarm(CHECKTIME * 60); num_checks = 0; } #endif crmode(); /* Cbreak mode */ noecho(); /* Echo off */ } /* * playit: * The main loop of the program. Loop until the game is over, * refreshing things and looking at the proper times. */ playit() { register char *opts; /* * set up defaults for slow terminals */ #if USG==1 if ((_tty.c_cflag & CBAUD) < B1200) #else if (_tty.sg_ospeed < B1200) #endif { terse = TRUE; jump = TRUE; } /* * parse environment declaration of options */ if ((opts = getenv("ROGUEOPTS")) != NULL) parse_opts(opts); oldpos = hero; oldrp = roomin(&hero); while (playing) command(); /* Command execution */ endit(); } #if MAXLOAD|MAXUSERS /* * see if the system is being used too much for this game */ too_much() { #ifdef MAXLOAD double avec[3]; #else register int cnt; #endif #ifdef MAXLOAD loadav(avec); return (avec[2] > (MAXLOAD / 10.0)); #else return (ucount() > MAXUSERS); #endif } /* * see if a user is an author of the program */ author() { switch (getuid()) { case 24601: return TRUE; default: return FALSE; } } #endif #ifdef CHECKTIME checkout() { static char *msgs[] = { "The load is too high to be playing. Please leave in %d minutes", "Please save your game. You have %d minutes", "Last warning. You have %d minutes to leave", }; int checktime; signal(SIGALRM, checkout); if (too_much()) { if (num_checks == 3) fatal("Sorry. You took to long. You are dead\n"); checktime = CHECKTIME / (num_checks + 1); chmsg(msgs[num_checks++], checktime); alarm(checktime * 60); } else { if (num_checks) { chmsg("The load has dropped back down. You have a reprieve."); num_checks = 0; } alarm(CHECKTIME * 60); } } /* * checkout()'s version of msg. If we are in the middle of a shell, do a * printf instead of a msg to avoid the refresh. */ chmsg(fmt, arg) char *fmt; int arg; { if (in_shell) { printf(fmt, arg); putchar('\n'); fflush(stdout); } else msg(fmt, arg); } #endif #ifdef LOADAV #include <nlist.h> struct nlist avenrun = { "_avenrun" }; loadav(avg) register double *avg; { register int kmem; if ((kmem = open("/dev/kmem", 0)) < 0) goto bad; nlist(NAMELIST, &avenrun); if (avenrun.n_type == 0) { bad: avg[0] = avg[1] = avg[2] = 0.0; return; } lseek(kmem, (long) avenrun.n_value, 0); read(kmem, avg, 3 * sizeof (double)); } #endif #ifdef UCOUNT #include <utmp.h> struct utmp buf; ucount() { register struct utmp *up; register FILE *utmp; register int count; if ((utmp = fopen(UTMP, "r")) == NULL) return 0; up = &buf; count = 0; while (fread(up, 1, sizeof (*up), utmp) > 0) if (buf.ut_name[0] != '\0') count++; fclose(utmp); return count; } #endif