/* ************************************************************************
* file: autowiz.c Part of tbaMUD *
* Usage: self-updating wizlists *
* Written by Jeremy Elson *
* All Rights Reserved *
* Copyright (C) 1993 The Trustees of The Johns Hopkins University *
************************************************************************* */
#include "conf.h"
#include "sysdep.h"
#include <signal.h>
#include "structs.h"
#include "utils.h"
#include "db.h"
#define IMM_LMARG " "
#define IMM_NSIZE 16
#define LINE_LEN 64
#define MIN_LEVEL LVL_IMMORT
/* max level that should be in columns instead of centered */
#define COL_LEVEL LVL_IMMORT
struct name_rec {
char name[25];
struct name_rec *next;
};
struct control_rec {
int level;
char *level_name;
};
struct level_rec {
struct control_rec *params;
struct level_rec *next;
struct name_rec *names;
};
struct control_rec level_params[] =
{
{LVL_IMMORT, "Immortals"},
{LVL_GOD, "Gods"},
{LVL_GRGOD, "Greater Gods"},
{LVL_IMPL, "Implementors"},
{0, ""}
};
struct level_rec *levels = 0;
void initialize(void)
{
struct level_rec *tmp;
int i = 0;
while (level_params[i].level > 0) {
tmp = (struct level_rec *) malloc(sizeof(struct level_rec));
tmp->names = 0;
tmp->params = &(level_params[i++]);
tmp->next = levels;
levels = tmp;
}
}
void read_file(void)
{
void add_name(byte level, char *name);
char *CAP(char *txt);
int get_line(FILE * fl, char *buf);
bitvector_t asciiflag_conv(char *flag);
FILE *fl;
int recs, i, last = 0, level = 0, flags = 0;
char index_name[40], line[256], bits[64];
char name[MAX_NAME_LENGTH];
long id = 0;
sprintf(index_name, "%s%s", LIB_PLRFILES, INDEX_FILE);
if (!(fl = fopen(index_name, "r"))) {
perror("Error opening playerfile");
exit(1);
}
/* count the number of players in the index */
recs = 0;
while (get_line(fl, line))
if (*line != '~')
recs++;
rewind(fl);
for (i = 0; i < recs; i++) {
get_line(fl, line);
sscanf(line, "%ld %s %d %s %d", &id, name, &level, bits, &last);
CAP(name);
flags = asciiflag_conv(bits);
if (level >= MIN_LEVEL &&
!(IS_SET(flags, PINDEX_NOWIZLIST)) &&
!(IS_SET(flags, PINDEX_DELETED)))
add_name(level, name);
}
fclose(fl);
}
void add_name(byte level, char *name)
{
struct name_rec *tmp;
struct level_rec *curr_level;
char *ptr;
if (!*name)
return;
for (ptr = name; *ptr; ptr++)
if (!isalpha(*ptr))
return;
tmp = (struct name_rec *) malloc(sizeof(struct name_rec));
strcpy(tmp->name, name);
tmp->next = 0;
curr_level = levels;
while (curr_level->params->level > level)
curr_level = curr_level->next;
tmp->next = curr_level->names;
curr_level->names = tmp;
}
void sort_names(void)
{
struct level_rec *curr_level;
struct name_rec *a, *b;
char temp[100];
for (curr_level = levels; curr_level; curr_level = curr_level->next) {
for (a = curr_level->names; a && a->next; a = a->next) {
for (b = a->next; b; b = b->next) {
if (strcmp(a->name, b->name) > 0) {
strcpy(temp, a->name);
strcpy(a->name, b->name);
strcpy(b->name, temp);
}
}
}
}
}
void write_wizlist(FILE * out, int minlev, int maxlev)
{
char buf[100];
struct level_rec *curr_level;
struct name_rec *curr_name;
int i, j;
fprintf(out,
"*******************************************************************************\n"
"* The following people have reached immortality on tbaMUD. *\n"
"*******************************************************************************\n\n");
for (curr_level = levels; curr_level; curr_level = curr_level->next) {
if (curr_level->params->level < minlev ||
curr_level->params->level > maxlev)
continue;
i = 39 - (strlen(curr_level->params->level_name) >> 1);
for (j = 1; j <= i; j++)
fputc(' ', out);
fprintf(out, "%s\n", curr_level->params->level_name);
for (j = 1; j <= i; j++)
fputc(' ', out);
for (j = 1; j <= strlen(curr_level->params->level_name); j++)
fputc('~', out);
fprintf(out, "\n");
strcpy(buf, "");
curr_name = curr_level->names;
while (curr_name) {
strcat(buf, curr_name->name);
if (strlen(buf) > LINE_LEN) {
if (curr_level->params->level <= COL_LEVEL)
fprintf(out, IMM_LMARG);
else {
i = 40 - (strlen(buf) >> 1);
for (j = 1; j <= i; j++)
fputc(' ', out);
}
fprintf(out, "%s\n", buf);
strcpy(buf, "");
} else {
if (curr_level->params->level <= COL_LEVEL) {
for (j = 1; j <= (IMM_NSIZE - strlen(curr_name->name)); j++)
strcat(buf, " ");
}
if (curr_level->params->level > COL_LEVEL)
strcat(buf, " ");
}
curr_name = curr_name->next;
}
if (*buf) {
if (curr_level->params->level <= COL_LEVEL)
fprintf(out, "%s%s\n", IMM_LMARG, buf);
else {
i = 40 - (strlen(buf) >> 1);
for (j = 1; j <= i; j++)
fputc(' ', out);
fprintf(out, "%s\n", buf);
}
}
fprintf(out, "\n");
}
}
int main(int argc, char **argv)
{
int wizlevel, immlevel, pid = 0;
FILE *fl;
if (argc != 5 && argc != 6) {
printf("Format: %s wizlev wizlistfile immlev immlistfile [pid to signal]\n",
argv[0]);
exit(0);
}
wizlevel = atoi(argv[1]);
immlevel = atoi(argv[3]);
#ifdef CIRCLE_UNIX /* Perhaps #ifndef CIRCLE_WINDOWS but ... */
if (argc == 6)
pid = atoi(argv[5]);
#endif
initialize();
read_file();
sort_names();
fl = fopen(argv[2], "w");
write_wizlist(fl, wizlevel, LVL_IMPL);
fclose(fl);
fl = fopen(argv[4], "w");
write_wizlist(fl, immlevel, wizlevel - 1);
fclose(fl);
#ifdef CIRCLE_UNIX /* ... I don't have the platforms to test. */
if (pid)
kill(pid, SIGUSR1);
#endif
return (0);
}
char *CAP(char *txt)
{
*txt = UPPER(*txt);
return (txt);
}
/* get_line reads the next non-blank line off of the input stream. The newline
* character is removed from the input. Lines which begin with '*' are
* considered to be comments. Returns the number of lines advanced in the
* file. */
int get_line(FILE * fl, char *buf)
{
char temp[256], *buf2;
int lines = 0;
do {
buf2 = fgets(temp, 256, fl);
if (feof(fl))
return (0);
lines++;
} while (*temp == '*' || *temp == '\n');
temp[strlen(temp) - 1] = '\0';
strcpy(buf, temp);
return (lines);
}
bitvector_t asciiflag_conv(char *flag)
{
bitvector_t flags = 0;
int is_number = 1;
register char *p;
for (p = flag; *p; p++) {
if (islower(*p))
flags |= 1 << (*p - 'a');
else if (isupper(*p))
flags |= 1 << (26 + (*p - 'A'));
if (!isdigit(*p))
is_number = 0;
}
if (is_number)
flags = atol(flag);
return (flags);
}