Annotation of early-roguelike/urogue/bag.c, Revision 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