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