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