[BACK]Return to bag.c CVS log [TXT][DIR] Up to [contributed] / early-roguelike / urogue

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