pc-hack

PC HACK 3.61 source code (archival)
git clone http://frotz.net/git/pc-hack.git
Log | Files | Refs

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 }