]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.read.c
Ixfay iticalcray ugsbay! Eservepray artstay-ofway-ordway andway
[bsdgames-darwin.git] / hack / hack.read.c
1 /*
2 * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
3 */
4
5 #ifndef lint
6 static char rcsid[] = "$NetBSD: hack.read.c,v 1.3 1995/03/23 08:31:22 cgd Exp $";
7 #endif /* not lint */
8
9 #include "hack.h"
10
11 extern struct monst *makemon();
12 extern struct obj *mkobj_at();
13 int identify();
14
15 doread() {
16 register struct obj *scroll;
17 register boolean confused = (Confusion != 0);
18 register boolean known = FALSE;
19 extern struct obj *some_armor();
20
21 scroll = getobj("?", "read");
22 if(!scroll) return(0);
23 if(!scroll->dknown && Blind) {
24 pline("Being blind, you cannot read the formula on the scroll.");
25 return(0);
26 }
27 if(Blind)
28 pline("As you pronounce the formula on it, the scroll disappears.");
29 else
30 pline("As you read the scroll, it disappears.");
31 if(confused)
32 pline("Being confused, you mispronounce the magic words ... ");
33
34 switch(scroll->otyp) {
35 #ifdef MAIL
36 case SCR_MAIL:
37 readmail(/* scroll */);
38 break;
39 #endif MAIL
40 case SCR_ENCHANT_ARMOR:
41 { register struct obj *otmp = some_armor();
42 if(!otmp) {
43 strange_feeling(scroll,"Your skin glows then fades.");
44 return(1);
45 }
46 if(confused) {
47 pline("Your %s glows silver for a moment.",
48 objects[otmp->otyp].oc_name);
49 otmp->rustfree = 1;
50 break;
51 }
52 if(otmp->spe > 3 && rn2(otmp->spe)) {
53 pline("Your %s glows violently green for a while, then evaporates.",
54 objects[otmp->otyp].oc_name);
55 useup(otmp);
56 break;
57 }
58 pline("Your %s glows green for a moment.",
59 objects[otmp->otyp].oc_name);
60 otmp->cursed = 0;
61 otmp->spe++;
62 break;
63 }
64 case SCR_DESTROY_ARMOR:
65 if(confused) {
66 register struct obj *otmp = some_armor();
67 if(!otmp) {
68 strange_feeling(scroll,"Your bones itch.");
69 return(1);
70 }
71 pline("Your %s glows purple for a moment.",
72 objects[otmp->otyp].oc_name);
73 otmp->rustfree = 0;
74 break;
75 }
76 if(uarm) {
77 pline("Your armor turns to dust and falls to the floor!");
78 useup(uarm);
79 } else if(uarmh) {
80 pline("Your helmet turns to dust and is blown away!");
81 useup(uarmh);
82 } else if(uarmg) {
83 pline("Your gloves vanish!");
84 useup(uarmg);
85 selftouch("You");
86 } else {
87 strange_feeling(scroll,"Your skin itches.");
88 return(1);
89 }
90 break;
91 case SCR_CONFUSE_MONSTER:
92 if(confused) {
93 pline("Your hands begin to glow purple.");
94 Confusion += rnd(100);
95 } else {
96 pline("Your hands begin to glow blue.");
97 u.umconf = 1;
98 }
99 break;
100 case SCR_SCARE_MONSTER:
101 { register int ct = 0;
102 register struct monst *mtmp;
103
104 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
105 if(cansee(mtmp->mx,mtmp->my)) {
106 if(confused)
107 mtmp->mflee = mtmp->mfroz =
108 mtmp->msleep = 0;
109 else
110 mtmp->mflee = 1;
111 ct++;
112 }
113 if(!ct) {
114 if(confused)
115 pline("You hear sad wailing in the distance.");
116 else
117 pline("You hear maniacal laughter in the distance.");
118 }
119 break;
120 }
121 case SCR_BLANK_PAPER:
122 if(confused)
123 pline("You see strange patterns on this scroll.");
124 else
125 pline("This scroll seems to be blank.");
126 break;
127 case SCR_REMOVE_CURSE:
128 { register struct obj *obj;
129 if(confused)
130 pline("You feel like you need some help.");
131 else
132 pline("You feel like someone is helping you.");
133 for(obj = invent; obj ; obj = obj->nobj)
134 if(obj->owornmask)
135 obj->cursed = confused;
136 if(Punished && !confused) {
137 Punished = 0;
138 freeobj(uchain);
139 unpobj(uchain);
140 free((char *) uchain);
141 uball->spe = 0;
142 uball->owornmask &= ~W_BALL;
143 uchain = uball = (struct obj *) 0;
144 }
145 break;
146 }
147 case SCR_CREATE_MONSTER:
148 { register int cnt = 1;
149
150 if(!rn2(73)) cnt += rnd(4);
151 if(confused) cnt += 12;
152 while(cnt--)
153 (void) makemon(confused ? PM_ACID_BLOB :
154 (struct permonst *) 0, u.ux, u.uy);
155 break;
156 }
157 case SCR_ENCHANT_WEAPON:
158 if(uwep && confused) {
159 pline("Your %s glows silver for a moment.",
160 objects[uwep->otyp].oc_name);
161 uwep->rustfree = 1;
162 } else
163 if(!chwepon(scroll, 1)) /* tests for !uwep */
164 return(1);
165 break;
166 case SCR_DAMAGE_WEAPON:
167 if(uwep && confused) {
168 pline("Your %s glows purple for a moment.",
169 objects[uwep->otyp].oc_name);
170 uwep->rustfree = 0;
171 } else
172 if(!chwepon(scroll, -1)) /* tests for !uwep */
173 return(1);
174 break;
175 case SCR_TAMING:
176 { register int i,j;
177 register int bd = confused ? 5 : 1;
178 register struct monst *mtmp;
179
180 for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++)
181 if(mtmp = m_at(u.ux+i, u.uy+j))
182 (void) tamedog(mtmp, (struct obj *) 0);
183 break;
184 }
185 case SCR_GENOCIDE:
186 { extern char genocided[], fut_geno[];
187 char buf[BUFSZ];
188 register struct monst *mtmp, *mtmp2;
189
190 pline("You have found a scroll of genocide!");
191 known = TRUE;
192 if(confused)
193 *buf = u.usym;
194 else do {
195 pline("What monster do you want to genocide (Type the letter)? ");
196 getlin(buf);
197 } while(strlen(buf) != 1 || !monstersym(*buf));
198 if(!index(fut_geno, *buf))
199 charcat(fut_geno, *buf);
200 if(!index(genocided, *buf))
201 charcat(genocided, *buf);
202 else {
203 pline("Such monsters do not exist in this world.");
204 break;
205 }
206 for(mtmp = fmon; mtmp; mtmp = mtmp2){
207 mtmp2 = mtmp->nmon;
208 if(mtmp->data->mlet == *buf)
209 mondead(mtmp);
210 }
211 pline("Wiped out all %c's.", *buf);
212 if(*buf == u.usym) {
213 killer = "scroll of genocide";
214 u.uhp = -1;
215 }
216 break;
217 }
218 case SCR_LIGHT:
219 if(!Blind) known = TRUE;
220 litroom(!confused);
221 break;
222 case SCR_TELEPORTATION:
223 if(confused)
224 level_tele();
225 else {
226 #ifdef QUEST
227 register int oux = u.ux, ouy = u.uy;
228 tele();
229 if(dist(oux, ouy) > 100) known = TRUE;
230 #else QUEST
231 register int uroom = inroom(u.ux, u.uy);
232 tele();
233 if(uroom != inroom(u.ux, u.uy)) known = TRUE;
234 #endif QUEST
235 }
236 break;
237 case SCR_GOLD_DETECTION:
238 /* Unfortunately this code has become slightly less elegant,
239 now that gold and traps no longer are of the same type. */
240 if(confused) {
241 register struct trap *ttmp;
242
243 if(!ftrap) {
244 strange_feeling(scroll, "Your toes stop itching.");
245 return(1);
246 } else {
247 for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
248 if(ttmp->tx != u.ux || ttmp->ty != u.uy)
249 goto outtrapmap;
250 /* only under me - no separate display required */
251 pline("Your toes itch!");
252 break;
253 outtrapmap:
254 cls();
255 for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
256 at(ttmp->tx, ttmp->ty, '$');
257 prme();
258 pline("You feel very greedy!");
259 }
260 } else {
261 register struct gold *gtmp;
262
263 if(!fgold) {
264 strange_feeling(scroll, "You feel materially poor.");
265 return(1);
266 } else {
267 known = TRUE;
268 for(gtmp = fgold; gtmp; gtmp = gtmp->ngold)
269 if(gtmp->gx != u.ux || gtmp->gy != u.uy)
270 goto outgoldmap;
271 /* only under me - no separate display required */
272 pline("You notice some gold between your feet.");
273 break;
274 outgoldmap:
275 cls();
276 for(gtmp = fgold; gtmp; gtmp = gtmp->ngold)
277 at(gtmp->gx, gtmp->gy, '$');
278 prme();
279 pline("You feel very greedy, and sense gold!");
280 }
281 }
282 /* common sequel */
283 more();
284 docrt();
285 break;
286 case SCR_FOOD_DETECTION:
287 { register ct = 0, ctu = 0;
288 register struct obj *obj;
289 register char foodsym = confused ? POTION_SYM : FOOD_SYM;
290
291 for(obj = fobj; obj; obj = obj->nobj)
292 if(obj->olet == FOOD_SYM) {
293 if(obj->ox == u.ux && obj->oy == u.uy) ctu++;
294 else ct++;
295 }
296 if(!ct && !ctu) {
297 strange_feeling(scroll,"Your nose twitches.");
298 return(1);
299 } else if(!ct) {
300 known = TRUE;
301 pline("You smell %s close nearby.",
302 confused ? "something" : "food");
303
304 } else {
305 known = TRUE;
306 cls();
307 for(obj = fobj; obj; obj = obj->nobj)
308 if(obj->olet == foodsym)
309 at(obj->ox, obj->oy, FOOD_SYM);
310 prme();
311 pline("Your nose tingles and you smell %s!",
312 confused ? "something" : "food");
313 more();
314 docrt();
315 }
316 break;
317 }
318 case SCR_IDENTIFY:
319 /* known = TRUE; */
320 if(confused)
321 pline("You identify this as an identify scroll.");
322 else
323 pline("This is an identify scroll.");
324 useup(scroll);
325 objects[SCR_IDENTIFY].oc_name_known = 1;
326 if(!confused)
327 while(
328 !ggetobj("identify", identify, rn2(5) ? 1 : rn2(5))
329 && invent
330 );
331 return(1);
332 case SCR_MAGIC_MAPPING:
333 { register struct rm *lev;
334 register int num, zx, zy;
335
336 known = TRUE;
337 pline("On this scroll %s a map!",
338 confused ? "was" : "is");
339 for(zy = 0; zy < ROWNO; zy++)
340 for(zx = 0; zx < COLNO; zx++) {
341 if(confused && rn2(7)) continue;
342 lev = &(levl[zx][zy]);
343 if((num = lev->typ) == 0)
344 continue;
345 if(num == SCORR) {
346 lev->typ = CORR;
347 lev->scrsym = CORR_SYM;
348 } else
349 if(num == SDOOR) {
350 lev->typ = DOOR;
351 lev->scrsym = '+';
352 /* do sth in doors ? */
353 } else if(lev->seen) continue;
354 #ifndef QUEST
355 if(num != ROOM)
356 #endif QUEST
357 {
358 lev->seen = lev->new = 1;
359 if(lev->scrsym == ' ' || !lev->scrsym)
360 newsym(zx,zy);
361 else
362 on_scr(zx,zy);
363 }
364 }
365 break;
366 }
367 case SCR_AMNESIA:
368 { register int zx, zy;
369
370 known = TRUE;
371 for(zx = 0; zx < COLNO; zx++) for(zy = 0; zy < ROWNO; zy++)
372 if(!confused || rn2(7))
373 if(!cansee(zx,zy))
374 levl[zx][zy].seen = 0;
375 docrt();
376 pline("Thinking of Maud you forget everything else.");
377 break;
378 }
379 case SCR_FIRE:
380 { register int num;
381 register struct monst *mtmp;
382
383 known = TRUE;
384 if(confused) {
385 pline("The scroll catches fire and you burn your hands.");
386 losehp(1, "scroll of fire");
387 } else {
388 pline("The scroll erupts in a tower of flame!");
389 if(Fire_resistance)
390 pline("You are uninjured.");
391 else {
392 num = rnd(6);
393 u.uhpmax -= num;
394 losehp(num, "scroll of fire");
395 }
396 }
397 num = (2*num + 1)/3;
398 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
399 if(dist(mtmp->mx,mtmp->my) < 3) {
400 mtmp->mhp -= num;
401 if(index("FY", mtmp->data->mlet))
402 mtmp->mhp -= 3*num; /* this might well kill 'F's */
403 if(mtmp->mhp < 1) {
404 killed(mtmp);
405 break; /* primitive */
406 }
407 }
408 }
409 break;
410 }
411 case SCR_PUNISHMENT:
412 known = TRUE;
413 if(confused) {
414 pline("You feel guilty.");
415 break;
416 }
417 pline("You are being punished for your misbehaviour!");
418 if(Punished){
419 pline("Your iron ball gets heavier.");
420 uball->owt += 15;
421 break;
422 }
423 Punished = INTRINSIC;
424 setworn(mkobj_at(CHAIN_SYM, u.ux, u.uy), W_CHAIN);
425 setworn(mkobj_at(BALL_SYM, u.ux, u.uy), W_BALL);
426 uball->spe = 1; /* special ball (see save) */
427 break;
428 default:
429 impossible("What weird language is this written in? (%u)",
430 scroll->otyp);
431 }
432 if(!objects[scroll->otyp].oc_name_known) {
433 if(known && !confused) {
434 objects[scroll->otyp].oc_name_known = 1;
435 more_experienced(0,10);
436 } else if(!objects[scroll->otyp].oc_uname)
437 docall(scroll);
438 }
439 useup(scroll);
440 return(1);
441 }
442
443 identify(otmp) /* also called by newmail() */
444 register struct obj *otmp;
445 {
446 objects[otmp->otyp].oc_name_known = 1;
447 otmp->known = otmp->dknown = 1;
448 prinv(otmp);
449 return(1);
450 }
451
452 litroom(on)
453 register boolean on;
454 {
455 register num,zx,zy;
456
457 /* first produce the text (provided he is not blind) */
458 if(Blind) goto do_it;
459 if(!on) {
460 if(u.uswallow || !xdnstair || levl[u.ux][u.uy].typ == CORR ||
461 !levl[u.ux][u.uy].lit) {
462 pline("It seems even darker in here than before.");
463 return;
464 } else
465 pline("It suddenly becomes dark in here.");
466 } else {
467 if(u.uswallow){
468 pline("%s's stomach is lit.", Monnam(u.ustuck));
469 return;
470 }
471 if(!xdnstair){
472 pline("Nothing Happens.");
473 return;
474 }
475 #ifdef QUEST
476 pline("The cave lights up around you, then fades.");
477 return;
478 #else QUEST
479 if(levl[u.ux][u.uy].typ == CORR) {
480 pline("The corridor lights up around you, then fades.");
481 return;
482 } else if(levl[u.ux][u.uy].lit) {
483 pline("The light here seems better now.");
484 return;
485 } else
486 pline("The room is lit.");
487 #endif QUEST
488 }
489
490 do_it:
491 #ifdef QUEST
492 return;
493 #else QUEST
494 if(levl[u.ux][u.uy].lit == on)
495 return;
496 if(levl[u.ux][u.uy].typ == DOOR) {
497 if(IS_ROOM(levl[u.ux][u.uy+1].typ)) zy = u.uy+1;
498 else if(IS_ROOM(levl[u.ux][u.uy-1].typ)) zy = u.uy-1;
499 else zy = u.uy;
500 if(IS_ROOM(levl[u.ux+1][u.uy].typ)) zx = u.ux+1;
501 else if(IS_ROOM(levl[u.ux-1][u.uy].typ)) zx = u.ux-1;
502 else zx = u.ux;
503 } else {
504 zx = u.ux;
505 zy = u.uy;
506 }
507 for(seelx = u.ux; (num = levl[seelx-1][zy].typ) != CORR && num != 0;
508 seelx--);
509 for(seehx = u.ux; (num = levl[seehx+1][zy].typ) != CORR && num != 0;
510 seehx++);
511 for(seely = u.uy; (num = levl[zx][seely-1].typ) != CORR && num != 0;
512 seely--);
513 for(seehy = u.uy; (num = levl[zx][seehy+1].typ) != CORR && num != 0;
514 seehy++);
515 for(zy = seely; zy <= seehy; zy++)
516 for(zx = seelx; zx <= seehx; zx++) {
517 levl[zx][zy].lit = on;
518 if(!Blind && dist(zx,zy) > 2)
519 if(on) prl(zx,zy); else nosee(zx,zy);
520 }
521 if(!on) seehx = 0;
522 #endif QUEST
523 }
524
525 /* Test whether we may genocide all monsters with symbol ch */
526 monstersym(ch) /* arnold@ucsfcgl */
527 register char ch;
528 {
529 register struct permonst *mp;
530 extern struct permonst pm_eel;
531
532 /*
533 * can't genocide certain monsters
534 */
535 if (index("12 &:", ch))
536 return FALSE;
537
538 if (ch == pm_eel.mlet)
539 return TRUE;
540 for (mp = mons; mp < &mons[CMNUM+2]; mp++)
541 if (mp->mlet == ch)
542 return TRUE;
543 return FALSE;
544 }