xref: /netbsd-src/games/hack/hack.read.c (revision 8e73b3ad763e92a803658f492d224264534c3d17)
1*8e73b3adSdholland /*	$NetBSD: hack.read.c,v 1.11 2011/08/06 20:29:37 dholland Exp $	*/
23ea4a95cSchristos 
3210cab45Smycroft /*
41c7f94e5Sjsm  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm  * Amsterdam
61c7f94e5Sjsm  * All rights reserved.
71c7f94e5Sjsm  *
81c7f94e5Sjsm  * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm  * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm  * met:
111c7f94e5Sjsm  *
121c7f94e5Sjsm  * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm  * this list of conditions and the following disclaimer.
141c7f94e5Sjsm  *
151c7f94e5Sjsm  * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm  * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm  * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm  *
191c7f94e5Sjsm  * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm  * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm  * promote products derived from this software without specific prior
221c7f94e5Sjsm  * written permission.
231c7f94e5Sjsm  *
241c7f94e5Sjsm  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm  */
361c7f94e5Sjsm 
371c7f94e5Sjsm /*
381c7f94e5Sjsm  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm  * All rights reserved.
401c7f94e5Sjsm  *
411c7f94e5Sjsm  * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm  * modification, are permitted provided that the following conditions
431c7f94e5Sjsm  * are met:
441c7f94e5Sjsm  * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm  *    notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm  * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm  *    notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm  *    documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm  * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm  *    derived from this software without specific prior written permission.
511c7f94e5Sjsm  *
521c7f94e5Sjsm  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
551c7f94e5Sjsm  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62210cab45Smycroft  */
63210cab45Smycroft 
643ea4a95cSchristos #include <sys/cdefs.h>
65210cab45Smycroft #ifndef lint
66*8e73b3adSdholland __RCSID("$NetBSD: hack.read.c,v 1.11 2011/08/06 20:29:37 dholland Exp $");
67210cab45Smycroft #endif				/* not lint */
6861f28255Scgd 
693ea4a95cSchristos #include <stdlib.h>
7061f28255Scgd #include "hack.h"
713ea4a95cSchristos #include "extern.h"
7261f28255Scgd 
739b92b189Sdholland static int identify(struct obj *);
749b92b189Sdholland static int monstersym(int);
759b92b189Sdholland 
763ea4a95cSchristos int
doread(void)771fa8a9a6Sdholland doread(void)
783ea4a95cSchristos {
793ea4a95cSchristos 	struct obj     *scroll;
803ea4a95cSchristos 	boolean         confused = (Confusion != 0);
813ea4a95cSchristos 	boolean         known = FALSE;
8261f28255Scgd 
8361f28255Scgd 	scroll = getobj("?", "read");
843ea4a95cSchristos 	if (!scroll)
853ea4a95cSchristos 		return (0);
8661f28255Scgd 	if (!scroll->dknown && Blind) {
8761f28255Scgd 		pline("Being blind, you cannot read the formula on the scroll.");
8861f28255Scgd 		return (0);
8961f28255Scgd 	}
9061f28255Scgd 	if (Blind)
9161f28255Scgd 		pline("As you pronounce the formula on it, the scroll disappears.");
9261f28255Scgd 	else
9361f28255Scgd 		pline("As you read the scroll, it disappears.");
9461f28255Scgd 	if (confused)
9561f28255Scgd 		pline("Being confused, you mispronounce the magic words ... ");
9661f28255Scgd 
9761f28255Scgd 	switch (scroll->otyp) {
9861f28255Scgd #ifdef MAIL
9961f28255Scgd 	case SCR_MAIL:
10061f28255Scgd 		readmail( /* scroll */ );
10161f28255Scgd 		break;
1023ea4a95cSchristos #endif	/* MAIL */
10361f28255Scgd 	case SCR_ENCHANT_ARMOR:
1043ea4a95cSchristos 		{
1053ea4a95cSchristos 			struct obj     *otmp = some_armor();
10661f28255Scgd 			if (!otmp) {
10761f28255Scgd 				strange_feeling(scroll, "Your skin glows then fades.");
10861f28255Scgd 				return (1);
10961f28255Scgd 			}
11061f28255Scgd 			if (confused) {
11161f28255Scgd 				pline("Your %s glows silver for a moment.",
11261f28255Scgd 				      objects[otmp->otyp].oc_name);
11361f28255Scgd 				otmp->rustfree = 1;
11461f28255Scgd 				break;
11561f28255Scgd 			}
11661f28255Scgd 			if (otmp->spe > 3 && rn2(otmp->spe)) {
11761f28255Scgd 				pline("Your %s glows violently green for a while, then evaporates.",
11861f28255Scgd 				      objects[otmp->otyp].oc_name);
11961f28255Scgd 				useup(otmp);
12061f28255Scgd 				break;
12161f28255Scgd 			}
12261f28255Scgd 			pline("Your %s glows green for a moment.",
12361f28255Scgd 			      objects[otmp->otyp].oc_name);
12461f28255Scgd 			otmp->cursed = 0;
12561f28255Scgd 			otmp->spe++;
12661f28255Scgd 			break;
12761f28255Scgd 		}
12861f28255Scgd 	case SCR_DESTROY_ARMOR:
12961f28255Scgd 		if (confused) {
1303ea4a95cSchristos 			struct obj     *otmp = some_armor();
13161f28255Scgd 			if (!otmp) {
13261f28255Scgd 				strange_feeling(scroll, "Your bones itch.");
13361f28255Scgd 				return (1);
13461f28255Scgd 			}
13561f28255Scgd 			pline("Your %s glows purple for a moment.",
13661f28255Scgd 			      objects[otmp->otyp].oc_name);
13761f28255Scgd 			otmp->rustfree = 0;
13861f28255Scgd 			break;
13961f28255Scgd 		}
14061f28255Scgd 		if (uarm) {
14161f28255Scgd 			pline("Your armor turns to dust and falls to the floor!");
14261f28255Scgd 			useup(uarm);
14361f28255Scgd 		} else if (uarmh) {
14461f28255Scgd 			pline("Your helmet turns to dust and is blown away!");
14561f28255Scgd 			useup(uarmh);
14661f28255Scgd 		} else if (uarmg) {
14761f28255Scgd 			pline("Your gloves vanish!");
14861f28255Scgd 			useup(uarmg);
14961f28255Scgd 			selftouch("You");
15061f28255Scgd 		} else {
15161f28255Scgd 			strange_feeling(scroll, "Your skin itches.");
15261f28255Scgd 			return (1);
15361f28255Scgd 		}
15461f28255Scgd 		break;
15561f28255Scgd 	case SCR_CONFUSE_MONSTER:
15661f28255Scgd 		if (confused) {
15761f28255Scgd 			pline("Your hands begin to glow purple.");
15861f28255Scgd 			Confusion += rnd(100);
15961f28255Scgd 		} else {
16061f28255Scgd 			pline("Your hands begin to glow blue.");
16161f28255Scgd 			u.umconf = 1;
16261f28255Scgd 		}
16361f28255Scgd 		break;
16461f28255Scgd 	case SCR_SCARE_MONSTER:
1653ea4a95cSchristos 		{
1663ea4a95cSchristos 			int             ct = 0;
1673ea4a95cSchristos 			struct monst   *mtmp;
16861f28255Scgd 
16961f28255Scgd 			for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
17061f28255Scgd 				if (cansee(mtmp->mx, mtmp->my)) {
17161f28255Scgd 					if (confused)
17261f28255Scgd 						mtmp->mflee = mtmp->mfroz =
17361f28255Scgd 							mtmp->msleep = 0;
17461f28255Scgd 					else
17561f28255Scgd 						mtmp->mflee = 1;
17661f28255Scgd 					ct++;
17761f28255Scgd 				}
17861f28255Scgd 			if (!ct) {
17961f28255Scgd 				if (confused)
18061f28255Scgd 					pline("You hear sad wailing in the distance.");
18161f28255Scgd 				else
18261f28255Scgd 					pline("You hear maniacal laughter in the distance.");
18361f28255Scgd 			}
18461f28255Scgd 			break;
18561f28255Scgd 		}
18661f28255Scgd 	case SCR_BLANK_PAPER:
18761f28255Scgd 		if (confused)
18861f28255Scgd 			pline("You see strange patterns on this scroll.");
18961f28255Scgd 		else
19061f28255Scgd 			pline("This scroll seems to be blank.");
19161f28255Scgd 		break;
19261f28255Scgd 	case SCR_REMOVE_CURSE:
1933ea4a95cSchristos 		{
1943ea4a95cSchristos 			struct obj     *obj;
19561f28255Scgd 			if (confused)
19661f28255Scgd 				pline("You feel like you need some help.");
19761f28255Scgd 			else
19861f28255Scgd 				pline("You feel like someone is helping you.");
19961f28255Scgd 			for (obj = invent; obj; obj = obj->nobj)
20061f28255Scgd 				if (obj->owornmask)
20161f28255Scgd 					obj->cursed = confused;
20261f28255Scgd 			if (Punished && !confused) {
20361f28255Scgd 				Punished = 0;
20461f28255Scgd 				freeobj(uchain);
20561f28255Scgd 				unpobj(uchain);
206*8e73b3adSdholland 				free(uchain);
20761f28255Scgd 				uball->spe = 0;
20861f28255Scgd 				uball->owornmask &= ~W_BALL;
20961f28255Scgd 				uchain = uball = (struct obj *) 0;
21061f28255Scgd 			}
21161f28255Scgd 			break;
21261f28255Scgd 		}
21361f28255Scgd 	case SCR_CREATE_MONSTER:
2143ea4a95cSchristos 		{
2153ea4a95cSchristos 			int             cnt = 1;
21661f28255Scgd 
2173ea4a95cSchristos 			if (!rn2(73))
2183ea4a95cSchristos 				cnt += rnd(4);
2193ea4a95cSchristos 			if (confused)
2203ea4a95cSchristos 				cnt += 12;
22161f28255Scgd 			while (cnt--)
22261f28255Scgd 				(void) makemon(confused ? PM_ACID_BLOB :
22361f28255Scgd 					 (struct permonst *) 0, u.ux, u.uy);
22461f28255Scgd 			break;
22561f28255Scgd 		}
22661f28255Scgd 	case SCR_ENCHANT_WEAPON:
22761f28255Scgd 		if (uwep && confused) {
22861f28255Scgd 			pline("Your %s glows silver for a moment.",
22961f28255Scgd 			      objects[uwep->otyp].oc_name);
23061f28255Scgd 			uwep->rustfree = 1;
2313ea4a95cSchristos 		} else if (!chwepon(scroll, 1))	/* tests for !uwep */
23261f28255Scgd 			return (1);
23361f28255Scgd 		break;
23461f28255Scgd 	case SCR_DAMAGE_WEAPON:
23561f28255Scgd 		if (uwep && confused) {
23661f28255Scgd 			pline("Your %s glows purple for a moment.",
23761f28255Scgd 			      objects[uwep->otyp].oc_name);
23861f28255Scgd 			uwep->rustfree = 0;
2393ea4a95cSchristos 		} else if (!chwepon(scroll, -1))	/* tests for !uwep */
24061f28255Scgd 			return (1);
24161f28255Scgd 		break;
24261f28255Scgd 	case SCR_TAMING:
2433ea4a95cSchristos 		{
2443ea4a95cSchristos 			int             i, j;
2453ea4a95cSchristos 			int             bd = confused ? 5 : 1;
2463ea4a95cSchristos 			struct monst   *mtmp;
24761f28255Scgd 
2483ea4a95cSchristos 			for (i = -bd; i <= bd; i++)
2493ea4a95cSchristos 				for (j = -bd; j <= bd; j++)
2503ea4a95cSchristos 					if ((mtmp = m_at(u.ux + i, u.uy + j)) != NULL)
25161f28255Scgd 						(void) tamedog(mtmp, (struct obj *) 0);
25261f28255Scgd 			break;
25361f28255Scgd 		}
25461f28255Scgd 	case SCR_GENOCIDE:
2553ea4a95cSchristos 		{
25661f28255Scgd 			char            buf[BUFSZ];
2573ea4a95cSchristos 			struct monst   *mtmp, *mtmp2;
25861f28255Scgd 
25961f28255Scgd 			pline("You have found a scroll of genocide!");
26061f28255Scgd 			known = TRUE;
26161f28255Scgd 			if (confused)
26261f28255Scgd 				*buf = u.usym;
2633ea4a95cSchristos 			else
2643ea4a95cSchristos 				do {
26561f28255Scgd 					pline("What monster do you want to genocide (Type the letter)? ");
26661f28255Scgd 					getlin(buf);
26761f28255Scgd 				} while (strlen(buf) != 1 || !monstersym(*buf));
2683ea4a95cSchristos 			if (!strchr(fut_geno, *buf))
26961f28255Scgd 				charcat(fut_geno, *buf);
2703ea4a95cSchristos 			if (!strchr(genocided, *buf))
27161f28255Scgd 				charcat(genocided, *buf);
27261f28255Scgd 			else {
27361f28255Scgd 				pline("Such monsters do not exist in this world.");
27461f28255Scgd 				break;
27561f28255Scgd 			}
27661f28255Scgd 			for (mtmp = fmon; mtmp; mtmp = mtmp2) {
27761f28255Scgd 				mtmp2 = mtmp->nmon;
27861f28255Scgd 				if (mtmp->data->mlet == *buf)
27961f28255Scgd 					mondead(mtmp);
28061f28255Scgd 			}
28161f28255Scgd 			pline("Wiped out all %c's.", *buf);
28261f28255Scgd 			if (*buf == u.usym) {
28361f28255Scgd 				killer = "scroll of genocide";
28461f28255Scgd 				u.uhp = -1;
28561f28255Scgd 			}
28661f28255Scgd 			break;
28761f28255Scgd 		}
28861f28255Scgd 	case SCR_LIGHT:
2893ea4a95cSchristos 		if (!Blind)
2903ea4a95cSchristos 			known = TRUE;
29161f28255Scgd 		litroom(!confused);
29261f28255Scgd 		break;
29361f28255Scgd 	case SCR_TELEPORTATION:
29461f28255Scgd 		if (confused)
29561f28255Scgd 			level_tele();
29661f28255Scgd 		else {
29761f28255Scgd #ifdef QUEST
2983ea4a95cSchristos 			int             oux = u.ux, ouy = u.uy;
29961f28255Scgd 			tele();
3003ea4a95cSchristos 			if (dist(oux, ouy) > 100)
3013ea4a95cSchristos 				known = TRUE;
3023ea4a95cSchristos #else	/* QUEST */
3033ea4a95cSchristos 			int             uroom = inroom(u.ux, u.uy);
30461f28255Scgd 			tele();
3053ea4a95cSchristos 			if (uroom != inroom(u.ux, u.uy))
3063ea4a95cSchristos 				known = TRUE;
3073ea4a95cSchristos #endif	/* QUEST */
30861f28255Scgd 		}
30961f28255Scgd 		break;
31061f28255Scgd 	case SCR_GOLD_DETECTION:
3113ea4a95cSchristos 		/*
3123ea4a95cSchristos 		 * Unfortunately this code has become slightly less elegant,
3133ea4a95cSchristos 		 * now that gold and traps no longer are of the same type.
3143ea4a95cSchristos 		 */
31561f28255Scgd 		if (confused) {
3163ea4a95cSchristos 			struct trap    *ttmp;
31761f28255Scgd 
31861f28255Scgd 			if (!ftrap) {
31961f28255Scgd 				strange_feeling(scroll, "Your toes stop itching.");
32061f28255Scgd 				return (1);
32161f28255Scgd 			} else {
32261f28255Scgd 				for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
32361f28255Scgd 					if (ttmp->tx != u.ux || ttmp->ty != u.uy)
32461f28255Scgd 						goto outtrapmap;
3253ea4a95cSchristos 				/*
3263ea4a95cSchristos 				 * only under me - no separate display
3273ea4a95cSchristos 				 * required
3283ea4a95cSchristos 				 */
32961f28255Scgd 				pline("Your toes itch!");
33061f28255Scgd 				break;
33161f28255Scgd 		outtrapmap:
33261f28255Scgd 				cls();
33361f28255Scgd 				for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
33461f28255Scgd 					at(ttmp->tx, ttmp->ty, '$');
33561f28255Scgd 				prme();
33661f28255Scgd 				pline("You feel very greedy!");
33761f28255Scgd 			}
33861f28255Scgd 		} else {
3393ea4a95cSchristos 			struct gold    *gtmp;
34061f28255Scgd 
34161f28255Scgd 			if (!fgold) {
34261f28255Scgd 				strange_feeling(scroll, "You feel materially poor.");
34361f28255Scgd 				return (1);
34461f28255Scgd 			} else {
34561f28255Scgd 				known = TRUE;
34661f28255Scgd 				for (gtmp = fgold; gtmp; gtmp = gtmp->ngold)
34761f28255Scgd 					if (gtmp->gx != u.ux || gtmp->gy != u.uy)
34861f28255Scgd 						goto outgoldmap;
3493ea4a95cSchristos 				/*
3503ea4a95cSchristos 				 * only under me - no separate display
3513ea4a95cSchristos 				 * required
3523ea4a95cSchristos 				 */
35361f28255Scgd 				pline("You notice some gold between your feet.");
35461f28255Scgd 				break;
35561f28255Scgd 		outgoldmap:
35661f28255Scgd 				cls();
35761f28255Scgd 				for (gtmp = fgold; gtmp; gtmp = gtmp->ngold)
35861f28255Scgd 					at(gtmp->gx, gtmp->gy, '$');
35961f28255Scgd 				prme();
36061f28255Scgd 				pline("You feel very greedy, and sense gold!");
36161f28255Scgd 			}
36261f28255Scgd 		}
36361f28255Scgd 		/* common sequel */
36461f28255Scgd 		more();
36561f28255Scgd 		docrt();
36661f28255Scgd 		break;
36761f28255Scgd 	case SCR_FOOD_DETECTION:
3683ea4a95cSchristos 		{
3693ea4a95cSchristos 			int ct = 0, ctu = 0;
3703ea4a95cSchristos 			struct obj     *obj;
3713ea4a95cSchristos 			char            foodsym = confused ? POTION_SYM : FOOD_SYM;
37261f28255Scgd 
37361f28255Scgd 			for (obj = fobj; obj; obj = obj->nobj)
37461f28255Scgd 				if (obj->olet == FOOD_SYM) {
3753ea4a95cSchristos 					if (obj->ox == u.ux && obj->oy == u.uy)
3763ea4a95cSchristos 						ctu++;
3773ea4a95cSchristos 					else
3783ea4a95cSchristos 						ct++;
37961f28255Scgd 				}
38061f28255Scgd 			if (!ct && !ctu) {
38161f28255Scgd 				strange_feeling(scroll, "Your nose twitches.");
38261f28255Scgd 				return (1);
38361f28255Scgd 			} else if (!ct) {
38461f28255Scgd 				known = TRUE;
38561f28255Scgd 				pline("You smell %s close nearby.",
38661f28255Scgd 				      confused ? "something" : "food");
38761f28255Scgd 
38861f28255Scgd 			} else {
38961f28255Scgd 				known = TRUE;
39061f28255Scgd 				cls();
39161f28255Scgd 				for (obj = fobj; obj; obj = obj->nobj)
39261f28255Scgd 					if (obj->olet == foodsym)
39361f28255Scgd 						at(obj->ox, obj->oy, FOOD_SYM);
39461f28255Scgd 				prme();
39561f28255Scgd 				pline("Your nose tingles and you smell %s!",
39661f28255Scgd 				      confused ? "something" : "food");
39761f28255Scgd 				more();
39861f28255Scgd 				docrt();
39961f28255Scgd 			}
40061f28255Scgd 			break;
40161f28255Scgd 		}
40261f28255Scgd 	case SCR_IDENTIFY:
40361f28255Scgd 		/* known = TRUE; */
40461f28255Scgd 		if (confused)
40561f28255Scgd 			pline("You identify this as an identify scroll.");
40661f28255Scgd 		else
40761f28255Scgd 			pline("This is an identify scroll.");
40861f28255Scgd 		useup(scroll);
40961f28255Scgd 		objects[SCR_IDENTIFY].oc_name_known = 1;
41061f28255Scgd 		if (!confused)
41161f28255Scgd 			while (
41261f28255Scgd 			 !ggetobj("identify", identify, rn2(5) ? 1 : rn2(5))
41361f28255Scgd 			       && invent
41461f28255Scgd 				);
41561f28255Scgd 		return (1);
41661f28255Scgd 	case SCR_MAGIC_MAPPING:
4173ea4a95cSchristos 		{
4183ea4a95cSchristos 			struct rm      *lev;
4193ea4a95cSchristos 			int             num, zx, zy;
42061f28255Scgd 
42161f28255Scgd 			known = TRUE;
42261f28255Scgd 			pline("On this scroll %s a map!",
42361f28255Scgd 			      confused ? "was" : "is");
42461f28255Scgd 			for (zy = 0; zy < ROWNO; zy++)
42561f28255Scgd 				for (zx = 0; zx < COLNO; zx++) {
4263ea4a95cSchristos 					if (confused && rn2(7))
4273ea4a95cSchristos 						continue;
42861f28255Scgd 					lev = &(levl[zx][zy]);
42961f28255Scgd 					if ((num = lev->typ) == 0)
43061f28255Scgd 						continue;
43161f28255Scgd 					if (num == SCORR) {
43261f28255Scgd 						lev->typ = CORR;
43361f28255Scgd 						lev->scrsym = CORR_SYM;
4343ea4a95cSchristos 					} else if (num == SDOOR) {
43561f28255Scgd 						lev->typ = DOOR;
43661f28255Scgd 						lev->scrsym = '+';
43761f28255Scgd 						/* do sth in doors ? */
4383ea4a95cSchristos 					} else if (lev->seen)
4393ea4a95cSchristos 						continue;
44061f28255Scgd #ifndef QUEST
44161f28255Scgd 					if (num != ROOM)
4423ea4a95cSchristos #endif	/* QUEST */
44361f28255Scgd 					{
44461f28255Scgd 						lev->seen = lev->new = 1;
44561f28255Scgd 						if (lev->scrsym == ' ' || !lev->scrsym)
44661f28255Scgd 							newsym(zx, zy);
44761f28255Scgd 						else
44861f28255Scgd 							on_scr(zx, zy);
44961f28255Scgd 					}
45061f28255Scgd 				}
45161f28255Scgd 			break;
45261f28255Scgd 		}
45361f28255Scgd 	case SCR_AMNESIA:
4543ea4a95cSchristos 		{
4553ea4a95cSchristos 			int             zx, zy;
45661f28255Scgd 
45761f28255Scgd 			known = TRUE;
4583ea4a95cSchristos 			for (zx = 0; zx < COLNO; zx++)
4593ea4a95cSchristos 				for (zy = 0; zy < ROWNO; zy++)
46061f28255Scgd 					if (!confused || rn2(7))
46161f28255Scgd 						if (!cansee(zx, zy))
46261f28255Scgd 							levl[zx][zy].seen = 0;
46361f28255Scgd 			docrt();
46461f28255Scgd 			pline("Thinking of Maud you forget everything else.");
46561f28255Scgd 			break;
46661f28255Scgd 		}
46761f28255Scgd 	case SCR_FIRE:
4683ea4a95cSchristos 		{
4693ea4a95cSchristos 			int             num = 0;
4703ea4a95cSchristos 			struct monst   *mtmp;
47161f28255Scgd 
47261f28255Scgd 			known = TRUE;
47361f28255Scgd 			if (confused) {
47461f28255Scgd 				pline("The scroll catches fire and you burn your hands.");
47561f28255Scgd 				losehp(1, "scroll of fire");
47661f28255Scgd 			} else {
47761f28255Scgd 				pline("The scroll erupts in a tower of flame!");
47861f28255Scgd 				if (Fire_resistance)
47961f28255Scgd 					pline("You are uninjured.");
48061f28255Scgd 				else {
48161f28255Scgd 					num = rnd(6);
48261f28255Scgd 					u.uhpmax -= num;
48361f28255Scgd 					losehp(num, "scroll of fire");
48461f28255Scgd 				}
48561f28255Scgd 			}
48661f28255Scgd 			num = (2 * num + 1) / 3;
48761f28255Scgd 			for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
48861f28255Scgd 				if (dist(mtmp->mx, mtmp->my) < 3) {
48961f28255Scgd 					mtmp->mhp -= num;
4903ea4a95cSchristos 					if (strchr("FY", mtmp->data->mlet))
4913ea4a95cSchristos 						mtmp->mhp -= 3 * num;	/* this might well kill
4923ea4a95cSchristos 									 * 'F's */
49361f28255Scgd 					if (mtmp->mhp < 1) {
49461f28255Scgd 						killed(mtmp);
49561f28255Scgd 						break;	/* primitive */
49661f28255Scgd 					}
49761f28255Scgd 				}
49861f28255Scgd 			}
49961f28255Scgd 			break;
50061f28255Scgd 		}
50161f28255Scgd 	case SCR_PUNISHMENT:
50261f28255Scgd 		known = TRUE;
50361f28255Scgd 		if (confused) {
50461f28255Scgd 			pline("You feel guilty.");
50561f28255Scgd 			break;
50661f28255Scgd 		}
50761f28255Scgd 		pline("You are being punished for your misbehaviour!");
50861f28255Scgd 		if (Punished) {
50961f28255Scgd 			pline("Your iron ball gets heavier.");
51061f28255Scgd 			uball->owt += 15;
51161f28255Scgd 			break;
51261f28255Scgd 		}
51361f28255Scgd 		Punished = INTRINSIC;
51461f28255Scgd 		setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN);
51561f28255Scgd 		setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL);
51661f28255Scgd 		uball->spe = 1;	/* special ball (see save) */
51761f28255Scgd 		break;
51861f28255Scgd 	default:
51961f28255Scgd 		impossible("What weird language is this written in? (%u)",
52061f28255Scgd 			   scroll->otyp);
52161f28255Scgd 	}
52261f28255Scgd 	if (!objects[scroll->otyp].oc_name_known) {
52361f28255Scgd 		if (known && !confused) {
52461f28255Scgd 			objects[scroll->otyp].oc_name_known = 1;
52561f28255Scgd 			more_experienced(0, 10);
52661f28255Scgd 		} else if (!objects[scroll->otyp].oc_uname)
52761f28255Scgd 			docall(scroll);
52861f28255Scgd 	}
52961f28255Scgd 	useup(scroll);
53061f28255Scgd 	return (1);
53161f28255Scgd }
53261f28255Scgd 
5339b92b189Sdholland static int
identify(struct obj * otmp)5341fa8a9a6Sdholland identify(struct obj *otmp)		/* also called by newmail() */
53561f28255Scgd {
53661f28255Scgd 	objects[otmp->otyp].oc_name_known = 1;
53761f28255Scgd 	otmp->known = otmp->dknown = 1;
53861f28255Scgd 	prinv(otmp);
53961f28255Scgd 	return (1);
54061f28255Scgd }
54161f28255Scgd 
5423ea4a95cSchristos void
litroom(boolean on)5431fa8a9a6Sdholland litroom(boolean on)
54461f28255Scgd {
5453ea4a95cSchristos #ifndef QUEST
5463ea4a95cSchristos 	int num, zx, zy;
5473ea4a95cSchristos #endif
54861f28255Scgd 
54961f28255Scgd 	/* first produce the text (provided he is not blind) */
5503ea4a95cSchristos 	if (Blind)
5513ea4a95cSchristos 		goto do_it;
55261f28255Scgd 	if (!on) {
55361f28255Scgd 		if (u.uswallow || !xdnstair || levl[u.ux][u.uy].typ == CORR ||
55461f28255Scgd 		    !levl[u.ux][u.uy].lit) {
55561f28255Scgd 			pline("It seems even darker in here than before.");
55661f28255Scgd 			return;
55761f28255Scgd 		} else
55861f28255Scgd 			pline("It suddenly becomes dark in here.");
55961f28255Scgd 	} else {
56061f28255Scgd 		if (u.uswallow) {
56161f28255Scgd 			pline("%s's stomach is lit.", Monnam(u.ustuck));
56261f28255Scgd 			return;
56361f28255Scgd 		}
56461f28255Scgd 		if (!xdnstair) {
56561f28255Scgd 			pline("Nothing Happens.");
56661f28255Scgd 			return;
56761f28255Scgd 		}
56861f28255Scgd #ifdef QUEST
56961f28255Scgd 		pline("The cave lights up around you, then fades.");
57061f28255Scgd 		return;
5713ea4a95cSchristos #else	/* QUEST */
57261f28255Scgd 		if (levl[u.ux][u.uy].typ == CORR) {
57361f28255Scgd 			pline("The corridor lights up around you, then fades.");
57461f28255Scgd 			return;
57561f28255Scgd 		} else if (levl[u.ux][u.uy].lit) {
57661f28255Scgd 			pline("The light here seems better now.");
57761f28255Scgd 			return;
57861f28255Scgd 		} else
57961f28255Scgd 			pline("The room is lit.");
5803ea4a95cSchristos #endif	/* QUEST */
58161f28255Scgd 	}
58261f28255Scgd 
58361f28255Scgd do_it:
58461f28255Scgd #ifdef QUEST
58561f28255Scgd 	return;
5863ea4a95cSchristos #else	/* QUEST */
58761f28255Scgd 	if (levl[u.ux][u.uy].lit == on)
58861f28255Scgd 		return;
58961f28255Scgd 	if (levl[u.ux][u.uy].typ == DOOR) {
5903ea4a95cSchristos 		if (IS_ROOM(levl[u.ux][u.uy + 1].typ))
5913ea4a95cSchristos 			zy = u.uy + 1;
5923ea4a95cSchristos 		else if (IS_ROOM(levl[u.ux][u.uy - 1].typ))
5933ea4a95cSchristos 			zy = u.uy - 1;
5943ea4a95cSchristos 		else
5953ea4a95cSchristos 			zy = u.uy;
5963ea4a95cSchristos 		if (IS_ROOM(levl[u.ux + 1][u.uy].typ))
5973ea4a95cSchristos 			zx = u.ux + 1;
5983ea4a95cSchristos 		else if (IS_ROOM(levl[u.ux - 1][u.uy].typ))
5993ea4a95cSchristos 			zx = u.ux - 1;
6003ea4a95cSchristos 		else
6013ea4a95cSchristos 			zx = u.ux;
60261f28255Scgd 	} else {
60361f28255Scgd 		zx = u.ux;
60461f28255Scgd 		zy = u.uy;
60561f28255Scgd 	}
60661f28255Scgd 	for (seelx = u.ux; (num = levl[seelx - 1][zy].typ) != CORR && num != 0;
60761f28255Scgd 	     seelx--);
60861f28255Scgd 	for (seehx = u.ux; (num = levl[seehx + 1][zy].typ) != CORR && num != 0;
60961f28255Scgd 	     seehx++);
61061f28255Scgd 	for (seely = u.uy; (num = levl[zx][seely - 1].typ) != CORR && num != 0;
61161f28255Scgd 	     seely--);
61261f28255Scgd 	for (seehy = u.uy; (num = levl[zx][seehy + 1].typ) != CORR && num != 0;
61361f28255Scgd 	     seehy++);
61461f28255Scgd 	for (zy = seely; zy <= seehy; zy++)
61561f28255Scgd 		for (zx = seelx; zx <= seehx; zx++) {
61661f28255Scgd 			levl[zx][zy].lit = on;
61704afeca6Sveego 			if (!Blind && dist(zx, zy) > 2) {
6183ea4a95cSchristos 				if (on)
6193ea4a95cSchristos 					prl(zx, zy);
6203ea4a95cSchristos 				else
6213ea4a95cSchristos 					nosee(zx, zy);
62261f28255Scgd 			}
62304afeca6Sveego 		}
6243ea4a95cSchristos 	if (!on)
6253ea4a95cSchristos 		seehx = 0;
6263ea4a95cSchristos #endif	/* QUEST */
62761f28255Scgd }
62861f28255Scgd 
62961f28255Scgd /* Test whether we may genocide all monsters with symbol  ch  */
6309b92b189Sdholland static int
monstersym(int ch)6311fa8a9a6Sdholland monstersym(int ch)		/* arnold@ucsfcgl */
63261f28255Scgd {
633ab8b6343Sjsm 	const struct permonst *mp;
63461f28255Scgd 
63561f28255Scgd 	/*
63661f28255Scgd 	 * can't genocide certain monsters
63761f28255Scgd 	 */
6383ea4a95cSchristos 	if (strchr("12 &:", ch))
63961f28255Scgd 		return FALSE;
64061f28255Scgd 
64161f28255Scgd 	if (ch == pm_eel.mlet)
64261f28255Scgd 		return TRUE;
64361f28255Scgd 	for (mp = mons; mp < &mons[CMNUM + 2]; mp++)
64461f28255Scgd 		if (mp->mlet == ch)
64561f28255Scgd 			return TRUE;
64661f28255Scgd 	return FALSE;
64761f28255Scgd }
648