Annotation of early-roguelike/rogue5/pack.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * Routines to deal with the pack
3: *
4: * @(#)pack.c 4.40 (Berkeley) 02/05/99
5: *
6: * Rogue: Exploring the Dungeons of Doom
7: * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
8: * All rights reserved.
9: *
10: * See the file LICENSE.TXT for full copyright and licensing information.
11: */
12:
13: #include <string.h>
14: #include <curses.h>
15: #include <ctype.h>
16: #include "rogue.h"
17:
18: /*
19: * update_mdest:
20: * Called after picking up an object, before discarding it.
21: * If this was the object of something's desire, that monster will
22: * get mad and run at the hero
23: */
24: void
25: update_mdest(THING *obj)
26: {
27: register THING *mp;
28:
29: for (mp = mlist; mp != NULL; mp = next(mp))
30: if (mp->t_dest == &obj->o_pos)
31: mp->t_dest = &hero;
32: }
33:
34: /*
35: * add_pack:
36: * Pick up an object and add it to the pack. If the argument is
37: * non-null use it as the linked_list pointer instead of gettting
38: * it off the ground.
39: */
40:
41: void
42: add_pack(THING *obj, int silent)
43: {
44: THING *op, *lp;
45: int from_floor;
46: int discarded = 0;
47:
48: from_floor = FALSE;
49: if (obj == NULL)
50: {
51: if ((obj = find_obj(hero.y, hero.x)) == NULL)
52: return;
53: from_floor = TRUE;
54: }
55:
56: /*
57: * Check for and deal with scare monster scrolls
58: */
59: if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
60: if (obj->o_flags & ISFOUND)
61: {
62: detach(lvl_obj, obj);
63: mvaddch(hero.y, hero.x, floor_ch());
64: chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
65: update_mdest(obj);
66: discarded = 1;
67: discard(obj);
68: msg("the scroll turns to dust as you pick it up");
69: return;
70: }
71:
72: if (pack == NULL)
73: {
74: pack = obj;
75: obj->o_packch = pack_char();
76: inpack++;
77: }
78: else
79: {
80: lp = NULL;
81: for (op = pack; op != NULL; op = next(op))
82: {
83: if (op->o_type != obj->o_type)
84: lp = op;
85: else
86: {
87: while (op->o_type == obj->o_type && op->o_which != obj->o_which)
88: {
89: lp = op;
90: if (next(op) == NULL)
91: break;
92: else
93: op = next(op);
94: }
95: if (op->o_type == obj->o_type && op->o_which == obj->o_which)
96: {
97: if (ISMULT(op->o_type))
98: {
99: if (!pack_room(from_floor, obj))
100: return;
101: op->o_count++;
102: dump_it:
103: update_mdest(obj);
104: discard(obj);
105: obj = op;
106: discarded = 1;
107: lp = NULL;
108: goto out;
109: }
110: else if (obj->o_group)
111: {
112: lp = op;
113: while (op->o_type == obj->o_type
114: && op->o_which == obj->o_which
115: && op->o_group != obj->o_group)
116: {
117: lp = op;
118: if (next(op) == NULL)
119: break;
120: else
121: op = next(op);
122: }
123: if (op->o_type == obj->o_type
124: && op->o_which == obj->o_which
125: && op->o_group == obj->o_group)
126: {
127: op->o_count += obj->o_count;
128: inpack--;
129: if (!pack_room(from_floor, obj))
130: return;
131: goto dump_it;
132: }
133: }
134: else
135: lp = op;
136: }
137: out:
138: break;
139: }
140: }
141:
142: if (lp != NULL)
143: {
144: if (!pack_room(from_floor, obj))
145: return;
146: else
147: {
148: obj->o_packch = pack_char();
149: next(obj) = next(lp);
150: prev(obj) = lp;
151: if (next(lp) != NULL)
152: prev(next(lp)) = obj;
153: next(lp) = obj;
154: }
155: }
156: }
157:
158: obj->o_flags |= ISFOUND;
159:
160: /*
161: * If this was the object of something's desire, that monster will
162: * get mad and run at the hero.
163: */
164: if (!discarded)
165: update_mdest(obj);
166:
167: if (obj->o_type == AMULET)
168: amulet = TRUE;
169: /*
170: * Notify the user
171: */
172: if (!silent)
173: {
174: if (!terse)
175: addmsg("you now have ");
176: msg("%s (%c)", inv_name(obj, !terse), obj->o_packch);
177: }
178: }
179:
180: /*
181: * pack_room:
182: * See if there's room in the pack. If not, print out an
183: * appropriate message
184: */
185: int
186: pack_room(int from_floor, THING *obj)
187: {
188: if (++inpack > MAXPACK)
189: {
190: if (!terse)
191: addmsg("there's ");
192: addmsg("no room");
193: if (!terse)
194: addmsg(" in your pack");
195: endmsg();
196: if (from_floor)
197: move_msg(obj);
198: inpack = MAXPACK;
199: return FALSE;
200: }
201:
202: if (from_floor)
203: {
204: detach(lvl_obj, obj);
205: mvaddch(hero.y, hero.x, floor_ch());
206: chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
207: }
208:
209: return TRUE;
210: }
211:
212: /*
213: * leave_pack:
214: * take an item out of the pack
215: */
216: THING *
217: leave_pack(THING *obj, int newobj, int all)
218: {
219: THING *nobj;
220:
221: inpack--;
222: nobj = obj;
223: if (obj->o_count > 1 && !all)
224: {
225: last_pick = obj;
226: obj->o_count--;
227: if (obj->o_group)
228: inpack++;
229: if (newobj)
230: {
231: nobj = new_item();
232: *nobj = *obj;
233: next(nobj) = NULL;
234: prev(nobj) = NULL;
235: nobj->o_count = 1;
236: }
237: }
238: else
239: {
240: last_pick = NULL;
241: pack_used[obj->o_packch - 'a'] = FALSE;
242: detach(pack, obj);
243: }
244: return nobj;
245: }
246:
247: /*
248: * pack_char:
249: * Return the next unused pack character.
250: */
251: int
252: pack_char(void)
253: {
254: int *bp;
255:
256: for (bp = pack_used; *bp; bp++)
257: continue;
258: *bp = TRUE;
259: return ((int)(bp - pack_used) + 'a');
260: }
261:
262: /*
263: * inventory:
264: * List what is in the pack. Return TRUE if there is something of
265: * the given type.
266: */
267: int
268: inventory(const THING *list, int type)
269: {
270: static char inv_temp[MAXSTR];
271:
272: n_objs = 0;
273: for (; list != NULL; list = next(list))
274: {
275: if (type && type != list->o_type && !(type == CALLABLE &&
276: list->o_type != FOOD && list->o_type != AMULET) &&
277: !(type == R_OR_S && (list->o_type == RING || list->o_type == STICK)))
278: continue;
279: n_objs++;
280: #ifdef MASTER
281: if (!list->o_packch)
282: strcpy(inv_temp, "%s");
283: else
284: #endif
285: sprintf(inv_temp, "%c) %%s", list->o_packch);
286: msg_esc = TRUE;
287: if (add_line(inv_temp, inv_name(list, FALSE)) == ESCAPE)
288: {
289: msg_esc = FALSE;
290: msg("");
291: return TRUE;
292: }
293: msg_esc = FALSE;
294: }
295: if (n_objs == 0)
296: {
297: if (terse)
298: msg(type == 0 ? "empty handed" :
299: "nothing appropriate");
300: else
301: msg(type == 0 ? "you are empty handed" :
302: "you don't have anything appropriate");
303: return FALSE;
304: }
305: end_line();
306: return TRUE;
307: }
308:
309: /*
310: * pick_up:
311: * Add something to characters pack.
312: */
313:
314: void
315: pick_up(int ch)
316: {
317: THING *obj;
318:
319: if (on(player, ISLEVIT))
320: return;
321:
322: obj = find_obj(hero.y, hero.x);
323: if (move_on)
324: move_msg(obj);
325: else
326: switch (ch)
327: {
328: case GOLD:
329: if (obj == NULL)
330: return;
331: money(obj->o_goldval);
332: detach(lvl_obj, obj);
333: update_mdest(obj);
334: discard(obj);
335: proom->r_goldval = 0;
336: break;
337: default:
338: #ifdef MASTER
339: debug("Where did you pick a '%s' up???", unctrl(ch));
340: #endif
341: case ARMOR:
342: case POTION:
343: case FOOD:
344: case WEAPON:
345: case SCROLL:
346: case AMULET:
347: case RING:
348: case STICK:
349: add_pack(NULL, FALSE);
350: break;
351: }
352: }
353:
354: /*
355: * move_msg:
356: * Print out the message if you are just moving onto an object
357: */
358:
359: void
360: move_msg(const THING *obj)
361: {
362: if (!terse)
363: addmsg("you ");
364: msg("moved onto %s", inv_name(obj, TRUE));
365: }
366:
367: /*
368: * picky_inven:
369: * Allow player to inventory a single item
370: */
371:
372: void
373: picky_inven(void)
374: {
375: THING *obj;
376: int mch;
377:
378: if (pack == NULL)
379: msg("you aren't carrying anything");
380: else if (next(pack) == NULL)
381: msg("a) %s", inv_name(pack, FALSE));
382: else
383: {
384: msg(terse ? "item: " : "which item do you wish to inventory: ");
385: mpos = 0;
386: if ((mch = readchar()) == ESCAPE)
387: {
388: msg("");
389: return;
390: }
391: for (obj = pack; obj != NULL; obj = next(obj))
392: if (mch == obj->o_packch)
393: {
394: msg("%c) %s", mch, inv_name(obj, FALSE));
395: return;
396: }
397: msg("'%s' not in pack", unctrl(mch));
398: }
399: }
400:
401: /*
402: * get_item:
403: * Pick something out of a pack for a purpose
404: */
405: THING *
406: get_item(const char *purpose, int type)
407: {
408: THING *obj;
409: int ch;
410:
411: if (pack == NULL)
412: msg("you aren't carrying anything");
413: else if (again)
414: if (last_pick)
415: return last_pick;
416: else
417: msg("you ran out");
418: else
419: {
420: for (;;)
421: {
422: if (!terse)
423: addmsg("which object do you want to ");
424: addmsg(purpose);
425: if (terse)
426: addmsg(" what");
427: msg("? (* for list): ");
428: ch = readchar();
429: mpos = 0;
430: /*
431: * Give the poor player a chance to abort the command
432: */
433: if (ch == ESCAPE)
434: {
435: reset_last();
436: after = FALSE;
437: msg("");
438: return NULL;
439: }
440: n_objs = 1; /* normal case: person types one char */
441: if (ch == '*')
442: {
443: mpos = 0;
444: if (inventory(pack, type) == 0)
445: {
446: after = FALSE;
447: return NULL;
448: }
449: continue;
450: }
451: for (obj = pack; obj != NULL; obj = next(obj))
452: if (obj->o_packch == ch)
453: break;
454: if (obj == NULL)
455: {
456: msg("'%s' is not a valid item",unctrl(ch));
457: continue;
458: }
459: else {
460: msg("");
461: return obj;
462: }
463: }
464: }
465: return NULL;
466: }
467:
468: /*
469: * money:
470: * Add or subtract gold from the pack
471: */
472:
473: void
474: money(int value)
475: {
476: purse += value;
477: mvaddch(hero.y, hero.x, floor_ch());
478: chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
479: if (value > 0)
480: {
481: if (!terse)
482: addmsg("you found ");
483: msg("%d gold pieces", value);
484: }
485: }
486:
487: /*
488: * floor_ch:
489: * Return the appropriate floor character for her room
490: */
491: int
492: floor_ch(void)
493: {
494: if (proom->r_flags & ISGONE)
495: return PASSAGE;
496: return (show_floor() ? FLOOR : ' ');
497: }
498:
499: /*
500: * floor_at:
501: * Return the character at hero's position, taking see_floor
502: * into account
503: */
504: int
505: floor_at(void)
506: {
507: int ch;
508:
509: ch = chat(hero.y, hero.x);
510: if (ch == FLOOR)
511: ch = floor_ch();
512: return ch;
513: }
514:
515: /*
516: * reset_last:
517: * Reset the last command when the current one is aborted
518: */
519:
520: void
521: reset_last(void)
522: {
523: last_comm = l_last_comm;
524: last_dir = l_last_dir;
525: last_pick = l_last_pick;
526: }
CVSweb