Source:NetHack 2.2a/invent.c

Below is the full text to invent.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/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	2.1	87/10/19 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.     4.    #include	  5.    #include	"hack.h"  6.    extern struct obj *splitobj; 7.   extern struct obj zeroobj; 8.   extern char morc; 9.   extern char quitchars[]; 10.  static char *xprname; 11.   12.   #ifndef NOWORM 13.  #include	"wseg.h"  14. extern struct wseg *wsegs[32]; 15.  #endif 16.   17.   #define	NOINVSYM	'#' 18.   19.   int lastinvnr = 51;	/* 0 ... 51 */ 20.    21.   static 22.  assigninvlet(otmp) 23.  register struct obj *otmp; 24.  {  25.   	boolean inuse[52]; 26.  	register int i;  27. register struct obj *obj; 28.   29.   	for(i = 0; i < 52; i++) inuse[i] = FALSE; 30.  	for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) { 31.  		i = obj->invlet; 32.  		if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else 33.  		if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE; 34.  		if(i == otmp->invlet) otmp->invlet = 0; 35.  	}  36.   	if((i = otmp->invlet) &&  37.   	    (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z'))) 38.  		return; 39.  	for(i = lastinvnr+1; i != lastinvnr; i++) { 40.  		if(i == 52) { i = -1; continue; } 41.  		if(!inuse[i]) break; 42.  	}  43.   	otmp->invlet = (inuse[i] ? NOINVSYM :  44.   			(i < 26) ? ('a'+i) : ('A'+i-26)); 45.  	lastinvnr = i;  46. } 47.    48.   struct obj * 49.  addinv(obj) 50.  register struct obj *obj; 51.  {  52.   	register struct obj *otmp; 53.   54.   	/* merge or attach to end of chain */ 55.  	if(!invent) { 56.  		invent = obj; 57.  		otmp = 0; 58.  	} else 59.  	for(otmp = invent; /* otmp */; otmp = otmp->nobj) { 60.  		if(merged(otmp, obj, 0)) 61.  			return(otmp); 62.  		if(!otmp->nobj) { 63.  			otmp->nobj = obj; 64.  			break; 65.  		}  66.   	}  67.   	obj->nobj = 0; 68.   69.   	if(flags.invlet_constant) { 70.  		assigninvlet(obj); 71.  		/*  72.   		 * The ordering of the chain is nowhere significant 73.  		 * so in case you prefer some other order than the 74.  		 * historical one, change the code below. 75.  		 */  76.   		if(otmp) {	/* find proper place in chain */ 77.  			otmp->nobj = 0; 78.  			if((invent->invlet ^ 040) > (obj->invlet ^ 040)) { 79.  				obj->nobj = invent; 80.  				invent = obj; 81.  			} else 82.  			for(otmp = invent; ; otmp = otmp->nobj) { 83.  			    if(!otmp->nobj ||  84.   				(otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){ 85.  				obj->nobj = otmp->nobj; 86.  				otmp->nobj = obj; 87.  				break; 88.  			    }  89.   			}  90.   		}  91.   	}  92.    93.   	return(obj); 94.  }  95.    96.   useup(obj) 97.  register struct obj *obj; 98.  {  99.   	if(obj->quan > 1){ 100. 		obj->quan--; 101. 		obj->owt = weight(obj); 102. 	} else { 103. 		setnotworn(obj); 104. 		freeinv(obj); 105. 		obfree(obj, (struct obj *) 0); 106. 	}  107.  }  108.   109.  freeinv(obj) 110. register struct obj *obj; 111. {  112.  	register struct obj *otmp; 113.  114.  	if(obj == invent) 115. 		invent = invent->nobj; 116. 	else { 117. 		for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj) 118. 			if(!otmp->nobj) panic("freeinv"); 119. 		otmp->nobj = obj->nobj; 120. 	}  121.  }  122.   123.  /* destroy object in fobj chain (if unpaid, it remains on the bill) */ 124. delobj(obj) register struct obj *obj; { 125. 	freeobj(obj); 126. 	unpobj(obj); 127. 	obfree(obj, (struct obj *) 0); 128. }  129.   130.  /* unlink obj from chain starting with fobj */ 131. freeobj(obj) register struct obj *obj; { 132. 	register struct obj *otmp; 133.  134.  	if(obj == fobj) fobj = fobj->nobj; 135. 	else { 136. 		for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj) 137. 			if(!otmp) panic("error in freeobj"); 138. 		otmp->nobj = obj->nobj; 139. 	}  140.  }  141.   142.  /* Note: freegold throws away its argument! */ 143.  freegold(gold) register struct gold *gold; { 144. 	register struct gold *gtmp; 145.  146.  	if(gold == fgold) fgold = gold->ngold; 147. 	else { 148. 		for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold) 149. 			if(!gtmp) panic("error in freegold"); 150. 		gtmp->ngold = gold->ngold; 151. 	}  152.  	free((char *) gold); 153. }  154.   155.  deltrap(trap) 156. register struct trap *trap; 157. {  158.  	register struct trap *ttmp; 159.  160.  	if(trap == ftrap) 161. 		ftrap = ftrap->ntrap; 162. 	else { 163. 		for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ; 164. 		ttmp->ntrap = trap->ntrap; 165. 	}  166.  	free((char *) trap); 167. }  168.   169.  struct wseg *m_atseg; 170.  171.  struct monst * 172. m_at(x,y) 173. register x,y; 174. {  175.  	register struct monst *mtmp; 176. #ifndef NOWORM 177. 	register struct wseg *wtmp; 178. #endif 179.  180.  	m_atseg = 0; 181. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ 182. 		if(mtmp->mx == x && mtmp->my == y)  183. return(mtmp); 184. #ifndef NOWORM 185. 		if(mtmp->wormno){ 186. 		    for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg) 187. 		    if(wtmp->wx == x && wtmp->wy == y){ 188. 			m_atseg = wtmp; 189. 			return(mtmp); 190. 		    }  191.  		}  192.  #endif 193. 	}  194.  	return(0); 195. }  196.   197.  struct obj * 198. o_at(x,y) 199. register x,y; 200. {  201.  	register struct obj *otmp; 202.  203.  	for(otmp = fobj; otmp; otmp = otmp->nobj) 204. 		if(otmp->ox == x && otmp->oy == y) return(otmp); 205. 	return(0); 206. }  207.   208.  struct obj * 209. sobj_at(n,x,y) 210. register n,x,y; 211. {  212.  	register struct obj *otmp; 213.  214.  	for(otmp = fobj; otmp; otmp = otmp->nobj) 215. 		if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)  216. return(otmp); 217. 	return(0); 218. }  219.   220.  carried(obj) register struct obj *obj; { 221. register struct obj *otmp; 222. 	for(otmp = invent; otmp; otmp = otmp->nobj) 223. 		if(otmp == obj) return(1); 224. 	return(0); 225. }  226.   227.  struct obj * 228. carrying(type) 229. register int type; 230. {  231.  	register struct obj *otmp; 232.  233.  	for(otmp = invent; otmp; otmp = otmp->nobj) 234. 		if(otmp->otyp == type) 235. 			return(otmp); 236. 	return((struct obj *) 0); 237. }  238.   239.  struct obj * 240. o_on(id, objchn) unsigned int id; register struct obj *objchn; { 241. 	while(objchn) { 242. 		if(objchn->o_id == id) return(objchn); 243. 		objchn = objchn->nobj; 244. 	}  245.  	return((struct obj *) 0); 246. }  247.   248.  struct trap * 249. t_at(x,y) 250. register x,y; 251. {  252.  	register struct trap *trap = ftrap; 253. 	while(trap) { 254. 		if(trap->tx == x && trap->ty == y) return(trap); 255. 		trap = trap->ntrap; 256. 	}  257.  	return(0); 258. }  259.   260.  struct gold * 261. g_at(x,y) 262. register x,y; 263. {  264.  	register struct gold *gold = fgold; 265. 	while(gold) { 266. 		if(gold->gx == x && gold->gy == y) return(gold); 267. 		gold = gold->ngold; 268. 	}  269.  	return(0); 270. }  271.   272.  /* make dummy object structure containing gold - for temporary use only */ 273. struct obj * 274. mkgoldobj(q) 275. register long q;  276. { 277.  	register struct obj *otmp; 278.  279.  	otmp = newobj(0); 280. 	/* should set o_id etc. but otmp will be freed soon */ 281. 	otmp->olet = GOLD_SYM; 282. 	u.ugold -= q;  283. OGOLD(otmp) = q; 284. flags.botl = 1; 285. 	return(otmp); 286. }  287.   288.  /*  289.   * getobj returns: 290.  *	struct obj *xxx:	object to do something with. 291.  *	(struct obj *) 0	error return: no object. 292.  *	&zeroobj		explicitly no object (as in w-). 293.  */  294.  struct obj * 295. getobj(let,word) 296. register char *let,*word; 297. {  298.  	register struct obj *otmp; 299. 	register char ilet,ilet1,ilet2; 300. 	char buf[BUFSZ]; 301. 	char lets[BUFSZ]; 302. 	register int foo = 0, foo2; 303. 	register char *bp = buf; 304. 	xchar allowcnt = 0;	/* 0, 1 or 2 */ 305. 	boolean allowgold = FALSE; 306. 	boolean allowall = FALSE; 307. 	boolean allownone = FALSE; 308. 	xchar foox = 0; 309. 	long cnt; 310.  311.  	if(*let == '0') let++, allowcnt = 1; 312. 	if(*let == GOLD_SYM) let++, allowgold = TRUE; 313. 	if(*let == '#') let++, allowall = TRUE; 314. 	if(*let == '-') let++, allownone = TRUE; 315. 	if(allownone) *bp++ = '-'; 316. 	if(allowgold) *bp++ = GOLD_SYM; 317. 	if(bp > buf && bp[-1] == '-') *bp++ = ' '; 318.  319.  	ilet = 'a'; 320. 	for(otmp = invent; otmp; otmp = otmp->nobj){ 321. 	    if(!*let || index(let, otmp->olet)) { 322. 		bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet; 323.  324.  		/* ugly check: remove inappropriate things */ 325. 		if((!strcmp(word, "take off") && 326. 		    !(otmp->owornmask & (W_ARMOR - W_ARM2)))  327.  		|| (!strcmp(word, "wear") && 328. 		    (otmp->owornmask & (W_ARMOR | W_RING)))  329.  		|| (!strcmp(word, "wield") && 330. 		    (otmp->owornmask & W_WEP))  331.  #ifdef MARKER  332.  		|| (!strcmp(word, "write with") && 333. 		    (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER))  334.  #endif  335.  		    ) { 336. 			foo--; 337. 			foox++; 338. 		}  339.  	    }  340.  	    if(ilet == 'z') ilet = 'A'; else ilet++; 341. 	}  342.  	bp[foo] = 0; 343. 	if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0; 344. 	(void) strcpy(lets, bp);	/* necessary since we destroy buf */ 345. 	if(foo > 5) {			/* compactify string */ 346. 		foo = foo2 = 1; 347. 		ilet2 = bp[0]; 348. 		ilet1 = bp[1]; 349. 		while(ilet = bp[++foo2] = bp[++foo]){ 350. 			if(ilet == ilet1+1){ 351. 				if(ilet1 == ilet2+1) 352. 					bp[foo2 - 1] = ilet1 = '-'; 353. 				else if(ilet2 == '-') { 354. 					bp[--foo2] = ++ilet1; 355. 					continue; 356. 				}  357.  			}  358.  			ilet2 = ilet1; 359. 			ilet1 = ilet; 360. 		}  361.  	}  362.  	if(!foo && !allowall && !allowgold && !allownone) { 363. 		pline("You don't have anything %sto %s.",  364.  			foox ? "else " : "", word); 365. 		return(0); 366. 	}  367.  	for { 368. 		if(!buf[0]) { 369. #ifdef REDO 370. 		    if(!in_doagain) 371. #endif 372. 			pline("What do you want to %s [*]? ", word); 373. 		} else { 374. #ifdef REDO 375. 		    if(!in_doagain) 376. #endif 377. 			pline("What do you want to %s [%s or ?*]? ",  378.  				word, buf); 379. 		}  380.  		cnt = 0; 381. 		ilet = readchar; 382. 		while(digit(ilet) && allowcnt) { 383. #ifdef REDO 384. 			if (ilet != '?' && ilet != '*')	savech(ilet); 385. #endif 386. 			cnt = 10*cnt + (ilet - '0'); 387. 			allowcnt = 2;	/* signal presence of cnt */ 388. 			ilet = readchar; 389. 		}  390.  		if(digit(ilet)) { 391. 			pline("No count allowed with this command."); 392. 			continue; 393. 		}  394.  		if(index(quitchars,ilet)) { 395. 			pline("Never mind."); 396. 			return((struct obj *)0); 397. 		}  398.  		if(ilet == '-') { 399. 			return(allownone ? &zeroobj : (struct obj *) 0); 400. 		}  401.  		if(ilet == GOLD_SYM) { 402. 			if(!allowgold){ 403. 				pline("You cannot %s gold.", word); 404. 				continue; 405. 			}  406.  			if(!(allowcnt == 2 && cnt < u.ugold)) 407. 				cnt = u.ugold; 408. 			return(mkgoldobj(cnt)); 409. 		}  410.  		if(ilet == '?') { 411. 			doinv(lets); 412. 			if(!(ilet = morc)) continue; 413. 			/* he typed a letter (not a space) to more */ 414. 		} else if(ilet == '*') { 415. 			doinv((char *) 0); 416. 			if(!(ilet = morc)) continue; 417. 			/* ... */  418.  		}  419.  #ifdef REDO 420. 		if (ilet != '?' && ilet != '*')	savech(ilet); 421. #endif 422. 		if(flags.invlet_constant) { 423. 			for(otmp = invent; otmp; otmp = otmp->nobj) 424. 				if(otmp->invlet == ilet) break; 425. 		} else { 426. 			if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1; 427. 			ilet -= 'a'; 428. 			for(otmp = invent; otmp && ilet;  429.  					ilet--, otmp = otmp->nobj) ; 430. 		}  431.  		if(!otmp) { 432. 			pline("You don't have that object."); 433. 			continue; 434. 		}  435.  		if(cnt < 0 || otmp->quan < cnt) { 436. 			pline("You don't have that many! [You have %u]"  437.  		, otmp->quan); 438. 			continue; 439. 		}  440.  		break; 441. 	}  442.  	if(!allowall && let && !index(let,otmp->olet)) { 443. 		pline("That is a silly thing to %s.",word); 444. 		return(0); 445. 	}  446.  	if(allowcnt == 2) {	/* cnt given */ 447. 		if(cnt == 0) return(0); 448. 		if(cnt != otmp->quan) { 449. 			register struct obj *obj; 450. 			obj = splitobj(otmp, (int) cnt); 451. 			if(otmp == uwep) setuwep(obj); 452. 		}  453.  	}  454.  	return(otmp); 455. }  456.   457.  ckunpaid(otmp) register struct obj *otmp; { 458. 	return( otmp->unpaid ); 459. }  460.   461.  /* interactive version of getobj - used for Drop and Identify */ 462. /* return the number of times fn was called successfully */ 463. ggetobj(word, fn, max) 464. char *word; 465. int (*fn),  max; 466. {  467.  char buf[BUFSZ]; 468. register char *ip; 469. register char sym; 470. register int oletct = 0, iletct = 0; 471. register boolean allflag = FALSE; 472. char olets[20], ilets[20]; 473. int (*ckfn) = (int (*)) 0; 474. xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0;	/* BAH */ 475. 	if(!invent && !allowgold){ 476. 		pline("You have nothing to %s.", word); 477. 		return(0); 478. 	} else { 479. 		register struct obj *otmp = invent; 480. 		register int uflg = 0; 481.  482.  		if(allowgold) ilets[iletct++] = GOLD_SYM; 483. 		ilets[iletct] = 0; 484. 		while(otmp) { 485. 			if(!index(ilets, otmp->olet)){ 486. 				ilets[iletct++] = otmp->olet; 487. 				ilets[iletct] = 0; 488. 			}  489.  			if(otmp->unpaid) uflg = 1; 490. 			otmp = otmp->nobj; 491. 		}  492.  		ilets[iletct++] = ' '; 493. 		if(uflg) ilets[iletct++] = 'u'; 494. 		if(invent) ilets[iletct++] = 'a'; 495. 		ilets[iletct] = 0; 496. 	}  497.  	pline("What kinds of thing do you want to %s? [%s] ",  498.  		word, ilets); 499. 	getlin(buf); 500. 	if(buf[0] == '\033') { 501. 		clrlin; 502. 		return(0); 503. 	}  504.  	ip = buf; 505. 	olets[0] = 0; 506. 	while(sym = *ip++){ 507. 		if(sym == ' ') continue; 508. 		if(sym == GOLD_SYM) { 509. 			if(allowgold == 1) 510. 				(*fn)(mkgoldobj(u.ugold)); 511. 			else if(!u.ugold) 512. 				pline("You have no gold."); 513. 			allowgold = 2; 514. 		} else 515. 		if(sym == 'a' || sym == 'A') allflag = TRUE; else 516. 		if(sym == 'u' || sym == 'U') ckfn = ckunpaid; else 517. #ifdef SPELLS 518. 		if(index("!%?[=*/+\"0", sym)){  519.  #else  520.  		if(index("!%?[=*/\"0", sym)){ 521. #endif 522. 			if(!index(olets, sym)){ 523. 				olets[oletct++] = sym; 524. 				olets[oletct] = 0; 525. 			}  526.  		}  527.  		else pline("You don't have any %c's.", sym); 528. 	}  529.  	if(allowgold == 2 && !oletct) 530. 		return(1);	/* he dropped gold (or at least tried to) */ 531. 	else 532. 		return(askchain(invent, olets, allflag, fn, ckfn, max)); 533. }  534.   535.  /*  536.   * Walk through the chain starting at objchn and ask for all objects 537.  * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL) 538.  * whether the action in question (i.e., fn) has to be performed. 539.  * If allflag then no questions are asked. Max gives the max nr of 540. * objects to be treated. Return the number of objects treated. 541.  */  542.  askchain(objchn, olets, allflag, fn, ckfn, max) 543. struct obj *objchn; 544. register char *olets; 545. int allflag; 546. int (*fn), (*ckfn); 547. int max; 548. {  549.  register struct obj *otmp, *otmp2; 550. register char sym, ilet; 551. register int cnt = 0; 552. #ifdef SORTING 553. 	/* changes so the askchain is interrogated in the order specified. 554. 	 * For example, if a person specifies =/ then first all rings will be  555. * asked about followed by all wands -dgk 556. 	 */  557.  nextclass: 558. #endif 559. 	ilet = 'a'-1; 560. 	for(otmp = objchn; otmp; otmp = otmp2){ 561. 		if(ilet == 'z') ilet = 'A'; else ilet++; 562. 		otmp2 = otmp->nobj; 563. #ifdef SORTING 564. 		if (olets && *olets && otmp->olet != *olets) continue; 565. #else 566. 		if(olets && *olets && !index(olets, otmp->olet)) continue; 567. #endif 568. 		if(ckfn && !(*ckfn)(otmp)) continue; 569. 		if(!allflag) { 570. 			pline(xprname(otmp, ilet)); 571. 			addtopl(" [nyaq]? "); 572. 			sym = readchar; 573. 		}  574.  		else	sym = 'y'; 575.  576.  		switch(sym){ 577. 		case 'a': 578. 			allflag = 1; 579. 		case 'y': 580. 			cnt += (*fn)(otmp); 581. 			if(--max == 0) goto ret; 582. 		case 'n': 583. 		default: 584. 			break; 585. 		case 'q': 586. 			goto ret; 587. 		}  588.  	}  589.  #ifdef SORTING 590. 	if (olets && *olets && *++olets) 591. 		goto nextclass; 592. #endif 593. 	pline(cnt ? "That was all." : "No applicable objects."); 594. ret: 595. 	return(cnt); 596. }  597.   598.  obj_to_let(obj)	/* should of course only be called for things in invent */ 599. register struct obj *obj; 600. {  601.  	register struct obj *otmp; 602. 	register char ilet; 603.  604.  	if(flags.invlet_constant) 605. 		return(obj->invlet); 606. 	ilet = 'a'; 607. 	for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj) 608. 		if(++ilet > 'z') ilet = 'A'; 609. 	return(otmp ? ilet : NOINVSYM); 610. }  611.   612.  prinv(obj) 613. register struct obj *obj; 614. {  615.  	pline(xprname(obj, obj_to_let(obj))); 616. }  617.   618.  static char * 619. xprname(obj,let) 620. register struct obj *obj; 621. register char let; 622. {  623.  	static char li[BUFSZ]; 624.  625.  	(void) sprintf(li, "%c - %s.",  626.  		flags.invlet_constant ? obj->invlet : let,  627.  		doname(obj)); 628. 	return(li); 629. }  630.   631.  ddoinv 632. {  633.  	doinv((char *) 0); 634. 	return(0); 635. }  636.   637.  #ifdef SORTING 638. # ifdef SPELLS 639. char inv_order[] = "\")[%?+/=!(*0_`";	/* to be safe, include _ and ` */  640.  # else  641.  char inv_order[] = "\")[%?/=!(*0_`"; 642. # endif 643. extern char *let_to_name; 644. #endif 645.  646.  /* called with 0 or "": all objects in inventory */ 647. /* otherwise: all objects with (serial) letter in lets */ 648. doinv(lets) 649. register char *lets; 650. {  651.  	register struct obj *otmp; 652. 	register char ilet; 653. 	int ct = 0; 654. 	char any[BUFSZ]; 655. #ifdef SORTING 656. 	char *invlet = inv_order; 657. 	int classcount = 0; 658. #endif /* SORTING /**/ 659.  660.  	morc = 0;		/* just to be sure */ 661.  662.  	if(!invent){ 663. 		pline("Not carrying anything."); 664. 		return; 665. 	}  666.   667.  	cornline(0, (char *) 0); 668. #ifdef SORTING 669. nextclass: 670. 	classcount = 0; 671. 	ilet = 'a'; 672. 	for(otmp = invent; otmp; otmp = otmp->nobj) { 673. 		if(flags.invlet_constant) ilet = otmp->invlet; 674. 		if(!lets || !*lets || index(lets, ilet)) { 675. 			if (!flags.sortpack || otmp->olet == *invlet) { 676. 				if (flags.sortpack && !classcount) { 677. 					cornline(1, let_to_name(*invlet)); 678. 					classcount++; 679. 				}  680.  				cornline(1, xprname(otmp, ilet)); 681. 				any[ct++] = ilet; 682. 			}  683.  		}  684.  		if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 685. 	}  686.  	if (flags.sortpack && *++invlet) goto nextclass; 687. #else 688. 	ilet = 'a'; 689. 	for(otmp = invent; otmp; otmp = otmp->nobj) { 690. 	    if(flags.invlet_constant) ilet = otmp->invlet; 691. 	    if(!lets || !*lets || index(lets, ilet)) { 692. 		    cornline(1, xprname(otmp, ilet)); 693. 		    any[ct++] = ilet; 694. 	    }  695.  	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 696. 	}  697.  #endif /* SORTING /**/ 698. 	any[ct] = 0; 699. 	cornline(2, any); 700. }  701.   702.  dotypeinv 				/* free after Robert Viduya */ 703. /* Changed to one type only, so he doesnt have to type cr */ 704. {  705.      char c, ilet; 706.     char stuff[BUFSZ]; 707.     register int stct; 708.     register struct obj *otmp; 709.     boolean billx = inshop && doinvbill(0); 710.     boolean unpd = FALSE; 711.  712.  	if (!invent && !u.ugold && !billx) { 713. 	    pline ("You aren't carrying anything."); 714. 	    return(0); 715. 	}  716.   717.  	stct = 0; 718. 	if(u.ugold) stuff[stct++] = GOLD_SYM; 719. 	stuff[stct] = 0; 720. 	for(otmp = invent; otmp; otmp = otmp->nobj) { 721. 	    if (!index (stuff, otmp->olet)) { 722. 		stuff[stct++] = otmp->olet; 723. 		stuff[stct] = 0; 724. 	    }  725.  	    if(otmp->unpaid) 726. 		unpd = TRUE; 727. 	}  728.  	if(unpd) stuff[stct++] = 'u'; 729. 	if(billx) stuff[stct++] = 'x'; 730. 	stuff[stct] = 0; 731.  732.  	if(stct > 1) { 733. #ifdef REDO 734. 	  if (!in_doagain) 735. #endif 736. 	    pline ("What type of object [%s] do you want an inventory of? ",  737.  		stuff); 738. 	    c = readchar; 739. #ifdef REDO 740. 	    savech(c); 741. #endif 742. 	    if(index(quitchars,c)) { 743. 	    	    clrlin; 744. 	    	    return(0); 745. 	    }  746.  	} else 747. 	    c = stuff[0]; 748.  749.  	if(c == GOLD_SYM) 750. 	    return(doprgold); 751.  752.  	if(c == 'x' || c == 'X') { 753. 	    if(billx) 754. 		(void) doinvbill(1); 755. 	    else 756. 		pline("No used-up objects on the shopping bill."); 757. 	    return(0); 758. 	}  759.   760.  	if((c == 'u' || c == 'U') && !unpd) { 761. 		pline("You are not carrying any unpaid objects."); 762. 		return(0); 763. 	}  764.   765.  	stct = 0; 766. 	ilet = 'a'; 767. 	for (otmp = invent; otmp; otmp = otmp -> nobj) { 768. 	    if(flags.invlet_constant) ilet = otmp->invlet; 769. 	    if (c == otmp -> olet || (c == 'u' && otmp -> unpaid)) 770. 		stuff[stct++] = ilet; 771. 	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 772. 	}  773.  	stuff[stct] = '\0'; 774. 	if(stct == 0) 775. 		pline("You have no such objects."); 776. 	else 777. 		doinv (stuff); 778.  779.  	return(0); 780. }  781.   782.  /* look at what is here */ 783. dolook { 784.     register struct obj *otmp, *otmp0; 785.     register struct gold *gold; 786.     char *verb = Blind ? "feel" : "see"; 787.     int	ct = 0; 788.     int fd = 0; 789.  790.  #ifdef KAA 791.     read_engr_at(u.ux, u.uy); /* Eric Backus */ 792. #endif 793.     if(!u.uswallow) { 794. 	otmp0 = o_at(u.ux, u.uy); 795. 	gold = g_at(u.ux, u.uy); 796.     }  else  { 797. 	pline("You %s no objects here.", verb); 798. 	return(!!Blind); 799.     }  800.   801.      /* added by GAN 10/30/86 */ 802. #ifdef FOUNTAINS 803.     if(IS_FOUNTAIN(levl[u.ux][u.uy].typ))  { 804. 	fd++; 805. 	pline("There is a fountain here."); 806.     }  807.  #endif 808. #ifdef NEWCLASS 809.     if(IS_THRONE(levl[u.ux][u.uy].typ))  { 810. 	fd++; 811. 	pline("There is an opulent throne here."); 812.     }     813.  #endif 814.     if(u.ux == xupstair && u.uy == yupstair)  { 815. 	fd++; 816. 	pline("There is a stairway up here."); 817.     }  818.      if(u.ux == xdnstair && u.uy == ydnstair)  { 819. 	fd++; 820. 	pline("There is a stairway down here."); 821.     }  822.      if(Blind)  { 823. 	 pline("You try to feel what is lying here on the floor."); 824. 	 if(Levitation)  { 825. 		pline("But you can't reach it!"); 826. 		return(0); 827. 	 }  828.      }  829.    830.      if(!otmp0 && !gold) { 831. 	if(Blind || !fd) 832. 		pline("You %s no objects here.", verb); 833. 	return(!!Blind); 834.     }  835.   836.      cornline(0, "Things that are here:"); 837.     for(otmp = otmp0; otmp; otmp = otmp->nobj) { 838. 	if(otmp->ox == u.ux && otmp->oy == u.uy) { 839. 	    ct++; 840. 	    cornline(1, doname(otmp)); 841. 			  842.  	    if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) { 843. 		pline("Touching the dead cockatrice is a fatal mistake ..."); 844. 		pline("You die ..."); 845. 		killer = "dead cockatrice"; 846. 		done("died"); 847. 	    }  848.  	}  849.      }  850.   851.      if(gold) { 852. 	char gbuf[30]; 853.  854.  	(void) sprintf(gbuf, "%ld gold piece%s",  855.  		gold->amount, plur(gold->amount)); 856. 	if(!ct++) 857. 	    pline("You %s here %s.", verb, gbuf); 858. 	else 859. 	    cornline(1, gbuf); 860.     }  861.   862.      if(ct == 1 && !gold) { 863. 	pline("You %s here %s.", verb, doname(otmp0)); 864. 	cornline(3, (char *) 0); 865.     }  866.      if(ct > 1) 867. 	cornline(2, (char *) 0); 868.     return(!!Blind); 869. }  870.   871.  stackobj(obj) register struct obj *obj; { 872. register struct obj *otmp = fobj; 873. 	for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj) 874. 	if(otmp->ox == obj->ox && otmp->oy == obj->oy &&  875.  		merged(obj,otmp,1)) 876. 			return; 877. }  878.   879.  /* merge obj with otmp and delete obj if types agree */ 880. merged(otmp,obj,lose) register struct obj *otmp, *obj; { 881. 	if(obj->otyp == otmp->otyp &&  882.  	  obj->unpaid == otmp->unpaid &&  883.  	  obj->spe == otmp->spe &&  884.  	  obj->dknown == otmp->dknown &&  885.  	  obj->cursed == otmp->cursed &&  886.  #ifdef SPELLS  887.  	  (index("%*?!+", obj->olet) || 888. #else 889. 	  (index("%*?!", obj->olet) ||  890.  #endif  891.  	    (obj->known == otmp->known && 892. 		(obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)))) {  893.  		otmp->quan += obj->quan;  894.  		otmp->owt += obj->owt;  895.  		if(lose) freeobj(obj);  896.  		obfree(obj,otmp);	/* free(obj), bill->otmp */  897.  		return(1);  898.  	} else	return(0);  899.  }  900.   901.  /*  902.   * Gold is no longer displayed; in fact, when you have a lot of money,  903.   * it may take a while before you have counted it all.  904.   * [Bug: d$ and pickup still tell you how much it was.]  905.   */  906.  extern int (*occupation);  907.  extern char *occtxt;  908.  static long goldcounted;  909.   910.  countgold{  911.  	if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) {  912.  		long eps = 0;  913.  		if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1));  914.  		pline("You probably have about %ld gold pieces.", 915. 			u.ugold + eps);  916.  		return(0);	/* done */  917.  	}  918.  	return(1);		/* continue */  919.  }  920.   921.  doprgold{  922.  	if(!u.ugold)  923.  		pline("You do not carry any gold.");  924.  	else if(u.ugold <= 500)  925.  		pline("You are carrying %ld gold piece%s.", u.ugold, plur(u.ugold));  926.  	else {  927.  		pline("You sit down in order to count your gold pieces.");  928.  		goldcounted = 500;  929.  		occupation = countgold;  930.  		occtxt = "counting your gold";  931.  	}  932.  	return(1);  933.  }  934.   935.  /* --- end of gold counting section --- */  936.   937.  doprwep{  938.  	if(!uwep) pline("You are empty handed.");  939.  	else prinv(uwep);  940.  	return(0);  941.  }  942.   943.  doprarm{  944.  	if(!uarm && !uarmg && !uarms && !uarmh)  945.  		pline("You are not wearing any armor.");  946.  	else {  947.  		char lets[6];  948.  		register int ct = 0; 949.  950.  		if(uarm) lets[ct++] = obj_to_let(uarm); 951. 		if(uarm2) lets[ct++] = obj_to_let(uarm2); 952. 		if(uarmh) lets[ct++] = obj_to_let(uarmh); 953. 		if(uarms) lets[ct++] = obj_to_let(uarms); 954. 		if(uarmg) lets[ct++] = obj_to_let(uarmg); 955. 		lets[ct] = 0; 956. 		doinv(lets); 957. 	}  958.  	return(0); 959. }  960.   961.  doprring{ 962. 	if(!uleft && !uright) 963. 		pline("You are not wearing any rings."); 964. 	else { 965. 		char lets[3]; 966. 		register int ct = 0; 967.  968.  		if(uleft) lets[ct++] = obj_to_let(uleft); 969. 		if(uright) lets[ct++] = obj_to_let(uright); 970. 		lets[ct] = 0; 971. 		doinv(lets); 972. 	}  973.  	return(0); 974. }  975.   976.  digit(c) char c; { 977. 	return(c >= '0' && c <= '9'); 978. }  979.   980.  /*  981.   * useupf(obj) 982.  * uses up an object that's on the floor 983.  */  984.  useupf(obj) 985. register struct obj *obj; 986. {  987.  	if(obj->quan > 1)  { 988. 		obj->quan--; 989. 		obj->owt = weight(obj); 990. 	}  else delobj(obj); 991. }  992.   993.  #ifdef SORTING 994. /*  995.   * Convert from a symbol to a string for printing object classes 996.  *  997.   * Names from objects.h  998. * char obj_symbols[] = { 999.  *	ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM, 1000. *	BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM, 1001. *	WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 }; 1002. */  1003. #define Sprintf (void) sprintf 1004. 1005. extern char obj_symbols[]; 1006. static char *names[] = {"Illegal objects", "Amulets", "Comestibles", "Weapons", 1007. 			"Tools", "Iron balls", "Chains", "Rocks", "Armor", 1008. 			"Potions", "Scrolls", "Wands", 1009. #ifdef SPELLS 1010. 			"Spellbooks", 1011. #endif 1012. 			"Rings", "Gems"}; 1013. char * 1014. let_to_name(let) 1015. char let; 1016. { 1017. 	char *pos = index(obj_symbols, let); 1018. 	extern char *HI, *HE; 1019. 	/* arbitrary buffer size by Tom May (tom@uw-warp) */ 1020. 	static char *buf = NULL; 1021. 1022. 	if (buf == NULL) 1023. 	   buf = (char *) alloc (strlen(HI) + strlen(HE) + 15 + 1); 1024. 1025. 	if (pos == NULL) pos = obj_symbols; 1026. 	if (HI && HE) 1027. 	   Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE); 1028. 	else 1029. 	   Sprintf(buf, "%s", names[pos - obj_symbols]); 1030. 	return (buf); 1031. } 1032. #endif /* SORTING /**/ 1033. 1034. reassign 1035. { 1036. 	register int i;  1037. register struct obj *obj; 1038. 1039. 	for(obj = invent, i = 0; obj; obj = obj->nobj, i++) 1040. 		obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26); 1041. 	lastinvnr = i; 1042. }