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