Source:NetHack 1.3d/topten.c

From NetHackWiki
Revision as of 00:32, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 1.3d/topten.c moved to Source:NetHack 1.3d/topten.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

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

Screenshots and source code from Hack are used under the CWI license.

1.    /*	SCCS Id: @(#)topten.c	1.3	87/07/14
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* topten.c - version 1.0 */
4.    
5.    #include <stdio.h>
6.    #include "hack.h"
7.    #define	Sprintf	(void) sprintf
8.    extern char plname[], pl_character[];
9.    extern char *itoa(), *ordin(), *eos();
10.   extern int done_hup, done_stopprint;
11.   
12.   #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
13.   #define	NAMSZ	10
14.   #define	DTHSZ	40
15.   #define	PERSMAX	 3
16.   #define	POINTSMIN	1	/* must be > 0 */
17.   #define	ENTRYMAX	100	/* must be >= 10 */
18.   #ifndef MSDOS
19.   #define	PERS_IS_UID		/* delete for PERSMAX per name; now per uid */
20.   #endif
21.   struct toptenentry {
22.   	struct toptenentry *tt_next;
23.   	long int points;
24.   	int level,maxlvl,hp,maxhp;
25.   	int uid;
26.   	char plchar;
27.   	char sex;
28.   	char name[NAMSZ+1];
29.   	char death[DTHSZ+1];
30.   	char date[7];		/* yymmdd */
31.   } *tt_head;
32.   
33.   topten(){
34.   	int uid = getuid();
35.   	int rank, rank0 = -1, rank1 = 0;
36.   	int occ_cnt = PERSMAX;
37.   	register struct toptenentry *t0, *t1, *tprev;
38.   	char *recfile = RECORD;
39.   #ifdef UNIX
40.   	char *reclock = "record_lock";
41.   #endif
42.   	int sleepct = 300;
43.   	FILE *rfile;
44.   	register flg = 0;
45.   	extern char *getdate();
46.   #ifndef DGK
47.   #define	HUP	if(!done_hup)
48.   #else
49.   #define
50.   #endif
51.   #ifdef UNIX
52.   	while(link(recfile, reclock) == -1) {
53.   		HUP perror(reclock);
54.   		if(!sleepct--) {
55.   			HUP puts("I give up. Sorry.");
56.   			HUP puts("Perhaps there is an old record_lock around?");
57.   			return;
58.   		}
59.   		HUP printf("Waiting for access to record file. (%d)\n",
60.   			sleepct);
61.   		HUP (void) fflush(stdout);
62.   		sleep(1);
63.   	}
64.   #endif
65.   	if(!(rfile = fopen(recfile,"r"))){
66.   		HUP puts("Cannot open record file!");
67.   		goto unlock;
68.   	}
69.   	HUP (void) putchar('\n');
70.   
71.   	/* create a new 'topten' entry */
72.   	t0 = newttentry();
73.   	t0->level = dlevel;
74.   	t0->maxlvl = maxdlevel;
75.   	t0->hp = u.uhp;
76.   	t0->maxhp = u.uhpmax;
77.   	t0->points = u.urexp;
78.   	t0->plchar = pl_character[0];
79.   	t0->sex = (flags.female ? 'F' : 'M');
80.   	t0->uid = uid;
81.   	(void) strncpy(t0->name, plname, NAMSZ);
82.   	(t0->name)[NAMSZ] = 0;
83.   	(void) strncpy(t0->death, killer, DTHSZ);
84.   	(t0->death)[DTHSZ] = 0;
85.   	(void) strcpy(t0->date, getdate());
86.   
87.   	/* assure minimum number of points */
88.   	if(t0->points < POINTSMIN)
89.   		t0->points = 0;
90.   
91.   	t1 = tt_head = newttentry();
92.   	tprev = 0;
93.   	/* rank0: -1 undefined, 0 not_on_list, n n_th on list */
94.   	for(rank = 1; ; ) {
95.   	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
96.   		t1->date, &t1->uid,
97.   		&t1->level, &t1->maxlvl,
98.   		&t1->hp, &t1->maxhp, &t1->points,
99.   		&t1->plchar, &t1->sex, t1->name, t1->death) != 11
100.  	  || t1->points < POINTSMIN)
101.  			t1->points = 0;
102.  	  if(rank0 < 0 && t1->points < t0->points) {
103.  		rank0 = rank++;
104.  		if(tprev == 0)
105.  			tt_head = t0;
106.  		else
107.  			tprev->tt_next = t0;
108.  		t0->tt_next = t1;
109.  		occ_cnt--;
110.  		flg++;		/* ask for a rewrite */
111.  	  } else
112.  		tprev = t1;
113.  	  if(t1->points == 0) break;
114.  	  if(
115.  #ifdef PERS_IS_UID
116.  	     t1->uid == t0->uid &&
117.  #else
118.  	     strncmp(t1->name, t0->name, NAMSZ) == 0 &&
119.  #endif
120.  	     t1->plchar == t0->plchar && --occ_cnt <= 0){
121.  		if(rank0 < 0){
122.  			rank0 = 0;
123.  			rank1 = rank;
124.  	HUP printf("You didn't beat your previous score of %ld points.\n\n",
125.  				t1->points);
126.  		}
127.  		if(occ_cnt < 0){
128.  			flg++;
129.  			continue;
130.  		}
131.  	  }
132.  	  if(rank <= ENTRYMAX){
133.  		t1 = t1->tt_next = newttentry();
134.  		rank++;
135.  	  }
136.  	  if(rank > ENTRYMAX){
137.  		t1->points = 0;
138.  		break;
139.  	  }
140.  	}
141.  	if(flg) {	/* rewrite record file */
142.  		(void) fclose(rfile);
143.  		if(!(rfile = fopen(recfile,"w"))){
144.  			HUP puts("Cannot write record file\n");
145.  			goto unlock;
146.  		}
147.  
148.  		if(!done_stopprint) if(rank0 > 0){
149.  		    if(rank0 <= 10)
150.  			puts("You made the top ten list!\n");
151.  		    else
152.  		printf("You reached the %d%s place on the top %d list.\n\n",
153.  			rank0, ordin(rank0), ENTRYMAX);
154.  		}
155.  	}
156.  	if(rank0 == 0) rank0 = rank1;
157.  	if(rank0 <= 0) rank0 = rank;
158.  	if(!done_stopprint) outheader();
159.  	t1 = tt_head;
160.  	for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
161.  	  if(flg) fprintf(rfile,"%6s %d %d %d %d %d %ld %c%c %s,%s\n",
162.  	    t1->date, t1->uid,
163.  	    t1->level, t1->maxlvl,
164.  	    t1->hp, t1->maxhp, t1->points,
165.  	    t1->plchar, t1->sex, t1->name, t1->death);
166.  	  if(done_stopprint) continue;
167.  	  if(rank > flags.end_top &&
168.  	    (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
169.  	    && (!flags.end_own ||
170.  #ifdef PERS_IS_UID
171.  				  t1->uid != t0->uid ))
172.  #else
173.  				  strncmp(t1->name, t0->name, NAMSZ)))
174.  #endif
175.  		continue;
176.  	  if(rank == rank0-flags.end_around &&
177.  	     rank0 > flags.end_top+flags.end_around+1 &&
178.  	     !flags.end_own)
179.  		(void) putchar('\n');
180.  	  if(rank != rank0)
181.  		(void) outentry(rank, t1, 0);
182.  	  else if(!rank1)
183.  		(void) outentry(rank, t1, 1);
184.  	  else {
185.  		int t0lth = outentry(0, t0, -1);
186.  		int t1lth = outentry(rank, t1, t0lth);
187.  		if(t1lth > t0lth) t0lth = t1lth;
188.  		(void) outentry(0, t0, t0lth);
189.  	  }
190.  	}
191.  	if(rank0 >= rank) if(!done_stopprint)
192.  		(void) outentry(0, t0, 1);
193.  	(void) fclose(rfile);
194.  unlock:	;
195.  #ifdef UNIX
196.  	(void) unlink(reclock);
197.  #endif
198.  }
199.  
200.  outheader() {
201.  char linebuf[BUFSZ];
202.  register char *bp;
203.  	(void) strcpy(linebuf, "Number Points  Name");
204.  	bp = eos(linebuf);
205.  	while(bp < linebuf + COLNO - 9) *bp++ = ' ';
206.  	(void) strcpy(bp, "Hp [max]");
207.  	puts(linebuf);
208.  }
209.  
210.  /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
211.  int
212.  outentry(rank,t1,so) register struct toptenentry *t1; {
213.  boolean quit = FALSE, killed = FALSE, starv = FALSE;
214.  char linebuf[BUFSZ];
215.  	linebuf[0] = 0;
216.  	if(rank) Sprintf(eos(linebuf), "%3d", rank);
217.  		else Sprintf(eos(linebuf), "   ");
218.  #ifdef DGKMOD
219.  	Sprintf(eos(linebuf), " %6ld %10s", t1->points, t1->name);
220.  #else
221.  	Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->name);
222.  #endif
223.  	if(t1->plchar == 'X') Sprintf(eos(linebuf), " ");
224.  	else Sprintf(eos(linebuf), "-%c ", t1->plchar);
225.  	if(!strncmp("escaped", t1->death, 7)) {
226.  	  if(!strcmp(" (with amulet)", t1->death+7))
227.  	    Sprintf(eos(linebuf), "escaped the dungeon with amulet");
228.  	  else
229.  	    Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
230.  	      t1->maxlvl);
231.  	} else {
232.  	  if(!strncmp(t1->death,"quit",4)) {
233.  	    quit = TRUE;
234.  	    if(t1->maxhp < 3*t1->hp && t1->maxlvl < 4)
235.  		Sprintf(eos(linebuf), "cravenly gave up");
236.  	    else
237.  		Sprintf(eos(linebuf), "quit");
238.  	  }
239.  	  else if(!strcmp(t1->death,"choked"))
240.  	    Sprintf(eos(linebuf), "choked on %s food",
241.  		(t1->sex == 'F') ? "her" : "his");
242.  	  else if(!strncmp(t1->death,"starv",5))
243.  	    Sprintf(eos(linebuf), "starved to death"), starv = TRUE;
244.  	  else Sprintf(eos(linebuf), "was killed"), killed = TRUE;
245.  	  Sprintf(eos(linebuf), " on%s level %d",
246.  	    (killed || starv) ? "" : " dungeon", t1->level);
247.  	  if(t1->maxlvl != t1->level)
248.  	    Sprintf(eos(linebuf), " [max %d]", t1->maxlvl);
249.  	  if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4);
250.  	}
251.  	if(killed) Sprintf(eos(linebuf), " by %s%s",
252.  	  (!strncmp(t1->death, "trick", 5) || !strncmp(t1->death, "the ", 4))
253.  		? "" :
254.  	  index(vowels,*t1->death) ? "an " : "a ",
255.  	  t1->death);
256.  	Sprintf(eos(linebuf), ".");
257.  	if(t1->maxhp) {
258.  	  register char *bp = eos(linebuf);
259.  	  char hpbuf[10];
260.  	  int hppos;
261.  	  Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-");
262.  	  hppos = COLNO - 7 - strlen(hpbuf);
263.  	  if(bp <= linebuf + hppos) {
264.  	    while(bp < linebuf + hppos) *bp++ = ' ';
265.  	    (void) strcpy(bp, hpbuf);
266.  	    Sprintf(eos(bp), " [%d]", t1->maxhp);
267.  	  }
268.  	}
269.  	if(so == 0) puts(linebuf);
270.  	else if(so > 0) {
271.  	  register char *bp = eos(linebuf);
272.  	  if(so >= COLNO) so = COLNO-1;
273.  	  while(bp < linebuf + so) *bp++ = ' ';
274.  	  *bp = 0;
275.  	  standoutbeg();
276.  	  fputs(linebuf,stdout);
277.  	  standoutend();
278.  	  (void) putchar('\n');
279.  	}
280.  	return(strlen(linebuf));
281.  }
282.  
283.  char *
284.  itoa(a) int a; {
285.  static char buf[12];
286.  	Sprintf(buf,"%d",a);
287.  	return(buf);
288.  }
289.  
290.  char *
291.  ordin(n) int n; {
292.  register int d = n%10;
293.  	return((d==0 || d>3 || n/10==1) ? "th" : (d==1) ? "st" :
294.  		(d==2) ? "nd" : "rd");
295.  }
296.  
297.  char *
298.  eos(s)
299.  register char *s;
300.  {
301.  	while(*s) s++;
302.  	return(s);
303.  }
304.  
305.  /*
306.   * Called with args from main if argc >= 0. In this case, list scores as
307.   * requested. Otherwise, find scores for the current player (and list them
308.   * if argc == -1).
309.   */
310.  prscore(argc,argv) int argc; char **argv; {
311.  	extern char *hname;
312.  	char **players;
313.  	int playerct;
314.  	int rank;
315.  	register struct toptenentry *t1, *t2;
316.  	char *recfile = RECORD;
317.  	FILE *rfile;
318.  	register flg = 0;
319.  	register int i;
320.  #ifdef nonsense
321.  	long total_score = 0L;
322.  	char totchars[10];
323.  	int totcharct = 0;
324.  #endif
325.  	int outflg = (argc >= -1);
326.  #ifdef PERS_IS_UID
327.  	int uid = -1;
328.  #else
329.  	char *player0;
330.  #endif
331.  
332.  	if(!(rfile = fopen(recfile,"r"))){
333.  		puts("Cannot open record file!");
334.  		return;
335.  	}
336.  
337.  	if(argc > 1 && !strncmp(argv[1], "-s", 2)){
338.  		if(!argv[1][2]){
339.  			argc--;
340.  			argv++;
341.  		} else if(!argv[1][3] && index("CFKSTWX", argv[1][2])) {
342.  			argv[1]++;
343.  			argv[1][0] = '-';
344.  		} else	argv[1] += 2;
345.  	}
346.  	if(argc <= 1){
347.  #ifdef PERS_IS_UID
348.  		uid = getuid();
349.  		playerct = 0;
350.  #else
351.  		player0 = plname;
352.  		if(!*player0)
353.  			player0 = "hackplayer";
354.  		playerct = 1;
355.  		players = &player0;
356.  #endif
357.  	} else {
358.  		playerct = --argc;
359.  		players = ++argv;
360.  	}
361.  	if(outflg) putchar('\n');
362.  
363.  	t1 = tt_head = newttentry();
364.  	for(rank = 1; ; rank++) {
365.  	  if(fscanf(rfile, "%6s %d %d %d %d %d %ld %c%c %[^,],%[^\n]",
366.  		t1->date, &t1->uid,
367.  		&t1->level, &t1->maxlvl,
368.  		&t1->hp, &t1->maxhp, &t1->points,
369.  		&t1->plchar, &t1->sex, t1->name, t1->death) != 11)
370.  			t1->points = 0;
371.  	  if(t1->points == 0) break;
372.  #ifdef PERS_IS_UID
373.  	  if(!playerct && t1->uid == uid)
374.  		flg++;
375.  	  else
376.  #endif
377.  	  for(i = 0; i < playerct; i++){
378.  		if(strcmp(players[i], "all") == 0 ||
379.  		   strncmp(t1->name, players[i], NAMSZ) == 0 ||
380.  		  (players[i][0] == '-' &&
381.  		   players[i][1] == t1->plchar &&
382.  		   players[i][2] == 0) ||
383.  		  (digit(players[i][0]) && rank <= atoi(players[i])))
384.  			flg++;
385.  	  }
386.  	  t1 = t1->tt_next = newttentry();
387.  	}
388.  	(void) fclose(rfile);
389.  	if(!flg) {
390.  	    if(outflg) {
391.  		printf("Cannot find any entries for ");
392.  		if(playerct < 1) printf("you.\n");
393.  		else {
394.  		  if(playerct > 1) printf("any of ");
395.  		  for(i=0; i<playerct; i++)
396.  			printf("%s%s", players[i], (i<playerct-1)?", ":".\n");
397.  		  printf("Call is: %s -s [playernames]\n", hname);
398.  		}
399.  	    }
400.  	    return;
401.  	}
402.  
403.  	if(outflg) outheader();
404.  	t1 = tt_head;
405.  	for(rank = 1; t1->points != 0; rank++, t1 = t2) {
406.  		t2 = t1->tt_next;
407.  #ifdef PERS_IS_UID
408.  		if(!playerct && t1->uid == uid)
409.  			goto outwithit;
410.  		else
411.  #endif
412.  		for(i = 0; i < playerct; i++){
413.  			if(strcmp(players[i], "all") == 0 ||
414.  			   strncmp(t1->name, players[i], NAMSZ) == 0 ||
415.  			  (players[i][0] == '-' &&
416.  			   players[i][1] == t1->plchar &&
417.  			   players[i][2] == 0) ||
418.  			  (digit(players[i][0]) && rank <= atoi(players[i]))){
419.  			outwithit:
420.  				if(outflg)
421.  				    (void) outentry(rank, t1, 0);
422.  #ifdef nonsense
423.  				total_score += t1->points;
424.  				if(totcharct < sizeof(totchars)-1)
425.  				    totchars[totcharct++] = t1->plchar;
426.  #endif
427.  				break;
428.  			}
429.  		}
430.  		free((char *) t1);
431.  	}
432.  #ifdef nonsense
433.  	totchars[totcharct] = 0;
434.  
435.  	/* We would like to determine whether he is experienced. However,
436.  	   the information collected here only tells about the scores/roles
437.  	   that got into the topten (top 100?). We should maintain a
438.  	   .hacklog or something in his home directory. */
439.  	flags.beginner = (total_score < 6000);
440.  	for(i=0; i<6; i++)
441.  	    if(!index(totchars, "CFKSTWX"[i])) {
442.  		flags.beginner = 1;
443.  		if(!pl_character[0]) pl_character[0] = "CFKSTWX"[i];
444.  		break;
445.  	}
446.  #endif /* nonsense /**/
447.  }