1 /* $NetBSD: score.c,v 1.15 2000/04/27 19:31:23 thorpej 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.15 2000/04/27 19:31:23 thorpej Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 # include "robots.h" 46 # include "pathnames.h" 47 48 const 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 static void read_score __P((int)); 57 static void write_score __P((int)); 58 59 /* 60 * read_score: 61 * Read the score file in MI format 62 */ 63 static void 64 read_score(inf) 65 int inf; 66 { 67 SCORE *scp; 68 69 if (read(inf, &max_uid, sizeof max_uid) == sizeof max_uid) { 70 max_uid = ntohl(max_uid); 71 72 read(inf, Top, sizeof Top); 73 for (scp = Top; scp < &Top[MAXSCORES]; scp++) { 74 scp->s_uid = ntohl(scp->s_uid); 75 scp->s_score = ntohl(scp->s_score); 76 scp->s_auto = ntohl(scp->s_auto); 77 scp->s_level = ntohl(scp->s_level); 78 } 79 } 80 else { 81 for (scp = Top; scp < &Top[MAXSCORES]; scp++) 82 scp->s_score = 0; 83 max_uid = Max_per_uid; 84 } 85 } 86 87 /* 88 * write_score: 89 * Write the score file in MI format 90 */ 91 static void 92 write_score(inf) 93 int inf; 94 { 95 SCORE *scp; 96 97 lseek(inf, 0L, SEEK_SET); 98 99 max_uid = htonl(max_uid); 100 write(inf, &max_uid, sizeof max_uid); 101 102 for (scp = Top; scp < &Top[MAXSCORES]; scp++) { 103 scp->s_uid = htonl(scp->s_uid); 104 scp->s_score = htonl(scp->s_score); 105 scp->s_auto = htonl(scp->s_auto); 106 scp->s_level = htonl(scp->s_level); 107 } 108 109 write(inf, Top, sizeof Top); 110 } 111 112 113 /* 114 * score: 115 * Post the player's score, if reasonable, and then print out the 116 * top list. 117 */ 118 void 119 score(score_wfd) 120 int score_wfd; 121 { 122 int inf = score_wfd; 123 SCORE *scp; 124 u_int32_t uid; 125 bool done_show = FALSE; 126 127 Newscore = FALSE; 128 if (inf < 0) 129 return; 130 131 read_score(inf); 132 133 uid = getuid(); 134 if (Top[MAXSCORES-1].s_score <= Score) { 135 numscores = 0; 136 for (scp = Top; scp < &Top[MAXSCORES]; scp++) 137 if ((scp->s_uid == uid && ++numscores == max_uid)) { 138 if (scp->s_score > Score) 139 break; 140 scp->s_score = Score; 141 scp->s_uid = uid; 142 scp->s_auto = Auto_bot; 143 scp->s_level = Level; 144 set_name(scp); 145 Newscore = TRUE; 146 break; 147 } 148 if (scp == &Top[MAXSCORES]) { 149 Top[MAXSCORES-1].s_score = Score; 150 Top[MAXSCORES-1].s_uid = uid; 151 Top[MAXSCORES-1].s_auto = Auto_bot; 152 Top[MAXSCORES-1].s_level = Level; 153 set_name(&Top[MAXSCORES-1]); 154 Newscore = TRUE; 155 } 156 if (Newscore) 157 qsort(Top, MAXSCORES, sizeof Top[0], cmp_sc); 158 } 159 160 if (!Newscore) { 161 Full_clear = FALSE; 162 lseek(inf, 0, SEEK_SET); 163 return; 164 } 165 else 166 Full_clear = TRUE; 167 168 move(1, 15); 169 printw("%5.5s %5.5s %-9.9s %-8.8s %5.5s", "Rank", "Score", "User", 170 " ", "Level"); 171 172 for (scp = Top; scp < &Top[MAXSCORES]; scp++) { 173 if (scp->s_score == 0) 174 break; 175 move((scp - Top) + 2, 15); 176 if (!done_show && scp->s_uid == uid && scp->s_score == Score) 177 standout(); 178 printw("%5ld %5d %-8.8s %-9.9s %5d", 179 (long)(scp - Top) + 1, scp->s_score, scp->s_name, 180 scp->s_auto ? "(autobot)" : "", scp->s_level); 181 if (!done_show && scp->s_uid == uid && scp->s_score == Score) { 182 standend(); 183 done_show = TRUE; 184 } 185 } 186 Num_scores = scp - Top; 187 refresh(); 188 189 if (Newscore) { 190 write_score(inf); 191 } 192 lseek(inf, 0, SEEK_SET); 193 } 194 195 void 196 set_name(scp) 197 SCORE *scp; 198 { 199 PASSWD *pp; 200 static char unknown[] = "???"; 201 202 if ((pp = getpwuid(scp->s_uid)) == NULL) 203 pp->pw_name = unknown; 204 strncpy(scp->s_name, pp->pw_name, MAXNAME); 205 } 206 207 /* 208 * cmp_sc: 209 * Compare two scores. 210 */ 211 int 212 cmp_sc(s1, s2) 213 const void *s1, *s2; 214 { 215 return ((const SCORE *)s2)->s_score - ((const SCORE *)s1)->s_score; 216 } 217 218 /* 219 * show_score: 220 * Show the score list for the '-s' option. 221 */ 222 void 223 show_score() 224 { 225 SCORE *scp; 226 int inf; 227 228 if ((inf = open(Scorefile, O_RDONLY)) < 0) { 229 warn("opening `%s'", Scorefile); 230 return; 231 } 232 233 read_score(inf); 234 close(inf); 235 inf = 1; 236 printf("%5.5s %5.5s %-9.9s %-8.8s %5.5s\n", "Rank", "Score", "User", 237 " ", "Level"); 238 for (scp = Top; scp < &Top[MAXSCORES]; scp++) 239 if (scp->s_score > 0) 240 printf("%5d %5d %-8.8s %-9.9s %5d\n", 241 inf++, scp->s_score, scp->s_name, 242 scp->s_auto ? "(autobot)" : "", scp->s_level); 243 } 244