1/* $NetBSD: score.c,v 1.22 2009/08/03 06:04:12 dholland 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. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33#ifndef lint 34#if 0 35static char sccsid[] = "@(#)score.c 8.1 (Berkeley) 5/31/93"; 36#else 37__RCSID("$NetBSD: score.c,v 1.22 2009/08/03 06:04:12 dholland Exp $"); 38#endif 39#endif /* not lint */ 40 41#include <curses.h> 42#include <err.h> 43#include <fcntl.h> 44#include <pwd.h> 45#include <stdio.h> 46#include <stdlib.h> 47#include <string.h> 48#include <unistd.h> 49#include "robots.h" 50#include "pathnames.h" 51 52const char *Scorefile = _PATH_SCORE; 53 54int Max_per_uid = MAX_PER_UID; 55 56static SCORE Top[MAXSCORES]; 57 58static uint32_t numscores, max_uid; 59 60static int cmp_sc(const void *, const void *); 61static void set_name(SCORE *); 62 63/* 64 * read_score: 65 * Read the score file in MI format 66 */ 67static void 68read_score(int inf) 69{ 70 SCORE *scp; 71 72 if (read(inf, &max_uid, sizeof max_uid) == sizeof max_uid && 73 read(inf, Top, sizeof Top) == sizeof Top) { 74 max_uid = ntohl(max_uid); 75 for (scp = Top; scp < &Top[MAXSCORES]; scp++) { 76 scp->s_uid = ntohl(scp->s_uid); 77 scp->s_score = ntohl(scp->s_score); 78 scp->s_auto = ntohl(scp->s_auto); 79 scp->s_level = ntohl(scp->s_level); 80 } 81 } 82 else { 83 for (scp = Top; scp < &Top[MAXSCORES]; scp++) 84 scp->s_score = 0; 85 max_uid = Max_per_uid; 86 } 87} 88 89/* 90 * write_score: 91 * Write the score file in MI format 92 */ 93static void 94write_score(int inf) 95{ 96 SCORE *scp; 97 98 lseek(inf, 0L, SEEK_SET); 99 100 max_uid = htonl(max_uid); 101 write(inf, &max_uid, sizeof max_uid); 102 103 for (scp = Top; scp < &Top[MAXSCORES]; scp++) { 104 scp->s_uid = htonl(scp->s_uid); 105 scp->s_score = htonl(scp->s_score); 106 scp->s_auto = htonl(scp->s_auto); 107 scp->s_level = htonl(scp->s_level); 108 } 109 110 write(inf, Top, sizeof Top); 111} 112 113 114/* 115 * score: 116 * Post the player's score, if reasonable, and then print out the 117 * top list. 118 */ 119void 120score(int score_wfd) 121{ 122 int inf = score_wfd; 123 SCORE *scp; 124 uint32_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 195static void 196set_name(SCORE *scp) 197{ 198 struct passwd *pp; 199 200 if ((pp = getpwuid(scp->s_uid)) == NULL) 201 strncpy(scp->s_name, "???", MAXNAME); 202 else 203 strncpy(scp->s_name, pp->pw_name, MAXNAME); 204} 205 206/* 207 * cmp_sc: 208 * Compare two scores. 209 */ 210static int 211cmp_sc(const void *s1, const void *s2) 212{ 213 return ((const SCORE *)s2)->s_score - ((const SCORE *)s1)->s_score; 214} 215 216/* 217 * show_score: 218 * Show the score list for the '-s' option. 219 */ 220void 221show_score(void) 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("%5d %5d %-8.8s %-9.9s %5d\n", 239 inf++, scp->s_score, scp->s_name, 240 scp->s_auto ? "(autobot)" : "", scp->s_level); 241} 242