home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / d / d-linux.zip / dm-dist / handler.c < prev    next >
C/C++ Source or Header  |  1991-03-01  |  28KB  |  1,315 lines

  1. /* ************************************************************************
  2. *  file: handler.c , Handler module.                      Part of DIKUMUD *
  3. *  Usage: Various routines for moving about objects/players               *
  4. *  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
  5. ************************************************************************* */
  6.     
  7. #include <string.h>
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include <assert.h>
  11.  
  12. #include "structs.h"
  13. #include "utils.h"
  14. #include "comm.h"
  15. #include "db.h"
  16. #include "handler.h"
  17.  
  18. extern struct room_data *world;
  19. extern struct obj_data  *object_list;
  20. extern struct char_data *character_list;
  21. extern struct index_data *mob_index;
  22. extern struct index_data *obj_index;
  23. extern struct descriptor_data *descriptor_list;
  24.  
  25. /* External procedures */
  26.  
  27. int str_cmp(char *arg1, char *arg2);
  28. void free_char(struct char_data *ch);
  29. void stop_fighting(struct char_data *ch);
  30. void remove_follower(struct char_data *ch);
  31.  
  32.  
  33.  
  34. char *fname(char *namelist)
  35. {
  36.     static char holder[30];
  37.     register char *point;
  38.  
  39.     for (point = holder; isalpha(*namelist); namelist++, point++)
  40.         *point = *namelist;
  41.  
  42.     *point = '\0';
  43.  
  44.     return(holder);
  45. }
  46.  
  47. int isname(char *str, char *namelist)
  48. {
  49.     register char *curname, *curstr;
  50.  
  51.     curname = namelist;
  52.     for (;;)
  53.     {
  54.         for (curstr = str;; curstr++, curname++)
  55.         {
  56.             if (!*curstr && !isalpha(*curname))
  57.                 return(1);
  58.  
  59.             if (!*curname)
  60.                 return(0);
  61.  
  62.             if (!*curstr || *curname == ' ')
  63.                 break;
  64.  
  65.             if (LOWER(*curstr) != LOWER(*curname))
  66.                 break;
  67.         }
  68.  
  69.         /* skip to next name */
  70.  
  71.         for (; isalpha(*curname); curname++);
  72.         if (!*curname)
  73.             return(0);
  74.         curname++;            /* first char of new name */
  75.     }
  76. }
  77.  
  78.  
  79.  
  80. void affect_modify(struct char_data *ch, byte loc, byte mod, long bitv, bool add)
  81. {
  82.     int maxabil;
  83.  
  84.     if (add) {
  85.         SET_BIT(ch->specials.affected_by, bitv);
  86.     } else {
  87.         REMOVE_BIT(ch->specials.affected_by, bitv);
  88.         mod = -mod;
  89.     }
  90.  
  91.  
  92.     maxabil = (IS_NPC(ch) ? 25:18);
  93.  
  94.     switch(loc)
  95.     {
  96.         case APPLY_NONE:
  97.             break;
  98.  
  99.         case APPLY_STR:
  100.             GET_STR(ch) += mod;
  101.             break;
  102.  
  103.         case APPLY_DEX:
  104.             GET_DEX(ch) += mod;
  105.             break;
  106.  
  107.         case APPLY_INT:
  108.             GET_INT(ch) += mod;
  109.             break;
  110.  
  111.         case APPLY_WIS:
  112.             GET_WIS(ch) += mod;
  113.             break;
  114.  
  115.         case APPLY_CON:
  116.             GET_CON(ch) += mod;
  117.             break;
  118.  
  119.         case APPLY_SEX:
  120.             /* ??? GET_SEX(ch) += mod; */
  121.             break;
  122.  
  123.         case APPLY_CLASS:
  124.             /* ??? GET_CLASS(ch) += mod; */
  125.             break;
  126.  
  127.         case APPLY_LEVEL:
  128.             /* ??? GET_LEVEL(ch) += mod; */
  129.             break;
  130.  
  131.         case APPLY_AGE:
  132. /*            ch->player.time.birth += mod; */
  133.             break;
  134.  
  135.         case APPLY_CHAR_WEIGHT:
  136.             GET_WEIGHT(ch) += mod;
  137.             break;
  138.  
  139.         case APPLY_CHAR_HEIGHT:
  140.             GET_HEIGHT(ch) += mod;
  141.             break;
  142.  
  143.         case APPLY_MANA:
  144.             break;
  145.  
  146.         case APPLY_HIT:
  147.             ch->points.max_hit += mod;
  148.             break;
  149.  
  150.         case APPLY_MOVE:
  151.             /* Will change nothing on playes ch->points.max_move += mod; */
  152.             break;
  153.  
  154.         case APPLY_GOLD:
  155.             break;
  156.  
  157.         case APPLY_EXP:
  158.             break;
  159.  
  160.         case APPLY_AC:
  161.             GET_AC(ch) += mod;
  162.             break;
  163.  
  164.         case APPLY_HITROLL:
  165.             GET_HITROLL(ch) += mod;
  166.             break;
  167.  
  168.         case APPLY_DAMROLL:
  169.             GET_DAMROLL(ch) += mod;
  170.             break;
  171.  
  172.         case APPLY_SAVING_PARA:
  173.             ch->specials.apply_saving_throw[0] += mod;
  174.             break;
  175.  
  176.         case APPLY_SAVING_ROD:
  177.             ch->specials.apply_saving_throw[1] += mod;
  178.             break;
  179.  
  180.         case APPLY_SAVING_PETRI:
  181.             ch->specials.apply_saving_throw[2] += mod;
  182.             break;
  183.  
  184.         case APPLY_SAVING_BREATH:
  185.             ch->specials.apply_saving_throw[3] += mod;
  186.             break;
  187.  
  188.         case APPLY_SAVING_SPELL:
  189.             ch->specials.apply_saving_throw[4] += mod;
  190.             break;
  191.  
  192.         default:
  193.             log("Unknown apply adjust attempt (handler.c, affect_modify).");
  194.             break;
  195.  
  196.     } /* switch */
  197. }
  198.  
  199.  
  200.  
  201. /* This updates a character by subtracting everything he is affected by */
  202. /* restoring original abilities, and then affecting all again           */
  203. void affect_total(struct char_data *ch)
  204. {
  205.     struct affected_type *af;
  206.     int i,j;
  207.  
  208.     for(i=0; i<MAX_WEAR; i++) {
  209.         if (ch->equipment[i])
  210.             for(j=0; j<MAX_OBJ_AFFECT; j++)
  211.                 affect_modify(ch, ch->equipment[i]->affected[j].location,
  212.                               ch->equipment[i]->affected[j].modifier,
  213.                               ch->equipment[i]->obj_flags.bitvector, FALSE);
  214.     }
  215.  
  216.  
  217.     for(af = ch->affected; af; af=af->next)
  218.         affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE);
  219.  
  220.     ch->tmpabilities = ch->abilities;
  221.  
  222.     for(i=0; i<MAX_WEAR; i++) {
  223.         if (ch->equipment[i])
  224.             for(j=0; j<MAX_OBJ_AFFECT; j++)
  225.                 affect_modify(ch, ch->equipment[i]->affected[j].location,
  226.                               ch->equipment[i]->affected[j].modifier,
  227.                               ch->equipment[i]->obj_flags.bitvector, TRUE);
  228.     }
  229.  
  230.  
  231.     for(af = ch->affected; af; af=af->next)
  232.         affect_modify(ch, af->location, af->modifier, af->bitvector, TRUE);
  233.  
  234.     /* Make certain values are between 0..25, not < 0 and not > 25! */
  235.  
  236.     i = (IS_NPC(ch) ? 25 :18);
  237.  
  238.     GET_DEX(ch) = MAX(0,MIN(GET_DEX(ch), i));
  239.     GET_INT(ch) = MAX(0,MIN(GET_INT(ch), i));
  240.     GET_WIS(ch) = MAX(0,MIN(GET_WIS(ch), i));
  241.     GET_CON(ch) = MAX(0,MIN(GET_CON(ch), i));
  242.     GET_STR(ch) = MAX(0,GET_STR(ch));
  243.  
  244.     if (IS_NPC(ch)) {
  245.         GET_STR(ch) = MIN(GET_STR(ch), i);
  246.     } else {
  247.         if (GET_STR(ch) > 18) {
  248.             i = GET_ADD(ch) + ((GET_STR(ch)-18)*10);
  249.             GET_ADD(ch) = MIN(i, 100);
  250.             GET_STR(ch) = 18;
  251.         }
  252.     }
  253. }
  254.  
  255.  
  256.  
  257. /* Insert an affect_type in a char_data structure
  258.    Automatically sets apropriate bits and apply's */
  259. void affect_to_char( struct char_data *ch, struct affected_type *af )
  260. {
  261.     struct affected_type *affected_alloc;
  262.  
  263.     CREATE(affected_alloc, struct affected_type, 1);
  264.  
  265.     *affected_alloc = *af;
  266.     affected_alloc->next = ch->affected;
  267.     ch->affected = affected_alloc;
  268.  
  269.     affect_modify(ch, af->location, af->modifier,
  270.                   af->bitvector, TRUE);
  271.     affect_total(ch);
  272. }
  273.  
  274.  
  275.  
  276. /* Remove an affected_type structure from a char (called when duration
  277.    reaches zero). Pointer *af must never be NIL! Frees mem and calls 
  278.    affect_location_apply                                                */
  279. void affect_remove( struct char_data *ch, struct affected_type *af )
  280. {
  281.     struct affected_type *hjp;
  282.  
  283.     assert(ch->affected);
  284.  
  285.     affect_modify(ch, af->location, af->modifier,
  286.                   af->bitvector, FALSE);
  287.  
  288.  
  289.     /* remove structure *af from linked list */
  290.  
  291.     if (ch->affected == af) {
  292.         /* remove head of list */
  293.         ch->affected = af->next;
  294.     } else {
  295.  
  296.         for(hjp = ch->affected; (hjp->next) && (hjp->next != af); hjp = hjp->next);
  297.  
  298.         if (hjp->next != af) {
  299.             log("FATAL : Could not locate affected_type in ch->affected. (handler.c, affect_remove)");
  300.             exit(1);
  301.         }
  302.         hjp->next = af->next; /* skip the af element */
  303.     }
  304.  
  305.     free ( af );
  306.  
  307.     affect_total(ch);
  308. }
  309.  
  310.  
  311.  
  312. /* Call affect_remove with every spell of spelltype "skill" */
  313. void affect_from_char( struct char_data *ch, byte skill)
  314. {
  315.     struct affected_type *hjp;
  316.  
  317.     for(hjp = ch->affected; hjp; hjp = hjp->next)
  318.         if (hjp->type == skill)
  319.             affect_remove( ch, hjp );
  320.  
  321. }
  322.  
  323.  
  324.  
  325. /* Return if a char is affected by a spell (SPELL_XXX), NULL indicates 
  326.    not affected                                                        */
  327. bool affected_by_spell( struct char_data *ch, byte skill )
  328. {
  329.     struct affected_type *hjp;
  330.  
  331.     for (hjp = ch->affected; hjp; hjp = hjp->next)
  332.         if ( hjp->type == skill )
  333.             return( TRUE );
  334.  
  335.     return( FALSE );
  336. }
  337.  
  338.  
  339.  
  340. void affect_join( struct char_data *ch, struct affected_type *af,
  341.                   bool avg_dur, bool avg_mod )
  342. {
  343.     struct affected_type *hjp;
  344.     bool found = FALSE;
  345.  
  346.     for (hjp = ch->affected; !found && hjp; hjp = hjp->next) {
  347.         if ( hjp->type == af->type ) {
  348.             
  349.             af->duration += hjp->duration;
  350.             if (avg_dur)
  351.                 af->duration /= 2;
  352.  
  353.             af->modifier += hjp->modifier;
  354.             if (avg_mod)
  355.                 af->modifier /= 2;
  356.  
  357.             affect_remove(ch, hjp);
  358.             affect_to_char(ch, af);
  359.             found = TRUE;
  360.         }
  361.     }
  362.     if (!found)
  363.         affect_to_char(ch, af);
  364. }
  365.  
  366. /* move a player out of a room */
  367. void char_from_room(struct char_data *ch)
  368. {
  369.     struct char_data *i;
  370.  
  371.     if (ch->in_room == NOWHERE) {
  372.         log("NOWHERE extracting char from room (handler.c, char_from_room)");
  373.         exit(1);
  374.     }
  375.  
  376.     if (ch->equipment[WEAR_LIGHT])
  377.         if (ch->equipment[WEAR_LIGHT]->obj_flags.type_flag == ITEM_LIGHT)
  378.             if (ch->equipment[WEAR_LIGHT]->obj_flags.value[2]) /* Light is ON */
  379.                 world[ch->in_room].light--;
  380.  
  381.     if (ch == world[ch->in_room].people)  /* head of list */
  382.          world[ch->in_room].people = ch->next_in_room;
  383.  
  384.     else    /* locate the previous element */
  385.     {
  386.         for (i = world[ch->in_room].people; 
  387.              i->next_in_room != ch; i = i->next_in_room);
  388.  
  389.          i->next_in_room = ch->next_in_room;
  390.     }
  391.  
  392.     ch->in_room = NOWHERE;
  393.     ch->next_in_room = 0;
  394. }
  395.  
  396.  
  397. /* place a character in a room */
  398. void char_to_room(struct char_data *ch, int room)
  399. {
  400.     void raw_kill(struct char_data *ch);
  401.  
  402.     ch->next_in_room = world[room].people;
  403.     world[room].people = ch;
  404.     ch->in_room = room;
  405.  
  406.     if (ch->equipment[WEAR_LIGHT])
  407.         if (ch->equipment[WEAR_LIGHT]->obj_flags.type_flag == ITEM_LIGHT)
  408.             if (ch->equipment[WEAR_LIGHT]->obj_flags.value[2]) /* Light is ON */
  409.                 world[room].light++;
  410. }
  411.  
  412.  
  413. /* give an object to a char   */
  414. void obj_to_char(struct obj_data *object, struct char_data *ch)
  415. {
  416.     object->next_content = ch->carrying;
  417.     ch->carrying = object;
  418.     object->carried_by = ch;
  419.     object->in_room = NOWHERE;
  420.     IS_CARRYING_W(ch) += GET_OBJ_WEIGHT(object);
  421.     IS_CARRYING_N(ch)++;
  422. }
  423.  
  424.  
  425. /* take an object from a char */
  426. void obj_from_char(struct obj_data *object)
  427. {
  428.     struct obj_data *tmp;
  429.  
  430.     if (object->carried_by->carrying == object)   /* head of list */
  431.          object->carried_by->carrying = object->next_content;
  432.  
  433.     else
  434.     {
  435.         for (tmp = object->carried_by->carrying; 
  436.              tmp && (tmp->next_content != object); 
  437.               tmp = tmp->next_content); /* locate previous */
  438.  
  439.         tmp->next_content = object->next_content;
  440.     }
  441.  
  442.     IS_CARRYING_W(object->carried_by) -= GET_OBJ_WEIGHT(object);
  443.     IS_CARRYING_N(object->carried_by)--;
  444.     object->carried_by = 0;
  445.     object->next_content = 0;
  446. }
  447.  
  448.  
  449.  
  450. /* Return the effect of a piece of armor in position eq_pos */
  451. int apply_ac(struct char_data *ch, int eq_pos)
  452. {
  453.   assert(ch->equipment[eq_pos]);
  454.  
  455.   if (!(GET_ITEM_TYPE(ch->equipment[eq_pos]) == ITEM_ARMOR))
  456.     return 0;
  457.  
  458.   switch (eq_pos) {
  459.  
  460.     case WEAR_BODY:
  461.       return (3*ch->equipment[eq_pos]->obj_flags.value[0]);  /* 30% */
  462.     case WEAR_HEAD:
  463.       return (2*ch->equipment[eq_pos]->obj_flags.value[0]);  /* 20% */
  464.     case WEAR_LEGS:
  465.       return (2*ch->equipment[eq_pos]->obj_flags.value[0]);  /* 20% */
  466.     case WEAR_FEET:
  467.       return (ch->equipment[eq_pos]->obj_flags.value[0]);    /* 10% */
  468.     case WEAR_HANDS:
  469.       return (ch->equipment[eq_pos]->obj_flags.value[0]);    /* 10% */
  470.     case WEAR_ARMS:
  471.       return (ch->equipment[eq_pos]->obj_flags.value[0]);    /* 10% */
  472.     case WEAR_SHIELD:
  473.       return (ch->equipment[eq_pos]->obj_flags.value[0]);    /* 10% */
  474.   }
  475.   return 0;
  476. }
  477.  
  478.  
  479.  
  480. void equip_char(struct char_data *ch, struct obj_data *obj, int pos)
  481. {
  482.     int j;
  483.  
  484.     assert(pos>=0 && pos<MAX_WEAR);
  485.     assert(!(ch->equipment[pos]));
  486.  
  487.     if (obj->carried_by) {
  488.         log("EQUIP: Obj is carried_by when equip.");
  489.         return;
  490.     }
  491.  
  492.     if (obj->in_room!=NOWHERE) {
  493.         log("EQUIP: Obj is in_room when equip.");
  494.         return;
  495.     }
  496.  
  497.     if ((IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) ||
  498.         (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) ||
  499.         (IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch))) {
  500.         if (ch->in_room != NOWHERE) {
  501.  
  502.             act("You are zapped by $p and instantly drop it.", FALSE, ch, obj, 0, TO_CHAR);
  503.             act("$n is zapped by $p and instantly drop it.", FALSE, ch, obj, 0, TO_ROOM);
  504.             obj_to_room(obj, ch->in_room);
  505.             return;
  506.         } else {
  507.             log("ch->in_room = NOWHERE when equipping char.");
  508.         }
  509.     }
  510.  
  511.     ch->equipment[pos] = obj;
  512.  
  513.     if (GET_ITEM_TYPE(obj) == ITEM_ARMOR)
  514.         GET_AC(ch) -= apply_ac(ch, pos);
  515.  
  516.     for(j=0; j<MAX_OBJ_AFFECT; j++)
  517.         affect_modify(ch, obj->affected[j].location,
  518.           obj->affected[j].modifier,
  519.           obj->obj_flags.bitvector, TRUE);
  520.  
  521.     affect_total(ch);
  522. }
  523.  
  524.  
  525.  
  526. struct obj_data *unequip_char(struct char_data *ch, int pos)
  527. {
  528.     int j;
  529.     struct obj_data *obj;
  530.  
  531.     assert(pos>=0 && pos<MAX_WEAR);
  532.     assert(ch->equipment[pos]);
  533.  
  534.     obj = ch->equipment[pos];
  535.     if (GET_ITEM_TYPE(obj) == ITEM_ARMOR)
  536.         GET_AC(ch) += apply_ac(ch, pos);
  537.  
  538.     ch->equipment[pos] = 0;
  539.  
  540.     for(j=0; j<MAX_OBJ_AFFECT; j++)
  541.         affect_modify(ch, obj->affected[j].location,
  542.           obj->affected[j].modifier,
  543.           obj->obj_flags.bitvector, FALSE);
  544.  
  545.     affect_total(ch);
  546.  
  547.     return(obj);
  548. }
  549.  
  550.  
  551. int get_number(char **name) {
  552.  
  553.     int i;
  554.     char *ppos;
  555.   char number[MAX_INPUT_LENGTH] = "";
  556.  
  557.     if (ppos = index(*name, '.')) {
  558.         *ppos++ = '\0';
  559.         strcpy(number,*name);
  560.         strcpy(*name, ppos);
  561.  
  562.         for(i=0; *(number+i); i++)
  563.             if (!isdigit(*(number+i)))
  564.                 return(0);
  565.  
  566.         return(atoi(number));
  567.     }
  568.  
  569.     return(1);
  570. }
  571.  
  572.  
  573. /* Search a given list for an object, and return a pointer to that object */
  574. struct obj_data *get_obj_in_list(char *name, struct obj_data *list)
  575. {
  576.     struct obj_data *i;
  577.     int j, number;
  578.     char tmpname[MAX_INPUT_LENGTH];
  579.   char *tmp;
  580.  
  581.     strcpy(tmpname,name);
  582.     tmp = tmpname;
  583.   if(!(number = get_number(&tmp)))
  584.     return(0);
  585.  
  586.     for (i = list, j = 1; i && (j <= number); i = i->next_content)
  587.         if (isname(tmp, i->name)) {
  588.             if (j == number) 
  589.                 return(i);
  590.             j++;
  591.         }
  592.  
  593.     return(0);
  594. }
  595.  
  596.  
  597.  
  598. /* Search a given list for an object number, and return a ptr to that obj */
  599. struct obj_data *get_obj_in_list_num(int num, struct obj_data *list)
  600. {
  601.     struct obj_data *i;
  602.  
  603.     for (i = list; i; i = i->next_content)
  604.         if (i->item_number == num) 
  605.             return(i);
  606.         
  607.     return(0);
  608. }
  609.  
  610.  
  611.  
  612.  
  613.  
  614. /*search the entire world for an object, and return a pointer  */
  615. struct obj_data *get_obj(char *name)
  616. {
  617.     struct obj_data *i;
  618.     int j, number;
  619.     char tmpname[MAX_INPUT_LENGTH];
  620.     char *tmp;
  621.  
  622.     strcpy(tmpname,name);
  623.     tmp = tmpname;
  624.   if(!(number = get_number(&tmp)))
  625.     return(0);
  626.  
  627.     for (i = object_list, j = 1; i && (j <= number); i = i->next)
  628.         if (isname(tmp, i->name)) {
  629.             if (j == number)
  630.                 return(i);
  631.             j++;
  632.         }
  633.  
  634.     return(0);
  635. }
  636.  
  637.  
  638.  
  639.  
  640.  
  641. /*search the entire world for an object number, and return a pointer  */
  642. struct obj_data *get_obj_num(int nr)
  643. {
  644.     struct obj_data *i;
  645.  
  646.     for (i = object_list; i; i = i->next)
  647.         if (i->item_number == nr) 
  648.             return(i);
  649.  
  650.     return(0);
  651. }
  652.  
  653.  
  654.  
  655.  
  656.  
  657. /* search a room for a char, and return a pointer if found..  */
  658. struct char_data *get_char_room(char *name, int room)
  659. {
  660.     struct char_data *i;
  661.     int j, number;
  662.     char tmpname[MAX_INPUT_LENGTH];
  663.     char *tmp;
  664.  
  665.     strcpy(tmpname,name);
  666.     tmp = tmpname;
  667.     if(!(number = get_number(&tmp)))
  668.     return(0);
  669.  
  670.     for (i = world[room].people, j = 1; i && (j <= number); i = i->next_in_room)
  671.         if (isname(tmp, GET_NAME(i))) {
  672.             if (j == number)
  673.         return(i);
  674.             j++;
  675.         }
  676.  
  677.     return(0);
  678. }
  679.  
  680.  
  681.  
  682.  
  683.  
  684. /* search all over the world for a char, and return a pointer if found */
  685. struct char_data *get_char(char *name)
  686. {
  687.     struct char_data *i;
  688.     int j, number;
  689.     char tmpname[MAX_INPUT_LENGTH];
  690.     char *tmp;
  691.  
  692.     strcpy(tmpname,name);
  693.     tmp = tmpname;
  694.   if(!(number = get_number(&tmp)))
  695.     return(0);
  696.  
  697.     for (i = character_list, j = 1; i && (j <= number); i = i->next)
  698.         if (isname(tmp, GET_NAME(i))) {
  699.             if (j == number)
  700.                 return(i);
  701.             j++;
  702.         }
  703.  
  704.     return(0);
  705. }
  706.  
  707.  
  708.  
  709. /* search all over the world for a char num, and return a pointer if found */
  710. struct char_data *get_char_num(int nr)
  711. {
  712.     struct char_data *i;
  713.  
  714.     for (i = character_list; i; i = i->next)
  715.         if (i->nr == nr)
  716.             return(i);
  717.  
  718.     return(0);
  719. }
  720.  
  721.  
  722.  
  723.  
  724. /* put an object in a room */
  725. void obj_to_room(struct obj_data *object, int room)
  726. {
  727.     object->next_content = world[room].contents;
  728.     world[room].contents = object;
  729.     object->in_room = room;
  730.     object->carried_by = 0;
  731. }
  732.  
  733.  
  734. /* Take an object from a room */
  735. void obj_from_room(struct obj_data *object)
  736. {
  737.     struct obj_data *i;
  738.  
  739.     /* remove object from room */
  740.  
  741.     if (object == world[object->in_room].contents)  /* head of list */
  742.        world[object->in_room].contents = object->next_content;
  743.  
  744.     else     /* locate previous element in list */
  745.     {
  746.         for (i = world[object->in_room].contents; i && 
  747.            (i->next_content != object); i = i->next_content);
  748.  
  749.         i->next_content = object->next_content;
  750.      }
  751.  
  752.     object->in_room = NOWHERE;
  753.     object->next_content = 0;
  754. }
  755.  
  756.  
  757. /* put an object in an object (quaint)  */
  758. void obj_to_obj(struct obj_data *obj, struct obj_data *obj_to)
  759. {
  760.     struct obj_data *tmp_obj;
  761.  
  762.     obj->next_content = obj_to->contains;
  763.     obj_to->contains = obj;
  764.     obj->in_obj = obj_to;
  765.  
  766.     for(tmp_obj = obj->in_obj; tmp_obj;
  767.       GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj), tmp_obj = tmp_obj->in_obj);
  768. }
  769.  
  770.  
  771. /* remove an object from an object */
  772. void obj_from_obj(struct obj_data *obj)
  773. {
  774.     struct obj_data *tmp, *obj_from;
  775.  
  776.     if (obj->in_obj) {
  777.         obj_from = obj->in_obj;
  778.         if (obj == obj_from->contains)   /* head of list */
  779.            obj_from->contains = obj->next_content;
  780.         else {
  781.             for (tmp = obj_from->contains; 
  782.                 tmp && (tmp->next_content != obj);
  783.                 tmp = tmp->next_content); /* locate previous */
  784.  
  785.             if (!tmp) {
  786.                 perror("Fatal error in object structures.");
  787.                 abort();
  788.             }
  789.  
  790.             tmp->next_content = obj->next_content;
  791.         }
  792.  
  793.  
  794.         /* Subtract weight from containers container */
  795.         for(tmp = obj->in_obj; tmp->in_obj; tmp = tmp->in_obj)
  796.             GET_OBJ_WEIGHT(tmp) -= GET_OBJ_WEIGHT(obj);
  797.  
  798.         GET_OBJ_WEIGHT(tmp) -= GET_OBJ_WEIGHT(obj);
  799.  
  800.         /* Subtract weight from char that carries the object */
  801.         if (tmp->carried_by)
  802.             IS_CARRYING_W(tmp->carried_by) -= GET_OBJ_WEIGHT(obj);
  803.  
  804.         obj->in_obj = 0;
  805.         obj->next_content = 0;
  806.     } else {
  807.         perror("Trying to object from object when in no object.");
  808.         abort();
  809.     }
  810. }
  811.  
  812.  
  813. /* Set all carried_by to point to new owner */
  814. void object_list_new_owner(struct obj_data *list, struct char_data *ch)
  815. {
  816.     if (list) {
  817.         object_list_new_owner(list->contains, ch);
  818.         object_list_new_owner(list->next_content, ch);
  819.         list->carried_by = ch;
  820.     }
  821. }
  822.  
  823.  
  824. /* Extract an object from the world */
  825. void extract_obj(struct obj_data *obj)
  826. {
  827.     struct obj_data *temp1, *temp2;
  828.  
  829.     if(obj->in_room != NOWHERE)
  830.         obj_from_room(obj);
  831.     else if(obj->carried_by)
  832.         obj_from_char(obj);
  833.     else if(obj->in_obj)
  834.     {
  835.         temp1 = obj->in_obj;
  836.         if(temp1->contains == obj)   /* head of list */
  837.             temp1->contains = obj->next_content;
  838.         else
  839.         {
  840.             for( temp2 = temp1->contains ;
  841.                 temp2 && (temp2->next_content != obj);
  842.                 temp2 = temp2->next_content );
  843.  
  844.             if(temp2) {
  845.                 temp2->next_content =
  846.                     obj->next_content; }
  847.         }
  848.     }
  849.  
  850.     for( ; obj->contains; extract_obj(obj->contains)); 
  851.         /* leaves nothing ! */
  852.  
  853.     if (object_list == obj )       /* head of list */
  854.         object_list = obj->next;
  855.     else
  856.     {
  857.         for(temp1 = object_list; 
  858.             temp1 && (temp1->next != obj);
  859.             temp1 = temp1->next);
  860.         
  861.         if(temp1)
  862.             temp1->next = obj->next;
  863.     }
  864.  
  865.     if(obj->item_number>=0)
  866.         (obj_index[obj->item_number].number)--;
  867.     free_obj(obj);
  868. }
  869.         
  870. void update_object( struct obj_data *obj, int use){
  871.  
  872.     if (obj->obj_flags.timer > 0)    obj->obj_flags.timer -= use;
  873.     if (obj->contains) update_object(obj->contains, use);
  874.     if (obj->next_content) update_object(obj->next_content, use);
  875. }
  876.  
  877. void update_char_objects( struct char_data *ch )
  878. {
  879.  
  880.     int i;
  881.  
  882.     if (ch->equipment[WEAR_LIGHT])
  883.         if (ch->equipment[WEAR_LIGHT]->obj_flags.type_flag == ITEM_LIGHT)
  884.             if (ch->equipment[WEAR_LIGHT]->obj_flags.value[2] > 0)
  885.                 (ch->equipment[WEAR_LIGHT]->obj_flags.value[2])--;
  886.  
  887.     for(i = 0;i < MAX_WEAR;i++) 
  888.         if (ch->equipment[i])
  889.             update_object(ch->equipment[i],2);
  890.  
  891.     if (ch->carrying) update_object(ch->carrying,1);
  892. }
  893.  
  894.  
  895.  
  896. /* Extract a ch completely from the world, and leave his stuff behind */
  897. void extract_char(struct char_data *ch)
  898. {
  899.     struct obj_data *i;
  900.     struct char_data *k, *next_char;
  901.     struct descriptor_data *t_desc;
  902.     int l, was_in;
  903.  
  904.     extern struct char_data *combat_list;
  905.  
  906.     void do_save(struct char_data *ch, char *argument, int cmd);
  907.     void do_return(struct char_data *ch, char *argument, int cmd);
  908.  
  909.     void die_follower(struct char_data *ch);
  910.  
  911.     if(!IS_NPC(ch) && !ch->desc)
  912.     {
  913.         for(t_desc = descriptor_list; t_desc; t_desc = t_desc->next)
  914.             if(t_desc->original==ch)
  915.                 do_return(t_desc->character, "", 0);
  916.     }
  917.  
  918.     if (ch->in_room == NOWHERE) {
  919.         log("NOWHERE extracting char. (handler.c, extract_char)");
  920.         exit(1);
  921.     }
  922.  
  923.     if (ch->followers || ch->master)
  924.         die_follower(ch);
  925.  
  926.    if(ch->desc) {
  927.         /* Forget snooping */
  928.         if (ch->desc->snoop.snooping)
  929.             ch->desc->snoop.snooping->desc->snoop.snoop_by = 0;
  930.  
  931.         if (ch->desc->snoop.snoop_by)
  932.             {
  933.                 send_to_char("Your victim is no longer among us.\n\r",
  934.                     ch->desc->snoop.snoop_by);
  935.                 ch->desc->snoop.snoop_by->desc->snoop.snooping = 0;
  936.             }
  937.         
  938.         ch->desc->snoop.snooping = ch->desc->snoop.snoop_by = 0;
  939.     }
  940.  
  941.     if (ch->carrying)
  942.     {
  943.         /* transfer ch's objects to room */
  944.         
  945.         if (world[ch->in_room].contents)  /* room nonempty */
  946.         {
  947.             /* locate tail of room-contents */
  948.             for (i = world[ch->in_room].contents; i->next_content; 
  949.                i = i->next_content);
  950.  
  951.             /* append ch's stuff to room-contents */
  952.             i->next_content = ch->carrying;
  953.         }
  954.         else
  955.            world[ch->in_room].contents = ch->carrying;
  956.  
  957.         /* connect the stuff to the room */
  958.         for (i = ch->carrying; i; i = i->next_content)
  959.         {
  960.             i->carried_by = 0;
  961.             i->in_room = ch->in_room;
  962.         }
  963.     }
  964.  
  965.  
  966.     
  967.     if (ch->specials.fighting)
  968.         stop_fighting(ch);
  969.  
  970.     for (k = combat_list; k ; k = next_char)
  971.     {
  972.         next_char = k->next_fighting;
  973.         if (k->specials.fighting == ch)
  974.             stop_fighting(k);
  975.     }
  976.  
  977.     /* Must remove from room before removing the equipment! */
  978.     was_in = ch->in_room;
  979.     char_from_room(ch);
  980.  
  981.     /* clear equipment_list */
  982.     for (l = 0; l < MAX_WEAR; l++)
  983.         if (ch->equipment[l])
  984.             obj_to_room(unequip_char(ch,l), was_in);
  985.  
  986.  
  987.     /* pull the char from the list */
  988.  
  989.     if (ch == character_list)  
  990.        character_list = ch->next;
  991.     else
  992.     {
  993.         for(k = character_list; (k) && (k->next != ch); k = k->next);
  994.         if(k)
  995.             k->next = ch->next;
  996.         else {
  997.             log("Trying to remove ?? from character_list. (handler.c, extract_char)");
  998.             abort();
  999.         }
  1000.     }
  1001.  
  1002.     GET_AC(ch) = 100;
  1003.  
  1004.     if (ch->desc)
  1005.     {
  1006.         if (ch->desc->original)
  1007.             do_return(ch, "", 0);
  1008.         save_char(ch, NOWHERE);
  1009.     }
  1010.  
  1011.     if (IS_NPC(ch)) 
  1012.     {
  1013.         if (ch->nr > -1) /* if mobile */
  1014.             mob_index[ch->nr].number--;
  1015.         free_char(ch);
  1016.     }
  1017.  
  1018.     if (ch->desc) {
  1019.         ch->desc->connected = CON_SLCT;
  1020.         SEND_TO_Q(MENU, ch->desc);
  1021.     }
  1022. }
  1023.  
  1024.  
  1025.  
  1026. /* ***********************************************************************
  1027.    Here follows high-level versions of some earlier routines, ie functions
  1028.    which incorporate the actual player-data.
  1029.    *********************************************************************** */
  1030.  
  1031.  
  1032. struct char_data *get_char_room_vis(struct char_data *ch, char *name)
  1033. {
  1034.     struct char_data *i;
  1035.     int j, number;
  1036.   char tmpname[MAX_INPUT_LENGTH];
  1037.     char *tmp;
  1038.  
  1039.     strcpy(tmpname,name);
  1040.     tmp = tmpname;
  1041.     if(!(number = get_number(&tmp)))
  1042.     return(0);
  1043.  
  1044.     for (i = world[ch->in_room].people, j = 1; i && (j <= number); i = i->next_in_room)
  1045.         if (isname(tmp, GET_NAME(i)))
  1046.             if (CAN_SEE(ch, i))    {
  1047.                 if (j == number) 
  1048.                     return(i);
  1049.                 j++;
  1050.             }
  1051.  
  1052.     return(0);
  1053. }
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059. struct char_data *get_char_vis(struct char_data *ch, char *name)
  1060. {
  1061.     struct char_data *i;
  1062.     int j, number;
  1063.   char tmpname[MAX_INPUT_LENGTH];
  1064.     char *tmp;
  1065.  
  1066.     /* check location */
  1067.     if (i = get_char_room_vis(ch, name))
  1068.         return(i);
  1069.  
  1070.   strcpy(tmpname,name);
  1071.     tmp = tmpname;
  1072.     if(!(number = get_number(&tmp)))
  1073.         return(0);
  1074.  
  1075.     for (i = character_list, j = 1; i && (j <= number); i = i->next)
  1076.         if (isname(tmp, GET_NAME(i)))
  1077.             if (CAN_SEE(ch, i))    {
  1078.                 if (j == number)
  1079.                     return(i);
  1080.                 j++;
  1081.             }
  1082.  
  1083.     return(0);
  1084. }
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091. struct obj_data *get_obj_in_list_vis(struct char_data *ch, char *name, 
  1092.                 struct obj_data *list)
  1093. {
  1094.     struct obj_data *i;
  1095.     int j, number;
  1096.   char tmpname[MAX_INPUT_LENGTH];
  1097.     char *tmp;
  1098.  
  1099.   strcpy(tmpname,name);
  1100.     tmp = tmpname;
  1101.     if(!(number = get_number(&tmp)))
  1102.         return(0);
  1103.  
  1104.     for (i = list, j = 1; i && (j <= number); i = i->next_content)
  1105.         if (isname(tmp, i->name))
  1106.             if (CAN_SEE_OBJ(ch, i)) {
  1107.                 if (j == number)
  1108.                     return(i);
  1109.                 j++;
  1110.             }
  1111.     return(0);
  1112. }
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118. /*search the entire world for an object, and return a pointer  */
  1119. struct obj_data *get_obj_vis(struct char_data *ch, char *name)
  1120. {
  1121.     struct obj_data *i;
  1122.     int j, number;
  1123.   char tmpname[MAX_INPUT_LENGTH];
  1124.     char *tmp;
  1125.  
  1126.     /* scan items carried */
  1127.     if (i = get_obj_in_list_vis(ch, name, ch->carrying))
  1128.         return(i);
  1129.  
  1130.     /* scan room */
  1131.     if (i = get_obj_in_list_vis(ch, name, world[ch->in_room].contents))
  1132.         return(i);
  1133.  
  1134.   strcpy(tmpname,name);
  1135.     tmp = tmpname;
  1136.     if(!(number = get_number(&tmp)))
  1137.         return(0);
  1138.  
  1139.     /* ok.. no luck yet. scan the entire obj list   */
  1140.     for (i = object_list, j = 1; i && (j <= number); i = i->next)
  1141.         if (isname(tmp, i->name))
  1142.             if (CAN_SEE_OBJ(ch, i)) {
  1143.                 if (j == number)
  1144.                     return(i);
  1145.                 j++;
  1146.             }
  1147.     return(0);
  1148. }
  1149.  
  1150.  
  1151. struct obj_data *create_money( int amount )
  1152. {
  1153.     struct obj_data *obj;
  1154.     struct extra_descr_data *new_descr;
  1155.     char buf[80];
  1156.  
  1157.     char *strdup(char *str);
  1158.  
  1159.     if(amount<=0)
  1160.     {
  1161.         log("ERROR: Try to create negative money.");
  1162.         exit(1);
  1163.     }
  1164.  
  1165.     CREATE(obj, struct obj_data, 1);
  1166.     CREATE(new_descr, struct extra_descr_data, 1);
  1167.     clear_object(obj);
  1168.  
  1169.     if(amount==1)
  1170.     {
  1171.         obj->name = strdup("coin gold");
  1172.         obj->short_description = strdup("a gold coin");
  1173.         obj->description = strdup("One miserable gold coin.");
  1174.  
  1175.         new_descr->keyword = strdup("coin gold");
  1176.         new_descr->description = strdup("One miserable gold coin.");
  1177.     }
  1178.     else
  1179.     {
  1180.         obj->name = strdup("coins gold");
  1181.         obj->short_description = strdup("gold coins");
  1182.         obj->description = strdup("A pile of gold coins.");
  1183.  
  1184.         new_descr->keyword = strdup("coins gold");
  1185.         if(amount<10) {
  1186.             sprintf(buf,"There is %d coins.",amount);
  1187.             new_descr->description = strdup(buf);
  1188.         } 
  1189.         else if (amount<100) {
  1190.             sprintf(buf,"There is about %d coins",10*(amount/10));
  1191.             new_descr->description = strdup(buf);
  1192.         }
  1193.         else if (amount<1000) {
  1194.             sprintf(buf,"It looks like something round %d coins",100*(amount/100));
  1195.             new_descr->description = strdup(buf);
  1196.         }
  1197.         else if (amount<100000) {
  1198.             sprintf(buf,"You guess there is %d coins",1000*((amount/1000)+ number(0,(amount/1000))));
  1199.             new_descr->description = strdup(buf);
  1200.         }
  1201.         else 
  1202.             new_descr->description = strdup("There is A LOT of coins");            
  1203.     }
  1204.  
  1205.     new_descr->next = 0;
  1206.     obj->ex_description = new_descr;
  1207.  
  1208.     obj->obj_flags.type_flag = ITEM_MONEY;
  1209.     obj->obj_flags.wear_flags = ITEM_TAKE;
  1210.     obj->obj_flags.value[0] = amount;
  1211.     obj->obj_flags.cost = amount;
  1212.     obj->item_number = -1;
  1213.  
  1214.     obj->next = object_list;
  1215.     object_list = obj;
  1216.  
  1217.     return(obj);
  1218. }
  1219.  
  1220.  
  1221.  
  1222. /* Generic Find, designed to find any object/character                    */
  1223. /* Calling :                                                              */
  1224. /*  *arg     is the sting containing the string to be searched for.       */
  1225. /*           This string doesn't have to be a single word, the routine    */
  1226. /*           extracts the next word itself.                               */
  1227. /*  bitv..   All those bits that you want to "search through".            */
  1228. /*           Bit found will be result of the function                     */
  1229. /*  *ch      This is the person that is trying to "find"                  */
  1230. /*  **tar_ch Will be NULL if no character was found, otherwise points     */
  1231. /* **tar_obj Will be NULL if no object was found, otherwise points        */
  1232. /*                                                                        */
  1233. /* The routine returns a pointer to the next word in *arg (just like the  */
  1234. /* one_argument routine).                                                 */
  1235.  
  1236. int generic_find(char *arg, int bitvector, struct char_data *ch,
  1237.                    struct char_data **tar_ch, struct obj_data **tar_obj)
  1238. {
  1239.     static char *ignore[] = {
  1240.         "the",
  1241.         "in",
  1242.         "on",
  1243.         "at",
  1244.         "\n" };
  1245.  
  1246.     int i;
  1247.     char name[256];
  1248.     bool found;
  1249.  
  1250.     found = FALSE;
  1251.  
  1252.  
  1253.     /* Eliminate spaces and "ignore" words */
  1254.     while (*arg && !found) {
  1255.  
  1256.         for(; *arg == ' '; arg++)   ;
  1257.  
  1258.         for(i=0; (name[i] = *(arg+i)) && (name[i]!=' '); i++)   ;
  1259.         name[i] = 0;
  1260.         arg+=i;
  1261.         if (search_block(name, ignore, TRUE) > -1)
  1262.             found = TRUE;
  1263.  
  1264.     }
  1265.  
  1266.     if (!name[0])
  1267.         return(0);
  1268.  
  1269.     *tar_ch  = 0;
  1270.     *tar_obj = 0;
  1271.  
  1272.     if (IS_SET(bitvector, FIND_CHAR_ROOM)) {      /* Find person in room */
  1273.         if (*tar_ch = get_char_room_vis(ch, name)) {
  1274.             return(FIND_CHAR_ROOM);
  1275.         }
  1276.     }
  1277.  
  1278.     if (IS_SET(bitvector, FIND_CHAR_WORLD)) {
  1279.         if (*tar_ch = get_char_vis(ch, name)) {
  1280.             return(FIND_CHAR_WORLD);
  1281.         }
  1282.     }
  1283.  
  1284.     if (IS_SET(bitvector, FIND_OBJ_EQUIP)) {
  1285.         for(found=FALSE, i=0; i<MAX_WEAR && !found; i++)
  1286.             if (ch->equipment[i] && str_cmp(name, ch->equipment[i]->name) == 0) {
  1287.                 *tar_obj = ch->equipment[i];
  1288.                 found = TRUE;
  1289.             }
  1290.             if (found) {
  1291.                 return(FIND_OBJ_EQUIP);
  1292.             }
  1293.     }
  1294.  
  1295.     if (IS_SET(bitvector, FIND_OBJ_INV)) {
  1296.         if (*tar_obj = get_obj_in_list_vis(ch, name, ch->carrying)) {
  1297.             return(FIND_OBJ_INV);
  1298.         }
  1299.     }
  1300.  
  1301.     if (IS_SET(bitvector, FIND_OBJ_ROOM)) {
  1302.         if (*tar_obj = get_obj_in_list_vis(ch, name, world[ch->in_room].contents)) {
  1303.             return(FIND_OBJ_ROOM);
  1304.         }
  1305.     }
  1306.  
  1307.     if (IS_SET(bitvector, FIND_OBJ_WORLD)) {
  1308.         if (*tar_obj = get_obj_vis(ch, name)) {
  1309.             return(FIND_OBJ_WORLD);
  1310.         }
  1311.     }
  1312.  
  1313.     return(0);
  1314. }
  1315.