diff --git a/deps/reclist.c b/deps/reclist.c deleted file mode 100644 index d461b62..0000000 --- a/deps/reclist.c +++ /dev/null @@ -1,929 +0,0 @@ -/* List the Nethack record file and the average score. - Nethack 3.4-3.6, 3.3, 3.2 and 3.1 RECORD file formats supported - Output: stdout - - RECLIST [-f filename] [-u playername] [-p profession] [-r race] - [-n number] [-ns score] [-np interval] [-d] - [-ds date since] [-du date until] - [-g version] - - Check out the comments in the #defines and #includes before compiling -*/ - -/* J. Lahtinen 8/1993 - 12/2015 internet: jslahtin@gmail.com - Some parts of this program are copied from the Nethack 3.3.0 sources, - the rest I wrote myself. - Tell me if you find any bugs.. including the program telling the death - reason differently from "nethack -s". - When reporting bugs, please include the line in your record file that - reclist doesn't treat properly (copy & paste is just fine). - - 2015-12-12 - confirmed compatibility to Nethack 3.6.0 - - removed the warning of "too" modern game version - 2015-02-21 confirmed the compatibility to the leaked Nethack 3.5.0 version - 2003-01-20 changed the parameters -ds and -du from long to char* to allow - comparisons of partial date (for example -ds 2003 to list games - finished after the beginning of year 2003) - 2002-03-29 v3.4.0 - 2001-04-07 increased the size of the line buffer to fit Lethe patch scores - 2000-09-06 removed the level number from escaping scores - 2000-08-21 removed the level number from ascensions - anything in curly braces shown even if the "death" string isn't - (for the move counter added with my moves patch) - 2000-08-12 v3.3.1 - 2000-07-30 added option -ns to show only scores above some limit - 2000-01-23 added option -a to select by alignment - 2000-01-02 v3.3 - updated to understand the file format of game version 3.3.0 - removed old compile options NHPLUS and ENDGAME - 980731 v3.2.2 - removed false append of "with the Amulet" on escaped games - 980108 options -ds and -du to delimit game ending dates - 971130 v3.2.1 - changed the endgame level names to those used by the game - version 3.2.2 - 970525 don't split lines between [] (the game version 3.2 itself doesn't). - give an error message from parameter -f without a filename.. - 961124 v3.2, fixed the endgame level indexes changed from game ver.3.1 - 960628 option -g to select scores of a certain game version - 960505 Both 3.1 and 3.2 game versions handled - 960421 v3.0: File format changed for game version 3.2 - 950524 don't print "in the endgame" when the exact end level is shown - I noticed the NhPlus class U missing from the helps, added it there.. - 950523 2.3 - fixed a difference between this and nethack -s in splitting the line - when the death string is 55 characters - made the more accurate endgame level names optional (#define ENDGAME) - 950521 alternative definition of getch for unix users - 950228 2.2c - "Escaped with the Amulet" added - 950117 a negative number in -npX stops display only at the end - -npX always stops at the end - 941117 option -npX pauses after about every X lines - 940601 -l option reads the logfile. - Option -help works like -? - 940517 added the missing "." in the ascensions - 940509 "Crushed" and "escaped" ends specified - 940406 Make the difference between demigod and demigoddess - 940322 2.2a - Endgame- levels specified - 940224 the parameter -d displays the date also with the scores on a single - display line - 940110 2.2 - the parameter -fs may be used to read stdin - 931203 2.1b - conio.h headers removed for better operating system compatibility - extra space on "quit" scores removed - uid longer than 1 character caused some errors in unix, fixed - -*/ - -#include -#include -#include -#include -#if defined(__MSDOS__)||defined(__OS2__) - #include -#else - #define getch() getc(stdin) - /* getch() reads one character without waiting for CR in MSDOS and OS/2 - and it's currently the only thing in conio.h I use */ -#endif - -/* The functions strnicmp and stricmp are not ANSI, according to the BorlandC - help files. If your compiler doesn't understand them, you can replace them - with the standard functions (and lose the case insensitivity..) with these - following defines (or use suitable case-insensitive functions that your - compiler understands): - - #define strnicmp strncmp - #define stricmp strcmp -*/ -/* NOTE: With unix you may prefer defining them as strncasecmp and strcasecmp - as below.. -*/ - -#if defined(__unix__) - #define RECORD "/usr/games/lib/nethackdir/record" - #define LOGFILE "/usr/games/lib/nethackdir/logfile" - #ifndef stricmp - #define strnicmp strncasecmp - #define stricmp strcasecmp - #endif -#else - #define RECORD "record" - #define LOGFILE "logfile" -#endif - -/* Some defines taken from game sources (src/topten.c) */ -#define NAMSZ 10 /* max length of player name */ -#define DTHSZ 100 /* max length of "killer" string */ -#define ROLESZ 3 /* role length */ -#define BUFSZ 256 /* text buffer size */ - -char *eos(char *p); - -char *ver="3.6.0"; /* version number */ - -/* command line parameters */ -int pause=0, /* pause interval */ - plin=0, /* lines printed without pause */ - pnum=0, /* how many scores to show */ - day=0; /* !0 : show dying dates */ -long low=0; /* minimum score to show */ -char *begdate=NULL, /* date boundaries */ - *enddate=NULL, - *name=NULL, /* if only one username is to be listed */ - *prole=NULL, /* character class */ - *prace=NULL, - *pver=NULL, /* if only scores of a certain version are to be listed */ - *pgend=NULL, /* list only this gender */ - *palign=NULL; /* only this alignment */ - -/* other globals used everywhere */ -int num=0; /* number of scores listed */ - -int main(int argc, char *argv[]) -{ - FILE *inp; - - int i; - long sum=0, - score=0; - - char line[BUFSZ], - fver[6]; - char *filename=RECORD; - - long chkline(char *line); - void help(char *prog,char *par,char *explain); - -/* Command line parameters */ - for (i=1; i'3') { - sprintf(line,"-g %s",pver); - help(argv[0],line,"Versions later than 3.x.x not supported yet"); - } - } - else if (!(strnicmp(argv[i],"-np",3))) /* pause interval, MUST be */ - if (strlen(argv[i])==3) { /* checked before -n */ - i++; - pause=atoi(argv[i]); } - else - pause=atoi(argv[i]+3); - else if (!(strnicmp(argv[i],"-ns",3))) /* minimum score to list */ - if (strlen(argv[i])==3) { /* MUST be checked before -n */ - i++; - low=atol(argv[i]); } - else - low=atol(argv[i]+3); - 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 (!(strnicmp(argv[i],"-ds",3))) /* dates since.. */ - if (strlen(argv[i])==3) { /* MUST be checked before -d */ - i++; - begdate=argv[i]; } - else - begdate=argv[i]+3; - else if (!(strnicmp(argv[i],"-du",3))) /* dates until.. */ - if (strlen(argv[i])==3) { /* MUST be checked before -d */ - i++; - enddate=argv[i]; } - else - enddate=argv[i]+3; - else if (argv[i][1]=='d') /* display the dates */ - day=1; - else if (!(strnicmp(argv[i],"-p",2))) /* role */ - if (strlen(argv[i])==2) { - i++; - prole=argv[i]; } - else - prole=argv[i]+2; - else if (!(strnicmp(argv[i],"-r",2))) { /* race */ - if (strlen(argv[i])==2) { - i++; - prace=argv[i]; } - else - prace=argv[i]+2; - } - else if (!(strnicmp(argv[i],"-a",2))) { /* alignment */ - if (strlen(argv[i])==2) { - i++; - palign=argv[i]; } - else - palign=argv[i]+2; - if (strlen(palign)>3) { - sprintf(line,"-a %s",palign); - help(argv[0],line,"Alignment should be one of law/neu/cha/l/n/c"); - } - } - } - - /* Command line ok, let's process the file */ - - if (!filename) - inp=stdin; /* I don't know if this works on all compilers.. */ - else - if (!(inp=fopen(filename,"r"))) { - printf ("File %s not found\n",filename); - exit (2); - } - - /* Actually I now think there's no point in this. - * You'll probably see if the output looks funny anyway, - * so you might consider the warning more annoying than helpful. 12.12.2015 - fgets(line,sizeof(line),inp); - sscanf(line,"%5s",fver); - if (fver[1]=='.' && fver[3]=='.' && strncmp(fver,"3.6",3) > 0) { - printf ("The file seems to be from a game version newer than me.\n"); - printf ("The output may be incorrect.\n\n"); - } else if (fver[1] != '.') { - printf ("Not sure about which game version the file is from.\n"); - printf ("Version 3.1 assumed for unknown lines.\n\n"); - } - */ - - printf("%-71s%s"," No Points Name","Hp [max]\n"); - /* HERE is the main loop */ - while ((!(feof(inp))) && ((!pnum) || (num0 && plin >= pause) { - printf ("--more--\r"); - if (tolower(getch()=='n')) - pnum = num; - printf (" \r"); - plin = 0; - } - if (score == -9) { - printf ("\nInvalid file format!\n"); - return 1; - } - sum += score; - fgets(line,sizeof(line),inp); - } - - if (num) - printf("\n%d scores. Average score %ld\n",num,sum/(long)num); - else - printf("\nNo games found.\n"); - if (inp!=stdin) - fclose (inp); - if (pause) getch(); - return 0; -} - - -/* Interpret one line of the file. Check for the game version. */ - -long chkline - (char *line) -{ - long line33 (char *line,int rank); - long line32 (char *line); - long line31 (char *line); - - int ver_major, ver_minor, patchlevel, - n; - static int rank=0; - - /* Which game version did this score come from? Are we interested in - scores of that version? */ - n = sscanf (line, "%d.%d.%d", &ver_major, &ver_minor, &patchlevel); - if (!pver || !strncmp(pver,line,strlen(pver)) || !strncmp(pver,"3.1",3)) { - rank++; - if ((ver_major == 3 && ver_minor >= 3) || ver_major > 3) - return line33(line,rank); - else if (ver_major == 3 && ver_minor == 2) - return line32(line); - else - return line31(line); - } - else if (pver) /* We didn't care about that version */ - return 0; - else - return -9; /* I don't understand this version. Newer than 3.3 */ - -} - -/* Interpret a line of game version 3.3 format */ -long line33 - (char *line, int rank) -{ - #define ENDGAMBR 7 - #define EGMIN -5 /* last endgame level */ - #define EGMAX -1 /* first endgame level */ - #define DUNMIN 0 /* minimum dungeonbranch number */ - #define DUNMAX 7 /* maximum dungeonbranch number */ - long score; - int dtype, dlev, maxlev, hp, maxhp; - char bdate[BUFSZ], /* 9 should be enough in VALID files, but we don't */ - ddate[BUFSZ], /* want to crash on invalid entries either.. */ - role[ROLESZ+1], - race[ROLESZ+1], - gender[ROLESZ+1], - align[ROLESZ+1], - plname[NAMSZ+1], - death[DTHSZ+1]; - char linebuf[BUFSZ], - prtbuf[81], - hpbuf[6]; - char *start, *end; - int n, - secline=1, - dayshown=0, - par=0, - hppos; - static char *eglev[] ={"Plane of Earth", /* -1 */ - "Plane of Air", /* -2 */ - "Plane of Fire", /* -3 */ - "Plane of Water", /* -4 */ - "Astral Plane"}; /* -5 */ - static char *dungeon[] ={"The Dungeons of Doom", /* 0 */ - "Gehennom", /* 1 */ - "The Gnomish Mines", /* 2 */ - "The Quest", /* 3 */ - "Sokoban", /* 4 */ - "Fort Ludios", /* 5 */ - "Vlad's Tower", /* 6 */ - "the endgame"}; /* 7 */ - - /* Fields in the line: version(3.3.n, ignored here), score, dungeon branch, - dlevel, max dlevel, hp, max hp, number of deaths (ignored), birthdate, - death date, uid (ignored), role, race, gender, alignment, name, reason */ - n = sscanf(line, - "%*d.%*d.%*d %ld %d %d %d %d %d %*d %s %s %*d %s %s %s %s %[^,],%[^\n\r]", - &score,&dtype,&dlev,&maxlev,&hp,&maxhp,&ddate,&bdate, - role, race, gender, align, plname, death); - if (n<14) /* Invalid line, not all fields found */ - return 0L; - - /* Are we interested in this playername, role, alignment and deathdate? */ - if (role[0]<'A') - return 0L; - if ((prole) && (strnicmp(prole,role,strlen(prole)))) - return 0L; - if ((name) && (strcmp(name,plname))) - return 0L; - if ((prace) && (strnicmp(prace,race,strlen(prace)))) - return 0L; - if ((palign) && (strnicmp(palign,align,strlen(palign)))) - return 0L; - if ((begdate != NULL && strcmp(ddate,begdate) < 0) || - (enddate != NULL && strcmp(ddate,enddate) > 0)) - return 0L; - if (score= EGMIN && dlev <= EGMAX) { - sprintf(eos(linebuf)," on the %s",eglev[-dlev - 1]); - } else { - strcat(linebuf," on the Plane of Void"); - } - } - } else if (strncmp(death,"escape",6)) { - sprintf(eos(linebuf), " in %s on level %d", - (dtype >= DUNMIN && dtype < DUNMAX)? dungeon[dtype]: - "an unknown dungeon branch", - dlev); - if (dlev != maxlev) - sprintf(eos(linebuf), " [max %d]", maxlev); - } - - strcat(linebuf,"."); - - if (secline) - sprintf(eos(linebuf)," %c%s.",toupper(*death),death+1); - else if (start=strchr(death,'{')) - /* Anyway, print what may be in curly braces. I have the game duration - * appended there with my topten patch - * (http://www.clinet.fi/~walker/nethack.html#moves) */ - sprintf(eos(linebuf)," %s",start); - - start=linebuf; - if (hp>0) - sprintf(hpbuf,"%d",hp); - else - sprintf(hpbuf,"-"); - hppos=70; - while (strlen(start)>=hppos) { /* split the line as necessary */ - - for (end=start; end start && (*end != ' ' || par)) { - if (*end == '[') - par=0; - else if (*end == ']') - par=1; - end--; - } - if (end == start) /* There was no good split position, shouldn't happen */ - end=start+hppos; - - strncpy(prtbuf, start, end-start); - prtbuf[end-start]=0; - printf("%s\n",prtbuf); /* This display line */ - plin++; - - if (day && !dayshown) { - printf(" %-15s", ddate); - dayshown=1; - } else - printf("%16s"," "); - start=end+1; /* Start position of the NEXT line */ - hppos= 57 - strlen(hpbuf); - } - end=eos(start); - while (end < start+hppos && end < linebuf+sizeof(linebuf)) - *end++=' '; - sprintf(end,hpbuf); - printf("%s",start); - sprintf(hpbuf,"[%d]",maxhp); - printf("%6s\n",hpbuf); - plin++; - if (day && !dayshown) { - printf(" %-15s\n",ddate); - plin++; - } - num++; - return score; -} - -/* Interpret a line of game version 3.2 format */ -long line32 - (char *line) -{ - int n, - pos, - pos2, - dtype, - dlev, - maxlev, - hp, - maxhp, - par=0, - dayshown=0; - static int nro=0; - long score; - char pvm1[BUFSZ], - pvm2[BUFSZ], - chclass, - sex, - sver[10], - death[150]={""}, - ascend=0; - char *reason; - - long line31(char *line); - - 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[]={"Plane of Earth", /* -1 */ - "Plane of Air", /* -2 */ - "Plane of Fire", /* -3 */ - "Plane of Water", /* -4 */ - "Astral Plane"}; /* -5 */ - nro++; - /* First there is the game version (3.2.something), then comes the actual - score. Then the dungeon branch of death and dlevel, maxdlevel, hp, maxhp, - number of deaths(ignored), dates when the game ended and started, - userid(ignored, character class&sex, name and reason for game ending - */ - - n = sscanf (line,"%9s %ld %d %d %d %d %d %*d %s %s %*d %c%c", - &sver,&score,&dtype,&dlev,&maxlev,&hp,&maxhp, - &pvm1,&pvm2,&chclass,&sex); - - if (chclass<'A') - return (0L); /* The VMS version may have end line with 'class' < A */ - if ((prole) && (prole[0]!=chclass)) - return (0L); /* Some other class specified on the command line */ - if (scorestrlen(line)) /* Never is in a valid file. But we don't want */ - return (0L); /* to crash just if the file is invalid, do we.. */ - pos += 3; - for (pos2=0;(line[pos]!=',')&&(pos2 0)) - return (0L); /* We're not intrested in dates this early /late */ - - 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; - /* Here is the part where I'm not yet totally sure everything still works - as it should.. but this worked on the 3.1 files */ - if (!(strncmp(reason,"poisoned",8))) - strcat(death," was poisoned"); - else if (!(strncmp(reason,"petrified",9))) - strcat(death," turned to stone"); - else if (!(strncmp(reason,"starv",5))) - 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 */ - { - if (dlev < -5 || dlev > -1) { - printf ("Invalid endgame level number %d in file!\n", dlev); - return (0L); - } - sprintf (death+pos," on the %s. ",eglev[-1-dlev]); - /* dlev is negative if you die in the endgame, from -1 to -5 */ - } - else { - sprintf (death+pos," in %s",dungeon[dtype]); - if (dtype!=6) - sprintf(death+strlen(death)," on level %d",dlev); - if (maxlev!=dlev) - sprintf(death+strlen(death)," [max %d]. ",maxlev); - else strcat(death,". "); - } - } - - if ((strncmp(reason,"quit",4)) && (strncmp(reason,"starvation",10)) - && (!ascend)) - { reason[0]=toupper(reason[0]); - for (pos2=0; reason[pos2]>=' '; pos2++); - reason[pos2++]='.'; - reason[pos2]=0; - pos=strlen(death); - strcat(death,reason); - } - - pos=strlen(death); - if (pos>54) { /* split line at the last space before position 54 */ - while (pos>54 || death[pos]!=' ' || (par>0 && pos>30)) { - if(death[pos]==']') /* but we don't split between [] */ - par++; - if(death[pos]=='[') - par--; - pos--; - } - death[pos]=0; - if (day && !dayshown) { - printf ("%s\n %s\t\t",death,pvm1); - dayshown=1; - } - else { - printf("%s\n\t\t",death); - } - plin++; - pos++; - pos2=0; - while (death[pos]) { - death[pos2]=death[pos]; - pos++; - pos2++; } - death[pos2]=0; - } - - printf("%-54s",death); - pos=0; - - if (hp>0) - printf("%3d",hp); - else - printf(" -"); - sprintf(death,"[%d]\n",maxhp); - printf("%7s",death); - plin++; - - if (day && !dayshown) { - printf (" %s\n",pvm1); - plin++; - } - num++; - - return (score); -} - -/* Show some help about the arguments */ -void help(char *prog, char *par, char *explain) -{ - printf ("RECLIST, version %s\n",ver); - printf ("List Nethack 3.1 - 3.5 record file and calculate the average score.\n"); - printf("\nUsage: %s [-f file / -fs / -l] [-u name] [-p role] [-r race]\n", - prog); - printf(" [-a alignment] [-g ver] [-nX] [-nsX] [-npX] [-d]"); - printf(" [-ds date] [-du date]\n\n"); - printf("The options are:\n"); - printf("\t-u name list only the scores of player 'name'\n"); - printf("\t-p profession list only the scores for one character class\n"); - printf("\t-r race race to be listed (since 3.3: hum/dwa/elf/gno/orc)\n"); - printf("\t-a alignment list only this alignment (since 3.3: l/n/c)\n"); - printf("\t-f filename read the scores from the file 'filename'\n"); - printf("\t-fs read the scorelist from stdin\n"); - printf("\t-l read the logfile from %s\n", LOGFILE); - printf("\t-g ver list only scores of game version ver\n"); - printf("\t-n X list only X scores\n"); - printf("\t-np X pause after every X lines\n"); - printf("\t-ns X don't list scores below X points\n"); - printf("\t-d show also the dates\n"); - printf("\t-ds date games ended at or after date\n"); - printf("\t-du date games ended at or before date\n"); - printf("\nYou may specify the options in any order.\n"); - printf("The space after -f, -g, -u, -r, -a, -n, -ns or -np is optional.\n"); - if (par) - printf ("\nUnknown parameter %s\n",par); - if (explain) - printf("%s\n", explain); - exit (1); -} - - -/* If it wasn't a 3.2 record file, we may still check if it makes sense - in the 3.1 format */ - -long line31 (char *line) -{ - int pos, pos2, - dtype, dlev, maxlev, - hp, maxhp, - dayshown=0; - static int nro=0, - plin=1; - 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[]={"Earth", /* 0 */ - "Air", /* -1*/ - "Fire", /* -2*/ - "Water", /* -3*/ - "Astral"}; /* -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 ((prole) && (prole[0]!=chclass)) - return (0); - if (scorestrlen(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]!=',')&&(pos254) { /* split the line before the death reason */ - death[pos]=0; - if (day && !dayshown) { - printf ("%s\n %ld\t\t",death,pvm); - plin++; - dayshown=0; - } - else { - printf("%s\n\t\t",death); - plin++; - } - 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); - plin++; - - 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 && !dayshown) { - printf(" %ld",pvm); - dayshown=0; - } - printf("\t\t%s.\n",reason); - plin++; - } - if (day && !dayshown) { - printf (" %ld\n",pvm); - plin++; - } - num++; - - if (pause>0 && plin >= pause) { - printf ("--more--\r"); - if (tolower(getch()=='n')) - pnum = num; - printf (" \r"); - plin = 0; - } - - return (score); -} - -char *eos(char *p) -{ - while (*p) - p++; - return (p); -}