Mercurial > hg > early-roguelike
view rogue5/pack.c @ 255:69ffcb6b90da
Merge the bugfix branch, which had missed an update.
author | John "Elwin" Edwards |
---|---|
date | Fri, 10 Feb 2017 09:06:50 -0500 |
parents | e5a15b09ce1d |
children |
line wrap: on
line source
/* * Routines to deal with the pack * * @(#)pack.c 4.40 (Berkeley) 02/05/99 * * Rogue: Exploring the Dungeons of Doom * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman * All rights reserved. * * See the file LICENSE.TXT for full copyright and licensing information. */ #include <string.h> #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 */ 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, int silent) { THING *op, *lp; int from_floor; int discarded = 0; from_floor = FALSE; if (obj == NULL) { if ((obj = find_obj(hero.y, hero.x)) == NULL) return; from_floor = TRUE; } /* * 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_ch()); chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; update_mdest(obj); discarded = 1; discard(obj); msg("the scroll turns to dust as you pick it up"); return; } if (pack == NULL) { pack = obj; obj->o_packch = pack_char(); inpack++; } else { lp = NULL; for (op = pack; op != NULL; op = next(op)) { if (op->o_type != obj->o_type) lp = op; else { while (op->o_type == obj->o_type && op->o_which != obj->o_which) { lp = op; if (next(op) == NULL) break; else op = next(op); } if (op->o_type == obj->o_type && op->o_which == obj->o_which) { if (ISMULT(op->o_type)) { if (!pack_room(from_floor, obj)) return; op->o_count++; dump_it: update_mdest(obj); discard(obj); obj = op; discarded = 1; lp = NULL; goto out; } else if (obj->o_group) { lp = op; while (op->o_type == obj->o_type && op->o_which == obj->o_which && op->o_group != obj->o_group) { lp = op; if (next(op) == NULL) break; else op = next(op); } if (op->o_type == obj->o_type && op->o_which == obj->o_which && op->o_group == obj->o_group) { op->o_count += obj->o_count; inpack--; if (!pack_room(from_floor, obj)) return; goto dump_it; } } else lp = op; } out: break; } } if (lp != NULL) { if (!pack_room(from_floor, obj)) return; else { obj->o_packch = pack_char(); next(obj) = next(lp); prev(obj) = lp; if (next(lp) != NULL) prev(next(lp)) = obj; next(lp) = obj; } } } obj->o_flags |= ISFOUND; /* * 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), obj->o_packch); } } /* * pack_room: * See if there's room in the pack. If not, print out an * appropriate message */ int pack_room(int from_floor, THING *obj) { if (++inpack > MAXPACK) { if (!terse) addmsg("there's "); addmsg("no room"); if (!terse) addmsg(" in your pack"); endmsg(); if (from_floor) move_msg(obj); inpack = MAXPACK; return FALSE; } if (from_floor) { detach(lvl_obj, obj); mvaddch(hero.y, hero.x, floor_ch()); chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; } return TRUE; } /* * leave_pack: * take an item out of the pack */ THING * leave_pack(THING *obj, int newobj, int all) { THING *nobj; inpack--; nobj = obj; if (obj->o_count > 1 && !all) { last_pick = obj; obj->o_count--; if (obj->o_group) inpack++; if (newobj) { nobj = new_item(); *nobj = *obj; next(nobj) = NULL; prev(nobj) = NULL; nobj->o_count = 1; } } else { last_pick = NULL; pack_used[obj->o_packch - 'a'] = FALSE; detach(pack, obj); } return nobj; } /* * pack_char: * Return the next unused pack character. */ int pack_char(void) { int *bp; for (bp = pack_used; *bp; bp++) continue; *bp = TRUE; return ((int)(bp - pack_used) + 'a'); } /* * inventory: * List what is in the pack. Return TRUE if there is something of * the given type. */ int inventory(const THING *list, int type) { static char inv_temp[MAXSTR]; n_objs = 0; for (; list != NULL; list = next(list)) { if (type && type != list->o_type && !(type == CALLABLE && list->o_type != FOOD && list->o_type != AMULET) && !(type == R_OR_S && (list->o_type == RING || list->o_type == STICK))) continue; n_objs++; #ifdef MASTER if (!list->o_packch) strcpy(inv_temp, "%s"); else #endif sprintf(inv_temp, "%c) %%s", list->o_packch); msg_esc = TRUE; if (add_line(inv_temp, inv_name(list, FALSE)) == ESCAPE) { msg_esc = FALSE; msg(""); return TRUE; } msg_esc = 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(int ch) { THING *obj; if (on(player, ISLEVIT)) return; obj = find_obj(hero.y, hero.x); if (move_on) move_msg(obj); else switch (ch) { case GOLD: if (obj == NULL) return; money(obj->o_goldval); detach(lvl_obj, obj); update_mdest(obj); discard(obj); proom->r_goldval = 0; break; default: #ifdef MASTER debug("Where did you pick a '%s' up???", unctrl(ch)); #endif case ARMOR: case POTION: case FOOD: case WEAPON: case SCROLL: case AMULET: case RING: case STICK: add_pack(NULL, FALSE); break; } } /* * move_msg: * Print out the message if you are just moving onto an object */ void move_msg(const THING *obj) { if (!terse) addmsg("you "); msg("moved onto %s", inv_name(obj, TRUE)); } /* * picky_inven: * Allow player to inventory a single item */ void picky_inven(void) { THING *obj; int 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 (obj = pack; obj != NULL; obj = next(obj)) if (mch == obj->o_packch) { msg("%c) %s", mch, inv_name(obj, FALSE)); return; } msg("'%s' not in pack", unctrl(mch)); } } /* * get_item: * Pick something out of a pack for a purpose */ THING * get_item(const char *purpose, int type) { THING *obj; int ch; if (pack == NULL) msg("you aren't carrying anything"); else if (again) if (last_pick) return last_pick; else msg("you ran out"); 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) { reset_last(); after = FALSE; msg(""); return NULL; } n_objs = 1; /* normal case: person types one char */ if (ch == '*') { mpos = 0; if (inventory(pack, type) == 0) { after = FALSE; return NULL; } continue; } for (obj = pack; obj != NULL; obj = next(obj)) if (obj->o_packch == ch) break; if (obj == NULL) { msg("'%s' is not a valid item",unctrl(ch)); continue; } else { msg(""); return obj; } } } return NULL; } /* * money: * Add or subtract gold from the pack */ void money(int value) { purse += value; mvaddch(hero.y, hero.x, floor_ch()); chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; if (value > 0) { if (!terse) addmsg("you found "); msg("%d gold pieces", value); } } /* * floor_ch: * Return the appropriate floor character for her room */ int floor_ch(void) { if (proom->r_flags & ISGONE) return PASSAGE; return (show_floor() ? FLOOR : ' '); } /* * floor_at: * Return the character at hero's position, taking see_floor * into account */ int floor_at(void) { int ch; ch = chat(hero.y, hero.x); if (ch == FLOOR) ch = floor_ch(); return ch; } /* * reset_last: * Reset the last command when the current one is aborted */ void reset_last(void) { last_comm = l_last_comm; last_dir = l_last_dir; last_pick = l_last_pick; }