home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part67
< prev
next >
Wrap
Internet Message Format
|
1993-02-04
|
60KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i075: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part67/108
Message-ID: <4378@master.CNA.TEK.COM>
Date: 1 Feb 93 19:51:23 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2214
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1625
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 75
Archive-name: nethack31/Part67
Supersedes: nethack3p9: Volume 10, Issue 46-102
Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 67 (of 108)."
# Contents: dat/knox.des src/topten.c src/trap.c2
# Wrapped by billr@saab on Wed Jan 27 16:09:13 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dat/knox.des' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dat/knox.des'\"
else
echo shar: Extracting \"'dat/knox.des'\" \(3808 characters\)
sed "s/^X//" >'dat/knox.des' <<'END_OF_FILE'
X# SCCS Id: @(#)knox.des 3.1 90/02/26
X# Copyright (c) 1989 by Jean-Christophe Collet
X# Copyright (c) 1992 by Izchak Miller
X# NetHack may be freely redistributed. See license for details.
X#
XMAZE:"knox",' '
XFLAGS: noteleport
XGEOMETRY:center,center
XMAP
X----------------------------------------------------------------------------
X| |........|...............................................................|
X| |........|.................................................------------..|
X| -------+--.................................................|..........|..|
X| |........}}}}}}}....................}}}}}}}..........|..........|..|
X| |........}-----}....................}-----}..........--+--+--...|..|
X| ---........}|...|}}}}}}}}}}}}}}}}}}}}}}|...|}.................|...|..|
X| |..........}---S------------------------S---}.................|...|..|
X| |..........}}}|...............|..........|}}}.................+...|..|
X| -------..........}|...............S..........|}...................|...|..|
X| |.....|..........}|...............|......\...S}...................|...|..|
X| |.....+........}}}|...............|..........|}}}.................+...|..|
X| |.....|........}---S------------------------S---}.................|...|..|
X| |.....|........}|...|}}}}}}}}}}}}}}}}}}}}}}|...|}.................|...|..|
X| |..-S----......}-----}....................}-----}..........--+--+--...|..|
X| |..|....|......}}}}}}}....................}}}}}}}..........|..........|..|
X| |..|....|..................................................|..........|..|
X| -----------................................................------------..|
X| |..............................................................|
X----------------------------------------------------------------------------
XENDMAP
X# Non diggable walls
XNON_DIGGABLE:(00,00,75,19)
X# Portal arrival point
XBRANCH:(08,16,08,16),(0,0,0,0)
X# Throne room, with Croesus on the throne
XREGION:(37,08,46,11),lit,"throne"
XMONSTER:'@',"Croesus",(43,10),hostile
X# The Vault
X# Using unfilled morgue for
X# identification in mkmaze.c
XREGION:(21,08,35,11),lit,"morgue",unfilled
X# Corner towers
XREGION:(19,06,21,06),lit,"ordinary"
XREGION:(46,06,48,06),lit,"ordinary"
XREGION:(19,13,21,13),lit,"ordinary"
XREGION:(46,13,48,13),lit,"ordinary"
X# A welcoming committee
XREGION:(03,10,07,13),lit,"zoo",filled,true
X# Barracks
XREGION:(62,03,71,04),lit,"barracks",filled,true
X# Doors
XDOOR:closed,(06,14)
XDOOR:closed,(09,03)
XDOOR:open,(63,05)
XDOOR:open,(66,05)
XDOOR:open,(68,08)
XDOOR:locked,(08,11)
XDOOR:open,(68,11)
XDOOR:closed,(63,14)
XDOOR:closed,(66,14)
X# Soldiers guarding the fort
XMONSTER:'@',"soldier",(12,14)
XMONSTER:'@',"soldier",(12,13)
XMONSTER:'@',"soldier",(11,10)
XMONSTER:'@',"soldier",(13,02)
XMONSTER:'@',"soldier",(14,03)
XMONSTER:'@',"soldier",(20,02)
XMONSTER:'@',"soldier",(30,02)
XMONSTER:'@',"soldier",(40,02)
XMONSTER:'@',"soldier",(30,16)
XMONSTER:'@',"soldier",(32,16)
XMONSTER:'@',"soldier",(40,16)
XMONSTER:'@',"soldier",(54,16)
XMONSTER:'@',"soldier",(54,14)
XMONSTER:'@',"soldier",(54,13)
XMONSTER:'@',"soldier",(57,10)
XMONSTER:'@',"soldier",(57,09)
XMONSTER:'@',"lieutenant",(15,08)
X# Four dragons guarding each side
XMONSTER:'D',random,(18,09)
XMONSTER:'D',random,(49,10)
XMONSTER:'D',random,(33,05)
XMONSTER:'D',random,(33,14)
X# Eels in the moat
XMONSTER:';',"giant eel",(09,08)
XMONSTER:';',"giant eel",(09,11)
XMONSTER:';',"giant eel",(48,08)
XMONSTER:';',"giant eel",(48,11)
X# The corner rooms treasures
XOBJECT:'*',"diamond",(19,06)
XOBJECT:'*',"diamond",(20,06)
XOBJECT:'*',"diamond",(21,06)
XOBJECT:'*',"emerald",(19,13)
XOBJECT:'*',"emerald",(20,13)
XOBJECT:'*',"emerald",(21,13)
XOBJECT:'*',"ruby",(46,06)
XOBJECT:'*',"ruby",(47,06)
XOBJECT:'*',"ruby",(48,06)
XOBJECT:'*',"amethyst",(46,13)
XOBJECT:'*',"amethyst",(47,13)
XOBJECT:'*',"amethyst",(48,13)
END_OF_FILE
if test 3808 -ne `wc -c <'dat/knox.des'`; then
echo shar: \"'dat/knox.des'\" unpacked with wrong size!
fi
# end of 'dat/knox.des'
fi
if test -f 'src/topten.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/topten.c'\"
else
echo shar: Extracting \"'src/topten.c'\" \(18740 characters\)
sed "s/^X//" >'src/topten.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)topten.c 3.1 92/11/20 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
X#ifdef VMS
X /* We don't want to rewrite the whole file, because that entails */
X /* creating a new version which requires that the old one be deletable. */
X# define UPDATE_RECORD_IN_PLACE
X#endif
X
X/*
X * Updating in place can leave junk at the end of the file in some
X * circumstances (if it shrinks and the O.S. doesn't have a straightforward
X * way to truncate it). The trailing junk is harmless and the code
X * which reads the scores will ignore it.
X */
X#ifdef UPDATE_RECORD_IN_PLACE
X# ifndef SEEK_SET
X# define SEEK_SET 0
X# endif
Xstatic long final_fpos;
X#endif
X
X#ifdef NO_SCAN_BRACK
Xstatic void FDECL(nsb_mung_line,(char*));
Xstatic void FDECL(nsb_unmung_line,(char*));
X#endif
X
X#define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
X#define dealloc_ttentry(ttent) free((genericptr_t) (ttent))
X#define NAMSZ 10
X#define DTHSZ 60
X#define PERSMAX 3 /* entries per name/uid per char. allowed */
X#define POINTSMIN 1 /* must be > 0 */
X#define ENTRYMAX 100 /* must be >= 10 */
X
X#ifndef MICRO
X#define PERS_IS_UID /* delete for PERSMAX per name; now per uid */
X#endif
Xstruct toptenentry {
X struct toptenentry *tt_next;
X#ifdef UPDATE_RECORD_IN_PLACE
X long fpos;
X#endif
X long points;
X int deathdnum, deathlev;
X int maxlvl,hp,maxhp;
X int uid;
X char plchar;
X char sex;
X char name[NAMSZ+1];
X char death[DTHSZ+1];
X char date[7]; /* yymmdd */
X} *tt_head;
X
Xstatic void NDECL(outheader);
Xstatic int FDECL(outentry, (int,struct toptenentry *,int));
Xstatic void FDECL(readentry, (FILE *,struct toptenentry *));
Xstatic void FDECL(writeentry, (FILE *,struct toptenentry *));
Xstatic int FDECL(classmon, (CHAR_P,BOOLEAN_P));
X
X/* must fit with end.c */
Xconst char NEARDATA *killed_by_prefix[] = {
X "killed by ", "choked on ", "poisoned by ", "", "drowned in ",
X "", "crushed to death by ", "petrified by ", "",
X "", "",
X "", "", "" };
X
Xstatic void
Xreadentry(rfile,tt)
XFILE *rfile;
Xstruct toptenentry *tt;
X{
X#ifdef UPDATE_RECORD_IN_PLACE
X /* note: fscanf() below must read the record's terminating newline */
X final_fpos = tt->fpos = ftell(rfile);
X#endif
X#ifdef NO_SCAN_BRACK
X if(fscanf(rfile,"%6s %d %d %d %d %d %d %ld%*c%c%c %s %s%*c",
X# define TTFIELDS 13
X#else
X if(fscanf(rfile, "%6s %d %d %d %d %d %d %ld %c%c %[^,],%[^\n]%*c",
X# define TTFIELDS 12
X#endif
X tt->date, &tt->uid,
X &tt->deathdnum, &tt->deathlev,
X &tt->maxlvl, &tt->hp, &tt->maxhp, &tt->points,
X &tt->plchar, &tt->sex,
X#ifdef LATTICE /* return value is broken also, sigh */
X tt->name, tt->death) < 1)
X#else
X tt->name, tt->death) != TTFIELDS)
X#endif
X#undef TTFIELDS
X tt->points = 0;
X else {
X#ifdef NO_SCAN_BRACK
X if(tt->points > 0) {
X nsb_unmung_line(tt->name);
X nsb_unmung_line(tt->death);
X }
X#endif
X }
X}
X
Xstatic void
Xwriteentry(rfile,tt)
XFILE *rfile;
Xstruct toptenentry *tt;
X{
X#ifdef NO_SCAN_BRACK
X nsb_mung_line(tt->name);
X nsb_mung_line(tt->death);
X (void) fprintf(rfile,"%6s %d %d %d %d %d %d %ld %c%c %s %s\n",
X#else
X (void) fprintf(rfile,"%6s %d %d %d %d %d %d %ld %c%c %s,%s\n",
X#endif
X tt->date, tt->uid,
X tt->deathdnum, tt->deathlev,
X tt->maxlvl, tt->hp, tt->maxhp, tt->points,
X tt->plchar, tt->sex,
X onlyspace(tt->name) ? "_" : tt->name, tt->death);
X#ifdef NO_SCAN_BRACK
X nsb_unmung_line(tt->name);
X nsb_unmung_line(tt->death);
X#endif
X}
X
Xvoid
Xtopten(how)
Xint how;
X{
X int uid = getuid();
X int rank, rank0 = -1, rank1 = 0;
X int occ_cnt = PERSMAX;
X register struct toptenentry *t0, *tprev;
X struct toptenentry *t1;
X FILE *rfile;
X register int flg = 0;
X#ifdef LOGFILE
X FILE *lfile;
X#endif /* LOGFILE */
X
X#if defined(MICRO)
X#define HUP
X#else
X#define HUP if(!done_hup)
X#endif
X /* create a new 'topten' entry */
X t0 = newttentry();
X /* deepest_lev_reached() is in terms of depth(), and reporting the
X * deepest level reached in the dungeon death occurred in doesn't
X * seem right, so we have to report the death level in depth() terms
X * as well (which also seems reasonable since that's all the player
X * sees on the screen anyway)
X */
X t0->deathdnum = u.uz.dnum;
X t0->deathlev = depth(&u.uz);
X t0->maxlvl = deepest_lev_reached(TRUE);
X t0->hp = u.uhp;
X t0->maxhp = u.uhpmax;
X t0->points = u.urexp;
X t0->plchar = pl_character[0];
X t0->sex = (flags.female ? 'F' : 'M');
X t0->uid = uid;
X (void) strncpy(t0->name, plname, NAMSZ);
X t0->name[NAMSZ] = '\0';
X t0->death[0] = '\0';
X switch (killer_format) {
X default: impossible("bad killer format?");
X case KILLED_BY_AN:
X Strcat(t0->death, killed_by_prefix[how]);
X (void) strncat(t0->death, an(killer), DTHSZ);
X break;
X case KILLED_BY:
X Strcat(t0->death, killed_by_prefix[how]);
X (void) strncat(t0->death, killer, DTHSZ);
X break;
X case NO_KILLER_PREFIX:
X (void) strncat(t0->death, killer, DTHSZ);
X break;
X }
X Strcpy(t0->date, get_date());
X t0->tt_next = 0;
X#ifdef UPDATE_RECORD_IN_PLACE
X t0->fpos = -1L;
X#endif
X
X#ifdef LOGFILE /* used for debugging (who dies of what, where) */
X if (lock_file(LOGFILE, 10)) {
X if(!(lfile = fopen_datafile(LOGFILE,"a"))) {
X HUP raw_print("Cannot open log file!");
X } else {
X writeentry(lfile, t0);
X (void) fclose(lfile);
X }
X unlock_file(LOGFILE);
X }
X#endif /* LOGFILE */
X
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X if (wizard || discover) {
X raw_print("");
X raw_printf(
X "Since you were in %s mode, the score list will not be checked.",
X wizard ? "wizard" : "discover");
X return;
X }
X#endif
X
X if (!lock_file(RECORD, 60)) return;
X
X#ifdef UPDATE_RECORD_IN_PLACE
X rfile = fopen_datafile(RECORD, "r+");
X#else
X rfile = fopen_datafile(RECORD, "r");
X#endif
X
X if (!rfile) {
X HUP raw_print("Cannot open record file!");
X unlock_file(RECORD);
X return;
X }
X
X HUP raw_print("");
X
X /* assure minimum number of points */
X if(t0->points < POINTSMIN) t0->points = 0;
X
X t1 = tt_head = newttentry();
X tprev = 0;
X /* rank0: -1 undefined, 0 not_on_list, n n_th on list */
X for(rank = 1; ; ) {
X readentry(rfile, t1);
X if (t1->points < POINTSMIN) t1->points = 0;
X if(rank0 < 0 && t1->points < t0->points) {
X rank0 = rank++;
X if(tprev == 0)
X tt_head = t0;
X else
X tprev->tt_next = t0;
X t0->tt_next = t1;
X#ifdef UPDATE_RECORD_IN_PLACE
X t0->fpos = t1->fpos; /* insert here */
X#endif
X occ_cnt--;
X flg++; /* ask for a rewrite */
X } else tprev = t1;
X
X if(t1->points == 0) break;
X if(
X#ifdef PERS_IS_UID
X t1->uid == t0->uid &&
X#else
X strncmp(t1->name, t0->name, NAMSZ) == 0 &&
X#endif
X t1->plchar == t0->plchar && --occ_cnt <= 0) {
X if(rank0 < 0) {
X rank0 = 0;
X rank1 = rank;
X HUP {
X raw_printf(
X "You didn't beat your previous score of %ld points.",
X t1->points);
X raw_print("");
X }
X }
X if(occ_cnt < 0) {
X flg++;
X continue;
X }
X }
X if(rank <= ENTRYMAX) {
X t1 = t1->tt_next = newttentry();
X rank++;
X }
X if(rank > ENTRYMAX) {
X t1->points = 0;
X break;
X }
X }
X if(flg) { /* rewrite record file */
X#ifdef UPDATE_RECORD_IN_PLACE
X (void) fseek(rfile, (t0->fpos >= 0 ?
X t0->fpos : final_fpos), SEEK_SET);
X#else
X (void) fclose(rfile);
X if(!(rfile = fopen_datafile(RECORD,"w"))){
X HUP raw_print("Cannot write record file");
X unlock_file(RECORD);
X return;
X }
X#endif /* UPDATE_RECORD_IN_PLACE */
X if(!done_stopprint) if(rank0 > 0){
X if(rank0 <= 10)
X raw_print("You made the top ten list!");
X else {
X raw_printf(
X "You reached the %d%s place on the top %d list.",
X rank0, ordin(rank0), ENTRYMAX);
X }
X raw_print("");
X }
X }
X if(rank0 == 0) rank0 = rank1;
X if(rank0 <= 0) rank0 = rank;
X if(!done_stopprint) outheader();
X t1 = tt_head;
X for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
X if(flg
X#ifdef UPDATE_RECORD_IN_PLACE
X && rank >= rank0
X#endif
X ) writeentry(rfile, t1);
X if(done_stopprint) continue;
X if(rank > flags.end_top &&
X (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
X && (!flags.end_own ||
X#ifdef PERS_IS_UID
X t1->uid != t0->uid
X#else
X strncmp(t1->name, t0->name, NAMSZ)
X#endif
X )) continue;
X if(rank == rank0-flags.end_around &&
X rank0 > flags.end_top+flags.end_around+1 &&
X !flags.end_own)
X raw_print("");
X if(rank != rank0)
X (void) outentry(rank, t1, 0);
X else if(!rank1)
X (void) outentry(rank, t1, 1);
X else {
X int t0lth = outentry(0, t0, -1);
X int t1lth = outentry(rank, t1, t0lth);
X if(t1lth > t0lth) t0lth = t1lth;
X (void) outentry(0, t0, t0lth);
X }
X }
X if(rank0 >= rank) if(!done_stopprint)
X (void) outentry(0, t0, 1);
X#ifdef UPDATE_RECORD_IN_PLACE
X if (flg) {
X# ifdef TRUNCATE_FILE
X /* if a reasonable way to truncate a file exists, use it */
X truncate_file(rfile);
X# else
X /* use sentinel record rather than relying on truncation */
X t0->points = 0L; /* terminates file when read back in */
X t0->uid = t0->deathdnum = t0->deathlev = 0;
X t0->maxlvl = t0->hp = t0->maxhp = 0;
X t0->plchar = t0->sex = '-';
X Strcpy(t0->name, "@");
X Strcpy(t0->death, "<eod>\n");
X writeentry(rfile, t0);
X (void) fflush(rfile);
X# endif /* TRUNCATE_FILE */
X }
X#endif /* UPDATE_RECORD_IN_PLACE */
X (void) fclose(rfile);
X unlock_file(RECORD);
X}
X
Xstatic void
Xoutheader() {
X char linebuf[BUFSZ];
X register char *bp;
X
X Strcpy(linebuf, " No Points Name");
X bp = eos(linebuf);
X while(bp < linebuf + COLNO - 9) *bp++ = ' ';
X Strcpy(bp, "Hp [max]");
X raw_print(linebuf);
X}
X
X/* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
Xstatic int
Xoutentry(rank, t1, so)
Xregister struct toptenentry *t1;
Xregister int rank, so;
X{
X register boolean second_line = TRUE;
X char linebuf[BUFSZ], linebuf2[BUFSZ], linebuf3[BUFSZ], pbuf[BUFSZ];
X
X linebuf[0] = linebuf2[0] = linebuf3[0] = 0;
X if(rank) Sprintf(eos(linebuf), "%3d", rank);
X else Strcat(linebuf, " ");
X
X Sprintf(eos(linebuf), " %10ld %.10s", t1->points, t1->name);
X Sprintf(eos(linebuf), "-%c ", t1->plchar);
X if(!strncmp("escaped", t1->death, 7)) {
X second_line = FALSE;
X if(!strcmp(" (with the Amulet)", t1->death+7))
X Strcat(linebuf, "escaped the dungeon with the Amulet");
X else
X Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
X t1->maxlvl);
X } else if(!strncmp("ascended", t1->death, 8)) {
X Strcat(linebuf, "ascended to demigod");
X if (t1->sex == 'F') Strcat(linebuf, "dess");
X Strcat(linebuf, "-hood");
X second_line = FALSE;
X } else {
X if(!strncmp(t1->death,"quit",4)) {
X Strcat(linebuf, "quit");
X second_line = FALSE;
X } else if(!strncmp(t1->death,"starv",5)) {
X Strcat(linebuf, "starved to death");
X second_line = FALSE;
X } else if(!strncmp(t1->death,"choked",6)) {
X Sprintf(eos(linebuf), "choked on h%s food",
X (t1->sex == 'F') ? "er" : "is");
X } else if(!strncmp(t1->death,"poisoned",8)) {
X Strcat(linebuf, "was poisoned");
X } else if(!strncmp(t1->death,"crushed",7)) {
X Strcat(linebuf, "was crushed to death");
X } else if(!strncmp(t1->death, "petrified by ",13)) {
X Strcat(linebuf, "turned to stone");
X } else Strcat(linebuf, "died");
X
X if (t1->deathdnum == astral_level.dnum)
X Strcpy(linebuf3, " in the endgame");
X else
X Sprintf(linebuf3, " in %s on level %d",
X dungeons[t1->deathdnum].dname, t1->deathlev);
X if(t1->deathlev != t1->maxlvl)
X Sprintf(eos(linebuf3), " [max %d]", t1->maxlvl);
X /* kludge for "quit while already on Charon's boat" */
X if(!strncmp(t1->death, "quit ", 5))
X Strcat(linebuf3, t1->death + 4);
X }
X Strcat(linebuf3, ".");
X
X if(t1->maxhp) {
X register char *bp;
X char hpbuf[10];
X int hppos;
X int lngr = strlen(linebuf) + strlen(linebuf3);
X if (t1->hp <= 0) hpbuf[0] = '-', hpbuf[1] = '\0';
X else Sprintf(hpbuf, "%d", t1->hp);
X hppos = COLNO - 7 - (int)strlen(hpbuf);
X if (lngr >= hppos) {
X if(so > 0) {
X bp = eos(linebuf);
X while(bp < linebuf + (COLNO-1)) *bp++ = ' ';
X *bp = 0;
X raw_print_bold(linebuf);
X } else if(so == 0)
X raw_print(linebuf);
X Strcpy(linebuf, " ");
X }
X Strcat(linebuf, linebuf3);
X bp = eos(linebuf);
X
X if(bp <= linebuf + hppos) {
X /* pad any necessary blanks to the hit point entry */
X while(bp < linebuf + hppos) *bp++ = ' ';
X Strcpy(bp, hpbuf);
X if(t1->maxhp < 10)
X Sprintf(eos(bp), " [%d]", t1->maxhp);
X else if(t1->maxhp < 100)
X Sprintf(eos(bp), " [%d]", t1->maxhp);
X else Sprintf(eos(bp), " [%d]", t1->maxhp);
X }
X }
X
X/* Line 2 now contains the killer name */
X
X /* Quit, starved, ascended, and escaped contain no second line */
X if (second_line) {
X Strcpy(linebuf2, t1->death);
X *linebuf2 = highc(*linebuf2);
X Strcat(linebuf2, ".");
X }
X
X if(so == 0) {
X raw_print(linebuf);
X if (second_line)
X raw_printf(" %s", linebuf2);
X } else if(so > 0) {
X register char *bp = eos(linebuf);
X if(so >= COLNO) so = COLNO-1;
X while(bp < linebuf + so) *bp++ = ' ';
X *bp = 0;
X raw_print_bold(linebuf);
X if(second_line) {
X Sprintf(pbuf, " %s", linebuf2);
X raw_print_bold(pbuf);
X }
X }
X return((int)strlen(linebuf)+(int)strlen(linebuf2));
X}
X
X/*
X * Called with args from main if argc >= 0. In this case, list scores as
X * requested. Otherwise, find scores for the current player (and list them
X * if argc == -1).
X */
Xvoid
Xprscore(argc,argv)
Xint argc;
Xchar **argv;
X{
X const char **players;
X int playerct;
X int rank;
X register struct toptenentry *t1, *t2;
X FILE *rfile;
X register int flg = 0, i;
X char pbuf[BUFSZ];
X#ifdef nonsense
X long total_score = 0L;
X char totchars[10];
X int totcharct = 0;
X#endif
X int outflg = (argc >= -1);
X#ifdef PERS_IS_UID
X int uid = -1;
X#else
X const char *player0;
X#endif
X rfile = fopen_datafile(RECORD, "r");
X if (!rfile) {
X raw_print("Cannot open record file!");
X return;
X }
X
X /* If the score list isn't after a game, we never went through */
X /* init_dungeons() */
X if (wiz1_level.dlevel == 0) init_dungeons();
X
X if(argc > 1 && !strncmp(argv[1], "-s", 2)){
X if(!argv[1][2]){
X argc--;
X argv++;
X } else if(!argv[1][3] && index(pl_classes, argv[1][2])) {
X argv[1]++;
X argv[1][0] = '-';
X } else argv[1] += 2;
X }
X if(argc <= 1){
X#ifdef PERS_IS_UID
X uid = getuid();
X playerct = 0;
X# if defined(LINT) || defined(GCC_WARN)
X players = 0;
X# endif
X#else
X player0 = plname;
X if(!*player0)
X player0 = "hackplayer";
X playerct = 1;
X players = &player0;
X#endif
X } else {
X playerct = --argc;
X players = (const char **)++argv;
X }
X if(outflg) raw_print("");
X
X t1 = tt_head = newttentry();
X for(rank = 1; ; rank++) {
X readentry(rfile, t1);
X if(t1->points == 0) break;
X#ifdef PERS_IS_UID
X if(!playerct && t1->uid == uid)
X flg++;
X else
X#endif
X for(i = 0; i < playerct; i++){
X if(strcmp(players[i], "all") == 0 ||
X strncmp(t1->name, players[i], NAMSZ) == 0 ||
X (players[i][0] == '-' &&
X players[i][1] == t1->plchar &&
X players[i][2] == 0) ||
X (digit(players[i][0]) && rank <= atoi(players[i])))
X flg++;
X }
X t1 = t1->tt_next = newttentry();
X }
X (void) fclose(rfile);
X if(!flg) {
X if(outflg) {
X Strcpy(pbuf, "Cannot find any entries for ");
X if(playerct < 1) Strcat(pbuf, "you.");
X else {
X if(playerct > 1) Strcat(pbuf, "any of ");
X for(i=0; i<playerct; i++) {
X Strcat(pbuf, players[i]);
X if(i<playerct-1) Strcat(pbuf, ":");
X }
X raw_print(pbuf);
X raw_printf("Call is: %s -s [-role] [maxrank] [playernames]",
X hname);
X }
X }
X return;
X }
X
X if(outflg) outheader();
X t1 = tt_head;
X for(rank = 1; t1->points != 0; rank++, t1 = t2) {
X t2 = t1->tt_next;
X#ifdef PERS_IS_UID
X if(!playerct && t1->uid == uid)
X goto outwithit;
X else
X#endif
X for(i = 0; i < playerct; i++){
X if(strcmp(players[i], "all") == 0 ||
X strncmp(t1->name, players[i], NAMSZ) == 0 ||
X (players[i][0] == '-' &&
X players[i][1] == t1->plchar &&
X players[i][2] == 0) ||
X (digit(players[i][0]) && rank <= atoi(players[i]))){
X#ifdef PERS_IS_UID
X outwithit:
X#endif
X if(outflg)
X (void) outentry(rank, t1, 0);
X#ifdef nonsense
X total_score += t1->points;
X if(totcharct < sizeof(totchars)-1)
X totchars[totcharct++] = t1->plchar;
X#endif
X break;
X }
X }
X dealloc_ttentry(t1);
X }
X#ifdef nonsense
X totchars[totcharct] = 0;
X
X /* We would like to determine whether you're experienced. However,
X the information collected here only tells about the scores/roles
X that got into the topten (top 100?). We should maintain a
X .hacklog or something in his home directory. */
X flags.beginner = (total_score < 6000);
X for(i=0; i<6; i++)
X if(!index(totchars, pl_classes[i])) {
X flags.beginner = 1;
X if(!pl_character[0]) pl_character[0] = pl_classes[i];
X break;
X }
X#endif /* nonsense /**/
X}
X
Xstatic int
Xclassmon(plch, fem)
Xchar plch;
Xboolean fem;
X{
X switch (plch) {
X case 'A': return PM_ARCHEOLOGIST;
X case 'B': return PM_BARBARIAN;
X case 'C': return (fem ? PM_CAVEWOMAN : PM_CAVEMAN);
X case 'E': return PM_ELF;
X case 'H': return PM_HEALER;
X case 'F': /* accept old Fighter class */
X case 'K': return PM_KNIGHT;
X case 'P': return (fem ? PM_PRIESTESS : PM_PRIEST);
X case 'R': return PM_ROGUE;
X case 'N': /* accept old Ninja class */
X case 'S': return PM_SAMURAI;
X#ifdef TOURIST
X case 'T': return PM_TOURIST;
X#else
X case 'T': return PM_HUMAN;
X#endif
X case 'V': return PM_VALKYRIE;
X case 'W': return PM_WIZARD;
X default: impossible("What weird class is this? (%c)", plch);
X return PM_HUMAN_ZOMBIE;
X }
X}
X
X/*
X * Get a random player name and class from the high score list,
X * and attach them to an object (for statues or morgue corpses).
X */
Xstruct obj *
Xtt_oname(otmp)
Xstruct obj *otmp;
X{
X int rank;
X register int i;
X register struct toptenentry *tt;
X FILE *rfile;
X
X if (!otmp) return((struct obj *) 0);
X
X rfile = fopen_datafile(RECORD, "r");
X if (!rfile) {
X panic("Cannot open record file!");
X }
X
X tt = newttentry();
X rank = rnd(10);
Xpickentry:
X for(i = rank; i; i--) {
X readentry(rfile, tt);
X if(tt->points == 0) break;
X }
X
X if(tt->points == 0) {
X if(rank > 1) {
X rank = 1;
X rewind(rfile);
X goto pickentry;
X }
X dealloc_ttentry(tt);
X otmp = (struct obj *) 0;
X } else {
X otmp->corpsenm = classmon(tt->plchar, (tt->sex == 'F'));
X otmp->owt = weight(otmp);
X /* Note: oname() is safe since otmp is first in chains */
X otmp = oname(otmp, tt->name, 0);
X fobj = otmp;
X level.objects[otmp->ox][otmp->oy] = otmp;
X dealloc_ttentry(tt);
X }
X
X (void) fclose(rfile);
X return otmp;
X}
X
X#ifdef NO_SCAN_BRACK
X/* Lattice scanf isn't up to reading the scorefile. What */
X/* follows deals with that; I admit it's ugly. (KL) */
X/* Now generally available (KL) */
Xstatic void
Xnsb_mung_line(p)
X char *p;
X {
X while(p=index(p,' '))*p='|';
X}
X
Xstatic void
Xnsb_unmung_line(p)
X char *p;
X {
X while(p=index(p,'|'))*p=' ';
X}
X#endif
X
X/*topten.c*/
END_OF_FILE
if test 18740 -ne `wc -c <'src/topten.c'`; then
echo shar: \"'src/topten.c'\" unpacked with wrong size!
fi
# end of 'src/topten.c'
fi
if test -f 'src/trap.c2' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/trap.c2'\"
else
echo shar: Extracting \"'src/trap.c2'\" \(31932 characters\)
sed "s/^X//" >'src/trap.c2' <<'END_OF_FILE'
Xint
Xfloat_down()
X{
X register struct trap *trap = (struct trap *)0;
X boolean no_msg = FALSE;
X
X if(Levitation) return(0); /* maybe another ring/potion/boots */
X
X if (Punished && !carried(uball) &&
X (is_pool(uball->ox, uball->oy) ||
X ((trap = t_at(uball->ox, uball->oy)) &&
X ((trap->ttyp == PIT) || (trap->ttyp == SPIKED_PIT) ||
X (trap->ttyp == TRAPDOOR))))) {
X u.ux0 = u.ux;
X u.uy0 = u.uy;
X u.ux = uball->ox;
X u.uy = uball->oy;
X movobj(uchain, uball->ox, uball->oy);
X newsym(u.ux0, u.uy0);
X vision_full_recalc = 1; /* in case the hero moved. */
X }
X /* check for falling into pool - added by GAN 10/20/86 */
X#ifdef POLYSELF
X if(!is_flyer(uasmon)) {
X#endif
X /* kludge alert:
X * drown() and lava_effects() print various messages almost
X * every time they're called which conflict with the "fall
X * into" message below. Thus, we want to avoid printing
X * confusing, duplicate or out-of-order messages.
X * Use knowledge of the two routines as a hack -- this
X * should really handled differently -dlc
X */
X if(is_pool(u.ux,u.uy) && !Wwalking && !u.uinwater)
X no_msg = drown();
X
X if(is_lava(u.ux,u.uy)) {
X (void) lava_effects();
X no_msg = TRUE;
X }
X#ifdef POLYSELF
X }
X#endif
X if (!trap) {
X if(Is_airlevel(&u.uz))
X You("begin to tumble in place.");
X if(Is_waterlevel(&u.uz) && !no_msg)
X You("feel heavier.");
X /* u.uinwater msgs already in spoteffects()/drown() */
X else if (!u.uinwater && !no_msg) {
X if (Hallucination)
X pline("Bummer! You've %s.",
X is_pool(u.ux,u.uy) ?
X "splashed down" : "hit the ground");
X else
X You("float gently to the %s.",
X is_pool(u.ux,u.uy) ? "water" : "ground");
X }
X trap = t_at(u.ux,u.uy);
X }
X
X if(trap)
X switch(trap->ttyp) {
X case STATUE_TRAP:
X break;
X case TRAPDOOR:
X if(!Can_fall_thru(&u.uz) || u.ustuck)
X break;
X /* fall into next case */
X default:
X dotrap(trap);
X }
X if(!flags.nopick && OBJ_AT(u.ux, u.uy) &&
X !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) &&
X (!is_pool(u.ux,u.uy) || Underwater))
X pickup(1);
X return 0;
X}
X
X
Xvoid
Xtele()
X{
X coord cc;
X
X /* Disable teleportation in stronghold && Vlad's Tower */
X if(level.flags.noteleport) {
X#ifdef WIZARD
X if (!wizard) {
X#endif
X pline("A mysterious force prevents you from teleporting!");
X return;
X#ifdef WIZARD
X }
X#endif
X }
X
X /* don't show trap if "Sorry..." */
X if(!Blinded) make_blinded(0L,FALSE);
X
X if((u.uhave.amulet || Is_wiz1_level(&u.uz) || Is_wiz2_level(&u.uz) ||
X Is_wiz3_level(&u.uz)) && !rn2(3)) {
X You("feel disoriented for a moment.");
X return;
X }
X if(Teleport_control
X#ifdef WIZARD
X || wizard
X#endif
X ) {
X if (unconscious())
X pline("Being unconscious, you cannot control your teleport.");
X else {
X pline("To what position do you want to be teleported?");
X cc.x = u.ux;
X cc.y = u.uy;
X getpos(&cc, TRUE, "the desired position");/* force valid*/
X if(cc.x == -10) return; /* abort */
X /* possible extensions: introduce a small error if
X magic power is low; allow transfer to solid rock */
X if(teleok(cc.x, cc.y, FALSE)){
X teleds(cc.x, cc.y);
X return;
X }
X pline("Sorry...");
X }
X }
X
X (void) safe_teleds();
X}
X
Xvoid
Xteleds(nux, nuy)
Xregister int nux,nuy;
X{
X if (Punished) unplacebc();
X u.utrap = 0;
X u.ustuck = 0;
X u.ux0 = u.ux;
X u.uy0 = u.uy;
X u.ux = nux;
X u.uy = nuy;
X fill_pit(u.ux0, u.uy0); /* do this now so that cansee() is correct */
X#ifdef POLYSELF
X if (hides_under(uasmon))
X u.uundetected = OBJ_AT(nux, nuy);
X else
X u.uundetected = 0;
X if (u.usym == S_MIMIC_DEF) u.usym = S_MIMIC;
X#endif
X if(Punished) placebc();
X if(u.uswallow){
X u.uswldtim = u.uswallow = 0;
X docrt();
X }
X initrack(); /* teleports mess up tracking monsters without this */
X /*
X * Make sure the hero disappears from the old location. This will
X * not happen if she is teleported within sight of her previous
X * location. Force a full vision recalculation because the hero
X * is now in a new location.
X */
X newsym(u.ux0,u.uy0);
X vision_full_recalc = 1;
X nomul(0);
X spoteffects();
X}
X
Xint
Xdotele()
X{
X struct trap *trap;
X boolean castit = FALSE;
X register int sp_no = 0;
X
X trap = t_at(u.ux, u.uy);
X if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP))
X trap = 0;
X
X if (trap) {
X if (trap->once) {
X pline("This is a vault teleport, usable once only.");
X if (yn("Jump in?") == 'n')
X trap = 0;
X else {
X deltrap(trap);
X newsym(u.ux, u.uy);
X }
X }
X if (trap)
X#ifdef POLYSELF
X You("%s onto the teleportation trap.",
X locomotion(uasmon, "jump"));
X#else
X You("jump onto the teleportation trap.");
X#endif
X }
X if(!trap && (!Teleportation ||
X (u.ulevel < (pl_character[0] == 'W' ? 8 : 12)
X#ifdef POLYSELF
X && !can_teleport(uasmon)
X#endif
X )
X )) {
X /* Try to use teleport away spell. */
X castit = objects[SPE_TELEPORT_AWAY].oc_name_known;
X if (castit) {
X for (sp_no = 0; sp_no < MAXSPELL &&
X spl_book[sp_no].sp_id != NO_SPELL &&
X spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY; sp_no++);
X
X if (sp_no == MAXSPELL ||
X spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY)
X castit = FALSE;
X }
X#ifdef WIZARD
X if (!wizard) {
X#endif
X if (!castit) {
X if (!Teleportation)
X You("don't know that spell.");
X else You("are not able to teleport at will.");
X return(0);
X }
X#ifdef WIZARD
X }
X#endif
X }
X
X if(!trap && (u.uhunger <= 100 || ACURR(A_STR) < 6)) {
X You("lack the strength for a teleport spell.");
X#ifdef WIZARD
X if(!wizard)
X#endif
X return(1);
X }
X if(!trap &&
X check_capacity("Your concentration falters from carrying so much."))
X return 1;
X
X if (castit) {
X exercise(A_WIS, TRUE);
X if (spelleffects(++sp_no, TRUE))
X return(1);
X else
X#ifdef WIZARD
X if (!wizard)
X#endif
X return(0);
X }
X#ifdef WALKIES
X if(next_to_u()) {
X#endif
X if (trap && trap->once) vtele();
X else tele();
X#ifdef WALKIES
X (void) next_to_u();
X } else {
X You(shudder_for_moment);
X return(0);
X }
X#endif
X if (!trap) morehungry(100);
X return(1);
X}
X
X
Xvoid
Xlevel_tele()
X{
X register int newlev;
X d_level newlevel;
X
X if((u.uhave.amulet || In_endgame(&u.uz))
X#ifdef WIZARD
X && !wizard
X#endif
X ) {
X You("feel very disoriented for a moment.");
X return;
X }
X if(Teleport_control
X#ifdef WIZARD
X || wizard
X#endif
X ) {
X char buf[BUFSZ];
X
X do {
X getlin("To what level do you want to teleport? [type a number]",
X buf);
X } while(!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1])));
X newlev = atoi(buf);
X
X /* no dungeon escape via this route */
X if(newlev == 0) {
X if(ynq("Go to Nowhere. Are you sure?") != 'y') return;
X You("scream in agony as your body begins to warp...");
X display_nhwindow(WIN_MESSAGE, FALSE);
X You("cease to exist.");
X killer_format = NO_KILLER_PREFIX;
X killer = "committed suicide";
X done(DIED);
X return;
X }
X#ifdef MULDGN
X /* if in Knox and the requested level > 0, stay put.
X * we let negative values requests fall into the "heaven" loop.
X */
X if(Is_knox(&u.uz) && newlev > 0) {
X You(shudder_for_moment);
X return;
X }
X /* if in Quest, the player sees "Home 1", etc., on the status
X * line, instead of the logical depth of the level. controlled
X * level teleport request is likely to be relativized to the
X * status line, and consequently it should be incremented to
X * the value of the logical depth of the target level.
X *
X * we let negative values requests fall into the "heaven" loop.
X */
X if(In_quest(&u.uz) && newlev > 0)
X newlev = newlev + dungeons[u.uz.dnum].depth_start - 1;
X#endif
X } else { /* involuntary level tele */
X#ifdef MULDGN
X if(Is_knox(&u.uz)) {
X You(shudder_for_moment);
X return;
X }
X#endif
X if(rn2(5)) newlev = rnd((int)depth(&u.uz) + 3);
X else {
X You(shudder_for_moment);
X return;
X }
X if(newlev == depth(&u.uz)) {
X /* if in a single-level dungeon... */
X if(dunlevs_in_dungeon(&u.uz) == 1) {
X You(shudder_for_moment);
X return;
X }
X else if(dunlev(&u.uz) == 1) newlev++;
X else if(dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz)) newlev--;
X else if(In_hell(&u.uz)) newlev--;
X else newlev++;
X }
X }
X
X#ifdef WALKIES
X if(!next_to_u()) {
X You(shudder_for_moment);
X return;
X }
X#endif
X if(newlev < 0) {
X if(newlev <= -10) {
X You("arrive in heaven.");
X verbalize("Thou art early, but we'll admit thee.");
X killer_format = NO_KILLER_PREFIX;
X killer = "went to heaven prematurely";
X done(DIED);
X return;
X } else if (newlev == -9) {
X You("feel deliriously happy. ");
X pline("(In fact, you're on Cloud 9!) ");
X display_nhwindow(WIN_MESSAGE, FALSE);
X } else
X You("are now high above the clouds...");
X
X if(Levitation || is_floater(uasmon)) {
X You("float gently down to earth.");
X u.uz.dnum = 0; /* he might have been in another dgn */
X newlev = 1;
X }
X#ifdef POLYSELF
X else if(is_flyer(uasmon)) {
X You("fly down to earth.");
X u.uz.dnum = 0; /* he might have been in another dgn */
X newlev = 1;
X }
X#endif
X else {
X d_level save_dlevel;
X
X assign_level(&save_dlevel, &u.uz);
X pline("Unfortunately, you don't know how to fly.");
X You("plummet a few thousand feet to your death.");
X u.uz.dnum = 0;
X u.uz.dlevel = 0;
X killer_format = NO_KILLER_PREFIX;
X killer =
X self_pronoun("teleported out of the dungeon and fell to %s death","his");
X done(DIED);
X assign_level(&u.uz, &save_dlevel);
X flags.botl = 1;
X return;
X }
X }
X
X# ifdef WIZARD
X if (In_endgame(&u.uz)) { /* must already be wizard */
X newlevel.dnum = u.uz.dnum;
X newlevel.dlevel = newlev;
X goto_level(&newlevel, FALSE, FALSE, FALSE);
X return;
X }
X# endif
X
X /* calls done(ESCAPED) if newlevel==0 */
X if(u.uz.dnum == medusa_level.dnum &&
X newlev >= dungeons[u.uz.dnum].depth_start +
X dunlevs_in_dungeon(&u.uz)) {
X
X goto_hell(TRUE, FALSE);
X } else {
X /* if invocation did not yet occur, teleporting into
X * the last level of Gehennom is forbidden.
X */
X if(Inhell && !u.uevent.invoked &&
X newlev >= (dungeons[u.uz.dnum].depth_start +
X dunlevs_in_dungeon(&u.uz) - 1)) {
X newlev = dungeons[u.uz.dnum].depth_start +
X dunlevs_in_dungeon(&u.uz) - 2;
X pline("Sorry...");
X }
X#ifdef MULDGN
X /* no teleporting out of quest dungeon */
X if(In_quest(&u.uz) && newlev < depth(&qstart_level))
X newlev = depth(&qstart_level);
X#endif
X /* the player thinks of levels purely in logical terms, so
X * we must translate newlev to a number relative to the
X * current dungeon.
X */
X get_level(&newlevel, newlev);
X goto_level(&newlevel, FALSE, FALSE, FALSE);
X }
X}
X
Xstatic void
Xdofiretrap()
X{
X
X register int num;
X
X /* changed to be in conformance with
X * SCR_FIRE by GAN 11/02/86
X */
X
X pline("A tower of flame bursts from the floor!");
X if(Fire_resistance) {
X shieldeff(u.ux, u.uy);
X You("are uninjured.");
X } else {
X num = rnd(6);
X u.uhpmax -= num;
X losehp(num,"burst of flame", KILLED_BY_AN);
X }
X destroy_item(SCROLL_CLASS, AD_FIRE);
X destroy_item(SPBOOK_CLASS, AD_FIRE);
X destroy_item(POTION_CLASS, AD_FIRE);
X}
X
Xstatic void
Xdomagicportal(ttmp)
Xregister struct trap *ttmp;
X{
X struct d_level target_level;
X
X /* if landed from another portal, do nothing */
X /* problem: level teleport landing escapes the check */
X if(!on_level(&u.uz, &u.uz0)) return;
X
X You("activated a magic portal!");
X You("feel dizzy for a moment, but the sensation passes.");
X
X /* prevent the poor shnook, whose amulet was stolen */
X /* while in the endgame, from accidently triggering */
X /* the portal to the next level, and thus losing the */
X /* game */
X if(In_endgame(&u.uz) && !u.uhave.amulet) return;
X
X target_level = ttmp->dst;
X goto_level(&target_level, FALSE, FALSE, TRUE);
X}
X
Xstatic void
Xdomagictrap()
X{
X register int fate = rnd(20);
X
X /* What happened to the poor sucker? */
X
X if (fate < 10) {
X
X /* Most of the time, it creates some monsters. */
X register int cnt = rnd(4);
X
X /* below checks for blindness added by GAN 10/30/86 */
X if (!Blind) {
X You("are momentarily blinded by a flash of light!");
X make_blinded((long)rn1(5,10),FALSE);
X } else
X You("hear a deafening roar!");
X while(cnt--)
X (void) makemon((struct permonst *) 0, u.ux, u.uy);
X }
X else
X switch (fate) {
X
X case 10:
X case 11:
X /* sometimes nothing happens */
X break;
X case 12: /* a flash of fire */
X dofiretrap();
X break;
X
X /* odd feelings */
X case 13: pline("A shiver runs up and down your %s!",
X body_part(SPINE));
X break;
X case 14: You(Hallucination ?
X "hear the moon howling at you." :
X "hear distant howling.");
X break;
X case 15: You("suddenly yearn for %s.",
X Hallucination ? "Cleveland" :
X "your distant homeland");
X break;
X case 16: Your("pack shakes violently!");
X break;
X case 17: You(Hallucination ?
X "smell hamburgers." :
X "smell charred flesh.");
X break;
X
X /* very occasionally something nice happens. */
X
X case 19:
X /* tame nearby monsters */
X { register int i,j;
X register struct monst *mtmp;
X
X /* below pline added by GAN 10/30/86 */
X (void) adjattrib(A_CHA,1,FALSE);
X for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
X if(!isok(u.ux+i, u.uy+j)) continue;
X mtmp = m_at(u.ux+i, u.uy+j);
X if(mtmp)
X (void) tamedog(mtmp, (struct obj *)0);
X }
X break;
X }
X
X case 20:
X /* uncurse stuff */
X { register struct obj *obj;
X
X /* below plines added by GAN 10/30/86 */
X You(Hallucination ?
X "feel in touch with the Universal Oneness." :
X "feel like someone is helping you.");
X for(obj = invent; obj ; obj = obj->nobj)
X if(obj->owornmask || obj->otyp == LOADSTONE)
X uncurse(obj);
X if(Punished) unpunish();
X break;
X }
X default: break;
X }
X}
X
Xvoid
Xwater_damage(obj,force)
Xregister struct obj *obj;
Xregister boolean force;
X{
X /* Scrolls, spellbooks, potions, weapons and
X pieces of armor may get affected by the water */
X for(; obj; obj = obj->nobj) {
X
X (void) snuff_lit(obj);
X
X if(obj->greased) {
X if (force || !rn2(2)) obj->greased = 0;
X } else if(Is_container(obj) && !Is_box(obj) &&
X (obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) {
X water_damage(obj->cobj,force);
X } else if(obj->oclass == SCROLL_CLASS && (force || rn2(12) > Luck)
X#ifdef MAIL
X && obj->otyp != SCR_MAIL
X#endif
X ) {
X obj->otyp = SCR_BLANK_PAPER;
X } else if(obj->oclass == SPBOOK_CLASS && (force || rn2(12) > Luck)) {
X if (obj->otyp == SPE_BOOK_OF_THE_DEAD)
X pline("Steam rises from %s.", the(xname(obj)));
X else obj->otyp = SPE_BLANK_PAPER;
X } else if(obj->oclass == POTION_CLASS && (force || rn2(12) > Luck)) {
X if (obj->spe == -1) {
X obj->otyp = POT_WATER;
X obj->blessed = obj->cursed = 0;
X obj->spe = 0;
X } else obj->spe--;
X } else if(is_rustprone(obj) && obj->oeroded < MAX_ERODE &&
X !(obj->oerodeproof || (obj->blessed && !rnl(4))) &&
X (force || rn2(12) > Luck)) {
X /* all metal stuff and armor except body armor
X protected by oilskin cloak */
X if(obj->oclass != ARMOR_CLASS || obj != uarm ||
X !uarmc || uarmc->otyp != OILSKIN_CLOAK ||
X (uarmc->cursed && !rn2(3)))
X obj->oeroded++;
X }
X }
X}
X
X/*
X * This function is potentially expensive - rolling
X * inventory list multiple times. Luckily it's seldom needed.
X * Returns TRUE if disrobing made player unencumbered enough to
X * crawl out of the current predicament.
X */
Xstatic boolean
Xemergency_disrobe(lostsome)
Xboolean *lostsome;
X{
X int invc = inv_cnt();
X
X while (near_capacity() > (Punished ? UNENCUMBERED : SLT_ENCUMBER)) {
X register struct obj *obj, *otmp = (struct obj *)0;
X register int i = rn2(invc);
X
X for (obj = invent; obj; obj = obj->nobj) {
X /*
X * Undroppables are: body armor, boots, gloves,
X * amulets, and rings because of the time and effort
X * in removing them + loadstone and other cursed stuff
X * for obvious reasons.
X */
X if (!(obj->otyp == LOADSTONE ||
X obj == uamul || obj == uleft || obj == uright ||
X obj == ublindf || obj == uarm || obj == uarmc ||
X obj == uarmg || obj == uarmf ||
X#ifdef TOURIST
X obj == uarmu ||
X#endif
X (obj->cursed && (obj == uarmh || obj == uarms)) ||
X welded(obj)))
X otmp = obj;
X /* reached the mark and found some stuff to drop? */
X if (--i < 0 && otmp) break;
X
X /* else continue */
X }
X
X /* nothing to drop and still overweight */
X if (!otmp) return(FALSE);
X
X if (otmp == uarmh) (void) Helmet_off();
X else if (otmp == uarms) (void) Shield_off();
X else if (otmp == uwep) setuwep((struct obj *)0);
X *lostsome = TRUE;
X dropx(otmp);
X invc--;
X }
X return(TRUE);
X}
X
X/*
X * return(TRUE) == player relocated
X */
Xboolean
Xdrown()
X{
X boolean inpool_ok = FALSE, crawl_ok;
X int i, x, y;
X
X /* happily wading in the same contiguous pool */
X if (u.uinwater && is_pool(u.ux-u.dx,u.uy-u.dy) &&
X Magical_breathing) {
X /* water effects on objects every now and then */
X if (!rn2(5)) inpool_ok = TRUE;
X else return(FALSE);
X }
X
X if (!u.uinwater) {
X You("%s into the water!",
X Is_waterlevel(&u.uz) ? "plunge" : "fall");
X#ifdef POLYSELF
X if(!is_swimmer(uasmon))
X#endif
X if (!Is_waterlevel(&u.uz))
X You("sink like %s.",
X Hallucination ? "the Titanic" : "a rock");
X }
X
X water_damage(invent,FALSE);
X
X#ifdef POLYSELF
X if(u.umonnum == PM_GREMLIN && rn2(3)) {
X struct monst *mtmp;
X if(mtmp = cloneu()) {
X mtmp->mhpmax = (u.mhmax /= 2);
X You("multiply.");
X }
X }
X
X if(is_swimmer(uasmon)) return(FALSE);
X#endif
X if (inpool_ok) return(FALSE);
X#ifdef WALKIES
X if ((i = number_leashed()) > 0) {
X pline("The leash%s slip%s loose.",
X (i > 1) ? "es" : "",
X (i > 1) ? "" : "s");
X unleash_all();
X }
X#endif
X if (Magical_breathing) {
X pline("But wait!");
X Your("lungs start acting like gills.");
X if (!Is_waterlevel(&u.uz))
X Your("%s the bottom.",Hallucination ? "keel hits" : "feet touch");
X if (Punished) placebc();
X u.uinwater = 1;
X under_water(1);
X return(FALSE);
X }
X if((Teleportation || can_teleport(uasmon)) &&
X (Teleport_control || rn2(3) < Luck+2)) {
X You("attempt a teleport spell."); /* utcsri!carroll */
X (void) dotele();
X if(!is_pool(u.ux,u.uy))
X return(TRUE);
X }
X crawl_ok = FALSE;
X /* look around for a place to crawl to */
X for (i = 0; i < 100; i++) {
X x = rn1(3,u.ux - 1);
X y = rn1(3,u.uy - 1);
X if (teleok(x,y,TRUE)) {
X crawl_ok = TRUE;
X goto crawl;
X }
X }
X /* one more scan */
X for (x = u.ux - 1; x <= u.ux + 1; x++)
X for (y = u.uy - 1; y <= u.uy + 1; y++)
X if (teleok(x,y,TRUE)) {
X crawl_ok = TRUE;
X goto crawl;
X }
Xcrawl:;
X if (crawl_ok) {
X boolean lost = FALSE;
X /* time to do some strip-tease... */
X boolean succ = Is_waterlevel(&u.uz) ? TRUE :
X emergency_disrobe(&lost);
X
X You("try to crawl out of the water.");
X if (lost)
X You("dump some of your gear to lose weight...");
X if (succ) {
X pline("Pheew! That was close.");
X teleds(x,y);
X return(TRUE);
X }
X /* still too much weight */
X pline("But in vain.");
X }
X u.uinwater = 1;
X You("drown.");
X killer_format = KILLED_BY_AN;
X killer = (levl[u.ux][u.uy].typ == POOL || Is_medusa_level(&u.uz)) ?
X "pool of water" : "moat";
X done(DROWNING);
X /* oops, we're still alive. better get out of the water. */
X if (!safe_teleds())
X while (1) {
X pline("You're still drowning.");
X done(DROWNING);
X }
X u.uinwater = 0;
X You("find yourself back %s.",Is_waterlevel(&u.uz) ?
X "in an air bubble" : "on dry land");
X return(TRUE);
X}
X
Xvoid
Xdrain_en(n)
Xregister int n;
X{
X if (!u.uenmax) return;
X You("feel your magical energy drain away!");
X u.uen -= n;
X if(u.uen < 0) {
X u.uenmax += u.uen;
X if(u.uenmax < 0) u.uenmax = 0;
X u.uen = 0;
X }
X flags.botl = 1;
X}
X
Xint
Xdountrap() /* disarm a trapped object */
X{
X#ifdef POLYSELF
X if(nohands(uasmon)) {
X pline("And just how do you expect to do that?");
X return(0);
X }
X#endif
X return untrap(FALSE);
X}
X
Xint
Xuntrap(force)
Xboolean force;
X{
X register struct obj *otmp;
X register boolean confused = (Confusion > 0 || Hallucination > 0);
X register int x,y;
X int ch;
X struct trap *ttmp;
X struct monst *mtmp;
X boolean trap_skipped = FALSE;
X
X if(!getdir(NULL)) return(0);
X x = u.ux + u.dx;
X y = u.uy + u.dy;
X
X if(!u.dx && !u.dy) {
X for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
X if(Is_box(otmp)) {
X pline("There is %s here.", doname(otmp));
X
X switch (ynq("Check for traps?")) {
X case 'q': return(0);
X case 'n': continue;
X }
X
X if((otmp->otrapped && (force || (!confused
X && rn2(MAXULEV + 1 - (int)u.ulevel) < 10)))
X || (!force && confused && !rn2(3))) {
X You("find a trap on %s!", the(xname(otmp)));
X exercise(A_WIS, TRUE);
X
X switch (ynq("Disarm it?")) {
X case 'q': return(1);
X case 'n': trap_skipped = TRUE; continue;
X }
X
X if(otmp->otrapped) {
X exercise(A_DEX, TRUE);
X ch = ACURR(A_DEX) + u.ulevel;
X if (pl_character[0] == 'R') ch *= 2;
X if(!force && (confused || Fumbling ||
X rnd(75+level_difficulty()/2) > ch)) {
X (void) chest_trap(otmp, FINGER, TRUE);
X } else {
X You("disarm it!");
X otmp->otrapped = 0;
X }
X } else pline("That %s was not trapped.", doname(otmp));
X return(1);
X } else {
X You("find no traps on %s.", the(xname(otmp)));
X return(1);
X }
X }
X if ((ttmp = t_at(x,y)) && ttmp->tseen)
X You("cannot disable this trap.");
X else
X You(trap_skipped ? "find no other traps here."
X : "know of no traps here.");
X return(0);
X }
X
X if ((mtmp = m_at(x,y)) &&
X mtmp->m_ap_type == M_AP_FURNITURE &&
X (mtmp->mappearance == S_hcdoor ||
X mtmp->mappearance == S_vcdoor) &&
X !Protection_from_shape_changers) {
X
X stumble_onto_mimic(mtmp);
X return(1);
X }
X
X if (!IS_DOOR(levl[x][y].typ)) {
X if ((ttmp = t_at(x,y)) && ttmp->tseen)
X You("cannot disable that trap.");
X else
X You("know of no traps there.");
X return(0);
X }
X
X switch (levl[x][y].doormask) {
X case D_NODOOR:
X You("%s no door there.", Blind ? "feel" : "see");
X return(0);
X case D_ISOPEN:
X pline("This door is safely open.");
X return(0);
X case D_BROKEN:
X pline("This door is broken.");
X return(0);
X }
X
X if ((levl[x][y].doormask & D_TRAPPED
X && (force ||
X (!confused && rn2(MAXULEV - (int)u.ulevel + 11) < 10)))
X || (!force && confused && !rn2(3))) {
X You("find a trap on the door!");
X exercise(A_WIS, TRUE);
X if (ynq("Disarm it?") != 'y') return(1);
X if (levl[x][y].doormask & D_TRAPPED) {
X ch = 15 +
X (pl_character[0] == 'R') ? u.ulevel*3 :
X u.ulevel;
X exercise(A_DEX, TRUE);
X if(!force && (confused || Fumbling ||
X rnd(75+level_difficulty()/2) > ch)) {
X You("set it off!");
X b_trapped("door");
X } else
X You("disarm it!");
X levl[x][y].doormask &= ~D_TRAPPED;
X } else pline("This door was not trapped.");
X return(1);
X } else {
X You("find no traps on the door.");
X return(1);
X }
X}
X
X/* only called when the player is doing something to the chest directly */
Xboolean
Xchest_trap(obj, bodypart, disarm)
Xregister struct obj *obj;
Xregister int bodypart;
Xboolean disarm;
X{
X register struct obj *otmp = obj, *otmp2;
X char buf[80];
X const char *msg;
X
X You(disarm ? "set it off!" : "trigger a trap!");
X display_nhwindow(WIN_MESSAGE, FALSE);
X if (Luck > -13 && rn2(13+Luck) > 7) { /* saved by luck */
X /* trap went off, but good luck prevents damage */
X switch (rn2(13)) {
X case 12:
X case 11: msg = "explosive charge is a dud"; break;
X case 10:
X case 9: msg = "electric charge is grounded"; break;
X case 8:
X case 7: msg = "flame fizzles out"; break;
X case 6:
X case 5:
X case 4: msg = "poisoned needle misses"; break;
X case 3:
X case 2:
X case 1:
X case 0: msg = "gas cloud blows away"; break;
X default: impossible("chest disarm bug"); msg = NULL; break;
X }
X if (msg) pline("But luckily the %s!", msg);
X } else {
X switch(rn2(20) ? ((Luck >= 13) ? 0 : rn2(13-Luck)) : rn2(26)) {
X case 25:
X case 24:
X case 23:
X case 22:
X case 21: {
X register struct monst *shkp;
X long loss = 0L;
X boolean costly, insider;
X register xchar ox = obj->ox, oy = obj->oy;
X
X#ifdef GCC_WARN
X shkp = (struct monst *) 0;
X#endif
X /* the obj location need not be that of player */
X costly = (costly_spot(ox, oy) &&
X (shkp = shop_keeper(*in_rooms(ox, oy,
X SHOPBASE))) != (struct monst *)0);
X insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
X *in_rooms(ox, oy, SHOPBASE) == *u.ushops);
X
X pline("%s explodes!", The(xname(obj)));
X Sprintf(buf, "exploding %s", xname(obj));
X
X if(costly)
X loss += stolen_value(obj, ox, oy,
X (boolean)shkp->mpeaceful, TRUE);
X delete_contents(obj);
X for(otmp = level.objects[u.ux][u.uy];
X otmp; otmp = otmp2) {
X otmp2 = otmp->nexthere;
X if(costly)
X loss += stolen_value(otmp, otmp->ox,
X otmp->oy, (boolean)shkp->mpeaceful,
X TRUE);
X delobj(otmp);
X }
X exercise(A_STR, FALSE);
X losehp(d(6,6), buf, KILLED_BY_AN);
X if(costly && loss) {
X if(insider)
X You("owe %ld zorkmids for objects destroyed.",
X loss);
X else {
X You("caused %ld zorkmids worth of damage!",
X loss);
X make_angry_shk(shkp, ox, oy);
X }
X }
X wake_nearby();
X return TRUE;
X }
X case 20:
X case 19:
X case 18:
X case 17:
X pline("A cloud of noxious gas billows from %s.",
X the(xname(obj)));
X poisoned("gas cloud", A_STR, "cloud of poison gas",15);
X exercise(A_CON, FALSE);
X break;
X case 16:
X case 15:
X case 14:
X case 13:
X You("feel a needle prick your %s.",body_part(bodypart));
X poisoned("needle", A_CON, "poison needle",10);
X exercise(A_CON, FALSE);
X break;
X case 12:
X case 11:
X case 10:
X case 9:
X pline("A tower of flame erupts from %s!",
X the(xname(obj)));
X if(Fire_resistance) {
X shieldeff(u.ux, u.uy);
X You("don't seem to be affected.");
X } else losehp(d(4, 6), "tower of flame", KILLED_BY_AN);
X destroy_item(SCROLL_CLASS, AD_FIRE);
X destroy_item(SPBOOK_CLASS, AD_FIRE);
X destroy_item(POTION_CLASS, AD_FIRE);
X break;
X case 8:
X case 7:
X case 6:
X You("are jolted by a surge of electricity!");
X if(Shock_resistance) {
X shieldeff(u.ux, u.uy);
X You("don't seem to be affected.");
X } else losehp(d(4, 4), "electric shock", KILLED_BY_AN);
X destroy_item(RING_CLASS, AD_ELEC);
X destroy_item(WAND_CLASS, AD_ELEC);
X break;
X case 5:
X case 4:
X case 3:
X pline("Suddenly you are frozen in place!");
X nomul(-d(5, 6));
X exercise(A_DEX, FALSE);
X nomovemsg = "You can move again.";
X break;
X case 2:
X case 1:
X case 0:
X pline("A cloud of %s gas billows from %s",
X hcolor(), the(xname(obj)));
X if(!Stunned)
X if (Hallucination)
X pline("What a groovy feeling!");
X else
X You("stagger and your vision blurs...");
X make_stunned(HStun + rn1(7, 16),FALSE);
X make_hallucinated(HHallucination + rn1(5, 16),FALSE,0L);
X break;
X default: impossible("bad chest trap");
X break;
X }
X bot(); /* to get immediate botl re-display */
X }
X otmp->otrapped = 0; /* these traps are one-shot things */
X
X return FALSE;
X}
X
X#endif /* OVLB */
X#ifdef OVL0
X
Xstruct trap *
Xt_at(x,y)
Xregister int x, y;
X{
X register struct trap *trap = ftrap;
X while(trap) {
X if(trap->tx == x && trap->ty == y) return(trap);
X trap = trap->ntrap;
X }
X return((struct trap *)0);
X}
X
X#endif /* OVL0 */
X#ifdef OVLB
X
Xvoid
Xdeltrap(trap)
Xregister struct trap *trap;
X{
X register struct trap *ttmp;
X
X if(trap == ftrap)
X ftrap = ftrap->ntrap;
X else {
X for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
X ttmp->ntrap = trap->ntrap;
X }
X dealloc_trap(trap);
X}
X
X/* used for doors. can be used for anything else that opens. */
Xvoid
Xb_trapped(item)
Xregister const char *item;
X{
X register int lvl = level_difficulty();
X int dmg = rnd(5 + (lvl<5 ? lvl : 2+lvl/2));
X
X pline("KABOOM!! %s was booby-trapped!", The(item));
X if (u.ulevel < 4 && lvl < 3 && !rnl(3))
X You("are shaken, but luckily unhurt.");
X else losehp(dmg, "explosion", KILLED_BY_AN);
X exercise(A_STR, FALSE);
X make_stunned(HStun + dmg, TRUE);
X}
X
X/* Monster is hit by trap. */
X/* Note: doesn't work if both obj and d_override are null */
XSTATIC_OVL boolean
Xthitm(tlev, mon, obj, d_override)
Xregister int tlev;
Xregister struct monst *mon;
Xregister struct obj *obj;
Xint d_override;
X{
X register int strike;
X register boolean trapkilled = FALSE;
X
X if (d_override) strike = 1;
X else if (obj) strike = (find_mac(mon) + tlev + obj->spe <= rnd(20));
X else strike = (find_mac(mon) + tlev <= rnd(20));
X
X /* Actually more accurate than thitu, which doesn't take
X * obj->spe into account.
X */
X if(!strike) {
X if (cansee(mon->mx, mon->my))
X pline("%s is almost hit by %s!", Monnam(mon),
X doname(obj));
X } else {
X int dam = 1;
X
X if (obj && cansee(mon->mx, mon->my))
X pline("%s is hit by %s!", Monnam(mon), doname(obj));
X if (d_override) dam = d_override;
X else if (obj) {
X dam = dmgval(obj, mon->data);
X if (dam < 1) dam = 1;
X }
X if ((mon->mhp -= dam) <= 0) {
X int xx = mon->mx;
X int yy = mon->my;
X
X monkilled(mon, "", AD_PHYS);
X newsym(xx, yy);
X trapkilled = TRUE;
X }
X }
X if (obj && (!strike || d_override)) {
X place_object(obj, mon->mx, mon->my);
X obj->nobj = fobj;
X fobj = obj;
X stackobj(fobj);
X } else if (obj) dealloc_obj(obj);
X
X return trapkilled;
X}
X
Xboolean
Xunconscious()
X{
X return (multi < 0 && (!nomovemsg ||
X u.usleep ||
X !strncmp(nomovemsg,"You regain con", 15) ||
X !strncmp(nomovemsg,"You are consci", 15)));
X}
X
Xstatic char lava_killer[] = "molten lava";
X
Xboolean
Xlava_effects()
X{
X register struct obj *obj, *obj2;
X int dmg;
X
X if (!Fire_resistance) {
X if(Wwalking) {
X dmg = d(6,6);
X pline("The lava here burns you!");
X if(dmg < u.uhp) {
X losehp(dmg, lava_killer, KILLED_BY);
X goto burn_stuff;
X }
X } else
X You("fall into the lava!");
X
X for(obj = invent; obj; obj = obj2) {
X obj2 = obj->nobj;
X if(is_organic(obj) && !obj->oerodeproof) {
X if(obj->owornmask) {
X if(obj == uarm) (void) Armor_gone();
X else if(obj == uarmc) (void) Cloak_off();
X else if(obj == uarmh) (void) Helmet_off();
X else if(obj == uarms) (void) Shield_off();
X else if(obj == uarmg) (void) Gloves_off();
X else if(obj == uarmf) (void) Boots_off();
X#ifdef TOURIST
X else if(obj == uarmu) setnotworn(obj);
X#endif
X else if(obj == uleft) Ring_gone(obj);
X else if(obj == uright) Ring_gone(obj);
X else if(obj == ublindf) Blindf_off(obj);
X else if(obj == uwep) uwepgone();
X if(Lifesaved
X#ifdef WIZARD
X || wizard
X#endif
X ) Your("%s into flame!", aobjnam(obj, "burst"));
X }
X useup(obj);
X }
X }
X
X /* s/he died... */
X u.uhp = -1;
X killer_format = KILLED_BY;
X killer = lava_killer;
X You("burn to a crisp...");
X done(BURNING);
X if (!safe_teleds())
X while (1) {
X pline("You're still burning.");
X done(BURNING);
X }
X You("find yourself back on solid ground.");
X return(TRUE);
X }
X
X if (!Wwalking) {
X u.utrap = rn1(4, 4) + (rn1(4, 12) << 8);
X u.utraptype = TT_LAVA;
X You("sink into the lava, but it doesn't burn you!");
X }
X /* just want to burn boots, not all armor; destroy_item doesn't work on
X armor anyway */
Xburn_stuff:
X if(uarmf && !uarmf->oerodeproof && is_organic(uarmf)) {
X /* save uarmf value because Boots_off() sets uarmf to NULL */
X obj = uarmf;
X Your("%s burst into flame!", xname(obj));
X (void) Boots_off();
X useup(obj);
X }
X destroy_item(SCROLL_CLASS, AD_FIRE);
X destroy_item(SPBOOK_CLASS, AD_FIRE);
X destroy_item(POTION_CLASS, AD_FIRE);
X return(FALSE);
X}
X
X#endif /* OVLB */
X
X/*trap.c*/
END_OF_FILE
if test 31932 -ne `wc -c <'src/trap.c2'`; then
echo shar: \"'src/trap.c2'\" unpacked with wrong size!
fi
# end of 'src/trap.c2'
fi
echo shar: End of archive 67 \(of 108\).
cp /dev/null ark67isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
101 102 103 104 105 106 107 108 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 108 archives.
echo "Now execute 'rebuild.sh'"
rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0