score.c revision 1.4
1/*	$OpenBSD: score.c,v 1.4 1998/07/09 04:34:25 pjanzen Exp $	*/
2/*	$NetBSD: score.c,v 1.3 1995/04/22 10:09:12 cgd Exp $	*/
3
4/*
5 * Copyright (c) 1980, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38#if 0
39static char sccsid[] = "@(#)score.c	8.1 (Berkeley) 5/31/93";
40#else
41static char rcsid[] = "$OpenBSD: score.c,v 1.4 1998/07/09 04:34:25 pjanzen Exp $";
42#endif
43#endif /* not lint */
44
45#include	"robots.h"
46#include	"pathnames.h"
47
48char	*Scorefile = _PATH_SCORE;
49
50#ifndef MAX_PER_UID
51#define MAX_PER_UID	5
52#endif
53
54int	Max_per_uid = MAX_PER_UID;
55
56static SCORE	Top[MAXSCORES];
57
58/*
59 * score:
60 *	Post the player's score, if reasonable, and then print out the
61 *	top list.
62 */
63void
64score(score_wfd)
65     int score_wfd;
66{
67	register int	inf = score_wfd;
68	register SCORE	*scp;
69	uid_t	uid;
70	register bool	done_show = FALSE;
71	static int	numscores, max_uid;
72
73	Newscore = FALSE;
74
75	if (read(inf, &max_uid, sizeof max_uid) == sizeof max_uid)
76		read(inf, Top, sizeof Top);
77	else {
78		for (scp = Top; scp < &Top[MAXSCORES]; scp++)
79			scp->s_score = -1;
80		max_uid = Max_per_uid;
81	}
82
83	uid = getuid();
84	if (Top[MAXSCORES-1].s_score <= Score) {
85		numscores = 0;
86		for (scp = Top; scp < &Top[MAXSCORES]; scp++)
87			if (scp->s_score < 0 ||
88			    (scp->s_uid == uid && ++numscores == max_uid)) {
89				if (scp->s_score > Score)
90					break;
91				scp->s_score = Score;
92				scp->s_uid = uid;
93				set_name(scp);
94				Newscore = TRUE;
95				break;
96			}
97		if (scp == &Top[MAXSCORES]) {
98			Top[MAXSCORES-1].s_score = Score;
99			Top[MAXSCORES-1].s_uid = uid;
100			set_name(&Top[MAXSCORES-1]);
101			Newscore = TRUE;
102		}
103		if (Newscore)
104			qsort(Top, MAXSCORES, sizeof Top[0], cmp_sc);
105	}
106
107	if (!Newscore) {
108		Full_clear = FALSE;
109		fsync(inf);
110		lseek(inf, 0, SEEK_SET);
111		return;
112	}
113	else
114		Full_clear = TRUE;
115
116	for (scp = Top; scp < &Top[MAXSCORES]; scp++) {
117		if (scp->s_score < 0)
118			break;
119		move((scp - Top) + 1, 15);
120		if (!done_show && scp->s_uid == uid && scp->s_score == Score)
121			standout();
122		printw(" %d\t%d\t%-*s ", (scp - Top) + 1, scp->s_score,
123			(int)(sizeof scp->s_name), scp->s_name);
124		if (!done_show && scp->s_uid == uid && scp->s_score == Score) {
125			standend();
126			done_show = TRUE;
127		}
128	}
129	Num_scores = scp - Top;
130	refresh();
131
132	if (Newscore) {
133		lseek(inf, 0L, SEEK_SET);
134		write(inf, &max_uid, sizeof max_uid);
135		write(inf, Top, sizeof Top);
136	}
137	fsync(inf);
138	lseek(inf, 0, SEEK_SET);
139}
140
141void
142set_name(scp)
143	SCORE	*scp;
144{
145	PASSWD	*pp;
146
147	if ((pp = getpwuid(scp->s_uid)) == NULL)
148		pp->pw_name = "???";
149	strncpy(scp->s_name, pp->pw_name, MAXNAME);
150}
151
152/*
153 * cmp_sc:
154 *	Compare two scores.
155 */
156int
157cmp_sc(s1, s2)
158	const void	*s1, *s2;
159{
160	return ((SCORE *)s2)->s_score - ((SCORE *)s1)->s_score;
161}
162
163/*
164 * show_score:
165 *	Show the score list for the '-s' option.
166 */
167void
168show_score()
169{
170	register SCORE	*scp;
171	register int	inf;
172	static int	max_score;
173
174	if ((inf = open(Scorefile, O_RDONLY)) < 0) {
175		perror(Scorefile);
176		return;
177	}
178
179	for (scp = Top; scp < &Top[MAXSCORES]; scp++)
180		scp->s_score = -1;
181
182	read(inf, &max_score, sizeof max_score);
183	read(inf, Top, sizeof Top);
184	close(inf);
185	inf = 1;
186	for (scp = Top; scp < &Top[MAXSCORES]; scp++)
187		if (scp->s_score >= 0)
188			printf("%d\t%d\t%.*s\n", inf++, scp->s_score,
189				(int)(sizeof scp->s_name), scp->s_name);
190}
191