#include #include #include "netprot.h" /* * Routines to deal with the pack * * @(#)packet.c 4.40 (Berkeley) 02/05/99 */ /* * 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, bool silent) { THING *op, *lp; bool from_floor; 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; 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: discard(obj); obj = op; 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. */ for (op = Mlist; op != NULL; op = next(op)) if (op->t_dest = &obj->o_pos) op->t_dest = &Hero; 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 */ bool pack_room(bool 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, bool newobj, bool 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. */ char pack_char(void) { bool *bp; for (bp = Pack_used; *bp; bp++) continue; *bp = TRUE; return (bp - Pack_used) + 'a'; } /* * inventory: * List what is in the pack. Return TRUE if there is something of * the given type. */ bool inventory(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(char 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); 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((THING *) NULL, FALSE); break; } } /* * move_msg: * Print out the message if you are just moving onto an object */ void move_msg(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; char 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(char *purpose, int type) { THING *obj; char 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("that's not a valid item"); continue; } else 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 */ char 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 */ char floor_at(void) { char 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; }