1 /*        $NetBSD: main.c,v 1.34 2022/06/27 18:48:49 christos 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 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
35  The Regents of the University of California.  All rights reserved.");
36 #endif /* not lint */
37 
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)main.c      8.1 (Berkeley) 5/31/93";
41 #else
42 __RCSID("$NetBSD: main.c,v 1.34 2022/06/27 18:48:49 christos Exp $");
43 #endif
44 #endif /* not lint */
45 
46 #include <ctype.h>
47 #include <curses.h>
48 #include <string.h>
49 #include <err.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <signal.h>
53 #include <stdlib.h>
54 #include <time.h>
55 #include <unistd.h>
56 #include "robots.h"
57 
58 extern const char *Scorefile;
59 extern int Max_per_uid;
60 
61 static bool another(void);
62 
63 int
main(int argc,char ** argv)64 main(int argc, char **argv)
65 {
66           const char *word;
67           bool show_only;
68           int score_wfd; /* high score writable file descriptor */
69           int score_err = 0; /* hold errno from score file open */
70           int maximum = 0;
71           int ch, i;
72 
73           score_wfd = open(Scorefile, O_RDWR);
74           if (score_wfd < 0)
75                     score_err = errno;
76           else if (score_wfd < 3)
77                     exit(1);
78 
79           /* Revoke setgid privileges */
80           setgid(getgid());
81 
82           show_only = false;
83           Num_games = 1;
84 
85           while ((ch = getopt(argc, argv, "Aajnrst")) != -1) {
86                     switch (ch) {
87                         case 'A':
88                               Auto_bot = true;
89                               break;
90                         case 'a':
91                               Start_level = 4;
92                               break;
93                         case 'j':
94                               Jump = true;
95                               break;
96                         case 'n':
97                               Num_games++;
98                               break;
99                         case 'r':
100                               Real_time = true;
101                               break;
102                         case 's':
103                               show_only = true;
104                               break;
105                         case 't':
106                               Teleport = true;
107                               break;
108                         default:
109                               errx(1,
110                                   "Usage: robots [-Aajnrst] [maximum] [scorefile]");
111                               break;
112                     }
113           }
114 
115           for (i = optind; i < argc; i++) {
116                     word = argv[i];
117                     if (isdigit((unsigned char)word[0])) {
118                               maximum = atoi(word);
119                     } else {
120                               Scorefile = word;
121                               Max_per_uid = maximum;
122                               if (score_wfd >= 0)
123                                         close(score_wfd);
124                               score_wfd = open(Scorefile, O_RDWR);
125                               if (score_wfd < 0)
126                                         score_err = errno;
127 #ifdef FANCY
128                               word = strrchr(Scorefile, '/');
129                               if (word == NULL)
130                                         word = Scorefile;
131                               if (strcmp(word, "pattern_roll") == 0)
132                                         Pattern_roll = true;
133                               else if (strcmp(word, "stand_still") == 0)
134                                         Stand_still = true;
135                               if (Pattern_roll || Stand_still)
136                                         Teleport = true;
137 #endif
138                     }
139           }
140 
141           if (show_only) {
142                     show_score();
143                     exit(0);
144                     /* NOTREACHED */
145           }
146 
147           if (score_wfd < 0) {
148                     errno = score_err;
149                     warn("%s", Scorefile);
150                     warnx("High scores will not be recorded!");
151                     sleep(2);
152           }
153 
154           if (!initscr())
155                     errx(0, "couldn't initialize screen");
156           signal(SIGINT, quit);
157           cbreak();
158           noecho();
159           nonl();
160           if (LINES != Y_SIZE || COLS != X_SIZE) {
161                     if (LINES < Y_SIZE || COLS < X_SIZE) {
162                               endwin();
163                               printf("Need at least a %dx%d screen\n",
164                                   Y_SIZE, X_SIZE);
165                               exit(1);
166                     }
167                     delwin(stdscr);
168                     stdscr = newwin(Y_SIZE, X_SIZE, 0, 0);
169           }
170 
171           if (Real_time)
172                     signal(SIGALRM, move_robots);
173           do {
174                     while (Num_games--) {
175                               init_field();
176                               for (Level = Start_level; !Dead; Level++) {
177                                         make_level();
178                                         play_level();
179                                         if (Auto_bot)
180                                                   sleep(1);
181                               }
182                               move(My_pos.y, My_pos.x);
183                               printw("AARRrrgghhhh....");
184                               refresh();
185                               if (Auto_bot)
186                                         sleep(1);
187                               score(score_wfd);
188                               if (Auto_bot)
189                                         sleep(1);
190                               refresh();
191                     }
192                     Num_games = 1;
193           } while (!Auto_bot && another());
194           quit(0);
195           /* NOTREACHED */
196           return(0);
197 }
198 
199 /*
200  * quit:
201  *        Leave the program elegantly.
202  */
203 void
quit(int dummy __unused)204 quit(int dummy __unused)
205 {
206           endwin();
207           exit(0);
208           /* NOTREACHED */
209 }
210 
211 /*
212  * another:
213  *        See if another game is desired
214  */
215 static bool
another(void)216 another(void)
217 {
218           int y;
219 
220 #ifdef FANCY
221           if ((Stand_still || Pattern_roll) && !Newscore)
222                     return true;
223 #endif
224 
225           if (query("Another game?")) {
226                     if (Full_clear) {
227                               for (y = 1; y <= Num_scores; y++) {
228                                         move(y, 1);
229                                         clrtoeol();
230                               }
231                               refresh();
232                     }
233                     return true;
234           }
235           return false;
236 }
237