[Circle] Forwarded mail.... part 1 of 4

From: Pandion (s337239@student.uq.edu.au)
Date: 07/26/96


Here it is in chunks.  Tear it up as you wish.

Good luck understanding it all !!!!!

I did it as modularly as possible.  If you like it... please tell me.  
Moreover if you find bugs, please tell me.

Also I forgot to include the call to update_memorising() which is 
supposed to be right after the call to pulse_violence() in comm.c

work the rest out yourself.. *grin*.. damn I am helpful

Chris Voutsis

---------- Forwarded message ----------
Date: Fri, 26 Jul 1996 22:28:04 +1000
From: System Adminisitrator <root@Linux.slip.cc.uq.oz.au>
To: s337239@student.uq.edu.au

/* ************************************************************************
*   File: circles.c                                     Part of CircleMUD *
*  Usage: Definition and implementation of Circle magic system            *
*									  *
*  Written by Chris Voutsis  (hopefully)				  *
*                                                                         *
************************************************************************ */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "handler.h"
#include "interpreter.h"
#include "db.h"
#include "spells.h"

/* External structures */

extern int spell_sort_info[MAX_SPELLS+1];

char *how_good(int percent);

/* Definitions for circle magic system */

/* Some associated definitions are in structs.h, such as MAX_CIRCLES,	  *
 * MAX_CIRCLE_TYPES, and some others.  Also included here will be macros  *
 * that cannot be done in utils.h...					  */

/* this is done so classes can have some balance */

const int class_multipliers[NUM_CLASSES][MAX_CIRCLE_TYPES] =
{
  { 10,  1},
  {  1, 10},
  { 10, 10},
  { 10, 10}
};

#define CMULT(ch, i) class_multipliers[(int) (GET_CLASS(ch))][i]

/* change this to the highest number in the table below !!!!!!!! */

#define MAX_OF_MAX_CASTINGS 10

const int max_castings[MAX_CIRCLE_TYPES][MAX_CIRCLES] =
{
 {10, 9, 8, 7, 6, 5, 4, 3, 3, 2},
 {10, 9, 8, 7, 6, 5, 4, 3, 3, 2}
};

/* in the following structure, the third dimension of this array should
   REALLY be the max_castings for that circle type and circle.		*/

const int circle_gains[MAX_CIRCLE_TYPES][MAX_CIRCLES][MAX_OF_MAX_CASTINGS] = {
  {
  { 1,  2,  3,  6,  9, 12, 15, 18, 22, 25},
  { 3,  4,  5,  7, 10, 13, 16, 20, 24},
  { 5,  6,  8, 11, 14, 17, 21, 25},
  { 8, 10, 13, 17, 20, 23, 27},
  {11, 13, 16, 19, 22, 26},
  {15, 18, 21, 24, 28},
  {19, 21, 24, 27},
  {22, 25, 29},
  {25, 27, 30},
  {29, 30},
  },
  {
  { 1,  2,  3,  6,  9, 12, 15, 18, 22, 25},
  { 3,  4,  5,  7, 10, 13, 16, 20, 24},
  { 5,  6,  8, 11, 14, 17, 21, 25},
  { 8, 10, 13, 17, 20, 23, 27},
  {11, 13, 16, 19, 22, 26},
  {15, 18, 21, 24, 28},
  {19, 21, 24, 27},
  {22, 25, 29},
  {25, 27, 30},
  {29, 30},
  }
};

const char *spell_circles[MAX_CIRCLES] =
{
  "Initiate Circle",  /* A better name than !UNUSED!, dont you think ?	*/
  "First Circle",
  "Second Circle",
  "Third Circle",
  "Fourth Circle",
  "Fifth Circle",
  "Sixth Circle",
  "Seventh Circle",
  "Eighth Circle",
  "Ninth Circle",
  "Tenth Circle"
};

const char *spell_circle_descr[MAX_CIRCLES] =
{
  "not trained in",
  "of the First Circle of",
  "of the Second Circle of",
  "of the Third Circle of",
  "of the Fourth Circle of",
  "of the Fifth Circle of",
  "of the Sixth Circle of",
  "of the Seventh Circle of",
  "of the Eighth Circle of",
  "of the Ninth Circle of",
  "of the Tenth Circle of"
};

int cleric_circle(struct char_data *ch) {

  int i;

  for (i = 0; i < MAX_CIRCLES - 1; i++)
    if (GET_LEVEL(ch) <
	(circle_gains[CIRCLE_CLERIC][i][0] * CMULT(ch, CIRCLE_CLERIC)))
      return i;
  return (MAX_CIRCLES - 1);
}

int magic_circle(struct char_data *ch) {

  int i;

  for (i = 0; i < MAX_CIRCLES - 1; i++)
    if (GET_LEVEL(ch) <
	(circle_gains[CIRCLE_MAGIC][i][0] * CMULT(ch, CIRCLE_MAGIC)))
      return i;
  return (MAX_CIRCLES - 1);
}

int get_max_ccastings(struct char_data *ch, int circle) {

  int j, i;

  i = max_castings[CIRCLE_CLERIC][circle - 1];

  for (j = 0; j < i; j++)
    if (GET_LEVEL(ch) <
	(circle_gains[CIRCLE_CLERIC][circle - 1][j] * CMULT(ch, CIRCLE_CLERIC)))
      return j;
  return i;
}

int get_max_mcastings(struct char_data *ch, int circle) {

  int j, i;

  i = max_castings[CIRCLE_MAGIC][circle - 1];

  for (j = 0; j < i; j++)
    if (GET_LEVEL(ch) <
	(circle_gains[CIRCLE_MAGIC][circle - 1][j] * CMULT(ch, CIRCLE_MAGIC)))
      return j;
  return i;
}

int has_cleric_circle(struct char_data *ch, int circle) {

  if ((cleric_circle(ch) >= circle) && (circle > 0))
    return 1;
  else
    return 0;
}

int has_magic_circle(struct char_data *ch, int circle) {

  if ((magic_circle(ch) >= circle) && (circle > 0))
    return 1;
  else
    return 0;
}

void max_out_castings(struct char_data *ch) {

  int i;

  for (i = 1; i < MAX_CIRCLES; i++) {
    GET_CCASTINGS(ch, i) = get_max_ccastings(ch, i);
    GET_MCASTINGS(ch, i) = get_max_mcastings(ch, i);
  }
}

#define IS_SPELL(i) ((i >= 1) && (i <= MAX_SPELLS))

void list_magic_spells(struct char_data * ch)
{
  extern char *spells[];
  extern struct spell_info_type spell_info[];
  int i, j, sortpos, counter = 0;

  if (!has_magic_circle(ch, 1)) {
    send_to_char("You are not trained in magical spells.\r\n", ch);
    return;
  }

  if (!GET_PRACTICES(ch))
    strcpy(buf, "You have no practice sessions remaining.\r\n");
  else
    sprintf(buf, "You have %d practice session%s remaining.\r\n",
            GET_PRACTICES(ch), (GET_PRACTICES(ch) == 1 ? "" : "s"));

  sprintf(buf, "%sYou know of the following spells:\r\n", buf);

  strcpy(buf2, buf);
  for (j = 1; j < MAX_CIRCLES; j++) {
    if (has_magic_circle(ch, j)) {
      counter = 0;
      strcat(buf2, spell_circles[j]);
      strcat(buf2, ":\r\n\r\n");
      for (sortpos = 1; sortpos < MAX_SKILLS; sortpos++) {
        i = spell_sort_info[sortpos];
        if (strlen(buf2) >= MAX_STRING_LENGTH - 32) {
          strcat(buf2, "**OVERFLOW**\r\n");
          break;
        }
        if (IS_SPELL(i)) {
          if (SPELL_MAGIC_CIRCLE(i) == j) {
            sprintf(buf, "%-20s %s\r\n", spells[i], how_good(GET_SKILL(ch, i)));
            strcat(buf2, buf);
            counter++;
          }
        }
      }
      if (!counter)
        strcat(buf2, "None !\r\n\r\n");
      else {
        sprintf(buf, "\r\nYou may cast %d of a maximum %d spells of this circle.\r\n\r\n",
                GET_MCASTINGS(ch, j), get_max_mcastings(ch, j));
        strcat(buf2, buf);
      }
    }
  }
  page_string(ch->desc, buf2, 1);
}

void list_cleric_spells(struct char_data * ch)
{
  extern char *spells[];
  extern struct spell_info_type spell_info[];
  int i, j, sortpos, counter = 0;

  if (!has_cleric_circle(ch, 1)) {
    send_to_char("You are not trained in clerical spells.\r\n", ch);
    return;
  }

  if (!GET_PRACTICES(ch))
    strcpy(buf, "You have no practice sessions remaining.\r\n");
  else
    sprintf(buf, "You have %d practice session%s remaining.\r\n",
            GET_PRACTICES(ch), (GET_PRACTICES(ch) == 1 ? "" : "s"));

  sprintf(buf, "%sYou know of the following spells:\r\n", buf);

  strcpy(buf2, buf);

  for (j = 1; j < MAX_CIRCLES; j++) {
    if (has_cleric_circle(ch, j)) {
      counter = 0;
      strcat(buf2, spell_circles[j]);
      strcat(buf2, ":\r\n\r\n");
      for (sortpos = 1; sortpos < MAX_SKILLS; sortpos++) {
        i = spell_sort_info[sortpos];
        if (strlen(buf2) >= MAX_STRING_LENGTH - 32) {
          strcat(buf2, "**OVERFLOW**\r\n");
          break;
        }
        if (IS_SPELL(i)) {
          if (SPELL_CLERIC_CIRCLE(i) == j) {
            sprintf(buf, "%-20s %s\r\n", spells[i], how_good(GET_SKILL(ch, i)));
            strcat(buf2, buf);
            counter++;
          }
        }
      }
      if (!counter)
        strcat(buf2, "None !\r\n\r\n");
      else {
        sprintf(buf, "\r\nYou may cast %d of a maximum %d spells of this circle.\r\n\r\n",
                GET_CCASTINGS(ch, j), get_max_ccastings(ch, j));
        strcat(buf2, buf);
      }
    }
  }
  page_string(ch->desc, buf2, 1);
}

ACMD(do_memorise)
{
  void list_magic_spells(struct char_data *ch);

  float a, b, c;
  int circle;

  one_argument(argument, arg);

  if (*arg) {
    if (!str_cmp("stop", arg)) {
      if (!PLR_FLAGGED(ch, PLR_MEMORISING)) {
        send_to_char("You are not memorising.  How can you stop ?", ch);
        return;
      }
      REMOVE_BIT(PLR_FLAGS(ch), PLR_MEMORISING);
      GET_CIRCLE(ch) = 0;
      GET_TIME_LEFT(ch) = 0;
      send_to_char("You stop memorising.\r\n", ch);
      act("$n packs up $s spellbook, somewhat frustrated.\r\n", FALSE, ch, 0, 0, TO_ROOM);
      return;
    }
    if (!is_number(arg)) {
      send_to_char("Please specify the circle of spell you wish to memorise.\r\n", ch);
      return;
    }
    if (PLR_FLAGGED(ch, PLR_PRAYING)) {
      send_to_char("You are already praying for a spell.  Stop praying first.\r\n", ch);
      return;
    }
    if (PLR_FLAGGED(ch, PLR_MEMORISING)) {
      send_to_char("You are already memorising a spell.  Stop memorising first.\r\n", ch);
      return;
    }
    circle = atoi(arg);
    if (!has_magic_circle(ch, circle)) {
      send_to_char("But you do not know of that circle of spells!  How can you memorise them ?\r\n", ch);
      return;
    }
    if (GET_MCASTINGS(ch, circle) >= get_max_mcastings(ch, circle)) {
      send_to_char("You have already memorised all you can from that circle.\r\n", ch);
      return;
    }
    if ((GET_POS(ch) != POS_RESTING) && (GET_POS(ch) != POS_SITTING)) {
      send_to_char("There's no way you can memorise like this.  Try sitting or resting.\r\n", ch);
      return;
    }
    act("$n studies a spellbook intently.", FALSE, ch, 0, 0, TO_ROOM);
    SET_BIT(PLR_FLAGS(ch), PLR_MEMORISING);
    GET_CIRCLE(ch) = circle;
    a = circle;
    b = magic_circle(ch);
    c = a / b;
    c = c * 30;
    GET_TIME_LEFT(ch) = (int) c;
    sprintf(buf, "You start memorising a %s spell, which will take about %d seconds.\r\n",
	spell_circles[GET_CIRCLE(ch)], GET_TIME_LEFT(ch) * 2);
    send_to_char(buf, ch);
  } else
    if (!PLR_FLAGGED(ch, PLR_MEMORISING)) {
      list_magic_spells(ch);
    } else {
      sprintf(buf, "Circle: %s, Time Remaining: %d seconds.\r\n",
        spell_circles[GET_CIRCLE(ch)], GET_TIME_LEFT(ch) * 2);
      send_to_char("You are currently memorising:\r\n\r\n", ch);
      send_to_char(buf, ch);
    }
}

ACMD(do_pray)
{
  void list_cleric_spells(struct char_data *ch);

  float a, b, c;
  int circle;

  one_argument(argument, arg);

  if (*arg) {
    if (!str_cmp("stop", arg)) {
      if (!PLR_FLAGGED(ch, PLR_PRAYING)) {
        send_to_char("You are not praying.  How can you stop ?", ch);
        return;
      }
      REMOVE_BIT(PLR_FLAGS(ch), PLR_PRAYING);
      GET_CIRCLE(ch) = 0;
      GET_TIME_LEFT(ch) = 0;
      send_to_char("You cease your prayers.\r\n", ch);
      act("$n opens $s eyes, somewhat frustrated.\r\n", FALSE, ch, 0, 0, TO_ROOM);
      return;
    }
    if (!is_number(arg)) {
      send_to_char("Please specify the circle of spell you wish to pray for.\r\n", ch);
      return;
    }
    if (PLR_FLAGGED(ch, PLR_PRAYING)) {
      send_to_char("You are already praying for a spell.  Stop praying first.\r\n", ch);
      return;
    }
    if (PLR_FLAGGED(ch, PLR_MEMORISING)) {
      send_to_char("You are already memorising a spell.  Stop memorising first.\r\n", ch);
      return;
    }
    circle = atoi(arg);
    if (!has_cleric_circle(ch, circle)) {
      send_to_char("But you do not know of that circle of spells!  How can you pray for it ?\r\n", ch);
      return;
    }
    if (GET_CCASTINGS(ch, circle) >= get_max_ccastings(ch, circle)) {
      send_to_char("You have already prayed for all you can from that circle.\r\n", ch);
      return;
    }
    if ((GET_POS(ch) != POS_RESTING) && (GET_POS(ch) != POS_SITTING)) {
      send_to_char("There's no way you can pray like this.  Try sitting or resting.\r\n", ch);
      return;
    }
    act("$n closes $s eyes in a prayer to $s god.", FALSE, ch, 0, 0, TO_ROOM);
    SET_BIT(PLR_FLAGS(ch), PLR_PRAYING);
    GET_CIRCLE(ch) = circle;
    a = circle;
    b = cleric_circle(ch);
    c = a / b;
    c = c * 30;
    GET_TIME_LEFT(ch) = (int) c;
    sprintf(buf, "You start praying for a %s spell, which will take about %d seconds.\r\n",
	spell_circles[GET_CIRCLE(ch)], GET_TIME_LEFT(ch) * 2);
    send_to_char(buf, ch);
  } else
    if (!PLR_FLAGGED(ch, PLR_PRAYING)) {
      list_cleric_spells(ch);
    } else {
      sprintf(buf, "Circle: %s, Time Remaining: %d seconds.\r\n",
        spell_circles[GET_CIRCLE(ch)], GET_TIME_LEFT(ch) * 2);
      send_to_char("You are currently praying for:\r\n\r\n", ch);
      send_to_char(buf, ch);
    }
}

ACMD(do_grant)
{
  struct char_data *vict;
  char param1[MAX_INPUT_LENGTH], param2[MAX_INPUT_LENGTH];
  int circle;

  if (IS_NPC(ch))
    return;

  if (!*argument) {
    send_to_char("Usage of command (gods and above): \r\n\r\n", ch);
    if (subcmd == SCMD_CL)
      send_to_char("  cgrant (name) (circle)\r\n\r\n", ch);
    else if (subcmd == SCMD_MU)
      send_to_char("  mgrant (name) (circle)\r\n\r\n", ch);
    send_to_char("To grant player (name) spell circle (circle).\r\n", ch);
    return;
  }
  half_chop(argument, param1, param2);

  if (!(vict = get_player_vis(ch, param1, 0))) {
    send_to_char("There is no such player.\r\n", ch);
    return;
  }
  if (!is_number(param2)) {
    send_to_char("Which circle is THAT ?\r\n", ch);
    return;
  }
  circle = atoi(param2);

  if (circle < 1 || circle >= MAX_CIRCLES) {
    send_to_char("That is not a valid circle.\r\n", ch);
    return;
  }
  if (GET_LEVEL(vict) > GET_LEVEL(ch)) {
    send_to_char("Lets not, and say we did, okay ?\r\n", ch);
  }
  sprintf(buf, "You grant %s a spell of the %s.\r\n", GET_NAME(vict),
        spell_circles[circle]);
  send_to_char(buf, ch);
  if (subcmd == SCMD_CL) {
    sprintf(buf, "(GC) %s grants a clerical spell of the %s to %s.", GET_NAME(ch),
        spell_circles[circle], GET_NAME(vict));
    mudlog(buf, BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE);
    if ((PLR_FLAGGED(vict, PLR_PRAYING)) && (GET_CIRCLE(vict) = circle)) {
      sprintf(buf, "%s has granted your spell!\r\n", GET_NAME(ch));
      send_to_char(buf, vict);
      GET_TIME_LEFT(vict) = 0;
    } else {
      GET_CCASTINGS(vict, circle)++;
      sprintf(buf, "%s has granted you a casting %s Clerics!\r\n",
                GET_NAME(ch), spell_circle_descr[circle]);
      send_to_char(buf, vict);
    }
  } else if (subcmd == SCMD_MU) {
    sprintf(buf, "(GC) %s grants a magical spell of the %s to %s.", GET_NAME(ch),
        spell_circles[circle], GET_NAME(vict));
    mudlog(buf, BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE);
    if ((PLR_FLAGGED(vict, PLR_MEMORISING)) && (GET_CIRCLE(vict) = circle)) {
      sprintf(buf, "%s has granted your spell!\r\n", GET_NAME(ch));
      send_to_char(buf, vict);
      GET_TIME_LEFT(vict) = 0;
    } else {
      GET_MCASTINGS(vict, circle)++;
      sprintf(buf, "%s has granted you a casting %s Magiks!\r\n",
                GET_NAME(ch), spell_circle_descr[circle]);
      send_to_char(buf, vict);
    }
  }
}

ACMD(do_ungrant)
{
  struct char_data *vict;
  char param1[MAX_INPUT_LENGTH], param2[MAX_INPUT_LENGTH];
  int circle;

  if (IS_NPC(ch))
    return;

  if (!*argument) {
    send_to_char("Usage of command (gods and above): \r\n\r\n", ch);
    if (subcmd == SCMD_CL)
      send_to_char("  cungrant (name) (circle)\r\n\r\n", ch);
    else if (subcmd == SCMD_MU)
      send_to_char("  mungrant (name) (circle)\r\n\r\n", ch);
    send_to_char("To grant player (name) spell circle (circle).\r\n", ch);
    return;
  }
  half_chop(argument, param1, param2);

  if (!(vict = get_player_vis(ch, param1, 0))) {
    send_to_char("There is no such player.\r\n", ch);
    return;
  }
  if (!is_number(param2)) {
    send_to_char("Which circle is THAT ?\r\n", ch);
    return;
  }
  circle = atoi(param2);

  if (circle < 1 || circle >= MAX_CIRCLES) {
    send_to_char("That is not a valid circle.\r\n", ch);
    return;
  }
  if (GET_LEVEL(vict) > GET_LEVEL(ch)) {
    send_to_char("Lets not, and say we did, okay ?\r\n", ch);
  }
  sprintf(buf, "You ungrant %s a spell of the %s.\r\n", GET_NAME(vict),
        spell_circles[circle]);
  send_to_char(buf, ch);
  if (subcmd == SCMD_CL) {
    sprintf(buf, "(GC) %s ungrants a clerical spell of the %s to %s.", GET_NAME(ch),
        spell_circles[circle], GET_NAME(vict));
    mudlog(buf, BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE);
    if ((PLR_FLAGGED(vict, PLR_PRAYING)) && (GET_CIRCLE(vict) = circle)) {
      sprintf(buf, "%s has denied you your spell!\r\n", GET_NAME(ch));
      send_to_char(buf, vict);
      GET_CCASTINGS(vict, circle)--;
      GET_TIME_LEFT(vict) = 0;
    } else {
      GET_CCASTINGS(vict, circle)--;
      sprintf(buf, "%s has withdrawn from you a casting %s Clerics!\r\n",
                GET_NAME(ch), spell_circle_descr[circle]);
      send_to_char(buf, vict);
    }
  } else if (subcmd == SCMD_MU) {
    sprintf(buf, "(GC) %s ungrants a magical spell of the %s to %s.", GET_NAME(ch),
        spell_circles[circle], GET_NAME(vict));
    mudlog(buf, BRF, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE);
    if ((PLR_FLAGGED(vict, PLR_MEMORISING)) && (GET_CIRCLE(vict) = circle)) {
      sprintf(buf, "%s has denied your spell!\r\n", GET_NAME(ch));
      send_to_char(buf, vict);
      GET_MCASTINGS(vict, circle)--;
      GET_TIME_LEFT(vict) = 0;
    } else {
      GET_MCASTINGS(vict, circle)--;
      sprintf(buf, "%s has withdrawn from you a casting %s Magiks!\r\n",
                GET_NAME(ch), spell_circle_descr[circle]);
      send_to_char(buf, vict);
    }
  }
}

void update_memorising(void) {
  extern struct char_data *character_list;

  struct char_data *ch, *next_ch;

  for (ch = character_list; ch; ch = next_ch) {
    next_ch = ch->next;
    if (!IS_NPC(ch)) {
      if (PLR_FLAGGED(ch, PLR_PRAYING) || PLR_FLAGGED(ch, PLR_MEMORISING)) {
        if (FIGHTING(ch) || !AWAKE(ch) || AFF_FLAGGED(ch, AFF_FROZEN) ||
          AFF_FLAGGED(ch, AFF_PETRIFY) || AFF_FLAGGED(ch, AFF_FIRE) ||
          (GET_POS(ch) != POS_SITTING && GET_POS(ch) != POS_RESTING)) {
          sprintf(buf, "Well, so much for %s.\r\n", (PLR_FLAGGED(ch, PLR_PRAYING)) ?
                "praying" : "memorising");
          send_to_char(buf, ch);
          REMOVE_BIT(PLR_FLAGS(ch), PLR_PRAYING | PLR_MEMORISING);
          GET_CIRCLE(ch) = 0;
          GET_TIME_LEFT(ch) = 0;
          return;
        }
        if (GET_TIME_LEFT(ch) > 0)
          GET_TIME_LEFT(ch)--;
        if (!GET_TIME_LEFT(ch)) {
          if PLR_FLAGGED(ch, PLR_PRAYING) {
            sprintf(buf, "You have finished praying for a spell of the %s.\r\n",
                spell_circles[GET_CIRCLE(ch)]);
            send_to_char(buf, ch);
            act("$n opens $s eyes and smiles happily.", FALSE, ch, 0, 0, TO_ROOM);
            GET_CCASTINGS(ch, GET_CIRCLE(ch))++;
            REMOVE_BIT(PLR_FLAGS(ch), PLR_PRAYING | PLR_MEMORISING);
            GET_CIRCLE(ch) = 0;
            return;
          } else {
            sprintf(buf, "You have finished memorising a spell of the %s.\r\n",
                spell_circles[GET_CIRCLE(ch)]);
            send_to_char(buf, ch);
            act("$n closes $s spellbook and smiles happily.", FALSE, ch, 0, 0, TO_ROOM);
            GET_MCASTINGS(ch, GET_CIRCLE(ch))++;
            REMOVE_BIT(PLR_FLAGS(ch), PLR_PRAYING | PLR_MEMORISING);
            GET_CIRCLE(ch) = 0;
            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