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