Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Reclist.c 2.2b

2 views
Skip to first unread message

Jukka S Lahtinen

unread,
Jun 12, 1994, 5:47:03 PM6/12/94
to
Some time ago I posted the C source for a little program to list
the record file. Since then I have made some little changes, some of
which were from the mail Boudewijn sent to me, and some are my own
improvements. I thought it is time to send the newest version of the
source again. It is written with Borland C, but I think it should
compile with almost any ANSI C compiler without (or with very little)
changes. Here you go:

-- cut here --

/* Show the Nethack RECORD file as with nethack -s
and calculate the average score

RECLIST [-ffilename] [-uplayername] [-character] [-nnumber] [-d]
*/

/* Jukka Lahtinen, wal...@mits.mdata.fi
08.93 - 06.94
*/

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

#define RECORD "record"
#define LOGFILE "logfile"

/* #define NHPLUS /* Recognize classes D and M of Stephen White's NhPlus */

/* if your compiler doesn't have the case-insensitive strnicmp and stricmp
functions, you can replace them with the standard functions with these
definitions and lose most of the case-insensitiveness..
#define strnicmp strncmp
#define stricmp strcmp
*/

char *ver="2.2b"; /* version number */

int main(int argc, char *argv[])
{
FILE *inp;

int i,
num=0,
pnum=0,
day=0;
long sum=0;

char chclass=0,
line[150];

char *name=NULL,
*filename=RECORD;

long chkline(char *line,char *name,char chclass, int *num, int day);
void help(char *prog,char *par);

/* Command line parameters */
for (i=1; i<argc; i++) {
if (argv[i][0]=='/')
argv[i][0]='-';
if ((argv[i][0]=='?') || (argv[i][1]=='?') ||
(!stricmp(argv[i]+1,"-help")))
help(argv[0],argv[i]);
else if (!(strnicmp(argv[i],"-f",2))) { /* filename */
if (strlen(argv[i])==2) {
i++;
filename=argv[i]; }
else
filename=argv[i]+2;
if (!stricmp(filename,"s"))
filename=NULL; /* stdio */
}
else if (!(stricmp(argv[i],"-l"))) /* logfile */
filename=LOGFILE;
else if (!(strnicmp(argv[i],"-u",2))) /* player name */
if (strlen(argv[i])==2) {
i++;
name=argv[i]; }
else
name=argv[i]+2;
else if (!(strnicmp(argv[i],"-n",2))) /* number */
if (strlen(argv[i])==2) {
i++;
pnum=atoi(argv[i]); }
else
pnum=atoi(argv[i]+2);
else if (argv[i][1]=='d') /* display the dates */
day=1;
else
if (argv[i][0]=='-') {
switch (toupper(argv[i][1])) { /* character class */
case 'A': case 'B': case 'C': case 'E': case 'H':
case 'K': case 'P': case 'R': case 'S': case 'T':
case 'V': case 'W':
#ifdef NHPLUS
case 'D': case 'M':
#endif
chclass=toupper(argv[i][1]);
break;
default:
help(argv[0],argv[i]);
} } }

/* Command line ok, let's process the file */

if (!filename)
inp=stdin; /* I'm not sure if this works on all compilers.. */
else
if (!(inp=fopen(filename,"r"))) {
printf ("File %s not found\n",filename);
exit (2);
}

printf("%-71s%s"," No Points Name","Hp [max]\n");
fgets(line,sizeof(line),inp);

/* HERE is the main loop */
while ((!(feof(inp))) && ((!pnum) || (num<pnum))) {
sum += chkline(line,name,chclass,&num,day);
fgets(line,sizeof(line),inp);
}

if (num)
printf("\n%d scores. Average score %ld",num,sum/num);
else
printf("\nNo games found.");
if (inp!=stdin)
fclose (inp);
return 0;
}


/* Interpret one line of the file */

long chkline (char *line,char *parnimi,char parchclass,int *num,int day)
{
int pos,
pos2,
dtype,
dlev,
maxlev,
hp,
maxhp;
static int nro=0;
long score,
pvm;
char chclass,
sex,
death[70]={""},
ascend=0;
char *reason;

static char *dungeon[]={"The Dungeons of Doom",/* 0 */
"Gehennom", /* 1 */
"The Gnomish Mines", /* 2 */
"The Quest", /* 3 */
"Fort Ludios", /* 4 */
"Vlad's Tower", /* 5 */
"The Endgame"}; /* 6 */

static char *eglev[]={"the Earth Plane", /* 0 */
"the Air Plane", /* -1*/
"the Fire Plane", /* -2*/
"the Water Plane", /* -3*/
"the Astral Plane"}; /* -4*/

nro++;

/* The date uses positions 0-5 (YYMMDD), uid starts in 7.
After that, the dungeon branch of death and dlevel, maxdlevel, hp, maxhp,
score, character class&sex, name and reason for game ending
*/
sscanf (line,"%ld %*d %d %d %d %d %d %ld %c%c",
&pvm,&dtype,&dlev,&maxlev,&hp,&maxhp,&score,&chclass,&sex);

if (chclass<'A')
return (0); /* The VMS version may have end line with class < A */
if ((parchclass) && (parchclass!=chclass))
return (0);

/* Find the player name. I don't use sscanf for it because it wouldn't
stop in the comma after the name. Besides, I don't know if the name
in the file can contain spaces on some operating system.. Anyway,
the name is after the character class and sex, which are the first
alphabets on the line and can never be before position 20.
*/
for (pos=20;!isalpha(line[pos]);pos++); /* pos points to class now */
if (pos>strlen(line)) /* Never is in a valid file. But we don't want */
return (0); /* to crash just if the file is invalid.. */
pos += 3;
for (pos2=0;(line[pos]!=',')&&(pos2<sizeof(death));pos2++,pos++)
death[pos2]=line[pos];
death[pos2]=0;

if ((parnimi) && (strcmp(parnimi,death)))
return (0);

printf("%3d%11ld ",nro,score);
reason= &line[pos+1];
strcat(death,"-"); /* The name is already there in the beginnin of string */
pos=strlen(death);
death[pos]=chclass; death[pos+1]=0;
if (!(strncmp(reason,"poisoned",8)))
strcat(death," was poisoned");
else if (!(strncmp(reason,"petrified",9)))
strcat(death," turned to stone");
else if (!(strncmp(reason,"starvation",10)))
strcat(death," starved to death");
else if (!(strncmp(reason,"quit",4)))
strcat(death," quit");
else if (!(strncmp(reason,"crushed",7)))
strcat(death," was crushed to death");
else if (!(strncmp(reason,"choked",6)))
if (sex=='M')
strcat(death," choked on his food");
else
strcat(death," choked on her food");
else if (!(strncmp(reason,"ascended",8))) {
if (sex=='F')
strcat(death," ascended to demigoddess-hood.");
else
strcat(death," ascended to demigod-hood.");
ascend=1;
}
else if (!(strncmp(reason,"escaped",7))) {
sprintf (death+strlen(death)," escaped the dungeon [max level %d].",
maxlev);
ascend=1; /* Not an ascension, but also listed in a special way. */
}
else
strcat(death," died");
if (!ascend) {
pos=strlen(death);
if (dtype==6) /* The endgame */
sprintf (death+pos," in %s on %s.",dungeon[dtype],eglev[-dlev]);
/* dlev is negative if you die in the endgame */
else {
sprintf (death+pos," in %s on level %d",dungeon[dtype],dlev);
if (maxlev!=dlev)
sprintf(death+strlen(death)," [max %d].",maxlev);
else strcat(death,".");
}
if (strlen(death)>55) { /* split the line before the death reason */
death[pos]=0;
if (day) {
printf ("%s\n %ld\t\t",death,pvm);
day=0;
}
else
printf("%s\n\t\t",death);
pos++;
pos2=0;
while (death[pos]) {
death[pos2]=death[pos];
pos++;
pos2++; }
death[pos2]=0;
}
if (strlen(death)==55)
death[54]=0;
}
printf("%-54s",death);

if (hp>0)
printf("%3d",hp);
else
printf(" -");
sprintf(death,"[%d]",maxhp);
printf("%6s\n",death);

if ((strncmp(reason,"quit",4)) && (strncmp(reason,"starvation",10))
&& (!ascend)) {
reason[0]=toupper(reason[0]);
reason[strlen(reason)-1]=0; /* remove the linefeed at the end */
if (day) {
printf(" %ld",pvm);
day=0;
}
printf("\t\t%s.\n",reason);
}
if (day)
printf (" %ld\n",pvm);
(*num)++;
return (score);
}

void help(char *prog, char *par)
{
printf ("RECLIST, version %s\n\n",ver);
printf("List Nethack 3.1 record file and calculate the average score.\n\n");
printf("Usage: %s [-f file /-fs /-l] [-u name]\n",prog);
printf("[-abcehkprstvw] [-n] [-d]\n\n");
printf("The options are:\n\n");
printf("\t-f filename to read the scores from the file 'filename'\n");
printf("\t-fs to read the scorelist from stdin\n");
printf("\t-u name to list only the scores of player 'name'\n");
#ifdef NHPLUS
printf("\t-abcDehkmprstvw to list only the scores for one character\n");
#else
printf("\t-abcehkprstvw to list only the scores for one character\n");
#endif
printf("\t-n number to list only given number of scores\n");
printf("\t-d to show also the dates\n");
printf("\nYou may specify any combination of these in any order.\n");
printf("The space after -f, -u or -n is optional.\n");
printf("The output may also be redirected with '>' or '|'.\n");
if (par)
printf ("\nUnknown parameter %s\n",par);
exit (1);
}

-- cut here --
--
+-------------------------------------------------------------------------+
! Jukka S Lahtinen ! jsla...@vipunen.hut.fi ! wal...@mits.mdata.fi !
+-------------------------------------------------------------------------+

0 new messages