Annotation of early-roguelike/urogue/bag.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: bag.c - functions for dealing with bags
3:
4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5: Copyright (C) 1986, 1992, 1993, 1995 Herb Chong
6: All rights reserved.
7:
8: See the file LICENSE.TXT for full copyright and licensing information.
9: */
10:
11: /*
12: * new bag functions
13: *
14: * This is a simple version of bag.c that uses linked lists to perform the bag
15: * functions. The bag is just a linked list of objects (struct object) to be
16: * specific, but most of that is supposed to be hidden from the user, who
17: * should access the bag only through the functions presented here.
18: */
19:
20: #include <stdlib.h>
21: #include "rogue.h"
22:
23: /*
24: * apply_to_bag
25: *
26: * This is the general bag manipulation routine. The bag is subjected to
27: * selection criteria and those objects which pass are processed by an action
28: * routine. The two criteria are type and filter function. The filter
29: * function returns TRUE if the object passes and FALSE otherwise. The filter
30: * function is passed the object and the user-supplied argument. This gives
31: * the user plenty of flexibility in determining which items will be
32: * processed. The action routine is passed the object, the id, and the
33: * user-supplied argument given to apply_to_bag. Specifying NULL for either
34: * the type or filter function means that criterion always selects. A NULL
35: * action routine means no processing is done and the first object which
36: * passes the filter is returned to the user. The action routine returns TRUE
37: * if processing should continue or FALSE if the current item should be
38: * returned to the caller.
39: *
40: * Returns NULL if the bag is empty or if nothing qualified.
41: *
42: * linked_list *bag_p; // linked list of objects
43: * int type; // what is its type (ARMOR, ...)
44: * int (*bff_p)(); // bag filter function
45: * int (*baf_p)(); // bag action routine
46: * long user_arg; // user argument for filter, action
47: *
48: */
49:
50: struct object *
51: apply_to_bag(struct linked_list *bag_p,
52: int type,
53: int (*bff_p)(struct object *obj, bag_arg *user_arg),
54: int (*baf_p)(struct object *obj, bag_arg *user_arg, int id),
55: void *user_arg)
56: {
57: struct object *bag_obj_p = NULL; /* qualifying object */
58: struct object *cur_obj_p; /* current object */
59: bag_arg arg;
60:
61: arg.varg = user_arg;
62:
63: if (bag_p == NULL)
64: return (NULL);
65:
66: for (; bag_p != NULL; bag_p = next(bag_p))
67: {
68: cur_obj_p = OBJPTR(bag_p);
69:
70: if (type != 0 && type != cur_obj_p->o_type)
71: continue;
72:
73: if (bff_p != NULL && !(*bff_p)(cur_obj_p, &arg))
74: continue;
75:
76: /*
77: * At this point, we have an object which qualifies for
78: * processing
79: */
80:
81: bag_obj_p = cur_obj_p; /* in case the user wants it */
82:
83: if (baf_p != NULL && (*baf_p)(cur_obj_p, &arg, identifier(bag_obj_p)))
84: continue;
85:
86: /*
87: * We have an object which qualifies, quit now!
88: */
89:
90: break;
91: }
92:
93: if (bag_p == NULL)
94: return (NULL);
95:
96: return (bag_obj_p);
97: }
98:
99: /*
100: count_bag()
101:
102: Counts up all bag items which meet the selection criteria
103: */
104:
105: int
106: count_bag(linked_list *bag_p,
107: int type,
108: int (*bff_p)(struct object *obj, bag_arg *junk))
109: {
110: int cnt = 0;
111: apply_to_bag(bag_p, type, bff_p, baf_increment, &cnt);
112:
113: return(cnt);
114: }
115:
116: /*
117: del_bag()
118:
119: Removes an object from a bag and throws it away.
120: */
121:
122: void
123: del_bag(linked_list *bag_p, object *obj_p)
124: {
125: pop_bag(&bag_p, obj_p); /* get the thing from the bag */
126: ur_free(obj_p); /* release the memory */
127: }
128:
129: /*
130: pop_bag()
131:
132: Removes an item from a bag and returns it to the user. If the item is
133: not in the bag, return NULL.
134: */
135:
136: struct object *
137: pop_bag(linked_list **bag_pp, object *obj_p)
138: {
139: linked_list *item_p;
140:
141: for (item_p = *bag_pp; item_p != NULL && OBJPTR(item_p) != obj_p;
142: item_p = next(item_p));
143:
144: if (item_p == NULL)
145: return (NULL);
146:
147: _detach(bag_pp, item_p);
148:
149: return (obj_p);
150: }
151:
152: /*
153: push_bag()
154:
155: stuff another item into the bag
156: */
157:
158: void
159: push_bag(linked_list **bag_pp, object *obj_p)
160: {
161: struct linked_list *item_p = NULL;
162: struct linked_list *new_p = NULL;
163: struct linked_list *best_p = NULL;
164:
165: new_p = new_list();
166: new_p->data.obj = obj_p; /* attach our object */
167: identifier(obj_p) = get_ident(obj_p); /* tag this object for */
168: /* inventory */
169: /*
170: * Find a place in the bag - try to match the type, then sort by
171: * identifier
172: */
173:
174: for (item_p = *bag_pp; item_p != NULL; item_p = next(item_p))
175: {
176: if ((OBJPTR(item_p))->o_type == obj_p->o_type)
177: {
178: if (best_p == NULL)
179: best_p = item_p;
180: else if (identifier((OBJPTR(item_p))) >
181: identifier((OBJPTR(best_p))) &&
182: identifier((OBJPTR(item_p))) <
183: identifier(obj_p))
184: best_p = item_p;
185: }
186: }
187:
188: _attach_after(bag_pp, best_p, new_p); /* stuff it in the list */
189:
190: return;
191: }
192:
193: /*
194: scan_bag()
195:
196: Gets the object from the bag that matches the type and id. The object
197: is not removed from the bag.
198: */
199:
200: struct object *
201: scan_bag(linked_list *bag_p, int type, int id)
202: {
203: object *obj_p = NULL;
204:
205: for (; bag_p != NULL; bag_p = next(bag_p))
206: {
207: obj_p = OBJPTR(bag_p);
208:
209: if (obj_p->o_type == type && identifier(obj_p) == id)
210: break;
211: }
212:
213: if (bag_p == NULL)
214: return(NULL);
215:
216: return(obj_p);
217: }
218:
219: /*
220: baf_decrement_test()
221:
222: Assumes the argument is a pointer to int and it just decrements it.
223: Returns TRUE, except when the count goes to zero.
224: */
225:
226: int
227: baf_decrement_test(struct object *obj_p, bag_arg *count_p, int id)
228: {
229: NOOP(obj_p);
230: NOOP(id);
231:
232: if (*count_p->iarg > 0)
233: return(TRUE);
234:
235: return(FALSE);
236: }
237:
238: /*
239: baf_identify()
240:
241: Bag action function to identify an object. This is needed to conform
242: to bag action routine calling conventions and to put the linked list
243: structure on top of the object before calling whatis()
244: */
245:
246: int
247: baf_identify(struct object *obj_p, bag_arg *junk, int id)
248: {
249: linked_list l;
250: linked_list *lp = &l;
251:
252: NOOP(junk);
253: NOOP(id);
254:
255: lp->data.obj = obj_p; /* stuff object in the right place */
256: whatis(lp);
257:
258: return(TRUE);
259: }
260:
261: /*
262: baf_increment()
263:
264: Assumes the argument is a pointer to int and it just increments it and
265: returns TRUE
266: */
267:
268: int
269: baf_increment(object *obj_p, bag_arg *count_p, int id)
270: {
271: NOOP(obj_p);
272: NOOP(id);
273:
274: (*count_p->iarg)++;
275:
276: return(TRUE);
277: }
278:
279: /*
280: baf_print_item()
281: Bag action function to print a single item, inventory style.
282: */
283:
284: int
285: baf_print_item(struct object *obj_p, bag_arg *type, int id)
286: {
287: char inv_temp[3 * LINELEN]; /* plenty of space for paranoid programmers */
288:
289: if (*type->iarg == 0)
290: sprintf(inv_temp, "%c%c) %s", obj_p->o_type,
291: print_letters[id], inv_name(obj_p, LOWERCASE));
292: else
293: sprintf(inv_temp, "%c) %s", print_letters[id],
294: inv_name(obj_p, LOWERCASE));
295:
296: add_line(inv_temp);
297: return(TRUE);
298: }
299:
300: /*
301: bff_group()
302: This bag filter function checks to see if two items can be combined by
303: adjusting the count. Grouped items can be combined if the group numbers
304: match. The only other item that is allowed to have a count is food, and
305: there an exact match is required.
306: */
307:
308: int
309: bff_group(struct object *obj_p, bag_arg *arg)
310: {
311: struct object *new_obj_p = arg->obj;
312:
313: if (new_obj_p->o_group > 0 && new_obj_p->o_group == obj_p->o_group)
314: return(TRUE);
315:
316: if (new_obj_p->o_type == FOOD &&
317: obj_p->o_type == new_obj_p->o_type &&
318: obj_p->o_which == new_obj_p->o_which)
319: return(TRUE);
320:
321: return(FALSE);
322: }
323:
324: /*
325: bff_callable
326: Figures out which items can be callable: current rules are:
327: potions, scrolls, staffs, and rings.
328: */
329:
330: int
331: bff_callable(struct object *obj_p, bag_arg *junk)
332: {
333: NOOP(junk);
334:
335: if (obj_p->o_type == POTION || obj_p->o_type == RING ||
336: obj_p->o_type == STICK || obj_p->o_type == SCROLL)
337: return(TRUE);
338:
339: return(FALSE);
340: }
341:
342: /*
343: bff_markable()
344: Selects which items can be marked. Current rules exclude only gold.
345: */
346:
347: int
348: bff_markable(struct object *obj_p, bag_arg *junk)
349: {
350: NOOP(junk);
351:
352: if (obj_p->o_type == GOLD)
353: return(FALSE);
354:
355: return(TRUE);
356: }
357:
358: /*
359: bffron()
360: returns TRUE if hero is wearing this ring
361: */
362:
363: int
364: bffron(object *obj_p, bag_arg *junk)
365: {
366: NOOP(junk);
367:
368: return(cur_ring[LEFT_1] == obj_p || cur_ring[LEFT_2] == obj_p ||
369: cur_ring[LEFT_3] == obj_p || cur_ring[LEFT_4] == obj_p ||
370: cur_ring[LEFT_5] ||
371: cur_ring[RIGHT_1] == obj_p || cur_ring[RIGHT_2] == obj_p ||
372: cur_ring[RIGHT_3] == obj_p || cur_ring[RIGHT_4] == obj_p ||
373: cur_ring[RIGHT_5]);
374: }
375:
376: /*
377: bff_zappable()
378: Selects which items can be zapped. This includes both sticks and
379: magically enhanced weapons with lightning ability.
380: */
381:
382: int
383: bff_zappable(struct object *obj_p, bag_arg *junk)
384: {
385: NOOP(junk);
386:
387: if (obj_p->o_type == STICK)
388: return(TRUE);
389:
390: if (obj_p->o_type == WEAPON && obj_p->o_flags & ISZAPPED)
391: return(TRUE);
392:
393: return (FALSE);
394: }
395:
396: /*
397: baf_curse()
398: Curse all non-artifact items in the player's pack
399: */
400:
401: int
402: baf_curse(struct object *obj_p, bag_arg *junk, int id)
403: {
404: NOOP(junk);
405: NOOP(id);
406:
407: if (obj_p->o_type != ARTIFACT && rnd(8) == 0)
408: {
409: obj_p->o_flags |= ISCURSED;
410: obj_p->o_flags &= ~ISBLESSED;
411: }
412:
413: return(TRUE);
414: }
415:
416: /*
417: bafcweapon()
418: bag action routine to fetch the current weapon
419: */
420:
421: int
422: bafcweapon(struct object *obj_p, bag_arg *junk, int id)
423: {
424: NOOP(junk);
425: NOOP(id);
426:
427: if (obj_p == cur_weapon)
428: return(FALSE); /* found what we wanted - stop and return it */
429:
430: return(TRUE);
431: }
432:
433: /*
434: bafcarmor()
435: bag action routine to fetch the current armor
436: */
437:
438: int
439: bafcarmor(struct object *obj_p, bag_arg *junk, int id)
440: {
441: NOOP(junk);
442: NOOP(id);
443:
444: if (obj_p == cur_armor)
445: return(FALSE); /* found what we wanted - stop and return it */
446:
447: return(TRUE);
448: }
CVSweb