Source:NetHack 1.3d/invent.c

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