Mercurial > hg > early-roguelike
diff srogue/pack.c @ 36:2128c7dc8a40
Import Super-Rogue 9.0 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Thu, 25 Nov 2010 12:21:41 +0000 |
parents | |
children | 7f5f5f1ba09c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srogue/pack.c Thu Nov 25 12:21:41 2010 +0000 @@ -0,0 +1,475 @@ +/* + * 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 <ctype.h> +#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. + */ +add_pack(item, silent) +struct linked_list *item; +bool silent; +{ + reg struct linked_list *ip, *lp; + reg struct object *obj, *op; + 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 + */ +inventory(list, type) +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. + */ +pick_up(ch) +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 + */ +picky_inven() +{ + 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(purpose, type) +char *purpose; +int type; +{ + reg struct linked_list *obj, *pit, *savepit; + 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(obj) +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 + */ +idenpack() +{ + 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 + */ +del_pack(what) +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 + */ +cur_null(op) +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; +}