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