Home | History | Annotate | Line # | Download | only in rogue
inventory.c revision 1.12
      1  1.12  dholland /*	$NetBSD: inventory.c,v 1.12 2008/01/14 00:23:51 dholland 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.12  dholland __RCSID("$NetBSD: inventory.c,v 1.12 2008/01/14 00:23:51 dholland 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.11  dholland #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.11  dholland 	short i = 0, j;
    221  1.11  dholland 	size_t maxlen = 0, n;
    222   1.1       cgd 	short row, col;
    223   1.1       cgd 
    224  1.11  dholland 	struct {
    225  1.11  dholland 		short letter;
    226  1.11  dholland 		short sepchar;
    227  1.11  dholland 		char desc[DCOLS];
    228  1.12  dholland 		char savebuf[DCOLS+8];
    229  1.11  dholland 	} descs[MAX_PACK_COUNT+1];
    230  1.11  dholland 
    231  1.11  dholland 
    232   1.1       cgd 	obj = pack->next_object;
    233   1.1       cgd 
    234   1.1       cgd 	if (!obj) {
    235  1.11  dholland 		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.11  dholland 			descs[i].letter = obj->ichar;
    241  1.11  dholland 			descs[i].sepchar = ((obj->what_is & ARMOR) && obj->is_protected)
    242   1.1       cgd 				? '}' : ')';
    243  1.11  dholland 			get_desc(obj, descs[i].desc, sizeof(descs[i].desc));
    244  1.11  dholland 			n = strlen(descs[i].desc) + 4;
    245  1.11  dholland 			if (n > maxlen) {
    246   1.1       cgd 				maxlen = n;
    247   1.1       cgd 			}
    248  1.11  dholland 			i++;
    249  1.11  dholland 			/*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.11  dholland 	if (maxlen > DCOLS-2) maxlen = DCOLS-2;
    255   1.1       cgd 	col = DCOLS - (maxlen + 2);
    256   1.1       cgd 
    257  1.11  dholland 	for (row = 0; ((row <= i) && (row < DROWS)); row++) {
    258  1.11  dholland 		for (j = col; j < DCOLS; j++) {
    259  1.11  dholland 			descs[row].savebuf[j-col] = mvinch(row, j);
    260  1.11  dholland 		}
    261  1.11  dholland 		descs[row].savebuf[j-col] = 0;
    262  1.11  dholland 		if (row < i) {
    263  1.12  dholland 			mvprintw(row, col, " %c%c %s",
    264  1.12  dholland 				descs[row].letter, descs[row].sepchar,
    265  1.11  dholland 				descs[row].desc);
    266  1.11  dholland 		}
    267  1.11  dholland 		else {
    268  1.11  dholland 			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.11  dholland 	for (j = 1; ((j <= i) && (j < DROWS)); j++) {
    279  1.11  dholland 		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.11  dholland 		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.11  dholland 					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.11  dholland 	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.11  dholland 		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.11  dholland 			until = " until adjacent";
    415   1.1       cgd 		} else {
    416   1.1       cgd 			ch += 32;
    417  1.11  dholland 			until = "";
    418   1.1       cgd 		}
    419  1.12  dholland 		(void)get_com_id(&n, ch);
    420   1.1       cgd 		check_message();
    421  1.11  dholland 		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.11  dholland 		strlcpy(t, id_potions[j].title, sizeof(t));
    438  1.11  dholland 		strlcpy(id_potions[j].title, id_potions[k].title,
    439  1.11  dholland 			sizeof(id_potions[j].title));
    440  1.11  dholland 		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.11  dholland 	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.12  dholland 		(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.12  dholland 			(void)strlcat(id_scrolls[i].title, syllables[s],
    458  1.11  dholland 					maxlen);
    459   1.1       cgd 		}
    460  1.11  dholland 		/* trim trailing space */
    461   1.1       cgd 		n = strlen(id_scrolls[i].title);
    462  1.11  dholland 		id_scrolls[i].title[n-1] = 0;
    463  1.11  dholland 
    464  1.12  dholland 		(void)strlcat(id_scrolls[i].title, "' ", maxlen);
    465  1.11  dholland 	}
    466  1.11  dholland }
    467  1.11  dholland 
    468  1.11  dholland struct sbuf {
    469  1.11  dholland 	char *buf;
    470  1.11  dholland 	size_t maxlen;
    471  1.11  dholland };
    472  1.11  dholland 
    473  1.11  dholland static void sbuf_init __P((struct sbuf *s, char *buf, size_t maxlen));
    474  1.11  dholland static void sbuf_addstr __P((struct sbuf *s, const char *str));
    475  1.11  dholland static void sbuf_addf __P((struct sbuf *s, const char *fmt, ...));
    476  1.11  dholland static void desc_count __P((struct sbuf *s, int n));
    477  1.11  dholland static void desc_called __P((struct sbuf *s, const object *));
    478  1.11  dholland 
    479  1.11  dholland static
    480  1.11  dholland void
    481  1.11  dholland sbuf_init(s, buf, maxlen)
    482  1.11  dholland 	struct sbuf *s;
    483  1.11  dholland 	char *buf;
    484  1.11  dholland 	size_t maxlen;
    485  1.11  dholland {
    486  1.11  dholland 	s->buf = buf;
    487  1.11  dholland 	s->maxlen = maxlen;
    488  1.11  dholland 	/*assert(maxlen>0);*/
    489  1.11  dholland 	s->buf[0] = 0;
    490  1.11  dholland }
    491  1.11  dholland 
    492  1.11  dholland static
    493  1.11  dholland void
    494  1.11  dholland sbuf_addstr(s, str)
    495  1.11  dholland 	struct sbuf *s;
    496  1.11  dholland 	const char *str;
    497  1.11  dholland {
    498  1.11  dholland 	strlcat(s->buf, str, s->maxlen);
    499  1.11  dholland }
    500  1.11  dholland 
    501  1.11  dholland static void sbuf_addf(struct sbuf *s, const char *fmt, ...)
    502  1.11  dholland 	__attribute__((__format__(__printf__, 2, 3)));
    503  1.11  dholland 
    504  1.11  dholland static
    505  1.11  dholland void
    506  1.11  dholland sbuf_addf(struct sbuf *s, const char *fmt, ...)
    507  1.11  dholland {
    508  1.11  dholland 	va_list ap;
    509  1.11  dholland 	size_t initlen;
    510  1.11  dholland 
    511  1.11  dholland 	initlen = strlen(s->buf);
    512  1.11  dholland 	va_start(ap, fmt);
    513  1.11  dholland 	vsnprintf(s->buf+initlen, s->maxlen-initlen, fmt, ap);
    514  1.11  dholland 	va_end(ap);
    515  1.11  dholland }
    516  1.11  dholland 
    517  1.11  dholland static
    518  1.11  dholland void
    519  1.11  dholland desc_count(s, n)
    520  1.11  dholland 	struct sbuf *s;
    521  1.11  dholland 	int n;
    522  1.11  dholland {
    523  1.11  dholland 	if (n == 1) {
    524  1.11  dholland 		sbuf_addstr(s, "an ");
    525  1.11  dholland 	} else {
    526  1.11  dholland 		sbuf_addf(s, "%d ", n);
    527   1.1       cgd 	}
    528   1.1       cgd }
    529   1.1       cgd 
    530  1.11  dholland static
    531   1.5     lukem void
    532  1.11  dholland desc_called(s, obj)
    533  1.11  dholland 	struct sbuf *s;
    534  1.11  dholland 	const object *obj;
    535  1.11  dholland {
    536  1.11  dholland 	struct id *id_table;
    537  1.11  dholland 
    538  1.11  dholland 	id_table = get_id_table(obj);
    539  1.11  dholland 	sbuf_addstr(s, name_of(obj));
    540  1.11  dholland 	sbuf_addstr(s, "called ");
    541  1.11  dholland 	sbuf_addstr(s, id_table[obj->which_kind].title);
    542  1.11  dholland }
    543  1.11  dholland 
    544  1.11  dholland void
    545  1.11  dholland get_desc(obj, desc, desclen)
    546   1.6   hubertf 	const object *obj;
    547   1.5     lukem 	char *desc;
    548  1.11  dholland 	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.11  dholland 	struct sbuf db;
    553  1.11  dholland 	unsigned short objtype_id_status;
    554   1.1       cgd 
    555   1.1       cgd 	if (obj->what_is == AMULET) {
    556  1.12  dholland 		(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.11  dholland 		snprintf(desc, desclen, "%d pieces of gold", obj->quantity);
    562   1.1       cgd 		return;
    563   1.1       cgd 	}
    564   1.1       cgd 
    565  1.11  dholland 	item_name = name_of(obj);
    566  1.11  dholland 	id_table = get_id_table(obj);
    567  1.11  dholland 	if (wizard || id_table == NULL) {
    568  1.11  dholland 		objtype_id_status = IDENTIFIED;
    569  1.11  dholland 	}
    570  1.11  dholland 	else {
    571  1.11  dholland 		objtype_id_status = id_table[obj->which_kind].id_status;
    572  1.11  dholland 	}
    573  1.11  dholland 	if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) {
    574  1.11  dholland 		if (obj->identified) {
    575  1.11  dholland 			objtype_id_status = IDENTIFIED;
    576   1.1       cgd 		}
    577   1.1       cgd 	}
    578  1.11  dholland 
    579  1.11  dholland 	sbuf_init(&db, desc, desclen);
    580  1.11  dholland 
    581  1.11  dholland 	switch (obj->what_is) {
    582  1.11  dholland 	case FOOD:
    583   1.1       cgd 		if (obj->which_kind == RATION) {
    584   1.1       cgd 			if (obj->quantity > 1) {
    585  1.11  dholland 				sbuf_addf(&db,
    586  1.11  dholland 					 "%d rations of %s", obj->quantity,
    587  1.11  dholland 					 item_name);
    588   1.1       cgd 			} else {
    589  1.11  dholland 				sbuf_addf(&db, "some %s", item_name);
    590   1.1       cgd 			}
    591   1.1       cgd 		} else {
    592  1.11  dholland 			sbuf_addf(&db, "an %s", item_name);
    593   1.1       cgd 		}
    594  1.11  dholland 		break;
    595  1.11  dholland 	case SCROL:
    596  1.11  dholland 		desc_count(&db, obj->quantity);
    597  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    598  1.11  dholland 			sbuf_addstr(&db, item_name);
    599  1.11  dholland 			sbuf_addstr(&db, "entitled: ");
    600  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    601  1.11  dholland 		} else if (objtype_id_status==CALLED) {
    602  1.11  dholland 			desc_called(&db, obj);
    603  1.11  dholland 		} else {
    604  1.11  dholland 			sbuf_addstr(&db, item_name);
    605  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    606   1.1       cgd 		}
    607   1.1       cgd 		break;
    608  1.11  dholland 	case POTION:
    609  1.11  dholland 		desc_count(&db, obj->quantity);
    610  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    611  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    612  1.11  dholland 			sbuf_addstr(&db, item_name);
    613  1.11  dholland 		} else if (objtype_id_status==CALLED) {
    614  1.11  dholland 			desc_called(&db, obj);
    615  1.11  dholland 		} else {
    616  1.11  dholland 			sbuf_addstr(&db, item_name);
    617  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    618   1.1       cgd 		}
    619   1.1       cgd 		break;
    620  1.11  dholland 	case WAND:
    621  1.11  dholland 		desc_count(&db, obj->quantity);
    622  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    623  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    624  1.11  dholland 			sbuf_addstr(&db, item_name);
    625  1.11  dholland 		} else if (objtype_id_status==CALLED) {
    626  1.11  dholland 			desc_called(&db, obj);
    627  1.11  dholland 		} else {
    628  1.11  dholland 			sbuf_addstr(&db, item_name);
    629  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    630   1.1       cgd 			if (wizard || obj->identified) {
    631  1.11  dholland 				sbuf_addf(&db, "[%d]", obj->class);
    632   1.1       cgd 			}
    633  1.11  dholland 		}
    634  1.11  dholland 		break;
    635  1.11  dholland 	case RING:
    636  1.11  dholland 		desc_count(&db, obj->quantity);
    637  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    638  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    639  1.11  dholland 			sbuf_addstr(&db, item_name);
    640  1.11  dholland 		} else if (objtype_id_status==CALLED) {
    641  1.11  dholland 			desc_called(&db, obj);
    642  1.11  dholland 		} else {
    643  1.11  dholland 			if ((wizard || obj->identified) &&
    644  1.11  dholland 			    (obj->which_kind == DEXTERITY ||
    645  1.11  dholland 			     obj->which_kind == ADD_STRENGTH)) {
    646  1.11  dholland 				sbuf_addf(&db, "%+d ", obj->class);
    647   1.1       cgd 			}
    648  1.11  dholland 			sbuf_addstr(&db, item_name);
    649  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    650   1.1       cgd 		}
    651   1.1       cgd 		break;
    652  1.11  dholland 	case ARMOR:
    653  1.11  dholland 		/* no desc_count() */
    654  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    655  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    656  1.11  dholland 		} else {
    657  1.11  dholland 			sbuf_addf(&db, "%+d %s[%d] ", obj->d_enchant,
    658  1.11  dholland 				id_table[obj->which_kind].title,
    659  1.11  dholland 				get_armor_class(obj));
    660  1.11  dholland     		}
    661  1.11  dholland 		break;
    662  1.11  dholland 	case WEAPON:
    663  1.11  dholland 		desc_count(&db, obj->quantity);
    664  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    665  1.11  dholland 			sbuf_addstr(&db, name_of(obj));
    666  1.11  dholland 		} else {
    667  1.11  dholland 			sbuf_addf(&db, "%+d,%+d %s",
    668  1.11  dholland 				obj->hit_enchant, obj->d_enchant,
    669  1.11  dholland 				name_of(obj));
    670   1.1       cgd 		}
    671  1.11  dholland 		break;
    672   1.1       cgd 	}
    673  1.11  dholland 
    674   1.1       cgd 	if (obj->in_use_flags & BEING_WIELDED) {
    675  1.11  dholland 		sbuf_addstr(&db, "in hand");
    676   1.1       cgd 	} else if (obj->in_use_flags & BEING_WORN) {
    677  1.11  dholland 		sbuf_addstr(&db, "being worn");
    678   1.1       cgd 	} else if (obj->in_use_flags & ON_LEFT_HAND) {
    679  1.11  dholland 		sbuf_addstr(&db, "on left hand");
    680   1.1       cgd 	} else if (obj->in_use_flags & ON_RIGHT_HAND) {
    681  1.11  dholland 		sbuf_addstr(&db, "on right hand");
    682  1.11  dholland 	}
    683  1.11  dholland 
    684  1.11  dholland 	if (!strncmp(db.buf, "an ", 3)) {
    685  1.11  dholland 		if (!is_vowel(db.buf[3])) {
    686  1.11  dholland 			memmove(db.buf+2, db.buf+3, strlen(db.buf+3)+1);
    687  1.11  dholland 			db.buf[1] = ' ';
    688  1.11  dholland 		}
    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.12  dholland 		(void)strlcpy(id_wands[i].title, wand_materials[j],
    707  1.11  dholland 			       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.12  dholland 		(void)strlcpy(id_rings[i].title, gems[j],
    719  1.11  dholland 			       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.11  dholland 	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.11  dholland 		messagef(0, "no such item.");
    738   1.1       cgd 		return;
    739   1.1       cgd 	}
    740  1.11  dholland 	ch2 = ((obj->what_is & ARMOR) && obj->is_protected) ? '}' : ')';
    741  1.11  dholland 	get_desc(obj, desc, sizeof(desc));
    742  1.11  dholland 	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.12  dholland 	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.11  dholland 			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.11  dholland 			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.11  dholland 	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.11  dholland 	messagef(0, "'%c': %s", ch, id);
    861   1.1       cgd }
    862