/* * Rogue: Exploring the Dungeons of Doom * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman * All rights reserved. * * See the file LICENSE.TXT for full copyright and licensing information. * * @(#)main.c 4.22 (Berkeley) 02/05/99 */ #include #include #include #include #include #include #include "rogue.h" /* * main: * The main program, of course */ struct rogue_state globalR; void rogueiterate(struct rogue_state *rs) { seed = rs->seed; initscr(); /* Start up cursor package */ init_probs(); /* Set up prob tables for objects */ init_player(rs); /* Set up initial player stats */ 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 */ setup(); /* * The screen must be at least NUMLINES x NUMCOLS */ if (LINES < NUMLINES || COLS < NUMCOLS) { printf("\nSorry, the screen must be at least %dx%d\n", NUMLINES, NUMCOLS); endwin(); my_exit(1); } // Set up windows hw = newwin(LINES, COLS, 0, 0); idlok(stdscr, TRUE); idlok(hw, TRUE); #ifdef MASTER noscore = wizard; #endif new_level(rs); // Draw current level // Start up daemons and fuses start_daemon(runners, 0, AFTER); start_daemon(doctor, 0, AFTER); fuse(swander, 0, WANDERTIME, AFTER); start_daemon(stomach, 0, AFTER); playit(rs); } int32_t roguefname(char *fname,uint64_t seed,int32_t counter) { sprintf(fname,"rogue.%llu.%d",(long long)seed,counter); return(0); } int32_t flushkeystrokes(struct rogue_state *rs) { char fname[1024]; FILE *fp; int32_t i,retflag = -1; roguefname(fname,rs->seed,rs->counter); if ( (fp= fopen(fname,"wb")) != 0 ) { if ( fwrite(rs->buffered,1,rs->num,fp) == rs->num ) { rs->counter++; rs->num = 0; retflag = 0; fclose(fp); if ( (fp= fopen("savefile","wb")) != 0 ) { save_file(fp,0); if ( 0 && (fp= fopen("savefile","rb")) != 0 ) { for (i=0; i<0x150; i++) fprintf(stderr,"%02x",fgetc(fp)); fprintf(stderr," first part rnd.%d\n",rnd(1000)); fclose(fp); } roguefname(fname,rs->seed,rs->counter); if ( (fp= fopen(fname,"wb")) != 0 ) // truncate next file fclose(fp); //fprintf(stderr,"savefile <- %s retflag.%d\n",fname,retflag); } } else fprintf(stderr,"error writing (%s)\n",fname); } else fprintf(stderr,"error creating (%s)\n",fname); return(retflag); } long get_filesize(FILE *fp) { long fsize,fpos = ftell(fp); fseek(fp,0,SEEK_END); fsize = ftell(fp); fseek(fp,fpos,SEEK_SET); return(fsize); } int32_t rogue_replay(uint64_t seed) { FILE *fp; char fname[1024]; char *keystrokes = 0; long num=0,fsize; int32_t i,counter = 0; struct rogue_state *rs; while ( 1 ) { roguefname(fname,seed,counter); if ( (fp= fopen(fname,"rb")) == 0 ) break; if ( (fsize= get_filesize(fp)) <= 0 ) { fclose(fp); break; } if ( (keystrokes= (char *)realloc(keystrokes,num+fsize)) == 0 ) { fprintf(stderr,"error reallocating keystrokes\n"); fclose(fp); return(-1); } if ( fread(&keystrokes[num],1,fsize,fp) != fsize ) { fprintf(stderr,"error reading keystrokes from (%s)\n",fname); fclose(fp); return(-1); } fclose(fp); num += fsize; counter++; fprintf(stderr,"loaded %ld from (%s) total %ld\n",fsize,fname,num); } if ( num > 0 ) { rs = (struct rogue_state *)calloc(1,sizeof(*rs)); rs->seed = seed; rs->keystrokes = keystrokes; rs->numkeys = num; rogueiterate(rs); if ( (fp= fopen("checkfile","wb")) != 0 ) { save_file(fp,0); if ( 0 && (fp= fopen("checkfile","rb")) != 0 ) { for (i=0; i<0x150; i++) fprintf(stderr,"%02x",fgetc(fp)); fprintf(stderr," first part rnd.%d\n",rnd(1000)); fclose(fp); } } fatal("finished replay\n"); } if ( keystrokes != 0 ) free(keystrokes); return(num); } int rogue(int argc, char **argv, char **envp) { char *env; int lowtime; struct rogue_state *rs = &globalR; memset(rs,0,sizeof(*rs)); rs->seed = 777; rs->guiflag = 1; md_init(); #ifdef MASTER /* * 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; player.t_flags |= SEEMONST; argv++; argc--; } #endif /* * get home and options from environment */ strncpy(home, md_gethomedir(), MAXSTR); strcpy(file_name, home); strcat(file_name, "rogue.save"); if ((env = getenv("ROGUEOPTS")) != NULL) parse_opts(env); if (env == NULL || whoami[0] == '\0') strucpy(whoami, md_getusername(), (int) strlen(md_getusername())); lowtime = (int) time(NULL); #ifdef MASTER if (wizard && getenv("SEED") != NULL) dnum = atoi(getenv("SEED")); else #endif dnum = lowtime + md_getpid(); if ( rs != 0 ) seed = rs->seed; else seed = 777; dnum = (int)seed; open_score(); /* * Drop setuid/setgid after opening the scoreboard file. */ md_normaluser(); /* * check for print-score option */ md_normaluser(); /* we drop any setgid/setuid priveldges here */ if (argc == 2) { if (strcmp(argv[1], "-s") == 0) { noscore = TRUE; score(0, -1, 0); exit(0); } else if (strcmp(argv[1], "-d") == 0) { dnum = rnd(100); /* throw away some rnd()s to break patterns */ while (--dnum) rnd(100); purse = rnd(100) + 1; level = rnd(100) + 1; initscr(); getltchars(); death(death_monst()); exit(0); } } init_check(); /* check for legal startup */ if (argc == 2) if (!restore(rs,argv[1], envp)) /* Note: restore will never return */ my_exit(1); #ifdef MASTER if (wizard) printf("Hello %s, welcome to dungeon #%d", whoami, dnum); else #endif printf("Hello %s, just a moment while I dig the dungeon... seed.%llu", whoami,(long long)rs->seed); fflush(stdout); rogueiterate(rs); return(0); } /* * endit: * Exit the program abnormally. */ void endit(int sig) { NOOP(sig); fatal("Okay, bye bye!\n"); } /* * fatal: * Exit the program, printing a message. */ void fatal(char *s) { mvaddstr(LINES - 2, 0, s); refresh(); endwin(); my_exit(0); } /* * rnd: * Pick a very random number. */ int rnd(int range) { return range == 0 ? 0 : abs((int) RN) % range; } /* * roll: * Roll a number of dice */ int roll(int number, int sides) { int dtotal = 0; while (number--) dtotal += rnd(sides)+1; return dtotal; } /* * tstp: * Handle stop and start signals */ void tstp(int ignored) { int y, x; int oy, ox; NOOP(ignored); /* * leave nicely */ getyx(curscr, oy, ox); mvcur(0, COLS - 1, LINES - 1, 0); endwin(); resetltchars(); fflush(stdout); md_tstpsignal(); /* * start back up again */ md_tstpresume(); raw(); noecho(); keypad(stdscr,1); playltchars(); clearok(curscr, TRUE); wrefresh(curscr); getyx(curscr, y, x); mvcur(y, x, oy, ox); fflush(stdout); //wmove(curscr,oy,ox); #ifndef __APPLE__ curscr->_cury = oy; curscr->_curx = ox; #endif } /* * playit: * The main loop of the program. Loop until the game is over, * refreshing things and looking at the proper times. */ void playit(struct rogue_state *rs) { char *opts; /* * set up defaults for slow terminals */ if (baudrate() <= 1200) { terse = TRUE; jump = TRUE; see_floor = FALSE; } if (md_hasclreol()) inv_type = INV_CLEAR; /* * parse environment declaration of options */ if ((opts = getenv("ROGUEOPTS")) != NULL) parse_opts(opts); oldpos = hero; oldrp = roomin(rs,&hero); while (playing) { command(rs); // Command execution if ( rs->guiflag == 0 ) { if ( rs->replaydone != 0 ) { //fprintf(stderr,"replaydone\n"); sleep(3); return; } usleep(50000); } else { if ( rs->needflush != 0 ) { if ( flushkeystrokes(rs) == 0 ) rs->needflush = 0; } } } endit(0); } /* * quit: * Have player make certain, then exit. */ void quit(int sig) { struct rogue_state *rs = &globalR; int oy, ox; NOOP(sig); /* * Reset the signal in case we got here via an interrupt */ if (!q_comm) mpos = 0; getyx(curscr, oy, ox); msg(rs,"really quit?"); if (readchar(rs) == 'y') { signal(SIGINT, leave); clear(); mvprintw(LINES - 2, 0, "You quit with %d gold pieces", purse); move(LINES - 1, 0); refresh(); score(purse, 1, 0); my_exit(0); } else { move(0, 0); clrtoeol(); status(rs); move(oy, ox); refresh(); mpos = 0; count = 0; to_death = FALSE; } } /* * leave: * Leave quickly, but curteously */ void leave(int sig) { static char buf[BUFSIZ]; NOOP(sig); setbuf(stdout, buf); /* throw away pending output */ if (!isendwin()) { mvcur(0, COLS - 1, LINES - 1, 0); endwin(); } putchar('\n'); my_exit(0); } /* * shell: * Let them escape for a while */ void shell(struct rogue_state *rs) { if ( rs != 0 && rs->guiflag != 0 ) { /* * Set the terminal back to original mode */ move(LINES-1, 0); refresh(); endwin(); resetltchars(); putchar('\n'); in_shell = TRUE; after = FALSE; fflush(stdout); /* * Fork and do a shell */ md_shellescape(); printf("\n[Press return to continue]"); fflush(stdout); noecho(); raw(); keypad(stdscr,1); playltchars(); in_shell = FALSE; wait_for(rs,'\n'); clearok(stdscr, TRUE); } else fprintf(stderr,"no shell in the blockchain\n"); } /* * my_exit: * Leave the process properly */ void my_exit(int st) { resetltchars(); exit(st); }