de82ffd7cb
scores file, the append-only log of all games) as int32_t instead of time_t. Log files from before the 64-bit time_t change can now be read again; however, log files from the last year of -current are hosed. All none of you who play larn, take note...
868 lines
23 KiB
C
868 lines
23 KiB
C
/* $NetBSD: scores.c,v 1.20 2010/04/24 00:56:14 dholland Exp $ */
|
|
|
|
/*
|
|
* scores.c Larn is copyrighted 1986 by Noah Morgan.
|
|
*
|
|
* Functions in this file are:
|
|
*
|
|
* readboard() Function to read in the scoreboard into a static buffer
|
|
* writeboard() Function to write the scoreboard from readboard()'s buffer
|
|
* makeboard() Function to create a new scoreboard (wipe out old one)
|
|
* hashewon() Function to return 1 if player has won a game before, else 0
|
|
* long paytaxes(x) Function to pay taxes if any are due winshou()
|
|
* ubroutine to print out the winning scoreboard shou(x)
|
|
* ubroutine to print out the non-winners scoreboard showscores()
|
|
* unction to show the scoreboard on the terminal showallscores()
|
|
* Function to show scores and the iven lists that go with them sortboard()
|
|
* unction to sort the scoreboard newscore(score, whoo, whyded, winner)
|
|
* Function to add entry to scoreboard new1sub(score,i,whoo,taxes)
|
|
* Subroutine to put player into a new2sub(score,i,whoo,whyded)
|
|
* Subroutine to put player into a died(x) Subroutine to record who
|
|
* played larn, and what the score was diedsub(x) Subroutine to print out a
|
|
* line showing player when he is killed diedlog() Subroutine to read a
|
|
* log file and print it out in ascii format getplid(name)
|
|
* on to get players id # from id file
|
|
*
|
|
*/
|
|
#include <sys/cdefs.h>
|
|
#ifndef lint
|
|
__RCSID("$NetBSD: scores.c,v 1.20 2010/04/24 00:56:14 dholland Exp $");
|
|
#endif /* not lint */
|
|
#include <sys/types.h>
|
|
#include <sys/times.h>
|
|
#include <sys/stat.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include "header.h"
|
|
#include "extern.h"
|
|
|
|
struct scofmt { /* This is the structure for the scoreboard */
|
|
long score; /* the score of the player */
|
|
long suid; /* the user id number of the player */
|
|
short what; /* the number of the monster that killed
|
|
* player */
|
|
short level; /* the level player was on when he died */
|
|
short hardlev;/* the level of difficulty player played at */
|
|
short order; /* the relative ordering place of this entry */
|
|
char who[40];/* the name of the character */
|
|
char sciv[26][2]; /* this is the inventory list of the
|
|
* character */
|
|
};
|
|
struct wscofmt { /* This is the structure for the winning
|
|
* scoreboard */
|
|
long score; /* the score of the player */
|
|
long timeused; /* the time used in mobuls to win the
|
|
* game */
|
|
long taxes; /* taxes he owes to LRS */
|
|
long suid; /* the user id number of the player */
|
|
short hardlev;/* the level of difficulty player played at */
|
|
short order; /* the relative ordering place of this entry */
|
|
char who[40];/* the name of the character */
|
|
};
|
|
|
|
struct log_fmt { /* 102 bytes struct for the log file */
|
|
long score; /* the players score */
|
|
int32_t diedtime; /* time when game was over */
|
|
short cavelev;/* level in caves */
|
|
short diff; /* difficulty player played at */
|
|
#ifdef EXTRA
|
|
long elapsedtime; /* real time of game in seconds */
|
|
long bytout; /* bytes input and output */
|
|
long bytin;
|
|
long moves; /* number of moves made by player */
|
|
short ac; /* armor class of player */
|
|
short hp, hpmax; /* players hitpoints */
|
|
short cputime;/* CPU time needed in seconds */
|
|
short killed, spused; /* monsters killed and spells cast */
|
|
short usage; /* usage of the CPU in % */
|
|
short lev; /* player level */
|
|
#endif
|
|
char who[12];/* player name */
|
|
char what[46]; /* what happened to player */
|
|
};
|
|
|
|
static struct scofmt sco[SCORESIZE]; /* the structure for the scoreboard */
|
|
static struct wscofmt winr[SCORESIZE]; /* struct for the winning scoreboard */
|
|
static struct log_fmt logg; /* structure for the log file */
|
|
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",
|
|
/* 26 */ "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);
|
|
|
|
/*
|
|
* readboard() Function to read in the scoreboard into a static buffer
|
|
*
|
|
* returns -1 if unable to read in the scoreboard, returns 0 if all is OK
|
|
*/
|
|
static int
|
|
readboard()
|
|
{
|
|
int i;
|
|
|
|
if (gid != egid)
|
|
setegid(egid);
|
|
i = lopen(scorefile);
|
|
if (gid != egid)
|
|
setegid(gid);
|
|
if (i < 0) {
|
|
lprcat("Can't read scoreboard\n");
|
|
lflush();
|
|
return (-1);
|
|
}
|
|
lrfill((char *) sco, sizeof(sco));
|
|
lrfill((char *) winr, sizeof(winr));
|
|
lrclose();
|
|
lcreat((char *) 0);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* writeboard() Function to write the scoreboard from readboard()'s buffer
|
|
*
|
|
* returns -1 if unable to write the scoreboard, returns 0 if all is OK
|
|
*/
|
|
static int
|
|
writeboard()
|
|
{
|
|
int i;
|
|
|
|
set_score_output();
|
|
if (gid != egid)
|
|
setegid(egid);
|
|
i = lcreat(scorefile);
|
|
if (gid != egid)
|
|
setegid(gid);
|
|
if (i < 0) {
|
|
lprcat("Can't write scoreboard\n");
|
|
lflush();
|
|
return (-1);
|
|
}
|
|
lwrite((char *) sco, sizeof(sco));
|
|
lwrite((char *) winr, sizeof(winr));
|
|
lwclose();
|
|
lcreat((char *) 0);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* makeboard() Function to create a new scoreboard (wipe out old one)
|
|
*
|
|
* returns -1 if unable to write the scoreboard, returns 0 if all is OK
|
|
*/
|
|
int
|
|
makeboard()
|
|
{
|
|
int i;
|
|
set_score_output();
|
|
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);
|
|
if (gid != egid)
|
|
setegid(egid);
|
|
chmod(scorefile, 0660);
|
|
if (gid != egid)
|
|
setegid(gid);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* hashewon() Function to return 1 if player has won a game before, else 0
|
|
*
|
|
* This function also sets c[HARDGAME] to appropriate value -- 0 if not a
|
|
* winner, otherwise the next level of difficulty listed in the winners
|
|
* scoreboard. This function also sets outstanding_taxes to the value in
|
|
* the winners scoreboard.
|
|
*/
|
|
int
|
|
hashewon()
|
|
{
|
|
int i;
|
|
c[HARDGAME] = 0;
|
|
if (readboard() < 0)
|
|
return (0); /* can't find scoreboard */
|
|
for (i = 0; i < SCORESIZE; i++) /* search through winners scoreboard */
|
|
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(x) Function to pay taxes if any are due
|
|
*
|
|
* Enter with the amount (in gp) to pay on the taxes.
|
|
* Returns amount actually paid.
|
|
*/
|
|
long
|
|
paytaxes(x)
|
|
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) /* look for players winning
|
|
* entry */
|
|
if (winr[i].score > 0) { /* search for a winning
|
|
* entry for the player */
|
|
amt = winr[i].taxes;
|
|
if (x < amt)
|
|
amt = x; /* don't overpay taxes
|
|
* (Ughhhhh) */
|
|
winr[i].taxes -= amt;
|
|
outstanding_taxes -= amt;
|
|
set_score_output();
|
|
if (writeboard() < 0)
|
|
return (0);
|
|
return (amt);
|
|
}
|
|
return (0L); /* couldn't find user on winning scoreboard */
|
|
}
|
|
|
|
/*
|
|
* winshou() Subroutine to print out the winning scoreboard
|
|
*
|
|
* Returns the number of players on scoreboard that were shown
|
|
*/
|
|
static int
|
|
winshou()
|
|
{
|
|
struct wscofmt *p;
|
|
int i, j, count;
|
|
for (count = j = i = 0; i < SCORESIZE; i++) /* is there anyone on
|
|
* the scoreboard? */
|
|
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++) /* this loop is needed to
|
|
* print out the */
|
|
for (j = 0; j < SCORESIZE; j++) { /* winners in order */
|
|
p = &winr[j]; /* pointer to the scoreboard
|
|
* entry */
|
|
if (p->order == i) {
|
|
if (p->score) {
|
|
count++;
|
|
lprintf("%10ld %2ld %5ld Mobuls %s \n",
|
|
(long) p->score, (long) p->hardlev, (long) p->timeused, p->who);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return (count); /* return number of people on scoreboard */
|
|
}
|
|
|
|
/*
|
|
* shou(x) Subroutine to print out the non-winners scoreboard
|
|
* int x;
|
|
*
|
|
* Enter with 0 to list the scores, enter with 1 to list inventories too
|
|
* Returns the number of players on scoreboard that were shown
|
|
*/
|
|
static int
|
|
shou(x)
|
|
int x;
|
|
{
|
|
int i, j, n, k;
|
|
int count;
|
|
for (count = j = i = 0; i < SCORESIZE; i++) /* is the scoreboard
|
|
* empty? */
|
|
if (sco[i].score != 0) {
|
|
j++;
|
|
break;
|
|
}
|
|
if (j) {
|
|
lprcat("\n Score Difficulty Larn Visitor Log\n");
|
|
for (i = 0; i < SCORESIZE; i++) /* be sure to print them out
|
|
* in order */
|
|
for (j = 0; j < SCORESIZE; j++)
|
|
if (sco[j].order == i) {
|
|
if (sco[j].score) {
|
|
count++;
|
|
lprintf("%10ld %2ld %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); /* return the number of players just shown */
|
|
}
|
|
|
|
/*
|
|
* showscores() Function to show the scoreboard on the terminal
|
|
*
|
|
* Returns nothing of value
|
|
*/
|
|
static char esb[] = "The scoreboard is empty.\n";
|
|
void
|
|
showscores()
|
|
{
|
|
int i, j;
|
|
lflush();
|
|
lcreat((char *) 0);
|
|
if (readboard() < 0)
|
|
return;
|
|
i = winshou();
|
|
j = shou(0);
|
|
if (i + j == 0)
|
|
lprcat(esb);
|
|
else
|
|
lprc('\n');
|
|
lflush();
|
|
}
|
|
|
|
/*
|
|
* showallscores() Function to show scores and the iven lists that go with them
|
|
*
|
|
* Returns nothing of value
|
|
*/
|
|
void
|
|
showallscores()
|
|
{
|
|
int i, j;
|
|
lflush();
|
|
lcreat((char *) 0);
|
|
if (readboard() < 0)
|
|
return;
|
|
c[WEAR] = c[WIELD] = c[SHIELD] = -1; /* not wielding or wearing
|
|
* anything */
|
|
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();
|
|
}
|
|
|
|
/*
|
|
* sortboard() Function to sort the scoreboard
|
|
*
|
|
* Returns 0 if no sorting done, else returns 1
|
|
*/
|
|
static int
|
|
sortboard()
|
|
{
|
|
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);
|
|
}
|
|
|
|
/*
|
|
* newscore(score, whoo, whyded, winner) Function to add entry to scoreboard
|
|
* int score, winner, whyded;
|
|
* char *whoo;
|
|
*
|
|
* Enter with the total score in gp in score, players name in whoo,
|
|
* died() reason # in whyded, and TRUE/FALSE in winner if a winner
|
|
* ex. newscore(1000, "player 1", 32, 0);
|
|
*/
|
|
static void
|
|
newscore(score, whoo, whyded, winner)
|
|
long score;
|
|
int winner, whyded;
|
|
char *whoo;
|
|
{
|
|
int i;
|
|
long taxes;
|
|
if (readboard() < 0)
|
|
return; /* do the scoreboard */
|
|
/* if a winner then delete all non-winning scores */
|
|
if (cheat)
|
|
winner = 0; /* if he cheated, don't let him win */
|
|
if (winner) {
|
|
for (i = 0; i < SCORESIZE; i++)
|
|
if (sco[i].suid == userid)
|
|
sco[i].score = 0;
|
|
taxes = score * TAXRATE;
|
|
score += 100000 * c[HARDGAME]; /* bonus for winning */
|
|
/*
|
|
* if he has a slot on the winning scoreboard update it if
|
|
* greater score
|
|
*/
|
|
for (i = 0; i < SCORESIZE; i++)
|
|
if (winr[i].suid == userid) {
|
|
new1sub(score, i, whoo, taxes);
|
|
return;
|
|
}
|
|
/*
|
|
* he had no entry. look for last entry and see if he has a
|
|
* greater score
|
|
*/
|
|
for (i = 0; i < SCORESIZE; i++)
|
|
if (winr[i].order == SCORESIZE - 1) {
|
|
new1sub(score, i, whoo, taxes);
|
|
return;
|
|
}
|
|
} else if (!cheat) { /* for not winning scoreboard */
|
|
/*
|
|
* if he has a slot on the scoreboard update it if greater
|
|
* score
|
|
*/
|
|
for (i = 0; i < SCORESIZE; i++)
|
|
if (sco[i].suid == userid) {
|
|
new2sub(score, i, whoo, whyded);
|
|
return;
|
|
}
|
|
/*
|
|
* he had no entry. look for last entry and see if he has a
|
|
* greater score
|
|
*/
|
|
for (i = 0; i < SCORESIZE; i++)
|
|
if (sco[i].order == SCORESIZE - 1) {
|
|
new2sub(score, i, whoo, whyded);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* new1sub(score,i,whoo,taxes) Subroutine to put player into a
|
|
* int score,i,whyded,taxes; winning scoreboard entry if his score
|
|
* char *whoo; is high enough
|
|
*
|
|
* Enter with the total score in gp in score, players name in whoo,
|
|
* died() reason # in whyded, and TRUE/FALSE in winner if a winner
|
|
* slot in scoreboard in i, and the tax bill in taxes.
|
|
* Returns nothing of value
|
|
*/
|
|
static void
|
|
new1sub(score, i, whoo, taxes)
|
|
long score, taxes;
|
|
int i;
|
|
char *whoo;
|
|
{
|
|
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 = gltime / 100;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* new2sub(score,i,whoo,whyded) Subroutine to put player into a
|
|
* int score,i,whyded,taxes; non-winning scoreboard entry if his
|
|
* char *whoo; score is high enough
|
|
*
|
|
* Enter with the total score in gp in score, players name in whoo,
|
|
* died() reason # in whyded, and slot in scoreboard in i.
|
|
* Returns nothing of value
|
|
*/
|
|
static void
|
|
new2sub(score, i, whoo, whyded)
|
|
long score;
|
|
int i, whyded;
|
|
char *whoo;
|
|
{
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* died(x) Subroutine to record who played larn, and what the score was
|
|
* int x;
|
|
*
|
|
* if x < 0 then don't show scores
|
|
* died() never returns! (unless c[LIFEPROT] and a reincarnatable death!)
|
|
*
|
|
* < 256 killed by the monster number
|
|
* 256 quit
|
|
* 257 suspended
|
|
* 258 self - annihilated
|
|
* 259 shot by an arrow
|
|
* 260 hit by a dart
|
|
* 261 fell into a pit
|
|
* 262 fell into a bottomless pit
|
|
* 263 a winner
|
|
* 264 trapped in solid rock
|
|
* 265 killed by a missing save file
|
|
* 266 killed by an old save file
|
|
* 267 caught by the greedy cheater checker trap
|
|
* 268 killed by a protected save file
|
|
* 269 killed his family and killed himself
|
|
* 270 erased by a wayward finger
|
|
* 271 fell through a bottomless trap door
|
|
* 272 fell through a trap door
|
|
* 273 drank some poisonous water
|
|
* 274 fried by an electric shock
|
|
* 275 slipped on a volcano shaft
|
|
* 276 killed by a stupid act of frustration
|
|
* 277 attacked by a revolting demon
|
|
* 278 hit by his own magic
|
|
* 279 demolished by an unseen attacker
|
|
* 280 fell into the dreadful sleep
|
|
* 281 killed by an exploding chest
|
|
* 282 killed by a missing maze data file
|
|
* 283 killed by a sphere of annihilation
|
|
* 284 died a post mortem death
|
|
* 285 malloc() failure
|
|
* 300 quick quit -- don't put on scoreboard
|
|
*/
|
|
|
|
static int scorerror;
|
|
void
|
|
died(x)
|
|
int x;
|
|
{
|
|
int f, win;
|
|
char ch;
|
|
const char *mod;
|
|
time_t zzz;
|
|
if (c[LIFEPROT] > 0) { /* if life protection */
|
|
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; /* can't be saved */
|
|
};
|
|
--c[LIFEPROT];
|
|
c[HP] = 1;
|
|
--c[CONSTITUTION];
|
|
cursors();
|
|
lprcat("\nYou feel wiiieeeeerrrrrd all over! ");
|
|
beep();
|
|
lflush();
|
|
sleep(4);
|
|
return; /* only case where died() returns */
|
|
}
|
|
invalid:
|
|
clearvt100();
|
|
lflush();
|
|
f = 0;
|
|
if (ckpflag)
|
|
unlink(ckpfile);/* remove checkpoint file if used */
|
|
if (x < 0) {
|
|
f++;
|
|
x = -x;
|
|
} /* if we are not to display the scores */
|
|
if ((x == 300) || (x == 257))
|
|
exit(0); /* for quick exit or saved game */
|
|
if (x == 263)
|
|
win = 1;
|
|
else
|
|
win = 0;
|
|
c[GOLD] += c[BANKACCOUNT];
|
|
c[BANKACCOUNT] = 0;
|
|
/* now enter the player at the end of the scoreboard */
|
|
newscore(c[GOLD], logname, x, win);
|
|
diedsub(x); /* print out the score line */
|
|
lflush();
|
|
|
|
set_score_output();
|
|
if ((wizard == 0) && (c[GOLD] > 0)) { /* wizards can't score */
|
|
#ifndef NOLOG
|
|
if (gid != egid)
|
|
setegid(egid);
|
|
if (lappend(logfile) < 0) { /* append to file */
|
|
if (lcreat(logfile) < 0) { /* and can't create new
|
|
* log file */
|
|
lcreat((char *) 0);
|
|
lprcat("\nCan't open record file: I can't post your score.\n");
|
|
sncbr();
|
|
resetscroll();
|
|
lflush();
|
|
exit(0);
|
|
}
|
|
if (gid != egid)
|
|
setegid(egid);
|
|
chmod(logfile, 0660);
|
|
if (gid != egid)
|
|
setegid(gid);
|
|
}
|
|
if (gid != egid)
|
|
setegid(gid);
|
|
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";
|
|
snprintf(logg.what, sizeof(logg.what),
|
|
"killed by %s %s", mod, monster[x].name);
|
|
} else
|
|
snprintf(logg.what, sizeof(logg.what),
|
|
"%s", whydead[x - 256]);
|
|
logg.cavelev = level;
|
|
time(&zzz); /* get CPU time -- write out score info */
|
|
logg.diedtime = zzz;
|
|
#ifdef EXTRA
|
|
times(&cputime);/* get CPU time -- write out score info */
|
|
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 /* NOLOG */
|
|
|
|
/*
|
|
* now for the scoreboard maintenance -- not for a suspended
|
|
* game
|
|
*/
|
|
if (x != 257) {
|
|
if (sortboard()) {
|
|
set_score_output();
|
|
scorerror = writeboard();
|
|
}
|
|
}
|
|
}
|
|
if ((x == 256) || (x == 257) || (f != 0))
|
|
exit(0);
|
|
if (scorerror == 0)
|
|
showscores(); /* if we updated the scoreboard */
|
|
if (x == 263)
|
|
mailbill();
|
|
exit(0);
|
|
}
|
|
|
|
/*
|
|
* diedsub(x) Subroutine to print out the line showing the player when he is killed
|
|
* int x;
|
|
*/
|
|
static void
|
|
diedsub(int x)
|
|
{
|
|
char ch;
|
|
const char *mod;
|
|
|
|
lprintf("Score: %ld, Diff: %ld, %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[level]);
|
|
else
|
|
lprc('\n');
|
|
}
|
|
|
|
/*
|
|
* diedlog() Subroutine to read a log file and print it out in ascii format
|
|
*/
|
|
void
|
|
diedlog()
|
|
{
|
|
int n;
|
|
char *p;
|
|
static char q[] = "?";
|
|
struct stat stbuf;
|
|
time_t t;
|
|
|
|
lcreat((char *) 0);
|
|
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));
|
|
t = logg.diedtime;
|
|
if ((p = ctime(&t)) == NULL)
|
|
p = q;
|
|
else {
|
|
p[16] = '\n';
|
|
p[17] = 0;
|
|
}
|
|
lprintf("Score: %ld, Diff: %ld, %s %s on %ld 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: %ld, AC: %ld, HP: %ld/%ld, Elapsed Time: %ld minutes\n", (long) (logg.lev), (long) (logg.ac), (long) (logg.hp), (long) (logg.hpmax), (long) (logg.elapsedtime));
|
|
lprintf(" CPU time used: %ld seconds, Machine usage: %ld.%02ld%%\n", (long) (logg.cputime), (long) (logg.usage / 100), (long) (logg.usage % 100));
|
|
lprintf(" BYTES in: %ld, out: %ld, moves: %ld, deaths: %ld, spells cast: %ld\n", (long) (logg.bytin), (long) (logg.bytout), (long) (logg.moves), (long) (logg.killed), (long) (logg.spused));
|
|
lprintf(" out bytes per move: %ld, time per move: %ld ms\n", (long) (logg.bytout / logg.moves), (long) ((logg.cputime * 1000) / logg.moves));
|
|
#endif
|
|
}
|
|
lflush();
|
|
lrclose();
|
|
return;
|
|
}
|
|
|
|
#ifndef UIDSCORE
|
|
/*
|
|
* getplid(name) Function to get players id # from id file
|
|
*
|
|
* Enter with the name of the players character in name.
|
|
* Returns the id # of the players character, or -1 if failure.
|
|
* This routine will try to find the name in the id file, if its not there,
|
|
* it will try to make a new entry in the file. Only returns -1 if can't
|
|
* find him in the file, and can't make a new entry in the file.
|
|
* Format of playerids file:
|
|
* Id # in ascii \n character name \n
|
|
*/
|
|
static int havepid = -1; /* playerid # if previously done */
|
|
int
|
|
getplid(nam)
|
|
char *nam;
|
|
{
|
|
int fd7, high = 999, no;
|
|
char *p, *p2;
|
|
char name[80];
|
|
if (havepid != -1)
|
|
return (havepid); /* already did it */
|
|
lflush(); /* flush any pending I/O */
|
|
snprintf(name, sizeof(name), "%s\n", nam);/* append a \n to name */
|
|
if (lopen(playerids) < 0) { /* no file, make it */
|
|
if ((fd7 = creat(playerids, 0664)) < 0)
|
|
return (-1); /* can't make it */
|
|
close(fd7);
|
|
goto addone; /* now append new playerid record to file */
|
|
}
|
|
for (;;) { /* now search for the name in the player id
|
|
* file */
|
|
p = lgetl();
|
|
if (p == NULL)
|
|
break; /* EOF? */
|
|
no = atoi(p); /* the id # */
|
|
p2 = lgetl();
|
|
if (p2 == NULL)
|
|
break; /* EOF? */
|
|
if (no > high)
|
|
high = no; /* accumulate highest id # */
|
|
if (strcmp(p2, name) == 0) { /* we found him */
|
|
return (no); /* his id number */
|
|
}
|
|
}
|
|
lrclose();
|
|
/* if we get here, we didn't find him in the file -- put him there */
|
|
addone:
|
|
if (lappend(playerids) < 0)
|
|
return (-1); /* can't open file for append */
|
|
lprintf("%ld\n%s", (long) ++high, name); /* new id # and name */
|
|
lwclose();
|
|
lcreat((char *) 0); /* re-open terminal channel */
|
|
return (high);
|
|
}
|
|
#endif /* UIDSCORE */
|