Source:NetHack 2.2a/topten.c

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