Source:NetHack 3.0.0/topten.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to topten.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/topten.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)topten.c	3.0	88/11/24
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    /* block some unused #defines to avoid overloading some cpp's */
6.    #define MONATTK_H
7.    #include "hack.h"
8.    
9.    #include <errno.h>      /* George Barbanis */
10.   
11.   static char *itoa P((int)), *ordin P((int));
12.   static void outheader();
13.   static int outentry P((int,struct toptenentry *,int));
14.   
15.   #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
16.   #define	NAMSZ	10
17.   #define	DTHSZ	60
18.   #define	PERSMAX	 3		/* entries per name/uid per char. allowed */
19.   #define	POINTSMIN	1	/* must be > 0 */
20.   #define	ENTRYMAX	100	/* must be >= 10 */
21.   #ifndef MSDOS
22.   #define	PERS_IS_UID		/* delete for PERSMAX per name; now per uid */
23.   #endif
24.   struct toptenentry {
25.   	struct toptenentry *tt_next;
26.   	long int points;
27.   	int level,maxlvl,hp,maxhp;
28.   	int uid;
29.   	char plchar;
30.   	char sex;
31.   	char name[NAMSZ+1];
32.   	char death[DTHSZ+1];
33.   	char date[7];		/* yymmdd */
34.   } *tt_head;
35.   
36.   void
37.   topten(){
38.   	int uid = getuid();
39.   	int rank, rank0 = -1, rank1 = 0;
40.   	int occ_cnt = PERSMAX;
41.   	register struct toptenentry *t0, *t1, *tprev;
42.   	char *recfile = RECORD;
43.   #ifdef UNIX
44.   	char *reclock = "record_lock";
45.   #endif
46.   	int sleepct = 300;
47.   	FILE *rfile;
48.   	register int flg = 0;
49.   #ifdef LOGFILE
50.   	char *lgfile = LOGFILE;
51.   	FILE *lfile;
52.   #ifdef UNIX
53.   	char *loglock = "logfile_lock";
54.   	int sleeplgct = 30;
55.   #endif /* UNIX */
56.   #endif /* LOGFILE */
57.   
58.   #ifdef MSDOS
59.   #define HUP
60.   #else
61.   #define	HUP	if(!done_hup)
62.   #endif
63.   
64.   #ifdef UNIX
65.   	while(link(recfile, reclock) == -1) {
66.   		HUP perror(reclock);
67.   		if(!sleepct--) {
68.   			HUP (void) puts("I give up.  Sorry.");
69.   			HUP (void) puts("Perhaps there is an old record_lock around?");
70.   			return;
71.   		}
72.   		HUP Printf("Waiting for access to record file. (%d)\n",
73.   			sleepct);
74.   		HUP (void) fflush(stdout);
75.   #if defined(SYSV) || defined(ULTRIX)
76.   		(void)
77.   #endif
78.   		    sleep(1);
79.   	}
80.   #endif
81.   	if(!(rfile = fopen(recfile,"r"))){
82.   		HUP (void) puts("Cannot open record file!");
83.   		goto unlock;
84.   	}
85.   	HUP (void) putchar('\n');
86.   
87.   	/* create a new 'topten' entry */
88.   	t0 = newttentry();
89.   	t0->level = dlevel;
90.   	t0->maxlvl = maxdlevel;
91.   	t0->hp = u.uhp;
92.   	t0->maxhp = u.uhpmax;
93.   	t0->points = u.urexp;
94.   	t0->plchar = pl_character[0];
95.   	t0->sex = (flags.female ? 'F' : 'M');
96.   	t0->uid = uid;
97.   	(void) strncpy(t0->name, plname, NAMSZ);
98.   	(t0->name)[NAMSZ] = 0;
99.   	(void) strncpy(t0->death, killer, DTHSZ);
100.  	(t0->death)[DTHSZ] = 0;
101.  	Strcpy(t0->date, getdate());
102.  
103.  	/* assure minimum number of points */
104.  	if(t0->points < POINTSMIN) t0->points = 0;
105.  #ifdef LOGFILE		/* used for debugging (who dies of what, where) */
106.  #ifdef UNIX
107.  	while(link(lgfile, loglock) == -1) {
108.  		extern int errno;
109.  
110.  		if (errno == ENOENT) /* If no such file, do not keep log */
111.  			goto lgend;  /* George Barbanis */
112.  		HUP perror(loglock);
113.  		if(!sleeplgct--) {
114.  			HUP (void) puts("I give up.  Sorry.");
115.  			HUP (void) puts("Perhaps there is an old logfile_lock around?");
116.  			goto lgend;
117.  		}
118.  		HUP Printf("Waiting for access to log file. (%d)\n",
119.   			sleeplgct);
120.  		HUP (void) fflush(stdout);
121.  #if defined(SYSV) || defined(ULTRIX)
122.  		(void)
123.  #endif
124.  		    sleep(1);
125.  	}
126.  #endif /* UNIX */
127.  	if(!(lfile = fopen(lgfile,"a"))){
128.  		HUP (void) puts("Cannot open log file!");
129.  		goto lgend;
130.  	}
131.  	(void) fprintf(lfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n",
132.  	    t0->date, t0->uid,
133.  	    t0->level, t0->maxlvl,
134.  	    t0->hp, t0->maxhp, t0->points,
135.  	    t0->plchar, t0->sex, t0->name, t0->death);
136.  	(void) fclose(lfile);
137.  #ifdef UNIX
138.  	(void) unlink(loglock);
139.  #endif /* UNIX */
140.        lgend:;
141.  #endif /* LOGFILE */
142.  
143.  	t1 = tt_head = newttentry();
144.  	tprev = 0;
145.  	/* rank0: -1 undefined, 0 not_on_list, n n_th on list */
146.  	for(rank = 1; ; ) {
147.  #ifdef TOS
148.  	    char k1[2],k2[2];
149.  	    if(fscanf(rfile, "%6s %d %d %d %d %d %ld %1s%1s %s %s]",
150.  #else
151.  	    if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
152.  #endif
153.  		t1->date, &t1->uid,
154.  		&t1->level, &t1->maxlvl,
155.  		&t1->hp, &t1->maxhp, &t1->points,
156.  #ifdef TOS
157.  		k1, k2,
158.  #else
159.  		&t1->plchar, &t1->sex,
160.  #endif
161.  		t1->name, t1->death) != 11 || t1->points < POINTSMIN)
162.  			t1->points = 0;
163.  
164.  #ifdef TOS
165.  	    t1->plchar=k1[0];
166.  	    t1->sex=k2[0];
167.  #endif
168.  	    if(rank0 < 0 && t1->points < t0->points) {
169.  		rank0 = rank++;
170.  		if(tprev == 0)
171.  			tt_head = t0;
172.  		else
173.  			tprev->tt_next = t0;
174.  		t0->tt_next = t1;
175.  		occ_cnt--;
176.  		flg++;		/* ask for a rewrite */
177.  	    } else tprev = t1;
178.  
179.  	    if(t1->points == 0) break;
180.  	    if(
181.  #ifdef PERS_IS_UID
182.  		t1->uid == t0->uid &&
183.  #else
184.  		strncmp(t1->name, t0->name, NAMSZ) == 0 &&
185.  #endif
186.  		t1->plchar == t0->plchar && --occ_cnt <= 0) {
187.  		    if(rank0 < 0) {
188.  			rank0 = 0;
189.  			rank1 = rank;
190.  	HUP Printf("You didn't beat your previous score of %ld points.\n\n",
191.  				t1->points);
192.  		    }
193.  		    if(occ_cnt < 0) {
194.  			flg++;
195.  			continue;
196.  		    }
197.  		}
198.  	    if(rank <= ENTRYMAX) {
199.  		t1 = t1->tt_next = newttentry();
200.  		rank++;
201.  	    }
202.  	    if(rank > ENTRYMAX) {
203.  		t1->points = 0;
204.  		break;
205.  	    }
206.  	}
207.  	if(flg) {	/* rewrite record file */
208.  		(void) fclose(rfile);
209.  		if(!(rfile = fopen(recfile,"w"))){
210.  			HUP (void) puts("Cannot write record file\n");
211.  			goto unlock;
212.  		}
213.  
214.  		if(!done_stopprint) if(rank0 > 0){
215.  		    if(rank0 <= 10)
216.  			(void) puts("You made the top ten list!\n");
217.  		    else
218.  		Printf("You reached the %d%s place on the top %d list.\n\n",
219.  			rank0, ordin(rank0), ENTRYMAX);
220.  		}
221.  	}
222.  	if(rank0 == 0) rank0 = rank1;
223.  	if(rank0 <= 0) rank0 = rank;
224.  	if(!done_stopprint) outheader();
225.  	t1 = tt_head;
226.  	for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
227.  	  if(flg) (void) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n",
228.  	    t1->date, t1->uid,
229.  	    t1->level, t1->maxlvl,
230.  	    t1->hp, t1->maxhp, t1->points,
231.  	    t1->plchar, t1->sex, t1->name, t1->death);
232.  	  if(done_stopprint) continue;
233.  	  if(rank > flags.end_top &&
234.  	    (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
235.  	    && (!flags.end_own ||
236.  #ifdef PERS_IS_UID
237.  				  t1->uid != t0->uid
238.  #else
239.  				  strncmp(t1->name, t0->name, NAMSZ)
240.  #endif
241.  		)) continue;
242.  	  if(rank == rank0-flags.end_around &&
243.  	     rank0 > flags.end_top+flags.end_around+1 &&
244.  	     !flags.end_own)
245.  		(void) putchar('\n');
246.  	  if(rank != rank0)
247.  		(void) outentry(rank, t1, 0);
248.  	  else if(!rank1)
249.  		(void) outentry(rank, t1, 1);
250.  	  else {
251.  		int t0lth = outentry(0, t0, -1);
252.  		int t1lth = outentry(rank, t1, t0lth);
253.  		if(t1lth > t0lth) t0lth = t1lth;
254.  		(void) outentry(0, t0, t0lth);
255.  	  }
256.  	}
257.  	if(rank0 >= rank) if(!done_stopprint)
258.  		(void) outentry(0, t0, 1);
259.  	(void) fclose(rfile);
260.  unlock:	;
261.  #ifdef UNIX
262.  	(void) unlink(reclock);
263.  #endif
264.  }
265.  
266.  static void
267.  outheader() {
268.  	char linebuf[BUFSZ];
269.  	register char *bp;
270.  
271.  	Strcpy(linebuf, " No  Points   Name");
272.  	bp = eos(linebuf);
273.  	while(bp < linebuf + COLNO - 9) *bp++ = ' ';
274.  	Strcpy(bp, "Hp [max]");
275.  	(void) puts(linebuf);
276.  }
277.  
278.  /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
279.  static int
280.  outentry(rank, t1, so)
281.  register struct toptenentry *t1;
282.  register int rank, so;
283.  {
284.  	register boolean quit = FALSE, iskilled = FALSE, starv = FALSE,
285.  		isstoned = FALSE;
286.  	char linebuf[BUFSZ];
287.  	linebuf[0] = 0;
288.  	if(rank) Sprintf(eos(linebuf), " %2d", rank);
289.  		else Sprintf(eos(linebuf), "   ");
290.  	Sprintf(eos(linebuf), " %7ld  %.10s", t1->points, t1->name);
291.  	Sprintf(eos(linebuf), "-%c ", t1->plchar);
292.  	if(!strncmp("escaped", t1->death, 7)) {
293.  	  if(!strcmp(" (with amulet)", t1->death+7))
294.  	    Sprintf(eos(linebuf), "escaped the dungeon with amulet");
295.  	  else
296.  	    Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
297.  	      t1->maxlvl);
298.  #ifdef ENDGAME
299.  	} else if(!strncmp("ascended", t1->death, 8)) {
300.  	   Sprintf(eos(linebuf), "ascended to demigod-hood");
301.  #endif
302.  	} else {
303.  	  if(!strncmp(t1->death,"quit",4)) {
304.  		quit = TRUE;
305.  		Sprintf(eos(linebuf), "quit");
306.  	  } else if(!strcmp(t1->death,"choked"))
307.  		Sprintf(eos(linebuf), "choked on %s food",
308.  			(t1->sex == 'F') ? "her" : "his");
309.  	  else if(!strncmp(t1->death,"starv",5)) {
310.  		Sprintf(eos(linebuf), "starved to death");
311.  		starv = TRUE;
312.  	  } else if(!strncmp(t1->death, "turned to stone by ",19)) {
313.  		Sprintf(eos(linebuf), "was petrified");
314.  		isstoned = TRUE;
315.  	  } else {
316.  		Sprintf(eos(linebuf), "was killed");
317.  		iskilled = TRUE;
318.  	  }
319.  #ifdef ENDLEVEL
320.  	  if (t1->level == ENDLEVEL)
321.  		Strcpy(eos(linebuf), " in the endgame");
322.  	  else
323.  #endif
324.  	    Sprintf(eos(linebuf), " on%s level %d",
325.  	      (iskilled || isstoned || starv) ? "" : " dungeon", t1->level);
326.  	  if(t1->maxlvl != t1->level)
327.  	    Sprintf(eos(linebuf), " [max %d]", t1->maxlvl);
328.  	  if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4);
329.  	}
330.  	if(iskilled) Sprintf(eos(linebuf), " by %s%s",
331.  	  (!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4)
332.  	   || !strncmp(t1->death, "Mr. ", 4) || !strncmp(t1->death, "Ms. ", 4)
333.  	   ) ? "" :
334.  	  index(vowels,*t1->death) ? "an " : "a ",
335.  	  t1->death);
336.  	if (isstoned) Sprintf(eos(linebuf), " by %s%s", index(vowels,
337.  		*(t1->death + 19)) ? "an " : "a ", t1->death + 19);
338.  	Sprintf(eos(linebuf), ".");
339.  	if(t1->maxhp) {
340.  	  register char *bp = eos(linebuf);
341.  	  char hpbuf[10];
342.  	  int hppos;
343.  	  int lngr = strlen(linebuf);
344.  	  Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-");
345.  	  hppos = COLNO - 7 - strlen(hpbuf);
346.  	  if (lngr >= hppos) hppos = (2*COLNO) - 7 - strlen(hpbuf);
347.  	  if(bp <= linebuf + hppos) {
348.  	    /* pad any necessary blanks to the hit point entry */
349.  	    while(bp < linebuf + hppos) *bp++ = ' ';
350.  	    Strcpy(bp, hpbuf);
351.  	    if(t1->maxhp < 10)
352.  		 Sprintf(eos(bp), "   [%d]", t1->maxhp);
353.  	    else if(t1->maxhp < 100)
354.  		 Sprintf(eos(bp), "  [%d]", t1->maxhp);
355.  	    else Sprintf(eos(bp), " [%d]", t1->maxhp);
356.  	  }
357.  	}
358.  	if(so == 0) (void) puts(linebuf);
359.  	else if(so > 0) {
360.  	  register char *bp = eos(linebuf);
361.  	  if(so >= COLNO) so = COLNO-1;
362.  	  while(bp < linebuf + so) *bp++ = ' ';
363.  	  *bp = 0;
364.  	  standoutbeg();
365.  	  (void) fputs(linebuf,stdout);
366.  	  standoutend();
367.  	  (void) putchar('\n');
368.  	}
369.  	return(strlen(linebuf));
370.  }
371.  
372.  static char *
373.  itoa(a) int a; {
374.  #ifdef LINT	/* static char buf[12]; */
375.  char buf[12];
376.  #else
377.  static char buf[12];
378.  #endif
379.  	Sprintf(buf,"%d",a);
380.  	return(buf);
381.  }
382.  
383.  static char *
384.  ordin(n)
385.  int n; {
386.  	register int dd = n%10;
387.  
388.  #if ENTRYMAX > 110
389.  	return((dd==0 || dd>3 || (n/10)%10==1) ? "th" :
390.  #else
391.  	return((dd==0 || dd>3 || n/10==1) ? "th" :
392.  #endif
393.  	       (dd==1) ? "st" : (dd==2) ? "nd" : "rd");
394.  }
395.  
396.  char *
397.  eos(s)
398.  register char *s;
399.  {
400.  	while(*s) s++;
401.  	return(s);
402.  }
403.  
404.  /*
405.   * Called with args from main if argc >= 0. In this case, list scores as
406.   * requested. Otherwise, find scores for the current player (and list them
407.   * if argc == -1).
408.   */
409.  void
410.  prscore(argc,argv)
411.  int argc;
412.  char **argv;
413.  {
414.  	char **players;
415.  	int playerct;
416.  	int rank;
417.  	register struct toptenentry *t1, *t2;
418.  	char *recfile = RECORD;
419.  	FILE *rfile;
420.  	register int flg = 0, i;
421.  #ifdef nonsense
422.  	long total_score = 0L;
423.  	char totchars[10];
424.  	int totcharct = 0;
425.  #endif
426.  	int outflg = (argc >= -1);
427.  #ifdef PERS_IS_UID
428.  	int uid = -1;
429.  #else
430.  	char *player0;
431.  #endif
432.  
433.  	if(!(rfile = fopen(recfile,"r"))){
434.  		(void) puts("Cannot open record file!");
435.  		return;
436.  	}
437.  
438.  	if(argc > 1 && !strncmp(argv[1], "-s", 2)){
439.  		if(!argv[1][2]){
440.  			argc--;
441.  			argv++;
442.  		} else if(!argv[1][3] && index("ABCEHKPRSTVW", argv[1][2])) {
443.  			argv[1]++;
444.  			argv[1][0] = '-';
445.  		} else	argv[1] += 2;
446.  	}
447.  	if(argc <= 1){
448.  #ifdef PERS_IS_UID
449.  		uid = getuid();
450.  		playerct = 0;
451.  #else
452.  		player0 = plname;
453.  		if(!*player0)
454.  			player0 = "hackplayer";
455.  		playerct = 1;
456.  		players = &player0;
457.  #endif
458.  	} else {
459.  		playerct = --argc;
460.  		players = ++argv;
461.  	}
462.  	if(outflg) (void) putchar('\n');
463.  
464.  	t1 = tt_head = newttentry();
465.  	for(rank = 1; ; rank++) {
466.  #ifdef TOS
467.  	  char k1[2], k2[2];
468.  	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %1s%1s %s %s]",
469.  #else
470.  	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
471.  #endif
472.  		t1->date, &t1->uid,
473.  		&t1->level, &t1->maxlvl,
474.  		&t1->hp, &t1->maxhp, &t1->points,
475.  #ifdef TOS
476.  		k1, k2,
477.  #else
478.  		&t1->plchar, &t1->sex,
479.  #endif
480.  		t1->name, t1->death) != 11)
481.  			t1->points = 0;
482.  	  if(t1->points == 0) break;
483.  #ifdef TOS
484.  	  t1->plchar=k1[0];
485.  	  t1->sex=k2[0];
486.  #endif
487.  #ifdef PERS_IS_UID
488.  	  if(!playerct && t1->uid == uid)
489.  		flg++;
490.  	  else
491.  #endif
492.  	  for(i = 0; i < playerct; i++){
493.  		if(strcmp(players[i], "all") == 0 ||
494.  		   strncmp(t1->name, players[i], NAMSZ) == 0 ||
495.  		  (players[i][0] == '-' &&
496.  		   players[i][1] == t1->plchar &&
497.  		   players[i][2] == 0) ||
498.  		  (digit(players[i][0]) && rank <= atoi(players[i])))
499.  			flg++;
500.  	  }
501.  	  t1 = t1->tt_next = newttentry();
502.  	}
503.  	(void) fclose(rfile);
504.  	if(!flg) {
505.  	    if(outflg) {
506.  		Printf("Cannot find any entries for ");
507.  		if(playerct < 1) Printf("you.\n");
508.  		else {
509.  		  if(playerct > 1) Printf("any of ");
510.  		  for(i=0; i<playerct; i++)
511.  			Printf("%s%s", players[i], (i<playerct-1)?", ":".\n");
512.  		  Printf("Call is: %s -s [-role] [maxrank] [playernames]\n", hname);
513.  		}
514.  	    }
515.  	    return;
516.  	}
517.  
518.  	if(outflg) outheader();
519.  	t1 = tt_head;
520.  	for(rank = 1; t1->points != 0; rank++, t1 = t2) {
521.  		t2 = t1->tt_next;
522.  #ifdef PERS_IS_UID
523.  		if(!playerct && t1->uid == uid)
524.  			goto outwithit;
525.  		else
526.  #endif
527.  		for(i = 0; i < playerct; i++){
528.  			if(strcmp(players[i], "all") == 0 ||
529.  			   strncmp(t1->name, players[i], NAMSZ) == 0 ||
530.  			  (players[i][0] == '-' &&
531.  			   players[i][1] == t1->plchar &&
532.  			   players[i][2] == 0) ||
533.  			  (digit(players[i][0]) && rank <= atoi(players[i]))){
534.  			outwithit:
535.  				if(outflg)
536.  				    (void) outentry(rank, t1, 0);
537.  #ifdef nonsense
538.  				total_score += t1->points;
539.  				if(totcharct < sizeof(totchars)-1)
540.  				    totchars[totcharct++] = t1->plchar;
541.  #endif
542.  				break;
543.  			}
544.  		}
545.  		free((genericptr_t) t1);
546.  	}
547.  #ifdef nonsense
548.  	totchars[totcharct] = 0;
549.  
550.  	/* We would like to determine whether he is experienced. However,
551.  	   the information collected here only tells about the scores/roles
552.  	   that got into the topten (top 100?). We should maintain a
553.  	   .hacklog or something in his home directory. */
554.  	flags.beginner = (total_score < 6000);
555.  	for(i=0; i<6; i++)
556.  	    if(!index(totchars, "ABCEHKPRSTVW"[i])) {
557.  		flags.beginner = 1;
558.  		if(!pl_character[0]) pl_character[0] = "ABCEHKPRSTVW"[i];
559.  		break;
560.  	}
561.  #endif /* nonsense /**/
562.  }
563.  
564.  static int
565.  classmon(plch, fem)
566.  char plch;
567.  boolean fem;
568.  {
569.  	switch (plch) {
570.  		case 'A': return PM_ARCHEOLOGIST;
571.  		case 'B': return PM_BARBARIAN;
572.  		case 'C': return (fem ? PM_CAVEWOMAN : PM_CAVEMAN);
573.  		case 'E': return PM_ELF;
574.  		case 'H': return PM_HEALER;
575.  		case 'F':	/* accept old Fighter class */
576.  		case 'K': return PM_KNIGHT;
577.  		case 'P': return (fem ? PM_PRIESTESS : PM_PRIEST);
578.  		case 'R': return PM_ROGUE;
579.  		case 'N':	/* accept old Ninja class */
580.  		case 'S': return PM_SAMURAI;
581.  		case 'T': return PM_TOURIST;
582.  		case 'V': return PM_VALKYRIE;
583.  		case 'W': return PM_WIZARD;
584.  		default: impossible("What weird class is this? (%c)", plch);
585.  			return PM_HUMAN_ZOMBIE;
586.  	}
587.  }
588.  
589.  /*
590.   * Get a random player name and class from the high score list,
591.   * and attach them to an object (for statues or morgue corpses).
592.   */
593.  struct obj *
594.  tt_oname(otmp)
595.  struct obj *otmp;
596.  {
597.  	int rank;
598.  	register int i;
599.  	register struct toptenentry *tt;
600.  	char *recfile = RECORD;
601.  	FILE *rfile;
602.  
603.  	if (!otmp) return((struct obj *) 0);
604.  
605.  	if(!(rfile = fopen(recfile,"r")))
606.  		panic("Cannot open record file!");
607.  
608.  	tt = newttentry();
609.  	rank = rnd(10);
610.  pickentry:
611.  	for(i = rank; i; i--) {
612.  #ifdef TOS
613.  	  char k1[2], k2[2];
614.  	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %1s%1s %s %s]",
615.  #else
616.  	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
617.  #endif
618.  		tt->date, &tt->uid,
619.  		&tt->level, &tt->maxlvl,
620.  		&tt->hp, &tt->maxhp, &tt->points,
621.  #ifdef TOS
622.  		k1, k2,
623.  #else
624.  		&tt->plchar, &tt->sex,
625.  #endif
626.  		tt->name, tt->death) != 11)
627.  			tt->points = 0;
628.  	  if(tt->points == 0) break;
629.  #ifdef TOS
630.  	  tt->plchar=k1[0];
631.  	  tt->sex=k2[0];
632.  #endif
633.  	}
634.  	(void) fclose(rfile);
635.  
636.  	if(tt->points == 0) {
637.  		if(rank > 1) {
638.  			rank = 1;
639.  			goto pickentry;
640.  		}
641.  		free((genericptr_t) tt);
642.  		return((struct obj *) 0);
643.  	} else {
644.  		otmp->corpsenm = classmon(tt->plchar, (tt->sex == 'F'));
645.  		otmp->owt = mons[otmp->corpsenm].cwt;
646.  		otmp = oname(otmp, tt->name, 0);
647.  		free((genericptr_t) tt);
648.  		return otmp;
649.  	}
650.  }