#include <stdio.h>
#include <string.h>
#include "lint.h"
#include "wiz_list.h"
#include "interpret.h"
/*
* Maintain the wizards high score list about most popular castle.
*/
extern char *string_copy PROT((char *)), *xalloc PROT((int));
struct wiz_list *all_wiz;
/*
* Sort the wiz list in ascending order.
*/
static struct wiz_list *insert(w, wl)
struct wiz_list *w, *wl;
{
if (wl == 0) {
w->next = 0;
return w;
}
if (w->score > wl->score) {
wl->next = insert(w, wl->next);
return wl;
}
w->next = wl;
return w;
}
static void rebuild_list() {
struct wiz_list *wl, *w, *new_list = 0;
for (w = all_wiz; w; w = wl) {
wl = w->next;
new_list = insert(w, new_list);
}
all_wiz = new_list;
}
/*
* Find the data, if it exists.
*/
static struct wiz_list *find_wiz(name)
char *name;
{
int length;
struct wiz_list *wl;
length = strlen(name);
for (wl = all_wiz; wl; wl = wl->next)
if (wl->length == length && strcmp(wl->name, name) == 0)
return wl;
return 0;
}
/*
* Check that a name exists. Add it, if it doesn't.
*/
struct wiz_list *add_name(str)
char *str;
{
struct wiz_list *wl;
wl = find_wiz(str);
if (wl)
return wl;
wl = (struct wiz_list *)xalloc(sizeof (struct wiz_list));
str = string_copy(str);
wl->name = str;
wl->length = strlen(str);
wl->score = 0;
wl->cost = 0;
wl->heart_beats = 0;
wl->total_worth = 0;
wl->next = all_wiz;
wl->size_array = 0;
wl->call_outs = 0;
wl->file_name = 0;
wl->error_message = 0;
all_wiz = wl;
return wl;
}
/*
* Add score to an existing name.
*/
void add_score(name, score)
char *name;
int score;
{
struct wiz_list *wl;
wl = find_wiz(name);
if (!wl)
fatal("Add_score: could not find wizard %s\n", name);
wl->score += score;
}
/*
* This one is called at every complete walkaround of reset.
*/
void wiz_decay() {
struct wiz_list *wl;
for (wl = all_wiz; wl; wl = wl->next) {
wl->score = wl->score * 99 / 100;
wl->total_worth = wl->total_worth * 99 / 100;
wl->cost = wl->cost * 9 / 10;
wl->heart_beats = wl->heart_beats * 9 / 10;
}
}
/*
* Load the wizlist file.
*/
void load_wiz_file()
{
char buff[1000]; /* I hate not knowing how much I need. */
FILE *f;
f = fopen("WIZLIST", "r");
if (f == NULL)
return;
while(fgets(buff, sizeof buff, f) != NULL) {
char *p;
int score;
p = strchr(buff, ' ');
if (p == 0) {
fprintf(stderr, "Bad WIZLIST file.\n");
break;
}
*p = '\0';
p++;
if (*p == '\0') {
fprintf(stderr, "Bad WIZLIST file.\n");
break;
}
score = atoi(p);
if (score > 0) {
(void)add_name(buff);
add_score(buff, atoi(p));
}
}
fclose(f);
}
/*
* Save the wizlist file.
*/
void save_wiz_file()
{
struct wiz_list *wl;
FILE *f;
f = fopen("WIZLIST", "w");
if (f == NULL) {
fprintf(stderr, "Could not open WIZLIST for write\n");
return;
}
for (wl = all_wiz; wl; wl = wl->next)
fprintf(f, "%s %d %d\n", wl->name, wl->score, wl->total_worth);
fclose(f);
}
void wizlist(v)
struct value *v;
{
struct wiz_list *wl, *this_wiz;
int total = 0, num = 0, this_pos, total_wizards;
extern struct object *command_giver;
int all = 0;
if (!command_giver)
return;
if (v == 0)
v = apply("query_real_name", command_giver, 0);
if (!v || v->type != T_STRING)
return;
if (strcmp(v->u.string, "ALL") == 0)
all = 1;
this_wiz = find_wiz(v->u.string);
rebuild_list();
for (num = 0, wl = all_wiz; wl; wl = wl->next) {
total += wl->score;
num++;
if (wl == this_wiz)
this_pos = num;
}
total_wizards = num;
add_message("\nWizard top score list\n\n");
this_pos = num - this_pos + 1;
if (total == 0)
total = 1;
for (wl = all_wiz; wl; wl = wl->next) {
if (!all && num > 15 && (num < this_pos - 2 || num > this_pos + 2))
;
else
add_message("%-15s %5d %2d%% (%d)\t[%4dk,%5d %5d] %6d %d\n", wl->name,
wl->score, wl->score * 100 / total, num,
wl->cost / 1000,
wl->heart_beats, wl->call_outs, wl->total_worth, wl->size_array);
num--;
}
add_message("\nTotal %7d (%d)\n\n", total, total_wizards);
}
void remove_wiz_list() {
struct wiz_list *wl, *w;
for (w = all_wiz; w; w = wl) {
free(w->name);
wl = w->next;
free((char *)w);
}
}
void save_error(msg, file, line)
char *msg;
char *file;
int line;
{
struct wiz_list *wl;
char name[100];
char *p;
int len;
if (sscanf(file, "players/%s/", name) != 1)
return;
p = strchr(name, '/');
if (p)
*p = '\0';
wl = add_name(name);
if (wl->file_name)
free(wl->file_name);
len = strlen(file);
wl->file_name = xalloc(len + 3); /* May add .c plus the null byte */
strcpy(wl->file_name, file);
/*
* If it is a cloned object, we have to find out what the file
* name is, and add '.c'.
*/
p = strrchr(wl->file_name, '#');
if (p) {
p[0] = '.';
p[1] = 'c';
p[2] = '\0';
len = p - wl->file_name + 2;
}
if (wl->file_name[len-1] != 'c' || wl->file_name[len-2] != '.')
strcat(wl->file_name, ".c");
if (wl->error_message)
free(wl->error_message);
wl->error_message = string_copy(msg);
wl->line_number = line;
}
char *get_error_file(name)
char *name;
{
struct value *v;
extern struct object *command_giver;
struct wiz_list *wl;
wl = add_name(name);
/*
* The error_message is used as a flag if there has been any error.
*/
if (wl->error_message == 0) {
add_message("No error.\n");
return 0;
}
add_message("%s line %d: %s\n", wl->file_name, wl->line_number,
wl->error_message);
free(wl->error_message);
wl->error_message = 0;
return wl->file_name;
}