/* * Routines to deal with the pack * * @(#)pack.c 9.0 (rdk) 7/17/84 * * Super-Rogue * Copyright (C) 1984 Robert D. Kindelberger * All rights reserved. * * Based on "Rogue: Exploring the Dungeons of Doom" * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman * All rights reserved. * * See the file LICENSE.TXT for full copyright and licensing information. */ #include #include "rogue.h" #include "rogue.ext" /* * 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 * getting it off the ground. */ bool add_pack(struct linked_list *item, bool silent) { reg struct linked_list *ip, *lp; reg struct object *obj, *op = NULL; bool from_floor; char delchar; if (player.t_room == NULL) delchar = PASSAGE; else delchar = FLOOR; if (item == NULL) { from_floor = TRUE; if ((item = find_obj(hero.y, hero.x)) == NULL) { mpos = 0; msg("That object must have been an illusion."); mvaddch(hero.y, hero.x, delchar); return FALSE; } /* * Check for scare monster scrolls */ obj = OBJPTR(item); if (obj->o_type == SCROLL && obj->o_which == S_SCARE) { if (o_on(obj,ISFOUND)) { msg("The scroll turns to dust as you pick it up."); detach(lvl_obj, item); discard(item); mvaddch(hero.y, hero.x, delchar); return FALSE; } } } else from_floor = FALSE; obj = OBJPTR(item); /* * See if this guy can carry any more weight */ if (itemweight(obj) + him->s_pack > him->s_carry) { msg("You can't carry that %s.", obj->o_typname); return FALSE; } /* * Check if there is room */ if (packvol + obj->o_vol > V_PACK) { msg("That %s won't fit in your pack.", obj->o_typname); return FALSE; } if (from_floor) { detach(lvl_obj, item); mvaddch(hero.y, hero.x, delchar); } item->l_prev = NULL; item->l_next = NULL; setoflg(obj, ISFOUND); /* * start looking thru pack to find the start of items * with the same type. */ lp = pack; for (ip = pack; ip != NULL; ip = next(ip)) { op = OBJPTR(ip); /* * If we find a matching type then quit. */ if (op->o_type == obj->o_type) break; if (next(ip) != NULL) lp = next(lp); /* update "previous" entry */ } /* * If the pack was empty, just stick the item in it. */ if (pack == NULL) { pack = item; item->l_prev = NULL; } /* * If we looked thru the pack, but could not find an * item of the same type, then stick it at the end, * unless it was food, then put it in front. */ else if (ip == NULL) { if (obj->o_type == FOOD) { /* insert food at front */ item->l_next = pack; pack->l_prev = item; pack = item; item->l_prev = NULL; } else { /* insert other stuff at back */ lp->l_next = item; item->l_prev = lp; } } /* * Here, we found at least one item of the same type. * Look thru these items to see if there is one of the * same group. If so, increment the count and throw the * new item away. If not, stick it at the end of the * items with the same type. Also keep all similar * objects near each other, like all identify scrolls, etc. */ else { struct linked_list **save; while (ip != NULL && op->o_type == obj->o_type) { if (op->o_group == obj->o_group) { if (op->o_flags == obj->o_flags) { op->o_count++; discard(item); item = ip; goto picked_up; } else { goto around; } } if (op->o_which == obj->o_which) { if (obj->o_type == FOOD) ip = next(ip); break; } around: ip = next(ip); if (ip != NULL) { op = OBJPTR(ip); lp = next(lp); } } /* * If inserting into last of group at end of pack, * just tack on the end. */ if (ip == NULL) { lp->l_next = item; item->l_prev = lp; } /* * Insert into the last of a group of objects * not at the end of the pack. */ else { save = &((ip->l_prev)->l_next); item->l_next = ip; item->l_prev = ip->l_prev; ip->l_prev = item; *save = item; } } picked_up: obj = OBJPTR(item); if (!silent) msg("%s (%c)",inv_name(obj,FALSE),pack_char(obj)); if (obj->o_type == AMULET) amulet = TRUE; updpack(); /* new pack weight & volume */ return TRUE; } /* * inventory: * Show what items are in a specific list */ bool inventory(struct linked_list *list, int type) { reg struct linked_list *pc; reg struct object *obj; reg char ch; reg int cnt; if (list == NULL) { /* empty list */ msg(type == 0 ? "Empty handed." : "Nothing appropriate."); return FALSE; } else if (next(list) == NULL) { /* only 1 item in list */ obj = OBJPTR(list); msg("a) %s", inv_name(obj, FALSE)); return TRUE; } cnt = 0; wclear(hw); for (ch = 'a', pc = list; pc != NULL; pc = next(pc), ch = npch(ch)) { obj = OBJPTR(pc); wprintw(hw,"%c) %s\n\r",ch,inv_name(obj, FALSE)); if (++cnt > LINES - 2 && next(pc) != NULL) { dbotline(hw, morestr); cnt = 0; wclear(hw); } } dbotline(hw,spacemsg); restscr(cw); return TRUE; } /* * pick_up: * Add something to characters pack. */ void pick_up(char ch) { nochange = FALSE; switch(ch) { case GOLD: money(); when ARMOR: case POTION: case FOOD: case WEAPON: case SCROLL: case AMULET: case RING: case STICK: add_pack(NULL, FALSE); otherwise: msg("That item is ethereal !!!"); } } /* * picky_inven: * Allow player to inventory a single item */ void picky_inven(void) { reg struct linked_list *item; reg char ch, mch; if (pack == NULL) msg("You aren't carrying anything."); else if (next(pack) == NULL) msg("a) %s", inv_name(OBJPTR(pack), FALSE)); else { msg("Item: "); mpos = 0; if ((mch = readchar()) == ESCAPE) { msg(""); return; } for (ch='a',item=pack; item != NULL; item=next(item),ch=npch(ch)) if (ch == mch) { msg("%c) %s",ch,inv_name(OBJPTR(item), FALSE)); return; } if (ch == 'A') ch = 'z'; else ch -= 1; msg("Range is 'a' to '%c'", ch); } } /* * get_item: * pick something out of a pack for a purpose */ struct linked_list * get_item(char *purpose, int type) { reg struct linked_list *obj, *pit, *savepit = NULL; struct object *pob; int ch, och, anr, cnt; if (pack == NULL) { msg("You aren't carrying anything."); return NULL; } if (type != WEAPON && (type != 0 || next(pack) == NULL)) { /* * see if we have any of the type requested */ pit = pack; anr = 0; for (ch = 'a'; pit != NULL; pit = next(pit), ch = npch(ch)) { pob = OBJPTR(pit); if (type == pob->o_type || type == 0) { ++anr; savepit = pit; /* save in case of only 1 */ } } if (anr == 0) { msg("Nothing to %s",purpose); after = FALSE; return NULL; } else if (anr == 1) { /* only found one of 'em */ do { struct object *opb; opb = OBJPTR(savepit); msg("%s what (* for the item)?",purpose); och = readchar(); if (och == '*') { mpos = 0; msg("%c) %s",pack_char(opb),inv_name(opb,FALSE)); continue; } if (och == ESCAPE) { msg(""); after = FALSE; return NULL; } if (isalpha(och) && och != pack_char(opb)) { mpos = 0; msg("You can't %s that !!", purpose); after = FALSE; return NULL; } } while(!isalpha(och)); mpos = 0; return savepit; /* return this item */ } } for (;;) { msg("%s what? (* for list): ",purpose); ch = readchar(); mpos = 0; if (ch == ESCAPE) { /* abort if escape hit */ after = FALSE; msg(""); /* clear display */ return NULL; } if (ch == '*') { wclear(hw); pit = pack; /* point to pack */ cnt = 0; for (ch='a'; pit != NULL; pit=next(pit), ch=npch(ch)) { pob = OBJPTR(pit); if (type == 0 || type == pob->o_type) { wprintw(hw,"%c) %s\n\r",ch,inv_name(pob,FALSE)); if (++cnt > LINES - 2 && next(pit) != NULL) { cnt = 0; dbotline(hw, morestr); wclear(hw); } } } wmove(hw, LINES - 1,0); wprintw(hw,"%s what? ",purpose); draw(hw); /* write screen */ anr = FALSE; do { ch = readchar(); if (isalpha(ch) || ch == ESCAPE) anr = TRUE; } while(!anr); /* do till we got it right */ restscr(cw); /* redraw orig screen */ if (ch == ESCAPE) { after = FALSE; msg(""); /* clear top line */ return NULL; /* all done if abort */ } /* ch has item to get from pack */ } for (obj=pack,och='a';obj!=NULL;obj=next(obj),och=npch(och)) if (ch == och) break; if (obj == NULL) { if (och == 'A') och = 'z'; else och -= 1; msg("Please specify a letter between 'a' and '%c'",och); continue; } else return obj; } } /* * pack_char: * Get the character of a particular item in the pack */ char pack_char(struct object *obj) { reg struct linked_list *item; reg char c; c = 'a'; for (item = pack; item != NULL; item = next(item)) if (OBJPTR(item) == obj) return c; else c = npch(c); return '%'; } /* * idenpack: * Identify all the items in the pack */ void idenpack(void) { reg struct linked_list *pc; for (pc = pack ; pc != NULL ; pc = next(pc)) whatis(pc); } /* * del_pack: * Take something out of the hero's pack */ void del_pack(struct linked_list *what) { reg struct object *op; op = OBJPTR(what); cur_null(op); /* check for current stuff */ if (op->o_count > 1) { op->o_count--; } else { detach(pack,what); discard(what); } updpack(); } /* * cur_null: * This updates cur_weapon etc for dropping things */ void cur_null(struct object *op) { if (op == cur_weapon) cur_weapon = NULL; else if (op == cur_armor) cur_armor = NULL; else if (op == cur_ring[LEFT]) cur_ring[LEFT] = NULL; else if (op == cur_ring[RIGHT]) cur_ring[RIGHT] = NULL; }