Guilds (Clan) -- CODE Help

From: Sean P. Mountcastle (mountcas@krusty.ee.cua.edu)
Date: 07/30/96


	Attached is almost the  entire code for my guild system (what 
most of you refer to as Clans).  The only two things that are saved in 
the pfiles are the guild id number and the player's guild level.  I  was 
planning on releasing this code to the list once I got it finished, but 
many other things have come up, so I haven't had a chance to fix it.  I 
think the problem is in load_guilds because the guilds are not being 
loaded from disk correctly.  If anyone can spot my errors and post a fix, 
I'll continue working on it till I get it working perfectly, then re-post 
it.  (or if you fix the entire thing, feel free to post it all, I guess).

	Many thanks in advance,

	- Sean

Here's the code:

/* Guilds start here */
#define MAX_GUILD_LVL 5
#define GUILD_ACC_LVL 4
#define GUILD_DIS_LVL 4
/* Guild globals */
struct guild_type *guild_info = NULL;    /* array of guilds  */
int    gnum  = 0;                        /* number of guilds */

/* Loads the guilds from the text file */
void load_guilds(void)
{
  FILE   *fl = NULL;
  int    guildnum = 0, line_num = 0, tmp, i = 0;
  long   tmp2, tmp3;
  struct guild_type *iterator = guild_info;
  char   name[80], flags[80];
  char   *ptr;
  /* extern func names */
  SPECIAL(guild_guard);
  void ASSIGNMOB(int mob, SPECIAL(fname));

  if ((fl = fopen(GUILD_FILE, "rt")) == NULL) {
    fprintf(stderr, "SYSERR: Unable to open guild file!");
    exit(0);
  }

  line_num += get_line(fl, buf);
  if (sscanf(buf, "%d", &guildnum) != 1) {
    fprintf(stderr, "Format error in guild, line %d (number of guilds)\n", line_num);
    exit(0);
  }
  /* Setup the global total number of guilds */
  gnum = guildnum;

  /* process each guild in order */
  for (guildnum = 0; guildnum < gnum; guildnum++) {
     /* Get the info for the individual guilds */
     line_num += get_line(fl, buf);
     if (sscanf(buf, "#%d", &tmp) != 1) {
       fprintf(stderr, "Format error in guild (No Unique GID), line %d\n", line_num);
       exit(0);
     }
     /* This must be the first one if iterator == NULL */
     if (iterator == NULL) {
       if ((iterator = (struct guild_type *) malloc(sizeof(struct guild_type))) == NULL) {
	 fprintf(stderr, "Not enough memory to load guilds!!!!\n");
	 exit(0);
       } else
	 iterator->next = NULL;
     } else {
       while (iterator != NULL)
	 iterator = iterator->next;
       if ((iterator = (struct guild_type *) malloc(sizeof(struct guild_type))) == NULL) {
	 fprintf(stderr, "Not enough memory to load guilds!!!!\n");
	 exit(0);
       } else
	 iterator->next = NULL;
     }
     /*
      * At this point we should have alloc'ed mem for the guild struct, let's
      *  start filling it!
      */
     iterator->number = tmp;
     /* Now get the name of the guild */
     line_num += get_line(fl, buf);
     if ((ptr = strchr(buf, '~')) != NULL) /* take off the '~' if it's there */
       *ptr = '\0';
     iterator->name = str_dup(buf);
     /* Now get the leader's title */
     line_num += get_line(fl, buf);
     if ((ptr = strchr(buf, '~')) != NULL) /* take off the '~' if it's there */
       *ptr = '\0';
     iterator->xlvlname = str_dup(buf);
     /* Now get the high lvl's title */
     line_num += get_line(fl, buf);
     if ((ptr = strchr(buf, '~')) != NULL) /* take off the '~' if it's there */
       *ptr = '\0';
     iterator->hlvlname = str_dup(buf);
     /* Now get the Med Lvl's title */
     line_num += get_line(fl, buf);
     if ((ptr = strchr(buf, '~')) != NULL) /* take off the '~' if it's there */
       *ptr = '\0';
     iterator->mlvlname = str_dup(buf);
     /* Now get the newbie's title */
     line_num += get_line(fl, buf);
     if ((ptr = strchr(buf, '~')) != NULL) /* take off the '~' if it's there */
       *ptr = '\0';
     iterator->blvlname = str_dup(buf);
     /* Now get restricts, entrance room and direction */
     line_num += get_line(fl, buf);
     if (sscanf(buf, "%s %ld %d %ld", flags, &tmp2, &tmp, &tmp3) != 4) {
       fprintf(stderr, "Format error in guild, line %d (flags, room, dir, mob)\n", line_num);
       exit(0);
     }
     iterator->restrictions    = asciiflag_conv(flags);
     iterator->guild_entr_room = tmp2;
     /* This is an SCMD_direction number */
     iterator->direction       = tmp;
     iterator->guardian_mob_vn = tmp3;
     /* now assign the special to the guardian mobile */
     ASSIGNMOB(tmp3, guild_guard);
     /* Skip this line it's just a header */
     line_num += get_line(fl, buf);
     /* Loop to get Members' Names */
     for (;;) {
       line_num += get_line(fl, buf);
       if (*buf == ';')
	 break;
       sscanf(buf, "%s %d", name, &tmp);
       if (tmp == MAX_GUILD_LVL)
	 iterator->leadersname = str_dup(name);
     }
     /* Okay we have the leader's name ... now for the petitioners */
     for (i = 0; i < 20; i++) {
       line_num += get_line(fl, buf);
       /* We're done when we hit the $ character */
       if (*buf == '$')
	 break;
       else if ((ptr = strchr(buf, '~')) != NULL) /* take off the '~' if it's there */
	 *ptr = '\0';
       iterator->petitioners[i] = str_dup(buf);
     }
     /* process the next guild */
  }
  /* done processing guilds -- close the file */
  fclose(fl);
}


void save_guilds(void)
{
  FILE   *gfile;
  int    guildnum = 0, i;
  struct guild_type *iterator = guild_info;
  char   flags[80];
  void   sprintbits(long bits, char *s);

  if ((gfile = fopen(GUILD_FILE, "wt")) == NULL) {
    fprintf(stderr, "SYSERR: Cannot save guilds!\n");
    exit(0);
  }
  /* The total number of guilds */
  fprintf(gfile, "%d\n", gnum);
  /* Save each guild */
  for (guildnum = 0; guildnum < gnum; guildnum++) {
    sprintbits(iterator->restrictions, flags);
    fprintf(gfile,  "#%d\n"
		    "%s~\n"
		    "%s~\n"
		    "%s~\n"
		    "%s~\n"
		    "%s~\n"
		    "%s %ld %d %;d\n"
		    "; Leader\n"
		    "%s %d\n"
		    "; Petitioners (Max of 20)\n",
		    iterator->number, iterator->name,
		    iterator->xlvlname, iterator->hlvlname,
		    iterator->mlvlname, iterator->blvlname,
		    flags, iterator->guild_entr_room, iterator->direction,
		    iterator->guardian_mob_vn, iterator->leadersname,
		    MAX_GUILD_LVL);
     for (i = 0; i < 20; i++) {
       if (iterator->petitioners[i] == NULL)
	 break;
       else /* Print the name */
	 fprintf("%s~", iterator->petitioners[i]);
     }
     iterator = iterator->next;
     /* process the next guild */
  }
  /* done processing guilds */
  fclose(gfile);
}


/* returns the guild member's guild level */
int guild_level(struct char_data *gm)
{
   if (GET_GUILD_LEV(gm) > MAX_GUILD_LVL || GET_GUILD_LEV(gm) < 0) {
       sprintf(buf, "SYSERR: %s's guild_level out of range!", GET_NAME(gm));
       mudlog(buf, NRM, LVL_GRGOD, TRUE);
       return 0;
   }
   return (GET_GUILD_LEV(gm));
}

/* Petition a guild for membership */
ACMD(do_petition)
{
   int i;
   struct guild_type *iterator = guild_info;

   if (IS_NPC(ch))
     return;

   if (GET_GUILD(ch) != GUILD_NONE) {
     send_to_char("If you'd like to leave your guild speak with your leader.\r\n", ch);
     return;
   }

   skip_spaces(&argument);

   for (; iterator != NULL; ) {
     if ((isname(argument, iterator->name)) || is_abbrev(argument, iterator->name))
       break;
     iterator = iterator->next;
   }

   if (iterator == NULL)
     send_to_char("There is no guild by that name, please type the WHOLE name.\r\n", ch);
   else {
     for (i = 0; i < 20; i++)
       if (iterator->petitioners[i] == NULL)
	 break;
     if ((iterator->petitioners[i] == NULL) && (i < 20)) {
       iterator->petitioners[i] = str_dup(GET_NAME(ch));
       save_guilds();
       sprintf(buf, "Your petition for admittance to %s has been noted.\r\n"
		    "You will receive notification when you have been accepted.\r\n",
		    iterator->name);
       send_to_char(buf, ch);
     } else
       send_to_char("This guild is already being petitioned by 20 other players, try again later.\r\n", ch);
   }
   return;
}

ACMD(do_accept)
{
   int i, found = 0, player_i = 0;
   struct guild_type *iterator = guild_info;
   struct char_data *vict = NULL, *cbuf = NULL;
   struct char_file_u tmp_store;
   /* Proto so that we can send notify mail to petitioner */
   void store_mail(long to, long from, char *message_pointer);
   extern struct room_data world[];

   /* No funky stuff */
   if (IS_NPC(ch))
     return;

   if (GET_GUILD(ch) == GUILD_NONE || GET_GUILD(ch) == GUILD_UNDEFINED) {
     send_to_char("But you're not a member of any guild!\r\n", ch);
     return;
   }

   if (GET_GUILD_LEV(ch) < GUILD_ACC_LVL) {
     send_to_char("You are not high enough level within the guild to accept new members!\r\n", ch);
     return;
   }

   /* Make sure iterator points to the correct guild */
   while (iterator->number != GET_GUILD(ch))
     iterator = iterator->next;

   one_argument(argument, arg);

   if (!*arg) {
     strcpy(buf, "Current petitioners are:\r\n");
     for (i = 0; i < 20; i++) {
       if (iterator->petitioners[i] != NULL)
	 sprintf(buf, "%s%s%s", buf, iterator->petitioners[i],
		  ((i+1) % 5 ? "\r\n" : " "));
     }
     strcat(buf,  "Whom do you wish to accept into the guild?\r\n");
     send_to_char(buf, ch);
     return;
   }
   /* Find the person who is being accepted */
   for (i = 0; i < 20; i++) {
     if (iterator->petitioners[i] != NULL) {
       if (isname(arg, iterator->petitioners[i]) || is_abbrev(arg, iterator->petitioners[i])) {
	 found = 1;
	 break;
       }
     }
   }
   if (!found) {
     send_to_char("There is no one petitioning your guild by that name.\r\n", ch);
     return;
   }
   /* Okay we have the name, now let's set the PC as a member */
   if (!(vict = get_player_vis(ch, arg, 0))) {
     /* we need to load the file up :( */
     CREATE(cbuf, struct char_data, 1);
     clear_char(cbuf);
     if (load_char(arg, &tmp_store) > -1) {
       store_to_char(&tmp_store, cbuf);
       vict = cbuf;
     }
   }
   if (vict != NULL) {
     GET_GUILD(vict)     = GET_GUILD(ch);
     GET_GUILD_LEV(vict) = 1;
     /* send some sort of mail to player notifying him/her of acceptance */
     sprintf(buf, "%s,\r\n\r\n"
		  "   Congratulations!  You have been accepted into the ranks of\r\n"
		  "%s.  The leader of our guild is %s, and the entrance to our\r\n"
		  "guild hall is located at %s.  Good luck.\r\n",
		  GET_NAME(vict), iterator->name, iterator->leadersname,
		  world[real_room(iterator->guild_entr_room)].name);
     store_mail(GET_IDNUM(vict), GET_IDNUM(ch), buf);
     /* now that the mail has been sent, let's continue. */
     sprintf(buf, "%s is now a %s in %s.\r\n", GET_NAME(vict), iterator->blvlname, iterator->name);
     send_to_char(buf, ch);
     if (cbuf != NULL) {
       char_to_store(vict, &tmp_store);
       fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET);
       fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl);
       free_char(cbuf);
     } else
       save_char(vict, NOWHERE);
     /* now remove the player from the petition list */
     for (; i < 19; i++)
       iterator->petitioners[i] = str_dup(iterator->petitioners[i+1]);
     save_guilds();
   }
}

ACMD(do_reject)
{
   int i, found = 0, player_i = 0;
   struct guild_type *iterator = guild_info;
   struct char_data *vict = NULL, *cbuf = NULL;
   struct char_file_u tmp_store;

   if (IS_NPC(ch))
     return;

   if (GET_GUILD(ch) == GUILD_NONE || GET_GUILD(ch) == GUILD_UNDEFINED) {
     send_to_char("But you're not a member of any guild!\r\n", ch);
     return;
   }

   if (GET_GUILD_LEV(ch) < GUILD_ACC_LVL) {
     send_to_char("You are not high enough level within the guild to reject petitioners!\r\n", ch);
     return;
   }

   /* Make sure iterator points to the correct guild */
   while (iterator->number != GET_GUILD(ch))
      iterator = iterator->next;

   one_argument(argument, arg);

   if (!*arg) {
     strcpy(buf, "Current petitioners are:\r\n");
     for (i = 0; i < 20; i++) {
	if (iterator->petitioners[i] != NULL)
	  sprintf(buf, "%s%s%s", buf, iterator->petitioners[i],
		  ((i+1) % 5 ? "\r\n" : " "));
     }
     strcat(buf,  "Whom do you wish to reject from the guild?\r\n");
     send_to_char(buf, ch);
     return;
   }
   /* Find the person who is being rejected */
   for (i = 0; i < 20; i++) {
     if (iterator->petitioners[i] != NULL)
       if (isname(arg, iterator->petitioners[i]) || is_abbrev(arg, iterator->petitioners[i])) {
	 found = 1;
	 break;
       }
   }
   if (!found) {
     send_to_char("There is no one petitioning your guild by that name.\r\n", ch);
     return;
   }
   /* Okay we have the name, now let's set the PC as a member */
   if (!(vict = get_player_vis(ch, arg, 0))) {
     /* we need to load the file up :( */
     CREATE(cbuf, struct char_data, 1);
     clear_char(cbuf);
     if (load_char(arg, &tmp_store) > -1) {
       store_to_char(&tmp_store, cbuf);
       vict = cbuf;
     }
   }
   if (vict != NULL) {
     GET_GUILD(vict)     = GUILD_NONE;
     GET_GUILD_LEV(vict) = 0;
     /* send some sort of mail to player notifying him/her of rejection */

     sprintf(buf, "%s has been rejected from %s.\r\n", GET_NAME(vict), iterator->name);
     send_to_char(buf, ch);
     if (cbuf != NULL) {
       char_to_store(vict, &tmp_store);
       fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET);
       fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl);
       free_char(cbuf);
     } else
       save_char(vict, NOWHERE);
     /* now remove the player from the petition list */
     for (; i < 19; i++)
       iterator->petitioners[i] = str_dup(iterator->petitioners[i+1]);
     save_guilds();
   }
}


ACMD(do_dismiss)
{
   int player_i = 0;
   struct guild_type *iterator = guild_info;
   struct char_data *vict = NULL, *cbuf = NULL;
   struct char_file_u tmp_store;

   if (IS_NPC(ch))
     return;

   if (GET_GUILD(ch) == GUILD_NONE || GET_GUILD(ch) == GUILD_UNDEFINED) {
     send_to_char("But you're not a member of any guild!\r\n", ch);
     return;
   }

   if (GET_GUILD_LEV(ch) < GUILD_DIS_LVL) {
     send_to_char("You are not high enough level within the guild to dismiss members!\r\n", ch);
     return;
   }

   /* Make sure iterator points to the correct guild */
   while (iterator->number != GET_GUILD(ch))
      iterator = iterator->next;

   one_argument(argument, arg);

   if (!*arg) {
     send_to_char("Whom do you wish to dismiss?\r\n", ch);
     return;
   }

   /* Okay we have the name, now let's try to dismiss this troublemaker */
   if (!(vict = get_player_vis(ch, arg, 0))) {
     /* we need to load the file up :( */
     CREATE(cbuf, struct char_data, 1);
     clear_char(cbuf);
     if (load_char(arg, &tmp_store) > -1) {
       store_to_char(&tmp_store, cbuf);
       vict = cbuf;
     }
   }
   if (vict != NULL) {
     if (GET_GUILD_LEV(vict) >= GET_GUILD_LEV(ch)) {
       send_to_char("You may not dismiss those of equal or greater guild status than yourself!\r\n", ch);
       return;
     }

     GET_GUILD(vict)     = GUILD_NONE;
     GET_GUILD_LEV(vict) = 0;
     /* send some sort of mail to player notifying him/her of rejection */

     sprintf(buf, "%s is no longer a member of %s.\r\n", GET_NAME(vict), iterator->name);
     send_to_char(buf, ch);
     if (cbuf != NULL) {
       char_to_store(vict, &tmp_store);
       fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET);
       fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl);
       free_char(cbuf);
     } else
       save_char(vict, NOWHERE);
   }
}

ACMD(do_promote)
{
   int player_i = 0;
   struct guild_type *iterator = guild_info;
   struct char_data *vict = NULL, *cbuf = NULL;
   struct char_file_u tmp_store;

   if (IS_NPC(ch))
     return;

   if (GET_GUILD(ch) == GUILD_NONE || GET_GUILD(ch) == GUILD_UNDEFINED) {
     send_to_char("But you're not a member of any guild!\r\n", ch);
     return;
   }

   if (GET_GUILD_LEV(ch) < MAX_GUILD_LVL) {
     send_to_char("You are not high enough level within the guild to promote members!\r\n", ch);
     return;
   }

   /* Make sure iterator points to the correct guild */
   while (iterator->number != GET_GUILD(ch))
      iterator = iterator->next;

   one_argument(argument, arg);

   if (!*arg) {
     send_to_char("Whom do you wish to promote?\r\n", ch);
     return;
   }

   /* Okay we have the name, now let's try to advance this member */
   if (!(vict = get_player_vis(ch, arg, 0))) {
     /* we need to load the file up :( */
     CREATE(cbuf, struct char_data, 1);
     clear_char(cbuf);
     if (load_char(arg, &tmp_store) > -1) {
       store_to_char(&tmp_store, cbuf);
       vict = cbuf;
     }
   }
   if (vict != NULL) {
     if (GET_GUILD_LEV(vict) == (GET_GUILD_LEV(ch) - 1)) {
       sprintf(buf, "There can be only one %s!\r\n", iterator->xlvlname);
       send_to_char(buf, ch);
       return;
     }

     GET_GUILD_LEV(vict)++;       /* Advance PC's Guild Lev by One */
     /* send some sort of mail to player notifying him/her of promotion */

     sprintf(buf, "%s is now level %d.\r\n", GET_NAME(vict), GET_GUILD_LEV(vict));
     send_to_char(buf, ch);
     if (cbuf != NULL) {
       char_to_store(vict, &tmp_store);
       fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET);
       fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl);
       free_char(cbuf);
     } else
       save_char(vict, NOWHERE);
   }

}

ACMD(do_demote)
{
   int player_i = 0;
   struct guild_type *iterator = guild_info;
   struct char_data *vict = NULL, *cbuf = NULL;
   struct char_file_u tmp_store;

   if (IS_NPC(ch))
     return;

   if (GET_GUILD(ch) == GUILD_NONE || GET_GUILD(ch) == GUILD_UNDEFINED) {
     send_to_char("But you're not a member of any guild!\r\n", ch);
     return;
   }

   if (GET_GUILD_LEV(ch) < MAX_GUILD_LVL) {
     send_to_char("You are not high enough level within the guild to demote members!\r\n", ch);
     return;
   }

   /* Make sure iterator points to the correct guild */
   while (iterator->number != GET_GUILD(ch))
      iterator = iterator->next;

   one_argument(argument, arg);

   if (!*arg) {
     send_to_char("Whom do you wish to demote?\r\n", ch);
     return;
   }

   /* Okay we have the name, now let's try to demote this member */
   if (!(vict = get_player_vis(ch, arg, 0))) {
     /* we need to load the file up :( */
     CREATE(cbuf, struct char_data, 1);
     clear_char(cbuf);
     if (load_char(arg, &tmp_store) > -1) {
       store_to_char(&tmp_store, cbuf);
       vict = cbuf;
     }
   }
   if (vict != NULL) {
     if (GET_GUILD_LEV(vict) == 1) {
       sprintf(buf, "%s is already a %s, use dismiss instead!\r\n", 
	       GET_NAME(vict), iterator->blvlname);
       send_to_char(buf, ch);
       return;
     }

     GET_GUILD_LEV(vict)--;       /* Lower PC's Guild Lev by One */
     /* send some sort of mail to player notifying him/her of promotion */

     sprintf(buf, "%s is now level %d.\r\n", GET_NAME(vict), GET_GUILD_LEV(vict));
     send_to_char(buf, ch);
     if (cbuf != NULL) {
       char_to_store(vict, &tmp_store);
       fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET);
       fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl);
       free_char(cbuf);
     } else
       save_char(vict, NOWHERE);
   }

}


ACMD(do_guild)
{
   /* !*arg == show members | *arg == say to members */
   int    j;
   struct descriptor_data  *i;
   struct char_file_u plr_rec;
   struct guild_type *iterator = guild_info;

   if (IS_NPC(ch))
     return;

   if (GET_GUILD(ch) == GUILD_NONE || GET_GUILD(ch) == GUILD_UNDEFINED) {
     send_to_char("You must be a member of a guild to do this.\n\r", ch);
     return;
   }

   if (IS_AFFECTED2(ch, AFF_SILENCE) && (*argument)) {
     send_to_char("Your throat is too tight to get the words out.\r\n", ch);
     return;
   }
   /* Make sure iterator points to the correct guild */
   while (iterator->number != GET_GUILD(ch))
      iterator = iterator->next;

   if (!(*argument)) {
     send_to_char(CCBMG(ch, C_NRM), ch);
     send_to_char("___________________________________________",ch);
     send_to_char("\r\n\r\n",ch);
     sprintf(buf, "Other members of %s", iterator->name);
     sprintf(buf, "%s...\r\n___________________________________________%s\r\n\r\n",
	    buf, CCNRM(ch, C_NRM));
     send_to_char(buf, ch);
     /* Go through the entire list of players color coding those who are on */
     for (j = 0; j < top_of_p_table; j++) {
	if (load_char(player_table[j].name, &plr_rec) > -1)
	  if (plr_rec.assocs[1] == iterator->number)
	    sprintf(buf, "%s the %s\r\n", plr_rec.name,
	     (plr_rec.assocs[2] == 5 ? iterator->xlvlname :
	      (plr_rec.assocs[2] == 4 ? iterator->hlvlname :
	       (plr_rec.assocs[2] == 1 ? iterator->blvlname :
		(plr_rec.assocs[2] == 0 ? "ERROR!" : iterator->mlvlname)))));
     }
   } else {  /* We have an argument */
     skip_spaces(&argument);
     /* The ch sees what he/she said */
     sprintf(buf, "\r\n%sYou guild tell> %s%s\r\n", CCBCN(ch, C_SPR), argument, CCNRM(ch, C_NRM));
     send_to_char(buf, ch);

     for (i = descriptor_list; i; i = i->next)
	if (i->character != ch && !i->connected &&
	    (GET_GUILD(ch) == (i->character->player.assocs[1])) &&
	    GET_POS(i->character) >= POS_RESTING) {
	  sprintf(buf2, "\r\n%s%s guild tells> %s%s\r\n",
		    CCBCN(i->character, C_SPR), GET_NAME(ch), argument,
		    CCNRM(i->character, C_SPR));
	  send_to_char(buf2, i->character);
     }
   }
   return;
}



+-----------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
|   http://cspo.queensu.ca/~fletcher/Circle/list_faq.html   |
+-----------------------------------------------------------+



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