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

Annotation of early-roguelike/urogue/pack.c, Revision 1.1

1.1     ! rubenllo    1: /*
        !             2:     pack.c - Routines to deal with the pack.
        !             3:
        !             4:     UltraRogue: The Ultimate Adventure in the Dungeons of Doom
        !             5:     Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
        !             6:     All rights reserved.
        !             7:
        !             8:     Based on "Advanced Rogue"
        !             9:     Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
        !            10:     All rights reserved.
        !            11:
        !            12:     Based on "Rogue: Exploring the Dungeons of Doom"
        !            13:     Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
        !            14:     All rights reserved.
        !            15:
        !            16:     See the file LICENSE.TXT for full copyright and licensing information.
        !            17: */
        !            18:
        !            19: /*
        !            20:     Notes
        !            21:
        !            22:         The new pack is implemented through the use of bags,
        !            23:         and items are classed by their types (see rogue.h) which also
        !            24:         happen to be their display character.
        !            25: */
        !            26:
        !            27: #include <stdlib.h>
        !            28: #include <ctype.h>
        !            29: #include "rogue.h"
        !            30:
        !            31: #define ESCAPE_EXIT(x) if (x == ESCAPE) {after = FALSE; msg(""); return(NULL);}
        !            32: #define BAD_NEWS    -1
        !            33: #define BAD_LIST ((struct linked_list *) BAD_NEWS)
        !            34: #define GOOD_NEWS   0
        !            35:
        !            36: static char type_list[] = "!?])/=:,";   /* things to inventory */
        !            37:
        !            38: /*
        !            39:     swap_top()
        !            40:         Takes an stacked object and exchanges places with the top
        !            41:         object. <node> must belong to the <top>'s stacked object list.
        !            42: */
        !            43:
        !            44: void
        !            45: swap_top(struct linked_list *top, struct linked_list *node)
        !            46: {
        !            47:     struct object   *obt, *obn;
        !            48:
        !            49:     obt = OBJPTR(top);
        !            50:     obn = OBJPTR(node);
        !            51:
        !            52:     detach((obt->next_obj), node);  /* Take it out of the stack */
        !            53:     attach(lvl_obj, node);  /* and put it into the level */
        !            54:     detach(lvl_obj, top);   /* Remove item from level */
        !            55:
        !            56:     obn->next_obj = obt->next_obj;
        !            57:     obt->next_obj = NULL;
        !            58:
        !            59:     if (obn->next_obj)
        !            60:         obn->next_obj->l_prev = NULL;
        !            61:
        !            62:     attach((obn->next_obj), top);
        !            63: }
        !            64:
        !            65:
        !            66: /*
        !            67:     get_all()
        !            68:         Get as many stacked items as possible.
        !            69: */
        !            70:
        !            71: void
        !            72: get_all(struct linked_list *top)
        !            73: {
        !            74:     struct linked_list  *node;
        !            75:     struct object   *obt;
        !            76:
        !            77:     while (top)
        !            78:     {
        !            79:         obt = OBJPTR(top);
        !            80:         node = obt->next_obj;
        !            81:
        !            82:         rem_obj(top, FALSE);
        !            83:
        !            84:         if (!add_pack(top, FALSE))
        !            85:             return;
        !            86:
        !            87:         top = node;
        !            88:     }
        !            89: }
        !            90:
        !            91:
        !            92: /*
        !            93:     get_stack()
        !            94:         Allows the user to chose from a stack of items.
        !            95: */
        !            96:
        !            97: struct linked_list *
        !            98: get_stack(struct linked_list *item)
        !            99: {
        !           100:     struct object   *obj;
        !           101:     char    buf[2 * LINELEN];
        !           102:     int i = 0, j;
        !           103:     struct linked_list  *ll;
        !           104: mpos = 0;
        !           105:     obj = OBJPTR(item);
        !           106:
        !           107:        ll = obj->next_obj;
        !           108:
        !           109:     sprintf(buf, "You are standing on top of the following items: ");
        !           110:     add_line(buf);
        !           111:     sprintf(buf, "%d) -- %s", i, inv_name(obj, TRUE));
        !           112:     add_line(buf);
        !           113:
        !           114:     while (ll)
        !           115:     {
        !           116:         i++;
        !           117:         obj = OBJPTR(ll);
        !           118:         sprintf(buf, "%d) -- %s", i, inv_name(obj, TRUE));
        !           119:         add_line(buf);
        !           120:         ll = next(ll);
        !           121:     }
        !           122:
        !           123:     end_line();
        !           124:
        !           125:     msg("Which one do you want to pick up? [* for all] ");
        !           126:
        !           127:     switch(get_string(buf, cw))
        !           128:     {
        !           129:         case NORM:
        !           130:             break;
        !           131:         case QUIT:  /* pick up nothing */
        !           132:             msg("");
        !           133:             return (NULL);
        !           134:     }
        !           135:
        !           136:     if (buf[0] == '*')
        !           137:     {
        !           138:         get_all(item);
        !           139:                msg("");
        !           140:         return(NULL);
        !           141:     }
        !           142:     else
        !           143:     {
        !           144:         i = atoi(buf);
        !           145:
        !           146:         if (i)
        !           147:         {
        !           148:             obj = OBJPTR(item);
        !           149:             ll = obj->next_obj;
        !           150:             j = 1;
        !           151:
        !           152:             while (ll && (j != i))
        !           153:             {
        !           154:                 ll = next(ll);
        !           155:                 j++;
        !           156:             }
        !           157:
        !           158:             if (ll)
        !           159:             {
        !           160:                 swap_top(item, ll);
        !           161:                 return(ll);
        !           162:             }
        !           163:             else
        !           164:             {
        !           165:                 debug("Got past last item while picking up.");
        !           166:                 return(item);
        !           167:             }
        !           168:         }
        !           169:         else
        !           170:             return (item);
        !           171:     }
        !           172: }
        !           173:
        !           174: /*
        !           175:     add_pack()
        !           176:         Pick up an object and add it to the pack.  If the argument is
        !           177:         non-null use it as the linked_list pointer instead of getting it off the
        !           178:         ground.
        !           179: */
        !           180:
        !           181: int
        !           182: add_pack(struct linked_list *item, int print_message)
        !           183: {
        !           184:     struct object   *obj, *op;
        !           185:     int from_floor;
        !           186:
        !           187:     if (item == NULL)
        !           188:     {
        !           189:         from_floor = TRUE;
        !           190:
        !           191:         if ((item = find_obj(hero.y, hero.x)) == NULL)
        !           192:         {
        !           193:             msg("Nothing to pick up.");
        !           194:             return(FALSE);
        !           195:         }
        !           196:     }
        !           197:     else
        !           198:         from_floor = FALSE;
        !           199:
        !           200:     if (from_floor)
        !           201:     {
        !           202:         item = get_stack(item);
        !           203:
        !           204:         if (!item)
        !           205:             return(FALSE);
        !           206:     }
        !           207:
        !           208:     obj = OBJPTR(item);
        !           209:
        !           210:     /* If it is gold, just add its value to rogue's purse and get rid of */
        !           211:
        !           212:     if (obj->o_type == GOLD)
        !           213:     {
        !           214:         struct linked_list  *mitem;
        !           215:         struct thing    *tp;
        !           216:
        !           217:         if (print_message)
        !           218:         {
        !           219:             if (!terse)
        !           220:                 addmsg("You found ");
        !           221:
        !           222:             msg("%d gold pieces.", obj->o_count);
        !           223:         }
        !           224:
        !           225:         /*
        !           226:          * First make sure no greedy monster is after this gold. If
        !           227:          * so, make the monster run after the rogue instead.
        !           228:          */
        !           229:
        !           230:         for (mitem = mlist; mitem != NULL; mitem = next(mitem))
        !           231:         {
        !           232:             tp = THINGPTR(mitem);
        !           233:
        !           234:             if (tp->t_horde==obj)
        !           235:             {
        !           236:                 tp->t_ischasing = TRUE;
        !           237:                 tp->t_chasee = &player;
        !           238:                 tp->t_horde  = NULL;
        !           239:             }
        !           240:         }
        !           241:
        !           242:         /*
        !           243:          * This will cause problems if people are able to drop and
        !           244:          * pick up gold, or when GOLDSTEAL monsters are killed.
        !           245:          */
        !           246:
        !           247:         /* Thieves get EXP for gold they pick up */
        !           248:
        !           249:         if (player.t_ctype == C_THIEF)
        !           250:         {
        !           251:             pstats.s_exp += obj->o_count / 4;
        !           252:             check_level();
        !           253:         }
        !           254:
        !           255:         purse += obj->o_count;
        !           256:
        !           257:         if (from_floor)
        !           258:             rem_obj(item, TRUE);    /* Remove object from the level */
        !           259:
        !           260:         return (TRUE);
        !           261:     }
        !           262:
        !           263:     /* see if he can carry any more weight */
        !           264:
        !           265:     if (itemweight(obj) + pstats.s_pack > pstats.s_carry)
        !           266:     {
        !           267:         msg("Too much for you to carry.");
        !           268:
        !           269:         if (print_message)
        !           270:         {
        !           271:             msg("%s onto %s", terse ? "Moved" : "You moved",
        !           272:                 inv_name(obj, LOWERCASE));
        !           273:         }
        !           274:
        !           275:         return(FALSE);
        !           276:     }
        !           277:
        !           278:     /*
        !           279:      * Link it into the pack. If the item can be grouped, try to find its
        !           280:      * neighbors and bump the count. A special case is food, which can't
        !           281:      * be grouped, but an exact match allows the count to get
        !           282:      * incremented.
        !           283:      */
        !           284:
        !           285:     if ((op = apply_to_bag(pack, obj->o_type, bff_group, NULL, obj)) != NULL)
        !           286:     {
        !           287:         op->o_count += obj->o_count;    /* add it to the rest */
        !           288:
        !           289:         if (from_floor)
        !           290:             rem_obj(item, FALSE);
        !           291:
        !           292:         pack_report(op, print_message, "You now have ");
        !           293:
        !           294:         return(TRUE);
        !           295:     }
        !           296:
        !           297:     /* Check for and deal with scare monster scrolls */
        !           298:
        !           299:     if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
        !           300:         if (obj->o_flags & ISCURSED)
        !           301:         {
        !           302:             msg("The scroll turns to dust as you pick it up.");
        !           303:             rem_obj(item, TRUE);
        !           304:             return(TRUE);
        !           305:         }
        !           306:
        !           307:     /* Check if there is room */
        !           308:
        !           309:     if (count_bag(pack, obj->o_type, NULL) == max_print())
        !           310:     {
        !           311:         msg("You have no room for more %s.", name_type(obj->o_type));
        !           312:
        !           313:         if (print_message)
        !           314:         {
        !           315:             obj = OBJPTR(item);
        !           316:             msg("%s onto %s.", terse ? "Moved" : "You moved",
        !           317:                 inv_name(obj, LOWERCASE));
        !           318:         }
        !           319:
        !           320:         return(FALSE);
        !           321:     }
        !           322:
        !           323:     /*
        !           324:      * finally, add the new item to the bag, and free up the linked list
        !           325:      * on top of it.
        !           326:      */
        !           327:
        !           328:     if (from_floor)
        !           329:         rem_obj(item, FALSE);
        !           330:
        !           331:     push_bag(&pack, obj);
        !           332:     pack_report(obj, print_message, "You now have ");
        !           333:     ur_free(item);
        !           334:
        !           335:     return(TRUE);      /* signal success */
        !           336: }
        !           337:
        !           338: /*
        !           339:     pack_report()
        !           340:         Notify the user about the results of the pack operation and do some
        !           341:         post processing.
        !           342: */
        !           343:
        !           344: void
        !           345: pack_report(object *obj, int print_message, char *message)
        !           346: {
        !           347:     /* Notify the user */
        !           348:
        !           349:     if (print_message)
        !           350:     {
        !           351:         if (!terse)
        !           352:             addmsg(message);
        !           353:
        !           354:         msg("(%c%c) %s.", obj->o_type, print_letters[get_ident(obj)],
        !           355:             inv_name(obj, !terse));
        !           356:     }
        !           357:
        !           358:     if (obj->o_type == ARTIFACT)
        !           359:     {
        !           360:         has_artifact |= (1 << obj->o_which);
        !           361:         picked_artifact |= (1 << obj->o_which);
        !           362:
        !           363:         if (!(obj->ar_flags & ISUSED))
        !           364:         {
        !           365:             obj->ar_flags |= ISUSED;
        !           366:             pstats.s_exp += arts[obj->o_which].ar_worth / 10;
        !           367:             check_level();
        !           368:         }
        !           369:     }
        !           370:
        !           371:     updpack();
        !           372:
        !           373:     return;
        !           374: }
        !           375:
        !           376: /*
        !           377:     inventory()
        !           378:         list what is in the pack
        !           379: */
        !           380:
        !           381: void
        !           382: inventory(struct linked_list *container, int type)
        !           383: {
        !           384:     int cnt;
        !           385:
        !           386:     if (type == 0)
        !           387:     {
        !           388:         msg("What kind of item <%s> to inventory (* for all)?",  type_list);
        !           389:
        !           390:         type = readchar();
        !           391:
        !           392:         if (type == ESCAPE)
        !           393:         {
        !           394:             after = FALSE;
        !           395:             msg("");
        !           396:             return;
        !           397:         }
        !           398:     }
        !           399:
        !           400:     /*
        !           401:      * Get a list of items to print out. If the user selects '*', list
        !           402:      * them all.
        !           403:      */
        !           404:
        !           405:     if (type == '*')
        !           406:         type = 0;   /* no type passed ->use them all */
        !           407:
        !           408:     mpos = 0;
        !           409:
        !           410:     if ((cnt = count_bag(container, type, NULL)) == 0)
        !           411:         msg("You don't have any %s.", name_type(type));
        !           412:     else
        !           413:     {
        !           414:         apply_to_bag(container, type, NULL, baf_print_item, &type);
        !           415:         end_line();
        !           416:         msg("");
        !           417:     }
        !           418:
        !           419:     return;
        !           420: }
        !           421:
        !           422: /*
        !           423:     pick_up()
        !           424:         Add something to characters pack.
        !           425: */
        !           426:
        !           427: void
        !           428: pick_up(char ch)
        !           429: {
        !           430:     switch(ch)
        !           431:     {
        !           432:         default:
        !           433:             debug("Where did you pick that up???");
        !           434:             break;
        !           435:
        !           436:         case GOLD:
        !           437:         case ARMOR:
        !           438:         case POTION:
        !           439:         case FOOD:
        !           440:         case WEAPON:
        !           441:         case SCROLL:
        !           442:         case ARTIFACT:
        !           443:         case RING:
        !           444:         case STICK:
        !           445:             add_pack(NULL, MESSAGE);
        !           446:             break;
        !           447:     }
        !           448: }
        !           449:
        !           450: /*
        !           451:     get_object()
        !           452:
        !           453:         Pick something out of a pack for a purpose. The basic idea is to
        !           454:         list all the possibilities, let the user select one, get that item
        !           455:         from the container, and pass it back to the calling routine.
        !           456: */
        !           457:
        !           458: struct object *
        !           459: get_object(struct linked_list *container, char *purpose, int type, int (*bff_p)(struct object *obj, bag_arg *junk))
        !           460: /* char    *container;    what container has what we want               */
        !           461: /* char    *purpose;      a message (verb) to print if we cant find any */
        !           462: /* char    type;          type (o_type) to pick out (NULL = any)        */
        !           463: /* int     (*bff_p) ();   bag filter function to test item              */
        !           464: {
        !           465:     struct object   *obj_p = NULL;
        !           466:     char sel_id;   /* selected type and id */
        !           467:     int  sel_type;
        !           468:     char response;
        !           469:
        !           470:     if (container == NULL)
        !           471:     {
        !           472:         msg("There isn't anything in there.");
        !           473:         after = FALSE;
        !           474:         return(NULL);
        !           475:     }
        !           476:
        !           477:     /* Make sure we have at least one item that qualifies! */
        !           478:
        !           479:     if (apply_to_bag(container, type, bff_p, NULL, NULL) == NULL)
        !           480:     {
        !           481:         msg("You seem to have nothing to %s.", purpose);
        !           482:         after = FALSE;
        !           483:         return(NULL);
        !           484:     }
        !           485:
        !           486:     while (obj_p == NULL)
        !           487:     {
        !           488:         if (type == 0)
        !           489:         {
        !           490:             msg("What kind of item <%s> do you want to %s (* for list)?", type_list, purpose);
        !           491:
        !           492:             response = readchar();
        !           493:             ESCAPE_EXIT(response);
        !           494:             msg("");
        !           495:
        !           496:             if (response == '*')
        !           497:             {
        !           498:                 add_line("! Potion");
        !           499:                 add_line("? Scroll");
        !           500:                 add_line("= Ring");
        !           501:                 add_line("/ Stick");
        !           502:                 add_line("] Armor");
        !           503:                 add_line(") Weapon");
        !           504:                 add_line(": Food");
        !           505:                 end_line();
        !           506:                 continue;
        !           507:             }
        !           508:
        !           509:
        !           510:             if (!is_member(type_list, response)) { beep();
        !           511:                continue; }
        !           512:
        !           513:
        !           514:             if (count_bag(container, response, NULL) == 0)
        !           515:             {
        !           516:                 msg("You don't have any %s.", name_type(response));
        !           517:                 continue;
        !           518:             }
        !           519:
        !           520:             type = response;
        !           521:         }
        !           522:
        !           523:         while(obj_p == NULL)
        !           524:         {
        !           525:             msg("What item do you want to %s (* for list)?", purpose);
        !           526:             response = readchar();
        !           527:             msg("");
        !           528:             ESCAPE_EXIT(response);
        !           529:
        !           530:             if (response == '*')
        !           531:             {
        !           532:                 mpos = 0;
        !           533:                 apply_to_bag(container, type, bff_p, baf_print_item, &type);
        !           534:                 end_line();
        !           535:                 continue;
        !           536:             }
        !           537:
        !           538:             sel_type = type;
        !           539:             sel_id = response;
        !           540:
        !           541:             obj_p = scan_bag(container, sel_type,unprint_id(&sel_id));
        !           542:         }
        !           543:     }
        !           544:
        !           545:     mpos = 0;
        !           546:     msg("");
        !           547:     return(obj_p);
        !           548: }
        !           549:
        !           550: /*
        !           551:     get_item()
        !           552:
        !           553:         This is only an interim function that serves as an interface to
        !           554:         the old function get_item and its replacement get_object. It
        !           555:         assumes a NULL action routine and allocates a linked_list
        !           556:         structure on top of the object pointer.
        !           557: */
        !           558:
        !           559: struct linked_list *
        !           560: get_item(char *purpose, int type)
        !           561: {
        !           562:     struct object   *obj_p;
        !           563:
        !           564:     if ((obj_p = get_object(pack, purpose, type, NULL)) == NULL)
        !           565:         return(NULL);
        !           566:
        !           567:     return(make_item(obj_p));
        !           568: }
        !           569:
        !           570: /*
        !           571:     del_pack()
        !           572:         Take something out of the hero's pack and throw it away.
        !           573: */
        !           574:
        !           575: void
        !           576: del_pack(struct linked_list *what)
        !           577: {
        !           578:     rem_pack(OBJPTR(what));
        !           579:     discard(what);
        !           580: }
        !           581:
        !           582: /*
        !           583:     discard_pack
        !           584:         take an object from the pack and throw it away (like del_pack,
        !           585:         but without the linked_list structure)
        !           586: */
        !           587:
        !           588: void
        !           589: discard_pack(struct object *obj_p)
        !           590: {
        !           591:     rem_pack(obj_p);
        !           592:     throw_away(obj_p);
        !           593: }
        !           594:
        !           595: /*
        !           596:     rem_pack()
        !           597:         Removes an item from the pack.
        !           598: */
        !           599:
        !           600: void
        !           601: rem_pack(struct object *obj_p)
        !           602: {
        !           603:     cur_null(obj_p);    /* check for current stuff */
        !           604:     pop_bag(&pack, obj_p);
        !           605:     updpack();
        !           606:     return;      /* tell caller an item has been removed */
        !           607: }
        !           608:
        !           609: /*
        !           610:     cur_null()
        !           611:         This updates cur_weapon etc for dropping things
        !           612: */
        !           613:
        !           614: void
        !           615: cur_null(struct object *op)
        !           616: {
        !           617:     if (op == cur_weapon)
        !           618:         cur_weapon = NULL;
        !           619:     else if (op == cur_armor)
        !           620:         cur_armor = NULL;
        !           621:     else if (op == cur_ring[LEFT_1])
        !           622:         cur_ring[LEFT_1] = NULL;
        !           623:     else if (op == cur_ring[LEFT_2])
        !           624:         cur_ring[LEFT_2] = NULL;
        !           625:     else if (op == cur_ring[LEFT_3])
        !           626:         cur_ring[LEFT_3] = NULL;
        !           627:     else if (op == cur_ring[LEFT_4])
        !           628:         cur_ring[LEFT_4] = NULL;
        !           629:     else if (op == cur_ring[LEFT_5])
        !           630:         cur_ring[LEFT_5] = NULL;
        !           631:     else if (op == cur_ring[RIGHT_1])
        !           632:         cur_ring[RIGHT_1] = NULL;
        !           633:     else if (op == cur_ring[RIGHT_2])
        !           634:         cur_ring[RIGHT_2] = NULL;
        !           635:     else if (op == cur_ring[RIGHT_3])
        !           636:         cur_ring[RIGHT_3] = NULL;
        !           637:     else if (op == cur_ring[RIGHT_4])
        !           638:         cur_ring[RIGHT_4] = NULL;
        !           639:     else if (op == cur_ring[RIGHT_5])
        !           640:         cur_ring[RIGHT_5] = NULL;
        !           641: }
        !           642:
        !           643: /*
        !           644:     idenpack()
        !           645:         Identify all the items in the pack
        !           646: */
        !           647:
        !           648: void
        !           649: idenpack(void)
        !           650: {
        !           651:     apply_to_bag(pack, 0, NULL, baf_identify, NULL);
        !           652: }
        !           653:
        !           654: /*
        !           655:     show_floor()
        !           656:         Print out the item on the floor.  Used by the move command.
        !           657: */
        !           658:
        !           659: void
        !           660: show_floor(void)
        !           661: {
        !           662:     struct linked_list  *item;
        !           663:     struct object   *obj;
        !           664:
        !           665:     item = find_obj(hero.y, hero.x);
        !           666:
        !           667:     if (item != NULL)
        !           668:     {
        !           669:         addmsg("%s onto ", terse ? "Moved" : "You moved");
        !           670:
        !           671:         obj = OBJPTR(item);
        !           672:
        !           673:         if (obj->next_obj != NULL)
        !           674:                    msg("a stack of things.");
        !           675:                else if (obj->o_type == GOLD)
        !           676:             msg("%d gold pieces.", obj->o_count);
        !           677:         else
        !           678:         {
        !           679:             addmsg(inv_name(obj, TRUE));
        !           680:             addmsg(".");
        !           681:             endmsg();
        !           682:         }
        !           683:     }
        !           684: }

CVSweb