Annotation of early-roguelike/rogue4/pack.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * Routines to deal with the pack
! 3: *
! 4: * @(#)pack.c 4.15 (Berkeley) 4/6/82
! 5: *
! 6: * Rogue: Exploring the Dungeons of Doom
! 7: * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
! 8: * All rights reserved.
! 9: *
! 10: * See the file LICENSE.TXT for full copyright and licensing information.
! 11: */
! 12:
! 13: #include <curses.h>
! 14: #include <ctype.h>
! 15: #include "rogue.h"
! 16:
! 17: void money(int value);
! 18:
! 19: /*
! 20: * update_mdest:
! 21: * Called after picking up an object, before discarding it.
! 22: * If this was the object of something's desire, that monster will
! 23: * get mad and run at the hero
! 24: */
! 25: void
! 26: update_mdest(THING *obj)
! 27: {
! 28: register THING *mp;
! 29:
! 30: for (mp = mlist; mp != NULL; mp = next(mp))
! 31: if (mp->t_dest == &obj->o_pos)
! 32: mp->t_dest = &hero;
! 33: }
! 34:
! 35: /*
! 36: * add_pack:
! 37: * Pick up an object and add it to the pack. If the argument is
! 38: * non-null use it as the linked_list pointer instead of gettting
! 39: * it off the ground.
! 40: */
! 41: void
! 42: add_pack(THING *obj, bool silent)
! 43: {
! 44: register THING *op, *lp = NULL;
! 45: register bool exact, from_floor;
! 46: register char floor;
! 47: int discarded = 0;
! 48:
! 49: if (obj == NULL)
! 50: {
! 51: from_floor = TRUE;
! 52: if ((obj = find_obj(hero.y, hero.x)) == NULL)
! 53: return;
! 54: }
! 55: else
! 56: from_floor = FALSE;
! 57: /*
! 58: * Link it into the pack. Search the pack for a object of similar type
! 59: * if there isn't one, stuff it at the beginning, if there is, look for one
! 60: * that is exactly the same and just increment the count if there is.
! 61: * it that. Food is always put at the beginning for ease of access, but
! 62: * is not ordered so that you can't tell good food from bad. First check
! 63: * to see if there is something in thr same group and if there is then
! 64: * increment the count.
! 65: */
! 66: /* floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; */
! 67: if (proom) floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
! 68: else floor = FLOOR;
! 69: if (obj->o_group)
! 70: {
! 71: for (op = pack; op != NULL; op = next(op))
! 72: {
! 73: if (op->o_group == obj->o_group)
! 74: {
! 75: /*
! 76: * Put it in the pack and notify the user
! 77: */
! 78: op->o_count++;
! 79: if (from_floor)
! 80: {
! 81: detach(lvl_obj, obj);
! 82: mvaddch(hero.y, hero.x, floor);
! 83: chat(hero.y, hero.x) = floor;
! 84: }
! 85: update_mdest(obj);
! 86: discard(obj);
! 87: obj = op;
! 88: discarded = 1;
! 89: goto picked_up;
! 90: }
! 91: }
! 92: }
! 93: /*
! 94: * Check if there is room
! 95: */
! 96: if (inpack == MAXPACK-1)
! 97: {
! 98: msg("you can't carry anything else");
! 99: return;
! 100: }
! 101: /*
! 102: * Check for and deal with scare monster scrolls
! 103: */
! 104: if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
! 105: if (obj->o_flags & ISFOUND)
! 106: {
! 107: detach(lvl_obj, obj);
! 108: mvaddch(hero.y, hero.x, floor);
! 109: chat(hero.y, hero.x) = floor;
! 110: msg("the scroll turns to dust as you pick it up");
! 111: return;
! 112: }
! 113: else
! 114: obj->o_flags |= ISFOUND;
! 115:
! 116: inpack++;
! 117: if (from_floor)
! 118: {
! 119: detach(lvl_obj, obj);
! 120: mvaddch(hero.y, hero.x, floor);
! 121: chat(hero.y, hero.x) = floor;
! 122: }
! 123: /*
! 124: * Search for an object of the same type
! 125: */
! 126: exact = FALSE;
! 127: for (op = pack; op != NULL; op = next(op))
! 128: if (obj->o_type == op->o_type)
! 129: break;
! 130: if (op == NULL)
! 131: {
! 132: /*
! 133: * Put it at the end of the pack since it is a new type
! 134: */
! 135: for (op = pack; op != NULL; op = next(op))
! 136: {
! 137: if (op->o_type != FOOD)
! 138: break;
! 139: lp = op;
! 140: }
! 141: }
! 142: else
! 143: {
! 144: /*
! 145: * Search for an object which is exactly the same
! 146: */
! 147: while (op->o_type == obj->o_type)
! 148: {
! 149: if (op->o_which == obj->o_which)
! 150: {
! 151: exact = TRUE;
! 152: break;
! 153: }
! 154: lp = op;
! 155: if ((op = next(op)) == NULL)
! 156: break;
! 157: }
! 158: }
! 159: if (op == NULL)
! 160: {
! 161: /*
! 162: * Didn't find an exact match, just stick it here
! 163: */
! 164: if (pack == NULL)
! 165: pack = obj;
! 166: else
! 167: {
! 168: lp->l_next = obj;
! 169: obj->l_prev = lp;
! 170: obj->l_next = NULL;
! 171: }
! 172: }
! 173: else
! 174: {
! 175: /*
! 176: * If we found an exact match. If it is a potion, food, or a
! 177: * scroll, increase the count, otherwise put it with its clones.
! 178: */
! 179: if (exact && ISMULT(obj->o_type))
! 180: {
! 181: op->o_count++;
! 182: update_mdest(obj);
! 183: discard(obj);
! 184: obj = op;
! 185: discarded = 1;
! 186: goto picked_up;
! 187: }
! 188: if ((obj->l_prev = prev(op)) != NULL)
! 189: obj->l_prev->l_next = obj;
! 190: else
! 191: pack = obj;
! 192: obj->l_next = op;
! 193: op->l_prev = obj;
! 194: }
! 195: picked_up:
! 196: /*
! 197: * If this was the object of something's desire, that monster will
! 198: * get mad and run at the hero
! 199: */
! 200: if (!discarded)
! 201: update_mdest(obj);
! 202:
! 203: if (obj->o_type == AMULET)
! 204: amulet = TRUE;
! 205: /*
! 206: * Notify the user
! 207: */
! 208: if (!silent)
! 209: {
! 210: if (!terse)
! 211: addmsg("you now have ");
! 212: msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
! 213: }
! 214: }
! 215:
! 216: /*
! 217: * inventory:
! 218: * List what is in the pack
! 219: */
! 220: bool
! 221: inventory(THING *list, int type)
! 222: {
! 223: register char ch;
! 224: register int n_objs;
! 225: char inv_temp[MAXSTR];
! 226:
! 227: n_objs = 0;
! 228: for (ch = 'a'; list != NULL; ch++, list = next(list))
! 229: {
! 230: if (type && type != list->o_type && !(type == CALLABLE &&
! 231: (list->o_type == SCROLL || list->o_type == POTION ||
! 232: list->o_type == RING || list->o_type == STICK)))
! 233: continue;
! 234: n_objs++;
! 235: sprintf(inv_temp, "%c) %%s", ch);
! 236: add_line(inv_temp, inv_name(list, FALSE));
! 237: }
! 238: if (n_objs == 0)
! 239: {
! 240: if (terse)
! 241: msg(type == 0 ? "empty handed" :
! 242: "nothing appropriate");
! 243: else
! 244: msg(type == 0 ? "you are empty handed" :
! 245: "you don't have anything appropriate");
! 246: return FALSE;
! 247: }
! 248: end_line();
! 249: return TRUE;
! 250: }
! 251:
! 252: /*
! 253: * pick_up:
! 254: * Add something to characters pack.
! 255: */
! 256: void
! 257: pick_up(char ch)
! 258: {
! 259: register THING *obj, *mp;
! 260:
! 261: switch (ch)
! 262: {
! 263: case GOLD:
! 264: if ((obj = find_obj(hero.y, hero.x)) == NULL)
! 265: return;
! 266: money(obj->o_goldval);
! 267: detach(lvl_obj, obj);
! 268: update_mdest(obj);
! 269: discard(obj);
! 270: proom->r_goldval = 0;
! 271: break;
! 272: default:
! 273: #ifdef WIZARD
! 274: debug("Where did you pick a '%s' up???", unctrol(ch));
! 275: #endif
! 276: case ARMOR:
! 277: case POTION:
! 278: case FOOD:
! 279: case WEAPON:
! 280: case SCROLL:
! 281: case AMULET:
! 282: case RING:
! 283: case STICK:
! 284: add_pack(NULL, FALSE);
! 285: break;
! 286: }
! 287: }
! 288:
! 289: /*
! 290: * picky_inven:
! 291: * Allow player to inventory a single item
! 292: */
! 293: void
! 294: picky_inven(void)
! 295: {
! 296: register THING *obj;
! 297: register char ch, mch;
! 298:
! 299: if (pack == NULL)
! 300: msg("you aren't carrying anything");
! 301: else if (next(pack) == NULL)
! 302: msg("a) %s", inv_name(pack, FALSE));
! 303: else
! 304: {
! 305: msg(terse ? "item: " : "which item do you wish to inventory: ");
! 306: mpos = 0;
! 307: if ((mch = readchar()) == ESCAPE)
! 308: {
! 309: msg("");
! 310: return;
! 311: }
! 312: for (ch = 'a', obj = pack; obj != NULL; obj = next(obj), ch++)
! 313: if (ch == mch)
! 314: {
! 315: msg("%c) %s",ch,inv_name(obj, FALSE));
! 316: return;
! 317: }
! 318: if (!terse)
! 319: msg("'%s' not in pack", unctrol(mch));
! 320: msg("range is 'a' to '%c'", --ch);
! 321: }
! 322: }
! 323:
! 324: /*
! 325: * get_item:
! 326: * Pick something out of a pack for a purpose
! 327: */
! 328: THING *
! 329: get_item(char *purpose, int type)
! 330: {
! 331: register THING *obj;
! 332: register char ch, och;
! 333:
! 334: if (pack == NULL)
! 335: msg("you aren't carrying anything");
! 336: else
! 337: {
! 338: for (;;)
! 339: {
! 340: if (!terse)
! 341: addmsg("which object do you want to ");
! 342: addmsg(purpose);
! 343: if (terse)
! 344: addmsg(" what");
! 345: msg("? (* for list): ");
! 346: ch = readchar();
! 347: mpos = 0;
! 348: /*
! 349: * Give the poor player a chance to abort the command
! 350: */
! 351: if (ch == ESCAPE || ch == CTRL('G'))
! 352: {
! 353: after = FALSE;
! 354: msg("");
! 355: return NULL;
! 356: }
! 357: if (ch == '*')
! 358: {
! 359: mpos = 0;
! 360: if (inventory(pack, type) == 0)
! 361: {
! 362: after = FALSE;
! 363: return NULL;
! 364: }
! 365: continue;
! 366: }
! 367: for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++)
! 368: if (ch == och)
! 369: break;
! 370: if (obj == NULL)
! 371: {
! 372: msg("please specify a letter between 'a' and '%c'", och-1);
! 373: continue;
! 374: }
! 375: else
! 376: return obj;
! 377: }
! 378: }
! 379: return NULL;
! 380: }
! 381:
! 382: /*
! 383: * pack_char:
! 384: * Return which character would address a pack object
! 385: */
! 386: char
! 387: pack_char(THING *obj)
! 388: {
! 389: register THING *item;
! 390: register char c;
! 391:
! 392: c = 'a';
! 393: for (item = pack; item != NULL; item = next(item))
! 394: if (item == obj)
! 395: return c;
! 396: else
! 397: c++;
! 398: return '?';
! 399: }
! 400:
! 401: /*
! 402: * money:
! 403: * Add or subtract gold from the pack
! 404: */
! 405: void
! 406: money(int value)
! 407: {
! 408: register char floor;
! 409:
! 410: floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
! 411: purse += value;
! 412: mvaddch(hero.y, hero.x, floor);
! 413: chat(hero.y, hero.x) = floor;
! 414: if (value > 0)
! 415: {
! 416: if (!terse)
! 417: addmsg("you found ");
! 418: msg("%d gold pieces", value);
! 419: }
! 420: }
CVSweb