Mercurial > hg > early-roguelike
diff rogue3/pack.c @ 0:527e2150eaf0
Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Tue, 13 Oct 2009 13:33:34 +0000 |
parents | |
children | d9e44e18eeec |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue3/pack.c Tue Oct 13 13:33:34 2009 +0000 @@ -0,0 +1,399 @@ +/* + * Routines to deal with the pack + * + * @(#)pack.c 3.6 (Berkeley) 6/15/81 + * + * 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 "curses.h" +#include <ctype.h> +#include "rogue.h" + +/* + * 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(struct linked_list *item, int silent) +{ + struct linked_list *ip, *lp; + struct object *obj, *op; + int exact, from_floor; + + if (item == NULL) + { + from_floor = TRUE; + if ((item = find_obj(hero.y, hero.x)) == NULL) + return; + } + else + from_floor = FALSE; + obj = (struct object *) ldata(item); + /* + * 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. + */ + if (obj->o_group) + { + for (ip = pack; ip != NULL; ip = next(ip)) + { + op = (struct object *) ldata(ip); + 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, item); + mvaddch(hero.y, hero.x, + (roomin(&hero) == NULL ? PASSAGE : FLOOR)); + } + discard(item); + item = ip; + 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) + { + msg("The scroll turns to dust as you pick it up."); + detach(lvl_obj, item); + mvaddch(hero.y, hero.x, FLOOR); + return; + } + else + obj->o_flags |= ISFOUND; + + inpack++; + if (from_floor) + { + detach(lvl_obj, item); + mvaddch(hero.y, hero.x, (roomin(&hero) == NULL ? PASSAGE : FLOOR)); + } + /* + * Search for an object of the same type + */ + exact = FALSE; + for (ip = pack; ip != NULL; ip = next(ip)) + { + op = (struct object *) ldata(ip); + if (obj->o_type == op->o_type) + break; + } + if (ip == NULL) + { + /* + * Put it at the end of the pack since it is a new type + */ + for (ip = pack; ip != NULL; ip = next(ip)) + { + op = (struct object *) ldata(ip); + if (op->o_type != FOOD) + break; + lp = ip; + } + } + else + { + /* + * Search for an object which is exactly the same + */ + while (ip != NULL && op->o_type == obj->o_type) + { + if (op->o_which == obj->o_which) + { + exact = TRUE; + break; + } + lp = ip; + if ((ip = next(ip)) == NULL) + break; + op = (struct object *) ldata(ip); + } + } + if (ip == NULL) + { + /* + * Didn't find an exact match, just stick it here + */ + if (pack == NULL) + pack = item; + else + { + lp->l_next = item; + item->l_prev = lp; + item->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++; + discard(item); + item = ip; + goto picked_up; + } + if ((item->l_prev = prev(ip)) != NULL) + item->l_prev->l_next = item; + else + pack = item; + item->l_next = ip; + ip->l_prev = item; + } +picked_up: + /* + * Notify the user + */ + obj = (struct object *) ldata(item); + if (notify && !silent) + { + if (!terse) + addmsg("You now have "); + msg("%s (%c)", inv_name(obj, !terse), pack_char(obj)); + } + if (obj->o_type == AMULET) + amulet = TRUE; +} + +/* + * inventory: + * list what is in the pack + */ +int +inventory(struct linked_list *list, int type) +{ + struct object *obj; + int ch; + int n_objs; + char inv_temp[80]; + + n_objs = 0; + for (ch = 'a'; list != NULL; ch++, list = next(list)) + { + obj = (struct object *) ldata(list); + if (type && type != obj->o_type && !(type == CALLABLE && + (obj->o_type == SCROLL || obj->o_type == POTION || + obj->o_type == RING || obj->o_type == STICK))) + continue; + switch (n_objs++) + { + /* + * For the first thing in the inventory, just save the string + * in case there is only one. + */ + case 0: + sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE)); + break; + /* + * If there is more than one, clear the screen, print the + * saved message and fall through to ... + */ + case 1: + if (slow_invent) + msg(inv_temp); + else + { + wclear(hw); + waddstr(hw, inv_temp); + waddch(hw, '\n'); + } + /* + * Print the line for this object + */ + default: + if (slow_invent) + msg("%c) %s", ch, inv_name(obj, FALSE)); + else + wprintw(hw, "%c) %s\n", ch, inv_name(obj, 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; + } + if (n_objs == 1) + { + msg(inv_temp); + return TRUE; + } + if (!slow_invent) + { + mvwaddstr(hw, LINES-1, 0, "--Press space to continue--"); + draw(hw); + wait_for(hw,' '); + clearok(cw, TRUE); + touchwin(cw); + } + return TRUE; +} + +/* + * pick_up: + * Add something to characters pack. + */ +void +pick_up(int ch) +{ + switch(ch) + { + case GOLD: + money(); + break; + default: + debug("Where did you pick that up???"); + 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() +{ + struct linked_list *item; + int ch, mch; + + if (pack == NULL) + msg("You aren't carrying anything"); + else if (next(pack) == NULL) + msg("a) %s", inv_name((struct object *) ldata(pack), FALSE)); + else + { + msg(terse ? "Item: " : "Which item do you wish to inventory: "); + mpos = 0; + if ((mch = readchar(cw)) == ESCAPE) + { + msg(""); + return; + } + for (ch = 'a', item = pack; item != NULL; item = next(item), ch++) + if (ch == mch) + { + msg("%c) %s",ch,inv_name((struct object *) ldata(item), FALSE)); + return; + } + if (!terse) + msg("'%s' not in pack", unctrl(mch)); + 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) +{ + struct linked_list *obj; + int 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(cw); + 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; +} + +int +pack_char(struct object *obj) +{ + struct linked_list *item; + int c; + + c = 'a'; + for (item = pack; item != NULL; item = next(item)) + if ((struct object *) ldata(item) == obj) + return c; + else + c++; + return 'z'; +}