Mercurial > hg > early-roguelike
view arogue7/main.c @ 171:80c060734f51
arogue7: fix messages from detection potions.
Another fix for overwritten messages, this time for potions of monster
detection and magic detection.
I've made the message appear before the display of information, which
may be closer to the originally intended behavior.
author | John "Elwin" Edwards |
---|---|
date | Thu, 02 Jul 2015 16:27:39 -0400 |
parents | cadff8f047a1 |
children | f9ef86cf22b2 |
line wrap: on
line source
/* * main.c - setup code * * Advanced Rogue * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T * All rights reserved. * * Based on "Rogue: Exploring the Dungeons of Doom" * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman * All rights reserved. * * See the file LICENSE.TXT for full copyright and licensing information. */ #include "curses.h" #include <stdlib.h> #include <string.h> #include <signal.h> #ifdef BSD #include <sys/time.h> #else #include <time.h> #endif #include "mach_dep.h" #include "network.h" #include "rogue.h" #ifdef PC7300 #include "sys/window.h" #include <ctype.h> extern struct uwdata wdata, oldwin; extern char oldtext[WTXTNUM][WTXTLEN]; #endif void open_records(void); main(argc, argv, envp) char **argv; char **envp; { register char *env; int lowtime; time_t now; #ifdef PC7300 int hardwindow; /* Do we have a hardware window? */ #endif md_init(); /* * get home and options from environment */ strncpy(home, md_gethomedir(), LINELEN); /* Get default save file */ strcpy(file_name, home); strcat(file_name, "arogue77.sav"); /* Get default score file */ #ifdef SCOREFILE strncpy(score_file, SCOREFILE, LINELEN); score_file[LINELEN-1] = '\0'; #else strcpy(score_file, md_getroguedir()); if (*score_file) strcat(score_file,"/"); strcat(score_file,"arogue77.scr"); #endif #ifdef SAVEDIR /* Check for common save location */ if (argc >= 3 && strcmp(argv[1], "-n") == 0) { strncpy(whoami, argv[2], 79); whoami[79] = '\0'; use_savedir = TRUE; if (LINELEN <= snprintf(file_name, LINELEN, "%s/%d-%s.ar7sav", SAVEDIR, md_getuid(), whoami)) { strcpy(file_name, "xrogue.sav"); use_savedir = FALSE; } } #endif if ((env = getenv("ROGUEOPTS")) != NULL) parse_opts(env); if (whoami[0] == '\0') strucpy(whoami, md_getusername(), strlen(md_getusername())); open_records(); /* * check for print-score option */ if (argc == 2 && strcmp(argv[1], "-s") == 0) { waswizard = TRUE; score(0, SCOREIT, 0); exit(0); } #ifdef NUMNET /* * Check for a network update */ if (argc == 2 && strcmp(argv[1], "-u") == 0) { unsigned long netread(); int errcheck, errors = 0; unsigned long amount; short monster; /* Read in the amount and monster values to pass to score */ amount = netread(&errcheck, sizeof(unsigned long), stdin); if (errcheck) errors++; monster = (short) netread(&errcheck, sizeof(short), stdin); if (errcheck) errors++; /* Now do the update if there were no errors */ if (errors) exit(1); else { score(amount, UPDATE, monster); exit(0); } } #endif #ifdef WIZARD /* * Check to see if he is a wizard */ if (argc >= 2 && argv[1][0] == '\0') if (strcmp(PASSWD, md_crypt(md_getpass("Wizard's password: "), "mT")) == 0) { wizard = TRUE; argv++; argc--; } #endif if (!wizard && !author() && !holiday()) { printf("Sorry, %s, but you can't play during working hours.\n", whoami); printf("Try again later.\n"); exit(1); } if (!wizard && !author() && too_much()) { printf("Sorry, %s, but the system is too loaded now.\n", whoami); printf("Try again later.\n"); exit(1); } #if NICE if (!wizard) nice(19); /* nice the max amount */ #endif if (use_savedir) { if (!restore(file_name, envp)) exit(1); } else { md_normaluser(); } if (argc == 2) if (!restore(argv[1], envp)) /* Note: restore will never return */ exit(1); lowtime = (int) time(&now); dnum = (wizard && getenv("SEED") != NULL ? atoi(getenv("SEED")) : lowtime + getpid()); if (wizard) printf("Hello %s, welcome to dungeon #%d\n", whoami, dnum); else printf("Hello %s, just a moment while I dig the dungeon...\n", whoami); fflush(stdout); seed = dnum; md_srand(seed); #ifdef PC7300 /* Store static window parameters */ hardwindow = ioctl(0, WIOCGETD, &wdata); if (hardwindow >= 0) { /* We have a hardware window */ extern char **environ; /* Make sure our window is the right size */ oldwin = wdata; if ((wdata.uw_height / wdata.uw_vs) < 23 || (wdata.uw_width / wdata.uw_hs) < 75) { wdata.uw_width = 80 * wdata.uw_hs; wdata.uw_height = 24 * wdata.uw_vs; wdata.uw_x = 0; wdata.uw_y = wdata.uw_vs; wdata.uw_uflags = NBORDER; /* Make the change */ if (ioctl(1, WIOCSETD, &wdata) >= 0 && environ) { char **eptr, *tptr, *nptr, *newenv, *lptr = 0, *cptr = 0; int i, nlines = -1, ncols = -1, nlindig = 0, ncoldig = 0; struct utdata labelbuf; /* Save and change window-associated text */ for (i=0; i<WTXTNUM; i++) { labelbuf.ut_num = i; ioctl(1, WIOCGETTEXT, &labelbuf); strncpy(oldtext[i], labelbuf.ut_text, WTXTLEN - 1); if (*labelbuf.ut_text) { *labelbuf.ut_text = '\0'; ioctl(1, WIOCSETTEXT, &labelbuf); } } labelbuf.ut_num = WTXTLABEL; strcpy(labelbuf.ut_text, "Advanced Rogue"); ioctl(1, WIOCSETTEXT, &labelbuf); /* We have to change the TERMCAP entry */ eptr = environ; while (*eptr) { if (strncmp(*eptr, "TERMCAP=", 8) == 0) break; else eptr++; } /* We found a TERMCAP entry */ if (*eptr) { /* Search for li# and co# */ tptr = *eptr; while (*tptr) { switch (*tptr) { case 'l': if (nlines == -1 && strncmp(tptr, "li#", 3) == 0) { tptr += 3; lptr = tptr; lines = atoi(tptr); while (isdigit(*tptr)) { nlindig++;; tptr++; } } else tptr++; break; case 'c': if (ncols == -1 && strncmp(tptr, "co#", 3) == 0) { tptr += 3; cptr = tptr; cols = atoi(tptr); while (isdigit(*tptr)) { ncoldig++; tptr++; } } else tptr++; break; default: tptr++; } } /* Change the entry */ if (ncoldig != 2 || nlindig != 2) { int length; /* Add in difference in num lengths plus NULL */ length = strlen(*eptr) - ncoldig - nlindig + 5; if (ncoldig == 0) length += 4; /* For :co# */ if (nlindig == 0) length += 4; /* For :li# */ newenv = malloc(length); tptr = *eptr; nptr = newenv; if (nlindig == 0 || ncoldig == 0) { /* Copy up to the first : */ while (*tptr && *tptr != ':') *nptr++ = *tptr++; /* Do we have to add a field? */ if (nlindig == 0) { strcpy(nptr, ":li#24"); nptr += 6; } if (ncoldig == 0) { strcpy(nptr, ":co#80"); nptr += 6; } } while (*tptr) { if (tptr == lptr) { strcpy(nptr, "24"); nptr += 2; tptr += nlindig; } else if (tptr == cptr) { strcpy(nptr, "80"); nptr += 2; tptr += ncoldig; } else *nptr++ = *tptr++; } *nptr = '\0'; /* Replace the old one */ free(*eptr); *eptr = newenv; } else { /* Just overwrite the old numbers */ *lptr++ = '2'; *lptr = '4'; *cptr++ = '8'; *cptr = '0'; } } } } } #endif init_things(); /* Set up probabilities of things */ 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 */ init_names(); /* Set up names of scrolls */ init_misc(); /* Set up miscellaneous magic */ init_foods(); /* set up the food table */ cols = COLS; lines = LINES; if (cols > 85) cols = 85; if (lines > 24) lines = 24; if (lines < 23 || cols < 75) { /* give player a break if larger font used */ printf("\nERROR: screen size too small for rogue\n"); byebye(0); } /* * Now that we have cols and lines, we can update our window * structure for non-hardware windows. */ #ifdef PC7300 if (hardwindow < 0) { wdata.uw_x = 0; wdata.uw_y = 0; wdata.uw_width = COLS; wdata.uw_height = LINES; wdata.uw_uflags = 0; wdata.uw_hs = 1; wdata.uw_vs = 1; wdata.uw_baseline = 0; } #endif setup(); /* * Set up windows */ cw = newwin(lines, cols, 0, 0); mw = newwin(lines, cols, 0, 0); hw = newwin(lines, cols, 0, 0); msgw = newwin(4, cols, 0, 0); keypad(cw,TRUE); keypad(msgw,TRUE); init_player(); /* Roll up the rogue */ waswizard = wizard; #ifdef WIZARD /* A super wizard doesn't have to get equipped */ if (wizard && strcmp(getenv("SUPER"),"YES") == 0) { level = 1; new_level(NORMLEV); } else #endif new_level(STARTLEV); /* Draw current level */ /* * Start up daemons and fuses */ start_daemon(doctor, &player, AFTER); fuse(swander, 0, WANDERTIME, AFTER); if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER) fuse(spell_recovery, 0, SPELLTIME, AFTER); if (player.t_ctype == C_DRUID || player.t_ctype == C_RANGER) fuse(chant_recovery, 0, SPELLTIME, AFTER); if (player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN) fuse(prayer_recovery, 0, SPELLTIME, AFTER); start_daemon(stomach, 0, AFTER); if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASIN || player.t_ctype == C_MONK) start_daemon(trap_look, 0, AFTER); /* Does this character have any special knowledge? */ switch (player.t_ctype) { case C_ASSASIN: /* Assassins automatically recognize poison */ p_know[P_POISON] = TRUE; } /* Choose a quest item */ quest_item = rnd(MAXRELIC); draw(cw); msg("You have been quested to retrieve the %s....", rel_magic[quest_item].mi_name); mpos = 0; playit(); } /* * endit: * Exit the program abnormally. */ void endit(sig) int sig; { 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(); #ifdef PC7300 endhardwin(); #endif printf("\n"); /* So the curser doesn't stop at the end of the line */ exit(0); } /* * rnd: * Pick a very random number. */ rnd(range) register int range; { return(range <= 0 ? 0 : md_rand() % 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 */ void tstp(sig) int sig; { mvcur(0, cols - 1, lines - 1, 0); endwin(); fflush(stdout); kill(0, SIGTSTP); signal(SIGTSTP, tstp); raw(); noecho(); keypad(cw,1); keypad(msgw,1); clearok(curscr, TRUE); touchwin(cw); draw(cw); md_flushinp(); } # endif setup() { #ifdef CHECKTIME int checkout(); if (!author()) { signal(SIGALRM, checkout); alarm(CHECKTIME * 60); } #endif /* #ifndef DUMP signal(SIGILL, bugkill); #ifdef SIGTRAP signal(SIGTRAP, bugkill); #endif #ifdef SIGIOT signal(SIGIOT, bugkill); #endif #ifdef SIGEMT signal(SIGEMT, bugkill); #endif signal(SIGFPE, bugkill); #ifdef SIGBUS signal(SIGBUS, bugkill); #endif signal(SIGSEGV, bugkill); #ifdef SIGSYS signal(SIGSYS, bugkill); #endif #ifdef SIGPIPE signal(SIGPIPE, bugkill); #endif #endif */ #ifdef SIGTSTP signal(SIGTSTP, tstp); #endif #ifdef SIGHUP signal(SIGHUP, auto_save); #endif signal(SIGTERM, auto_save); signal(SIGINT, quit); #ifdef SIGQUIT signal(SIGQUIT, endit); #endif raw(); /* Cbreak mode */ noecho(); /* Echo off */ nonl(); } void open_records(void) { if (scorefd == -1) md_reopen_score(); #ifdef LOGFILE if (logfile == NULL) logfile = fopen(LOGFILE, "a"); #endif return; } /* * 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; /* * parse environment declaration of options */ if ((opts = getenv("ROGUEOPTS")) != NULL) parse_opts(opts); player.t_oldpos = hero; oldrp = roomin(&hero); after = TRUE; command(); /* Command execution */ endit(0); } /* * see if the system is being used too much for this game */ too_much() { #if MAXPROCESSES if (loadav() > MAXPROCESSES) return(TRUE); #endif #if MAXUSERS if (ucount() > MAXUSERS) return(TRUE); #endif return(FALSE); } /* * author: * See if a user is an author of the program */ author() { switch (md_getuid()) { #if AUTHOR case AUTHOR: #endif case 0: /* always OK for root to play */ return TRUE; default: return FALSE; } } #if CHECKTIME static int num_checks = 0; /* times we've gone over in checkout() */ checkout() { static char *msgs[] = { "The system is too loaded for games. Please leave in %d minutes", "Please save your game. You have %d minutes", "This is your last chance. You had better leave in %d minutes", }; int checktime; signal(SIGALRM, checkout); if (!holiday() && !author()) { msg("Game time is over. Your game is being saved.\n\n"); auto_save(); /* NO RETURN */ } if (too_much()) { if (num_checks >= 3) fatal("You didn't listen, so now 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. 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 MAXPROCESSES #include <fcntl.h> loadav() { char *sarcmd = "sar -v | cut -c17-20 | tail -2"; char *gettycmd = "grep getty /etc/inittab | wc -l"; char sysbuffer[BUFSIZ]; char tempfile[50]; char inbuf[BUFSIZ]; int fd, nprocess, ngetty; sprintf(tempfile, "/tmp/rg%d", getpid()); sprintf(sysbuffer, "%s > %s", sarcmd, tempfile); if (system(sysbuffer) != 0) { debug ("system() call failed"); return (MAXPROCESSES - 1); } if ((fd = open(tempfile, O_RDONLY)) == -1) { debug ("open() call failed"); return (MAXPROCESSES - 1); } if (read(fd, inbuf, BUFSIZ) == -1) { debug ("read() call failed"); return (MAXPROCESSES - 1); } close(fd); sscanf(inbuf, "%d", &nprocess); sprintf(sysbuffer, "%s > %s", gettycmd, tempfile); if (system(sysbuffer) != 0) { debug ("system() call failed"); return (MAXPROCESSES - 1); } if ((fd = open(tempfile, O_RDONLY)) == -1) { debug ("open() call failed"); return (MAXPROCESSES - 1); } if (read(fd, inbuf, BUFSIZ) == -1) { debug ("read() call failed"); return (MAXPROCESSES - 1); } close(fd); sscanf(inbuf, "%d", &ngetty); unlink(tempfile); return(nprocess - ngetty); } #endif #ifdef MAXUSERS /* * ucount: * Count the number of people on the system */ #include <sys/types.h> #include <utmp.h> struct utmp buf; ucount() { reg struct utmp *up; reg FILE *utmp; reg int count; if ((utmp = fopen(UTMP, "r")) == NULL) return 0; up = &buf; count = 0; while (fread(up, 1, sizeof (*up), utmp) > 0) #ifdef BSD if (buf.ut_line[0] == 't') /* On a tty */ #else if (buf.ut_type == USER_PROCESS) #endif count++; fclose(utmp); return count; } #endif /* * holiday: * Returns TRUE when it is a good time to play rogue */ holiday() { #ifdef CHECKTIME long now; struct tm *localtime(); reg struct tm *ntime; time(&now); /* get the current time */ ntime = localtime(&now); if(ntime->tm_wday == 0 || ntime->tm_wday == 6) return TRUE; /* OK on Sat & Sun */ if(ntime->tm_hour < 8 || ntime->tm_hour >= 18) return TRUE; /* OK before 8AM & after 6PM */ if(ntime->tm_yday <= 7 || ntime->tm_yday >= 350) return TRUE; /* OK during Christmas */ return FALSE; /* All other times are bad */ #else return TRUE; #endif }