xref: /openbsd-src/games/robots/main.c (revision d7259957e8a5d4370d76bfccd4a30d5d1fe80f38)
1*d7259957Scheloha /*	$OpenBSD: main.c,v 1.31 2022/12/04 23:50:45 cheloha Exp $	*/
2df930be7Sderaadt /*	$NetBSD: main.c,v 1.5 1995/04/22 10:08:54 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 <err.h>
342010f3c8Smestre #include <errno.h>
352010f3c8Smestre #include <fcntl.h>
362010f3c8Smestre #include <signal.h>
372010f3c8Smestre #include <stdlib.h>
382010f3c8Smestre #include <string.h>
392010f3c8Smestre #include <unistd.h>
402010f3c8Smestre 
41df930be7Sderaadt #include "robots.h"
42df930be7Sderaadt 
434c144bbcSpjanzen void
usage(void)443eb8c9edSjsg usage(void)
454c144bbcSpjanzen {
466fa5e1daSmestre 	fprintf(stderr, "usage: %s [-ajrst] [scorefile]\n", getprogname());
474c144bbcSpjanzen 	exit(1);
484c144bbcSpjanzen }
494c144bbcSpjanzen 
50d648d61bSpjanzen int
main(int ac,char * av[])513eb8c9edSjsg main(int ac, char *av[])
52df930be7Sderaadt {
5397419aa0Spjanzen 	bool		show_only;
54e224588fStb 	extern char	Scorefile[PATH_MAX];
555f463f57Skstailey 	int		score_wfd;     /* high score writable file descriptor */
56d648d61bSpjanzen 	int		score_err = 0; /* hold errno from score file open */
574c144bbcSpjanzen 	int		ch;
58e224588fStb 	int		ret;
59e224588fStb 	char		*home;
604c144bbcSpjanzen #ifdef FANCY
6197419aa0Spjanzen 	char		*sp;
624c144bbcSpjanzen #endif
63df930be7Sderaadt 
64e224588fStb 	home = getenv("HOME");
65e224588fStb 	if (home == NULL || *home == '\0')
66e224588fStb 		err(1, "getenv");
67e224588fStb 
68e224588fStb 	ret = snprintf(Scorefile, sizeof(Scorefile), "%s/%s", home,
69e224588fStb 	    ".robots.scores");
70e224588fStb 	if (ret < 0 || ret >= PATH_MAX)
71e224588fStb 		errc(1, ENAMETOOLONG, "%s/%s", home, ".robots.scores");
72e224588fStb 
73df69c215Sderaadt 	if ((score_wfd = open(Scorefile, O_RDWR | O_CREAT, 0666)) == -1)
74e224588fStb 		score_err = errno;
75161033a1Sderaadt 
76df930be7Sderaadt 	show_only = FALSE;
774c144bbcSpjanzen 	while ((ch = getopt(ac, av, "srajt")) != -1)
784c144bbcSpjanzen 		switch (ch) {
794c144bbcSpjanzen 		case 's':
804c144bbcSpjanzen 			show_only = TRUE;
814c144bbcSpjanzen 			break;
824c144bbcSpjanzen 		case 'r':
834c144bbcSpjanzen 			Real_time = TRUE;
844c144bbcSpjanzen 			/* Could be a command-line option */
854c144bbcSpjanzen 			tv.tv_sec = 3;
864c144bbcSpjanzen 			break;
874c144bbcSpjanzen 		case 'a':
884c144bbcSpjanzen 			Start_level = 4;
894c144bbcSpjanzen 			break;
904c144bbcSpjanzen 		case 'j':
914c144bbcSpjanzen 			Jump = TRUE;
924c144bbcSpjanzen 			break;
934c144bbcSpjanzen 		case 't':
944c144bbcSpjanzen 			Teleport = TRUE;
954c144bbcSpjanzen 			break;
964c144bbcSpjanzen 		default:
974c144bbcSpjanzen 			usage();
984c144bbcSpjanzen 		}
994c144bbcSpjanzen 	ac -= optind;
1004c144bbcSpjanzen 	av += optind;
1014c144bbcSpjanzen 
1024c144bbcSpjanzen 	if (ac > 1)
1034c144bbcSpjanzen 		usage();
1044c144bbcSpjanzen 	if (ac == 1) {
105e224588fStb 		if (strlcpy(Scorefile, av[0], sizeof(Scorefile)) >=
106e224588fStb 		    sizeof(Scorefile))
107e224588fStb 			errc(1, ENAMETOOLONG, "%s", av[0]);
108d648d61bSpjanzen 		if (score_wfd >= 0)
1095f463f57Skstailey 			close(score_wfd);
110fdb7e56cSpjanzen 		/* This file requires no special privileges. */
111df69c215Sderaadt 		if ((score_wfd = open(Scorefile, O_RDWR | O_CREAT, 0666)) == -1)
112d648d61bSpjanzen 			score_err = errno;
113d648d61bSpjanzen #ifdef	FANCY
114fdb7e56cSpjanzen 		sp = strrchr(Scorefile, '/');
115fdb7e56cSpjanzen 		if (sp == NULL)
116fdb7e56cSpjanzen 			sp = Scorefile;
117df930be7Sderaadt 		if (strcmp(sp, "pattern_roll") == 0)
118df930be7Sderaadt 			Pattern_roll = TRUE;
119df930be7Sderaadt 		else if (strcmp(sp, "stand_still") == 0)
120df930be7Sderaadt 			Stand_still = TRUE;
121df930be7Sderaadt 		if (Pattern_roll || Stand_still)
122df930be7Sderaadt 			Teleport = TRUE;
123df930be7Sderaadt #endif
124df930be7Sderaadt 	}
125df930be7Sderaadt 
126df930be7Sderaadt 	if (show_only) {
127df930be7Sderaadt 		show_score();
12817641e31Stb 		return 0;
129d648d61bSpjanzen 	}
130d648d61bSpjanzen 
1314c144bbcSpjanzen 	if (score_wfd < 0) {
132fdb7e56cSpjanzen 		warnx("%s: %s; no scores will be saved", Scorefile,
133fdb7e56cSpjanzen 			strerror(score_err));
1344c144bbcSpjanzen 		sleep(1);
1354c144bbcSpjanzen 	}
136df930be7Sderaadt 
137df930be7Sderaadt 	initscr();
1388ac81e2dSmestre 
1398ac81e2dSmestre 	if (pledge("stdio tty", NULL) == -1)
1408ac81e2dSmestre 		err(1, "pledge");
1418ac81e2dSmestre 
142df930be7Sderaadt 	signal(SIGINT, quit);
1438c730b5fSpjanzen 	cbreak();
144df930be7Sderaadt 	noecho();
145df930be7Sderaadt 	nonl();
146df930be7Sderaadt 	if (LINES != Y_SIZE || COLS != X_SIZE) {
147df930be7Sderaadt 		if (LINES < Y_SIZE || COLS < X_SIZE) {
148df930be7Sderaadt 			endwin();
149fdb7e56cSpjanzen 			errx(1, "Need at least a %dx%d screen", Y_SIZE, X_SIZE);
150df930be7Sderaadt 		}
151df930be7Sderaadt 		delwin(stdscr);
152df930be7Sderaadt 		stdscr = newwin(Y_SIZE, X_SIZE, 0, 0);
153df930be7Sderaadt 	}
154df930be7Sderaadt 
155df930be7Sderaadt 	do {
156df930be7Sderaadt 		init_field();
157df930be7Sderaadt 		for (Level = Start_level; !Dead; Level++) {
158df930be7Sderaadt 			make_level();
159df930be7Sderaadt 			play_level();
160df930be7Sderaadt 		}
161ebff5be7Stedu 		if (My_pos.x > X_FIELDSIZE - 16)
162ebff5be7Stedu 			move(My_pos.y, X_FIELDSIZE - 16);
163ebff5be7Stedu 		else
164df930be7Sderaadt 			move(My_pos.y, My_pos.x);
165df930be7Sderaadt 		printw("AARRrrgghhhh....");
166df930be7Sderaadt 		refresh();
1675f463f57Skstailey 		score(score_wfd);
168df930be7Sderaadt 	} while (another());
169d648d61bSpjanzen 	quit(0);
170df930be7Sderaadt }
171df930be7Sderaadt 
172df930be7Sderaadt /*
173df930be7Sderaadt  * quit:
174df930be7Sderaadt  *	Leave the program elegantly.
175df930be7Sderaadt  */
176df930be7Sderaadt void
quit(int dummy)1773eb8c9edSjsg quit(int dummy)
178df930be7Sderaadt {
179df930be7Sderaadt 	endwin();
180df930be7Sderaadt 	exit(0);
181df930be7Sderaadt }
182df930be7Sderaadt 
183df930be7Sderaadt /*
184df930be7Sderaadt  * another:
185df930be7Sderaadt  *	See if another game is desired
186df930be7Sderaadt  */
187d648d61bSpjanzen bool
another(void)1883eb8c9edSjsg another(void)
189df930be7Sderaadt {
19097419aa0Spjanzen 	int	y;
191df930be7Sderaadt 
192df930be7Sderaadt #ifdef	FANCY
193df930be7Sderaadt 	if ((Stand_still || Pattern_roll) && !Newscore)
194df930be7Sderaadt 		return TRUE;
195df930be7Sderaadt #endif
196df930be7Sderaadt 
197df930be7Sderaadt 	if (query("Another game?")) {
198df930be7Sderaadt 		if (Full_clear) {
199df930be7Sderaadt 			for (y = 1; y <= Num_scores; y++) {
200df930be7Sderaadt 				move(y, 1);
201df930be7Sderaadt 				clrtoeol();
202df930be7Sderaadt 			}
203df930be7Sderaadt 			refresh();
204df930be7Sderaadt 		}
205df930be7Sderaadt 		return TRUE;
206df930be7Sderaadt 	}
207df930be7Sderaadt 	return FALSE;
208df930be7Sderaadt }
209