void rloc(struct monst *mtmp) { int tx, ty; char ch = mtmp->data->mlet; #ifndef NOWORM if (ch == 'w' && mtmp->mx) /* do not relocate worms */ return; #endif /* NOWORM */ do { tx = rn1(COLNO - 3, 2); ty = rn2(ROWNO); } while (!goodpos(tx, ty)); mtmp->mx = tx; mtmp->my = ty; if (u.ustuck == mtmp) { if (u.uswallow) { u.ux = tx; u.uy = ty; docrt(); } else u.ustuck = 0; } pmon(mtmp); }
/* 0: open 1: wait+close 2: close */ void set_pager(int mode) { static boolean so; if(mode == 0) { if(!whole_screen) { /* clear topline */ clrlin(); /* use part of screen below level map */ curs(1, ROWNO+4); } else { cls(); } so = flags.standout; flags.standout = 1; } else { if(mode == 1) { curs(1, LI); more(); } flags.standout = so; if(whole_screen) docrt(); else { curs(1, ROWNO+4); cl_eos(); } } }
void morewhat(FILE *fp) { char bufr[BUFSZ]; char *ep; pline("More info? "); if(readchar() != 'y') { return; } cls(); while((fgets(bufr, BUFSZ, fp) != 0) && (*bufr == '\t')) { ep = index(bufr, '\n'); if(ep == NULL) { break; } *ep = 0; puts(bufr + 1); } more(); docrt(); }
void mondead(struct monst *mtmp) { relobj(mtmp, 1); unpmon(mtmp); relmon(mtmp); if(u.ustuck == mtmp) { u.ustuck = 0; if(u.uswallow != 0) { u.uswallow = 0; setsee(); docrt(); } } if(mtmp->isshk != 0) { shkdead(); } if(mtmp->isgd != 0) { gddead(); } #ifndef NOWORM if(mtmp->wormno) { wormdead(mtmp); } #endif monfree(mtmp); }
static void winch() { int oldLI = LI, oldCO = CO, i; register struct WinDesc *cw; getwindowsz(); if((oldLI != LI || oldCO != CO) && ttyDisplay) { ttyDisplay->rows = LI; ttyDisplay->cols = CO; cw = wins[BASE_WINDOW]; cw->rows = ttyDisplay->rows; cw->cols = ttyDisplay->cols; if(flags.window_inited) { cw = wins[WIN_MESSAGE]; cw->curx = cw->cury = 0; tty_destroy_nhwindow(WIN_STATUS); WIN_STATUS = tty_create_nhwindow(NHW_STATUS); if(u.ux) { #ifdef CLIPPING if(CO < COLNO || LI < ROWNO+3) { setclipped(); tty_cliparound(u.ux, u.uy); } else { clipping = FALSE; clipx = clipy = 0; } #endif i = ttyDisplay->toplin; ttyDisplay->toplin = 0; docrt(); bot(); ttyDisplay->toplin = i; flush_screen(1); if(i) { addtopl(toplines); } else for(i=WIN_INVEN; i < MAXWIN; i++) if(wins[i] && wins[i]->active) { /* cop-out */ addtopl("Press Return to continue: "); break; } (void) fflush(stdout); if(i < 2) flush_screen(1); } } } }
void newgame() { fobj = invent = level.buriedobjlist = migrating_objs = (struct obj *)0; fmon = migrating_mons = (struct monst *)0; ftrap = 0; flags.ident = 1; if(wiz1_level.dlevel == 0) init_dungeons(); init_objects(); /* must be before u_init() */ u_init(); init_artifacts(); /* must be after u_init() */ #ifndef NO_SIGNAL (void) signal(SIGINT, (SIG_RET_TYPE) done1); #endif #ifdef NEWS if(flags.news) display_file(NEWS, FALSE); #endif #ifdef MULDGN load_qtlist(); /* load up the quest text info */ quest_init(); if(flags.legacy && moves == 1) com_pager(1); #endif mklev(); u_on_upstairs(); check_special_room(FALSE); vision_reset(); /* set up internals for level (after mklev) */ flags.botlx = 1; /* Move the monster from under you or else * makedog() will fail when it calls makemon(). * - ucsfcgl!kneller */ if(MON_AT(u.ux, u.uy)) mnexto(m_at(u.ux, u.uy)); #ifdef CLIPPING cliparound(u.ux, u.uy); #endif (void) makedog(); docrt(); #ifdef INSURANCE save_currentstate(); #endif return; }
/* This cannot be part of hack.tty.c (as it was earlier) since on some systems (e.g. MUNIX) the include files <termio.h> and <sgtty.h> define the same constants, and the C preprocessor complains. */ #include <stdio.h> #include "config.h" #ifdef BSD #include <sgtty.h> struct ltchars ltc, ltc0; #else #include <termio.h> /* also includes part of <sgtty.h> */ struct termio termio; #endif BSD getioctls() { #ifdef BSD (void) ioctl(fileno(stdin), TIOCGLTC, (char *) <c); (void) ioctl(fileno(stdin), TIOCSLTC, (char *) <c0); #else (void) ioctl(fileno(stdin), TCGETA, &termio); #endif BSD } setioctls() { #ifdef BSD (void) ioctl(fileno(stdin), TIOCSLTC, (char *) <c); #else (void) ioctl(fileno(stdin), TCSETA, &termio); #endif BSD } #ifdef SUSPEND /* implies BSD */ dosuspend() { #include <signal.h> #ifdef SIGTSTP if(signal(SIGTSTP, SIG_IGN) == SIG_DFL) { settty((char *) 0); (void) signal(SIGTSTP, SIG_DFL); (void) kill(0, SIGTSTP); gettty(); setftty(); docrt(); } else { pline("I don't think your shell has job control."); } #else SIGTSTP pline("Sorry, it seems we have no SIGTSTP here. Try ! or S."); #endif SIGTSTP return(0); }
int child(int wt) { int status; int f; char *home; gid_t gid; f = fork(); if(f == 0){ /* child */ settty((char *) 0); /* also calls end_screen() */ /* revoke privs */ gid = getgid(); setresgid(gid, gid, gid); #ifdef CHDIR home = getenv("HOME"); if (home == NULL || *home == '\0') home = "/"; (void) chdir(home); #endif /* CHDIR */ return(1); } if(f == -1) { /* cannot fork */ pline("Fork failed. Try again."); return(0); } /* fork succeeded; wait for child to exit */ (void) signal(SIGINT,SIG_IGN); (void) signal(SIGQUIT,SIG_IGN); (void) wait(&status); gettty(); setftty(); (void) signal(SIGINT,done1); #ifdef WIZARD if(wizard) (void) signal(SIGQUIT,SIG_DFL); #endif /* WIZARD */ if(wt) getret(); docrt(); return(0); }
void rloc(struct monst *mtmp) { int tx; int ty; char ch = mtmp->data->mlet; #ifndef NOWORM if((ch == 'w') && (mtmp->mx)) { /* Do not relocate worms */ return; } #endif tx = rn1(COLNO - 3, 2); ty = rn2(ROWNO); while(goodpos(tx, ty) == 0) { tx = rn1(COLNO - 3, 2); ty = rn2(ROWNO); } mtmp->mx = tx; mtmp->my = ty; if(u.ustuck == mtmp) { if(u.uswallow != 0) { u.ux = tx; u.uy = ty; docrt(); } else { u.ustuck = 0; } } pmon(mtmp); }
bool dorecover (void) { char savefile [PATH_MAX]; snprintf (ArrayBlock(savefile), HACK_SAVEFILE, getenv("HOME")); int fd = open (savefile, O_RDONLY); if (fd < 0) return false; mread (fd, &_u, sizeof(struct you)); if (_u.maxdlevel < 1 || _u.maxdlevel > MAXLEVEL) { close (fd); you_dtor(); return false; } invent = restobjchn (fd); for (struct obj* o = invent; o; o = o->nobj) if (o->owornmask) setworn (o, o->owornmask); fcobj = restobjchn (fd); fallen_down = restmonchn (fd); mread (fd, &_wflags, sizeof(struct worldflag)); mread (fd, pl_character, sizeof pl_character); restnames (fd); restgenocided (fd); for (unsigned i = 0; i < _u.maxdlevel; ++i) { level_dtor (&_levels[i]); getlev (fd, &_levels[i]); } if (_u.dlevel < 1 || _u.dlevel > _u.maxdlevel) _u.dlevel = _u.maxdlevel; _level = &_levels[_u.dlevel-1]; setsee(); // only to recompute seelx etc. - these weren't saved docrt(); close (fd); unlink (savefile); return true; }
bool child(bool wt) { int status; int f; f = fork(); if (f == 0) { /* child */ settty(NULL); /* also calls end_screen() */ /* revoke */ setgid(getgid()); #ifdef CHDIR chdir(getenv("HOME")); #endif /* CHDIR */ return (1); } if (f == -1) { /* cannot fork */ pline("Fork failed. Try again."); return (0); } /* fork succeeded; wait for child to exit */ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); wait(&status); gettty(); setftty(); signal(SIGINT, done1); #ifdef WIZARD if (wizard) signal(SIGQUIT, SIG_DFL); #endif /* WIZARD */ if (wt) getret(); docrt(); return (0); }
void newgame() { int i; #ifdef MFLOPPY gameDiskPrompt(); #endif flags.ident = 1; for (i = 0; i < NUMMONS; i++) mvitals[i].mvflags = mons[i].geno & G_NOCORPSE; init_objects(); /* must be before u_init() */ flags.pantheon = -1; /* role_init() will reset this */ role_init(); /* must be before init_dungeons(), u_init(), * and init_artifacts() */ init_dungeons(); /* must be before u_init() to avoid rndmonst() * creating odd monsters for any tins and eggs * in hero's initial inventory */ init_artifacts(); /* before u_init() in case $WIZKIT specifies * any artifacts */ u_init(); #ifndef NO_SIGNAL (void) signal(SIGINT, (SIG_RET_TYPE) done1); #endif #ifdef NEWS if(iflags.news) display_file(NEWS, FALSE); #endif load_qtlist(); /* load up the quest text info */ /* quest_init();*/ /* Now part of role_init() */ mklev(); u_on_upstairs(); vision_reset(); /* set up internals for level (after mklev) */ check_special_room(FALSE); flags.botlx = 1; /* Move the monster from under you or else * makedog() will fail when it calls makemon(). * - ucsfcgl!kneller */ if(MON_AT(u.ux, u.uy)) mnexto(m_at(u.ux, u.uy)); (void) makedog(); docrt(); if (flags.legacy) { flush_screen(1); com_pager(1); } #ifdef INSURANCE save_currentstate(); #endif program_state.something_worth_saving++; /* useful data now exists */ #if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL) /* Start the timer here */ realtime_data.realtime = (time_t)0L; #if defined(BSD) && !defined(POSIX_TYPES) (void) time((long *)&realtime_data.restoretime); #else (void) time(&realtime_data.restoretime); #endif #endif /* RECORD_REALTIME || REALTIME_ON_BOTL */ /* Success! */ welcome(TRUE); return; }
int main(int argc, char *argv[]) { int fd; #ifdef CHDIR char *dir; #endif hname = argv[0]; hackpid = getpid(); #ifdef CHDIR /* otherwise no chdir() */ /* * See if we must change directory to the playground. * (Perhaps hack runs suid and playground is inaccessible * for the player.) * The environment variable HACKDIR is overridden by a * -d command line option (must be the first option given) */ dir = getenv("HACKDIR"); if (argc > 1 && !strncmp(argv[1], "-d", 2)) { argc--; argv++; dir = argv[0] + 2; if (*dir == '=' || *dir == ':') dir++; if (!*dir && argc > 1) { argc--; argv++; dir = argv[0]; } if (!*dir) error("Flag -d must be followed by a directory name."); } #endif /* * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS * 2. Use $USER or $LOGNAME (if 1. fails) * 3. Use getlogin() (if 2. fails) * The resulting name is overridden by command line options. * If everything fails, or if the resulting name is some generic * account like "games", "play", "player", "hack" then eventually * we'll ask him. * Note that we trust him here; it is possible to play under * somebody else's name. */ { char *s; initoptions(); if (!*plname && (s = getenv("USER"))) strncpy(plname, s, sizeof(plname) - 1); if (!*plname && (s = getenv("LOGNAME"))) strncpy(plname, s, sizeof(plname) - 1); if (!*plname && (s = getlogin())) strncpy(plname, s, sizeof(plname) - 1); } /* * Now we know the directory containing 'record' and * may do a prscore(). */ if (argc > 1 && !strncmp(argv[1], "-s", 2)) { #ifdef CHDIR chdirx(dir, 0); #endif prscore(argc, argv); exit(0); } /* * It seems he really wants to play. * Remember tty modes, to be restored on exit. */ gettty(); setbuf(stdout, obuf); umask(007); setrandom(); startup(); cls(); u.uhp = 1; /* prevent RIP on early quits */ u.ux = FAR; /* prevent nscr() */ signal(SIGHUP, hangup); /* * Find the creation date of this game, * so as to avoid restoring outdated savefiles. */ gethdate(hname); /* * We cannot do chdir earlier, otherwise gethdate will fail. */ #ifdef CHDIR chdirx(dir, 1); #endif /* * Process options. */ while (argc > 1 && argv[1][0] == '-') { argv++; argc--; switch (argv[0][1]) { #ifdef WIZARD case 'D': wizard = TRUE; break; #endif #ifdef NEWS case 'n': flags.nonews = TRUE; break; #endif case 'u': if (argv[0][2]) strncpy(plname, argv[0] + 2, sizeof(plname) - 1); else if (argc > 1) { argc--; argv++; strncpy(plname, argv[0], sizeof(plname) - 1); } else printf("Player name expected after -u\n"); break; default: /* allow -T for Tourist, etc. */ strncpy(pl_character, argv[0] + 1, sizeof(pl_character) - 1); } } if (argc > 1) locknum = atoi(argv[1]); #ifdef MAX_NR_OF_PLAYERS if (!locknum || locknum > MAX_NR_OF_PLAYERS) locknum = MAX_NR_OF_PLAYERS; #endif #ifdef DEF_PAGER if (!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER"))) catmore = DEF_PAGER; #endif #ifdef MAIL getmailstatus(); #endif #ifdef WIZARD if (wizard) strcpy(plname, "wizard"); else #endif if (!*plname || !strncmp(plname, "player", 4) || !strncmp(plname, "games", 4)) askname(); plnamesuffix(); /* strip suffix from name; calls askname() */ /* again if suffix was whole name */ /* accepts any suffix */ #ifdef WIZARD if (!wizard) { #endif /* * check for multiple games under the same name * (if !locknum) or check max nr of players (otherwise) */ signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); if (!locknum) strcpy(lock, plname); getlock(); /* sets lock if locknum != 0 */ #ifdef WIZARD } else { char *sfoo; strcpy(lock, plname); if ((sfoo = getenv("MAGIC"))) while (*sfoo) { switch (*sfoo++) { case 'n': srandom(*sfoo++); break; } } if ((sfoo = getenv("GENOCIDED")) != NULL) { if (*sfoo == '!') { struct permonst *pm = mons; char *gp = genocided; while (pm < mons + CMNUM + 2) { if (!strchr(sfoo, pm->mlet)) *gp++ = pm->mlet; pm++; } *gp = 0; } else strncpy(genocided, sfoo, sizeof(genocided) - 1); strcpy(fut_geno, genocided); } } #endif setftty(); sprintf(SAVEF, "save/%d%s", getuid(), plname); regularize(SAVEF + 5); /* avoid . or / in name */ if ((fd = open(SAVEF, O_RDONLY)) >= 0 && (uptodate(fd) || unlink(SAVEF) == 666)) { signal(SIGINT, done1); pline("Restoring old save file..."); fflush(stdout); if (!dorecover(fd)) goto not_recovered; pline("Hello %s, welcome to %s!", plname, gamename); flags.move = 0; } else { not_recovered: fobj = fcobj = invent = 0; fmon = fallen_down = 0; ftrap = 0; fgold = 0; flags.ident = 1; init_objects(); u_init(); signal(SIGINT, done1); mklev(); u.ux = xupstair; u.uy = yupstair; inshop(); setsee(); flags.botlx = 1; makedog(); { struct monst *mtmp; if ((mtmp = m_at(u.ux, u.uy)) != NULL) mnexto(mtmp); /* riv05!a3 */ } seemons(); #ifdef NEWS if (flags.nonews || !readnews()) /* after reading news we did docrt() already */ #endif docrt(); /* give welcome message before pickup messages */ pline("Hello %s, welcome to %s!", plname, gamename); pickup(1); read_engr_at(u.ux, u.uy); flags.move = 1; } flags.moonphase = phase_of_the_moon(); if (flags.moonphase == FULL_MOON) { pline("You are lucky! Full moon tonight."); u.uluck++; } else if (flags.moonphase == NEW_MOON) pline("Be careful! New moon tonight."); initrack(); for (;;) { if (flags.move) { /* actual time passed */ settrack(); if (moves % 2 == 0 || (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { movemon(); if (!rn2(70)) makemon(NULL, 0, 0); } if (Glib) glibr(); p_timeout(); ++moves; if (flags.time) flags.botl = 1; if (u.uhp < 1) { pline("You die..."); done("died"); } if (u.uhp * 10 < u.uhpmax && moves - wailmsg > 50) { wailmsg = moves; if (u.uhp == 1) pline("You hear the wailing of the Banshee..."); else pline("You hear the howling of the CwnAnnwn..."); } if (u.uhp < u.uhpmax) { if (u.ulevel > 9) { if (Regeneration || !(moves % 3)) { flags.botl = 1; u.uhp += rnd((int)u.ulevel - 9); if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; } } else if (Regeneration || (!(moves % (22 - u.ulevel * 2)))) { flags.botl = 1; u.uhp++; } } if (Teleportation && !rn2(85)) tele(); if (Searching && multi >= 0) dosearch(); gethungry(); invault(); amulet(); } if (multi < 0) { if (!++multi) { pline("%s", nomovemsg ? nomovemsg : "You can move again."); nomovemsg = 0; if (afternmv) (*afternmv)(); afternmv = NULL; } } find_ac(); #ifndef QUEST if (!flags.mv || Blind) #endif { seeobjs(); seemons(); nscr(); } if (flags.botl || flags.botlx) bot(); flags.move = 1; if (multi >= 0 && occupation) { if (monster_nearby()) stop_occupation(); else if ((*occupation)() == 0) occupation = NULL; continue; } if (multi > 0) { #ifdef QUEST if (flags.run >= 4) finddir(); #endif lookaround(); if (!multi) { /* lookaround may clear multi */ flags.move = 0; continue; } if (flags.mv) { if (multi < COLNO && !--multi) flags.mv = flags.run = 0; domove(); } else { --multi; rhack(save_cm); } } else if (multi == 0) { #ifdef MAIL ckmailstatus(); #endif rhack(NULL); } if (multi && multi % 7 == 0) fflush(stdout); } }
int dodrink() { struct obj *otmp,*objs; struct monst *mtmp; int unkn = 0, nothing = 0; otmp = getobj("!", "drink"); if(!otmp) return(0); if(!strcmp(objects[otmp->otyp].oc_descr, "smoky") && !rn2(13)) { ghost_from_bottle(); goto use_it; } switch(otmp->otyp){ case POT_RESTORE_STRENGTH: unkn++; pline("Wow! This makes you feel great!"); if(u.ustr < u.ustrmax) { u.ustr = u.ustrmax; flags.botl = 1; } break; case POT_BOOZE: unkn++; pline("Ooph! This tastes like liquid fire!"); Confusion += d(3,8); /* the whiskey makes us feel better */ if(u.uhp < u.uhpmax) losehp(-1, "bottle of whiskey"); if(!rn2(4)) { pline("You pass out."); multi = -rnd(15); nomovemsg = "You awake with a headache."; } break; case POT_INVISIBILITY: if(Invis || See_invisible) nothing++; else { if(!Blind) pline("Gee! All of a sudden, you can't see yourself."); else pline("You feel rather airy."), unkn++; newsym(u.ux,u.uy); } Invis += rn1(15,31); break; case POT_FRUIT_JUICE: pline("This tastes like fruit juice."); lesshungry(20); break; case POT_HEALING: pline("You begin to feel better."); flags.botl = 1; u.uhp += rnd(10); if(u.uhp > u.uhpmax) u.uhp = ++u.uhpmax; if(Blind) Blind = 1; /* see on next move */ if(Sick) Sick = 0; break; case POT_PARALYSIS: if(Levitation) pline("You are motionlessly suspended."); else pline("Your feet are frozen to the floor!"); nomul(-(rn1(10,25))); break; case POT_MONSTER_DETECTION: if(!fmon) { strange_feeling(otmp, "You feel threatened."); return(1); } else { cls(); for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->mx > 0) at(mtmp->mx,mtmp->my,mtmp->data->mlet); prme(); pline("You sense the presence of monsters."); more(); docrt(); } break; case POT_OBJECT_DETECTION: if(!fobj) { strange_feeling(otmp, "You feel a pull downward."); return(1); } else { for(objs = fobj; objs; objs = objs->nobj) if(objs->ox != u.ux || objs->oy != u.uy) goto outobjmap; pline("You sense the presence of objects close nearby."); break; outobjmap: cls(); for(objs = fobj; objs; objs = objs->nobj) at(objs->ox,objs->oy,objs->olet); prme(); pline("You sense the presence of objects."); more(); docrt(); } break; case POT_SICKNESS: pline("Yech! This stuff tastes like poison."); if(Poison_resistance) pline("(But in fact it was biologically contaminated orange juice.)"); losestr(rn1(4,3)); losehp(rnd(10), "contaminated potion"); break; case POT_CONFUSION: if(!Confusion) pline("Huh, What? Where am I?"); else nothing++; Confusion += rn1(7,16); break; case POT_GAIN_STRENGTH: pline("Wow do you feel strong!"); if(u.ustr >= 118) break; /* > 118 is impossible */ if(u.ustr > 17) u.ustr += rnd(118-u.ustr); else u.ustr++; if(u.ustr > u.ustrmax) u.ustrmax = u.ustr; flags.botl = 1; break; case POT_SPEED: if(Wounded_legs) { heal_legs(); unkn++; break; } if(!(Fast & ~INTRINSIC)) pline("You are suddenly moving much faster."); else pline("Your legs get new energy."), unkn++; Fast += rn1(10,100); break; case POT_BLINDNESS: if(!Blind) pline("A cloud of darkness falls upon you."); else nothing++; Blind += rn1(100,250); seeoff(0); break; case POT_GAIN_LEVEL: pluslvl(); break; case POT_EXTRA_HEALING: pline("You feel much better."); flags.botl = 1; u.uhp += d(2,20)+1; if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += 2); if(Blind) Blind = 1; if(Sick) Sick = 0; break; case POT_LEVITATION: if(!Levitation) float_up(); else nothing++; Levitation += rnd(100); u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down; break; default: impossible("What a funny potion! (%u)", otmp->otyp); return(0); } if(nothing) { unkn++; pline("You have a peculiar feeling for a moment, then it passes."); } if(otmp->dknown && !objects[otmp->otyp].oc_name_known) { if(!unkn) { objects[otmp->otyp].oc_name_known = 1; more_experienced(0,10); } else if(!objects[otmp->otyp].oc_uname) docall(otmp); } use_it: useup(otmp); return(1); }
int doread() { struct obj *scroll; boolean confused = (Confusion != 0); boolean known = FALSE; scroll = getobj("?", "read"); if(!scroll) return(0); if(!scroll->dknown && Blind) { pline("Being blind, you cannot read the formula on the scroll."); return(0); } if(Blind) pline("As you pronounce the formula on it, the scroll disappears."); else pline("As you read the scroll, it disappears."); if(confused) pline("Being confused, you mispronounce the magic words ... "); switch(scroll->otyp) { #ifdef MAIL case SCR_MAIL: readmail(/* scroll */); break; #endif /* MAIL */ case SCR_ENCHANT_ARMOR: { struct obj *otmp = some_armor(); if(!otmp) { strange_feeling(scroll,"Your skin glows then fades."); return(1); } if(confused) { pline("Your %s glows silver for a moment.", objects[otmp->otyp].oc_name); otmp->rustfree = 1; break; } if(otmp->spe > 3 && rn2(otmp->spe)) { pline("Your %s glows violently green for a while, then evaporates.", objects[otmp->otyp].oc_name); useup(otmp); break; } pline("Your %s glows green for a moment.", objects[otmp->otyp].oc_name); otmp->cursed = 0; otmp->spe++; break; } case SCR_DESTROY_ARMOR: if(confused) { struct obj *otmp = some_armor(); if(!otmp) { strange_feeling(scroll,"Your bones itch."); return(1); } pline("Your %s glows purple for a moment.", objects[otmp->otyp].oc_name); otmp->rustfree = 0; break; } if(uarm) { pline("Your armor turns to dust and falls to the floor!"); useup(uarm); } else if(uarmh) { pline("Your helmet turns to dust and is blown away!"); useup(uarmh); } else if(uarmg) { pline("Your gloves vanish!"); useup(uarmg); selftouch("You"); } else { strange_feeling(scroll,"Your skin itches."); return(1); } break; case SCR_CONFUSE_MONSTER: if(confused) { pline("Your hands begin to glow purple."); Confusion += rnd(100); } else { pline("Your hands begin to glow blue."); u.umconf = 1; } break; case SCR_SCARE_MONSTER: { int ct = 0; struct monst *mtmp; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(cansee(mtmp->mx,mtmp->my)) { if(confused) mtmp->mflee = mtmp->mfroz = mtmp->msleep = 0; else mtmp->mflee = 1; ct++; } if(!ct) { if(confused) pline("You hear sad wailing in the distance."); else pline("You hear maniacal laughter in the distance."); } break; } case SCR_BLANK_PAPER: if(confused) pline("You see strange patterns on this scroll."); else pline("This scroll seems to be blank."); break; case SCR_REMOVE_CURSE: { struct obj *obj; if(confused) pline("You feel like you need some help."); else pline("You feel like someone is helping you."); for(obj = invent; obj ; obj = obj->nobj) if(obj->owornmask) obj->cursed = confused; if(Punished && !confused) { Punished = 0; freeobj(uchain); unpobj(uchain); free(uchain); uball->spe = 0; uball->owornmask &= ~W_BALL; uchain = uball = (struct obj *) 0; } break; } case SCR_CREATE_MONSTER: { int cnt = 1; if(!rn2(73)) cnt += rnd(4); if(confused) cnt += 12; while(cnt--) (void) makemon(confused ? PM_ACID_BLOB : (struct permonst *) 0, u.ux, u.uy); break; } case SCR_ENCHANT_WEAPON: if(uwep && confused) { pline("Your %s glows silver for a moment.", objects[uwep->otyp].oc_name); uwep->rustfree = 1; } else if(!chwepon(scroll, 1)) /* tests for !uwep */ return(1); break; case SCR_DAMAGE_WEAPON: if(uwep && confused) { pline("Your %s glows purple for a moment.", objects[uwep->otyp].oc_name); uwep->rustfree = 0; } else if(!chwepon(scroll, -1)) /* tests for !uwep */ return(1); break; case SCR_TAMING: { int i,j; int bd = confused ? 5 : 1; struct monst *mtmp; for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) if ((mtmp = m_at(u.ux+i, u.uy+j))) (void) tamedog(mtmp, NULL); break; } case SCR_GENOCIDE: { extern char genocided[], fut_geno[]; char buf[BUFSZ]; struct monst *mtmp, *mtmp2; pline("You have found a scroll of genocide!"); known = TRUE; if(confused) *buf = u.usym; else do { pline("What monster do you want to genocide (Type the letter)? "); getlin(buf); } while(strlen(buf) != 1 || !monstersym(*buf)); if(!strchr(fut_geno, *buf)) charcat(fut_geno, *buf); if(!strchr(genocided, *buf)) charcat(genocided, *buf); else { pline("Such monsters do not exist in this world."); break; } for(mtmp = fmon; mtmp; mtmp = mtmp2){ mtmp2 = mtmp->nmon; if(mtmp->data->mlet == *buf) mondead(mtmp); } pline("Wiped out all %c's.", *buf); if(*buf == u.usym) { killer = "scroll of genocide"; u.uhp = -1; } break; } case SCR_LIGHT: if(!Blind) known = TRUE; litroom(!confused); break; case SCR_TELEPORTATION: if(confused) level_tele(); else { #ifdef QUEST int oux = u.ux, ouy = u.uy; tele(); if(dist(oux, ouy) > 100) known = TRUE; #else /* QUEST */ int uroom = inroom(u.ux, u.uy); tele(); if(uroom != inroom(u.ux, u.uy)) known = TRUE; #endif /* QUEST */ } break; case SCR_GOLD_DETECTION: /* Unfortunately this code has become slightly less elegant, now that gold and traps no longer are of the same type. */ if(confused) { struct trap *ttmp; if(!ftrap) { strange_feeling(scroll, "Your toes stop itching."); return(1); } else { for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) if(ttmp->tx != u.ux || ttmp->ty != u.uy) goto outtrapmap; /* only under me - no separate display required */ pline("Your toes itch!"); break; outtrapmap: cls(); for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) at(ttmp->tx, ttmp->ty, '$'); prme(); pline("You feel very greedy!"); } } else { struct gold *gtmp; if(!fgold) { strange_feeling(scroll, "You feel materially poor."); return(1); } else { known = TRUE; for(gtmp = fgold; gtmp; gtmp = gtmp->ngold) if(gtmp->gx != u.ux || gtmp->gy != u.uy) goto outgoldmap; /* only under me - no separate display required */ pline("You notice some gold between your feet."); break; outgoldmap: cls(); for(gtmp = fgold; gtmp; gtmp = gtmp->ngold) at(gtmp->gx, gtmp->gy, '$'); prme(); pline("You feel very greedy, and sense gold!"); } } /* common sequel */ more(); docrt(); break; case SCR_FOOD_DETECTION: { int ct = 0, ctu = 0; struct obj *obj; char foodsym = confused ? POTION_SYM : FOOD_SYM; for(obj = fobj; obj; obj = obj->nobj) if(obj->olet == FOOD_SYM) { if(obj->ox == u.ux && obj->oy == u.uy) ctu++; else ct++; } if(!ct && !ctu) { strange_feeling(scroll,"Your nose twitches."); return(1); } else if(!ct) { known = TRUE; pline("You smell %s close nearby.", confused ? "something" : "food"); } else { known = TRUE; cls(); for(obj = fobj; obj; obj = obj->nobj) if(obj->olet == foodsym) at(obj->ox, obj->oy, FOOD_SYM); prme(); pline("Your nose tingles and you smell %s!", confused ? "something" : "food"); more(); docrt(); } break; } case SCR_IDENTIFY: /* known = TRUE; */ if(confused) pline("You identify this as an identify scroll."); else pline("This is an identify scroll."); useup(scroll); objects[SCR_IDENTIFY].oc_name_known = 1; if(!confused) while( !ggetobj("identify", identify, rn2(5) ? 1 : rn2(5)) && invent ); return(1); case SCR_MAGIC_MAPPING: { struct rm *lev; int num, zx, zy; known = TRUE; pline("On this scroll %s a map!", confused ? "was" : "is"); for(zy = 0; zy < ROWNO; zy++) for(zx = 0; zx < COLNO; zx++) { if(confused && rn2(7)) continue; lev = &(levl[zx][zy]); if((num = lev->typ) == 0) continue; if(num == SCORR) { lev->typ = CORR; lev->scrsym = CORR_SYM; } else if(num == SDOOR) { lev->typ = DOOR; lev->scrsym = '+'; /* do sth in doors ? */ } else if(lev->seen) continue; #ifndef QUEST if(num != ROOM) #endif /* QUEST */ { lev->seen = lev->new = 1; if(lev->scrsym == ' ' || !lev->scrsym) newsym(zx,zy); else on_scr(zx,zy); } } break; } case SCR_AMNESIA: { int zx, zy; known = TRUE; for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++) if(!confused || rn2(7)) if(!cansee(zx,zy)) levl[zx][zy].seen = 0; docrt(); pline("Thinking of Maud you forget everything else."); break; } case SCR_FIRE: { int num; struct monst *mtmp; known = TRUE; if(confused) { pline("The scroll catches fire and you burn your hands."); losehp(1, "scroll of fire"); } else { pline("The scroll erupts in a tower of flame!"); if(Fire_resistance) pline("You are uninjured."); else { num = rnd(6); u.uhpmax -= num; losehp(num, "scroll of fire"); } } num = (2*num + 1)/3; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if(dist(mtmp->mx,mtmp->my) < 3) { mtmp->mhp -= num; if(strchr("FY", mtmp->data->mlet)) mtmp->mhp -= 3*num; /* this might well kill 'F's */ if(mtmp->mhp < 1) { killed(mtmp); break; /* primitive */ } } } break; } case SCR_PUNISHMENT: known = TRUE; if(confused) { pline("You feel guilty."); break; } pline("You are being punished for your misbehaviour!"); if(Punished){ pline("Your iron ball gets heavier."); uball->owt += 15; break; } Punished = INTRINSIC; setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN); setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL); uball->spe = 1; /* special ball (see save) */ break; default: impossible("What weird language is this written in? (%u)", scroll->otyp); }
void goto_level(int newlevel, boolean at_stairs) { int fd; boolean up = (newlevel < dlevel); if(newlevel <= 0) done("escaped"); /* in fact < 0 is impossible */ if(newlevel > MAXLEVEL) newlevel = MAXLEVEL; /* strange ... */ if(newlevel == dlevel) return; /* this can happen */ glo(dlevel); fd = creat(lock, FMASK); if(fd < 0) { /* * This is not quite impossible: e.g., we may have * exceeded our quota. If that is the case then we * cannot leave this level, and cannot save either. * Another possibility is that the directory was not * writable. */ pline("A mysterious force prevents you from going %s.", up ? "up" : "down"); return; } if(Punished) unplacebc(); u.utrap = 0; /* needed in level_tele */ u.ustuck = 0; /* idem */ keepdogs(); seeoff(1); if(u.uswallow) /* idem */ u.uswldtim = u.uswallow = 0; flags.nscrinh = 1; u.ux = FAR; /* hack */ (void) inshop(); /* probably was a trapdoor */ savelev(fd,dlevel); (void) close(fd); dlevel = newlevel; if(maxdlevel < dlevel) maxdlevel = dlevel; glo(dlevel); if(!level_exists[(int)dlevel]) mklev(); else { extern int hackpid; if((fd = open(lock, O_RDONLY)) < 0) { pline("Cannot open %s .", lock); pline("Probably someone removed it."); done("tricked"); } getlev(fd, hackpid, dlevel); (void) close(fd); } if(at_stairs) { if(up) { u.ux = xdnstair; u.uy = ydnstair; if(!u.ux) { /* entering a maze from below? */ u.ux = xupstair; /* this will confuse the player! */ u.uy = yupstair; } if(Punished && !Levitation){ pline("With great effort you climb the stairs."); placebc(1); } } else { u.ux = xupstair; u.uy = yupstair; if(inv_weight() + 5 > 0 || Punished){ pline("You fall down the stairs."); /* %% */ losehp(rnd(3), "fall"); if(Punished) { if(uwep != uball && rn2(3)){ pline("... and are hit by the iron ball."); losehp(rnd(20), "iron ball"); } placebc(1); } selftouch("Falling, you"); } } { struct monst *mtmp = m_at(u.ux, u.uy); if(mtmp) mnexto(mtmp); } } else { /* trapdoor or level_tele */ do { u.ux = rnd(COLNO-1); u.uy = rn2(ROWNO); } while(levl[(int)u.ux][(int)u.uy].typ != ROOM || m_at(u.ux,u.uy)); if(Punished){ if(uwep != uball && !up /* %% */ && rn2(5)){ pline("The iron ball falls on your head."); losehp(rnd(25), "iron ball"); } placebc(1); } selftouch("Falling, you"); } (void) inshop(); initrack(); losedogs(); { struct monst *mtmp; if ((mtmp = m_at(u.ux, u.uy))) mnexto(mtmp); /* riv05!a3 */ } flags.nscrinh = 0; setsee(); seeobjs(); /* make old cadavers disappear - riv05!a3 */ docrt(); pickup(1); read_engr_at(u.ux,u.uy); }
int dorecover(int fd) { int nfd; int tmp; /* not a ! */ unsigned mid; /* idem */ struct obj *otmp; restoring = TRUE; getlev(fd, 0, 0); invent = restobjchn(fd); for (otmp = invent; otmp; otmp = otmp->nobj) if (otmp->owornmask) setworn(otmp, otmp->owornmask); fcobj = restobjchn(fd); fallen_down = restmonchn(fd); mread(fd, &tmp, sizeof tmp); if (tmp != (int) getuid()) { /* strange ... */ (void) close(fd); (void) unlink(SAVEF); puts("Saved game was not yours."); restoring = FALSE; return (0); } mread(fd, &flags, sizeof(struct flag)); mread(fd, &dlevel, sizeof dlevel); mread(fd, &maxdlevel, sizeof maxdlevel); mread(fd, &moves, sizeof moves); mread(fd, &u, sizeof(struct you)); if (u.ustuck) mread(fd, &mid, sizeof mid); mread(fd, pl_character, sizeof pl_character); mread(fd, genocided, sizeof genocided); mread(fd, fut_geno, sizeof fut_geno); restnames(fd); while (1) { if (read(fd, &tmp, sizeof tmp) != sizeof tmp) break; getlev(fd, 0, tmp); glo(tmp); if ((nfd = creat(lock, FMASK)) < 0) panic("Cannot open temp file %s!\n", lock); savelev(nfd, tmp); (void) close(nfd); } (void) lseek(fd, (off_t) 0, SEEK_SET); getlev(fd, 0, 0); (void) close(fd); (void) unlink(SAVEF); if (Punished) { for (otmp = fobj; otmp; otmp = otmp->nobj) if (otmp->olet == CHAIN_SYM) goto chainfnd; panic("Cannot find the iron chain?"); chainfnd: uchain = otmp; if (!uball) { for (otmp = fobj; otmp; otmp = otmp->nobj) if (otmp->olet == BALL_SYM && otmp->spe) goto ballfnd; panic("Cannot find the iron ball?"); ballfnd: uball = otmp; } } if (u.ustuck) { struct monst *mtmp; for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) if (mtmp->m_id == mid) goto monfnd; panic("Cannot find the monster ustuck."); monfnd: u.ustuck = mtmp; } #ifndef QUEST setsee(); /* only to recompute seelx etc. - these * weren't saved */ #endif /* QUEST */ docrt(); restoring = FALSE; return (1); }