home *** CD-ROM | disk | FTP | other *** search
- /* SCCS Id: @(#)topten.c 3.1 92/11/20 */
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
- /* NetHack may be freely redistributed. See license for details. */
-
- #include "hack.h"
-
- #ifdef VMS
- /* We don't want to rewrite the whole file, because that entails */
- /* creating a new version which requires that the old one be deletable. */
- # define UPDATE_RECORD_IN_PLACE
- #endif
-
- /*
- * Updating in place can leave junk at the end of the file in some
- * circumstances (if it shrinks and the O.S. doesn't have a straightforward
- * way to truncate it). The trailing junk is harmless and the code
- * which reads the scores will ignore it.
- */
- #ifdef UPDATE_RECORD_IN_PLACE
- # ifndef SEEK_SET
- # define SEEK_SET 0
- # endif
- static long final_fpos;
- #endif
-
- #ifdef NO_SCAN_BRACK
- static void FDECL(nsb_mung_line,(char*));
- static void FDECL(nsb_unmung_line,(char*));
- #endif
-
- #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
- #define dealloc_ttentry(ttent) free((genericptr_t) (ttent))
- #define NAMSZ 10
- #define DTHSZ 60
- #define PERSMAX 3 /* entries per name/uid per char. allowed */
- #define POINTSMIN 1 /* must be > 0 */
- #define ENTRYMAX 100 /* must be >= 10 */
-
- #ifndef MICRO
- #define PERS_IS_UID /* delete for PERSMAX per name; now per uid */
- #endif
- struct toptenentry {
- struct toptenentry *tt_next;
- #ifdef UPDATE_RECORD_IN_PLACE
- long fpos;
- #endif
- long points;
- int deathdnum, deathlev;
- int maxlvl,hp,maxhp;
- int uid;
- char plchar;
- char sex;
- char name[NAMSZ+1];
- char death[DTHSZ+1];
- char date[7]; /* yymmdd */
- } *tt_head;
-
- static void NDECL(outheader);
- static int FDECL(outentry, (int,struct toptenentry *,int));
- static void FDECL(readentry, (FILE *,struct toptenentry *));
- static void FDECL(writeentry, (FILE *,struct toptenentry *));
- static int FDECL(classmon, (CHAR_P,BOOLEAN_P));
-
- /* must fit with end.c */
- const char NEARDATA *killed_by_prefix[] = {
- "killed by ", "choked on ", "poisoned by ", "", "drowned in ",
- "", "crushed to death by ", "petrified by ", "",
- "", "",
- "", "", "" };
-
- static void
- readentry(rfile,tt)
- FILE *rfile;
- struct toptenentry *tt;
- {
- #ifdef UPDATE_RECORD_IN_PLACE
- /* note: fscanf() below must read the record's terminating newline */
- final_fpos = tt->fpos = ftell(rfile);
- #endif
- #ifdef NO_SCAN_BRACK
- if(fscanf(rfile,"%6s %d %d %d %d %d %d %ld%*c%c%c %s %s%*c",
- # define TTFIELDS 13
- #else
- if(fscanf(rfile, "%6s %d %d %d %d %d %d %ld %c%c %[^,],%[^\n]%*c",
- # define TTFIELDS 12
- #endif
- tt->date, &tt->uid,
- &tt->deathdnum, &tt->deathlev,
- &tt->maxlvl, &tt->hp, &tt->maxhp, &tt->points,
- &tt->plchar, &tt->sex,
- #ifdef LATTICE /* return value is broken also, sigh */
- tt->name, tt->death) < 1)
- #else
- tt->name, tt->death) != TTFIELDS)
- #endif
- #undef TTFIELDS
- tt->points = 0;
- else {
- #ifdef NO_SCAN_BRACK
- if(tt->points > 0) {
- nsb_unmung_line(tt->name);
- nsb_unmung_line(tt->death);
- }
- #endif
- }
- }
-
- static void
- writeentry(rfile,tt)
- FILE *rfile;
- struct toptenentry *tt;
- {
- #ifdef NO_SCAN_BRACK
- nsb_mung_line(tt->name);
- nsb_mung_line(tt->death);
- (void) fprintf(rfile,"%6s %d %d %d %d %d %d %ld %c%c %s %s\n",
- #else
- (void) fprintf(rfile,"%6s %d %d %d %d %d %d %ld %c%c %s,%s\n",
- #endif
- tt->date, tt->uid,
- tt->deathdnum, tt->deathlev,
- tt->maxlvl, tt->hp, tt->maxhp, tt->points,
- tt->plchar, tt->sex,
- onlyspace(tt->name) ? "_" : tt->name, tt->death);
- #ifdef NO_SCAN_BRACK
- nsb_unmung_line(tt->name);
- nsb_unmung_line(tt->death);
- #endif
- }
-
- void
- topten(how)
- int how;
- {
- int uid = getuid();
- int rank, rank0 = -1, rank1 = 0;
- int occ_cnt = PERSMAX;
- register struct toptenentry *t0, *tprev;
- struct toptenentry *t1;
- FILE *rfile;
- register int flg = 0;
- #ifdef LOGFILE
- FILE *lfile;
- #endif /* LOGFILE */
-
- #if defined(MICRO)
- #define HUP
- #else
- #define HUP if(!done_hup)
- #endif
- /* create a new 'topten' entry */
- t0 = newttentry();
- /* deepest_lev_reached() is in terms of depth(), and reporting the
- * deepest level reached in the dungeon death occurred in doesn't
- * seem right, so we have to report the death level in depth() terms
- * as well (which also seems reasonable since that's all the player
- * sees on the screen anyway)
- */
- t0->deathdnum = u.uz.dnum;
- t0->deathlev = depth(&u.uz);
- t0->maxlvl = deepest_lev_reached(TRUE);
- t0->hp = u.uhp;
- t0->maxhp = u.uhpmax;
- t0->points = u.urexp;
- t0->plchar = pl_character[0];
- t0->sex = (flags.female ? 'F' : 'M');
- t0->uid = uid;
- (void) strncpy(t0->name, plname, NAMSZ);
- t0->name[NAMSZ] = '\0';
- t0->death[0] = '\0';
- switch (killer_format) {
- default: impossible("bad killer format?");
- case KILLED_BY_AN:
- Strcat(t0->death, killed_by_prefix[how]);
- (void) strncat(t0->death, an(killer), DTHSZ);
- break;
- case KILLED_BY:
- Strcat(t0->death, killed_by_prefix[how]);
- (void) strncat(t0->death, killer, DTHSZ);
- break;
- case NO_KILLER_PREFIX:
- (void) strncat(t0->death, killer, DTHSZ);
- break;
- }
- Strcpy(t0->date, get_date());
- t0->tt_next = 0;
- #ifdef UPDATE_RECORD_IN_PLACE
- t0->fpos = -1L;
- #endif
-
- #ifdef LOGFILE /* used for debugging (who dies of what, where) */
- if (lock_file(LOGFILE, 10)) {
- if(!(lfile = fopen_datafile(LOGFILE,"a"))) {
- HUP raw_print("Cannot open log file!");
- } else {
- writeentry(lfile, t0);
- (void) fclose(lfile);
- }
- unlock_file(LOGFILE);
- }
- #endif /* LOGFILE */
-
- #if defined(WIZARD) || defined(EXPLORE_MODE)
- if (wizard || discover) {
- raw_print("");
- raw_printf(
- "Since you were in %s mode, the score list will not be checked.",
- wizard ? "wizard" : "discover");
- return;
- }
- #endif
-
- if (!lock_file(RECORD, 60)) return;
-
- #ifdef UPDATE_RECORD_IN_PLACE
- rfile = fopen_datafile(RECORD, "r+");
- #else
- rfile = fopen_datafile(RECORD, "r");
- #endif
-
- if (!rfile) {
- HUP raw_print("Cannot open record file!");
- unlock_file(RECORD);
- return;
- }
-
- HUP raw_print("");
-
- /* assure minimum number of points */
- if(t0->points < POINTSMIN) t0->points = 0;
-
- t1 = tt_head = newttentry();
- tprev = 0;
- /* rank0: -1 undefined, 0 not_on_list, n n_th on list */
- for(rank = 1; ; ) {
- readentry(rfile, t1);
- if (t1->points < POINTSMIN) t1->points = 0;
- if(rank0 < 0 && t1->points < t0->points) {
- rank0 = rank++;
- if(tprev == 0)
- tt_head = t0;
- else
- tprev->tt_next = t0;
- t0->tt_next = t1;
- #ifdef UPDATE_RECORD_IN_PLACE
- t0->fpos = t1->fpos; /* insert here */
- #endif
- occ_cnt--;
- flg++; /* ask for a rewrite */
- } else tprev = t1;
-
- if(t1->points == 0) break;
- if(
- #ifdef PERS_IS_UID
- t1->uid == t0->uid &&
- #else
- strncmp(t1->name, t0->name, NAMSZ) == 0 &&
- #endif
- t1->plchar == t0->plchar && --occ_cnt <= 0) {
- if(rank0 < 0) {
- rank0 = 0;
- rank1 = rank;
- HUP {
- raw_printf(
- "You didn't beat your previous score of %ld points.",
- t1->points);
- raw_print("");
- }
- }
- if(occ_cnt < 0) {
- flg++;
- continue;
- }
- }
- if(rank <= ENTRYMAX) {
- t1 = t1->tt_next = newttentry();
- rank++;
- }
- if(rank > ENTRYMAX) {
- t1->points = 0;
- break;
- }
- }
- if(flg) { /* rewrite record file */
- #ifdef UPDATE_RECORD_IN_PLACE
- (void) fseek(rfile, (t0->fpos >= 0 ?
- t0->fpos : final_fpos), SEEK_SET);
- #else
- (void) fclose(rfile);
- if(!(rfile = fopen_datafile(RECORD,"w"))){
- HUP raw_print("Cannot write record file");
- unlock_file(RECORD);
- return;
- }
- #endif /* UPDATE_RECORD_IN_PLACE */
- if(!done_stopprint) if(rank0 > 0){
- if(rank0 <= 10)
- raw_print("You made the top ten list!");
- else {
- raw_printf(
- "You reached the %d%s place on the top %d list.",
- rank0, ordin(rank0), ENTRYMAX);
- }
- raw_print("");
- }
- }
- if(rank0 == 0) rank0 = rank1;
- if(rank0 <= 0) rank0 = rank;
- if(!done_stopprint) outheader();
- t1 = tt_head;
- for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
- if(flg
- #ifdef UPDATE_RECORD_IN_PLACE
- && rank >= rank0
- #endif
- ) writeentry(rfile, t1);
- if(done_stopprint) continue;
- if(rank > flags.end_top &&
- (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
- && (!flags.end_own ||
- #ifdef PERS_IS_UID
- t1->uid != t0->uid
- #else
- strncmp(t1->name, t0->name, NAMSZ)
- #endif
- )) continue;
- if(rank == rank0-flags.end_around &&
- rank0 > flags.end_top+flags.end_around+1 &&
- !flags.end_own)
- raw_print("");
- if(rank != rank0)
- (void) outentry(rank, t1, 0);
- else if(!rank1)
- (void) outentry(rank, t1, 1);
- else {
- int t0lth = outentry(0, t0, -1);
- int t1lth = outentry(rank, t1, t0lth);
- if(t1lth > t0lth) t0lth = t1lth;
- (void) outentry(0, t0, t0lth);
- }
- }
- if(rank0 >= rank) if(!done_stopprint)
- (void) outentry(0, t0, 1);
- #ifdef UPDATE_RECORD_IN_PLACE
- if (flg) {
- # ifdef TRUNCATE_FILE
- /* if a reasonable way to truncate a file exists, use it */
- truncate_file(rfile);
- # else
- /* use sentinel record rather than relying on truncation */
- t0->points = 0L; /* terminates file when read back in */
- t0->uid = t0->deathdnum = t0->deathlev = 0;
- t0->maxlvl = t0->hp = t0->maxhp = 0;
- t0->plchar = t0->sex = '-';
- Strcpy(t0->name, "@");
- Strcpy(t0->death, "<eod>\n");
- writeentry(rfile, t0);
- (void) fflush(rfile);
- # endif /* TRUNCATE_FILE */
- }
- #endif /* UPDATE_RECORD_IN_PLACE */
- (void) fclose(rfile);
- unlock_file(RECORD);
- }
-
- static void
- outheader() {
- char linebuf[BUFSZ];
- register char *bp;
-
- Strcpy(linebuf, " No Points Name");
- bp = eos(linebuf);
- while(bp < linebuf + COLNO - 9) *bp++ = ' ';
- Strcpy(bp, "Hp [max]");
- raw_print(linebuf);
- }
-
- /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
- static int
- outentry(rank, t1, so)
- register struct toptenentry *t1;
- register int rank, so;
- {
- register boolean second_line = TRUE;
- char linebuf[BUFSZ], linebuf2[BUFSZ], linebuf3[BUFSZ], pbuf[BUFSZ];
-
- linebuf[0] = linebuf2[0] = linebuf3[0] = 0;
- if(rank) Sprintf(eos(linebuf), "%3d", rank);
- else Strcat(linebuf, " ");
-
- Sprintf(eos(linebuf), " %10ld %.10s", t1->points, t1->name);
- Sprintf(eos(linebuf), "-%c ", t1->plchar);
- if(!strncmp("escaped", t1->death, 7)) {
- second_line = FALSE;
- if(!strcmp(" (with the Amulet)", t1->death+7))
- Strcat(linebuf, "escaped the dungeon with the Amulet");
- else
- Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
- t1->maxlvl);
- } else if(!strncmp("ascended", t1->death, 8)) {
- Strcat(linebuf, "ascended to demigod");
- if (t1->sex == 'F') Strcat(linebuf, "dess");
- Strcat(linebuf, "-hood");
- second_line = FALSE;
- } else {
- if(!strncmp(t1->death,"quit",4)) {
- Strcat(linebuf, "quit");
- second_line = FALSE;
- } else if(!strncmp(t1->death,"starv",5)) {
- Strcat(linebuf, "starved to death");
- second_line = FALSE;
- } else if(!strncmp(t1->death,"choked",6)) {
- Sprintf(eos(linebuf), "choked on h%s food",
- (t1->sex == 'F') ? "er" : "is");
- } else if(!strncmp(t1->death,"poisoned",8)) {
- Strcat(linebuf, "was poisoned");
- } else if(!strncmp(t1->death,"crushed",7)) {
- Strcat(linebuf, "was crushed to death");
- } else if(!strncmp(t1->death, "petrified by ",13)) {
- Strcat(linebuf, "turned to stone");
- } else Strcat(linebuf, "died");
-
- if (t1->deathdnum == astral_level.dnum)
- Strcpy(linebuf3, " in the endgame");
- else
- Sprintf(linebuf3, " in %s on level %d",
- dungeons[t1->deathdnum].dname, t1->deathlev);
- if(t1->deathlev != t1->maxlvl)
- Sprintf(eos(linebuf3), " [max %d]", t1->maxlvl);
- /* kludge for "quit while already on Charon's boat" */
- if(!strncmp(t1->death, "quit ", 5))
- Strcat(linebuf3, t1->death + 4);
- }
- Strcat(linebuf3, ".");
-
- if(t1->maxhp) {
- register char *bp;
- char hpbuf[10];
- int hppos;
- int lngr = strlen(linebuf) + strlen(linebuf3);
- if (t1->hp <= 0) hpbuf[0] = '-', hpbuf[1] = '\0';
- else Sprintf(hpbuf, "%d", t1->hp);
- hppos = COLNO - 7 - (int)strlen(hpbuf);
- if (lngr >= hppos) {
- if(so > 0) {
- bp = eos(linebuf);
- while(bp < linebuf + (COLNO-1)) *bp++ = ' ';
- *bp = 0;
- raw_print_bold(linebuf);
- } else if(so == 0)
- raw_print(linebuf);
- Strcpy(linebuf, " ");
- }
- Strcat(linebuf, linebuf3);
- bp = eos(linebuf);
-
- if(bp <= linebuf + hppos) {
- /* pad any necessary blanks to the hit point entry */
- while(bp < linebuf + hppos) *bp++ = ' ';
- Strcpy(bp, hpbuf);
- if(t1->maxhp < 10)
- Sprintf(eos(bp), " [%d]", t1->maxhp);
- else if(t1->maxhp < 100)
- Sprintf(eos(bp), " [%d]", t1->maxhp);
- else Sprintf(eos(bp), " [%d]", t1->maxhp);
- }
- }
-
- /* Line 2 now contains the killer name */
-
- /* Quit, starved, ascended, and escaped contain no second line */
- if (second_line) {
- Strcpy(linebuf2, t1->death);
- *linebuf2 = highc(*linebuf2);
- Strcat(linebuf2, ".");
- }
-
- if(so == 0) {
- raw_print(linebuf);
- if (second_line)
- raw_printf(" %s", linebuf2);
- } else if(so > 0) {
- register char *bp = eos(linebuf);
- if(so >= COLNO) so = COLNO-1;
- while(bp < linebuf + so) *bp++ = ' ';
- *bp = 0;
- raw_print_bold(linebuf);
- if(second_line) {
- Sprintf(pbuf, " %s", linebuf2);
- raw_print_bold(pbuf);
- }
- }
- return((int)strlen(linebuf)+(int)strlen(linebuf2));
- }
-
- /*
- * Called with args from main if argc >= 0. In this case, list scores as
- * requested. Otherwise, find scores for the current player (and list them
- * if argc == -1).
- */
- void
- prscore(argc,argv)
- int argc;
- char **argv;
- {
- const char **players;
- int playerct;
- int rank;
- register struct toptenentry *t1, *t2;
- FILE *rfile;
- register int flg = 0, i;
- char pbuf[BUFSZ];
- #ifdef nonsense
- long total_score = 0L;
- char totchars[10];
- int totcharct = 0;
- #endif
- int outflg = (argc >= -1);
- #ifdef PERS_IS_UID
- int uid = -1;
- #else
- const char *player0;
- #endif
- rfile = fopen_datafile(RECORD, "r");
- if (!rfile) {
- raw_print("Cannot open record file!");
- return;
- }
-
- /* If the score list isn't after a game, we never went through */
- /* init_dungeons() */
- if (wiz1_level.dlevel == 0) init_dungeons();
-
- if(argc > 1 && !strncmp(argv[1], "-s", 2)){
- if(!argv[1][2]){
- argc--;
- argv++;
- } else if(!argv[1][3] && index(pl_classes, argv[1][2])) {
- argv[1]++;
- argv[1][0] = '-';
- } else argv[1] += 2;
- }
- if(argc <= 1){
- #ifdef PERS_IS_UID
- uid = getuid();
- playerct = 0;
- # if defined(LINT) || defined(GCC_WARN)
- players = 0;
- # endif
- #else
- player0 = plname;
- if(!*player0)
- player0 = "hackplayer";
- playerct = 1;
- players = &player0;
- #endif
- } else {
- playerct = --argc;
- players = (const char **)++argv;
- }
- if(outflg) raw_print("");
-
- t1 = tt_head = newttentry();
- for(rank = 1; ; rank++) {
- readentry(rfile, t1);
- if(t1->points == 0) break;
- #ifdef PERS_IS_UID
- if(!playerct && t1->uid == uid)
- flg++;
- else
- #endif
- for(i = 0; i < playerct; i++){
- if(strcmp(players[i], "all") == 0 ||
- strncmp(t1->name, players[i], NAMSZ) == 0 ||
- (players[i][0] == '-' &&
- players[i][1] == t1->plchar &&
- players[i][2] == 0) ||
- (digit(players[i][0]) && rank <= atoi(players[i])))
- flg++;
- }
- t1 = t1->tt_next = newttentry();
- }
- (void) fclose(rfile);
- if(!flg) {
- if(outflg) {
- Strcpy(pbuf, "Cannot find any entries for ");
- if(playerct < 1) Strcat(pbuf, "you.");
- else {
- if(playerct > 1) Strcat(pbuf, "any of ");
- for(i=0; i<playerct; i++) {
- Strcat(pbuf, players[i]);
- if(i<playerct-1) Strcat(pbuf, ":");
- }
- raw_print(pbuf);
- raw_printf("Call is: %s -s [-role] [maxrank] [playernames]",
- hname);
- }
- }
- return;
- }
-
- if(outflg) outheader();
- t1 = tt_head;
- for(rank = 1; t1->points != 0; rank++, t1 = t2) {
- t2 = t1->tt_next;
- #ifdef PERS_IS_UID
- if(!playerct && t1->uid == uid)
- goto outwithit;
- else
- #endif
- for(i = 0; i < playerct; i++){
- if(strcmp(players[i], "all") == 0 ||
- strncmp(t1->name, players[i], NAMSZ) == 0 ||
- (players[i][0] == '-' &&
- players[i][1] == t1->plchar &&
- players[i][2] == 0) ||
- (digit(players[i][0]) && rank <= atoi(players[i]))){
- #ifdef PERS_IS_UID
- outwithit:
- #endif
- if(outflg)
- (void) outentry(rank, t1, 0);
- #ifdef nonsense
- total_score += t1->points;
- if(totcharct < sizeof(totchars)-1)
- totchars[totcharct++] = t1->plchar;
- #endif
- break;
- }
- }
- dealloc_ttentry(t1);
- }
- #ifdef nonsense
- totchars[totcharct] = 0;
-
- /* We would like to determine whether you're experienced. However,
- the information collected here only tells about the scores/roles
- that got into the topten (top 100?). We should maintain a
- .hacklog or something in his home directory. */
- flags.beginner = (total_score < 6000);
- for(i=0; i<6; i++)
- if(!index(totchars, pl_classes[i])) {
- flags.beginner = 1;
- if(!pl_character[0]) pl_character[0] = pl_classes[i];
- break;
- }
- #endif /* nonsense /**/
- }
-
- static int
- classmon(plch, fem)
- char plch;
- boolean fem;
- {
- switch (plch) {
- case 'A': return PM_ARCHEOLOGIST;
- case 'B': return PM_BARBARIAN;
- case 'C': return (fem ? PM_CAVEWOMAN : PM_CAVEMAN);
- case 'E': return PM_ELF;
- case 'H': return PM_HEALER;
- case 'F': /* accept old Fighter class */
- case 'K': return PM_KNIGHT;
- case 'P': return (fem ? PM_PRIESTESS : PM_PRIEST);
- case 'R': return PM_ROGUE;
- case 'N': /* accept old Ninja class */
- case 'S': return PM_SAMURAI;
- #ifdef TOURIST
- case 'T': return PM_TOURIST;
- #else
- case 'T': return PM_HUMAN;
- #endif
- case 'V': return PM_VALKYRIE;
- case 'W': return PM_WIZARD;
- default: impossible("What weird class is this? (%c)", plch);
- return PM_HUMAN_ZOMBIE;
- }
- }
-
- /*
- * Get a random player name and class from the high score list,
- * and attach them to an object (for statues or morgue corpses).
- */
- struct obj *
- tt_oname(otmp)
- struct obj *otmp;
- {
- int rank;
- register int i;
- register struct toptenentry *tt;
- FILE *rfile;
-
- if (!otmp) return((struct obj *) 0);
-
- rfile = fopen_datafile(RECORD, "r");
- if (!rfile) {
- panic("Cannot open record file!");
- }
-
- tt = newttentry();
- rank = rnd(10);
- pickentry:
- for(i = rank; i; i--) {
- readentry(rfile, tt);
- if(tt->points == 0) break;
- }
-
- if(tt->points == 0) {
- if(rank > 1) {
- rank = 1;
- rewind(rfile);
- goto pickentry;
- }
- dealloc_ttentry(tt);
- otmp = (struct obj *) 0;
- } else {
- otmp->corpsenm = classmon(tt->plchar, (tt->sex == 'F'));
- otmp->owt = weight(otmp);
- /* Note: oname() is safe since otmp is first in chains */
- otmp = oname(otmp, tt->name, 0);
- fobj = otmp;
- level.objects[otmp->ox][otmp->oy] = otmp;
- dealloc_ttentry(tt);
- }
-
- (void) fclose(rfile);
- return otmp;
- }
-
- #ifdef NO_SCAN_BRACK
- /* Lattice scanf isn't up to reading the scorefile. What */
- /* follows deals with that; I admit it's ugly. (KL) */
- /* Now generally available (KL) */
- static void
- nsb_mung_line(p)
- char *p;
- {
- while(p=index(p,' '))*p='|';
- }
-
- static void
- nsb_unmung_line(p)
- char *p;
- {
- while(p=index(p,'|'))*p=' ';
- }
- #endif
-
- /*topten.c*/
-