/* * Routines to deal with the pack * * @(#)pack.c 4.15 (Berkeley) 4/6/82 * * Rogue: Exploring the Dungeons of Doom * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman * All rights reserved. * * See the file LICENSE.TXT for full copyright and licensing information. */ #include #include #include "rogue.h" void money(int value); /* * update_mdest: * Called after picking up an object, before discarding it. * If this was the object of something's desire, that monster will * get mad and run at the hero */ void update_mdest(THING *obj) { register THING *mp; for (mp = mlist; mp != NULL; mp = next(mp)) if (mp->t_dest == &obj->o_pos) mp->t_dest = &hero; } /* * add_pack: * Pick up an object and add it to the pack. If the argument is * non-null use it as the linked_list pointer instead of gettting * it off the ground. */ void add_pack(THING *obj, bool silent) { register THING *op, *lp = NULL; register bool exact, from_floor; register char floor; int discarded = 0; if (obj == NULL) { from_floor = TRUE; if ((obj = find_obj(hero.y, hero.x)) == NULL) return; } else from_floor = FALSE; /* * Link it into the pack. Search the pack for a object of similar type * if there isn't one, stuff it at the beginning, if there is, look for one * that is exactly the same and just increment the count if there is. * it that. Food is always put at the beginning for ease of access, but * is not ordered so that you can't tell good food from bad. First check * to see if there is something in thr same group and if there is then * increment the count. */ /* floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; */ if (proom) floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; else floor = FLOOR; if (obj->o_group) { for (op = pack; op != NULL; op = next(op)) { if (op->o_group == obj->o_group) { /* * Put it in the pack and notify the user */ op->o_count++; if (from_floor) { detach(lvl_obj, obj); mvaddch(hero.y, hero.x, floor); chat(hero.y, hero.x) = floor; } update_mdest(obj); discard(obj); obj = op; discarded = 1; goto picked_up; } } } /* * Check if there is room */ if (inpack == MAXPACK-1) { msg("you can't carry anything else"); return; } /* * Check for and deal with scare monster scrolls */ if (obj->o_type == SCROLL && obj->o_which == S_SCARE) if (obj->o_flags & ISFOUND) { detach(lvl_obj, obj); mvaddch(hero.y, hero.x, floor); chat(hero.y, hero.x) = floor; msg("the scroll turns to dust as you pick it up"); return; } else obj->o_flags |= ISFOUND; inpack++; if (from_floor) { detach(lvl_obj, obj); mvaddch(hero.y, hero.x, floor); chat(hero.y, hero.x) = floor; } /* * Search for an object of the same type */ exact = FALSE; for (op = pack; op != NULL; op = next(op)) if (obj->o_type == op->o_type) break; if (op == NULL) { /* * Put it at the end of the pack since it is a new type */ for (op = pack; op != NULL; op = next(op)) { if (op->o_type != FOOD) break; lp = op; } } else { /* * Search for an object which is exactly the same */ while (op->o_type == obj->o_type) { if (op->o_which == obj->o_which) { exact = TRUE; break; } lp = op; if ((op = next(op)) == NULL) break; } } if (op == NULL) { /* * Didn't find an exact match, just stick it here */ if (pack == NULL) pack = obj; else { lp->l_next = obj; obj->l_prev = lp; obj->l_next = NULL; } } else { /* * If we found an exact match. If it is a potion, food, or a * scroll, increase the count, otherwise put it with its clones. */ if (exact && ISMULT(obj->o_type)) { op->o_count++; update_mdest(obj); discard(obj); obj = op; discarded = 1; goto picked_up; } if ((obj->l_prev = prev(op)) != NULL) obj->l_prev->l_next = obj; else pack = obj; obj->l_next = op; op->l_prev = obj; } picked_up: /* * If this was the object of something's desire, that monster will * get mad and run at the hero */ if (!discarded) update_mdest(obj); if (obj->o_type == AMULET) amulet = TRUE; /* * Notify the user */ if (!silent) { if (!terse) addmsg("you now have "); msg("%s (%c)", inv_name(obj, !terse), pack_char(obj)); } } /* * inventory: * List what is in the pack */ bool inventory(THING *list, int type) { register char ch; register int n_objs; char inv_temp[MAXSTR]; n_objs = 0; for (ch = 'a'; list != NULL; ch++, list = next(list)) { if (type && type != list->o_type && !(type == CALLABLE && (list->o_type == SCROLL || list->o_type == POTION || list->o_type == RING || list->o_type == STICK))) continue; n_objs++; sprintf(inv_temp, "%c) %%s", ch); add_line(inv_temp, inv_name(list, FALSE)); } if (n_objs == 0) { if (terse) msg(type == 0 ? "empty handed" : "nothing appropriate"); else msg(type == 0 ? "you are empty handed" : "you don't have anything appropriate"); return FALSE; } end_line(); return TRUE; } /* * pick_up: * Add something to characters pack. */ void pick_up(char ch) { register THING *obj, *mp; switch (ch) { case GOLD: if ((obj = find_obj(hero.y, hero.x)) == NULL) return; money(obj->o_goldval); detach(lvl_obj, obj); update_mdest(obj); discard(obj); proom->r_goldval = 0; break; default: #ifdef WIZARD debug("Where did you pick a '%s' up???", unctrol(ch)); #endif case ARMOR: case POTION: case FOOD: case WEAPON: case SCROLL: case AMULET: case RING: case STICK: add_pack(NULL, FALSE); break; } } /* * picky_inven: * Allow player to inventory a single item */ void picky_inven(void) { register THING *obj; register char ch, mch; if (pack == NULL) msg("you aren't carrying anything"); else if (next(pack) == NULL) msg("a) %s", inv_name(pack, FALSE)); else { msg(terse ? "item: " : "which item do you wish to inventory: "); mpos = 0; if ((mch = readchar()) == ESCAPE) { msg(""); return; } for (ch = 'a', obj = pack; obj != NULL; obj = next(obj), ch++) if (ch == mch) { msg("%c) %s",ch,inv_name(obj, FALSE)); return; } if (!terse) msg("'%s' not in pack", unctrol(mch)); msg("range is 'a' to '%c'", --ch); } } /* * get_item: * Pick something out of a pack for a purpose */ THING * get_item(char *purpose, int type) { register THING *obj; register char ch, och; if (pack == NULL) msg("you aren't carrying anything"); else { for (;;) { if (!terse) addmsg("which object do you want to "); addmsg(purpose); if (terse) addmsg(" what"); msg("? (* for list): "); ch = readchar(); mpos = 0; /* * Give the poor player a chance to abort the command */ if (ch == ESCAPE || ch == CTRL('G')) { after = FALSE; msg(""); return NULL; } if (ch == '*') { mpos = 0; if (inventory(pack, type) == 0) { after = FALSE; return NULL; } continue; } for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++) if (ch == och) break; if (obj == NULL) { msg("please specify a letter between 'a' and '%c'", och-1); continue; } else return obj; } } return NULL; } /* * pack_char: * Return which character would address a pack object */ char pack_char(THING *obj) { register THING *item; register char c; c = 'a'; for (item = pack; item != NULL; item = next(item)) if (item == obj) return c; else c++; return '?'; } /* * money: * Add or subtract gold from the pack */ void money(int value) { register char floor; floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; purse += value; mvaddch(hero.y, hero.x, floor); chat(hero.y, hero.x) = floor; if (value > 0) { if (!terse) addmsg("you found "); msg("%d gold pieces", value); } }