Source:NetHack 3.0.0/invent.c

Below is the full text to invent.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/invent.c#line123 ]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

1.   /*	SCCS Id: @(#)invent.c	3.0	88/10/22 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include	"hack.h"  6. 7.   #ifdef WORM 8.   #include "lev.h"  9.    #include "wseg.h"  10. #endif 11.   12.   #define	NOINVSYM	'#' 13.   14.   static boolean mergable; 15.   16.   int lastinvnr = 51;	/* 0 ... 51 */ 17.   static char *xprname; 18.   19.   char inv_order[] = { 20.  	AMULET_SYM, WEAPON_SYM, ARMOR_SYM, FOOD_SYM, SCROLL_SYM, 21.  #ifdef SPELLS 22.  	SPBOOK_SYM, 23.  #endif 24.  	POTION_SYM, RING_SYM, WAND_SYM, TOOL_SYM, GEM_SYM, 25.  	ROCK_SYM, BALL_SYM, CHAIN_SYM, 0 }; 26.   27.   static void 28.  assigninvlet(otmp) 29.  register struct obj *otmp; 30.  {  31.   	boolean inuse[52]; 32.  	register int i;  33. register struct obj *obj; 34.   35.   	for(i = 0; i < 52; i++) inuse[i] = FALSE; 36.  	for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) { 37.  		i = obj->invlet; 38.  		if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else 39.  		if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE; 40.  		if(i == otmp->invlet) otmp->invlet = 0; 41.  	}  42.   	if((i = otmp->invlet) &&  43.   	    (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z'))) 44.  		return; 45.  	for(i = lastinvnr+1; i != lastinvnr; i++) { 46.  		if(i == 52) { i = -1; continue; } 47.  		if(!inuse[i]) break; 48.  	}  49.   	otmp->invlet = (inuse[i] ? NOINVSYM :  50.   			(i < 26) ? ('a'+i) : ('A'+i-26)); 51.  	lastinvnr = i;  52. } 53.    54.   /* merge obj with otmp and delete obj if types agree */ 55.  static int 56.  merged(otmp, obj, lose) 57.  register struct obj *otmp, *obj; 58.  register int lose; 59.  {  60.   	if(mergable(otmp, obj)) { 61.  		/* Approximate age: we do it this way because if we were to  62. * do it "accurately" (merge only when ages are identical) 63.  		 * we'd wind up never merging any corpses. 64.  		 * otmp->age = otmp->age*(1-proportion) + obj->age*proportion; 65.  		 */  66.   		otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan)) 67.  			/ (otmp->quan + obj->quan); 68.  		otmp->quan += obj->quan; 69.  		otmp->owt += obj->owt; 70.  		if(lose) freeobj(obj); 71.  		obfree(obj,otmp);	/* free(obj), bill->otmp */ 72.  		return(1); 73.  	} else	return(0); 74.  }  75.    76.   struct obj * 77.  addinv(obj) 78.  register struct obj *obj; 79.  {  80.   	register struct obj *otmp; 81.   82.   	if (obj->otyp == AMULET_OF_YENDOR && !obj->spe) { 83.  		if (u.uhave_amulet) impossible ("already have amulet?"); 84.  		u.uhave_amulet = 1; 85.  	}  86.   	/* merge or attach to end of chain */ 87.  	if(!invent) { 88.  		invent = obj; 89.  		otmp = 0; 90.  	} else 91.  	for(otmp = invent; /* otmp */; otmp = otmp->nobj) { 92.  		if(merged(otmp, obj, 0)) { 93.  			obj = otmp; 94.  			goto added; 95.  		}  96.   		if(!otmp->nobj) { 97.  			otmp->nobj = obj; 98.  			break; 99.  		}  100.  	}  101.  	obj->nobj = 0; 102.  103.  	if(flags.invlet_constant) { 104. 		assigninvlet(obj); 105. 		/*  106.  		 * The ordering of the chain is nowhere significant 107. 		 * so in case you prefer some other order than the 108. 		 * historical one, change the code below. 109. 		 */  110.  		if(otmp) {	/* find proper place in chain */ 111. 			otmp->nobj = 0; 112. 			if((invent->invlet ^ 040) > (obj->invlet ^ 040)) { 113. 				obj->nobj = invent; 114. 				invent = obj; 115. 			} else 116. 			for(otmp = invent; ; otmp = otmp->nobj) { 117. 			    if(!otmp->nobj ||  118.  				(otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){ 119. 				obj->nobj = otmp->nobj; 120. 				otmp->nobj = obj; 121. 				break; 122. 			    }  123.  			}  124.  		}  125.  	}  126.   127.  added: 128. 	if (obj->otyp == LUCKSTONE) { 129. 		/* new luckstone must be in inventory by this point 130. 		 * for correct calculation */ 131. 		if (stone_luck(TRUE) >= 0) u.moreluck = LUCKADD; 132. 		else u.moreluck = -LUCKADD; 133. 		flags.botl = 1; 134. 	}  135.  	return(obj); 136. }  137.   138.  void 139. useup(obj) 140. register struct obj *obj; 141. {  142.  	if(obj->quan > 1){ 143. 		obj->quan--; 144. 		obj->owt = weight(obj); 145. 	} else { 146. 		setnotworn(obj); 147. 		freeinv(obj); 148. 		obfree(obj, (struct obj *) 0); 149. 	}  150.  }  151.   152.  void 153. freeinv(obj) 154. register struct obj *obj; 155. {  156.  	register struct obj *otmp; 157.  158.  	if(obj == invent) 159. 		invent = invent->nobj; 160. 	else { 161. 		for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj) 162. 			if(!otmp->nobj) panic("freeinv"); 163. 		otmp->nobj = obj->nobj; 164. 	}  165.  	if (obj->otyp == AMULET_OF_YENDOR && !obj->spe) { 166. 		if (!u.uhave_amulet) impossible ("don't have amulet?"); 167. 		u.uhave_amulet = 0; 168. 	}  169.  	if (obj->otyp == LOADSTONE) 170. 		curse(obj); 171. 	if (obj->otyp == LUCKSTONE) { 172. 		if (!carrying(LUCKSTONE)) u.moreluck = 0; 173. 		else if (stone_luck(TRUE) >= 0) u.moreluck = LUCKADD; 174. 		else u.moreluck = -LUCKADD; 175. 		flags.botl = 1; 176. 	}  177.  }  178.   179.  /* destroy object in fobj chain (if unpaid, it remains on the bill) */ 180. void 181. delobj(obj) 182. register struct obj *obj; 183. {  184.  #ifdef WALKIES 185. 	if(obj->otyp == LEASH && obj->leashmon != 0) o_unleash(obj); 186. #endif 187. 	freeobj(obj); 188. 	unpobj(obj); 189.  190.  /*	if contained in something else, decrease the container weight */ 191. 	if(obj->cobj) dec_cwt(obj->cobj, obj); 192.  193.  	obfree(obj, (struct obj *) 0); 194. }  195.   196.  /* unlink obj from chain starting with fobj */ 197. void 198. freeobj(obj) 199. register struct obj *obj; 200. {  201.  	register struct obj *otmp; 202. 	register int found = 0; 203. 	register struct rm *lev = &levl[obj->ox][obj->oy]; 204.  205.    	lev->omask = 0; 206.  207.  	if(obj == fobj) { 208. 		fobj = fobj->nobj; 209. 		found = 1; 210. 	}  211.  	for(otmp = fobj; otmp; otmp = otmp->nobj) { 212.  	    if (otmp->nobj == obj) { 213. 		otmp->nobj = obj->nobj; 214. 		found = 1; 215. 	    }  216.  	    if (otmp->ox == obj->ox && otmp->oy == obj->oy) { 217. 		lev->omask = 1; 218. 	    }  219.  	}  220.    	if (!found) panic("error in freeobj"); 221. #ifdef POLYSELF 222. 	if (!levl[u.ux][u.uy].omask && !levl[u.ux][u.uy].gmask) { 223. 		u.uundetected = 0; 224. 		if (!Invisible) pru; 225. 	}  226.  #endif 227. }  228.   229.  /* Note: freegold throws away its argument! */ 230.  void 231. freegold(gold) 232. register struct gold *gold; 233. {  234.  	register struct gold *gtmp; 235.  236.  	levl[gold->gx][gold->gy].gmask = 0; 237.  238.  	if(gold == fgold) fgold = gold->ngold; 239. 	else { 240. 		for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold) 241. 			if(!gtmp) panic("error in freegold"); 242. 		gtmp->ngold = gold->ngold; 243. 	}  244.  	free((genericptr_t) gold); 245. #ifdef POLYSELF 246. 	if (!levl[u.ux][u.uy].omask && !levl[u.ux][u.uy].gmask) { 247. 		u.uundetected = 0; 248. 		if (!Invisible) pru; 249. 	}  250.  #endif 251. }  252.   253.  struct monst * 254. m_at(x,y) 255. register int x, y;  256. { 257.  	register struct monst *mtmp; 258. #ifdef WORM 259. 	register struct wseg *wtmp; 260. 	m_atseg = 0; 261. #endif 262.  263.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ 264. 		if(mtmp->mx == x && mtmp->my == y)  265. return(mtmp); 266. #ifdef WORM 267. 		if(mtmp->wormno){ 268. 		    for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg) 269. 		    if(wtmp->wx == x && wtmp->wy == y){ 270. 			m_atseg = wtmp; 271. 			return(mtmp); 272. 		    }  273.  		}  274.  #endif 275. 	}  276.  	return((struct monst *)0); 277. }  278.   279.  struct obj * 280. o_at(x,y) 281. register int x, y;  282. { 283.  	register struct obj *otmp; 284.  285.  	for(otmp = fobj; otmp; otmp = otmp->nobj) 286. 		if(otmp->ox == x && otmp->oy == y) return(otmp); 287. 	return((struct obj *)0); 288. }  289.   290.  struct obj * 291. sobj_at(n,x,y) 292. register int n, x, y;  293. { 294.  	register struct obj *otmp; 295.  296.  	if(levl[x][y].omask) 297. 	    for(otmp = fobj; otmp; otmp = otmp->nobj) 298. 		if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)  299. return(otmp); 300. 	return((struct obj *)0); 301. }  302.   303.  int 304. carried(obj) 305. register struct obj *obj; 306. {  307.  	register struct obj *otmp; 308.  309.  	for(otmp = invent; otmp; otmp = otmp->nobj) 310. 		if(otmp == obj) return(1); 311. 	return(0); 312. }  313.   314.  struct obj * 315. carrying(type) 316. register int type; 317. {  318.  	register struct obj *otmp; 319.  320.  	for(otmp = invent; otmp; otmp = otmp->nobj) 321. 		if(otmp->otyp == type) 322. 			return(otmp); 323. 	return((struct obj *) 0); 324. }  325.   326.  struct obj * 327. o_on(id, objchn) 328. unsigned int id; 329. register struct obj *objchn; 330. {  331.  	while(objchn) { 332. 		if(objchn->o_id == id) return(objchn); 333. 		objchn = objchn->nobj; 334. 	}  335.  	return((struct obj *) 0); 336. }  337.   338.  struct gold * 339. g_at(x,y) 340. register int x, y;  341. { 342.  	register struct gold *gold = fgold; 343. 	while(gold) { 344. 		if(gold->gx == x && gold->gy == y) return(gold); 345. 		gold = gold->ngold; 346. 	}  347.  	return((struct gold *)0); 348. }  349.   350.  /* make dummy object structure containing gold - for temporary use only */ 351. static 352. struct obj * 353. mkgoldobj(q) 354. register long q;  355. { 356.  	register struct obj *otmp; 357.  358.  	otmp = newobj(0); 359. 	/* should set o_id etc. but otmp will be freed soon */ 360. 	otmp->olet = GOLD_SYM; 361. 	u.ugold -= q;  362. OGOLD(otmp) = q; 363. flags.botl = 1; 364. 	return(otmp); 365. }  366.   367.  /*  368.   * getobj returns: 369.  *	struct obj *xxx:	object to do something with. 370.  *	(struct obj *) 0	error return: no object. 371.  *	&zeroobj		explicitly no object (as in w-). 372.  */  373.  struct obj * 374. getobj(let,word) 375. register char *let,*word; 376. {  377.  	register struct obj *otmp; 378. 	register char ilet,ilet1,ilet2; 379. 	char buf[BUFSZ]; 380. 	char lets[BUFSZ]; 381. 	register int foo = 0, foo2; 382. 	register char *bp = buf; 383. 	xchar allowcnt = 0;	/* 0, 1 or 2 */ 384. 	boolean allowgold = FALSE, usegold = FALSE; 385. 		/* usegold is needed so that they are given a different message 386. 		 * if gold is prohibited because it's inappropriate, or because 387. 		 * it's appropriate if only they had any. 388. 		 */  389.  	boolean allowall = FALSE; 390. 	boolean allownone = FALSE; 391. 	xchar foox = 0; 392. 	long cnt; 393.  394.  	if(*let == '0') let++, allowcnt = 1; 395. 	if(*let == GOLD_SYM) let++, 396. 		usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE); 397. 	if(*let == '#') let++, allowall = TRUE; 398. 	if(*let == '-') let++, allownone = TRUE; 399. 	if(allownone) *bp++ = '-'; 400. 	if(allowgold) *bp++ = GOLD_SYM; 401. 	if(bp > buf && bp[-1] == '-') *bp++ = ' '; 402.  403.  	ilet = 'a'; 404. 	for(otmp = invent; otmp; otmp = otmp->nobj){ 405. 	    if(!*let || index(let, otmp->olet)) { 406. 		bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet; 407.  408.  		/* ugly check: remove inappropriate things */ 409. 		if((!strcmp(word, "take off") && 410. 		    (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))  411.  		     || (otmp==uarm && uarmc)  412.  #ifdef SHIRT  413.  		     || (otmp==uarmu && (uarm || uarmc))  414.  #endif  415.  		    ))  416.  		|| (!strcmp(word, "wear") && 417. 		     (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))  418.  							/* already worn */  419.  		|| (!strcmp(word, "wield") && 420. 		    (otmp->owornmask & W_WEP))  421.  		    ) { 422. 			foo--; 423. 			foox++; 424. 		}  425.   426.  		/* Second ugly check; unlike the first it won't trigger an  427. * "else" in "you don't have anything else to ___". 428. 		 */  429.  		if ((!strcmp(word, "wear") && 430. 		    (otmp->olet == TOOL_SYM && otmp->otyp != BLINDFOLD))  431.  		|| (!strcmp(word, "can") && 432. 		    (otmp->otyp != CORPSE))  433.  		|| (!strcmp(word, "write with") && 434. 		    (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER))  435.  		|| (!strcmp(word, "rub") && 436. 		    (otmp->olet == TOOL_SYM &&  437.  		     otmp->otyp != LAMP && otmp->otyp != MAGIC_LAMP))  438.  		    ) 439. 			foo--; 440. 	    }  441.  	    if(ilet == 'z') ilet = 'A'; else ilet++; 442. 	}  443.  	bp[foo] = 0; 444. 	if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0; 445. 	Strcpy(lets, bp);	/* necessary since we destroy buf */ 446. 	if(foo > 5) {			/* compactify string */ 447. 		foo = foo2 = 1; 448. 		ilet2 = bp[0]; 449. 		ilet1 = bp[1]; 450. 		while(ilet = bp[++foo2] = bp[++foo]){ 451. 			if(ilet == ilet1+1){ 452. 				if(ilet1 == ilet2+1) 453. 					bp[foo2 - 1] = ilet1 = '-'; 454. 				else if(ilet2 == '-') { 455. 					bp[--foo2] = ++ilet1; 456. 					continue; 457. 				}  458.  			}  459.  			ilet2 = ilet1; 460. 			ilet1 = ilet; 461. 		}  462.  	}  463.  	if(!foo && !allowall && !allowgold && !allownone) { 464. 		You("don't have anything %sto %s.",  465.  			foox ? "else " : "", word); 466. 		return((struct obj *)0); 467. 	}  468.  	for { 469. 		if(!buf[0]) { 470. #ifdef REDO 471. 		    if(!in_doagain) 472. #endif 473. 			pline("What do you want to %s? [*] ", word); 474. 		} else { 475. #ifdef REDO 476. 		    if(!in_doagain) 477. #endif 478. 			pline("What do you want to %s? [%s or ?*] ",  479.  				word, buf); 480. 		}  481.  		cnt = 0; 482. 		ilet = readchar; 483. 		while(digit(ilet) && allowcnt) { 484. #ifdef REDO 485. 			if (ilet != '?' && ilet != '*')	savech(ilet); 486. #endif 487. 			cnt = 10*cnt + (ilet - '0'); 488. 			allowcnt = 2;	/* signal presence of cnt */ 489. 			ilet = readchar; 490. 		}  491.  		if(digit(ilet)) { 492. 			pline("No count allowed with this command."); 493. 			continue; 494. 		}  495.  		if(index(quitchars,ilet)) { 496. 		    if(flags.verbose) 497. 			pline("Never mind."); 498. 		    return((struct obj *)0); 499. 		}  500.  		if(ilet == '-') { 501. 			return(allownone ? &zeroobj : (struct obj *) 0); 502. 		}  503.  		if(ilet == GOLD_SYM) { 504. 			if(!usegold){ 505. 				You("cannot %s gold.", word); 506. 				return(struct obj *)0; 507. 			} else if (!allowgold) { 508. 				You("are not carrying any gold."); 509. 				return(struct obj *)0; 510. 			}  511.  			if(!(allowcnt == 2 && cnt < u.ugold)) 512. 				cnt = u.ugold; 513. 			return(mkgoldobj(cnt)); 514. 		}  515.  		if(allowcnt == 2 && !strcmp(word,"throw")) { 516. 			/* permit counts for throwing gold, but don't accept 517. 			 * counts for other things since the throw code will 518. 			 * split off a single item anyway */ 519. 			allowcnt = 1; 520. 			if(cnt != 1) { 521. 			    pline("You can only throw one item at a time."); 522. 			    continue; 523. 			}  524.  		}  525.  		if(ilet == '?') { 526. 			doinv(lets); 527. 			if(!(ilet = morc)) continue; 528. 			/* he typed a letter (not a space) to more */ 529. 		} else if(ilet == '*') { 530. 			doinv(NULL); 531. 			if(!(ilet = morc)) continue; 532. 			/* ... */  533.  		}  534.  #ifdef REDO 535. 		if (ilet != '?' && ilet != '*')	savech(ilet); 536. #endif 537. 		if(flags.invlet_constant) { 538. 			for(otmp = invent; otmp; otmp = otmp->nobj) 539. 				if(otmp->invlet == ilet) break; 540. 		} else { 541. 			if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1; 542. 			ilet -= 'a'; 543. 			for(otmp = invent; otmp && ilet;  544.  					ilet--, otmp = otmp->nobj) ; 545. 		}  546.  		if(!otmp) { 547. 			You("don't have that object."); 548. 			continue; 549. 		}  550.  		if(cnt < 0 || otmp->quan < cnt) { 551. 			You("don't have that many!  You have only %u."  552.  		, otmp->quan); 553. 			continue; 554. 		}  555.  		break; 556. 	}  557.  	if(!allowall && let && !index(let,otmp->olet)) { 558. 		pline("That is a silly thing to %s.",word); 559. 		return((struct obj *)0); 560. 	}  561.  	if(allowcnt == 2) {	/* cnt given */ 562. 		if(cnt == 0) return (struct obj *)0; 563. 		if(cnt != otmp->quan) { 564. 			register struct obj *obj; 565. #ifdef LINT	/*splitobj for (long )cnt > 30000 && sizeof(int) == 2*/ 566. 			obj = (struct obj *)0; 567. #else 568. 			if (sizeof(int) == 2) 569. 				obj = splitobj(otmp,  570.  					(int )(cnt >30000 ? 30000 : cnt)); 571. 			else 572. 				obj = splitobj(otmp, (int) cnt); 573. #endif 574. 			if(otmp == uwep) setuwep(obj); 575. 		}  576.  	}  577.  	return(otmp); 578. }  579.   580.  static int 581. ckunpaid(otmp) 582. register struct obj *otmp; 583. {  584.  	return((int)(otmp->unpaid)); 585. }  586.   587.  static boolean 588. wearing_armor { 589. 	return(uarm || uarmc || uarmf || uarmg || uarmh || uarms  590.  #ifdef SHIRT  591.  		|| uarmu  592.  #endif  593.  		); 594. }  595.   596.  static boolean 597. is_worn(otmp) 598. register struct obj *otmp; 599. {  600.      return(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP))); 601. }  602.   603.  static const char removeables[] = 604. 	{ ARMOR_SYM, WEAPON_SYM, RING_SYM, AMULET_SYM, TOOL_SYM, ' ', 0 }; 605.  606.  /* interactive version of getobj - used for Drop, Identify and */ 607. /* Takeoff (A). Return the number of times fn was called successfully */ 608. int 609. ggetobj(word, fn, mx) 610. register char *word; 611. register int (*fn), mx; 612. {  613.  	char buf[BUFSZ]; 614. 	register char *ip; 615. 	register char sym; 616. 	register int oletct = 0, iletct = 0; 617. 	register boolean allflag = FALSE; 618. 	char olets[20], ilets[20]; 619. 	int (*ckfn) = (int (*)) 0; 620. 	xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */ 621. 	register boolean takeoff = !strcmp(word, "take off"); 622.  623.  	if(takeoff && !wearing_armor && !uwep && !uamul &&  624.  			!uleft && !uright && !ublindf) { 625. 		You("are not wearing anything."); 626. 		return(0); 627. 	}  628.  	if(!invent && !allowgold){ 629. 		You("have nothing to %s.", word); 630. 		return(0); 631. 	} else { 632. 		register struct obj *otmp = invent; 633. 		register int uflg = 0; 634.  635.  		if(allowgold) ilets[iletct++] = GOLD_SYM; 636. 		ilets[iletct] = 0; 637. 		while(otmp) { 638. 			if(!index(ilets, otmp->olet)){ 639. 			    if(!takeoff || is_worn(otmp)) 640. 				ilets[iletct++] = otmp->olet; 641. 			    ilets[iletct] = 0; 642. 			}  643.  			if(otmp->unpaid) uflg = 1; 644. 			otmp = otmp->nobj; 645. 		}  646.  		ilets[iletct++] = ' '; 647. 		if(uflg && !takeoff) ilets[iletct++] = 'u'; 648. 		if(invent && !takeoff) ilets[iletct++] = 'a'; 649. 		ilets[iletct] = 0; 650. 	}  651.  	pline("What kinds of thing do you want to %s? [%s] ",  652.  		word, ilets); 653. 	getlin(buf); 654. 	if(buf[0] == '\033') { 655. 		clrlin; 656. 		return(0); 657. 	}  658.  	ip = buf; 659. 	olets[0] = 0; 660. 	while(sym = *ip++){ 661. 		if(sym == ' ') continue; 662. 		if(takeoff) { 663. 		    if(!index(removeables,sym)) { 664. 			pline("Not applicable."); 665. 			return(0); 666. 		    } else if(sym == ARMOR_SYM && !wearing_armor) { 667. 			You("are not wearing any armor."); 668. 			return(0); 669. 		    } else if(sym == WEAPON_SYM && !uwep) { 670. 			You("are not wielding anything."); 671. 			return(0); 672. 		    } else if(sym == RING_SYM && !uright && !uleft) { 673. 			You("are not wearing rings."); 674. 			return(0); 675. 		    } else if(sym == AMULET_SYM && !uamul) { 676. 			You("are not wearing an amulet."); 677. 			return(0); 678. 		    } else if(sym == TOOL_SYM && !ublindf) { 679. 			You("are not wearing a blindfold."); 680. 			return(0); 681. 		    }  682.  		}  683.  		if(sym == GOLD_SYM) { 684. 			if(allowgold == 1) 685. 				(*fn)(mkgoldobj(u.ugold)); 686. 			else if(!u.ugold) 687. 				You("have no gold."); 688. 			allowgold = 2; 689. 		} else if(sym == 'a' || sym == 'A') 690. 			allflag = TRUE; 691. 		else if(sym == 'u' || sym == 'U') 692. 			ckfn = ckunpaid; 693. 		else if(index(inv_order, sym)) { 694. 			if(!index(olets, sym)) { 695. 				olets[oletct++] = sym; 696. 				olets[oletct] = 0; 697. 			}  698.  		} else You("don't have any %c's.", sym); 699. 	}  700.  	if(allowgold == 2 && !oletct) 701. 		return(1);	/* he dropped gold (or at least tried to) */ 702. 	else 703. 		return(askchain(invent, TRUE, olets, allflag, fn, ckfn, mx, word)); 704. }  705.   706.  /*  707.   * Walk through the chain starting at objchn and ask for all objects 708.  * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL) 709.  * whether the action in question (i.e., fn) has to be performed. 710.  * If allflag then no questions are asked. Max gives the max nr of 711. * objects to be treated. Return the number of objects treated. 712.  * If ininv is TRUE, the objects are in the player's inventory. 713.  */  714.  int 715. askchain(objchn, ininv, olets, allflag, fn, ckfn, mx, word) 716. register struct obj *objchn; 717. register int ininv, allflag, mx; 718. register char *olets, *word; 719. register int (*fn), (*ckfn); 720. {  721.  	register struct obj *otmp, *otmp2; 722. 	register char sym, ilet; 723. 	register int cnt = 0, dud = 0; 724. 	register boolean takeoff, nodot; 725.  726.  	takeoff = !strcmp(word, "take off"); 727. 	nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||  728.  	   		!strcmp(word, "identify") || takeoff); 729. 	/* changes so the askchain is interrogated in the order specified. 730. 	 * For example, if a person specifies =/ then first all rings will be  731. * asked about followed by all wands -dgk 732. 	 */  733.  nextclass: 734. 	ilet = 'a'-1; 735. 	for(otmp = (ininv ? invent : objchn); otmp; otmp = otmp2){ 736. 		if(ilet == 'z') ilet = 'A'; else ilet++; 737. 		otmp2 = otmp->nobj; 738. 		if (olets && *olets && otmp->olet != *olets) continue; 739. 		if(takeoff && !is_worn(otmp)) continue; 740. 		if(ckfn && !(*ckfn)(otmp)) continue; 741. 		if(!allflag) { 742. 			if(ininv) { 743. 			    if (nodot) 744. 				 pline(xprname(otmp, ilet, FALSE)); 745. 			    else pline(xprname(otmp, ilet, TRUE)); 746. 			}  747.  			else 748. 			    pline(doname(otmp)); 749. 			addtopl("? "); 750. 			sym = nyaq; 751. 		}  752.  		else	sym = 'y'; 753.  754.  		switch(sym){ 755. 		case 'a': 756. 			allflag = 1; 757. 		case 'y': 758. 			cnt += (*fn)(otmp); 759. 			if(--mx == 0) goto ret; 760. 		case 'n': 761. 			if(nodot) dud++; 762. 		default: 763. 			break; 764. 		case 'q': 765. 			goto ret; 766. 		}  767.  	}  768.  	if (olets && *olets && *++olets) 769. 		goto nextclass; 770. 	if(!takeoff && (dud || cnt)) pline("That was all."); 771. 	else if(!dud && !cnt) pline("No applicable objects."); 772. ret: 773. 	return(cnt); 774. }  775.   776.  static char 777. obj_to_let(obj)	/* should of course only be called for things in invent */ 778. register struct obj *obj; 779. {  780.  	register struct obj *otmp; 781. 	register char ilet; 782.  783.  	if(flags.invlet_constant) 784. 		return(obj->invlet); 785. 	ilet = 'a'; 786. 	for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj) 787. 		if(++ilet > 'z') ilet = 'A'; 788. 	return(otmp ? ilet : NOINVSYM); 789. }  790.   791.  void 792. prinv(obj) 793. register struct obj *obj; 794. {  795.  	pline(xprname(obj, obj_to_let(obj), TRUE)); 796. }  797.   798.  static char * 799. xprname(obj,let,dot) 800. register struct obj *obj; 801. register char let; 802. register boolean dot; 803. {  804.  #ifdef LINT	/* handle static char li[BUFSZ]; */ 805. 	char li[BUFSZ]; 806. #else 807. 	static char li[BUFSZ]; 808. #endif 809.  810.  	Sprintf(li, "%c - %s",  811.  		(flags.invlet_constant ? obj->invlet : let), 812.  		doname(obj)); 813. 	if(dot) Sprintf(eos(li),"."); 814. 	return(li); 815. }  816.   817.  int 818. ddoinv 819. {  820.  	doinv(NULL); 821. 	return 0; 822. }  823.   824.  /* called with 0 or "": all objects in inventory */ 825. /* otherwise: all objects with (serial) letter in lets */ 826. void 827. doinv(lets) 828. register char *lets; 829. {  830.  	register struct obj *otmp; 831. 	register char ilet; 832. 	int ct = 0; 833. 	char any[BUFSZ]; 834. 	char *invlet = inv_order; 835. 	int classcount = 0; 836.  837.  	morc = 0;		/* just to be sure */ 838.  839.  	if(!invent){ 840. 		pline("Not carrying anything."); 841. 		return; 842. 	}  843.  	if (lets != NULL) { 844. 		for(ct=0; lets[ct]; ct++) { 845. 			if (ct >= 52) { 846. 				impossible("bad lets contents"); 847. 				break; 848. 			}  849.  		}  850.  		if (ct==1) { 851. 			ilet = 'a'; 852. 			for(otmp = invent; otmp; otmp = otmp->nobj) { 853. 				if(flags.invlet_constant) ilet = otmp->invlet; 854.  855.  				if (ilet == lets[0]) 856. 					pline(xprname(otmp, lets[0], TRUE)); 857.  858.  				if(!flags.invlet_constant) 859. 					if(++ilet > 'z') ilet = 'A'; 860. 			}  861.  			return; 862. 		}  863.  	}  864.  	ct = 0; 865.  866.  	cornline(0, NULL); 867. nextclass: 868. 	classcount = 0; 869. 	ilet = 'a'; 870. 	for(otmp = invent; otmp; otmp = otmp->nobj) { 871. 		if(flags.invlet_constant) ilet = otmp->invlet; 872. 		if(!lets || !*lets || index(lets, ilet)) { 873. 			if (!flags.sortpack || otmp->olet == *invlet) { 874. 				if (flags.sortpack && !classcount) { 875. 					cornline(1, let_to_name(*invlet)); 876. 					classcount++; 877. 				}  878.  				cornline(1, xprname(otmp, ilet, TRUE)); 879. 				any[ct++] = ilet; 880. 			}  881.  		}  882.  		if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 883. 	}  884.  	if (flags.sortpack && *++invlet) goto nextclass; 885. 	any[ct] = 0; 886. 	cornline(2, any); 887. }  888.   889.  int 890. dotypeinv				/* free after Robert Viduya */ 891. /* Changed to one type only, so he doesn't have to type cr */ 892. {  893.      	char c, ilet; 894.     	char stuff[BUFSZ]; 895.     	register int stct; 896.     	register struct obj *otmp; 897.     	boolean billx = inshop && doinvbill(0); 898.     	boolean unpd = FALSE; 899.  900.  	if (!invent && !u.ugold && !billx) { 901. 	    You("aren't carrying anything."); 902. 	    return 0; 903. 	}  904.   905.  	stct = 0; 906. 	if(u.ugold) stuff[stct++] = GOLD_SYM; 907. 	stuff[stct] = 0; 908. 	for(otmp = invent; otmp; otmp = otmp->nobj) { 909. 	    if (!index (stuff, otmp->olet)) { 910. 		stuff[stct++] = otmp->olet; 911. 		stuff[stct] = 0; 912. 	    }  913.  	    if(otmp->unpaid) 914. 		unpd = TRUE; 915. 	}  916.  	if(unpd) stuff[stct++] = 'u'; 917. 	if(billx) stuff[stct++] = 'x'; 918. 	stuff[stct] = 0; 919.  920.  	if(stct > 1) { 921. #ifdef REDO 922. 	  if (!in_doagain) 923. #endif 924. 	    pline ("What type of object do you want an inventory of? [%s] ",  925.  			stuff); 926. 	    c = readchar; 927. #ifdef REDO 928. 	    savech(c); 929. #endif 930. 	    if(index(quitchars,c)) { 931. 	    	    clrlin; 932. 	    	    return 0; 933. 	    }  934.  	} else 935. 	    c = stuff[0]; 936.  937.  	if(c == GOLD_SYM) 938. 	    return(doprgold); 939.  940.  	if(c == 'x' || c == 'X') { 941. 	    if(billx) 942. 		(void) doinvbill(1); 943. 	    else 944. 		pline("No used-up objects on the shopping bill."); 945. 	    return(0); 946. 	}  947.   948.  	if((c == 'u' || c == 'U') && !unpd) { 949. 		You("are not carrying any unpaid objects."); 950. 		return(0); 951. 	}  952.   953.  	stct = 0; 954. 	ilet = 'a'; 955. 	for (otmp = invent; otmp; otmp = otmp -> nobj) { 956. 	    if(flags.invlet_constant) ilet = otmp->invlet; 957. 	    if (c == otmp -> olet || (c == 'u' && otmp -> unpaid)) 958. 		stuff[stct++] = ilet; 959. 	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 960. 	}  961.  	stuff[stct] = '\0'; 962. 	if(stct == 0) 963. 		You("have no such objects."); 964. 	else 965. 		doinv (stuff); 966.  967.  	return(0); 968. }  969.   970.  /* look at what is here */ 971. int 972. dolook { 973.     	register struct obj *otmp, *otmp0; 974.     	register struct gold *gold; 975.     	char *verb = Blind ? "feel" : "see"; 976.     	int ct = 0; 977.     	int fd = 0; 978.  979.      	read_engr_at(u.ux, u.uy); /* Eric Backus */ 980.     	if(!u.uswallow) { 981. 		otmp0 = o_at(u.ux, u.uy); 982. 		gold = g_at(u.ux, u.uy); 983.     	}  else  { 984. 		You("%s no objects here.", verb); 985. 		return(!!Blind); 986.     	}  987.   988.  	if(IS_DOOR(levl[u.ux][u.uy].typ))  { 989. 		fd++; 990. 		switch(levl[u.ux][u.uy].doormask) { 991. 		    case D_NODOOR: 992. 			pline("There is a doorway here."); break; 993. 		    case D_ISOPEN: 994. 			pline("There is an open door here."); break; 995. 		    case D_BROKEN: 996. 			pline("There is a broken door here."); break; 997. 		    default: 998. 			pline("There is a closed door here."); 999. 		}  1000. 	}  1001.     	/* added by GAN 10/30/86 */ 1002. #ifdef FOUNTAINS 1003.    	if(IS_FOUNTAIN(levl[u.ux][u.uy].typ))  { 1004. 		fd++; 1005. 		pline("There is a fountain here."); 1006.    	}  1007. #endif 1008. #ifdef THRONES 1009.    	if(IS_THRONE(levl[u.ux][u.uy].typ))  { 1010. 		fd++; 1011. 		pline("There is an opulent throne here."); 1012.    	}  1013. #endif 1014. #ifdef SINKS 1015.    	if(IS_SINK(levl[u.ux][u.uy].typ))  { 1016. 		fd++; 1017. 		pline("There is a kitchen sink here."); 1018.    	}  1019. #endif 1020. #ifdef ALTARS 1021.    	if(IS_ALTAR(levl[u.ux][u.uy].typ))  { 1022. 		char *al; 1023. 1024. 		fd++; 1025. 		switch (levl[u.ux][u.uy].altarmask & ~A_SHRINE) { 1026. 			case 0: al = "chaotic"; break; 1027. 			case 1: al = "neutral"; break; 1028. 			default: al = "lawful"; break; 1029. 		} 1030. 		pline("There is an altar to %s here (%s).", a_gname, al); 1031.    	}  1032. #endif 1033. 1034.     	if(u.ux == xupstair && u.uy == yupstair)  { 1035. 		fd++; 1036. 		pline("There is a stairway up here."); 1037.    	}  1038.     	if(u.ux == xdnstair && u.uy == ydnstair)  { 1039. 		fd++; 1040. 		pline("There is a stairway down here."); 1041.    	}  1042. #ifdef STRONGHOLD 1043.    	if(u.ux == xupladder && u.uy == yupladder)	{ 1044. 		fd++; 1045. 		pline("There is a ladder up here."); 1046.    	}  1047.     	if(u.ux == xdnladder && u.uy == ydnladder)	{ 1048. 		fd++; 1049. 		pline("There is a ladder down here."); 1050.    	}  1051.     	if (levl[u.ux][u.uy].typ == DRAWBRIDGE_DOWN) { 1052. 		fd++; 1053. 		pline("There is a lowered drawbridge here."); 1054.    	}  1055. #endif /* STRONGHOLD /**/ 1056. 1057.     	if(Blind)  { 1058. 		You("try to feel what is lying here on the floor."); 1059. 	 	if(Levitation) { 1060. 			pline("But you can't reach it!"); 1061. 			return(0); 1062. 	 	} 1063.     	}  1064.  1065.     	if(!otmp0 && !gold) { 1066. 		if(Blind || !fd) 1067. 			You("%s no objects here.", verb); 1068. 		return(!!Blind); 1069.    	}  1070.  1071.     	cornline(0, "Things that are here:"); 1072.    	for(otmp = otmp0; otmp; otmp = otmp->nobj) { 1073. 		if(otmp->ox == u.ux && otmp->oy == u.uy) { 1074. 	   		ct++; 1075. 	   		cornline(1, doname(otmp)); 1076. 1077. 	    		if(Blind  && !uarmg &&  1078. #ifdef POLYSELF  1079. 			!resists_ston(uasmon) &&  1080. #endif  1081. 	       		(otmp->otyp == CORPSE && otmp->corpsenm == PM_COCKATRICE)) { 1082. 			   pline("Touching the dead cockatrice is a fatal mistake..."); 1083. 			   You("turn to stone..."); 1084. 			   killer = "dead cockatrice"; 1085. 		 	   done("stoned"); 1086. 	   		}  1087. 		}  1088.     	}  1089.  1090.     	if(gold) { 1091. 		char gbuf[30]; 1092. 1093. 		Sprintf(gbuf, "%ld gold piece%s",  1094. 			gold->amount, plur(gold->amount)); 1095. 		if(!ct++) 1096. 	   		You("%s here %s.", verb, gbuf); 1097. 		else 1098. 	   		cornline(1, gbuf); 1099.    	}  1100.  1101.     	if(ct == 1 && !gold) { 1102. 		You("%s here %s.", verb, doname(otmp0)); 1103. 		cornline(3, NULL); 1104.    	}  1105.     	if(ct > 1) 1106. 		cornline(2, NULL); 1107.    	return(!!Blind); 1108. } 1109.  1110. void 1111. stackobj(obj) 1112. register struct obj *obj; 1113. { 1114. 	register struct obj *otmp = fobj; 1115. 	for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj) 1116. 		if(otmp->ox == obj->ox && otmp->oy == obj->oy && 1117. 			merged(obj,otmp,1)) 1118. 				break; 1119. 	return; 1120. } 1121.  1122. static boolean 1123. mergable(otmp, obj)	/* returns TRUE if obj & otmp can be merged */ 1124. 	register struct obj *otmp, *obj; 1125. { 1126. 	if(obj->otyp != otmp->otyp || obj->unpaid != otmp->unpaid ||  1127. 	   obj->spe != otmp->spe || obj->dknown != otmp->dknown ||  1128. 	   (obj->bknown != otmp->bknown && pl_character[0] != 'P') ||  1129. 	   obj->cursed != otmp->cursed || obj->blessed != otmp->blessed ||  1130. 	   obj->no_charge != otmp->no_charge ||  1131. 	   obj->otrapped != otmp->otrapped) 1132. 	   return(FALSE); 1133. 1134. 	else if((obj->olet==WEAPON_SYM || obj->olet==ARMOR_SYM) &&  1135. 		obj->rustfree != otmp->rustfree) return FALSE; 1136. 1137. 	else if(obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) 1138. 		return( (obj->corpsenm == otmp->corpsenm) && 1139. 			(!ONAME(obj) || !strcmp(ONAME(obj), ONAME(otmp))) ); 1140. 1141. 	else if(obj->known == otmp->known) { 1142. 		return(objects[obj->otyp].oc_merge); 1143. 	} else return(FALSE); 1144. } 1145.  1146. int 1147. doprgold{ 1148. 	if(!u.ugold) 1149. 		You("do not carry any gold."); 1150. 	else 1151. 		You("are carrying %ld gold piece%s.", u.ugold, plur(u.ugold)); 1152. 	return 0; 1153. } 1154.  1155. int 1156. doprwep 1157. { 1158. 	if(!uwep) You("are empty %s.", body_part(HANDED)); 1159. 	else prinv(uwep); 1160. 	return 0; 1161. } 1162.  1163. int 1164. doprarm{ 1165. 	if(!wearing_armor) 1166. 		You("are not wearing any armor."); 1167. 	else { 1168. #ifdef SHIRT 1169. 		char lets[8]; 1170. #else 1171. 		char lets[7]; 1172. #endif 1173. 		register int ct = 0; 1174. 1175. #ifdef SHIRT 1176. 		if(uarmu) lets[ct++] = obj_to_let(uarmu); 1177. #endif 1178. 		if(uarm) lets[ct++] = obj_to_let(uarm); 1179. 		if(uarmc) lets[ct++] = obj_to_let(uarmc); 1180. 		if(uarmh) lets[ct++] = obj_to_let(uarmh); 1181. 		if(uarms) lets[ct++] = obj_to_let(uarms); 1182. 		if(uarmg) lets[ct++] = obj_to_let(uarmg); 1183. 		if(uarmf) lets[ct++] = obj_to_let(uarmf); 1184. 		lets[ct] = 0; 1185. 		doinv(lets); 1186. 	} 1187. 	return 0; 1188. } 1189.  1190. int 1191. doprring{ 1192. 	if(!uleft && !uright) 1193. 		You("are not wearing any rings."); 1194. 	else { 1195. 		char lets[3]; 1196. 		register int ct = 0; 1197. 1198. 		if(uleft) lets[ct++] = obj_to_let(uleft); 1199. 		if(uright) lets[ct++] = obj_to_let(uright); 1200. 		lets[ct] = 0; 1201. 		doinv(lets); 1202. 	} 1203. 	return 0; 1204. } 1205.  1206. int 1207. dopramulet{ 1208. 	if (!uamul) 1209. 		You("are not wearing an amulet."); 1210. 	else 1211. 		prinv(uamul); 1212. 	return 0; 1213. } 1214.  1215. int 1216. doprtool{ 1217. 	register struct obj *otmp; 1218. 	register int ct=0; 1219. 	char lets[3]; /* Maximum: pick-axe, blindfold */ 1220. 1221. 	for(otmp = invent; otmp; otmp = otmp->nobj) { 1222. 		if (((otmp->owornmask & W_TOOL) && otmp->olet==TOOL_SYM) 1223. 		   || (otmp==uwep && 1224. 		  (otmp->otyp==PICK_AXE || otmp->otyp==TIN_OPENER))) 1225. 			lets[ct++] = obj_to_let(otmp); 1226. 	} 1227. 	lets[ct] = 0; 1228. 	if (!ct) You("are not using any tools."); 1229. 	else doinv(lets); 1230. 	return 0; 1231. } 1232.  1233. int 1234. digit(c) 1235. char c; 1236. { 1237. 	return(c >= '0' && c <= '9'); 1238. } 1239.  1240. /*  1241.  * useupf(obj) 1242. * uses up an object that's on the floor 1243. */  1244. void 1245. useupf(obj) 1246. register struct obj *obj; 1247. { 1248. 	if(obj->quan > 1)  { 1249. 		obj->quan--; 1250. 		obj->owt = weight(obj); 1251. 	} else delobj(obj); 1252. } 1253.  1254. /*  1255.  * Convert from a symbol to a string for printing object classes 1256. *  1257.  * Names from objects.h  1258. * char obj_symbols[] = { 1259. *	ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM, 1260. *	BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM, 1261. *	WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 }; 1262. */  1263.  1264. static const char *names[] = { 1265. 	"Illegal objects", "Amulets", "Comestibles", "Weapons", 1266. 	"Tools", "Iron balls", "Chains", "Boulders/Statues", "Armor", 1267. 	"Potions", "Scrolls", "Wands", 1268. #ifdef SPELLS 1269. 	"Spellbooks", 1270. #endif 1271. 	"Rings", "Gems"}; 1272. 1273. char * 1274. let_to_name(let) 1275. char let; 1276. { 1277. 	char *pos = index(obj_symbols, let); 1278. 	/* arbitrary buffer size by Tom May (tom@uw-warp) */ 1279. 	static char *buf = NULL; 1280. 1281. 	if (buf == NULL) 1282. 	   buf = (char *) alloc ((unsigned)(strlen(HI)+strlen(HE)+15+1)); 1283. 1284. 	if (pos == NULL) pos = obj_symbols; 1285. 	if (HI && HE) 1286. 	   Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE); 1287. 	else 1288. 	   Sprintf(buf, "%s", names[pos - obj_symbols]); 1289. 	return (buf); 1290. } 1291.  1292. void 1293. reassign 1294. { 1295. 	register int i;  1296. register struct obj *obj; 1297. 1298. 	for(obj = invent, i = 0; obj; obj = obj->nobj, i++) 1299. 		obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26); 1300. 	lastinvnr = i; 1301. }