Annotation of early-roguelike/rogue5/pack.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * Routines to deal with the pack
! 3: *
! 4: * @(#)pack.c 4.40 (Berkeley) 02/05/99
! 5: *
! 6: * Rogue: Exploring the Dungeons of Doom
! 7: * Copyright (C) 1980-1983, 1985, 1999 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 <string.h>
! 14: #include <curses.h>
! 15: #include <ctype.h>
! 16: #include "rogue.h"
! 17:
! 18: /*
! 19: * update_mdest:
! 20: * Called after picking up an object, before discarding it.
! 21: * If this was the object of something's desire, that monster will
! 22: * get mad and run at the hero
! 23: */
! 24: void
! 25: update_mdest(THING *obj)
! 26: {
! 27: register THING *mp;
! 28:
! 29: for (mp = mlist; mp != NULL; mp = next(mp))
! 30: if (mp->t_dest == &obj->o_pos)
! 31: mp->t_dest = &hero;
! 32: }
! 33:
! 34: /*
! 35: * add_pack:
! 36: * Pick up an object and add it to the pack. If the argument is
! 37: * non-null use it as the linked_list pointer instead of gettting
! 38: * it off the ground.
! 39: */
! 40:
! 41: void
! 42: add_pack(THING *obj, int silent)
! 43: {
! 44: THING *op, *lp;
! 45: int from_floor;
! 46: int discarded = 0;
! 47:
! 48: from_floor = FALSE;
! 49: if (obj == NULL)
! 50: {
! 51: if ((obj = find_obj(hero.y, hero.x)) == NULL)
! 52: return;
! 53: from_floor = TRUE;
! 54: }
! 55:
! 56: /*
! 57: * Check for and deal with scare monster scrolls
! 58: */
! 59: if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
! 60: if (obj->o_flags & ISFOUND)
! 61: {
! 62: detach(lvl_obj, obj);
! 63: mvaddch(hero.y, hero.x, floor_ch());
! 64: chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
! 65: update_mdest(obj);
! 66: discarded = 1;
! 67: discard(obj);
! 68: msg("the scroll turns to dust as you pick it up");
! 69: return;
! 70: }
! 71:
! 72: if (pack == NULL)
! 73: {
! 74: pack = obj;
! 75: obj->o_packch = pack_char();
! 76: inpack++;
! 77: }
! 78: else
! 79: {
! 80: lp = NULL;
! 81: for (op = pack; op != NULL; op = next(op))
! 82: {
! 83: if (op->o_type != obj->o_type)
! 84: lp = op;
! 85: else
! 86: {
! 87: while (op->o_type == obj->o_type && op->o_which != obj->o_which)
! 88: {
! 89: lp = op;
! 90: if (next(op) == NULL)
! 91: break;
! 92: else
! 93: op = next(op);
! 94: }
! 95: if (op->o_type == obj->o_type && op->o_which == obj->o_which)
! 96: {
! 97: if (ISMULT(op->o_type))
! 98: {
! 99: if (!pack_room(from_floor, obj))
! 100: return;
! 101: op->o_count++;
! 102: dump_it:
! 103: update_mdest(obj);
! 104: discard(obj);
! 105: obj = op;
! 106: discarded = 1;
! 107: lp = NULL;
! 108: goto out;
! 109: }
! 110: else if (obj->o_group)
! 111: {
! 112: lp = op;
! 113: while (op->o_type == obj->o_type
! 114: && op->o_which == obj->o_which
! 115: && op->o_group != obj->o_group)
! 116: {
! 117: lp = op;
! 118: if (next(op) == NULL)
! 119: break;
! 120: else
! 121: op = next(op);
! 122: }
! 123: if (op->o_type == obj->o_type
! 124: && op->o_which == obj->o_which
! 125: && op->o_group == obj->o_group)
! 126: {
! 127: op->o_count += obj->o_count;
! 128: inpack--;
! 129: if (!pack_room(from_floor, obj))
! 130: return;
! 131: goto dump_it;
! 132: }
! 133: }
! 134: else
! 135: lp = op;
! 136: }
! 137: out:
! 138: break;
! 139: }
! 140: }
! 141:
! 142: if (lp != NULL)
! 143: {
! 144: if (!pack_room(from_floor, obj))
! 145: return;
! 146: else
! 147: {
! 148: obj->o_packch = pack_char();
! 149: next(obj) = next(lp);
! 150: prev(obj) = lp;
! 151: if (next(lp) != NULL)
! 152: prev(next(lp)) = obj;
! 153: next(lp) = obj;
! 154: }
! 155: }
! 156: }
! 157:
! 158: obj->o_flags |= ISFOUND;
! 159:
! 160: /*
! 161: * If this was the object of something's desire, that monster will
! 162: * get mad and run at the hero.
! 163: */
! 164: if (!discarded)
! 165: update_mdest(obj);
! 166:
! 167: if (obj->o_type == AMULET)
! 168: amulet = TRUE;
! 169: /*
! 170: * Notify the user
! 171: */
! 172: if (!silent)
! 173: {
! 174: if (!terse)
! 175: addmsg("you now have ");
! 176: msg("%s (%c)", inv_name(obj, !terse), obj->o_packch);
! 177: }
! 178: }
! 179:
! 180: /*
! 181: * pack_room:
! 182: * See if there's room in the pack. If not, print out an
! 183: * appropriate message
! 184: */
! 185: int
! 186: pack_room(int from_floor, THING *obj)
! 187: {
! 188: if (++inpack > MAXPACK)
! 189: {
! 190: if (!terse)
! 191: addmsg("there's ");
! 192: addmsg("no room");
! 193: if (!terse)
! 194: addmsg(" in your pack");
! 195: endmsg();
! 196: if (from_floor)
! 197: move_msg(obj);
! 198: inpack = MAXPACK;
! 199: return FALSE;
! 200: }
! 201:
! 202: if (from_floor)
! 203: {
! 204: detach(lvl_obj, obj);
! 205: mvaddch(hero.y, hero.x, floor_ch());
! 206: chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
! 207: }
! 208:
! 209: return TRUE;
! 210: }
! 211:
! 212: /*
! 213: * leave_pack:
! 214: * take an item out of the pack
! 215: */
! 216: THING *
! 217: leave_pack(THING *obj, int newobj, int all)
! 218: {
! 219: THING *nobj;
! 220:
! 221: inpack--;
! 222: nobj = obj;
! 223: if (obj->o_count > 1 && !all)
! 224: {
! 225: last_pick = obj;
! 226: obj->o_count--;
! 227: if (obj->o_group)
! 228: inpack++;
! 229: if (newobj)
! 230: {
! 231: nobj = new_item();
! 232: *nobj = *obj;
! 233: next(nobj) = NULL;
! 234: prev(nobj) = NULL;
! 235: nobj->o_count = 1;
! 236: }
! 237: }
! 238: else
! 239: {
! 240: last_pick = NULL;
! 241: pack_used[obj->o_packch - 'a'] = FALSE;
! 242: detach(pack, obj);
! 243: }
! 244: return nobj;
! 245: }
! 246:
! 247: /*
! 248: * pack_char:
! 249: * Return the next unused pack character.
! 250: */
! 251: int
! 252: pack_char(void)
! 253: {
! 254: int *bp;
! 255:
! 256: for (bp = pack_used; *bp; bp++)
! 257: continue;
! 258: *bp = TRUE;
! 259: return ((int)(bp - pack_used) + 'a');
! 260: }
! 261:
! 262: /*
! 263: * inventory:
! 264: * List what is in the pack. Return TRUE if there is something of
! 265: * the given type.
! 266: */
! 267: int
! 268: inventory(const THING *list, int type)
! 269: {
! 270: static char inv_temp[MAXSTR];
! 271:
! 272: n_objs = 0;
! 273: for (; list != NULL; list = next(list))
! 274: {
! 275: if (type && type != list->o_type && !(type == CALLABLE &&
! 276: list->o_type != FOOD && list->o_type != AMULET) &&
! 277: !(type == R_OR_S && (list->o_type == RING || list->o_type == STICK)))
! 278: continue;
! 279: n_objs++;
! 280: #ifdef MASTER
! 281: if (!list->o_packch)
! 282: strcpy(inv_temp, "%s");
! 283: else
! 284: #endif
! 285: sprintf(inv_temp, "%c) %%s", list->o_packch);
! 286: msg_esc = TRUE;
! 287: if (add_line(inv_temp, inv_name(list, FALSE)) == ESCAPE)
! 288: {
! 289: msg_esc = FALSE;
! 290: msg("");
! 291: return TRUE;
! 292: }
! 293: msg_esc = FALSE;
! 294: }
! 295: if (n_objs == 0)
! 296: {
! 297: if (terse)
! 298: msg(type == 0 ? "empty handed" :
! 299: "nothing appropriate");
! 300: else
! 301: msg(type == 0 ? "you are empty handed" :
! 302: "you don't have anything appropriate");
! 303: return FALSE;
! 304: }
! 305: end_line();
! 306: return TRUE;
! 307: }
! 308:
! 309: /*
! 310: * pick_up:
! 311: * Add something to characters pack.
! 312: */
! 313:
! 314: void
! 315: pick_up(int ch)
! 316: {
! 317: THING *obj;
! 318:
! 319: if (on(player, ISLEVIT))
! 320: return;
! 321:
! 322: obj = find_obj(hero.y, hero.x);
! 323: if (move_on)
! 324: move_msg(obj);
! 325: else
! 326: switch (ch)
! 327: {
! 328: case GOLD:
! 329: if (obj == NULL)
! 330: return;
! 331: money(obj->o_goldval);
! 332: detach(lvl_obj, obj);
! 333: update_mdest(obj);
! 334: discard(obj);
! 335: proom->r_goldval = 0;
! 336: break;
! 337: default:
! 338: #ifdef MASTER
! 339: debug("Where did you pick a '%s' up???", unctrl(ch));
! 340: #endif
! 341: case ARMOR:
! 342: case POTION:
! 343: case FOOD:
! 344: case WEAPON:
! 345: case SCROLL:
! 346: case AMULET:
! 347: case RING:
! 348: case STICK:
! 349: add_pack(NULL, FALSE);
! 350: break;
! 351: }
! 352: }
! 353:
! 354: /*
! 355: * move_msg:
! 356: * Print out the message if you are just moving onto an object
! 357: */
! 358:
! 359: void
! 360: move_msg(const THING *obj)
! 361: {
! 362: if (!terse)
! 363: addmsg("you ");
! 364: msg("moved onto %s", inv_name(obj, TRUE));
! 365: }
! 366:
! 367: /*
! 368: * picky_inven:
! 369: * Allow player to inventory a single item
! 370: */
! 371:
! 372: void
! 373: picky_inven(void)
! 374: {
! 375: THING *obj;
! 376: int mch;
! 377:
! 378: if (pack == NULL)
! 379: msg("you aren't carrying anything");
! 380: else if (next(pack) == NULL)
! 381: msg("a) %s", inv_name(pack, FALSE));
! 382: else
! 383: {
! 384: msg(terse ? "item: " : "which item do you wish to inventory: ");
! 385: mpos = 0;
! 386: if ((mch = readchar()) == ESCAPE)
! 387: {
! 388: msg("");
! 389: return;
! 390: }
! 391: for (obj = pack; obj != NULL; obj = next(obj))
! 392: if (mch == obj->o_packch)
! 393: {
! 394: msg("%c) %s", mch, inv_name(obj, FALSE));
! 395: return;
! 396: }
! 397: msg("'%s' not in pack", unctrl(mch));
! 398: }
! 399: }
! 400:
! 401: /*
! 402: * get_item:
! 403: * Pick something out of a pack for a purpose
! 404: */
! 405: THING *
! 406: get_item(const char *purpose, int type)
! 407: {
! 408: THING *obj;
! 409: int ch;
! 410:
! 411: if (pack == NULL)
! 412: msg("you aren't carrying anything");
! 413: else if (again)
! 414: if (last_pick)
! 415: return last_pick;
! 416: else
! 417: msg("you ran out");
! 418: else
! 419: {
! 420: for (;;)
! 421: {
! 422: if (!terse)
! 423: addmsg("which object do you want to ");
! 424: addmsg(purpose);
! 425: if (terse)
! 426: addmsg(" what");
! 427: msg("? (* for list): ");
! 428: ch = readchar();
! 429: mpos = 0;
! 430: /*
! 431: * Give the poor player a chance to abort the command
! 432: */
! 433: if (ch == ESCAPE)
! 434: {
! 435: reset_last();
! 436: after = FALSE;
! 437: msg("");
! 438: return NULL;
! 439: }
! 440: n_objs = 1; /* normal case: person types one char */
! 441: if (ch == '*')
! 442: {
! 443: mpos = 0;
! 444: if (inventory(pack, type) == 0)
! 445: {
! 446: after = FALSE;
! 447: return NULL;
! 448: }
! 449: continue;
! 450: }
! 451: for (obj = pack; obj != NULL; obj = next(obj))
! 452: if (obj->o_packch == ch)
! 453: break;
! 454: if (obj == NULL)
! 455: {
! 456: msg("'%s' is not a valid item",unctrl(ch));
! 457: continue;
! 458: }
! 459: else {
! 460: msg("");
! 461: return obj;
! 462: }
! 463: }
! 464: }
! 465: return NULL;
! 466: }
! 467:
! 468: /*
! 469: * money:
! 470: * Add or subtract gold from the pack
! 471: */
! 472:
! 473: void
! 474: money(int value)
! 475: {
! 476: purse += value;
! 477: mvaddch(hero.y, hero.x, floor_ch());
! 478: chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
! 479: if (value > 0)
! 480: {
! 481: if (!terse)
! 482: addmsg("you found ");
! 483: msg("%d gold pieces", value);
! 484: }
! 485: }
! 486:
! 487: /*
! 488: * floor_ch:
! 489: * Return the appropriate floor character for her room
! 490: */
! 491: int
! 492: floor_ch(void)
! 493: {
! 494: if (proom->r_flags & ISGONE)
! 495: return PASSAGE;
! 496: return (show_floor() ? FLOOR : ' ');
! 497: }
! 498:
! 499: /*
! 500: * floor_at:
! 501: * Return the character at hero's position, taking see_floor
! 502: * into account
! 503: */
! 504: int
! 505: floor_at(void)
! 506: {
! 507: int ch;
! 508:
! 509: ch = chat(hero.y, hero.x);
! 510: if (ch == FLOOR)
! 511: ch = floor_ch();
! 512: return ch;
! 513: }
! 514:
! 515: /*
! 516: * reset_last:
! 517: * Reset the last command when the current one is aborted
! 518: */
! 519:
! 520: void
! 521: reset_last(void)
! 522: {
! 523: last_comm = l_last_comm;
! 524: last_dir = l_last_dir;
! 525: last_pick = l_last_pick;
! 526: }
CVSweb