[CODE] Function to find random targets in rooms

From: Chuck Reed (master@i-55.com)
Date: 05/21/99

Wrote this up for a special procedure I was writing one day.  I think it's
useful for a number of things, and may ought to be considered as a util
for future releases of circlemud.  I know it sure does make mobile
aggression more
interesting when players can't predict who will be attacked ;)

This is a utility function that allows you to choose a random target
from a room.  The function allows for restrictions to be sent as arguments
to add to the versatility of the function.  The arguments are sent in an
integer and the default call of random_target(ch, 0); will be to find a
random mortal/NPC in the room.  To expand on targets, you can use bitwise
operators in the function call, ie random_target(ch, TARG_MORT | TARG_MOB);
would return a random target from mobs and mortals in the room.  If the
TARG_ALL flag is sent, everything in the room will be a target, including
the character himself.

If anyone sees any problems with this or has an idea of how it can be
please give me a holler to let me know at this email address.  Anyhow, here
are the
instructions on installing it.  It should work with all versions of circlemud.

1) The following should be added somewhere in structs.h:

// Definitions for random_target() by Chuck Reed
#define TARG_MORT       (1 << 0)
#define TARG_IMM        (1 << 1)
#define TARG_MOB        (1 << 2)
#define TARG_SELF       (1 << 3)
#define TARG_ALL        (1 << 4)

struct target_data
   struct char_data *c;
   struct target_data *prev;
   struct target_data *next;

2) Now add the following function to utils.c and protoype it in utils.h:

struct char_data *random_target(struct char_data *ch, int type)
   struct target_data *t, *ctp, *ptp;
   int node, add, count = 0, i;
   struct char_data *cp, *rc;

   if (ch->in_room == NOWHERE)
      log("SYSERROR: random_target() being called on ch->in_room == NOWHERE");
      return NULL;

   if (!world[ch->in_room].people) // Hmm, not even counting the player
himself!  YAY!
      return NULL;

   t = malloc(sizeof(struct target_data));
   t->c = NULL;
   t->prev = NULL;
   t->next = NULL;
   ptp = t;
   for (cp = world[ch->in_room].people; cp; cp = cp->next_in_room)
      add = FALSE;
      if ((type & TARG_ALL))                  // Any target is allowed
         add = TRUE;
      else if (cp == ch) {                    // Self targeting check
         if ((type & TARG_SELF))
            add = TRUE;
     }else if (IS_MOB(cp)) {                  // Mob targeting check
         if ((type & TARG_MOB))
            add = TRUE;
     }else if (GET_LEVEL(cp) >= LVL_IMMORT) { // Immortal targeting check
         if ((type & TARG_IMM))
            add = TRUE;
         if ((type & TARG_MORT))              // Mortal targeting check
            add = TRUE;

      if (add == TRUE)
         ctp = malloc(sizeof(struct target_data));
         ctp->prev = ptp;
         ctp->next = NULL;
         ctp->c = cp;
         ptp->next = ctp;
         ptp = ctp;
   if (count == 0) // No valid targets
      return NULL;

   // At this point we should have a list of valid targets pointed to by t
   // Note: The first node of the list (0) is invalid, so number(1,count)
is always used
   node = number(1, count);
   for (i = 0, ctp = t;ctp;i++, ctp = ctp->next)
      if (i == node)
         rc = ctp->c;          // Save pointer to be returned
         for (ctp = t; ctp;)   // Free the list of targets
            if (ctp->next != NULL)
               ctp = ctp->next;
               ctp = NULL;
         return rc;
   return NULL;

     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     |  http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html  |

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