NetBSD/games/hack/hack.read.c

591 lines
13 KiB
C
Raw Normal View History

/* $NetBSD: hack.read.c,v 1.6 2001/02/05 00:37:43 christos Exp $ */
1997-10-19 20:56:41 +04:00
/*
* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
*/
1997-10-19 20:56:41 +04:00
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: hack.read.c,v 1.6 2001/02/05 00:37:43 christos Exp $");
1997-10-19 20:56:41 +04:00
#endif /* not lint */
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
#include <stdlib.h>
1993-03-21 12:45:37 +03:00
#include "hack.h"
1997-10-19 20:56:41 +04:00
#include "extern.h"
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
int
doread()
{
struct obj *scroll;
boolean confused = (Confusion != 0);
boolean known = FALSE;
1993-03-21 12:45:37 +03:00
scroll = getobj("?", "read");
1997-10-19 20:56:41 +04:00
if (!scroll)
return (0);
if (!scroll->dknown && Blind) {
pline("Being blind, you cannot read the formula on the scroll.");
return (0);
1993-03-21 12:45:37 +03:00
}
1997-10-19 20:56:41 +04:00
if (Blind)
pline("As you pronounce the formula on it, the scroll disappears.");
1993-03-21 12:45:37 +03:00
else
1997-10-19 20:56:41 +04:00
pline("As you read the scroll, it disappears.");
if (confused)
pline("Being confused, you mispronounce the magic words ... ");
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
switch (scroll->otyp) {
1993-03-21 12:45:37 +03:00
#ifdef MAIL
case SCR_MAIL:
1997-10-19 20:56:41 +04:00
readmail( /* scroll */ );
1993-03-21 12:45:37 +03:00
break;
1997-10-19 20:56:41 +04:00
#endif /* MAIL */
1993-03-21 12:45:37 +03:00
case SCR_ENCHANT_ARMOR:
1997-10-19 20:56:41 +04:00
{
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++;
1993-03-21 12:45:37 +03:00
break;
}
case SCR_DESTROY_ARMOR:
1997-10-19 20:56:41 +04:00
if (confused) {
struct obj *otmp = some_armor();
if (!otmp) {
strange_feeling(scroll, "Your bones itch.");
return (1);
1993-03-21 12:45:37 +03:00
}
pline("Your %s glows purple for a moment.",
1997-10-19 20:56:41 +04:00
objects[otmp->otyp].oc_name);
1993-03-21 12:45:37 +03:00
otmp->rustfree = 0;
break;
}
1997-10-19 20:56:41 +04:00
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) {
1993-03-21 12:45:37 +03:00
pline("Your gloves vanish!");
useup(uarmg);
selftouch("You");
} else {
1997-10-19 20:56:41 +04:00
strange_feeling(scroll, "Your skin itches.");
return (1);
1993-03-21 12:45:37 +03:00
}
break;
case SCR_CONFUSE_MONSTER:
1997-10-19 20:56:41 +04:00
if (confused) {
1993-03-21 12:45:37 +03:00
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:
1997-10-19 20:56:41 +04:00
{
int ct = 0;
struct monst *mtmp;
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
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.");
1993-03-21 12:45:37 +03:00
else
1997-10-19 20:56:41 +04:00
pline("You hear maniacal laughter in the distance.");
1993-03-21 12:45:37 +03:00
}
1997-10-19 20:56:41 +04:00
break;
1993-03-21 12:45:37 +03:00
}
case SCR_BLANK_PAPER:
1997-10-19 20:56:41 +04:00
if (confused)
pline("You see strange patterns on this scroll.");
1993-03-21 12:45:37 +03:00
else
1997-10-19 20:56:41 +04:00
pline("This scroll seems to be blank.");
1993-03-21 12:45:37 +03:00
break;
case SCR_REMOVE_CURSE:
1997-10-19 20:56:41 +04:00
{
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((char *) uchain);
uball->spe = 0;
uball->owornmask &= ~W_BALL;
uchain = uball = (struct obj *) 0;
}
break;
1993-03-21 12:45:37 +03:00
}
case SCR_CREATE_MONSTER:
1997-10-19 20:56:41 +04:00
{
int cnt = 1;
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
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;
}
1993-03-21 12:45:37 +03:00
case SCR_ENCHANT_WEAPON:
1997-10-19 20:56:41 +04:00
if (uwep && confused) {
1993-03-21 12:45:37 +03:00
pline("Your %s glows silver for a moment.",
1997-10-19 20:56:41 +04:00
objects[uwep->otyp].oc_name);
1993-03-21 12:45:37 +03:00
uwep->rustfree = 1;
1997-10-19 20:56:41 +04:00
} else if (!chwepon(scroll, 1)) /* tests for !uwep */
return (1);
1993-03-21 12:45:37 +03:00
break;
case SCR_DAMAGE_WEAPON:
1997-10-19 20:56:41 +04:00
if (uwep && confused) {
1993-03-21 12:45:37 +03:00
pline("Your %s glows purple for a moment.",
1997-10-19 20:56:41 +04:00
objects[uwep->otyp].oc_name);
1993-03-21 12:45:37 +03:00
uwep->rustfree = 0;
1997-10-19 20:56:41 +04:00
} else if (!chwepon(scroll, -1)) /* tests for !uwep */
return (1);
1993-03-21 12:45:37 +03:00
break;
case SCR_TAMING:
1997-10-19 20:56:41 +04:00
{
int i, j;
int bd = confused ? 5 : 1;
struct monst *mtmp;
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
for (i = -bd; i <= bd; i++)
for (j = -bd; j <= bd; j++)
if ((mtmp = m_at(u.ux + i, u.uy + j)) != NULL)
(void) tamedog(mtmp, (struct obj *) 0);
break;
}
1993-03-21 12:45:37 +03:00
case SCR_GENOCIDE:
1997-10-19 20:56:41 +04:00
{
char buf[BUFSZ];
struct monst *mtmp, *mtmp2;
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
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;
}
1993-03-21 12:45:37 +03:00
break;
}
case SCR_LIGHT:
1997-10-19 20:56:41 +04:00
if (!Blind)
known = TRUE;
1993-03-21 12:45:37 +03:00
litroom(!confused);
break;
case SCR_TELEPORTATION:
1997-10-19 20:56:41 +04:00
if (confused)
1993-03-21 12:45:37 +03:00
level_tele();
else {
#ifdef QUEST
1997-10-19 20:56:41 +04:00
int oux = u.ux, ouy = u.uy;
1993-03-21 12:45:37 +03:00
tele();
1997-10-19 20:56:41 +04:00
if (dist(oux, ouy) > 100)
known = TRUE;
#else /* QUEST */
int uroom = inroom(u.ux, u.uy);
1993-03-21 12:45:37 +03:00
tele();
1997-10-19 20:56:41 +04:00
if (uroom != inroom(u.ux, u.uy))
known = TRUE;
#endif /* QUEST */
1993-03-21 12:45:37 +03:00
}
break;
case SCR_GOLD_DETECTION:
1997-10-19 20:56:41 +04:00
/*
* 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;
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
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;
1993-03-21 12:45:37 +03:00
outtrapmap:
1997-10-19 20:56:41 +04:00
cls();
for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
at(ttmp->tx, ttmp->ty, '$');
prme();
pline("You feel very greedy!");
}
1993-03-21 12:45:37 +03:00
} else {
1997-10-19 20:56:41 +04:00
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;
1993-03-21 12:45:37 +03:00
outgoldmap:
1997-10-19 20:56:41 +04:00
cls();
for (gtmp = fgold; gtmp; gtmp = gtmp->ngold)
at(gtmp->gx, gtmp->gy, '$');
prme();
pline("You feel very greedy, and sense gold!");
}
1993-03-21 12:45:37 +03:00
}
/* common sequel */
more();
docrt();
break;
case SCR_FOOD_DETECTION:
1997-10-19 20:56:41 +04:00
{
int ct = 0, ctu = 0;
struct obj *obj;
char foodsym = confused ? POTION_SYM : FOOD_SYM;
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
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();
1993-03-21 12:45:37 +03:00
}
1997-10-19 20:56:41 +04:00
break;
1993-03-21 12:45:37 +03:00
}
case SCR_IDENTIFY:
/* known = TRUE; */
1997-10-19 20:56:41 +04:00
if (confused)
1993-03-21 12:45:37 +03:00
pline("You identify this as an identify scroll.");
else
pline("This is an identify scroll.");
useup(scroll);
objects[SCR_IDENTIFY].oc_name_known = 1;
1997-10-19 20:56:41 +04:00
if (!confused)
while (
!ggetobj("identify", identify, rn2(5) ? 1 : rn2(5))
&& invent
);
return (1);
1993-03-21 12:45:37 +03:00
case SCR_MAGIC_MAPPING:
1997-10-19 20:56:41 +04:00
{
struct rm *lev;
int num, zx, zy;
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
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;
1993-03-21 12:45:37 +03:00
#ifndef QUEST
1997-10-19 20:56:41 +04:00
if (num != ROOM)
#endif /* QUEST */
{
lev->seen = lev->new = 1;
if (lev->scrsym == ' ' || !lev->scrsym)
newsym(zx, zy);
else
on_scr(zx, zy);
}
1993-03-21 12:45:37 +03:00
}
1997-10-19 20:56:41 +04:00
break;
}
1993-03-21 12:45:37 +03:00
case SCR_AMNESIA:
1997-10-19 20:56:41 +04:00
{
int zx, zy;
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
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;
}
1993-03-21 12:45:37 +03:00
case SCR_FIRE:
1997-10-19 20:56:41 +04:00
{
int num = 0;
struct monst *mtmp;
1993-03-21 12:45:37 +03:00
1997-10-19 20:56:41 +04:00
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");
}
1993-03-21 12:45:37 +03:00
}
1997-10-19 20:56:41 +04:00
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;
1993-03-21 12:45:37 +03:00
}
case SCR_PUNISHMENT:
known = TRUE;
1997-10-19 20:56:41 +04:00
if (confused) {
1993-03-21 12:45:37 +03:00
pline("You feel guilty.");
break;
}
pline("You are being punished for your misbehaviour!");
1997-10-19 20:56:41 +04:00
if (Punished) {
1993-03-21 12:45:37 +03:00
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);
1997-10-19 20:56:41 +04:00
uball->spe = 1; /* special ball (see save) */
1993-03-21 12:45:37 +03:00
break;
default:
impossible("What weird language is this written in? (%u)",
1997-10-19 20:56:41 +04:00
scroll->otyp);
1993-03-21 12:45:37 +03:00
}
1997-10-19 20:56:41 +04:00
if (!objects[scroll->otyp].oc_name_known) {
if (known && !confused) {
1993-03-21 12:45:37 +03:00
objects[scroll->otyp].oc_name_known = 1;
1997-10-19 20:56:41 +04:00
more_experienced(0, 10);
} else if (!objects[scroll->otyp].oc_uname)
1993-03-21 12:45:37 +03:00
docall(scroll);
}
useup(scroll);
1997-10-19 20:56:41 +04:00
return (1);
1993-03-21 12:45:37 +03:00
}
1997-10-19 20:56:41 +04:00
int
identify(otmp) /* also called by newmail() */
struct obj *otmp;
1993-03-21 12:45:37 +03:00
{
objects[otmp->otyp].oc_name_known = 1;
otmp->known = otmp->dknown = 1;
prinv(otmp);
1997-10-19 20:56:41 +04:00
return (1);
1993-03-21 12:45:37 +03:00
}
1997-10-19 20:56:41 +04:00
void
1993-03-21 12:45:37 +03:00
litroom(on)
1997-10-19 20:56:41 +04:00
boolean on;
1993-03-21 12:45:37 +03:00
{
1997-10-19 20:56:41 +04:00
#ifndef QUEST
int num, zx, zy;
#endif
1993-03-21 12:45:37 +03:00
/* first produce the text (provided he is not blind) */
1997-10-19 20:56:41 +04:00
if (Blind)
goto do_it;
if (!on) {
if (u.uswallow || !xdnstair || levl[u.ux][u.uy].typ == CORR ||
1993-03-21 12:45:37 +03:00
!levl[u.ux][u.uy].lit) {
pline("It seems even darker in here than before.");
return;
} else
pline("It suddenly becomes dark in here.");
} else {
1997-10-19 20:56:41 +04:00
if (u.uswallow) {
1993-03-21 12:45:37 +03:00
pline("%s's stomach is lit.", Monnam(u.ustuck));
return;
}
1997-10-19 20:56:41 +04:00
if (!xdnstair) {
1993-03-21 12:45:37 +03:00
pline("Nothing Happens.");
return;
}
#ifdef QUEST
pline("The cave lights up around you, then fades.");
return;
1997-10-19 20:56:41 +04:00
#else /* QUEST */
if (levl[u.ux][u.uy].typ == CORR) {
pline("The corridor lights up around you, then fades.");
return;
} else if (levl[u.ux][u.uy].lit) {
pline("The light here seems better now.");
return;
1993-03-21 12:45:37 +03:00
} else
1997-10-19 20:56:41 +04:00
pline("The room is lit.");
#endif /* QUEST */
1993-03-21 12:45:37 +03:00
}
do_it:
#ifdef QUEST
return;
1997-10-19 20:56:41 +04:00
#else /* QUEST */
if (levl[u.ux][u.uy].lit == on)
1993-03-21 12:45:37 +03:00
return;
1997-10-19 20:56:41 +04:00
if (levl[u.ux][u.uy].typ == DOOR) {
if (IS_ROOM(levl[u.ux][u.uy + 1].typ))
zy = u.uy + 1;
else if (IS_ROOM(levl[u.ux][u.uy - 1].typ))
zy = u.uy - 1;
else
zy = u.uy;
if (IS_ROOM(levl[u.ux + 1][u.uy].typ))
zx = u.ux + 1;
else if (IS_ROOM(levl[u.ux - 1][u.uy].typ))
zx = u.ux - 1;
else
zx = u.ux;
1993-03-21 12:45:37 +03:00
} else {
zx = u.ux;
zy = u.uy;
}
1997-10-19 20:56:41 +04:00
for (seelx = u.ux; (num = levl[seelx - 1][zy].typ) != CORR && num != 0;
seelx--);
for (seehx = u.ux; (num = levl[seehx + 1][zy].typ) != CORR && num != 0;
seehx++);
for (seely = u.uy; (num = levl[zx][seely - 1].typ) != CORR && num != 0;
seely--);
for (seehy = u.uy; (num = levl[zx][seehy + 1].typ) != CORR && num != 0;
seehy++);
for (zy = seely; zy <= seehy; zy++)
for (zx = seelx; zx <= seehx; zx++) {
1993-03-21 12:45:37 +03:00
levl[zx][zy].lit = on;
1998-08-30 13:19:36 +04:00
if (!Blind && dist(zx, zy) > 2) {
1997-10-19 20:56:41 +04:00
if (on)
prl(zx, zy);
else
nosee(zx, zy);
1998-08-30 13:19:36 +04:00
}
1993-03-21 12:45:37 +03:00
}
1997-10-19 20:56:41 +04:00
if (!on)
seehx = 0;
#endif /* QUEST */
1993-03-21 12:45:37 +03:00
}
/* Test whether we may genocide all monsters with symbol ch */
1997-10-19 20:56:41 +04:00
int
monstersym(ch) /* arnold@ucsfcgl */
char ch;
1993-03-21 12:45:37 +03:00
{
1997-10-19 20:56:41 +04:00
struct permonst *mp;
1993-03-21 12:45:37 +03:00
/*
* can't genocide certain monsters
*/
1997-10-19 20:56:41 +04:00
if (strchr("12 &:", ch))
1993-03-21 12:45:37 +03:00
return FALSE;
if (ch == pm_eel.mlet)
return TRUE;
1997-10-19 20:56:41 +04:00
for (mp = mons; mp < &mons[CMNUM + 2]; mp++)
1993-03-21 12:45:37 +03:00
if (mp->mlet == ch)
return TRUE;
return FALSE;
}