xref: /openbsd-src/games/robots/score.c (revision aa41ab081c55d8a1e87222abe01b2e13009a5339)
1*aa41ab08Stb /*	$OpenBSD: score.c,v 1.17 2023/10/10 09:48:06 tb Exp $	*/
2df930be7Sderaadt /*	$NetBSD: score.c,v 1.3 1995/04/22 10:09:12 cgd Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*
5df930be7Sderaadt  * Copyright (c) 1980, 1993
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
9df930be7Sderaadt  * modification, are permitted provided that the following conditions
10df930be7Sderaadt  * are met:
11df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
12df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
13df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
14df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
15df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
167a09557bSmillert  * 3. Neither the name of the University nor the names of its contributors
17df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
18df930be7Sderaadt  *    without specific prior written permission.
19df930be7Sderaadt  *
20df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30df930be7Sderaadt  * SUCH DAMAGE.
31df930be7Sderaadt  */
32df930be7Sderaadt 
332010f3c8Smestre #include <fcntl.h>
342010f3c8Smestre #include <stdlib.h>
352010f3c8Smestre #include <string.h>
362010f3c8Smestre #include <unistd.h>
372010f3c8Smestre 
38df930be7Sderaadt #include "robots.h"
39df930be7Sderaadt 
40e224588fStb char	Scorefile[PATH_MAX];
41df930be7Sderaadt 
42d648d61bSpjanzen #ifndef MAX_PER_UID
43d648d61bSpjanzen #define MAX_PER_UID	5
44d648d61bSpjanzen #endif
45d648d61bSpjanzen 
46df930be7Sderaadt int	Max_per_uid = MAX_PER_UID;
47df930be7Sderaadt 
48df930be7Sderaadt static SCORE	Top[MAXSCORES];
49df930be7Sderaadt 
50df930be7Sderaadt /*
51df930be7Sderaadt  * score:
52df930be7Sderaadt  *	Post the player's score, if reasonable, and then print out the
53df930be7Sderaadt  *	top list.
54df930be7Sderaadt  */
55d648d61bSpjanzen void
score(int score_wfd)563eb8c9edSjsg score(int score_wfd)
57df930be7Sderaadt {
5897419aa0Spjanzen 	int	inf = score_wfd;
5997419aa0Spjanzen 	SCORE	*scp;
60d648d61bSpjanzen 	uid_t	uid;
6197419aa0Spjanzen 	bool	done_show = FALSE;
62df930be7Sderaadt 	static int	numscores, max_uid;
63df930be7Sderaadt 
64df930be7Sderaadt 	Newscore = FALSE;
65fdb7e56cSpjanzen 	if (inf < 0)
66fdb7e56cSpjanzen 		return;
67df930be7Sderaadt 
68df930be7Sderaadt 	if (read(inf, &max_uid, sizeof max_uid) == sizeof max_uid)
69df930be7Sderaadt 		read(inf, Top, sizeof Top);
70df930be7Sderaadt 	else {
71df930be7Sderaadt 		for (scp = Top; scp < &Top[MAXSCORES]; scp++)
72df930be7Sderaadt 			scp->s_score = -1;
73df930be7Sderaadt 		max_uid = Max_per_uid;
74df930be7Sderaadt 	}
75df930be7Sderaadt 
76df930be7Sderaadt 	uid = getuid();
77df930be7Sderaadt 	if (Top[MAXSCORES-1].s_score <= Score) {
78df930be7Sderaadt 		numscores = 0;
79df930be7Sderaadt 		for (scp = Top; scp < &Top[MAXSCORES]; scp++)
80df930be7Sderaadt 			if (scp->s_score < 0 ||
81df930be7Sderaadt 			    (scp->s_uid == uid && ++numscores == max_uid)) {
82df930be7Sderaadt 				if (scp->s_score > Score)
83df930be7Sderaadt 					break;
84df930be7Sderaadt 				scp->s_score = Score;
85df930be7Sderaadt 				scp->s_uid = uid;
86df930be7Sderaadt 				set_name(scp);
87df930be7Sderaadt 				Newscore = TRUE;
88df930be7Sderaadt 				break;
89df930be7Sderaadt 			}
90df930be7Sderaadt 		if (scp == &Top[MAXSCORES]) {
91df930be7Sderaadt 			Top[MAXSCORES-1].s_score = Score;
92df930be7Sderaadt 			Top[MAXSCORES-1].s_uid = uid;
93df930be7Sderaadt 			set_name(&Top[MAXSCORES-1]);
94df930be7Sderaadt 			Newscore = TRUE;
95df930be7Sderaadt 		}
96df930be7Sderaadt 		if (Newscore)
97df930be7Sderaadt 			qsort(Top, MAXSCORES, sizeof Top[0], cmp_sc);
98df930be7Sderaadt 	}
99df930be7Sderaadt 
100df930be7Sderaadt 	if (!Newscore) {
101df930be7Sderaadt 		Full_clear = FALSE;
1025f463f57Skstailey 		fsync(inf);
103d648d61bSpjanzen 		lseek(inf, 0, SEEK_SET);
104df930be7Sderaadt 		return;
105df930be7Sderaadt 	}
106df930be7Sderaadt 	else
107df930be7Sderaadt 		Full_clear = TRUE;
108df930be7Sderaadt 
109df930be7Sderaadt 	for (scp = Top; scp < &Top[MAXSCORES]; scp++) {
110df930be7Sderaadt 		if (scp->s_score < 0)
111df930be7Sderaadt 			break;
1121755eb3fStedu 		move((scp - Top) + 1, 6);
113df930be7Sderaadt 		if (!done_show && scp->s_uid == uid && scp->s_score == Score)
114df930be7Sderaadt 			standout();
115*aa41ab08Stb 		printw(" %td\t%d\t%-*s ", (scp - Top) + 1, scp->s_score,
116d648d61bSpjanzen 			(int)(sizeof scp->s_name), scp->s_name);
117df930be7Sderaadt 		if (!done_show && scp->s_uid == uid && scp->s_score == Score) {
118df930be7Sderaadt 			standend();
119df930be7Sderaadt 			done_show = TRUE;
120df930be7Sderaadt 		}
121df930be7Sderaadt 	}
122df930be7Sderaadt 	Num_scores = scp - Top;
123df930be7Sderaadt 	refresh();
124df930be7Sderaadt 
125df930be7Sderaadt 	if (Newscore) {
126d648d61bSpjanzen 		lseek(inf, 0L, SEEK_SET);
127df930be7Sderaadt 		write(inf, &max_uid, sizeof max_uid);
128df930be7Sderaadt 		write(inf, Top, sizeof Top);
129df930be7Sderaadt 	}
1305f463f57Skstailey 	fsync(inf);
131d648d61bSpjanzen 	lseek(inf, 0, SEEK_SET);
132df930be7Sderaadt }
133df930be7Sderaadt 
134d648d61bSpjanzen void
set_name(SCORE * scp)1353eb8c9edSjsg set_name(SCORE *scp)
136df930be7Sderaadt {
13787b7d5d4Stb 	const char	*name;
138df930be7Sderaadt 
13987b7d5d4Stb 	name = getenv("LOGNAME");
14087b7d5d4Stb 	if (name == NULL || *name == '\0')
14187b7d5d4Stb 		name = getenv("USER");
14287b7d5d4Stb 	if (name == NULL || *name == '\0')
14387b7d5d4Stb 		name = getlogin();
14487b7d5d4Stb 	if (name == NULL || *name == '\0')
14587b7d5d4Stb 		name = "  ???";
14687b7d5d4Stb 
14787b7d5d4Stb 	strlcpy(scp->s_name, name, LOGIN_NAME_MAX);
148df930be7Sderaadt }
149df930be7Sderaadt 
150df930be7Sderaadt /*
151df930be7Sderaadt  * cmp_sc:
152df930be7Sderaadt  *	Compare two scores.
153df930be7Sderaadt  */
154d648d61bSpjanzen int
cmp_sc(const void * s1,const void * s2)1553eb8c9edSjsg cmp_sc(const void *s1, const void *s2)
156df930be7Sderaadt {
157d648d61bSpjanzen 	return ((SCORE *)s2)->s_score - ((SCORE *)s1)->s_score;
158df930be7Sderaadt }
159df930be7Sderaadt 
160df930be7Sderaadt /*
161df930be7Sderaadt  * show_score:
162df930be7Sderaadt  *	Show the score list for the '-s' option.
163df930be7Sderaadt  */
164d648d61bSpjanzen void
show_score(void)1653eb8c9edSjsg show_score(void)
166df930be7Sderaadt {
16797419aa0Spjanzen 	SCORE	*scp;
16897419aa0Spjanzen 	int	inf;
169df930be7Sderaadt 	static int	max_score;
170df930be7Sderaadt 
171df69c215Sderaadt 	if ((inf = open(Scorefile, O_RDONLY)) == -1) {
172df930be7Sderaadt 		perror(Scorefile);
173df930be7Sderaadt 		return;
174df930be7Sderaadt 	}
175df930be7Sderaadt 
176df930be7Sderaadt 	for (scp = Top; scp < &Top[MAXSCORES]; scp++)
177df930be7Sderaadt 		scp->s_score = -1;
178df930be7Sderaadt 
179df930be7Sderaadt 	read(inf, &max_score, sizeof max_score);
180df930be7Sderaadt 	read(inf, Top, sizeof Top);
181df930be7Sderaadt 	close(inf);
182df930be7Sderaadt 	inf = 1;
183df930be7Sderaadt 	for (scp = Top; scp < &Top[MAXSCORES]; scp++)
184df930be7Sderaadt 		if (scp->s_score >= 0)
185d648d61bSpjanzen 			printf("%d\t%d\t%.*s\n", inf++, scp->s_score,
186d648d61bSpjanzen 				(int)(sizeof scp->s_name), scp->s_name);
187df930be7Sderaadt }
188