Mercurial > hg > early-roguelike
diff rogue4/pack.c @ 12:9535a08ddc39
Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Sat, 24 Oct 2009 16:52:52 +0000 |
parents | |
children | 1b73a8641b37 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rogue4/pack.c Sat Oct 24 16:52:52 2009 +0000 @@ -0,0 +1,421 @@ +/* + * 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 <curses.h> +#include <ctype.h> +#include "rogue.h" + +/* + * 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 + */ +update_mdest(obj) +register 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. + */ +add_pack(obj, silent) +register 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 + */ +inventory(list, type) +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. + */ +pick_up(ch) +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 + */ +picky_inven() +{ + 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(purpose, type) +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 + */ +pack_char(obj) +register 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 + */ +money(value) +register 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); + } +}