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