Re: Item stacking

From: The Oracle (oracle@beta.blkbox.com)
Date: 08/27/95


> I'v been trying to code item stacking with no luck....
> I tried doing it from scratch, and cut/pasteing it from Merc 2.1 code, 
> but that didn't work either... best I could get was a segmentation 
> fault whenever you look at yout inventory if something was in it....
> (I managed to get no compiler errors so I don't know what the problem 
> is)

By object stacking I'm assuming that you mean that if you have 34 loaves 
of bread, you want to see something like this in your inventory list:

a loaf of bread. [34]

   or, the Merc way:

  (34)  a loaf of bread.

At any rate, I coded this on Circle 3bpl7 a ways back.  Its a little 
messy, but it works quite well....

----------------------------------------------------------------------------

/*
 * The following struct & function are used by list_obj_to_char. naj 4/95
 * Just stick em' in act.informative.c before show_obj_to_char. 
 * Sorry there aren't any comments.  I wrote this in a big rush way back.
 * This would be a cool feature to see in a release of Circle. =) =) =)
 */

struct objlist {
  int num, cnt, mark;  
  struct objlist *n;
  };
  
void mark_elem(struct objlist *head, int num) {
  struct objlist *obj;
  for(obj=head;obj;obj=obj->n) 
    if (obj->num == num) {
      obj->mark = 1;
      return;
    }
} 

int is_marked_elem(struct objlist *head, int num) {
  struct objlist *obj;
  for(obj=head;obj;obj=obj->n)
    if ( (obj->num == num) && (obj->mark) )
      return 1;
  return 0;
}

int count_elem(struct objlist *head, int num) {
  struct objlist *obj;
  for(obj=head;obj;obj=obj->n)
    if (obj->num == num)
      return (obj->cnt);
  return 0;
}

void add_elem(struct objlist *head, int num) { 
  struct objlist *obj;
  for(obj=head;obj;obj=obj->n) {
    if ((obj->num) == num) { 
      obj->cnt++;   
      return;
    }
    if (!obj->n) {      
      obj->n = malloc( sizeof(struct objlist) );
      obj->n->num = num;
      obj->n->cnt = 1;
      obj->n->mark = 0;
      obj->n->n = NULL;
      return;
    }
  }
}

void destroy_list(struct objlist *head) {
  if (head != NULL) {
    destroy_list(head -> n);
    free(head);
  }
}

/*
 * This is a modified show_obj_to_char.  Note the int cnt in the prototype.
 * You will have to modify anything that calls this.  Chances are if it isn't
 * list_obj_to_char calling it, you can just use 1 as the value.
 */

void show_obj_to_char(struct obj_data * object, struct char_data * ch,
			int mode, int cnt)
{
  bool found;
  char buf2[20];

  *buf = '\0';
  if ((mode == 0) && object->description)
    strcpy(buf, object->description);
  else if (object->short_description && ((mode == 1) ||
				 (mode == 2) || (mode == 3) || (mode == 4)))
    strcpy(buf, object->short_description);
  else if (mode == 5) {
    if (GET_OBJ_TYPE(object) == ITEM_NOTE) {
      if (object->action_description) {
	strcpy(buf, "There is something written upon it:\r\n\r\n");
	strcat(buf, object->action_description);
	page_string(ch->desc, buf, 1);
      } else
	act("It's blank.", FALSE, ch, 0, 0, TO_CHAR);
      return;
    } else if (GET_OBJ_TYPE(object) != ITEM_DRINKCON) {
      strcpy(buf, "You see nothing special..");
    } else			/* ITEM_TYPE == ITEM_DRINKCON||FOUNTAIN */
      strcpy(buf, "It looks like a drink container.");
  }
  if (mode != 3) {
    found = FALSE;
    if (IS_OBJ_STAT(object, ITEM_INVISIBLE)) {
      strcat(buf, " (invisible)");
      found = TRUE;
    }
    if (IS_OBJ_STAT(object, ITEM_BLESS) && IS_AFFECTED(ch, AFF_DETECT_ALIGN)) {
      strcat(buf, " ..It glows blue!");
      found = TRUE;
    }
    if (IS_OBJ_STAT(object, ITEM_MAGIC) && IS_AFFECTED(ch, AFF_DETECT_MAGIC)) {
      strcat(buf, " ..It glows yellow!");
      found = TRUE;
    }
    if (IS_OBJ_STAT(object, ITEM_GLOW)) {
      strcat(buf, " ..It has a soft glowing aura!");
      found = TRUE;
    }
    if (IS_OBJ_STAT(object, ITEM_HUM)) {
      strcat(buf, " ..It emits a faint humming sound!");
      found = TRUE;
    }
  }

  if (cnt > 1) {
    sprintf(buf2, " [%d]", cnt);
    strcat(buf, buf2);
  }

  strcat(buf, "\r\n");

  page_string(ch->desc, buf, 1);
}

/*
 * Lots of changes to list_obj_to_char.
 */

void list_obj_to_char(struct obj_data * list, struct char_data * ch, int mode,
		           bool show)
{
  struct obj_data *i;
  bool found;
  struct objlist *head;

  if (!(head = malloc(sizeof(struct objlist))))
    log("NAJERR: list_obj_to_char: cannot create list");
  head -> n = NULL;
  head -> num = -1;
  head -> cnt = -1;
  head -> mark = 0;
  for (i = list; i; i = i->next_content) 
    if (CAN_SEE_OBJ(ch, i))
      add_elem(head, i->item_number);
  found = FALSE;
  for (i = list; i; i = i->next_content) {
    if (CAN_SEE_OBJ(ch, i)) {  /* list all corpses individually for now - naj  */
      if ( ((GET_OBJ_TYPE(i) == ITEM_CONTAINER && GET_OBJ_VAL(i, 3))) && (i->item_number == NOTHING) )
        show_obj_to_char(i, ch, mode, count_elem(head, 1));
      else if ( !is_marked_elem(head, i->item_number) ) { 
        show_obj_to_char(i, ch, mode, count_elem(head, i->item_number) );
        mark_elem(head, i->item_number);
        found = TRUE;
      }
    }
  }
  if (!found && show)
    send_to_char(" Nothing.\r\n", ch);

  destroy_list(head);

}


/*
 *   And that's it!  I _think_ that's all that I modified to make this work.
 *   Questions, comments, constructive criticisms to oracle@blkbox.com.
 *   Enjoy! =)
 */



This archive was generated by hypermail 2b30 : 12/18/00 PST