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