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