home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / rogue / pack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  11.6 KB  |  571 lines

  1. /*
  2.  * Copyright (c) 1988 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Timothy C. Stoehr.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)pack.c    5.3 (Berkeley) 6/1/90";
  39. #endif /* not lint */
  40.  
  41. /*
  42.  * pack.c
  43.  *
  44.  * This source herein may be modified and/or distributed by anybody who
  45.  * so desires, with the following restrictions:
  46.  *    1.)  No portion of this notice shall be removed.
  47.  *    2.)  Credit shall not be taken for the creation of this source.
  48.  *    3.)  This code is not to be traded, sold, or used for personal
  49.  *         gain or profit.
  50.  *
  51.  */
  52.  
  53. #include "rogue.h"
  54.  
  55. char *curse_message = "you can't, it appears to be cursed";
  56.  
  57. extern short levitate;
  58.  
  59. object *
  60. add_to_pack(obj, pack, condense)
  61. object *obj, *pack;
  62. {
  63.     object *op;
  64.  
  65.     if (condense) {
  66.         if (op = check_duplicate(obj, pack)) {
  67.             free_object(obj);
  68.             return(op);
  69.         } else {
  70.             obj->ichar = next_avail_ichar();
  71.         }
  72.     }
  73.     if (pack->next_object == 0) {
  74.         pack->next_object = obj;
  75.     } else {
  76.         op = pack->next_object;
  77.  
  78.         while (op->next_object) {
  79.             op = op->next_object;
  80.         }
  81.         op->next_object = obj;
  82.     }
  83.     obj->next_object = 0;
  84.     return(obj);
  85. }
  86.  
  87. take_from_pack(obj, pack)
  88. object *obj, *pack;
  89. {
  90.     while (pack->next_object != obj) {
  91.         pack = pack->next_object;
  92.     }
  93.     pack->next_object = pack->next_object->next_object;
  94. }
  95.  
  96. /* Note: *status is set to 0 if the rogue attempts to pick up a scroll
  97.  * of scare-monster and it turns to dust.  *status is otherwise set to 1.
  98.  */
  99.  
  100. object *
  101. pick_up(row, col, status)
  102. short *status;
  103. {
  104.     object *obj;
  105.  
  106.     *status = 1;
  107.  
  108.     if (levitate) {
  109.         message("you're floating in the air!", 0);
  110.         return((object *) 0);
  111.     }
  112.     obj = object_at(&level_objects, row, col);
  113.     if (!obj) {
  114.         message("pick_up(): inconsistent", 1);
  115.         return(obj);
  116.     }
  117.     if (    (obj->what_is == SCROL) &&
  118.             (obj->which_kind == SCARE_MONSTER) &&
  119.             obj->picked_up) {
  120.         message("the scroll turns to dust as you pick it up", 0);
  121.         dungeon[row][col] &= (~OBJECT);
  122.         vanish(obj, 0, &level_objects);
  123.         *status = 0;
  124.         if (id_scrolls[SCARE_MONSTER].id_status == UNIDENTIFIED) {
  125.             id_scrolls[SCARE_MONSTER].id_status = IDENTIFIED;
  126.         }
  127.         return((object *) 0);
  128.     }
  129.     if (obj->what_is == GOLD) {
  130.         rogue.gold += obj->quantity;
  131.         dungeon[row][col] &= ~(OBJECT);
  132.         take_from_pack(obj, &level_objects);
  133.         print_stats(STAT_GOLD);
  134.         return(obj);    /* obj will be free_object()ed in caller */
  135.     }
  136.     if (pack_count(obj) >= MAX_PACK_COUNT) {
  137.         message("pack too full", 1);
  138.         return((object *) 0);
  139.     }
  140.     dungeon[row][col] &= ~(OBJECT);
  141.     take_from_pack(obj, &level_objects);
  142.     obj = add_to_pack(obj, &rogue.pack, 1);
  143.     obj->picked_up = 1;
  144.     return(obj);
  145. }
  146.  
  147. drop()
  148. {
  149.     object *obj, *new;
  150.     short ch;
  151.     char desc[DCOLS];
  152.  
  153.     if (dungeon[rogue.row][rogue.col] & (OBJECT | STAIRS | TRAP)) {
  154.         message("there's already something there", 0);
  155.         return;
  156.     }
  157.     if (!rogue.pack.next_object) {
  158.         message("you have nothing to drop", 0);
  159.         return;
  160.     }
  161.     if ((ch = pack_letter("drop what?", ALL_OBJECTS)) == CANCEL) {
  162.         return;
  163.     }
  164.     if (!(obj = get_letter_object(ch))) {
  165.         message("no such item.", 0);
  166.         return;
  167.     }
  168.     if (obj->in_use_flags & BEING_WIELDED) {
  169.         if (obj->is_cursed) {
  170.             message(curse_message, 0);
  171.             return;
  172.         }
  173.         unwield(rogue.weapon);
  174.     } else if (obj->in_use_flags & BEING_WORN) {
  175.         if (obj->is_cursed) {
  176.             message(curse_message, 0);
  177.             return;
  178.         }
  179.         mv_aquatars();
  180.         unwear(rogue.armor);
  181.         print_stats(STAT_ARMOR);
  182.     } else if (obj->in_use_flags & ON_EITHER_HAND) {
  183.         if (obj->is_cursed) {
  184.             message(curse_message, 0);
  185.             return;
  186.         }
  187.         un_put_on(obj);
  188.     }
  189.     obj->row = rogue.row;
  190.     obj->col = rogue.col;
  191.  
  192.     if ((obj->quantity > 1) && (obj->what_is != WEAPON)) {
  193.         obj->quantity--;
  194.         new = alloc_object();
  195.         *new = *obj;
  196.         new->quantity = 1;
  197.         obj = new;
  198.     } else {
  199.         obj->ichar = 'L';
  200.         take_from_pack(obj, &rogue.pack);
  201.     }
  202.     place_at(obj, rogue.row, rogue.col);
  203.     (void) strcpy(desc, "dropped ");
  204.     get_desc(obj, desc+8);
  205.     message(desc, 0);
  206.     (void) reg_move();
  207. }
  208.  
  209. object *
  210. check_duplicate(obj, pack)
  211. object *obj, *pack;
  212. {
  213.     object *op;
  214.  
  215.     if (!(obj->what_is & (WEAPON | FOOD | SCROL | POTION))) {
  216.         return(0);
  217.     }
  218.     if ((obj->what_is == FOOD) && (obj->which_kind == FRUIT)) {
  219.         return(0);
  220.     }
  221.     op = pack->next_object;
  222.  
  223.     while (op) {
  224.         if ((op->what_is == obj->what_is) && 
  225.             (op->which_kind == obj->which_kind)) {
  226.  
  227.             if ((obj->what_is != WEAPON) ||
  228.             ((obj->what_is == WEAPON) &&
  229.             ((obj->which_kind == ARROW) ||
  230.             (obj->which_kind == DAGGER) ||
  231.             (obj->which_kind == DART) ||
  232.             (obj->which_kind == SHURIKEN)) &&
  233.             (obj->quiver == op->quiver))) {
  234.                 op->quantity += obj->quantity;
  235.                 return(op);
  236.             }
  237.         }
  238.         op = op->next_object;
  239.     }
  240.     return(0);
  241. }
  242.  
  243. next_avail_ichar()
  244. {
  245.     register object *obj;
  246.     register i;
  247.     boolean ichars[26];
  248.  
  249.     for (i = 0; i < 26; i++) {
  250.         ichars[i] = 0;
  251.     }
  252.     obj = rogue.pack.next_object;
  253.     while (obj) {
  254.         ichars[(obj->ichar - 'a')] = 1;
  255.         obj = obj->next_object;
  256.     }
  257.     for (i = 0; i < 26; i++) {
  258.         if (!ichars[i]) {
  259.             return(i + 'a');
  260.         }
  261.     }
  262.     return('?');
  263. }
  264.  
  265. wait_for_ack()
  266. {
  267.     while (rgetchar() != ' ') ;
  268. }
  269.  
  270. pack_letter(prompt, mask)
  271. char *prompt;
  272. unsigned short mask;
  273. {
  274.     short ch;
  275.     unsigned short tmask = mask;
  276.  
  277.     if (!mask_pack(&rogue.pack, mask)) {
  278.         message("nothing appropriate", 0);
  279.         return(CANCEL);
  280.     }
  281.     for (;;) {
  282.  
  283.         message(prompt, 0);
  284.  
  285.         for (;;) {
  286.             ch = rgetchar();
  287.             if (!is_pack_letter(&ch, &mask)) {
  288.                 sound_bell();
  289.             } else {
  290.                 break;
  291.             }
  292.         }
  293.  
  294.         if (ch == LIST) {
  295.             check_message();
  296.             inventory(&rogue.pack, mask);
  297.         } else {
  298.             break;
  299.         }
  300.         mask = tmask;
  301.     }
  302.     check_message();
  303.     return(ch);
  304. }
  305.  
  306. take_off()
  307. {
  308.     char desc[DCOLS];
  309.     object *obj;
  310.  
  311.     if (rogue.armor) {
  312.         if (rogue.armor->is_cursed) {
  313.             message(curse_message, 0);
  314.         } else {
  315.             mv_aquatars();
  316.             obj = rogue.armor;
  317.             unwear(rogue.armor);
  318.             (void) strcpy(desc, "was wearing ");
  319.             get_desc(obj, desc+12);
  320.             message(desc, 0);
  321.             print_stats(STAT_ARMOR);
  322.             (void) reg_move();
  323.         }
  324.     } else {
  325.         message("not wearing any", 0);
  326.     }
  327. }
  328.  
  329. wear()
  330. {
  331.     short ch;
  332.     register object *obj;
  333.     char desc[DCOLS];
  334.  
  335.     if (rogue.armor) {
  336.         message("your already wearing some", 0);
  337.         return;
  338.     }
  339.     ch = pack_letter("wear what?", ARMOR);
  340.  
  341.     if (ch == CANCEL) {
  342.         return;
  343.     }
  344.     if (!(obj = get_letter_object(ch))) {
  345.         message("no such item.", 0);
  346.         return;
  347.     }
  348.     if (obj->what_is != ARMOR) {
  349.         message("you can't wear that", 0);
  350.         return;
  351.     }
  352.     obj->identified = 1;
  353.     (void) strcpy(desc, "wearing ");
  354.     get_desc(obj, desc + 8);
  355.     message(desc, 0);
  356.     do_wear(obj);
  357.     print_stats(STAT_ARMOR);
  358.     (void) reg_move();
  359. }
  360.  
  361. unwear(obj)
  362. object *obj;
  363. {
  364.     if (obj) {
  365.         obj->in_use_flags &= (~BEING_WORN);
  366.     }
  367.     rogue.armor = (object *) 0;
  368. }
  369.  
  370. do_wear(obj)
  371. object *obj;
  372. {
  373.     rogue.armor = obj;
  374.     obj->in_use_flags |= BEING_WORN;
  375.     obj->identified = 1;
  376. }
  377.  
  378. wield()
  379. {
  380.     short ch;
  381.     register object *obj;
  382.     char desc[DCOLS];
  383.  
  384.     if (rogue.weapon && rogue.weapon->is_cursed) {
  385.         message(curse_message, 0);
  386.         return;
  387.     }
  388.     ch = pack_letter("wield what?", WEAPON);
  389.  
  390.     if (ch == CANCEL) {
  391.         return;
  392.     }
  393.     if (!(obj = get_letter_object(ch))) {
  394.         message("No such item.", 0);
  395.         return;
  396.     }
  397.     if (obj->what_is & (ARMOR | RING)) {
  398.         sprintf(desc, "you can't wield %s",
  399.             ((obj->what_is == ARMOR) ? "armor" : "rings"));
  400.         message(desc, 0);
  401.         return;
  402.     }
  403.     if (obj->in_use_flags & BEING_WIELDED) {
  404.         message("in use", 0);
  405.     } else {
  406.         unwield(rogue.weapon);
  407.         (void) strcpy(desc, "wielding ");
  408.         get_desc(obj, desc + 9);
  409.         message(desc, 0);
  410.         do_wield(obj);
  411.         (void) reg_move();
  412.     }
  413. }
  414.  
  415. do_wield(obj)
  416. object *obj;
  417. {
  418.     rogue.weapon = obj;
  419.     obj->in_use_flags |= BEING_WIELDED;
  420. }
  421.  
  422. unwield(obj)
  423. object *obj;
  424. {
  425.     if (obj) {
  426.         obj->in_use_flags &= (~BEING_WIELDED);
  427.     }
  428.     rogue.weapon = (object *) 0;
  429. }
  430.  
  431. call_it()
  432. {
  433.     short ch;
  434.     register object *obj;
  435.     struct id *id_table;
  436.     char buf[MAX_TITLE_LENGTH+2];
  437.  
  438.     ch = pack_letter("call what?", (SCROL | POTION | WAND | RING));
  439.  
  440.     if (ch == CANCEL) {
  441.         return;
  442.     }
  443.     if (!(obj = get_letter_object(ch))) {
  444.         message("no such item.", 0);
  445.         return;
  446.     }
  447.     if (!(obj->what_is & (SCROL | POTION | WAND | RING))) {
  448.         message("surely you already know what that's called", 0);
  449.         return;
  450.     }
  451.     id_table = get_id_table(obj);
  452.  
  453.     if (get_input_line("call it:","",buf,id_table[obj->which_kind].title,1,1)) {
  454.         id_table[obj->which_kind].id_status = CALLED;
  455.         (void) strcpy(id_table[obj->which_kind].title, buf);
  456.     }
  457. }
  458.  
  459. pack_count(new_obj)
  460. object *new_obj;
  461. {
  462.     object *obj;
  463.     short count = 0;
  464.  
  465.     obj = rogue.pack.next_object;
  466.  
  467.     while (obj) {
  468.         if (obj->what_is != WEAPON) {
  469.             count += obj->quantity;
  470.         } else if (!new_obj) {
  471.             count++;
  472.         } else if ((new_obj->what_is != WEAPON) ||
  473.             ((obj->which_kind != ARROW) &&
  474.             (obj->which_kind != DAGGER) &&
  475.             (obj->which_kind != DART) &&
  476.             (obj->which_kind != SHURIKEN)) ||
  477.             (new_obj->which_kind != obj->which_kind) ||
  478.             (obj->quiver != new_obj->quiver)) {
  479.             count++;
  480.         }
  481.         obj = obj->next_object;
  482.     }
  483.     return(count);
  484. }
  485.  
  486. boolean
  487. mask_pack(pack, mask)
  488. object *pack;
  489. unsigned short mask;
  490. {
  491.     while (pack->next_object) {
  492.         pack = pack->next_object;
  493.         if (pack->what_is & mask) {
  494.             return(1);
  495.         }
  496.     }
  497.     return(0);
  498. }
  499.  
  500. is_pack_letter(c, mask)
  501. short *c;
  502. unsigned short *mask;
  503. {
  504.     if (((*c == '?') || (*c == '!') || (*c == ':') || (*c == '=') ||
  505.         (*c == ')') || (*c == ']') || (*c == '/') || (*c == ','))) {
  506.         switch(*c) {
  507.         case '?':
  508.             *mask = SCROL;
  509.             break;
  510.         case '!':
  511.             *mask = POTION;
  512.             break;
  513.         case ':':
  514.             *mask = FOOD;
  515.             break;
  516.         case ')':
  517.             *mask = WEAPON;
  518.             break;
  519.         case ']':
  520.             *mask = ARMOR;
  521.             break;
  522.         case '/':
  523.             *mask = WAND;
  524.             break;
  525.         case '=':
  526.             *mask = RING;
  527.             break;
  528.         case ',':
  529.             *mask = AMULET;
  530.             break;
  531.         }
  532.         *c = LIST;
  533.         return(1);
  534.     }
  535.     return(((*c >= 'a') && (*c <= 'z')) || (*c == CANCEL) || (*c == LIST));
  536. }
  537.  
  538. has_amulet()
  539. {
  540.     return(mask_pack(&rogue.pack, AMULET));
  541. }
  542.  
  543. kick_into_pack()
  544. {
  545.     object *obj;
  546.     char desc[DCOLS];
  547.     short n, stat;
  548.  
  549.     if (!(dungeon[rogue.row][rogue.col] & OBJECT)) {
  550.         message("nothing here", 0);
  551.     } else {
  552.         if (obj = pick_up(rogue.row, rogue.col, &stat)) {
  553.             get_desc(obj, desc);
  554.             if (obj->what_is == GOLD) {
  555.                 message(desc, 0);
  556.                 free_object(obj);
  557.             } else {
  558.                 n = strlen(desc);
  559.                 desc[n] = '(';
  560.                 desc[n+1] = obj->ichar;
  561.                 desc[n+2] = ')';
  562.                 desc[n+3] = 0;
  563.                 message(desc, 0);
  564.             }
  565.         }
  566.         if (obj || (!stat)) {
  567.             (void) reg_move();
  568.         }
  569.     }
  570. }
  571.