Annotation of early-roguelike/rogue4/things.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * Contains functions for dealing with things like potions, scrolls,
3: * and other items.
4: *
5: * @(#)things.c 4.26 (Berkeley) 5/18/82
6: *
7: * Rogue: Exploring the Dungeons of Doom
8: * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
9: * All rights reserved.
10: *
11: * See the file LICENSE.TXT for full copyright and licensing information.
12: */
13:
14: #include <curses.h>
15: #include <ctype.h>
16: #include <string.h>
17: #include "rogue.h"
18:
19: int pick_one(struct magic_item *magic, int nitems);
20: void print_disc(char type);
21: void set_order(short *order, int numthings);
22: char *nothing(char type);
23:
24: bool got_genocide = FALSE;
25:
26: /*
27: * inv_name:
28: * Return the name of something as it would appear in an
29: * inventory.
30: */
31: char *
32: inv_name(THING *obj, bool drop)
33: {
34: register char *pb;
35:
36: pb = prbuf;
37: switch (obj->o_type)
38: {
39: case SCROLL:
40: if (obj->o_count == 1)
41: {
42: strcpy(pb, "A scroll ");
43: pb = &prbuf[9];
44: }
45: else
46: {
47: sprintf(pb, "%d scrolls ", obj->o_count);
48: pb = &prbuf[strlen(prbuf)];
49: }
50: if (s_know[obj->o_which])
51: sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);
52: else if (s_guess[obj->o_which])
53: sprintf(pb, "called %s", s_guess[obj->o_which]);
54: else
55: sprintf(pb, "titled '%s'", s_names[obj->o_which]);
56: when POTION:
57: if (obj->o_count == 1)
58: {
59: strcpy(pb, "A potion ");
60: pb = &prbuf[9];
61: }
62: else
63: {
64: sprintf(pb, "%d potions ", obj->o_count);
65: pb = &pb[strlen(prbuf)];
66: }
67: if (p_know[obj->o_which])
68: sprintf(pb, "of %s(%s)", p_magic[obj->o_which].mi_name,
69: p_colors[obj->o_which]);
70: else if (p_guess[obj->o_which])
71: sprintf(pb, "called %s(%s)", p_guess[obj->o_which],
72: p_colors[obj->o_which]);
73: else if (obj->o_count == 1)
74: sprintf(prbuf, "A%s %s potion", vowelstr(p_colors[obj->o_which]),
75: p_colors[obj->o_which]);
76: else
77: sprintf(prbuf, "%d %s potions", obj->o_count,
78: p_colors[obj->o_which]);
79: when FOOD:
80: if (obj->o_which == 1)
81: if (obj->o_count == 1)
82: sprintf(pb, "A%s %.76s", vowelstr(fruit), fruit);
83: else
84: sprintf(pb, "%d %.66ss", obj->o_count, fruit);
85: else
86: if (obj->o_count == 1)
87: strcpy(pb, "Some food");
88: else
89: sprintf(pb, "%d rations of food", obj->o_count);
90: when WEAPON:
91: if (obj->o_count > 1)
92: sprintf(pb, "%d ", obj->o_count);
93: else
94: sprintf(pb, "A%s ", vowelstr(w_names[obj->o_which]));
95: pb = &prbuf[strlen(prbuf)];
96: if (obj->o_flags & ISKNOW)
97: sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus, WEAPON),
98: w_names[obj->o_which]);
99: else
100: sprintf(pb, "%s", w_names[obj->o_which]);
101: if (obj->o_count > 1)
102: strcat(pb, "s");
103: when ARMOR:
104: if (obj->o_flags & ISKNOW)
105: {
106: sprintf(pb, "%s %s [",
107: num(a_class[obj->o_which] - obj->o_ac, 0, ARMOR),
108: a_names[obj->o_which]);
109: if (!terse)
110: strcat(pb, "armor class ");
111: pb = &prbuf[strlen(prbuf)];
112: sprintf(pb, "%d]", obj->o_ac);
113: }
114: else
115: sprintf(pb, "%s", a_names[obj->o_which]);
116: when AMULET:
117: strcpy(pb, "The Amulet of Yendor");
118: when STICK:
119: sprintf(pb, "A%s %s ", vowelstr(ws_type[obj->o_which]),
120: ws_type[obj->o_which]);
121: pb = &prbuf[strlen(prbuf)];
122: if (ws_know[obj->o_which])
123: sprintf(pb, "of %s%s(%s)", ws_magic[obj->o_which].mi_name,
124: charge_str(obj), ws_made[obj->o_which]);
125: else if (ws_guess[obj->o_which])
126: sprintf(pb, "called %s(%s)", ws_guess[obj->o_which],
127: ws_made[obj->o_which]);
128: else
129: sprintf(pb = &prbuf[1], "%s %s %s",
130: vowelstr(ws_made[obj->o_which]), ws_made[obj->o_which],
131: ws_type[obj->o_which]);
132: when RING:
133: if (r_know[obj->o_which])
134: sprintf(pb, "A%s ring of %s(%s)", ring_num(obj),
135: r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);
136: else if (r_guess[obj->o_which])
137: sprintf(pb, "A ring called %s(%s)",
138: r_guess[obj->o_which], r_stones[obj->o_which]);
139: else
140: sprintf(pb, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
141: r_stones[obj->o_which]);
142: when GOLD:
143: sprintf(pb, "%d pieces of gold", obj->o_goldval);
144: #ifdef WIZARD
145: otherwise:
146: debug("Picked up something funny %s", unctrol(obj->o_type));
147: sprintf(pb, "Something bizarre %s", unctrol(obj->o_type));
148: #endif
149: }
150: if (obj == cur_armor)
151: strcat(pb, " (being worn)");
152: if (obj == cur_weapon)
153: strcat(pb, " (weapon in hand)");
154: if (obj == cur_ring[LEFT])
155: strcat(pb, " (on left hand)");
156: else if (obj == cur_ring[RIGHT])
157: strcat(pb, " (on right hand)");
158: if (drop && isupper(prbuf[0]))
159: prbuf[0] = tolower(prbuf[0]);
160: else if (!drop && islower(*prbuf))
161: *prbuf = toupper(*prbuf);
162: return prbuf;
163: }
164:
165: /*
166: * drop:
167: * Put something down
168: */
169: void
170: drop(void)
171: {
172: register char ch;
173: register THING *nobj, *op;
174:
175: ch = chat(hero.y, hero.x);
176: if (ch != FLOOR && ch != PASSAGE)
177: {
178: after = FALSE;
179: msg("there is something there already");
180: return;
181: }
182: if ((op = get_item("drop", 0)) == NULL)
183: return;
184: if (!dropcheck(op))
185: return;
186: /*
187: * Take it out of the pack
188: */
189: if (op->o_count >= 2 && op->o_type != WEAPON)
190: {
191: op->o_count--;
192: nobj = new_item();
193: *nobj = *op;
194: nobj->o_count = 1;
195: op = nobj;
196: if (op->o_group != 0)
197: inpack++;
198: }
199: else
200: detach(pack, op);
201: inpack--;
202: /*
203: * Link it into the level object list
204: */
205: attach(lvl_obj, op);
206: chat(hero.y, hero.x) = op->o_type;
207: flat(hero.y, hero.x) |= F_DROPPED;
208: op->o_pos = hero;
209: if (op->o_type == AMULET)
210: amulet = FALSE;
211: msg("dropped %s", inv_name(op, TRUE));
212: }
213:
214: /*
215: * dropcheck:
216: * Do special checks for dropping or unweilding|unwearing|unringing
217: */
218: bool
219: dropcheck(THING *op)
220: {
221: if (op == NULL)
222: return TRUE;
223: if (op != cur_armor && op != cur_weapon
224: && op != cur_ring[LEFT] && op != cur_ring[RIGHT])
225: return TRUE;
226: if (op->o_flags & ISCURSED)
227: {
228: msg("you can't. It appears to be cursed");
229: return FALSE;
230: }
231: if (op == cur_weapon)
232: cur_weapon = NULL;
233: else if (op == cur_armor)
234: {
235: waste_time();
236: cur_armor = NULL;
237: }
238: else
239: {
240: cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
241: switch (op->o_which)
242: {
243: case R_ADDSTR:
244: chg_str(-op->o_ac);
245: break;
246: case R_SEEINVIS:
247: unsee();
248: extinguish(unsee);
249: break;
250: }
251: }
252: return TRUE;
253: }
254:
255: /*
256: * new_thing:
257: * Return a new thing
258: */
259: THING *
260: new_thing(void)
261: {
262: register THING *cur;
263: register int j, k;
264:
265: cur = new_item();
266: cur->o_hplus = cur->o_dplus = 0;
267: strcpy(cur->o_damage,"0d0");
268: strcpy(cur->o_hurldmg,"0d0");
269: cur->o_ac = 11;
270: cur->o_count = 1;
271: cur->o_group = 0;
272: cur->o_flags = 0;
273: /*
274: * Decide what kind of object it will be
275: * If we haven't had food for a while, let it be food.
276: */
277: switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS))
278: {
279: case 0:
280: cur->o_type = POTION;
281: cur->o_which = pick_one(p_magic, MAXPOTIONS);
282: when 1:
283: cur->o_type = SCROLL;
284: cur->o_which = pick_one(s_magic, MAXSCROLLS);
285: /*
286: * Only one genocide scroll allowed per game, so if it's
287: * the second one, then turn it into a identify scroll
288: */
289: if (cur->o_which == S_GENOCIDE)
290: if (got_genocide)
291: cur->o_which = S_IDENT;
292: else
293: got_genocide = TRUE;
294: when 2:
295: no_food = 0;
296: cur->o_type = FOOD;
297: if (rnd(10) != 0)
298: cur->o_which = 0;
299: else
300: cur->o_which = 1;
301: when 3:
302: cur->o_type = WEAPON;
303: cur->o_which = rnd(MAXWEAPONS);
304: init_weapon(cur, cur->o_which);
305: if ((k = rnd(100)) < 10)
306: {
307: cur->o_flags |= ISCURSED;
308: cur->o_hplus -= rnd(3) + 1;
309: }
310: else if (k < 15)
311: cur->o_hplus += rnd(3) + 1;
312: when 4:
313: cur->o_type = ARMOR;
314: for (j = 0, k = rnd(100); j < MAXARMORS; j++)
315: if (k < a_chances[j])
316: break;
317: #ifdef WIZARD
318: if (j == MAXARMORS)
319: {
320: debug("Picked a bad armor %d", k);
321: j = 0;
322: }
323: #endif
324: cur->o_which = j;
325: cur->o_ac = a_class[j];
326: if ((k = rnd(100)) < 20)
327: {
328: cur->o_flags |= ISCURSED;
329: cur->o_ac += rnd(3) + 1;
330: }
331: else if (k < 28)
332: cur->o_ac -= rnd(3) + 1;
333: when 5:
334: cur->o_type = RING;
335: cur->o_which = pick_one(r_magic, MAXRINGS);
336: switch (cur->o_which)
337: {
338: case R_ADDSTR:
339: case R_PROTECT:
340: case R_ADDHIT:
341: case R_ADDDAM:
342: if ((cur->o_ac = rnd(3)) == 0)
343: {
344: cur->o_ac = -1;
345: cur->o_flags |= ISCURSED;
346: }
347: when R_AGGR:
348: case R_TELEPORT:
349: cur->o_flags |= ISCURSED;
350: }
351: when 6:
352: cur->o_type = STICK;
353: cur->o_which = pick_one(ws_magic, MAXSTICKS);
354: fix_stick(cur);
355: #ifdef WIZARD
356: otherwise:
357: debug("Picked a bad kind of object");
358: wait_for(' ');
359: #endif
360: }
361: return cur;
362: }
363:
364: /*
365: * pick_one:
366: * Pick an item out of a list of nitems possible magic items
367: */
368: int
369: pick_one(struct magic_item *magic, int nitems)
370: {
371: register struct magic_item *end;
372: register int i;
373: register struct magic_item *start;
374:
375: start = magic;
376: for (end = &magic[nitems], i = rnd(100); magic < end; magic++)
377: if (i < magic->mi_prob)
378: break;
379: if (magic == end)
380: {
381: #ifdef WIZARD
382: if (wizard)
383: {
384: msg("bad pick_one: %d from %d items", i, nitems);
385: for (magic = start; magic < end; magic++)
386: msg("%s: %d%%", magic->mi_name, magic->mi_prob);
387: }
388: #endif
389: magic = start;
390: }
391: return magic - start;
392: }
393:
394: /*
395: * discovered:
396: * list what the player has discovered in this game of a certain type
397: */
398: static int line_cnt = 0;
399:
400: static bool newpage = FALSE;
401:
402: static char *lastfmt, *lastarg;
403:
404: void
405: discovered(void)
406: {
407: register char ch;
408: register bool disc_list;
409:
410: do {
411: disc_list = FALSE;
412: if (!terse)
413: addmsg("for ");
414: addmsg("what type");
415: if (!terse)
416: addmsg(" of object do you want a list");
417: msg("? (* for all)");
418: ch = readchar();
419: switch (ch)
420: {
421: case ESCAPE:
422: msg("");
423: return;
424: case POTION:
425: case SCROLL:
426: case RING:
427: case STICK:
428: case '*':
429: disc_list = TRUE;
430: break;
431: default:
432: if (terse)
433: msg("Not a type");
434: else
435: msg("Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK);
436: }
437: } while (!disc_list);
438: if (ch == '*')
439: {
440: print_disc(POTION);
441: add_line("", NULL);
442: print_disc(SCROLL);
443: add_line("", NULL);
444: print_disc(RING);
445: add_line("", NULL);
446: print_disc(STICK);
447: end_line();
448: }
449: else
450: {
451: print_disc(ch);
452: end_line();
453: }
454: }
455:
456: /*
457: * print_disc:
458: * Print what we've discovered of type 'type'
459: */
460:
461: #define MAX(a,b,c,d) (a > b ? (a > c ? (a > d ? a : d) : (c > d ? c : d)) : (b > c ? (b > d ? b : d) : (c > d ? c : d)))
462:
463: void
464: print_disc(char type)
465: {
466: register bool *know = NULL;
467: register char **guess = NULL;
468: register int i, maxnum = 0, num_found;
469: static THING obj;
470: static short order[MAX(MAXSCROLLS, MAXPOTIONS, MAXRINGS, MAXSTICKS)];
471:
472: switch (type)
473: {
474: case SCROLL:
475: maxnum = MAXSCROLLS;
476: know = s_know;
477: guess = s_guess;
478: break;
479: case POTION:
480: maxnum = MAXPOTIONS;
481: know = p_know;
482: guess = p_guess;
483: break;
484: case RING:
485: maxnum = MAXRINGS;
486: know = r_know;
487: guess = r_guess;
488: break;
489: case STICK:
490: maxnum = MAXSTICKS;
491: know = ws_know;
492: guess = ws_guess;
493: break;
494: }
495: set_order(order, maxnum);
496: obj.o_count = 1;
497: obj.o_flags = 0;
498: num_found = 0;
499: for (i = 0; i < maxnum; i++)
500: if (know[order[i]] || guess[order[i]])
501: {
502: obj.o_type = type;
503: obj.o_which = order[i];
504: add_line("%s", inv_name(&obj, FALSE));
505: num_found++;
506: }
507: if (num_found == 0)
508: add_line(nothing(type), NULL);
509: }
510:
511: /*
512: * set_order:
513: * Set up order for list
514: */
515: void
516: set_order(short *order, int numthings)
517: {
518: register int i, r, t;
519:
520: for (i = 0; i< numthings; i++)
521: order[i] = i;
522:
523: for (i = numthings; i > 0; i--)
524: {
525: r = rnd(i);
526: t = order[i - 1];
527: order[i - 1] = order[r];
528: order[r] = t;
529: }
530: }
531:
532: /*
533: * add_line:
534: * Add a line to the list of discoveries
535: */
536: void
537: add_line(char *fmt, char *arg)
538: {
539: if (line_cnt == 0)
540: {
541: wclear(hw);
542: if (slow_invent)
543: mpos = 0;
544: }
545: if (slow_invent)
546: {
547: if (fmt != NULL && *fmt != '\0')
548: msg(fmt, arg);
549: line_cnt++;
550: }
551: else
552: {
553: if (line_cnt >= LINES - 1 || fmt == NULL)
554: {
555: mvwaddstr(hw, LINES - 1, 0, "--Press space to continue--");
556: wrefresh(hw);
557: w_wait_for(hw,' ');
558: clearok(curscr, TRUE);
559: wclear(hw);
560: touchwin(stdscr);
561: newpage = TRUE;
562: line_cnt = 0;
563: }
564: if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0'))
565: {
566: mvwprintw(hw, line_cnt++, 0, fmt, arg);
567: lastfmt = fmt;
568: lastarg = arg;
569: }
570: }
571: }
572:
573: /*
574: * end_line:
575: * End the list of lines
576: */
577: void
578: end_line(void)
579: {
580: if (!slow_invent)
581: {
582: if (line_cnt == 1 && !newpage)
583: {
584: mpos = 0;
585: msg(lastfmt, lastarg);
586: }
587: else
588: {
589: add_line(NULL, NULL);
590: msg("");
591: }
592: }
593: line_cnt = 0;
594: newpage = FALSE;
595: }
596:
597: /*
598: * nothing:
599: * Set up prbuf so that message for "nothing found" is there
600: */
601: char *
602: nothing(char type)
603: {
604: register char *sp, *tystr = NULL;
605:
606: if (terse)
607: sprintf(prbuf, "Nothing");
608: else
609: sprintf(prbuf, "Haven't discovered anything");
610: if (type != '*')
611: {
612: sp = &prbuf[strlen(prbuf)];
613: switch (type)
614: {
615: case POTION: tystr = "potion";
616: when SCROLL: tystr = "scroll";
617: when RING: tystr = "ring";
618: when STICK: tystr = "stick";
619: }
620: sprintf(sp, " about any %ss", tystr);
621: }
622: return prbuf;
623: }
CVSweb