Home | History | Annotate | Line # | Download | only in rogue
      1  1.15  dholland /*	$NetBSD: inventory.c,v 1.15 2011/08/26 06:18:17 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.15  dholland __RCSID("$NetBSD: inventory.c,v 1.15 2011/08/26 06:18:17 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.13  dholland static 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.13  dholland static 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.13  dholland static 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.13  dholland static 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.14  dholland static int get_com_id(int *, short);
    215  1.14  dholland static int pr_com_id(int);
    216  1.14  dholland static int pr_motion_char(int);
    217  1.14  dholland 
    218   1.5     lukem void
    219  1.13  dholland inventory(const object *pack, unsigned short mask)
    220   1.1       cgd {
    221   1.1       cgd 	object *obj;
    222  1.11  dholland 	short i = 0, j;
    223  1.11  dholland 	size_t maxlen = 0, n;
    224   1.1       cgd 	short row, col;
    225   1.1       cgd 
    226  1.11  dholland 	struct {
    227  1.11  dholland 		short letter;
    228  1.11  dholland 		short sepchar;
    229  1.11  dholland 		char desc[DCOLS];
    230  1.12  dholland 		char savebuf[DCOLS+8];
    231  1.11  dholland 	} descs[MAX_PACK_COUNT+1];
    232  1.11  dholland 
    233  1.11  dholland 
    234   1.1       cgd 	obj = pack->next_object;
    235   1.1       cgd 
    236   1.1       cgd 	if (!obj) {
    237  1.11  dholland 		messagef(0, "your pack is empty");
    238   1.1       cgd 		return;
    239   1.1       cgd 	}
    240   1.1       cgd 	while (obj) {
    241   1.1       cgd 		if (obj->what_is & mask) {
    242  1.11  dholland 			descs[i].letter = obj->ichar;
    243  1.11  dholland 			descs[i].sepchar = ((obj->what_is & ARMOR) && obj->is_protected)
    244   1.1       cgd 				? '}' : ')';
    245  1.11  dholland 			get_desc(obj, descs[i].desc, sizeof(descs[i].desc));
    246  1.11  dholland 			n = strlen(descs[i].desc) + 4;
    247  1.11  dholland 			if (n > maxlen) {
    248   1.1       cgd 				maxlen = n;
    249   1.1       cgd 			}
    250  1.11  dholland 			i++;
    251  1.11  dholland 			/*assert(i<=MAX_PACK_COUNT);*/
    252   1.1       cgd 		}
    253   1.1       cgd 		obj = obj->next_object;
    254   1.1       cgd 	}
    255   1.1       cgd 	if (maxlen < 27) maxlen = 27;
    256  1.11  dholland 	if (maxlen > DCOLS-2) maxlen = DCOLS-2;
    257   1.1       cgd 	col = DCOLS - (maxlen + 2);
    258   1.1       cgd 
    259  1.11  dholland 	for (row = 0; ((row <= i) && (row < DROWS)); row++) {
    260  1.11  dholland 		for (j = col; j < DCOLS; j++) {
    261  1.11  dholland 			descs[row].savebuf[j-col] = mvinch(row, j);
    262  1.11  dholland 		}
    263  1.11  dholland 		descs[row].savebuf[j-col] = 0;
    264  1.11  dholland 		if (row < i) {
    265  1.12  dholland 			mvprintw(row, col, " %c%c %s",
    266  1.12  dholland 				descs[row].letter, descs[row].sepchar,
    267  1.11  dholland 				descs[row].desc);
    268  1.11  dholland 		}
    269  1.11  dholland 		else {
    270  1.11  dholland 			mvaddstr(row, col, press_space);
    271   1.1       cgd 		}
    272   1.1       cgd 		clrtoeol();
    273   1.1       cgd 	}
    274   1.1       cgd 	refresh();
    275   1.1       cgd 	wait_for_ack();
    276   1.1       cgd 
    277   1.1       cgd 	move(0, 0);
    278   1.1       cgd 	clrtoeol();
    279   1.1       cgd 
    280  1.11  dholland 	for (j = 1; ((j <= i) && (j < DROWS)); j++) {
    281  1.11  dholland 		mvaddstr(j, col, descs[j].savebuf);
    282   1.1       cgd 	}
    283   1.1       cgd }
    284   1.1       cgd 
    285   1.5     lukem void
    286  1.13  dholland id_com(void)
    287   1.1       cgd {
    288   1.1       cgd 	int ch = 0;
    289   1.1       cgd 	short i, j, k;
    290   1.1       cgd 
    291   1.1       cgd 	while (ch != CANCEL) {
    292   1.1       cgd 		check_message();
    293  1.11  dholland 		messagef(0, "Character you want help for (* for all):");
    294   1.1       cgd 
    295   1.1       cgd 		refresh();
    296   1.1       cgd 		ch = getchar();
    297   1.1       cgd 
    298   1.1       cgd 		switch(ch) {
    299   1.1       cgd 		case LIST:
    300   1.1       cgd 			{
    301   1.1       cgd 				char save[(((COMS / 2) + (COMS % 2)) + 1)][DCOLS];
    302   1.1       cgd 				short rows = (((COMS / 2) + (COMS % 2)) + 1);
    303   1.5     lukem 				boolean need_two_screens = FALSE;
    304   1.1       cgd 
    305   1.1       cgd 				if (rows > LINES) {
    306   1.1       cgd 					need_two_screens = 1;
    307   1.1       cgd 					rows = LINES;
    308   1.1       cgd 				}
    309   1.1       cgd 				k = 0;
    310   1.1       cgd 
    311   1.1       cgd 				for (i = 0; i < rows; i++) {
    312   1.1       cgd 					for (j = 0; j < DCOLS; j++) {
    313   1.1       cgd 						save[i][j] = mvinch(i, j);
    314   1.1       cgd 					}
    315   1.1       cgd 				}
    316   1.1       cgd MORE:
    317   1.1       cgd 				for (i = 0; i < rows; i++) {
    318   1.1       cgd 					move(i, 0);
    319   1.1       cgd 					clrtoeol();
    320   1.1       cgd 				}
    321   1.1       cgd 				for (i = 0; i < (rows-1); i++) {
    322   1.1       cgd 					if (i < (LINES-1)) {
    323   1.1       cgd 						if (((i + i) < COMS) && ((i+i+k) < COMS)) {
    324   1.1       cgd 							mvaddstr(i, 0, com_id_tab[i+i+k].com_desc);
    325   1.1       cgd 						}
    326   1.1       cgd 						if (((i + i + 1) < COMS) && ((i+i+k+1) < COMS)) {
    327   1.1       cgd 							mvaddstr(i, (DCOLS/2),
    328   1.1       cgd 										com_id_tab[i+i+k+1].com_desc);
    329   1.1       cgd 						}
    330   1.1       cgd 					}
    331   1.1       cgd 				}
    332   1.1       cgd 				mvaddstr(rows - 1, 0, need_two_screens ? more : press_space);
    333   1.1       cgd 				refresh();
    334   1.1       cgd 				wait_for_ack();
    335   1.1       cgd 
    336   1.1       cgd 				if (need_two_screens) {
    337   1.1       cgd 					k += ((rows-1) * 2);
    338   1.1       cgd 					need_two_screens = 0;
    339   1.1       cgd 					goto MORE;
    340   1.1       cgd 				}
    341   1.1       cgd 				for (i = 0; i < rows; i++) {
    342   1.1       cgd 					move(i, 0);
    343   1.1       cgd 					for (j = 0; j < DCOLS; j++) {
    344   1.1       cgd 						addch(save[i][j]);
    345   1.1       cgd 					}
    346   1.1       cgd 				}
    347   1.1       cgd 			}
    348   1.1       cgd 			break;
    349   1.1       cgd 		default:
    350   1.1       cgd 			if (!pr_com_id(ch)) {
    351   1.1       cgd 				if (!pr_motion_char(ch)) {
    352   1.1       cgd 					check_message();
    353  1.11  dholland 					messagef(0, "unknown character");
    354   1.1       cgd 				}
    355   1.1       cgd 			}
    356   1.1       cgd 			ch = CANCEL;
    357   1.1       cgd 			break;
    358   1.1       cgd 		}
    359   1.1       cgd 	}
    360   1.1       cgd }
    361   1.1       cgd 
    362  1.14  dholland static int
    363  1.13  dholland pr_com_id(int ch)
    364   1.1       cgd {
    365   1.1       cgd 	int i;
    366   1.1       cgd 
    367   1.1       cgd 	if (!get_com_id(&i, ch)) {
    368   1.1       cgd 		return(0);
    369   1.1       cgd 	}
    370   1.1       cgd 	check_message();
    371  1.11  dholland 	messagef(0, "%s", com_id_tab[i].com_desc);
    372   1.1       cgd 	return(1);
    373   1.1       cgd }
    374   1.1       cgd 
    375  1.14  dholland static int
    376  1.13  dholland get_com_id(int *indexp, short ch)
    377   1.1       cgd {
    378   1.1       cgd 	short i;
    379   1.1       cgd 
    380   1.1       cgd 	for (i = 0; i < COMS; i++) {
    381   1.1       cgd 		if (com_id_tab[i].com_char == ch) {
    382   1.7      tron 			*indexp = i;
    383   1.1       cgd 			return(1);
    384   1.1       cgd 		}
    385   1.1       cgd 	}
    386   1.1       cgd 	return(0);
    387   1.1       cgd }
    388   1.1       cgd 
    389  1.14  dholland static int
    390  1.13  dholland pr_motion_char(int ch)
    391   1.1       cgd {
    392   1.1       cgd 	if (	(ch == 'J') ||
    393   1.1       cgd 			(ch == 'K') ||
    394   1.1       cgd 			(ch == 'L') ||
    395   1.1       cgd 			(ch == 'H') ||
    396   1.1       cgd 			(ch == 'Y') ||
    397   1.1       cgd 			(ch == 'U') ||
    398   1.1       cgd 			(ch == 'N') ||
    399   1.1       cgd 			(ch == 'B') ||
    400   1.1       cgd 			(ch == '\012') ||
    401   1.1       cgd 			(ch == '\013') ||
    402   1.1       cgd 			(ch == '\010') ||
    403   1.1       cgd 			(ch == '\014') ||
    404   1.1       cgd 			(ch == '\025') ||
    405   1.1       cgd 			(ch == '\031') ||
    406   1.1       cgd 			(ch == '\016') ||
    407   1.1       cgd 			(ch == '\002')) {
    408  1.11  dholland 		const char *until;
    409  1.10  christos 		int n = 0;	/* XXX: GCC */
    410   1.1       cgd 		if (ch <= '\031') {
    411   1.1       cgd 			ch += 96;
    412  1.11  dholland 			until = " until adjacent";
    413   1.1       cgd 		} else {
    414   1.1       cgd 			ch += 32;
    415  1.11  dholland 			until = "";
    416   1.1       cgd 		}
    417  1.12  dholland 		(void)get_com_id(&n, ch);
    418   1.1       cgd 		check_message();
    419  1.11  dholland 		messagef(0, "run %s%s", com_id_tab[n].com_desc + 8, until);
    420   1.1       cgd 		return(1);
    421   1.1       cgd 	} else {
    422   1.1       cgd 		return(0);
    423   1.1       cgd 	}
    424   1.1       cgd }
    425   1.1       cgd 
    426   1.5     lukem void
    427  1.13  dholland mix_colors(void)
    428   1.1       cgd {
    429   1.1       cgd 	short i, j, k;
    430   1.8       mrg 	char t[MAX_ID_TITLE_LEN];
    431   1.1       cgd 
    432   1.1       cgd 	for (i = 0; i <= 32; i++) {
    433   1.1       cgd 		j = get_rand(0, (POTIONS - 1));
    434   1.1       cgd 		k = get_rand(0, (POTIONS - 1));
    435  1.11  dholland 		strlcpy(t, id_potions[j].title, sizeof(t));
    436  1.11  dholland 		strlcpy(id_potions[j].title, id_potions[k].title,
    437  1.11  dholland 			sizeof(id_potions[j].title));
    438  1.11  dholland 		strlcpy(id_potions[k].title, t, sizeof(id_potions[k].title));
    439   1.1       cgd 	}
    440   1.1       cgd }
    441   1.1       cgd 
    442   1.5     lukem void
    443  1.13  dholland make_scroll_titles(void)
    444   1.1       cgd {
    445   1.1       cgd 	short i, j, n;
    446   1.1       cgd 	short sylls, s;
    447  1.11  dholland 	size_t maxlen = sizeof(id_scrolls[0].title);
    448   1.1       cgd 
    449   1.1       cgd 	for (i = 0; i < SCROLS; i++) {
    450   1.1       cgd 		sylls = get_rand(2, 5);
    451  1.12  dholland 		(void)strlcpy(id_scrolls[i].title, "'", maxlen);
    452   1.1       cgd 
    453   1.1       cgd 		for (j = 0; j < sylls; j++) {
    454   1.1       cgd 			s = get_rand(1, (MAXSYLLABLES-1));
    455  1.12  dholland 			(void)strlcat(id_scrolls[i].title, syllables[s],
    456  1.11  dholland 					maxlen);
    457   1.1       cgd 		}
    458  1.11  dholland 		/* trim trailing space */
    459   1.1       cgd 		n = strlen(id_scrolls[i].title);
    460  1.11  dholland 		id_scrolls[i].title[n-1] = 0;
    461  1.11  dholland 
    462  1.12  dholland 		(void)strlcat(id_scrolls[i].title, "' ", maxlen);
    463  1.11  dholland 	}
    464  1.11  dholland }
    465  1.11  dholland 
    466  1.11  dholland struct sbuf {
    467  1.11  dholland 	char *buf;
    468  1.11  dholland 	size_t maxlen;
    469  1.11  dholland };
    470  1.11  dholland 
    471  1.13  dholland static void sbuf_init(struct sbuf *s, char *buf, size_t maxlen);
    472  1.13  dholland static void sbuf_addstr(struct sbuf *s, const char *str);
    473  1.15  dholland static void sbuf_addf(struct sbuf *s, const char *fmt, ...) __printflike(2,3);
    474  1.13  dholland static void desc_count(struct sbuf *s, int n);
    475  1.13  dholland static void desc_called(struct sbuf *s, const object *);
    476  1.11  dholland 
    477  1.11  dholland static
    478  1.11  dholland void
    479  1.13  dholland sbuf_init(struct sbuf *s, char *buf, size_t maxlen)
    480  1.11  dholland {
    481  1.11  dholland 	s->buf = buf;
    482  1.11  dholland 	s->maxlen = maxlen;
    483  1.11  dholland 	/*assert(maxlen>0);*/
    484  1.11  dholland 	s->buf[0] = 0;
    485  1.11  dholland }
    486  1.11  dholland 
    487  1.11  dholland static
    488  1.11  dholland void
    489  1.13  dholland sbuf_addstr(struct sbuf *s, const char *str)
    490  1.11  dholland {
    491  1.11  dholland 	strlcat(s->buf, str, s->maxlen);
    492  1.11  dholland }
    493  1.11  dholland 
    494  1.11  dholland static
    495  1.11  dholland void
    496  1.11  dholland sbuf_addf(struct sbuf *s, const char *fmt, ...)
    497  1.11  dholland {
    498  1.11  dholland 	va_list ap;
    499  1.11  dholland 	size_t initlen;
    500  1.11  dholland 
    501  1.11  dholland 	initlen = strlen(s->buf);
    502  1.11  dholland 	va_start(ap, fmt);
    503  1.11  dholland 	vsnprintf(s->buf+initlen, s->maxlen-initlen, fmt, ap);
    504  1.11  dholland 	va_end(ap);
    505  1.11  dholland }
    506  1.11  dholland 
    507  1.11  dholland static
    508  1.11  dholland void
    509  1.13  dholland desc_count(struct sbuf *s, int n)
    510  1.11  dholland {
    511  1.11  dholland 	if (n == 1) {
    512  1.11  dholland 		sbuf_addstr(s, "an ");
    513  1.11  dholland 	} else {
    514  1.11  dholland 		sbuf_addf(s, "%d ", n);
    515   1.1       cgd 	}
    516   1.1       cgd }
    517   1.1       cgd 
    518  1.11  dholland static
    519   1.5     lukem void
    520  1.13  dholland desc_called(struct sbuf *s, const object *obj)
    521  1.11  dholland {
    522  1.11  dholland 	struct id *id_table;
    523  1.11  dholland 
    524  1.11  dholland 	id_table = get_id_table(obj);
    525  1.11  dholland 	sbuf_addstr(s, name_of(obj));
    526  1.11  dholland 	sbuf_addstr(s, "called ");
    527  1.11  dholland 	sbuf_addstr(s, id_table[obj->which_kind].title);
    528  1.11  dholland }
    529  1.11  dholland 
    530  1.11  dholland void
    531  1.13  dholland get_desc(const object *obj, char *desc, size_t desclen)
    532   1.1       cgd {
    533   1.6   hubertf 	const char *item_name;
    534   1.1       cgd 	struct id *id_table;
    535  1.11  dholland 	struct sbuf db;
    536  1.11  dholland 	unsigned short objtype_id_status;
    537   1.1       cgd 
    538   1.1       cgd 	if (obj->what_is == AMULET) {
    539  1.12  dholland 		(void)strlcpy(desc, "the amulet of Yendor ", desclen);
    540   1.1       cgd 		return;
    541   1.1       cgd 	}
    542   1.1       cgd 
    543   1.1       cgd 	if (obj->what_is == GOLD) {
    544  1.11  dholland 		snprintf(desc, desclen, "%d pieces of gold", obj->quantity);
    545   1.1       cgd 		return;
    546   1.1       cgd 	}
    547   1.1       cgd 
    548  1.11  dholland 	item_name = name_of(obj);
    549  1.11  dholland 	id_table = get_id_table(obj);
    550  1.11  dholland 	if (wizard || id_table == NULL) {
    551  1.11  dholland 		objtype_id_status = IDENTIFIED;
    552  1.11  dholland 	}
    553  1.11  dholland 	else {
    554  1.11  dholland 		objtype_id_status = id_table[obj->which_kind].id_status;
    555  1.11  dholland 	}
    556  1.11  dholland 	if (obj->what_is & (WEAPON | ARMOR | WAND | RING)) {
    557  1.11  dholland 		if (obj->identified) {
    558  1.11  dholland 			objtype_id_status = IDENTIFIED;
    559   1.1       cgd 		}
    560   1.1       cgd 	}
    561  1.11  dholland 
    562  1.11  dholland 	sbuf_init(&db, desc, desclen);
    563  1.11  dholland 
    564  1.11  dholland 	switch (obj->what_is) {
    565  1.11  dholland 	case FOOD:
    566   1.1       cgd 		if (obj->which_kind == RATION) {
    567   1.1       cgd 			if (obj->quantity > 1) {
    568  1.11  dholland 				sbuf_addf(&db,
    569  1.11  dholland 					 "%d rations of %s", obj->quantity,
    570  1.11  dholland 					 item_name);
    571   1.1       cgd 			} else {
    572  1.11  dholland 				sbuf_addf(&db, "some %s", item_name);
    573   1.1       cgd 			}
    574   1.1       cgd 		} else {
    575  1.11  dholland 			sbuf_addf(&db, "an %s", item_name);
    576   1.1       cgd 		}
    577  1.11  dholland 		break;
    578  1.11  dholland 	case SCROL:
    579  1.11  dholland 		desc_count(&db, obj->quantity);
    580  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    581  1.11  dholland 			sbuf_addstr(&db, item_name);
    582  1.11  dholland 			sbuf_addstr(&db, "entitled: ");
    583  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    584  1.11  dholland 		} else if (objtype_id_status==CALLED) {
    585  1.11  dholland 			desc_called(&db, obj);
    586  1.11  dholland 		} else {
    587  1.11  dholland 			sbuf_addstr(&db, item_name);
    588  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    589   1.1       cgd 		}
    590   1.1       cgd 		break;
    591  1.11  dholland 	case POTION:
    592  1.11  dholland 		desc_count(&db, obj->quantity);
    593  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    594  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    595  1.11  dholland 			sbuf_addstr(&db, item_name);
    596  1.11  dholland 		} else if (objtype_id_status==CALLED) {
    597  1.11  dholland 			desc_called(&db, obj);
    598  1.11  dholland 		} else {
    599  1.11  dholland 			sbuf_addstr(&db, item_name);
    600  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    601   1.1       cgd 		}
    602   1.1       cgd 		break;
    603  1.11  dholland 	case WAND:
    604  1.11  dholland 		desc_count(&db, obj->quantity);
    605  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    606  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    607  1.11  dholland 			sbuf_addstr(&db, item_name);
    608  1.11  dholland 		} else if (objtype_id_status==CALLED) {
    609  1.11  dholland 			desc_called(&db, obj);
    610  1.11  dholland 		} else {
    611  1.11  dholland 			sbuf_addstr(&db, item_name);
    612  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    613   1.1       cgd 			if (wizard || obj->identified) {
    614  1.11  dholland 				sbuf_addf(&db, "[%d]", obj->class);
    615   1.1       cgd 			}
    616  1.11  dholland 		}
    617  1.11  dholland 		break;
    618  1.11  dholland 	case RING:
    619  1.11  dholland 		desc_count(&db, obj->quantity);
    620  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    621  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].title);
    622  1.11  dholland 			sbuf_addstr(&db, item_name);
    623  1.11  dholland 		} else if (objtype_id_status==CALLED) {
    624  1.11  dholland 			desc_called(&db, obj);
    625  1.11  dholland 		} else {
    626  1.11  dholland 			if ((wizard || obj->identified) &&
    627  1.11  dholland 			    (obj->which_kind == DEXTERITY ||
    628  1.11  dholland 			     obj->which_kind == ADD_STRENGTH)) {
    629  1.11  dholland 				sbuf_addf(&db, "%+d ", obj->class);
    630   1.1       cgd 			}
    631  1.11  dholland 			sbuf_addstr(&db, item_name);
    632  1.11  dholland 			sbuf_addstr(&db, id_table[obj->which_kind].real);
    633   1.1       cgd 		}
    634   1.1       cgd 		break;
    635  1.11  dholland 	case ARMOR:
    636  1.11  dholland 		/* no desc_count() */
    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 		} else {
    640  1.11  dholland 			sbuf_addf(&db, "%+d %s[%d] ", obj->d_enchant,
    641  1.11  dholland 				id_table[obj->which_kind].title,
    642  1.11  dholland 				get_armor_class(obj));
    643  1.11  dholland     		}
    644  1.11  dholland 		break;
    645  1.11  dholland 	case WEAPON:
    646  1.11  dholland 		desc_count(&db, obj->quantity);
    647  1.11  dholland 		if (objtype_id_status==UNIDENTIFIED) {
    648  1.11  dholland 			sbuf_addstr(&db, name_of(obj));
    649  1.11  dholland 		} else {
    650  1.11  dholland 			sbuf_addf(&db, "%+d,%+d %s",
    651  1.11  dholland 				obj->hit_enchant, obj->d_enchant,
    652  1.11  dholland 				name_of(obj));
    653   1.1       cgd 		}
    654  1.11  dholland 		break;
    655   1.1       cgd 	}
    656  1.11  dholland 
    657   1.1       cgd 	if (obj->in_use_flags & BEING_WIELDED) {
    658  1.11  dholland 		sbuf_addstr(&db, "in hand");
    659   1.1       cgd 	} else if (obj->in_use_flags & BEING_WORN) {
    660  1.11  dholland 		sbuf_addstr(&db, "being worn");
    661   1.1       cgd 	} else if (obj->in_use_flags & ON_LEFT_HAND) {
    662  1.11  dholland 		sbuf_addstr(&db, "on left hand");
    663   1.1       cgd 	} else if (obj->in_use_flags & ON_RIGHT_HAND) {
    664  1.11  dholland 		sbuf_addstr(&db, "on right hand");
    665  1.11  dholland 	}
    666  1.11  dholland 
    667  1.11  dholland 	if (!strncmp(db.buf, "an ", 3)) {
    668  1.11  dholland 		if (!is_vowel(db.buf[3])) {
    669  1.11  dholland 			memmove(db.buf+2, db.buf+3, strlen(db.buf+3)+1);
    670  1.11  dholland 			db.buf[1] = ' ';
    671  1.11  dholland 		}
    672   1.1       cgd 	}
    673   1.1       cgd }
    674   1.1       cgd 
    675   1.5     lukem void
    676  1.13  dholland get_wand_and_ring_materials(void)
    677   1.1       cgd {
    678   1.1       cgd 	short i, j;
    679   1.1       cgd 	boolean used[WAND_MATERIALS];
    680   1.1       cgd 
    681   1.1       cgd 	for (i = 0; i < WAND_MATERIALS; i++) {
    682   1.1       cgd 		used[i] = 0;
    683   1.1       cgd 	}
    684   1.1       cgd 	for (i = 0; i < WANDS; i++) {
    685   1.1       cgd 		do {
    686   1.1       cgd 			j = get_rand(0, WAND_MATERIALS-1);
    687   1.1       cgd 		} while (used[j]);
    688   1.1       cgd 		used[j] = 1;
    689  1.12  dholland 		(void)strlcpy(id_wands[i].title, wand_materials[j],
    690  1.11  dholland 			       sizeof(id_wands[i].title));
    691   1.1       cgd 		is_wood[i] = (j > MAX_METAL);
    692   1.1       cgd 	}
    693   1.1       cgd 	for (i = 0; i < GEMS; i++) {
    694   1.1       cgd 		used[i] = 0;
    695   1.1       cgd 	}
    696   1.1       cgd 	for (i = 0; i < RINGS; i++) {
    697   1.1       cgd 		do {
    698   1.1       cgd 			j = get_rand(0, GEMS-1);
    699   1.1       cgd 		} while (used[j]);
    700   1.1       cgd 		used[j] = 1;
    701  1.12  dholland 		(void)strlcpy(id_rings[i].title, gems[j],
    702  1.11  dholland 			       sizeof(id_rings[i].title));
    703   1.1       cgd 	}
    704   1.1       cgd }
    705   1.1       cgd 
    706   1.5     lukem void
    707  1.13  dholland single_inv(short ichar)
    708   1.1       cgd {
    709  1.11  dholland 	short ch, ch2;
    710   1.1       cgd 	char desc[DCOLS];
    711   1.1       cgd 	object *obj;
    712   1.1       cgd 
    713   1.1       cgd 	ch = ichar ? ichar : pack_letter("inventory what?", ALL_OBJECTS);
    714   1.1       cgd 
    715   1.1       cgd 	if (ch == CANCEL) {
    716   1.1       cgd 		return;
    717   1.1       cgd 	}
    718   1.1       cgd 	if (!(obj = get_letter_object(ch))) {
    719  1.11  dholland 		messagef(0, "no such item.");
    720   1.1       cgd 		return;
    721   1.1       cgd 	}
    722  1.11  dholland 	ch2 = ((obj->what_is & ARMOR) && obj->is_protected) ? '}' : ')';
    723  1.11  dholland 	get_desc(obj, desc, sizeof(desc));
    724  1.11  dholland 	messagef(0, "%c%c %s", ch, ch2, desc);
    725   1.1       cgd }
    726   1.1       cgd 
    727   1.1       cgd struct id *
    728  1.13  dholland get_id_table(const object *obj)
    729   1.1       cgd {
    730   1.1       cgd 	switch(obj->what_is) {
    731   1.1       cgd 	case SCROL:
    732   1.1       cgd 		return(id_scrolls);
    733   1.1       cgd 	case POTION:
    734   1.1       cgd 		return(id_potions);
    735   1.1       cgd 	case WAND:
    736   1.1       cgd 		return(id_wands);
    737   1.1       cgd 	case RING:
    738   1.1       cgd 		return(id_rings);
    739   1.1       cgd 	case WEAPON:
    740   1.1       cgd 		return(id_weapons);
    741   1.1       cgd 	case ARMOR:
    742   1.1       cgd 		return(id_armors);
    743   1.1       cgd 	}
    744  1.12  dholland 	return((struct id *)0);
    745   1.1       cgd }
    746   1.1       cgd 
    747   1.5     lukem void
    748  1.13  dholland inv_armor_weapon(boolean is_weapon)
    749   1.1       cgd {
    750   1.1       cgd 	if (is_weapon) {
    751   1.1       cgd 		if (rogue.weapon) {
    752   1.1       cgd 			single_inv(rogue.weapon->ichar);
    753   1.1       cgd 		} else {
    754  1.11  dholland 			messagef(0, "not wielding anything");
    755   1.1       cgd 		}
    756   1.1       cgd 	} else {
    757   1.1       cgd 		if (rogue.armor) {
    758   1.1       cgd 			single_inv(rogue.armor->ichar);
    759   1.1       cgd 		} else {
    760  1.11  dholland 			messagef(0, "not wearing anything");
    761   1.1       cgd 		}
    762   1.1       cgd 	}
    763   1.1       cgd }
    764   1.1       cgd 
    765   1.5     lukem void
    766  1.13  dholland id_type(void)
    767   1.1       cgd {
    768   1.6   hubertf 	const char *id;
    769   1.1       cgd 	int ch;
    770   1.1       cgd 
    771  1.11  dholland 	messagef(0, "what do you want identified?");
    772   1.1       cgd 
    773   1.1       cgd 	ch = rgetchar();
    774   1.1       cgd 
    775   1.1       cgd 	if ((ch >= 'A') && (ch <= 'Z')) {
    776   1.1       cgd 		id = m_names[ch-'A'];
    777   1.1       cgd 	} else if (ch < 32) {
    778   1.1       cgd 		check_message();
    779   1.1       cgd 		return;
    780   1.1       cgd 	} else {
    781   1.1       cgd 		switch(ch) {
    782   1.1       cgd 		case '@':
    783   1.1       cgd 			id = "you";
    784   1.1       cgd 			break;
    785   1.1       cgd 		case '%':
    786   1.1       cgd 			id = "staircase";
    787   1.1       cgd 			break;
    788   1.1       cgd 		case '^':
    789   1.1       cgd 			id = "trap";
    790   1.1       cgd 			break;
    791   1.1       cgd 		case '+':
    792   1.1       cgd 			id = "door";
    793   1.1       cgd 			break;
    794   1.1       cgd 		case '-':
    795   1.1       cgd 		case '|':
    796   1.1       cgd 			id = "wall of a room";
    797   1.1       cgd 			break;
    798   1.1       cgd 		case '.':
    799   1.1       cgd 			id = "floor";
    800   1.1       cgd 			break;
    801   1.1       cgd 		case '#':
    802   1.1       cgd 			id = "passage";
    803   1.1       cgd 			break;
    804   1.1       cgd 		case ' ':
    805   1.1       cgd 			id = "solid rock";
    806   1.1       cgd 			break;
    807   1.1       cgd 		case '=':
    808   1.1       cgd 			id = "ring";
    809   1.1       cgd 			break;
    810   1.1       cgd 		case '?':
    811   1.1       cgd 			id = "scroll";
    812   1.1       cgd 			break;
    813   1.1       cgd 		case '!':
    814   1.1       cgd 			id = "potion";
    815   1.1       cgd 			break;
    816   1.1       cgd 		case '/':
    817   1.1       cgd 			id = "wand or staff";
    818   1.1       cgd 			break;
    819   1.1       cgd 		case ')':
    820   1.1       cgd 			id = "weapon";
    821   1.1       cgd 			break;
    822   1.1       cgd 		case ']':
    823   1.1       cgd 			id = "armor";
    824   1.1       cgd 			break;
    825   1.1       cgd 		case '*':
    826   1.1       cgd 			id = "gold";
    827   1.1       cgd 			break;
    828   1.1       cgd 		case ':':
    829   1.1       cgd 			id = "food";
    830   1.1       cgd 			break;
    831   1.1       cgd 		case ',':
    832   1.1       cgd 			id = "the Amulet of Yendor";
    833   1.1       cgd 			break;
    834   1.1       cgd 		default:
    835   1.1       cgd 			id = "unknown character";
    836   1.1       cgd 			break;
    837   1.1       cgd 		}
    838   1.1       cgd 	}
    839   1.1       cgd 	check_message();
    840  1.11  dholland 	messagef(0, "'%c': %s", ch, id);
    841   1.1       cgd }
    842