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