xref: /openbsd-src/games/hack/hack.read.c (revision aed906e4b20d9afbda31247cdb6acf6f29da8819)
1*aed906e4Smestre /*	$OpenBSD: hack.read.c,v 1.9 2016/01/09 18:33:15 mestre Exp $	*/
2d0b779f3Sniklas 
3df930be7Sderaadt /*
4d25013f2Scamield  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5d25013f2Scamield  * Amsterdam
6d25013f2Scamield  * All rights reserved.
7d25013f2Scamield  *
8d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
9d25013f2Scamield  * modification, are permitted provided that the following conditions are
10d25013f2Scamield  * met:
11d25013f2Scamield  *
12d25013f2Scamield  * - Redistributions of source code must retain the above copyright notice,
13d25013f2Scamield  * this list of conditions and the following disclaimer.
14d25013f2Scamield  *
15d25013f2Scamield  * - Redistributions in binary form must reproduce the above copyright
16d25013f2Scamield  * notice, this list of conditions and the following disclaimer in the
17d25013f2Scamield  * documentation and/or other materials provided with the distribution.
18d25013f2Scamield  *
19d25013f2Scamield  * - Neither the name of the Stichting Centrum voor Wiskunde en
20d25013f2Scamield  * Informatica, nor the names of its contributors may be used to endorse or
21d25013f2Scamield  * promote products derived from this software without specific prior
22d25013f2Scamield  * written permission.
23d25013f2Scamield  *
24d25013f2Scamield  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25d25013f2Scamield  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26d25013f2Scamield  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27d25013f2Scamield  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28d25013f2Scamield  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31d25013f2Scamield  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32d25013f2Scamield  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33d25013f2Scamield  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34d25013f2Scamield  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35d25013f2Scamield  */
36d25013f2Scamield 
37d25013f2Scamield /*
38d25013f2Scamield  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39d25013f2Scamield  * All rights reserved.
40d25013f2Scamield  *
41d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
42d25013f2Scamield  * modification, are permitted provided that the following conditions
43d25013f2Scamield  * are met:
44d25013f2Scamield  * 1. Redistributions of source code must retain the above copyright
45d25013f2Scamield  *    notice, this list of conditions and the following disclaimer.
46d25013f2Scamield  * 2. Redistributions in binary form must reproduce the above copyright
47d25013f2Scamield  *    notice, this list of conditions and the following disclaimer in the
48d25013f2Scamield  *    documentation and/or other materials provided with the distribution.
49d25013f2Scamield  * 3. The name of the author may not be used to endorse or promote products
50d25013f2Scamield  *    derived from this software without specific prior written permission.
51d25013f2Scamield  *
52d25013f2Scamield  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53d25013f2Scamield  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54d25013f2Scamield  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55d25013f2Scamield  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58d25013f2Scamield  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59d25013f2Scamield  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60d25013f2Scamield  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61d25013f2Scamield  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62df930be7Sderaadt  */
63df930be7Sderaadt 
644a5fbbc4Spjanzen #include <stdlib.h>
65*aed906e4Smestre 
66df930be7Sderaadt #include "hack.h"
67df930be7Sderaadt 
684a5fbbc4Spjanzen static boolean monstersym(char);
69df930be7Sderaadt 
704a5fbbc4Spjanzen int
doread(void)71*aed906e4Smestre doread(void)
724a5fbbc4Spjanzen {
734a5fbbc4Spjanzen 	struct obj *scroll;
744a5fbbc4Spjanzen 	boolean confused = (Confusion != 0);
754a5fbbc4Spjanzen 	boolean known = FALSE;
76df930be7Sderaadt 
77df930be7Sderaadt 	scroll = getobj("?", "read");
78df930be7Sderaadt 	if(!scroll) return(0);
79df930be7Sderaadt 	if(!scroll->dknown && Blind) {
80df930be7Sderaadt 	    pline("Being blind, you cannot read the formula on the scroll.");
81df930be7Sderaadt 	    return(0);
82df930be7Sderaadt 	}
83df930be7Sderaadt 	if(Blind)
84df930be7Sderaadt 	  pline("As you pronounce the formula on it, the scroll disappears.");
85df930be7Sderaadt 	else
86df930be7Sderaadt 	  pline("As you read the scroll, it disappears.");
87df930be7Sderaadt 	if(confused)
88df930be7Sderaadt 	  pline("Being confused, you mispronounce the magic words ... ");
89df930be7Sderaadt 
90df930be7Sderaadt 	switch(scroll->otyp) {
91df930be7Sderaadt #ifdef MAIL
92df930be7Sderaadt 	case SCR_MAIL:
93df930be7Sderaadt 		readmail(/* scroll */);
94df930be7Sderaadt 		break;
9554da88e4Spjanzen #endif /* MAIL */
96df930be7Sderaadt 	case SCR_ENCHANT_ARMOR:
974a5fbbc4Spjanzen 	    {	struct obj *otmp = some_armor();
98df930be7Sderaadt 		if(!otmp) {
99df930be7Sderaadt 			strange_feeling(scroll,"Your skin glows then fades.");
100df930be7Sderaadt 			return(1);
101df930be7Sderaadt 		}
102df930be7Sderaadt 		if(confused) {
103df930be7Sderaadt 			pline("Your %s glows silver for a moment.",
104df930be7Sderaadt 				objects[otmp->otyp].oc_name);
105df930be7Sderaadt 			otmp->rustfree = 1;
106df930be7Sderaadt 			break;
107df930be7Sderaadt 		}
108df930be7Sderaadt 		if(otmp->spe > 3 && rn2(otmp->spe)) {
109df930be7Sderaadt 	pline("Your %s glows violently green for a while, then evaporates.",
110df930be7Sderaadt 			objects[otmp->otyp].oc_name);
111df930be7Sderaadt 			useup(otmp);
112df930be7Sderaadt 			break;
113df930be7Sderaadt 		}
114df930be7Sderaadt 		pline("Your %s glows green for a moment.",
115df930be7Sderaadt 			objects[otmp->otyp].oc_name);
116df930be7Sderaadt 		otmp->cursed = 0;
117df930be7Sderaadt 		otmp->spe++;
118df930be7Sderaadt 		break;
119df930be7Sderaadt 	    }
120df930be7Sderaadt 	case SCR_DESTROY_ARMOR:
121df930be7Sderaadt 		if(confused) {
1224a5fbbc4Spjanzen 			struct obj *otmp = some_armor();
123df930be7Sderaadt 			if(!otmp) {
124df930be7Sderaadt 				strange_feeling(scroll,"Your bones itch.");
125df930be7Sderaadt 				return(1);
126df930be7Sderaadt 			}
127df930be7Sderaadt 			pline("Your %s glows purple for a moment.",
128df930be7Sderaadt 				objects[otmp->otyp].oc_name);
129df930be7Sderaadt 			otmp->rustfree = 0;
130df930be7Sderaadt 			break;
131df930be7Sderaadt 		}
132df930be7Sderaadt 		if(uarm) {
133df930be7Sderaadt 		    pline("Your armor turns to dust and falls to the floor!");
134df930be7Sderaadt 		    useup(uarm);
135df930be7Sderaadt 		} else if(uarmh) {
136df930be7Sderaadt 		    pline("Your helmet turns to dust and is blown away!");
137df930be7Sderaadt 		    useup(uarmh);
138df930be7Sderaadt 		} else if(uarmg) {
139df930be7Sderaadt 			pline("Your gloves vanish!");
140df930be7Sderaadt 			useup(uarmg);
141df930be7Sderaadt 			selftouch("You");
142df930be7Sderaadt 		} else {
143df930be7Sderaadt 			strange_feeling(scroll,"Your skin itches.");
144df930be7Sderaadt 			return(1);
145df930be7Sderaadt 		}
146df930be7Sderaadt 		break;
147df930be7Sderaadt 	case SCR_CONFUSE_MONSTER:
148df930be7Sderaadt 		if(confused) {
149df930be7Sderaadt 			pline("Your hands begin to glow purple.");
150df930be7Sderaadt 			Confusion += rnd(100);
151df930be7Sderaadt 		} else {
152df930be7Sderaadt 			pline("Your hands begin to glow blue.");
153df930be7Sderaadt 			u.umconf = 1;
154df930be7Sderaadt 		}
155df930be7Sderaadt 		break;
156df930be7Sderaadt 	case SCR_SCARE_MONSTER:
1574a5fbbc4Spjanzen 	    {	int ct = 0;
1584a5fbbc4Spjanzen 		struct monst *mtmp;
159df930be7Sderaadt 
160df930be7Sderaadt 		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
161df930be7Sderaadt 			if(cansee(mtmp->mx,mtmp->my)) {
162df930be7Sderaadt 				if(confused)
163df930be7Sderaadt 					mtmp->mflee = mtmp->mfroz =
164df930be7Sderaadt 					mtmp->msleep = 0;
165df930be7Sderaadt 				else
166df930be7Sderaadt 					mtmp->mflee = 1;
167df930be7Sderaadt 				ct++;
168df930be7Sderaadt 			}
169df930be7Sderaadt 		if(!ct) {
170df930be7Sderaadt 		    if(confused)
171df930be7Sderaadt 			pline("You hear sad wailing in the distance.");
172df930be7Sderaadt 		    else
173df930be7Sderaadt 			pline("You hear maniacal laughter in the distance.");
174df930be7Sderaadt 		}
175df930be7Sderaadt 		break;
176df930be7Sderaadt 	    }
177df930be7Sderaadt 	case SCR_BLANK_PAPER:
178df930be7Sderaadt 		if(confused)
179df930be7Sderaadt 		    pline("You see strange patterns on this scroll.");
180df930be7Sderaadt 		else
181df930be7Sderaadt 		    pline("This scroll seems to be blank.");
182df930be7Sderaadt 		break;
183df930be7Sderaadt 	case SCR_REMOVE_CURSE:
1844a5fbbc4Spjanzen 	    {	struct obj *obj;
185df930be7Sderaadt 		if(confused)
186df930be7Sderaadt 		  pline("You feel like you need some help.");
187df930be7Sderaadt 		else
188df930be7Sderaadt 		  pline("You feel like someone is helping you.");
189df930be7Sderaadt 		for(obj = invent; obj ; obj = obj->nobj)
190df930be7Sderaadt 			if(obj->owornmask)
191df930be7Sderaadt 				obj->cursed = confused;
192df930be7Sderaadt 		if(Punished && !confused) {
193df930be7Sderaadt 			Punished = 0;
194df930be7Sderaadt 			freeobj(uchain);
195df930be7Sderaadt 			unpobj(uchain);
196ebf3d589Sguenther 			free(uchain);
197df930be7Sderaadt 			uball->spe = 0;
198df930be7Sderaadt 			uball->owornmask &= ~W_BALL;
199df930be7Sderaadt 			uchain = uball = (struct obj *) 0;
200df930be7Sderaadt 		}
201df930be7Sderaadt 		break;
202df930be7Sderaadt 	    }
203df930be7Sderaadt 	case SCR_CREATE_MONSTER:
2044a5fbbc4Spjanzen 	    {	int cnt = 1;
205df930be7Sderaadt 
206df930be7Sderaadt 		if(!rn2(73)) cnt += rnd(4);
207df930be7Sderaadt 		if(confused) cnt += 12;
208df930be7Sderaadt 		while(cnt--)
209df930be7Sderaadt 		    (void) makemon(confused ? PM_ACID_BLOB :
210df930be7Sderaadt 			(struct permonst *) 0, u.ux, u.uy);
211df930be7Sderaadt 		break;
212df930be7Sderaadt 	    }
213df930be7Sderaadt 	case SCR_ENCHANT_WEAPON:
214df930be7Sderaadt 		if(uwep && confused) {
215df930be7Sderaadt 			pline("Your %s glows silver for a moment.",
216df930be7Sderaadt 				objects[uwep->otyp].oc_name);
217df930be7Sderaadt 			uwep->rustfree = 1;
218df930be7Sderaadt 		} else
219df930be7Sderaadt 			if(!chwepon(scroll, 1))		/* tests for !uwep */
220df930be7Sderaadt 				return(1);
221df930be7Sderaadt 		break;
222df930be7Sderaadt 	case SCR_DAMAGE_WEAPON:
223df930be7Sderaadt 		if(uwep && confused) {
224df930be7Sderaadt 			pline("Your %s glows purple for a moment.",
225df930be7Sderaadt 				objects[uwep->otyp].oc_name);
226df930be7Sderaadt 			uwep->rustfree = 0;
227df930be7Sderaadt 		} else
228df930be7Sderaadt 			if(!chwepon(scroll, -1))	/* tests for !uwep */
229df930be7Sderaadt 				return(1);
230df930be7Sderaadt 		break;
231df930be7Sderaadt 	case SCR_TAMING:
2324a5fbbc4Spjanzen 	    {	int i,j;
2334a5fbbc4Spjanzen 		int bd = confused ? 5 : 1;
2344a5fbbc4Spjanzen 		struct monst *mtmp;
235df930be7Sderaadt 
236df930be7Sderaadt 		for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++)
2374a5fbbc4Spjanzen 		if ((mtmp = m_at(u.ux+i, u.uy+j)))
2384a5fbbc4Spjanzen 			(void) tamedog(mtmp, NULL);
239df930be7Sderaadt 		break;
240df930be7Sderaadt 	    }
241df930be7Sderaadt 	case SCR_GENOCIDE:
242df930be7Sderaadt 	    {	extern char genocided[], fut_geno[];
243df930be7Sderaadt 		char buf[BUFSZ];
2444a5fbbc4Spjanzen 		struct monst *mtmp, *mtmp2;
245df930be7Sderaadt 
246df930be7Sderaadt 		pline("You have found a scroll of genocide!");
247df930be7Sderaadt 		known = TRUE;
248df930be7Sderaadt 		if(confused)
249df930be7Sderaadt 			*buf = u.usym;
250df930be7Sderaadt 		else do {
251df930be7Sderaadt 	    pline("What monster do you want to genocide (Type the letter)? ");
252df930be7Sderaadt 			getlin(buf);
253df930be7Sderaadt 		} while(strlen(buf) != 1 || !monstersym(*buf));
254180acc8fSmillert 		if(!strchr(fut_geno, *buf))
255df930be7Sderaadt 			charcat(fut_geno, *buf);
256180acc8fSmillert 		if(!strchr(genocided, *buf))
257df930be7Sderaadt 			charcat(genocided, *buf);
258df930be7Sderaadt 		else {
259df930be7Sderaadt 			pline("Such monsters do not exist in this world.");
260df930be7Sderaadt 			break;
261df930be7Sderaadt 		}
262df930be7Sderaadt 		for(mtmp = fmon; mtmp; mtmp = mtmp2){
263df930be7Sderaadt 			mtmp2 = mtmp->nmon;
264df930be7Sderaadt 			if(mtmp->data->mlet == *buf)
265df930be7Sderaadt 				mondead(mtmp);
266df930be7Sderaadt 		}
267df930be7Sderaadt 		pline("Wiped out all %c's.", *buf);
268df930be7Sderaadt 		if(*buf == u.usym) {
269df930be7Sderaadt 			killer = "scroll of genocide";
270df930be7Sderaadt 			u.uhp = -1;
271df930be7Sderaadt 		}
272df930be7Sderaadt 		break;
273df930be7Sderaadt 		}
274df930be7Sderaadt 	case SCR_LIGHT:
275df930be7Sderaadt 		if(!Blind) known = TRUE;
276df930be7Sderaadt 		litroom(!confused);
277df930be7Sderaadt 		break;
278df930be7Sderaadt 	case SCR_TELEPORTATION:
279df930be7Sderaadt 		if(confused)
280df930be7Sderaadt 			level_tele();
281df930be7Sderaadt 		else {
282df930be7Sderaadt #ifdef QUEST
2834a5fbbc4Spjanzen 			int oux = u.ux, ouy = u.uy;
284df930be7Sderaadt 			tele();
285df930be7Sderaadt 			if(dist(oux, ouy) > 100) known = TRUE;
28654da88e4Spjanzen #else /* QUEST */
2874a5fbbc4Spjanzen 			int uroom = inroom(u.ux, u.uy);
288df930be7Sderaadt 			tele();
289df930be7Sderaadt 			if(uroom != inroom(u.ux, u.uy)) known = TRUE;
29054da88e4Spjanzen #endif /* QUEST */
291df930be7Sderaadt 		}
292df930be7Sderaadt 		break;
293df930be7Sderaadt 	case SCR_GOLD_DETECTION:
294df930be7Sderaadt 	    /* Unfortunately this code has become slightly less elegant,
295df930be7Sderaadt 	       now that gold and traps no longer are of the same type. */
296df930be7Sderaadt 	    if(confused) {
2974a5fbbc4Spjanzen 		struct trap *ttmp;
298df930be7Sderaadt 
299df930be7Sderaadt 		if(!ftrap) {
300df930be7Sderaadt 			strange_feeling(scroll, "Your toes stop itching.");
301df930be7Sderaadt 			return(1);
302df930be7Sderaadt 		} else {
303df930be7Sderaadt 			for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
304df930be7Sderaadt 				if(ttmp->tx != u.ux || ttmp->ty != u.uy)
305df930be7Sderaadt 					goto outtrapmap;
306df930be7Sderaadt 			/* only under me - no separate display required */
307df930be7Sderaadt 			pline("Your toes itch!");
308df930be7Sderaadt 			break;
309df930be7Sderaadt 		outtrapmap:
310df930be7Sderaadt 			cls();
311df930be7Sderaadt 			for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
312df930be7Sderaadt 				at(ttmp->tx, ttmp->ty, '$');
313df930be7Sderaadt 			prme();
314df930be7Sderaadt 			pline("You feel very greedy!");
315df930be7Sderaadt 		}
316df930be7Sderaadt 	    } else {
3174a5fbbc4Spjanzen 		struct gold *gtmp;
318df930be7Sderaadt 
319df930be7Sderaadt 		if(!fgold) {
320df930be7Sderaadt 			strange_feeling(scroll, "You feel materially poor.");
321df930be7Sderaadt 			return(1);
322df930be7Sderaadt 		} else {
323df930be7Sderaadt 			known = TRUE;
324df930be7Sderaadt 			for(gtmp = fgold; gtmp; gtmp = gtmp->ngold)
325df930be7Sderaadt 				if(gtmp->gx != u.ux || gtmp->gy != u.uy)
326df930be7Sderaadt 					goto outgoldmap;
327df930be7Sderaadt 			/* only under me - no separate display required */
328df930be7Sderaadt 			pline("You notice some gold between your feet.");
329df930be7Sderaadt 			break;
330df930be7Sderaadt 		outgoldmap:
331df930be7Sderaadt 			cls();
332df930be7Sderaadt 			for(gtmp = fgold; gtmp; gtmp = gtmp->ngold)
333df930be7Sderaadt 				at(gtmp->gx, gtmp->gy, '$');
334df930be7Sderaadt 			prme();
335df930be7Sderaadt 			pline("You feel very greedy, and sense gold!");
336df930be7Sderaadt 		}
337df930be7Sderaadt 	    }
338df930be7Sderaadt 		/* common sequel */
339df930be7Sderaadt 		more();
340df930be7Sderaadt 		docrt();
341df930be7Sderaadt 		break;
342df930be7Sderaadt 	case SCR_FOOD_DETECTION:
3434a5fbbc4Spjanzen 	    {	int ct = 0, ctu = 0;
3444a5fbbc4Spjanzen 		struct obj *obj;
3454a5fbbc4Spjanzen 		char foodsym = confused ? POTION_SYM : FOOD_SYM;
346df930be7Sderaadt 
347df930be7Sderaadt 		for(obj = fobj; obj; obj = obj->nobj)
348df930be7Sderaadt 			if(obj->olet == FOOD_SYM) {
349df930be7Sderaadt 				if(obj->ox == u.ux && obj->oy == u.uy) ctu++;
350df930be7Sderaadt 				else ct++;
351df930be7Sderaadt 			}
352df930be7Sderaadt 		if(!ct && !ctu) {
353df930be7Sderaadt 			strange_feeling(scroll,"Your nose twitches.");
354df930be7Sderaadt 			return(1);
355df930be7Sderaadt 		} else if(!ct) {
356df930be7Sderaadt 			known = TRUE;
357df930be7Sderaadt 			pline("You smell %s close nearby.",
358df930be7Sderaadt 				confused ? "something" : "food");
359df930be7Sderaadt 
360df930be7Sderaadt 		} else {
361df930be7Sderaadt 			known = TRUE;
362df930be7Sderaadt 			cls();
363df930be7Sderaadt 			for(obj = fobj; obj; obj = obj->nobj)
364df930be7Sderaadt 			    if(obj->olet == foodsym)
365df930be7Sderaadt 				at(obj->ox, obj->oy, FOOD_SYM);
366df930be7Sderaadt 			prme();
367df930be7Sderaadt 			pline("Your nose tingles and you smell %s!",
368df930be7Sderaadt 				confused ? "something" : "food");
369df930be7Sderaadt 			more();
370df930be7Sderaadt 			docrt();
371df930be7Sderaadt 		}
372df930be7Sderaadt 		break;
373df930be7Sderaadt 	    }
374df930be7Sderaadt 	case SCR_IDENTIFY:
375df930be7Sderaadt 		/* known = TRUE; */
376df930be7Sderaadt 		if(confused)
377df930be7Sderaadt 			pline("You identify this as an identify scroll.");
378df930be7Sderaadt 		else
379df930be7Sderaadt 			pline("This is an identify scroll.");
380df930be7Sderaadt 		useup(scroll);
381df930be7Sderaadt 		objects[SCR_IDENTIFY].oc_name_known = 1;
382df930be7Sderaadt 		if(!confused)
383df930be7Sderaadt 		    while(
384df930be7Sderaadt 			!ggetobj("identify", identify, rn2(5) ? 1 : rn2(5))
385df930be7Sderaadt 			&& invent
386df930be7Sderaadt 		    );
387df930be7Sderaadt 		return(1);
388df930be7Sderaadt 	case SCR_MAGIC_MAPPING:
3894a5fbbc4Spjanzen 	    {	struct rm *lev;
3904a5fbbc4Spjanzen 		int num, zx, zy;
391df930be7Sderaadt 
392df930be7Sderaadt 		known = TRUE;
393df930be7Sderaadt 		pline("On this scroll %s a map!",
394df930be7Sderaadt 			confused ? "was" : "is");
395df930be7Sderaadt 		for(zy = 0; zy < ROWNO; zy++)
396df930be7Sderaadt 			for(zx = 0; zx < COLNO; zx++) {
397df930be7Sderaadt 				if(confused && rn2(7)) continue;
398df930be7Sderaadt 				lev = &(levl[zx][zy]);
399df930be7Sderaadt 				if((num = lev->typ) == 0)
400df930be7Sderaadt 					continue;
401df930be7Sderaadt 				if(num == SCORR) {
402df930be7Sderaadt 					lev->typ = CORR;
403df930be7Sderaadt 					lev->scrsym = CORR_SYM;
404df930be7Sderaadt 				} else
405df930be7Sderaadt 				if(num == SDOOR) {
406df930be7Sderaadt 					lev->typ = DOOR;
407df930be7Sderaadt 					lev->scrsym = '+';
408df930be7Sderaadt 					/* do sth in doors ? */
409df930be7Sderaadt 				} else if(lev->seen) continue;
410df930be7Sderaadt #ifndef QUEST
411df930be7Sderaadt 				if(num != ROOM)
41254da88e4Spjanzen #endif /* QUEST */
413df930be7Sderaadt 				{
414df930be7Sderaadt 				  lev->seen = lev->new = 1;
415df930be7Sderaadt 				  if(lev->scrsym == ' ' || !lev->scrsym)
416df930be7Sderaadt 				    newsym(zx,zy);
417df930be7Sderaadt 				  else
418df930be7Sderaadt 				    on_scr(zx,zy);
419df930be7Sderaadt 				}
420df930be7Sderaadt 			}
421df930be7Sderaadt 		break;
422df930be7Sderaadt 	    }
423df930be7Sderaadt 	case SCR_AMNESIA:
4244a5fbbc4Spjanzen 	    {	int zx, zy;
425df930be7Sderaadt 
426df930be7Sderaadt 		known = TRUE;
427df930be7Sderaadt 		for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++)
428df930be7Sderaadt 		    if(!confused || rn2(7))
429df930be7Sderaadt 			if(!cansee(zx,zy))
430df930be7Sderaadt 			    levl[zx][zy].seen = 0;
431df930be7Sderaadt 		docrt();
432df930be7Sderaadt 		pline("Thinking of Maud you forget everything else.");
433df930be7Sderaadt 		break;
434df930be7Sderaadt 	    }
435df930be7Sderaadt 	case SCR_FIRE:
4364a5fbbc4Spjanzen 	    {	int num;
4374a5fbbc4Spjanzen 		struct monst *mtmp;
438df930be7Sderaadt 
439df930be7Sderaadt 		known = TRUE;
440df930be7Sderaadt 		if(confused) {
441df930be7Sderaadt 		    pline("The scroll catches fire and you burn your hands.");
442df930be7Sderaadt 		    losehp(1, "scroll of fire");
443df930be7Sderaadt 		} else {
444df930be7Sderaadt 		    pline("The scroll erupts in a tower of flame!");
445df930be7Sderaadt 		    if(Fire_resistance)
446df930be7Sderaadt 			pline("You are uninjured.");
447df930be7Sderaadt 		    else {
448df930be7Sderaadt 			num = rnd(6);
449df930be7Sderaadt 			u.uhpmax -= num;
450df930be7Sderaadt 			losehp(num, "scroll of fire");
451df930be7Sderaadt 		    }
452df930be7Sderaadt 		}
453df930be7Sderaadt 		num = (2*num + 1)/3;
454df930be7Sderaadt 		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
455df930be7Sderaadt 		    if(dist(mtmp->mx,mtmp->my) < 3) {
456df930be7Sderaadt 			mtmp->mhp -= num;
457180acc8fSmillert 			if(strchr("FY", mtmp->data->mlet))
458df930be7Sderaadt 			    mtmp->mhp -= 3*num;	/* this might well kill 'F's */
459df930be7Sderaadt 			if(mtmp->mhp < 1) {
460df930be7Sderaadt 			    killed(mtmp);
461df930be7Sderaadt 			    break;		/* primitive */
462df930be7Sderaadt 			}
463df930be7Sderaadt 		    }
464df930be7Sderaadt 		}
465df930be7Sderaadt 		break;
466df930be7Sderaadt 	    }
467df930be7Sderaadt 	case SCR_PUNISHMENT:
468df930be7Sderaadt 		known = TRUE;
469df930be7Sderaadt 		if(confused) {
470df930be7Sderaadt 			pline("You feel guilty.");
471df930be7Sderaadt 			break;
472df930be7Sderaadt 		}
473df930be7Sderaadt 		pline("You are being punished for your misbehaviour!");
474df930be7Sderaadt 		if(Punished){
475df930be7Sderaadt 			pline("Your iron ball gets heavier.");
476df930be7Sderaadt 			uball->owt += 15;
477df930be7Sderaadt 			break;
478df930be7Sderaadt 		}
479df930be7Sderaadt 		Punished = INTRINSIC;
480df930be7Sderaadt 		setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN);
481df930be7Sderaadt 		setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL);
482df930be7Sderaadt 		uball->spe = 1;		/* special ball (see save) */
483df930be7Sderaadt 		break;
484df930be7Sderaadt 	default:
485df930be7Sderaadt 		impossible("What weird language is this written in? (%u)",
486df930be7Sderaadt 			scroll->otyp);
487df930be7Sderaadt 	}
488df930be7Sderaadt 	if(!objects[scroll->otyp].oc_name_known) {
489df930be7Sderaadt 		if(known && !confused) {
490df930be7Sderaadt 			objects[scroll->otyp].oc_name_known = 1;
491df930be7Sderaadt 			more_experienced(0,10);
492df930be7Sderaadt 		} else if(!objects[scroll->otyp].oc_uname)
493df930be7Sderaadt 			docall(scroll);
494df930be7Sderaadt 	}
495df930be7Sderaadt 	useup(scroll);
496df930be7Sderaadt 	return(1);
497df930be7Sderaadt }
498df930be7Sderaadt 
4994a5fbbc4Spjanzen /* also called by newmail() */
5004a5fbbc4Spjanzen int
identify(struct obj * otmp)5014a5fbbc4Spjanzen identify(struct obj *otmp)
502df930be7Sderaadt {
503df930be7Sderaadt 	objects[otmp->otyp].oc_name_known = 1;
504df930be7Sderaadt 	otmp->known = otmp->dknown = 1;
505df930be7Sderaadt 	prinv(otmp);
506df930be7Sderaadt 	return(1);
507df930be7Sderaadt }
508df930be7Sderaadt 
5094a5fbbc4Spjanzen void
litroom(boolean on)5104a5fbbc4Spjanzen litroom(boolean on)
511df930be7Sderaadt {
5124a5fbbc4Spjanzen 	int num,zx,zy;
513df930be7Sderaadt 
514df930be7Sderaadt 	/* first produce the text (provided he is not blind) */
515df930be7Sderaadt 	if(Blind) goto do_it;
516df930be7Sderaadt 	if(!on) {
5174a5fbbc4Spjanzen 		if(u.uswallow || !xdnstair ||
5184a5fbbc4Spjanzen 		   levl[(int)u.ux][(int)u.uy].typ == CORR ||
5194a5fbbc4Spjanzen 		   !levl[(int)u.ux][(int)u.uy].lit) {
520df930be7Sderaadt 			pline("It seems even darker in here than before.");
521df930be7Sderaadt 			return;
522df930be7Sderaadt 		} else
523df930be7Sderaadt 			pline("It suddenly becomes dark in here.");
524df930be7Sderaadt 	} else {
525df930be7Sderaadt 		if(u.uswallow){
526df930be7Sderaadt 			pline("%s's stomach is lit.", Monnam(u.ustuck));
527df930be7Sderaadt 			return;
528df930be7Sderaadt 		}
529df930be7Sderaadt 		if(!xdnstair){
530df930be7Sderaadt 			pline("Nothing Happens.");
531df930be7Sderaadt 			return;
532df930be7Sderaadt 		}
533df930be7Sderaadt #ifdef QUEST
534df930be7Sderaadt 		pline("The cave lights up around you, then fades.");
535df930be7Sderaadt 		return;
53654da88e4Spjanzen #else /* QUEST */
5374a5fbbc4Spjanzen 		if (levl[(int)u.ux][(int)u.uy].typ == CORR) {
538df930be7Sderaadt 		    pline("The corridor lights up around you, then fades.");
539df930be7Sderaadt 		    return;
5404a5fbbc4Spjanzen 		} else if (levl[(int)u.ux][(int)u.uy].lit) {
541df930be7Sderaadt 		    pline("The light here seems better now.");
542df930be7Sderaadt 		    return;
543df930be7Sderaadt 		} else
544df930be7Sderaadt 		    pline("The room is lit.");
54554da88e4Spjanzen #endif /* QUEST */
546df930be7Sderaadt 	}
547df930be7Sderaadt 
548df930be7Sderaadt do_it:
549df930be7Sderaadt #ifdef QUEST
550df930be7Sderaadt 	return;
55154da88e4Spjanzen #else /* QUEST */
5524a5fbbc4Spjanzen 	if (levl[(int)u.ux][(int)u.uy].lit == on)
553df930be7Sderaadt 		return;
5544a5fbbc4Spjanzen 	if (levl[(int)u.ux][(int)u.uy].typ == DOOR) {
5554a5fbbc4Spjanzen 		if (IS_ROOM(levl[(int)u.ux][(int)u.uy+1].typ))
5564a5fbbc4Spjanzen 			zy = u.uy+1;
5574a5fbbc4Spjanzen 		else if(IS_ROOM(levl[(int)u.ux][u.uy-1].typ))
5584a5fbbc4Spjanzen 			zy = u.uy-1;
559df930be7Sderaadt 		else zy = u.uy;
5604a5fbbc4Spjanzen 		if(IS_ROOM(levl[u.ux+1][(int)u.uy].typ))
5614a5fbbc4Spjanzen 			zx = u.ux+1;
5624a5fbbc4Spjanzen 		else if(IS_ROOM(levl[u.ux-1][(int)u.uy].typ))
5634a5fbbc4Spjanzen 			zx = u.ux-1;
564df930be7Sderaadt 		else zx = u.ux;
565df930be7Sderaadt 	} else {
566df930be7Sderaadt 		zx = u.ux;
567df930be7Sderaadt 		zy = u.uy;
568df930be7Sderaadt 	}
569df930be7Sderaadt 	for(seelx = u.ux; (num = levl[seelx-1][zy].typ) != CORR && num != 0;
570df930be7Sderaadt 		seelx--);
571df930be7Sderaadt 	for(seehx = u.ux; (num = levl[seehx+1][zy].typ) != CORR && num != 0;
572df930be7Sderaadt 		seehx++);
573df930be7Sderaadt 	for(seely = u.uy; (num = levl[zx][seely-1].typ) != CORR && num != 0;
574df930be7Sderaadt 		seely--);
575df930be7Sderaadt 	for(seehy = u.uy; (num = levl[zx][seehy+1].typ) != CORR && num != 0;
576df930be7Sderaadt 		seehy++);
577df930be7Sderaadt 	for(zy = seely; zy <= seehy; zy++)
578df930be7Sderaadt 		for(zx = seelx; zx <= seehx; zx++) {
579df930be7Sderaadt 			levl[zx][zy].lit = on;
5804a5fbbc4Spjanzen 			if (!Blind && dist(zx,zy) > 2) {
5814a5fbbc4Spjanzen 				if(on)
5824a5fbbc4Spjanzen 					prl(zx,zy);
5834a5fbbc4Spjanzen 				else
5844a5fbbc4Spjanzen 					nosee(zx,zy);
585df930be7Sderaadt 			}
5864a5fbbc4Spjanzen 		}
5874a5fbbc4Spjanzen 	if(!on)
5884a5fbbc4Spjanzen 		seehx = 0;
58954da88e4Spjanzen #endif /* QUEST */
590df930be7Sderaadt }
591df930be7Sderaadt 
592df930be7Sderaadt /* Test whether we may genocide all monsters with symbol  ch  */
5934a5fbbc4Spjanzen /* arnold@ucsfcgl */
5944a5fbbc4Spjanzen static boolean
monstersym(char ch)5954a5fbbc4Spjanzen monstersym(char ch)
596df930be7Sderaadt {
5974a5fbbc4Spjanzen 	struct permonst *mp;
598df930be7Sderaadt 	extern struct permonst pm_eel;
599df930be7Sderaadt 
600df930be7Sderaadt 	/*
601df930be7Sderaadt 	 * can't genocide certain monsters
602df930be7Sderaadt 	 */
603180acc8fSmillert 	if (strchr("12 &:", ch))
604df930be7Sderaadt 		return FALSE;
605df930be7Sderaadt 
606df930be7Sderaadt 	if (ch == pm_eel.mlet)
607df930be7Sderaadt 		return TRUE;
608df930be7Sderaadt 	for (mp = mons; mp < &mons[CMNUM+2]; mp++)
609df930be7Sderaadt 		if (mp->mlet == ch)
610df930be7Sderaadt 			return TRUE;
611df930be7Sderaadt 	return FALSE;
612df930be7Sderaadt }
613