Merge branch 'master' into paxed-new_lev_comp

Conflicts:
	.gitignore
	doc/fixes35.0
	include/obj.h
	include/patchlevel.h
	src/dig.c
	src/mklev.c
	src/rumors.c
	src/save.c
	src/topten.c
	src/trap.c
	sys/winnt/Makefile.msc
	util/makedefs.c
	win/win32/levstuff.mak
This commit is contained in:
Pasi Kallinen
2015-03-21 19:39:48 +02:00
49 changed files with 1670 additions and 350 deletions
+7
View File
@@ -533,6 +533,13 @@ newgame()
#endif
program_state.something_worth_saving++; /* useful data now exists */
urealtime.realtime = (time_t)0L;
#if defined(BSD) && !defined(POSIX_TYPES)
(void) time((long *)&urealtime.restored);
#else
(void) time(&urealtime.restored);
#endif
/* Success! */
welcome(TRUE);
return;
+1
View File
@@ -136,6 +136,7 @@ NEARDATA struct sysflag sysflags = DUMMY;
NEARDATA struct instance_flags iflags = DUMMY;
NEARDATA struct you u = DUMMY;
NEARDATA time_t ubirthday = DUMMY;
NEARDATA struct u_realtime urealtime = DUMMY;
schar lastseentyp[COLNO][ROWNO] = {DUMMY}; /* last seen/touched dungeon typ */
+1
View File
@@ -1321,6 +1321,7 @@ boolean at_stairs, falling, portal;
#endif
You_hear("groans and moans everywhere.");
} else pline("It is hot here. You smell smoke...");
u.uachieve.enter_gehennom = 1;
}
/* in case we've managed to bypass the Valley's stairway down */
if (Inhell && !Is_valley(&u.uz)) u.uevent.gehennom_entered = 1;
+41 -94
View File
@@ -204,9 +204,25 @@ const char *goal;
lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1;
hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1;
for (tx = lo_x; tx <= hi_x; tx++) {
k = levl[tx][ty].glyph;
/* look at dungeon feature, not at user-visible glyph */
k = back_to_glyph(tx,ty);
/* uninteresting background glyph */
if (glyph_is_cmap(k) &&
matching[glyph_to_cmap(k)]) {
(IS_DOOR(levl[tx][ty].typ) ||
glyph_to_cmap(k) == S_room ||
glyph_to_cmap(k) == S_corr ||
glyph_to_cmap(k) == S_litcorr)) {
/* what the hero remembers to be at tx,ty */
k = glyph_at(tx, ty);
}
if (glyph_is_cmap(k) &&
matching[glyph_to_cmap(k)] &&
levl[tx][ty].seenv &&
(!IS_WALL(levl[tx][ty].typ)) &&
(levl[tx][ty].typ != SDOOR) &&
glyph_to_cmap(k) != S_room &&
glyph_to_cmap(k) != S_corr &&
glyph_to_cmap(k) != S_litcorr) {
cx = tx, cy = ty;
if (msg_given) {
clear_nhwindow(WIN_MESSAGE);
@@ -793,10 +809,10 @@ boolean called;
/* Put the actual monster name or type into the buffer now */
/* Be sure to remember whether the buffer starts with a name */
if (do_hallu) {
const char *rname = rndmonnam();
char rnamecode;
char *rname = rndmonnam(&rnamecode);
Strcat(buf, rname);
name_at_start = bogon_is_pname(rname);
name_at_start = bogon_is_pname(rnamecode);
} else if (has_mname(mtmp)) {
char *name = MNAME(mtmp);
@@ -990,113 +1006,44 @@ char *outbuf;
return outbuf;
}
/*
* Name prefix codes (same as shknam.c):
* dash - female, personal name
* underscore _ female, general name
* plus + male, personal name
* vertical bar | male, general name
* equals = gender not specified, personal name
*/
static const char * const bogusmons[] = {
"jumbo shrimp", "giant pigmy", "gnu", "killer penguin",
"giant cockroach", "giant slug", "maggot", "pterodactyl",
"tyrannosaurus rex", "basilisk", "beholder", "nightmare",
"efreeti", "marid", "rot grub", "bookworm", "master lichen",
"shadow", "hologram", "jester", "attorney", "sleazoid",
"killer tomato", "amazon", "robot", "battlemech",
"rhinovirus", "harpy", "lion-dog", "rat-ant", "Y2K bug",
/* misc. */
"grue", "Christmas-tree monster", "luck sucker", "paskald",
"brogmoid", "dornbeast", /* Quendor (Zork, &c.) */
"Ancient Multi-Hued Dragon", "+Evil Iggy",
/* Moria */
"emu", "kestrel", "xeroc", "venus flytrap",
/* Rogue */
"creeping coins", /* Wizardry */
"hydra", "siren", /* Greek legend */
"killer bunny", /* Monty Python */
"rodent of unusual size", /* The Princess Bride */
"were-rabbit", /* Wallace & Gromit */
"+Smokey Bear", /* "Only you can prevent forest fires!" */
"Luggage", /* Discworld */
"Ent", /* Lord of the Rings */
"tangle tree", "nickelpede", "wiggle", /* Xanth */
"white rabbit", "snark", /* Lewis Carroll */
"pushmi-pullyu", /* Dr. Dolittle */
"smurf", /* The Smurfs */
"tribble", "Klingon", "Borg", /* Star Trek */
"Ewok", /* Star Wars */
"Totoro", /* Tonari no Totoro */
"ohmu", /* Nausicaa */
"youma", /* Sailor Moon */
"nyaasu", /* Pokemon (Meowth) */
"-Godzilla", "+King Kong", /* monster movies */
"earthquake beast", /* old L of SH */
"Invid", /* Robotech */
"Terminator", /* The Terminator */
"boomer", /* Bubblegum Crisis */
"Dalek", /* Dr. Who ("Exterminate!") */
"microscopic space fleet", "Ravenous Bugblatter Beast of Traal",
/* HGttG */
"teenage mutant ninja turtle", /* TMNT */
"samurai rabbit", /* Usagi Yojimbo */
"aardvark", /* Cerebus */
"=Audrey II", /* Little Shop of Horrors */
"witch doctor", "one-eyed one-horned flying purple people eater",
/* 50's rock 'n' roll */
"+Barney the dinosaur", /* saccharine kiddy TV */
"+Morgoth", /* Angband */
"Vorlon", /* Babylon 5 */
"questing beast", /* King Arthur */
"Predator", /* Movie */
"mother-in-law" /* common pest */
};
#define BOGUSMONSIZE 100 /* arbitrary */
/* return a random monster name, for hallucination */
const char *
rndmonnam()
char *
rndmonnam(code)
char *code;
{
const char *mname;
static char buf[BUFSZ];
char *mname = buf;
int name;
if (code) *code = '\0';
do {
name = rn1(SPECIAL_PM + SIZE(bogusmons) - LOW_PM, LOW_PM);
name = rn1(SPECIAL_PM + BOGUSMONSIZE - LOW_PM, LOW_PM);
} while (name < SPECIAL_PM &&
(type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN)));
if (name >= SPECIAL_PM) {
mname = bogusmons[name - SPECIAL_PM];
get_rnd_text(BOGUSMONFILE, buf);
/* strip prefix if present */
if (!letter(*mname)) ++mname;
if (!letter(*mname)) {
if (code) *code = *mname;
++mname;
}
} else {
mname = mons[name].mname;
Strcpy(buf, mons[name].mname);
}
return mname;
}
#undef BOGUSMONSIZE
/* scan bogusmons to check whether this name is in the list and has a prefix */
boolean
bogon_is_pname(mname)
const char *mname;
bogon_is_pname(code)
char code;
{
const char *bname;
int name;
if (!mname || !*mname) return FALSE;
if (!strncmpi(mname, "the ", 4)) mname += 4;
/* scan the bogusmons[] list; case sensitive here */
for (name = 0; name < SIZE(bogusmons); name++) {
bname = bogusmons[name];
/* we can skip all ordinary entries */
if (letter(*bname)) continue;
/* starts with a classification code; does rest of name match? */
if (!strcmp(mname, bname + 1))
return index("-+=", *bname) ? TRUE : FALSE;
}
return FALSE;
if (!code) return FALSE;
return index("-+=", code) ? TRUE : FALSE;
}
const char *
+1 -1
View File
@@ -391,7 +391,7 @@ Helmet_on(VOID_ARGS)
properties, including levitation; uarmh could get
dropped or destroyed here */
uchangealign((u.ualign.type != A_NEUTRAL) ? -u.ualign.type :
rn2(2) ? A_CHAOTIC : A_LAWFUL, 1);
(uarmh->o_id % 2) ? A_CHAOTIC : A_LAWFUL, 1);
/* makeknown(uarmh->otyp); -- moved below, after xname() */
/*FALLTHRU*/
case DUNCE_CAP:
+2
View File
@@ -672,6 +672,8 @@ struct level_map {
{ "wizard1", &wiz1_level },
{ "wizard2", &wiz2_level },
{ "wizard3", &wiz3_level },
{ "minend", &mineend_level },
{ "soko1", &sokoend_level },
{ X_START, &qstart_level },
{ X_LOCATE, &qlocate_level },
{ X_GOAL, &nemesis_level },
+1 -1
View File
@@ -1252,7 +1252,7 @@ const char *mesg;
what = "chicken";
which = 1; /* suppress pluralization */
} else if (Hallucination) {
what = rndmonnam();
what = rndmonnam(NULL);
} else {
what = mons[mnum].mname;
if (the_unique_pm(&mons[mnum])) which = 2;
+1
View File
@@ -911,6 +911,7 @@ die:
topten figure it out separately and possibly getting different
time or even day if player is slow responding to --More-- */
endtime = getnow();
urealtime.realtime += (endtime - urealtime.restored);
/* Sometimes you die on the first move. Life's not fair.
* On those rare occasions you get hosed immediately, go out
+9 -64
View File
@@ -9,33 +9,6 @@
STATIC_VAR NEARDATA struct engr *head_engr;
/* random engravings */
static const char *random_mesg[] = {
"Elbereth",
/* trap engravings */
"Vlad was here", "ad aerarium",
/* take-offs and other famous engravings */
"Owlbreath", "Galadriel",
"Kilroy was here",
"A.S. ->", "<- A.S.", /* Journey to the Center of the Earth */
"You won't get it up the steps", /* Adventure */
"Lasciate ogni speranza o voi ch'entrate.", /* Inferno */
"Well Come", /* Prisoner */
"We apologize for the inconvenience.", /* So Long... */
"See you next Wednesday", /* Thriller */
"notary sojak", /* Smokey Stover */
"For a good time call 8?7-5309",
"Please don't feed the animals.", /* Various zoos around the world */
"Madam, in Eden, I'm Adam.", /* A palindrome */
"Two thumbs up!", /* Siskel & Ebert */
"Hello, World!", /* The First C Program */
#ifdef MAIL
"You've got mail!", /* AOL */
#endif
"As if!", /* Clueless */
"BAD WOLF", /* 200x incarnation of Dr.Who */
};
char *
random_engraving(outbuf)
char *outbuf;
@@ -44,8 +17,10 @@ char *outbuf;
/* a random engraving may come from the "rumors" file,
or from the list above */
if (!rn2(4) || !(rumor = getrumor(0, outbuf, TRUE)) || !*rumor)
Strcpy(outbuf, random_mesg[rn2(SIZE(random_mesg))]);
if (!rn2(4) || !(rumor = getrumor(0, outbuf, TRUE)) || !*rumor) {
char buf[BUFSZ];
Strcpy(outbuf, get_rnd_text(ENGRAVEFILE, buf));
}
wipeout_text(outbuf, (int)(strlen(outbuf) / 4), 0);
return outbuf;
@@ -1232,39 +1207,6 @@ struct engr *ep;
}
/* Epitaphs for random headstones */
static const char *epitaphs[] = {
"Rest in peace",
"R.I.P.",
"Rest In Pieces",
"Note -- there are NO valuable items in this grave",
"1994-1995. The Longest-Lived Hacker Ever",
"The Grave of the Unknown Hacker",
"We weren't sure who this was, but we buried him here anyway",
"Sparky -- he was a very good dog",
"Beware of Electric Third Rail",
"Made in Taiwan",
"Og friend. Og good dude. Og died. Og now food",
"Beetlejuice Beetlejuice Beetlejuice",
"Look out below!",
"Please don't dig me up. I'm perfectly happy down here. -- Resident",
"Postman, please note forwarding address: Gehennom, Asmodeus's Fortress, fifth lemure on the left",
"Mary had a little lamb/Its fleece was white as snow/When Mary was in trouble/The lamb was first to go",
"Be careful, or this could happen to you!",
"Soon you'll join this fellow in hell! -- the Wizard of Yendor",
"Caution! This grave contains toxic waste",
"Sum quod eris",
"Here lies an Atheist, all dressed up and no place to go",
"Here lies Ezekiel, age 102. The good die young.",
"Here lies my wife: Here let her lie! Now she's at rest and so am I.",
"Here lies Johnny Yeast. Pardon me for not rising.",
"He always lied while on the earth and now he's lying in it",
"I made an ash of myself",
"Soon ripe. Soon rotten. Soon gone. But not forgotten.",
"Here lies the body of Jonathan Blake. Stepped on the gas instead of the brake.",
"Go away!"
};
/* Create a headstone at the given location.
* The caller is responsible for newsym(x, y).
*/
@@ -1280,9 +1222,12 @@ const char *str;
levl[x][y].typ = GRAVE;
/* Engrave the headstone */
if (!str) str = epitaphs[rn2(SIZE(epitaphs))];
del_engr_at(x, y);
make_engr_at(x, y, str, 0L, HEADSTONE);
if (str) make_engr_at(x, y, str, 0L, HEADSTONE);
else {
char buf[BUFSZ];
make_engr_at(x, y, get_rnd_text(EPITAPHFILE, buf), 0L, HEADSTONE);
}
return;
}
+2 -2
View File
@@ -283,7 +283,7 @@ int expltype;
so avoid any which begins with a capital letter) */
do {
Sprintf(hallu_buf, "%s explosion",
s_suffix(rndmonnam()));
s_suffix(rndmonnam(NULL)));
} while (*hallu_buf != lowc(*hallu_buf));
str = hallu_buf;
}
@@ -365,7 +365,7 @@ int expltype;
if (do_hallu) { /* (see explanation above) */
do {
Sprintf(hallu_buf, "%s explosion",
s_suffix(rndmonnam()));
s_suffix(rndmonnam(NULL)));
} while (*hallu_buf != lowc(*hallu_buf));
str = hallu_buf;
}
+1 -1
View File
@@ -39,7 +39,7 @@ dowatersnakes() /* Fountain of snakes! */
if (!(mvitals[PM_WATER_MOCCASIN].mvflags & G_GONE)) {
if (!Blind)
pline("An endless stream of %s pours forth!",
Hallucination ? makeplural(rndmonnam()) : "snakes");
Hallucination ? makeplural(rndmonnam(NULL)) : "snakes");
else
You_hear("%s hissing!", something);
while(num-- > 0)
+34
View File
@@ -26,6 +26,7 @@ NetHack, except that rounddiv may call panic().
char chrcasecpy (int,int)
char * strcasecpy (char *,const char *)
char * s_suffix (const char *)
char * ing_suffix (const char *)
char * xcrypt (const char *, char *)
boolean onlyspace (const char *)
char * tabexpand (char *)
@@ -235,6 +236,39 @@ s_suffix(s) /* return a name converted to possessive */
return buf;
}
char *
ing_suffix(s)
const char *s;
{
const char *vowel = "aeiouy";
static char buf[BUFSZ];
char onoff[10];
char *p;
Strcpy(buf, s);
p = eos(buf);
onoff[0] = *p = *(p+1) = '\0';
if ((strlen(buf) > 4) &&
(!strcmpi(p-3, " on") ||
!strcmpi(p-4, " off") ||
!strcmpi(p-5, " with"))) {
p = strrchr(buf, ' ');
Strcpy(onoff, p);
}
if (!index(vowel, *(p-1)) && index(vowel, *(p-2)) && !index(vowel, *(p-3))) {
/* tip -> tipp + ing */
*p = *(p-1);
*(p+1) = '\0';
} else if (!strcmpi(p-2, "ie")) { /* vie -> vy + ing */
*(p-2) = 'y';
*(p-1) = '\0';
} else if (*(p-1) == 'e') /* grease -> greas + ing */
*(p-1) = '\0';
Strcat(buf, "ing");
if (onoff[0]) Strcat(buf, onoff);
return buf;
}
char *
xcrypt(str, buf) /* trivial text encryption routine (see makedefs) */
const char *str;
+28 -1
View File
@@ -240,15 +240,19 @@ struct obj *obj;
} else if (obj->otyp == AMULET_OF_YENDOR) {
if (u.uhave.amulet) impossible("already have amulet?");
u.uhave.amulet = 1;
u.uachieve.amulet = 1;
} else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
if (u.uhave.menorah) impossible("already have candelabrum?");
u.uhave.menorah = 1;
u.uachieve.menorah = 1;
} else if (obj->otyp == BELL_OF_OPENING) {
if (u.uhave.bell) impossible("already have silver bell?");
u.uhave.bell = 1;
u.uachieve.bell = 1;
} else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
if (u.uhave.book) impossible("already have the book?");
u.uhave.book = 1;
u.uachieve.book = 1;
} else if (obj->oartifact) {
if (is_quest_artifact(obj)) {
if (u.uhave.questart)
@@ -258,6 +262,15 @@ struct obj *obj;
}
set_artifact_intrinsic(obj, 1, W_ART);
}
if(obj->otyp == LUCKSTONE && obj->record_achieve_special) {
u.uachieve.mines_luckstone = 1;
obj->record_achieve_special = 0;
} else if((obj->otyp == AMULET_OF_REFLECTION ||
obj->otyp == BAG_OF_HOLDING) &&
obj->record_achieve_special) {
u.uachieve.finish_sokoban = 1;
obj->record_achieve_special = 0;
}
}
/*
@@ -959,7 +972,21 @@ register const char *let,*word;
return((struct obj *)0);
}
if(ilet == '-') {
return(allownone ? &zeroobj : (struct obj *) 0);
if (!allownone) {
char *suf = NULL;
strcpy(buf, word);
if ((bp = strstr(buf, " on the ")) != NULL) { /* rub on the stone[s] */
*bp = '\0';
suf = (bp + 1);
}
if ((bp = strstr(buf, " or ")) != NULL) {
*bp = '\0';
bp = (rn2(2) ? buf : (bp + 4));
} else bp = buf;
You("mime %s something%s%s.", ing_suffix(bp),
suf ? " " : "", suf ? suf : "");
}
return(allownone ? &zeroobj : (struct obj *) 0);
}
if(ilet == def_oc_syms[COIN_CLASS].sym) {
if (!usegold) {
+2
View File
@@ -1605,6 +1605,8 @@ register struct monst *mtmp;
}
if(mtmp->iswiz) wizdead();
if(mtmp->data->msound == MS_NEMESIS) nemdead();
if(mtmp->data == &mons[PM_MEDUSA])
u.uachieve.killed_medusa = 1;
if(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
unmap_object(mtmp->mx, mtmp->my);
m_detach(mtmp, mptr);
+1 -1
View File
@@ -88,7 +88,7 @@ struct obj *obj;
if (vis) {
pline("As %s opens the bottle, an enormous %s emerges!",
mon_nam(mon),
Hallucination ? rndmonnam() : (const char *)"ghost");
Hallucination ? rndmonnam(NULL) : (const char *)"ghost");
pline("%s is frightened to death, and unable to move.",
Monnam(mon));
}
+1 -1
View File
@@ -2040,7 +2040,7 @@ struct obj *box;
(void) add_to_container(box, deadcat);
}
pline_The("%s inside the box is dead!",
Hallucination ? rndmonnam() : "housecat");
Hallucination ? rndmonnam(NULL) : "housecat");
}
box->owt = weight(box);
return;
+1 -1
View File
@@ -371,7 +371,7 @@ ghost_from_bottle()
return;
}
pline("As you open the bottle, an enormous %s emerges!",
Hallucination ? rndmonnam() : (const char *)"ghost");
Hallucination ? rndmonnam(NULL) : (const char *)"ghost");
if(flags.verbose)
You("are frightened to death, and unable to move.");
nomul(-3);
+1
View File
@@ -1373,6 +1373,7 @@ dosacrifice()
done(ESCAPED);
} else { /* super big win */
adjalign(10);
u.uachieve.ascended = 1;
pline("An invisible choir sings, and you are bathed in radiance...");
godvoice(altaralign, "Congratulations, mortal!");
display_nhwindow(WIN_MESSAGE, FALSE);
+3 -2
View File
@@ -284,13 +284,14 @@ char *pname; /* caller-supplied output buffer */
boolean do_hallu = Hallucination,
aligned_priest = mon->data == &mons[PM_ALIGNED_PRIEST],
high_priest = mon->data == &mons[PM_HIGH_PRIEST];
const char *what = do_hallu ? rndmonnam() : mon->data->mname;
char whatcode = '\0';
const char *what = do_hallu ? rndmonnam(&whatcode) : mon->data->mname;
if (!mon->ispriest && !mon->isminion) /* should never happen... */
return strcpy(pname, what); /* caller must be confused */
*pname = '\0';
if (!do_hallu || !bogon_is_pname(what)) Strcat(pname, "the ");
if (!do_hallu || !bogon_is_pname(whatcode)) Strcat(pname, "the ");
if (mon->minvis) Strcat(pname, "invisible ");
if (mon->isminion && EMIN(mon)->renegade)
Strcat(pname, "renegade ");
+14 -3
View File
@@ -551,9 +551,20 @@ unsigned int *stuckid, *steedid;
amii_setpens(amii_numcolors); /* use colors from save file */
#endif
mread(fd, (genericptr_t) &u, sizeof(struct you));
mread(fd, (genericptr_t) timebuf, 14);
timebuf[14] = '\0';
ubirthday = time_from_yyyymmddhhmmss(timebuf);
#define ReadTimebuf(foo) mread(fd, (genericptr_t) timebuf, 14); \
timebuf[14] = '\0'; \
foo = time_from_yyyymmddhhmmss(timebuf);
ReadTimebuf(ubirthday);
ReadTimebuf(urealtime.realtime);
ReadTimebuf(urealtime.restored);
#if defined(BSD) && !defined(POSIX_TYPES)
(void) time((long *)&urealtime.restored);
#else
(void) time(&urealtime.restored);
#endif
set_uasmon();
#ifdef CLIPPING
+40
View File
@@ -266,6 +266,46 @@ rumor_check()
}
}
/* Gets a random line of text from file 'fname', and returns it. */
char *
get_rnd_text(fname, buf)
const char *fname;
char *buf;
{
dlb *fh;
buf[0] = '\0';
fh = dlb_fopen(fname, "r");
if (fh) {
/* TODO: cache sizetxt, starttxt, endtxt. maybe cache file contents? */
long sizetxt = 0, starttxt = 0, endtxt = 0, tidbit = 0;
char *endp, line[BUFSZ], xbuf[BUFSZ];
(void) dlb_fgets(line, sizeof line, fh); /* skip "don't edit" comment */
(void) dlb_fseek(fh, 0L, SEEK_CUR);
starttxt = dlb_ftell(fh);
(void) dlb_fseek(fh, 0L, SEEK_END);
endtxt = dlb_ftell(fh);
sizetxt = endtxt - starttxt;
tidbit = Rand() % sizetxt;
(void) dlb_fseek(fh, starttxt + tidbit, SEEK_SET);
(void) dlb_fgets(line, sizeof line, fh);
if (!dlb_fgets(line, sizeof line, fh)) {
(void) dlb_fseek(fh, starttxt, SEEK_SET);
(void) dlb_fgets(line, sizeof line, fh);
}
if ((endp = index(line, '\n')) != 0) *endp = 0;
Strcat(buf, xcrypt(line, xbuf));
(void) dlb_fclose(fh);
} else impossible("Can't open file %s!", fname);
return buf;
}
void
outrumor(truth, mechanism)
int truth; /* 1=true, -1=false, 0=either */
+3
View File
@@ -307,8 +307,11 @@ register int fd, mode;
#ifdef SYSFLAGS
bwrite(fd, (genericptr_t) &sysflags, sizeof(struct sysflag));
#endif
urealtime.realtime += (getnow() - urealtime.restored);
bwrite(fd, (genericptr_t) &u, sizeof(struct you));
bwrite(fd, yyyymmddhhmmss(ubirthday), 14);
bwrite(fd, yyyymmddhhmmss(urealtime.realtime), 14);
bwrite(fd, yyyymmddhhmmss(urealtime.restored), 14);
save_killers(fd, mode);
/* must come before migrating_objs and migrating_mons are freed */
+1 -1
View File
@@ -1006,7 +1006,7 @@ dochat()
if (!Blind) {
if (Hallucination) {
/* if you're hallucinating, you can't tell it's a statue */
pline_The("%s seems not to notice you.", rndmonnam());
pline_The("%s seems not to notice you.", rndmonnam(NULL));
}
else {
pline_The("statue seems not to notice you.");
+12
View File
@@ -1639,6 +1639,18 @@ struct mkroom *croom;
}
}
/* Nasty hack here: try to determine if this is the Mines or Sokoban
* "prize" and then set record_achieve_special (maps to corpsenm)
* for the object. That field will later be checked to find out if
* the player obtained the prize. */
if(otmp->otyp == LUCKSTONE && Is_mineend_level(&u.uz)) {
otmp->record_achieve_special = 1;
} else if((otmp->otyp == AMULET_OF_REFLECTION ||
otmp->otyp == BAG_OF_HOLDING) &&
Is_sokoend_level(&u.uz)) {
otmp->record_achieve_special = 1;
}
stackobj(otmp);
if (o->lit) {
+1 -1
View File
@@ -164,7 +164,7 @@ slime_dialogue()
if (!Blind) /* [what if you're already green?] */
pline(buf, hcolor(NH_GREEN));
} else
pline(buf, an(Hallucination ? rndmonnam() : "green slime"));
pline(buf, an(Hallucination ? rndmonnam(NULL) : "green slime"));
} else
pline1(buf);
}
+112
View File
@@ -65,6 +65,9 @@ STATIC_DCL void FDECL(outentry, (int,struct toptenentry *,BOOLEAN_P));
STATIC_DCL void FDECL(discardexcess, (FILE *));
STATIC_DCL void FDECL(readentry, (FILE *,struct toptenentry *));
STATIC_DCL void FDECL(writeentry, (FILE *,struct toptenentry *));
STATIC_DCL void FDECL(writexlentry, (FILE*, struct toptenentry *));
STATIC_DCL long NDECL(encodeconduct);
STATIC_DCL long NDECL(encodeachieve);
STATIC_DCL void FDECL(free_ttlist, (struct toptenentry *));
STATIC_DCL int FDECL(classmon, (char *,BOOLEAN_P));
STATIC_DCL int FDECL(score_wanted,
@@ -292,6 +295,100 @@ struct toptenentry *tt;
#endif
}
/* as tab is never used in eg. plname or death, no need to mangle those. */
STATIC_OVL void
writexlentry(rfile,tt)
FILE *rfile;
struct toptenentry *tt;
{
#define Fprintf (void)fprintf
#define XLOG_SEP '\t' /* xlogfile field separator. */
char buf[BUFSZ];
Sprintf(buf, "version=%d.%d.%d",
tt->ver_major, tt->ver_minor, tt->patchlevel);
Sprintf(eos(buf), "%cpoints=%ld%cdeathdnum=%d%cdeathlev=%d",
XLOG_SEP, tt->points,
XLOG_SEP, tt->deathdnum,
XLOG_SEP, tt->deathlev);
Sprintf(eos(buf), "%cmaxlvl=%d%chp=%d%cmaxhp=%d",
XLOG_SEP, tt->maxlvl,
XLOG_SEP, tt->hp,
XLOG_SEP, tt->maxhp);
Sprintf(eos(buf), "%cdeaths=%d%cdeathdate=%ld%cbirthdate=%ld%cuid=%d",
XLOG_SEP, tt->deaths,
XLOG_SEP, tt->deathdate,
XLOG_SEP, tt->birthdate,
XLOG_SEP, tt->uid);
Fprintf(rfile, "%s", buf);
Sprintf(buf, "%crole=%s%crace=%s%cgender=%s%calign=%s",
XLOG_SEP, tt->plrole,
XLOG_SEP, tt->plrace,
XLOG_SEP, tt->plgend,
XLOG_SEP, tt->plalign);
Fprintf(rfile, "%s%cname=%s%cdeath=%s",
buf, /* (already includes separator) */
XLOG_SEP, plname,
XLOG_SEP, tt->death);
Fprintf(rfile, "%cconduct=0x%lx%cturns=%ld%cachieve=0x%lx",
XLOG_SEP, encodeconduct(),
XLOG_SEP, moves,
XLOG_SEP, encodeachieve());
Fprintf(rfile, "%crealtime=%ld%cstarttime=%ld%cendtime=%ld",
XLOG_SEP, (long)urealtime.realtime,
XLOG_SEP, (long)ubirthday,
XLOG_SEP, (long)urealtime.endtime);
Fprintf(rfile, "%cgender0=%s%calign0=%s",
XLOG_SEP, genders[flags.initgend].filecode,
XLOG_SEP, aligns[1 - u.ualignbase[A_ORIGINAL]].filecode);
Fprintf(rfile, "\n");
#undef XLOG_SEP
}
STATIC_OVL long
encodeconduct()
{
long e = 0L;
if(!u.uconduct.food) e |= 1L << 0;
if(!u.uconduct.unvegan) e |= 1L << 1;
if(!u.uconduct.unvegetarian) e |= 1L << 2;
if(!u.uconduct.gnostic) e |= 1L << 3;
if(!u.uconduct.weaphit) e |= 1L << 4;
if(!u.uconduct.killer) e |= 1L << 5;
if(!u.uconduct.literate) e |= 1L << 6;
if(!u.uconduct.polypiles) e |= 1L << 7;
if(!u.uconduct.polyselfs) e |= 1L << 8;
if(!u.uconduct.wishes) e |= 1L << 9;
if(!u.uconduct.wisharti) e |= 1L << 10;
if(!num_genocides()) e |= 1L << 11;
return e;
}
STATIC_OVL long
encodeachieve()
{
long r = 0L;
if(u.uachieve.bell) r |= 1L << 0;
if(u.uachieve.enter_gehennom) r |= 1L << 1;
if(u.uachieve.menorah) r |= 1L << 2;
if(u.uachieve.book) r |= 1L << 3;
if(u.uevent.invoked) r |= 1L << 4;
if(u.uachieve.amulet) r |= 1L << 5;
if(In_endgame(&u.uz)) r |= 1L << 6;
if(Is_astralevel(&u.uz)) r |= 1L << 7;
if(u.uachieve.ascended) r |= 1L << 8;
if(u.uachieve.mines_luckstone) r |= 1L << 9;
if(u.uachieve.finish_sokoban) r |= 1L << 10;
if(u.uachieve.killed_medusa) r |= 1L << 11;
return r;
}
STATIC_OVL void
free_ttlist(tt)
struct toptenentry *tt;
@@ -322,6 +419,9 @@ time_t when;
#ifdef LOGFILE
FILE *lfile;
#endif /* LOGFILE */
#ifdef XLOGFILE
FILE *xlfile;
#endif /* XLOGFILE */
/* Under DICE 3.0, this crashes the system consistently, apparently due to
* corruption of *rfile somewhere. Until I figure this out, just cut out
@@ -380,6 +480,7 @@ time_t when;
t0->birthdate = yyyymmdd(ubirthday);
t0->deathdate = yyyymmdd(when);
t0->tt_next = 0;
urealtime.endtime = when;
#ifdef UPDATE_RECORD_IN_PLACE
t0->fpos = -1L;
#endif
@@ -395,6 +496,17 @@ time_t when;
unlock_file(LOGFILE);
}
#endif /* LOGFILE */
#ifdef XLOGFILE
if (lock_file(XLOGFILE, SCOREPREFIX, 10)) {
if(!(xlfile = fopen_datafile(XLOGFILE, "a", SCOREPREFIX))) {
HUP raw_print("Cannot open extended log file!");
} else {
writexlentry(xlfile, t0);
(void) fclose(xlfile);
}
unlock_file(XLOGFILE);
}
#endif /* XLOGFILE */
if (wizard || discover) {
if (how != PANICKED) HUP {
+46 -9
View File
@@ -621,7 +621,7 @@ int *fail_reason;
"statue");
pline("%s %s!", upstart(statuename), comes_to_life);
} else if (Hallucination) { /* They don't know it's a statue */
pline_The("%s suddenly seems more animated.", rndmonnam());
pline_The("%s suddenly seems more animated.", rndmonnam(NULL));
} else if (cause == ANIMATE_SHATTER) {
if (cansee(x, y))
Sprintf(statuename, "%s%s", shk_your(tmpbuf, statue),
@@ -3145,6 +3145,14 @@ struct obj *obj;
erode_obj(obj, NULL, ERODE_CORRODE, EF_GREASE | EF_VERBOSE);
}
/* context for water_damage(), managed by water_damage_chain();
when more than one stack of potions of acid explode while processing
a chain of objects, use alternate phrasing after the first message */
static struct h2o_ctx {
int dkn_boom, unk_boom; /* track dknown, !dknown separately */
boolean ctx_valid;
} acid_ctx = { 0, 0, FALSE };
/* Get an object wet and damage it appropriately.
* "ostr", if present, is used instead of the object name in some
* messages.
@@ -3158,6 +3166,7 @@ const char *ostr;
boolean force;
{
boolean exploded = FALSE;
if (!obj) return ER_NOTHING;
if (snuff_lit(obj))
return ER_DAMAGED;
@@ -3201,18 +3210,36 @@ boolean force;
return ER_DAMAGED;
} else if (obj->oclass == POTION_CLASS) {
if (obj->otyp == POT_ACID) {
char *bufp, buf[BUFSZ];
boolean one = (obj->quan == 1L);
boolean update = carried(obj);
char *bufp;
boolean one = (obj->quan == 1L),
update = carried(obj),
exploded = FALSE;
bufp = strcpy(buf, "potion");
if (!one) bufp = makeplural(bufp);
/* [should we damage player/monster?] */
if (Blind && !carried(obj)) obj->dknown = 0;
if (acid_ctx.ctx_valid)
exploded = ((obj->dknown ? acid_ctx.dkn_boom
: acid_ctx.unk_boom) > 0);
/* First message is
* "a [potion|<color> potion|potion of acid] explodes"
* depending on obj->dknown (potion has been seen) and
* objects[POT_ACID].oc_name_known (fully discovered),
* or "some {plural version} explode" when relevant.
* Second and subsequent messages for same chain and
* matching dknown status are
* "another [potion|<color> &c] explodes" or plural
* variant.
*/
bufp = simpleonames(obj);
pline("%s %s %s!", /* "A potion explodes!" */
!exploded ? (one ? "A" : "Some") :
(one ? "Another" : "More"),
(one ? "Another" : "More"),
bufp, vtense(bufp, "explode"));
exploded = TRUE;
if (acid_ctx.ctx_valid) {
if (obj->dknown)
acid_ctx.dkn_boom++;
else
acid_ctx.unk_boom++;
}
setnotworn(obj);
delobj(obj);
if (update)
@@ -3244,10 +3271,20 @@ struct obj *obj;
boolean here;
{
struct obj *otmp;
/* initialize acid context: so far, neither seen (dknown) potions of
acid nor unseen have exploded during this water damage sequence */
acid_ctx.dkn_boom = acid_ctx.unk_boom = 0;
acid_ctx.ctx_valid = TRUE;
for (; obj; obj = otmp) {
otmp = here ? obj->nexthere : obj->nobj;
water_damage(obj, NULL, FALSE);
}
/* reset acid context */
acid_ctx.dkn_boom = acid_ctx.unk_boom = 0;
acid_ctx.ctx_valid = FALSE;
}
/*
+1
View File
@@ -500,6 +500,7 @@ u_init()
(void) memset((genericptr_t)&u, 0, sizeof(u));
u.ustuck = (struct monst *)0;
(void) memset((genericptr_t)&ubirthday, 0, sizeof(ubirthday));
(void) memset((genericptr_t)&urealtime, 0, sizeof(urealtime));
#if 0 /* documentation of more zero values as desirable */
u.usick_cause[0] = 0;
+1 -1
View File
@@ -1799,7 +1799,7 @@ struct obj *obj, *otmp;
if (break_statue(obj)) {
if (cansee(obj->ox, obj->oy)) {
if (Hallucination)
pline_The("%s shatters.", rndmonnam());
pline_The("%s shatters.", rndmonnam(NULL));
else
pline_The("statue shatters.");
} else