Home | History | Annotate | Line # | Download | only in hack
hack.read.c revision 1.1
      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 	extern struct obj *some_armor();
     15 
     16 	scroll = getobj("?", "read");
     17 	if(!scroll) return(0);
     18 	if(!scroll->dknown && Blind) {
     19 	    pline("Being blind, you cannot read the formula on the scroll.");
     20 	    return(0);
     21 	}
     22 	if(Blind)
     23 	  pline("As you pronounce the formula on it, the scroll disappears.");
     24 	else
     25 	  pline("As you read the scroll, it disappears.");
     26 	if(confused)
     27 	  pline("Being confused, you mispronounce the magic words ... ");
     28 
     29 	switch(scroll->otyp) {
     30 #ifdef MAIL
     31 	case SCR_MAIL:
     32 		readmail(/* scroll */);
     33 		break;
     34 #endif MAIL
     35 	case SCR_ENCHANT_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 }
    540