Annotation of early-roguelike/rogue4/things.c, Revision 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