Home | History | Annotate | Line # | Download | only in rogue
inventory.c revision 1.10.10.1
      1  1.10.10.1      matt /*	$NetBSD: inventory.c,v 1.10.10.1 2008/01/09 01:30:56 matt Exp $	*/
      2        1.3       cgd 
      3        1.1       cgd /*
      4        1.3       cgd  * Copyright (c) 1988, 1993
      5        1.3       cgd  *	The Regents of the University of California.  All rights reserved.
      6        1.1       cgd  *
      7        1.1       cgd  * This code is derived from software contributed to Berkeley by
      8        1.1       cgd  * Timothy C. Stoehr.
      9        1.1       cgd  *
     10        1.1       cgd  * Redistribution and use in source and binary forms, with or without
     11        1.1       cgd  * modification, are permitted provided that the following conditions
     12        1.1       cgd  * are met:
     13        1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     14        1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     15        1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16        1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     17        1.1       cgd  *    documentation and/or other materials provided with the distribution.
     18        1.9       agc  * 3. Neither the name of the University nor the names of its contributors
     19        1.1       cgd  *    may be used to endorse or promote products derived from this software
     20        1.1       cgd  *    without specific prior written permission.
     21        1.1       cgd  *
     22        1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23        1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24        1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25        1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26        1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27        1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28        1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29        1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30        1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31        1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32        1.1       cgd  * SUCH DAMAGE.
     33        1.1       cgd  */
     34        1.1       cgd 
     35        1.5     lukem #include <sys/cdefs.h>
     36        1.1       cgd #ifndef lint
     37        1.3       cgd #if 0
     38        1.3       cgd static char sccsid[] = "@(#)inventory.c	8.1 (Berkeley) 5/31/93";
     39        1.3       cgd #else
     40  1.10.10.1      matt __RCSID("$NetBSD: inventory.c,v 1.10.10.1 2008/01/09 01:30:56 matt Exp $");
     41        1.3       cgd #endif
     42        1.1       cgd #endif /* not lint */
     43        1.1       cgd 
     44        1.1       cgd /*
     45        1.1       cgd  * inventory.c
     46        1.1       cgd  *
     47        1.1       cgd  * This source herein may be modified and/or distributed by anybody who
     48        1.1       cgd  * so desires, with the following restrictions:
     49        1.1       cgd  *    1.)  No portion of this notice shall be removed.
     50        1.1       cgd  *    2.)  Credit shall not be taken for the creation of this source.
     51        1.1       cgd  *    3.)  This code is not to be traded, sold, or used for personal
     52        1.1       cgd  *         gain or profit.
     53        1.1       cgd  *
     54        1.1       cgd  */
     55        1.1       cgd 
     56  1.10.10.1      matt #include <stdarg.h>
     57        1.1       cgd #include "rogue.h"
     58        1.1       cgd 
     59        1.1       cgd boolean is_wood[WANDS];
     60        1.6   hubertf const char *press_space = " --press space to continue--";
     61        1.1       cgd 
     62        1.6   hubertf const char *const wand_materials[WAND_MATERIALS] = {
     63        1.1       cgd 	"steel ",
     64        1.1       cgd 	"bronze ",
     65        1.1       cgd 	"gold ",
     66        1.1       cgd 	"silver ",
     67        1.1       cgd 	"copper ",
     68        1.1       cgd 	"nickel ",
     69        1.1       cgd 	"cobalt ",
     70        1.1       cgd 	"tin ",
     71        1.1       cgd 	"iron ",
     72        1.1       cgd 	"magnesium ",
     73        1.1       cgd 	"chrome ",
     74        1.1       cgd 	"carbon ",
     75        1.1       cgd 	"platinum ",
     76        1.1       cgd 	"silicon ",
     77        1.1       cgd 	"titanium ",
     78        1.1       cgd 
     79        1.1       cgd 	"teak ",
     80        1.1       cgd 	"oak ",
     81        1.1       cgd 	"cherry ",
     82        1.1       cgd 	"birch ",
     83        1.1       cgd 	"pine ",
     84        1.1       cgd 	"cedar ",
     85        1.1       cgd 	"redwood ",
     86        1.1       cgd 	"balsa ",
     87        1.1       cgd 	"ivory ",
     88        1.1       cgd 	"walnut ",
     89        1.1       cgd 	"maple ",
     90        1.1       cgd 	"mahogany ",
     91        1.1       cgd 	"elm ",
     92        1.1       cgd 	"palm ",
     93        1.1       cgd 	"wooden "
     94        1.1       cgd };
     95        1.1       cgd 
     96        1.6   hubertf const char *const gems[GEMS] = {
     97        1.1       cgd 	"diamond ",
     98        1.1       cgd 	"stibotantalite ",
     99        1.1       cgd 	"lapi-lazuli ",
    100        1.1       cgd 	"ruby ",
    101        1.1       cgd 	"emerald ",
    102        1.1       cgd 	"sapphire ",
    103        1.1       cgd 	"amethyst ",
    104        1.1       cgd 	"quartz ",
    105        1.1       cgd 	"tiger-eye ",
    106        1.1       cgd 	"opal ",
    107        1.1       cgd 	"agate ",
    108        1.1       cgd 	"turquoise ",
    109        1.1       cgd 	"pearl ",
    110        1.1       cgd 	"garnet "
    111        1.1       cgd };
    112        1.1       cgd 
    113        1.6   hubertf const char *const syllables[MAXSYLLABLES] = {
    114        1.1       cgd 	"blech ",
    115        1.1       cgd 	"foo ",
    116        1.1       cgd 	"barf ",
    117        1.1       cgd 	"rech ",
    118        1.1       cgd 	"bar ",
    119        1.1       cgd 	"blech ",
    120        1.1       cgd 	"quo ",
    121        1.1       cgd 	"bloto ",
    122        1.1       cgd 	"oh ",
    123        1.1       cgd 	"caca ",
    124        1.1       cgd 	"blorp ",
    125        1.1       cgd 	"erp ",
    126        1.1       cgd 	"festr ",
    127        1.1       cgd 	"rot ",
    128        1.1       cgd 	"slie ",
    129        1.1       cgd 	"snorf ",
    130        1.1       cgd 	"iky ",
    131        1.1       cgd 	"yuky ",
    132        1.1       cgd 	"ooze ",
    133        1.1       cgd 	"ah ",
    134        1.1       cgd 	"bahl ",
    135        1.1       cgd 	"zep ",
    136        1.1       cgd 	"druhl ",
    137        1.1       cgd 	"flem ",
    138        1.1       cgd 	"behil ",
    139        1.1       cgd 	"arek ",
    140        1.1       cgd 	"mep ",
    141        1.1       cgd 	"zihr ",
    142        1.1       cgd 	"grit ",
    143        1.1       cgd 	"kona ",
    144        1.1       cgd 	"kini ",
    145        1.1       cgd 	"ichi ",
    146        1.1       cgd 	"tims ",
    147        1.1       cgd 	"ogr ",
    148        1.1       cgd 	"oo ",
    149        1.1       cgd 	"ighr ",
    150        1.1       cgd 	"coph ",
    151        1.1       cgd 	"swerr ",
    152        1.1       cgd 	"mihln ",
    153        1.1       cgd 	"poxi "
    154        1.1       cgd };
    155        1.1       cgd 
    156        1.1       cgd #define COMS 48
    157        1.1       cgd 
    158        1.1       cgd struct id_com_s {
    159        1.1       cgd 	short com_char;
    160        1.6   hubertf 	const char *com_desc;
    161        1.1       cgd };
    162        1.1       cgd 
    163        1.6   hubertf const struct id_com_s com_id_tab[COMS] = {
    164        1.5     lukem 	{'?',	"?       prints help"},
    165        1.5     lukem 	{'r',	"r       read scroll"},
    166        1.5     lukem 	{'/',	"/       identify object"},
    167        1.5     lukem 	{'e',	"e       eat food"},
    168        1.5     lukem 	{'h',	"h       left "},
    169        1.5     lukem 	{'w',	"w       wield a weapon"},
    170        1.5     lukem 	{'j',	"j       down"},
    171        1.5     lukem 	{'W',	"W       wear armor"},
    172        1.5     lukem 	{'k',	"k       up"},
    173        1.5     lukem 	{'T',	"T       take armor off"},
    174        1.5     lukem 	{'l',	"l       right"},
    175        1.5     lukem 	{'P',	"P       put on ring"},
    176        1.5     lukem 	{'y',	"y       up & left"},
    177        1.5     lukem 	{'R',	"R       remove ring"},
    178        1.5     lukem 	{'u',	"u       up & right"},
    179        1.5     lukem 	{'d',	"d       drop object"},
    180        1.5     lukem 	{'b',	"b       down & left"},
    181        1.5     lukem 	{'c',	"c       call object"},
    182        1.5     lukem 	{'n',	"n       down & right"},
    183        1.5     lukem 	{'\0',	"<SHIFT><dir>: run that way"},
    184        1.5     lukem 	{')',	")       print current weapon"},
    185        1.5     lukem 	{'\0',	"<CTRL><dir>: run till adjacent"},
    186        1.5     lukem 	{']',	"]       print current armor"},
    187        1.5     lukem 	{'f',	"f<dir>  fight till death or near death"},
    188        1.5     lukem 	{'=',	"=       print current rings"},
    189        1.5     lukem 	{'t',	"t<dir>  throw something"},
    190        1.5     lukem 	{'\001',	"^A      print Hp-raise average"},
    191        1.5     lukem 	{'m',	"m<dir>  move onto without picking up"},
    192        1.5     lukem 	{'z',	"z<dir>  zap a wand in a direction"},
    193        1.5     lukem 	{'o',	"o       examine/set options"},
    194        1.5     lukem 	{'^',	"^<dir>  identify trap type"},
    195        1.5     lukem 	{'\022',	"^R      redraw screen"},
    196        1.5     lukem 	{'&',	"&       save screen into 'rogue.screen'"},
    197        1.5     lukem 	{'s',	"s       search for trap/secret door"},
    198        1.5     lukem 	{'\020',	"^P      repeat last message"},
    199        1.5     lukem 	{'>',	">       go down a staircase"},
    200        1.5     lukem 	{'\033',	"^[      cancel command"},
    201        1.5     lukem 	{'<',	"<       go up a staircase"},
    202        1.5     lukem 	{'S',	"S       save game"},
    203        1.5     lukem 	{'.',	".       rest for a turn"},
    204        1.5     lukem 	{'Q',	"Q       quit"},
    205        1.5     lukem 	{',',	",       pick something up"},
    206        1.5     lukem 	{'!',	"!       shell escape"},
    207        1.5     lukem 	{'i',	"i       inventory"},
    208        1.5     lukem 	{'F',	"F<dir>  fight till either of you dies"},
    209        1.5     lukem 	{'I',	"I       inventory single item"},
    210        1.5     lukem 	{'v',	"v       print version number"},
    211        1.5     lukem 	{'q',	"q       quaff potion" }
    212        1.1       cgd };
    213        1.1       cgd 
    214        1.5     lukem void
    215        1.1       cgd inventory(pack, mask)
    216        1.6   hubertf 	const object *pack;
    217        1.5     lukem 	unsigned short mask;
    218        1.1       cgd {
    219        1.1       cgd 	object *obj;
    220  1.10.10.1      matt 	short i = 0, j;
    221  1.10.10.1      matt 	size_t maxlen = 0, n;
    222        1.1       cgd 	short row, col;
    223        1.1       cgd 
    224  1.10.10.1      matt 	struct {
    225  1.10.10.1      matt 		short letter;
    226  1.10.10.1      matt 		short sepchar;
    227  1.10.10.1      matt 		char desc[DCOLS];
    228  1.10.10.1      matt 		char savebuf[DCOLS+8];
    229  1.10.10.1      matt 	} descs[MAX_PACK_COUNT+1];
    230  1.10.10.1      matt 
    231  1.10.10.1      matt 
    232        1.1       cgd 	obj = pack->next_object;
    233        1.1       cgd 
    234        1.1       cgd 	if (!obj) {
    235  1.10.10.1      matt 		messagef(0, "your pack is empty");
    236        1.1       cgd 		return;
    237        1.1       cgd 	}
    238        1.1       cgd 	while (obj) {
    239        1.1       cgd 		if (obj->what_is & mask) {
    240  1.10.10.1      matt 			descs[i].letter = obj->ichar;
    241  1.10.10.1      matt 			descs[i].sepchar = ((obj->what_is & ARMOR) && obj->is_protected)
    242        1.1       cgd 				? '}' : ')';
    243  1.10.10.1      matt 			get_desc(obj, descs[i].desc, sizeof(descs[i].desc));
    244  1.10.10.1      matt 			n = strlen(descs[i].desc) + 4;
    245  1.10.10.1      matt 			if (n > maxlen) {
    246        1.1       cgd 				maxlen = n;
    247        1.1       cgd 			}
    248  1.10.10.1      matt 			i++;
    249  1.10.10.1      matt 			/*assert(i<=MAX_PACK_COUNT);*/
    250        1.1       cgd 		}
    251        1.1       cgd 		obj = obj->next_object;
    252        1.1       cgd 	}
    253        1.1       cgd 	if (maxlen < 27) maxlen = 27;
    254  1.10.10.1      matt 	if (maxlen > DCOLS-2) maxlen = DCOLS-2;
    255        1.1       cgd 	col = DCOLS - (maxlen + 2);
    256        1.1       cgd 
    257  1.10.10.1      matt 	for (row = 0; ((row <= i) && (row < DROWS)); row++) {
    258  1.10.10.1      matt 		for (j = col; j < DCOLS; j++) {
    259  1.10.10.1      matt 			descs[row].savebuf[j-col] = mvinch(row, j);
    260  1.10.10.1      matt 		}
    261  1.10.10.1      matt 		descs[row].savebuf[j-col] = 0;
    262  1.10.10.1      matt 		if (row < i) {
    263  1.10.10.1      matt 			mvprintw(row, col, " %c%c %s",
    264  1.10.10.1      matt 				descs[row].letter, descs[row].sepchar,
    265  1.10.10.1      matt 				descs[row].desc);
    266  1.10.10.1      matt 		}
    267  1.10.10.1      matt 		else {
    268  1.10.10.1      matt 			mvaddstr(row, col, press_space);
    269        1.1       cgd 		}
    270        1.1       cgd 		clrtoeol();
    271        1.1       cgd 	}
    272        1.1       cgd 	refresh();
    273        1.1       cgd 	wait_for_ack();
    274        1.1       cgd 
    275        1.1       cgd 	move(0, 0);
    276        1.1       cgd 	clrtoeol();
    277        1.1       cgd 
    278  1.10.10.1      matt 	for (j = 1; ((j <= i) && (j < DROWS)); j++) {
    279  1.10.10.1      matt 		mvaddstr(j, col, descs[j].savebuf);
    280        1.1       cgd 	}
    281        1.1       cgd }
    282        1.1       cgd 
    283        1.5     lukem void
    284        1.1       cgd id_com()
    285        1.1       cgd {
    286        1.1       cgd 	int ch = 0;
    287        1.1       cgd 	short i, j, k;
    288        1.1       cgd 
    289        1.1       cgd 	while (ch != CANCEL) {
    290        1.1       cgd 		check_message();
    291  1.10.10.1      matt 		messagef(0, "Character you want help for (* for all):");
    292        1.1       cgd 
    293        1.1       cgd 		refresh();
    294        1.1       cgd 		ch = getchar();
    295        1.1       cgd 
    296        1.1       cgd 		switch(ch) {
    297        1.1       cgd 		case LIST:
    298        1.1       cgd 			{
    299        1.1       cgd 				char save[(((COMS / 2) + (COMS % 2)) + 1)][DCOLS];
    300        1.1       cgd 				short rows = (((COMS / 2) + (COMS % 2)) + 1);
    301        1.5     lukem 				boolean need_two_screens = FALSE;
    302        1.1       cgd 
    303        1.1       cgd 				if (rows > LINES) {
    304        1.1       cgd 					need_two_screens = 1;
    305        1.1       cgd 					rows = LINES;
    306        1.1       cgd 				}
    307        1.1       cgd 				k = 0;
    308        1.1       cgd 
    309        1.1       cgd 				for (i = 0; i < rows; i++) {
    310        1.1       cgd 					for (j = 0; j < DCOLS; j++) {
    311        1.1       cgd 						save[i][j] = mvinch(i, j);
    312        1.1       cgd 					}
    313        1.1       cgd 				}
    314        1.1       cgd MORE:
    315        1.1       cgd 				for (i = 0; i < rows; i++) {
    316        1.1       cgd 					move(i, 0);
    317        1.1       cgd 					clrtoeol();
    318        1.1       cgd 				}
    319        1.1       cgd 				for (i = 0; i < (rows-1); i++) {
    320        1.1       cgd 					if (i < (LINES-1)) {
    321        1.1       cgd 						if (((i + i) < COMS) && ((i+i+k) < COMS)) {
    322        1.1       cgd 							mvaddstr(i, 0, com_id_tab[i+i+k].com_desc);
    323        1.1       cgd 						}
    324        1.1       cgd 						if (((i + i + 1) < COMS) && ((i+i+k+1) < COMS)) {
    325        1.1       cgd 							mvaddstr(i, (DCOLS/2),
    326        1.1       cgd 										com_id_tab[i+i+k+1].com_desc);
    327        1.1       cgd 						}
    328        1.1       cgd 					}
    329        1.1       cgd 				}
    330        1.1       cgd 				mvaddstr(rows - 1, 0, need_two_screens ? more : press_space);
    331        1.1       cgd 				refresh();
    332        1.1       cgd 				wait_for_ack();
    333        1.1       cgd 
    334        1.1       cgd 				if (need_two_screens) {
    335        1.1       cgd 					k += ((rows-1) * 2);
    336        1.1       cgd 					need_two_screens = 0;
    337        1.1       cgd 					goto MORE;
    338        1.1       cgd 				}
    339        1.1       cgd 				for (i = 0; i < rows; i++) {
    340        1.1       cgd 					move(i, 0);
    341        1.1       cgd 					for (j = 0; j < DCOLS; j++) {
    342        1.1       cgd 						addch(save[i][j]);
    343        1.1       cgd 					}
    344        1.1       cgd 				}
    345        1.1       cgd 			}
    346        1.1       cgd 			break;
    347        1.1       cgd 		default:
    348        1.1       cgd 			if (!pr_com_id(ch)) {
    349        1.1       cgd 				if (!pr_motion_char(ch)) {
    350        1.1       cgd 					check_message();
    351  1.10.10.1      matt 					messagef(0, "unknown character");
    352        1.1       cgd 				}
    353        1.1       cgd 			}
    354        1.1       cgd 			ch = CANCEL;
    355        1.1       cgd 			break;
    356        1.1       cgd 		}
    357        1.1       cgd 	}
    358        1.1       cgd }
    359        1.1       cgd 
    360        1.5     lukem int
    361        1.1       cgd pr_com_id(ch)
    362        1.5     lukem 	int ch;
    363        1.1       cgd {
    364        1.1       cgd 	int i;
    365        1.1       cgd 
    366        1.1       cgd 	if (!get_com_id(&i, ch)) {
    367        1.1       cgd 		return(0);
    368        1.1       cgd 	}
    369        1.1       cgd 	check_message();
    370  1.10.10.1      matt 	messagef(0, "%s", com_id_tab[i].com_desc);
    371        1.1       cgd 	return(1);
    372        1.1       cgd }
    373        1.1       cgd 
    374        1.5     lukem int
    375        1.7      tron get_com_id(indexp, ch)
    376        1.7      tron 	int *indexp;
    377        1.5     lukem 	short ch;
    378        1.1       cgd {
    379        1.1       cgd 	short i;
    380        1.1       cgd 
    381        1.1       cgd 	for (i = 0; i < COMS; i++) {
    382        1.1       cgd 		if (com_id_tab[i].com_char == ch) {
    383        1.7      tron 			*indexp = i;
    384        1.1       cgd 			return(1);
    385        1.1       cgd 		}
    386        1.1       cgd 	}
    387        1.1       cgd 	return(0);
    388        1.1       cgd }
    389        1.1       cgd 
    390        1.5     lukem int
    391        1.1       cgd pr_motion_char(ch)
    392        1.5     lukem 	int ch;
    393        1.1       cgd {
    394        1.1       cgd 	if (	(ch == 'J') ||
    395        1.1       cgd 			(ch == 'K') ||
    396        1.1       cgd 			(ch == 'L') ||
    397        1.1       cgd 			(ch == 'H') ||
    398        1.1       cgd 			(ch == 'Y') ||
    399        1.1       cgd 			(ch == 'U') ||
    400        1.1       cgd 			(ch == 'N') ||
    401        1.1       cgd 			(ch == 'B') ||
    402        1.1       cgd 			(ch == '\012') ||
    403        1.1       cgd 			(ch == '\013') ||
    404        1.1       cgd 			(ch == '\010') ||
    405        1.1       cgd 			(ch == '\014') ||
    406        1.1       cgd 			(ch == '\025') ||
    407        1.1       cgd 			(ch == '\031') ||
    408        1.1       cgd 			(ch == '\016') ||
    409        1.1       cgd 			(ch == '\002')) {
    410  1.10.10.1      matt 		const char *until;
    411       1.10  christos 		int n = 0;	/* XXX: GCC */
    412        1.1       cgd 		if (ch <= '\031') {
    413        1.1       cgd 			ch += 96;
    414  1.10.10.1      matt 			until = " until adjacent";
    415        1.1       cgd 		} else {
    416        1.1       cgd 			ch += 32;
    417  1.10.10.1      matt 			until = "";
    418        1.1       cgd 		}
    419        1.1       cgd 		(void) get_com_id(&n, ch);
    420        1.1       cgd 		check_message();
    421  1.10.10.1      matt 		messagef(0, "run %s%s", com_id_tab[n].com_desc + 8, until);
    422        1.1       cgd 		return(1);
    423        1.1       cgd 	} else {
    424        1.1       cgd 		return(0);
    425        1.1       cgd 	}
    426        1.1       cgd }
    427        1.1       cgd 
    428        1.5     lukem void
    429        1.1       cgd mix_colors()
    430        1.1       cgd {
    431        1.1       cgd 	short i, j, k;
    432        1.8       mrg 	char t[MAX_ID_TITLE_LEN];
    433        1.1       cgd 
    434        1.1       cgd 	for (i = 0; i <= 32; i++) {
    435        1.1       cgd 		j = get_rand(0, (POTIONS - 1));
    436        1.1       cgd 		k = get_rand(0, (POTIONS - 1));
    437  1.10.10.1      matt 		strlcpy(t, id_potions[j].title, sizeof(t));
    438  1.10.10.1      matt 		strlcpy(id_potions[j].title, id_potions[k].title,
    439  1.10.10.1      matt 			sizeof(id_potions[j].title));
    440  1.10.10.1      matt 		strlcpy(id_potions[k].title, t, sizeof(id_potions[k].title));
    441        1.1       cgd 	}
    442        1.1       cgd }
    443        1.1       cgd 
    444        1.5     lukem void
    445        1.1       cgd make_scroll_titles()
    446        1.1       cgd {
    447        1.1       cgd 	short i, j, n;
    448        1.1       cgd 	short sylls, s;
    449  1.10.10.1      matt 	size_t maxlen = sizeof(id_scrolls[0].title);
    450        1.1       cgd 
    451        1.1       cgd 	for (i = 0; i < SCROLS; i++) {
    452        1.1       cgd 		sylls = get_rand(2, 5);
    453  1.10.10.1      matt 		(void) strlcpy(id_scrolls[i].title, "'", maxlen);
    454        1.1       cgd 
    455        1.1       cgd 		for (j = 0; j < sylls; j++) {
    456        1.1       cgd 			s = get_rand(1, (MAXSYLLABLES-1));
    457  1.10.10.1      matt 			(void) strlcat(id_scrolls[i].title, syllables[s],
    458  1.10.10.1      matt 					maxlen);
    459        1.1       cgd 		}
    460  1.10.10.1      matt 		/* trim trailing space */
    461        1.1       cgd 		n = strlen(id_scrolls[i].title);
    462  1.10.10.1      matt 		id_scrolls[i].title[n-1] = 0;
    463  1.10.10.1      matt 
    464  1.10.10.1      matt 		(void) strlcat(id_scrolls[i].title, "' ", maxlen);
    465  1.10.10.1      matt 	}
    466  1.10.10.1      matt }
    467  1.10.10.1      matt 
    468  1.10.10.1      matt struct sbuf {
    469  1.10.10.1      matt 	char *buf;
    470  1.10.10.1      matt 	size_t maxlen;
    471  1.10.10.1      matt };
    472  1.10.10.1      matt 
    473  1.10.10.1      matt static void sbuf_init __P((struct sbuf *s, char *buf, size_t maxlen));
    474  1.10.10.1      matt static void sbuf_addstr __P((struct sbuf *s, const char *str));
    475  1.10.10.1      matt static void sbuf_addf __P((struct sbuf *s, const char *fmt, ...));
    476  1.10.10.1      matt static void desc_count __P((struct sbuf *s, int n));
    477  1.10.10.1      matt static void desc_called __P((struct sbuf *s, const object *));
    478  1.10.10.1      matt 
    479  1.10.10.1      matt static
    480  1.10.10.1      matt void
    481  1.10.10.1      matt sbuf_init(s, buf, maxlen)
    482  1.10.10.1      matt 	struct sbuf *s;
    483  1.10.10.1      matt 	char *buf;
    484  1.10.10.1      matt 	size_t maxlen;
    485  1.10.10.1      matt {
    486  1.10.10.1      matt 	s->buf = buf;
    487  1.10.10.1      matt 	s->maxlen = maxlen;
    488  1.10.10.1      matt 	/*assert(maxlen>0);*/
    489  1.10.10.1      matt 	s->buf[0] = 0;
    490  1.10.10.1      matt }
    491  1.10.10.1      matt 
    492  1.10.10.1      matt static
    493  1.10.10.1      matt void
    494  1.10.10.1      matt sbuf_addstr(s, str)
    495  1.10.10.1      matt 	struct sbuf *s;
    496  1.10.10.1      matt 	const char *str;
    497  1.10.10.1      matt {
    498  1.10.10.1      matt 	strlcat(s->buf, str, s->maxlen);
    499  1.10.10.1      matt }
    500  1.10.10.1      matt 
    501  1.10.10.1      matt static void sbuf_addf(struct sbuf *s, const char *fmt, ...)
    502  1.10.10.1      matt 	__attribute__((__format__(__printf__, 2, 3)));
    503  1.10.10.1      matt 
    504  1.10.10.1      matt static
    505  1.10.10.1      matt void
    506  1.10.10.1      matt sbuf_addf(struct sbuf *s, const char *fmt, ...)
    507  1.10.10.1      matt {
    508  1.10.10.1      matt 	va_list ap;
    509  1.10.10.1      matt 	size_t initlen;
    510  1.10.10.1      matt 
    511  1.10.10.1      matt 	initlen = strlen(s->buf);
    512  1.10.10.1      matt 	va_start(ap, fmt);
    513  1.10.10.1      matt 	vsnprintf(s->buf+initlen, s->maxlen-initlen, fmt, ap);
    514  1.10.10.1      matt 	va_end(ap);
    515  1.10.10.1      matt }
    516  1.10.10.1      matt 
    517  1.10.10.1      matt static
    518  1.10.10.1      matt void
    519  1.10.10.1      matt desc_count(s, n)
    520  1.10.10.1      matt 	struct sbuf *s;
    521  1.10.10.1      matt 	int n;
    522  1.10.10.1      matt {
    523  1.10.10.1      matt 	if (n == 1) {
    524  1.10.10.1      matt 		sbuf_addstr(s, "an ");
    525  1.10.10.1      matt 	} else {
    526  1.10.10.1      matt 		sbuf_addf(s, "%d ", n);
    527        1.1       cgd 	}
    528        1.1       cgd }
    529        1.1       cgd 
    530  1.10.10.1      matt static
    531        1.5     lukem void
    532  1.10.10.1      matt desc_called(s, obj)
    533  1.10.10.1      matt 	struct sbuf *s;
    534  1.10.10.1      matt 	const object *obj;
    535  1.10.10.1      matt {
    536  1.10.10.1      matt 	struct id *id_table;
    537  1.10.10.1      matt 
    538  1.10.10.1      matt 	id_table = get_id_table(obj);
    539  1.10.10.1      matt 	sbuf_addstr(s, name_of(obj));
    540  1.10.10.1      matt 	sbuf_addstr(s, "called ");
    541  1.10.10.1      matt 	sbuf_addstr(s, id_table[obj->which_kind].title);
    542  1.10.10.1      matt }
    543  1.10.10.1      matt 
    544  1.10.10.1      matt void
    545  1.10.10.1      matt get_desc(obj, desc, desclen)
    546        1.6   hubertf 	const object *obj;
    547        1.5     lukem 	char *desc;
    548  1.10.10.1      matt 	size_t desclen;
    549        1.1       cgd {
    550        1.6   hubertf 	const char *item_name;
    551        1.1       cgd 	struct id *id_table;
    552  1.10.10.1      matt 	struct sbuf db;
    553  1.10.10.1      matt 	unsigned short objtype_id_status;
    554        1.1       cgd 
    555        1.1       cgd 	if (obj->what_is == AMULET) {
    556  1.10.10.1      matt 		(void) strlcpy(desc, "the amulet of Yendor ", desclen);
    557        1.1       cgd 		return;
    558        1.1       cgd 	}
    559        1.1       cgd 
    560        1.1       cgd 	if (obj->what_is == GOLD) {
    561  1.10.10.1      matt 		snprintf(desc, desclen, "%d pieces of gold", obj->quantity);
    562        1.1       cgd 		return;
    563        1.1       cgd 	}
    564        1.1       cgd 
    565  1.10.10.1      matt 	item_name = name_of(obj);
    566  1.10.10.1      matt 	id_table = get_id_table(obj);
    567  1.10.10.1      matt 	if (wizard || id_table == NULL) {
    568  1.10.10.1      matt 		objtype_id_status = IDENTIFIED;
    569  1.10.10.1      matt 	}
    570  1.10.10.1      matt 	else {
    571  1.10.10.1      matt 		objtype_id_status = id_table[obj->which_kind].id_status;
    572  1.10.10.1      matt 	}
    573  1.10.10.1      matt 	if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) {
    574  1.10.10.1      matt 		if (obj->identified) {
    575  1.10.10.1      matt 			objtype_id_status = IDENTIFIED;
    576        1.1       cgd 		}
    577        1.1       cgd 	}
    578  1.10.10.1      matt 
    579  1.10.10.1      matt 	sbuf_init(&db, desc, desclen);
    580  1.10.10.1      matt 
    581  1.10.10.1      matt 	switch (obj->what_is) {
    582  1.10.10.1      matt 	case FOOD:
    583        1.1       cgd 		if (obj->which_kind == RATION) {
    584        1.1       cgd 			if (obj->quantity > 1) {
    585  1.10.10.1      matt 				sbuf_addf(&db,
    586  1.10.10.1      matt 					 "%d rations of %s", obj->quantity,
    587  1.10.10.1      matt 					 item_name);
    588        1.1       cgd 			} else {
    589  1.10.10.1      matt 				sbuf_addf(&db, "some %s", item_name);
    590        1.1       cgd 			}
    591        1.1       cgd 		} else {
    592  1.10.10.1      matt 			sbuf_addf(&db, "an %s", item_name);
    593        1.1       cgd 		}
    594  1.10.10.1      matt 		break;
    595  1.10.10.1      matt 	case SCROL:
    596  1.10.10.1      matt 		desc_count(&db, obj->quantity);
    597  1.10.10.1      matt 		if (objtype_id_status==UNIDENTIFIED) {
    598  1.10.10.1      matt 			sbuf_addstr(&db, item_name);
    599  1.10.10.1      matt 			sbuf_addstr(&db, "entitled: ");
    600  1.10.10.1      matt 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    601  1.10.10.1      matt 		} else if (objtype_id_status==CALLED) {
    602  1.10.10.1      matt 			desc_called(&db, obj);
    603  1.10.10.1      matt 		} else {
    604  1.10.10.1      matt 			sbuf_addstr(&db, item_name);
    605  1.10.10.1      matt 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    606        1.1       cgd 		}
    607        1.1       cgd 		break;
    608  1.10.10.1      matt 	case POTION:
    609  1.10.10.1      matt 		desc_count(&db, obj->quantity);
    610  1.10.10.1      matt 		if (objtype_id_status==UNIDENTIFIED) {
    611  1.10.10.1      matt 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    612  1.10.10.1      matt 			sbuf_addstr(&db, item_name);
    613  1.10.10.1      matt 		} else if (objtype_id_status==CALLED) {
    614  1.10.10.1      matt 			desc_called(&db, obj);
    615  1.10.10.1      matt 		} else {
    616  1.10.10.1      matt 			sbuf_addstr(&db, item_name);
    617  1.10.10.1      matt 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    618        1.1       cgd 		}
    619        1.1       cgd 		break;
    620  1.10.10.1      matt 	case WAND:
    621  1.10.10.1      matt 		desc_count(&db, obj->quantity);
    622  1.10.10.1      matt 		if (objtype_id_status==UNIDENTIFIED) {
    623  1.10.10.1      matt 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    624  1.10.10.1      matt 			sbuf_addstr(&db, item_name);
    625  1.10.10.1      matt 		} else if (objtype_id_status==CALLED) {
    626  1.10.10.1      matt 			desc_called(&db, obj);
    627  1.10.10.1      matt 		} else {
    628  1.10.10.1      matt 			sbuf_addstr(&db, item_name);
    629  1.10.10.1      matt 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    630        1.1       cgd 			if (wizard || obj->identified) {
    631  1.10.10.1      matt 				sbuf_addf(&db, "[%d]", obj->class);
    632        1.1       cgd 			}
    633        1.1       cgd 		}
    634        1.1       cgd 		break;
    635  1.10.10.1      matt 	case RING:
    636  1.10.10.1      matt 		desc_count(&db, obj->quantity);
    637  1.10.10.1      matt 		if (objtype_id_status==UNIDENTIFIED) {
    638  1.10.10.1      matt 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    639  1.10.10.1      matt 			sbuf_addstr(&db, item_name);
    640  1.10.10.1      matt 		} else if (objtype_id_status==CALLED) {
    641  1.10.10.1      matt 			desc_called(&db, obj);
    642  1.10.10.1      matt 		} else {
    643  1.10.10.1      matt 			if ((wizard || obj->identified) &&
    644  1.10.10.1      matt 			    (obj->which_kind == DEXTERITY ||
    645  1.10.10.1      matt 			     obj->which_kind == ADD_STRENGTH)) {
    646  1.10.10.1      matt 				sbuf_addf(&db, "%+d ", obj->class);
    647        1.1       cgd 			}
    648  1.10.10.1      matt 			sbuf_addstr(&db, item_name);
    649  1.10.10.1      matt 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    650  1.10.10.1      matt 		}
    651  1.10.10.1      matt 		break;
    652  1.10.10.1      matt 	case ARMOR:
    653  1.10.10.1      matt 		/* no desc_count() */
    654  1.10.10.1      matt 		if (objtype_id_status==UNIDENTIFIED) {
    655  1.10.10.1      matt 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    656  1.10.10.1      matt 		} else {
    657  1.10.10.1      matt 			sbuf_addf(&db, "%+d %s[%d] ", obj->d_enchant,
    658  1.10.10.1      matt 				id_table[obj->which_kind].title,
    659  1.10.10.1      matt 				get_armor_class(obj));
    660  1.10.10.1      matt     		}
    661  1.10.10.1      matt 		break;
    662  1.10.10.1      matt 	case WEAPON:
    663  1.10.10.1      matt 		desc_count(&db, obj->quantity);
    664  1.10.10.1      matt 		if (objtype_id_status==UNIDENTIFIED) {
    665  1.10.10.1      matt 			sbuf_addstr(&db, name_of(obj));
    666  1.10.10.1      matt 		} else {
    667  1.10.10.1      matt 			sbuf_addf(&db, "%+d,%+d %s",
    668  1.10.10.1      matt 				obj->hit_enchant, obj->d_enchant,
    669  1.10.10.1      matt 				name_of(obj));
    670        1.1       cgd 		}
    671  1.10.10.1      matt 		break;
    672        1.1       cgd 	}
    673  1.10.10.1      matt 
    674        1.1       cgd 	if (obj->in_use_flags & BEING_WIELDED) {
    675  1.10.10.1      matt 		sbuf_addstr(&db, "in hand");
    676        1.1       cgd 	} else if (obj->in_use_flags & BEING_WORN) {
    677  1.10.10.1      matt 		sbuf_addstr(&db, "being worn");
    678        1.1       cgd 	} else if (obj->in_use_flags & ON_LEFT_HAND) {
    679  1.10.10.1      matt 		sbuf_addstr(&db, "on left hand");
    680        1.1       cgd 	} else if (obj->in_use_flags & ON_RIGHT_HAND) {
    681  1.10.10.1      matt 		sbuf_addstr(&db, "on right hand");
    682  1.10.10.1      matt 	}
    683  1.10.10.1      matt 
    684  1.10.10.1      matt 	if (!strncmp(db.buf, "an ", 3)) {
    685  1.10.10.1      matt 		if (!is_vowel(db.buf[3])) {
    686  1.10.10.1      matt 			memmove(db.buf+2, db.buf+3, strlen(db.buf+3)+1);
    687  1.10.10.1      matt 			db.buf[1] = ' ';
    688  1.10.10.1      matt 		}
    689        1.1       cgd 	}
    690        1.1       cgd }
    691        1.1       cgd 
    692        1.5     lukem void
    693        1.1       cgd get_wand_and_ring_materials()
    694        1.1       cgd {
    695        1.1       cgd 	short i, j;
    696        1.1       cgd 	boolean used[WAND_MATERIALS];
    697        1.1       cgd 
    698        1.1       cgd 	for (i = 0; i < WAND_MATERIALS; i++) {
    699        1.1       cgd 		used[i] = 0;
    700        1.1       cgd 	}
    701        1.1       cgd 	for (i = 0; i < WANDS; i++) {
    702        1.1       cgd 		do {
    703        1.1       cgd 			j = get_rand(0, WAND_MATERIALS-1);
    704        1.1       cgd 		} while (used[j]);
    705        1.1       cgd 		used[j] = 1;
    706  1.10.10.1      matt 		(void) strlcpy(id_wands[i].title, wand_materials[j],
    707  1.10.10.1      matt 			       sizeof(id_wands[i].title));
    708        1.1       cgd 		is_wood[i] = (j > MAX_METAL);
    709        1.1       cgd 	}
    710        1.1       cgd 	for (i = 0; i < GEMS; i++) {
    711        1.1       cgd 		used[i] = 0;
    712        1.1       cgd 	}
    713        1.1       cgd 	for (i = 0; i < RINGS; i++) {
    714        1.1       cgd 		do {
    715        1.1       cgd 			j = get_rand(0, GEMS-1);
    716        1.1       cgd 		} while (used[j]);
    717        1.1       cgd 		used[j] = 1;
    718  1.10.10.1      matt 		(void) strlcpy(id_rings[i].title, gems[j],
    719  1.10.10.1      matt 			       sizeof(id_rings[i].title));
    720        1.1       cgd 	}
    721        1.1       cgd }
    722        1.1       cgd 
    723        1.5     lukem void
    724        1.1       cgd single_inv(ichar)
    725        1.5     lukem 	short ichar;
    726        1.1       cgd {
    727  1.10.10.1      matt 	short ch, ch2;
    728        1.1       cgd 	char desc[DCOLS];
    729        1.1       cgd 	object *obj;
    730        1.1       cgd 
    731        1.1       cgd 	ch = ichar ? ichar : pack_letter("inventory what?", ALL_OBJECTS);
    732        1.1       cgd 
    733        1.1       cgd 	if (ch == CANCEL) {
    734        1.1       cgd 		return;
    735        1.1       cgd 	}
    736        1.1       cgd 	if (!(obj = get_letter_object(ch))) {
    737  1.10.10.1      matt 		messagef(0, "no such item.");
    738        1.1       cgd 		return;
    739        1.1       cgd 	}
    740  1.10.10.1      matt 	ch2 = ((obj->what_is & ARMOR) && obj->is_protected) ? '}' : ')';
    741  1.10.10.1      matt 	get_desc(obj, desc, sizeof(desc));
    742  1.10.10.1      matt 	messagef(0, "%c%c %s", ch, ch2, desc);
    743        1.1       cgd }
    744        1.1       cgd 
    745        1.1       cgd struct id *
    746        1.1       cgd get_id_table(obj)
    747        1.6   hubertf 	const object *obj;
    748        1.1       cgd {
    749        1.1       cgd 	switch(obj->what_is) {
    750        1.1       cgd 	case SCROL:
    751        1.1       cgd 		return(id_scrolls);
    752        1.1       cgd 	case POTION:
    753        1.1       cgd 		return(id_potions);
    754        1.1       cgd 	case WAND:
    755        1.1       cgd 		return(id_wands);
    756        1.1       cgd 	case RING:
    757        1.1       cgd 		return(id_rings);
    758        1.1       cgd 	case WEAPON:
    759        1.1       cgd 		return(id_weapons);
    760        1.1       cgd 	case ARMOR:
    761        1.1       cgd 		return(id_armors);
    762        1.1       cgd 	}
    763        1.1       cgd 	return((struct id *) 0);
    764        1.1       cgd }
    765        1.1       cgd 
    766        1.5     lukem void
    767        1.1       cgd inv_armor_weapon(is_weapon)
    768        1.5     lukem 	boolean is_weapon;
    769        1.1       cgd {
    770        1.1       cgd 	if (is_weapon) {
    771        1.1       cgd 		if (rogue.weapon) {
    772        1.1       cgd 			single_inv(rogue.weapon->ichar);
    773        1.1       cgd 		} else {
    774  1.10.10.1      matt 			messagef(0, "not wielding anything");
    775        1.1       cgd 		}
    776        1.1       cgd 	} else {
    777        1.1       cgd 		if (rogue.armor) {
    778        1.1       cgd 			single_inv(rogue.armor->ichar);
    779        1.1       cgd 		} else {
    780  1.10.10.1      matt 			messagef(0, "not wearing anything");
    781        1.1       cgd 		}
    782        1.1       cgd 	}
    783        1.1       cgd }
    784        1.1       cgd 
    785        1.5     lukem void
    786        1.1       cgd id_type()
    787        1.1       cgd {
    788        1.6   hubertf 	const char *id;
    789        1.1       cgd 	int ch;
    790        1.1       cgd 
    791  1.10.10.1      matt 	messagef(0, "what do you want identified?");
    792        1.1       cgd 
    793        1.1       cgd 	ch = rgetchar();
    794        1.1       cgd 
    795        1.1       cgd 	if ((ch >= 'A') && (ch <= 'Z')) {
    796        1.1       cgd 		id = m_names[ch-'A'];
    797        1.1       cgd 	} else if (ch < 32) {
    798        1.1       cgd 		check_message();
    799        1.1       cgd 		return;
    800        1.1       cgd 	} else {
    801        1.1       cgd 		switch(ch) {
    802        1.1       cgd 		case '@':
    803        1.1       cgd 			id = "you";
    804        1.1       cgd 			break;
    805        1.1       cgd 		case '%':
    806        1.1       cgd 			id = "staircase";
    807        1.1       cgd 			break;
    808        1.1       cgd 		case '^':
    809        1.1       cgd 			id = "trap";
    810        1.1       cgd 			break;
    811        1.1       cgd 		case '+':
    812        1.1       cgd 			id = "door";
    813        1.1       cgd 			break;
    814        1.1       cgd 		case '-':
    815        1.1       cgd 		case '|':
    816        1.1       cgd 			id = "wall of a room";
    817        1.1       cgd 			break;
    818        1.1       cgd 		case '.':
    819        1.1       cgd 			id = "floor";
    820        1.1       cgd 			break;
    821        1.1       cgd 		case '#':
    822        1.1       cgd 			id = "passage";
    823        1.1       cgd 			break;
    824        1.1       cgd 		case ' ':
    825        1.1       cgd 			id = "solid rock";
    826        1.1       cgd 			break;
    827        1.1       cgd 		case '=':
    828        1.1       cgd 			id = "ring";
    829        1.1       cgd 			break;
    830        1.1       cgd 		case '?':
    831        1.1       cgd 			id = "scroll";
    832        1.1       cgd 			break;
    833        1.1       cgd 		case '!':
    834        1.1       cgd 			id = "potion";
    835        1.1       cgd 			break;
    836        1.1       cgd 		case '/':
    837        1.1       cgd 			id = "wand or staff";
    838        1.1       cgd 			break;
    839        1.1       cgd 		case ')':
    840        1.1       cgd 			id = "weapon";
    841        1.1       cgd 			break;
    842        1.1       cgd 		case ']':
    843        1.1       cgd 			id = "armor";
    844        1.1       cgd 			break;
    845        1.1       cgd 		case '*':
    846        1.1       cgd 			id = "gold";
    847        1.1       cgd 			break;
    848        1.1       cgd 		case ':':
    849        1.1       cgd 			id = "food";
    850        1.1       cgd 			break;
    851        1.1       cgd 		case ',':
    852        1.1       cgd 			id = "the Amulet of Yendor";
    853        1.1       cgd 			break;
    854        1.1       cgd 		default:
    855        1.1       cgd 			id = "unknown character";
    856        1.1       cgd 			break;
    857        1.1       cgd 		}
    858        1.1       cgd 	}
    859        1.1       cgd 	check_message();
    860  1.10.10.1      matt 	messagef(0, "'%c': %s", ch, id);
    861        1.1       cgd }
    862