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