#include <sys/types.h>
#include <sys/times.h>
#include <sys/stat.h>
#include "header.h"
struct scofmt {
long score;
long suid;
short what;
short level;
short hardlev;
short order;
char who[40];
char sciv[26][2];
};
struct wscofmt {
long score;
long timeused;
long taxes;
long suid;
short hardlev;
short order;
char who[40];
};
struct log_fmt {
long score;
time_t diedtime;
short cavelev;
short diff;
#ifdef EXTRA
long elapsedtime;
long bytout;
long bytin;
long moves;
short ac;
short hp,hpmax;
short cputime;
short killed,spused;
short usage;
short lev;
#endif
char who[12];
char what[46];
};
static struct scofmt sco[SCORESIZE];
static struct wscofmt winr[SCORESIZE];
static struct log_fmt logg;
static const char *whydead[] = {
"quit", "suspended", "self - annihilated", "shot by an arrow",
"hit by a dart", "fell into a pit", "fell into a bottomless pit",
"a winner", "trapped in solid rock", "killed by a missing save file",
"killed by an old save file", "caught by the greedy cheater checker trap",
"killed by a protected save file", "killed his family and committed suicide",
"erased by a wayward finger", "fell through a bottomless trap door",
"fell through a trap door", "drank some poisonous water",
"fried by an electric shock", "slipped on a volcano shaft",
"killed by a stupid act of frustration", "attacked by a revolting demon",
"hit by his own magic", "demolished by an unseen attacker",
"fell into the dreadful sleep", "killed by an exploding chest",
"killed by a missing maze data file", "annihilated in a sphere",
"died a post mortem death", "wasted by a malloc() failure"
};
static int readboard(void);
static int writeboard(void);
static int winshou(void);
static int shou(int);
static int sortboard(void);
static void newscore(long, char *, int, int);
static void new1sub(long, int, char *, long);
static void new2sub(long, int, char *, int);
static void diedsub(int);
static int
readboard(void)
{
if (lopen(scorefile) < 0) {
lprcat("Can't read scoreboard\n");
lflush();
return (-1);
}
lrfill((char *)sco, sizeof(sco));
lrfill((char *)winr, sizeof(winr));
lrclose();
lcreat(NULL);
return (0);
}
static int
writeboard(void)
{
set_score_output();
if (lcreat(scorefile) < 0) {
lprcat("Can't write scoreboard\n");
lflush();
return (-1);
}
lwrite((char *)sco, sizeof(sco));
lwrite((char *)winr, sizeof(winr));
lwclose();
lcreat(NULL);
return (0);
}
int
makeboard(void)
{
int i;
for (i = 0; i < SCORESIZE; i++) {
winr[i].taxes = winr[i].score = sco[i].score = 0;
winr[i].order = sco[i].order = i;
}
if (writeboard())
return (-1);
chmod(scorefile, 0660);
return (0);
}
int
hashewon(void)
{
int i;
c[HARDGAME] = 0;
if (readboard() < 0)
return (0);
for (i = 0; i < SCORESIZE; i++)
if (winr[i].suid == userid)
if (winr[i].score > 0) {
c[HARDGAME] = winr[i].hardlev + 1;
outstanding_taxes = winr[i].taxes;
return (1);
}
return (0);
}
long
paytaxes(long x)
{
int i;
long amt;
if (x < 0)
return (0L);
if (readboard() < 0)
return (0L);
for (i = 0; i < SCORESIZE; i++)
if (winr[i].suid == userid)
if (winr[i].score > 0) {
amt = winr[i].taxes;
if (x < amt)
amt = x;
winr[i].taxes -= amt;
outstanding_taxes -= amt;
if (writeboard() < 0)
return (0);
return (amt);
}
return (0L);
}
static int
winshou(void)
{
struct wscofmt *p;
int i, j, count;
for (count = j = i = 0; i < SCORESIZE; i++)
if (winr[i].score != 0) {
j++;
break;
}
if (j) {
lprcat("\n Score Difficulty Time Needed Larn Winners List\n");
for (i = 0; i < SCORESIZE; i++)
for (j = 0; j < SCORESIZE; j++) {
p = &winr[j];
if (p->order == i) {
if (p->score) {
count++;
lprintf("%10d %2d %5d Mobuls %s \n",
(long)p->score, (long)p->hardlev, (long)p->timeused, p->who);
}
break;
}
}
}
return (count);
}
static int
shou(int x)
{
int i, j, n, k;
int count;
for (count = j = i = 0; i < SCORESIZE; i++)
if (sco[i].score != 0) {
j++;
break;
}
if (j) {
lprcat("\n Score Difficulty Larn Visitor Log\n");
for (i = 0; i < SCORESIZE; i++)
for (j = 0; j < SCORESIZE; j++)
if (sco[j].order == i) {
if (sco[j].score) {
count++;
lprintf("%10d %2d %s ",
(long)sco[j].score, (long)sco[j].hardlev, sco[j].who);
if (sco[j].what < 256)
lprintf("killed by a %s", monster[sco[j].what].name);
else
lprintf("%s", whydead[sco[j].what - 256]);
if (x != 263)
lprintf(" on %s", levelname[sco[j].level]);
if (x) {
for (n = 0; n < 26; n++) {
iven[n] = sco[j].sciv[n][0];
ivenarg[n] = sco[j].sciv[n][1];
}
for (k = 1; k < 99; k++)
for (n = 0; n < 26; n++)
if (k == iven[n]) {
srcount = 0;
show3(n);
}
lprcat("\n\n");
} else
lprc('\n');
}
j = SCORESIZE;
}
}
return (count);
}
static char esb[] = "The scoreboard is empty.\n";
void
showscores(void)
{
int i, j;
lflush();
lcreat(NULL);
if (readboard() < 0)
return;
i = winshou();
j = shou(0);
if (i + j == 0)
lprcat(esb);
else
lprc('\n');
lflush();
}
void
showallscores(void)
{
int i, j;
lflush();
lcreat(NULL);
if (readboard() < 0)
return;
c[WEAR] = c[WIELD] = c[SHIELD] = -1;
for (i = 0; i < MAXPOTION; i++)
potionname[i] = potionhide[i];
for (i = 0; i < MAXSCROLL; i++)
scrollname[i] = scrollhide[i];
i = winshou();
j = shou(1);
if (i + j == 0)
lprcat(esb);
else
lprc('\n');
lflush();
}
static int
sortboard(void)
{
int i, j = 0, pos;
long jdat;
for (i = 0; i < SCORESIZE; i++)
sco[i].order = winr[i].order = -1;
pos = 0;
while (pos < SCORESIZE) {
jdat = 0;
for (i = 0; i < SCORESIZE; i++)
if ((sco[i].order < 0) && (sco[i].score >= jdat)) {
j = i;
jdat = sco[i].score;
}
sco[j].order = pos++;
}
pos = 0;
while (pos < SCORESIZE) {
jdat = 0;
for (i = 0; i < SCORESIZE; i++)
if ((winr[i].order < 0) && (winr[i].score >= jdat)) {
j = i;
jdat = winr[i].score;
}
winr[j].order = pos++;
}
return (1);
}
static void
newscore(long score, char *whoo, int whyded, int winner)
{
int i;
long taxes;
if (readboard() < 0)
return;
if (cheat)
winner = 0;
if (winner) {
for (i = 0; i < SCORESIZE; i++)
if (sco[i].suid == userid)
sco[i].score = 0;
taxes = score * TAXRATE;
score += 100000 * c[HARDGAME];
for (i = 0; i < SCORESIZE; i++)
if (winr[i].suid == userid) {
new1sub(score, i, whoo, taxes);
return;
}
for (i = 0; i < SCORESIZE; i++)
if (winr[i].order == SCORESIZE - 1) {
new1sub(score, i, whoo, taxes);
return;
}
} else if (!cheat) {
for (i = 0; i < SCORESIZE; i++)
if (sco[i].suid == userid) {
new2sub(score, i, whoo, whyded);
return;
}
for (i = 0; i < SCORESIZE; i++)
if (sco[i].order == SCORESIZE - 1) {
new2sub(score, i, whoo, whyded);
return;
}
}
}
static void
new1sub(long score, int i, char *whoo, long taxes)
{
struct wscofmt *p;
p = &winr[i];
p->taxes += taxes;
if ((score >= p->score) || (c[HARDGAME] > p->hardlev)) {
strcpy(p->who, whoo);
p->score = score;
p->hardlev = c[HARDGAME];
p->suid = userid;
p->timeused = gtime / 100;
}
}
static void
new2sub(long score, int i, char *whoo, int whyded)
{
int j;
struct scofmt *p;
p = &sco[i];
if ((score >= p->score) || (c[HARDGAME] > p->hardlev)) {
strcpy(p->who, whoo);
p->score = score;
p->what = whyded;
p->hardlev = c[HARDGAME];
p->suid = userid;
p->level = level;
for (j = 0; j < 26; j++) {
p->sciv[j][0] = iven[j];
p->sciv[j][1] = ivenarg[j];
}
}
}
static int scorerror;
void
died(int x)
{
int f, win;
char ch;
const char *mod;
time_t zzz;
#ifdef EXTRA
long i;
struct tms cputime;
#endif
if (c[LIFEPROT] > 0) {
switch ((x > 0) ? x : -x) {
case 256:
case 257:
case 262:
case 263:
case 265:
case 266:
case 267:
case 268:
case 269:
case 271:
case 282:
case 284:
case 285:
case 300:
goto invalid;
}
--c[LIFEPROT];
c[HP] = 1;
--c[CONSTITUTION];
cursors();
lprcat("\nYou feel wiiieeeeerrrrrd all over! ");
beep();
lflush();
sleep(4);
return;
}
invalid:
clearvt100();
lflush();
f = 0;
if (ckpflag)
unlink(ckpfile);
if (x < 0) {
f++;
x = -x;
}
if ((x == 300) || (x == 257))
exit(0);
if (x == 263)
win = 1;
else
win = 0;
c[GOLD] += c[BANKACCOUNT];
c[BANKACCOUNT] = 0;
newscore(c[GOLD], logname, x, win);
diedsub(x);
lflush();
set_score_output();
if ((wizard == 0) && (c[GOLD] > 0)) {
#ifndef NOLOG
if (lappend(logfile) < 0) {
if (lcreat(logfile) < 0) {
lcreat(NULL);
lprcat("\nCan't open record file: I can't post your score.\n");
sncbr();
resetscroll();
lflush();
exit(1);
}
chmod(logfile, 0660);
}
strcpy(logg.who, loginname);
logg.score = c[GOLD];
logg.diff = c[HARDGAME];
if (x < 256) {
ch = *monster[x].name;
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
mod = "an";
else
mod = "a";
sprintf(logg.what, "killed by %s %s", mod, monster[x].name);
} else
sprintf(logg.what, "%s", whydead[x - 256]);
logg.cavelev = level;
time(&zzz);
logg.diedtime = zzz;
#ifdef EXTRA
times(&cputime);
logg.cputime = i = (cputime.tms_utime + cputime.tms_stime) / 60 + c[CPUTIME];
logg.lev = c[LEVEL];
logg.ac = c[AC];
logg.hpmax = c[HPMAX];
logg.hp = c[HP];
logg.elapsedtime = (zzz - initialtime + 59) / 60;
logg.usage = (10000 * i) / (zzz - initialtime);
logg.bytin = c[BYTESIN];
logg.bytout = c[BYTESOUT];
logg.moves = c[MOVESMADE];
logg.spused = c[SPELLSCAST];
logg.killed = c[MONSTKILLED];
#endif
lwrite((char *)&logg, sizeof(struct log_fmt));
lwclose();
#endif
if (x != 257) {
if (sortboard())
scorerror = writeboard();
}
}
if ((x == 256) || (x == 257) || (f != 0))
exit(0);
if (scorerror == 0)
showscores();
if (x == 263)
mailbill();
exit(0);
}
static void
diedsub(int x)
{
char ch;
const char *mod;
lprintf("Score: %d, Diff: %d, %s ", (long)c[GOLD], (long)c[HARDGAME], logname);
if (x < 256) {
ch = *monster[x].name;
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
mod = "an";
else
mod = "a";
lprintf("killed by %s %s", mod, monster[x].name);
} else
lprintf("%s", whydead[x - 256]);
if (x != 263)
lprintf(" on %s\n", levelname[(int)level]);
else
lprc('\n');
}
void
diedlog(void)
{
int n;
char *p;
struct stat stbuf;
lcreat(NULL);
if (lopen(logfile) < 0) {
lprintf("Can't locate log file <%s>\n", logfile);
return;
}
if (fstat(io_infd, &stbuf) < 0) {
lprintf("Can't stat log file <%s>\n", logfile);
return;
}
for (n = stbuf.st_size / sizeof(struct log_fmt); n > 0; --n) {
lrfill((char *)&logg, sizeof(struct log_fmt));
p = ctime(&logg.diedtime);
p[16] = '\n';
p[17] = 0;
lprintf("Score: %d, Diff: %d, %s %s on %d at %s", (long)(logg.score), (long)(logg.diff), logg.who, logg.what, (long)(logg.cavelev), p + 4);
#ifdef EXTRA
if (logg.moves <= 0)
logg.moves = 1;
lprintf(" Experience Level: %d, AC: %d, HP: %d/%d, Elapsed Time: %d minutes\n", (long)(logg.lev), (long)(logg.ac), (long)(logg.hp), (long)(logg.hpmax), (long)(logg.elapsedtime));
lprintf(" CPU time used: %d seconds, Machine usage: %d.%02d%%\n", (long)(logg.cputime), (long)(logg.usage / 100), (long)(logg.usage % 100));
lprintf(" BYTES in: %d, out: %d, moves: %d, deaths: %d, spells cast: %d\n", (long)(logg.bytin), (long)(logg.bytout), (long)(logg.moves), (long)(logg.killed), (long)(logg.spused));
lprintf(" out bytes per move: %d, time per move: %d ms\n", (long)(logg.bytout / logg.moves), (long)((logg.cputime * 1000) / logg.moves));
#endif
}
lflush();
lrclose();
return;
}
#ifndef UIDSCORE
static int havepid= -1;
int
getplid(char *nam)
{
int fd7, high = 999, no;
char *p, *p2;
char name[80];
if (havepid != -1)
return (havepid);
lflush();
sprintf(name, "%s\n", nam);
if (lopen(playerids) < 0) {
if ((fd7 = creat(playerids, 0666)) < 0)
return (-1);
close(fd7);
goto addone;
}
for (;;) {
p = lgetl();
if (p == NULL)
break;
no = atoi(p);
p2 = lgetl();
if (p2 == NULL)
break;
if (no > high)
high = no;
if (strcmp(p2, name) == 0) {
return (no);
}
}
lrclose();
addone:
if (lappend(playerids) < 0)
return (-1);
lprintf("%d\n%s", (long)++high, name);
lwclose();
lcreat(NULL);
return (high);
}
#endif