xref: /netbsd/games/rogue/init.c (revision 6550d01e)
1 /*	$NetBSD: init.c,v 1.18 2008/08/08 16:10:47 drochner Exp $	*/
2 
3 /*
4  * Copyright (c) 1988, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Timothy C. Stoehr.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)init.c	8.1 (Berkeley) 5/31/93";
39 #else
40 __RCSID("$NetBSD: init.c,v 1.18 2008/08/08 16:10:47 drochner Exp $");
41 #endif
42 #endif /* not lint */
43 
44 /*
45  * init.c
46  *
47  * This source herein may be modified and/or distributed by anybody who
48  * so desires, with the following restrictions:
49  *    1.)  No portion of this notice shall be removed.
50  *    2.)  Credit shall not be taken for the creation of this source.
51  *    3.)  This code is not to be traded, sold, or used for personal
52  *         gain or profit.
53  *
54  */
55 
56 #include <stdlib.h>
57 #include <fcntl.h>
58 
59 #include "rogue.h"
60 
61 static void do_args(int, char **);
62 static void do_opts(void);
63 static void env_get_value(char **, char *, boolean);
64 static void init_str(char **, const char *);
65 static void player_init(void);
66 
67 static char *rest_file = NULL;
68 static boolean init_curses = 0;
69 
70 char login_name[MAX_OPT_LEN];
71 char *nick_name = NULL;
72 boolean cant_int = 0;
73 boolean did_int = 0;
74 boolean score_only;
75 boolean save_is_interactive = 1;
76 boolean ask_quit = 1;
77 boolean no_skull = 0;
78 boolean passgo = 0;
79 const char *error_file = "rogue.esave";
80 const char *byebye_string = "Okay, bye bye!";
81 gid_t gid, egid;
82 
83 int
84 init(int argc, char *argv[])
85 {
86 	const char *pn;
87 	int seed;
88 	int fd;
89 
90 	gid = getgid();
91 	egid = getegid();
92 	setegid(gid);
93 	/* Check for dirty tricks with closed fds 0, 1, 2 */
94 	fd = open("/dev/null", O_RDONLY);
95 	if (fd < 3)
96 		exit(1);
97 	close(fd);
98 
99 	seed = 0;
100 	pn = md_gln();
101 	if ((!pn) || (strlen(pn) >= MAX_OPT_LEN)) {
102 		clean_up("Hey!  Who are you?");
103 	}
104 	/* LOGIN_NAME_SIZE == MAX_OPT_LEN now, but just in case... */
105 	(void)strlcpy(login_name, pn, sizeof(login_name));
106 
107 	do_args(argc, argv);
108 	do_opts();
109 
110 	if (!score_only && !rest_file) {
111 		printf("Hello %s, just a moment while I dig the dungeon...",
112 			nick_name);
113 		fflush(stdout);
114 	}
115 
116 	if (!initscr()) {
117 		fprintf(stderr, "couldn't initialize screen\n");
118 		exit (0);
119 	}
120 	if ((LINES < DROWS) || (COLS < DCOLS)) {
121 		clean_up("must be played on at least 80 x 24 screen");
122 	}
123 	start_window();
124 	init_curses = 1;
125 
126 	md_heed_signals();
127 
128 	if (score_only) {
129 		put_scores(NULL, 0);
130 	}
131 	seed = md_gseed();
132 	(void)srrandom(seed);
133 	if (rest_file) {
134 		restore(rest_file);
135 		return(1);
136 	}
137 	mix_colors();
138 	get_wand_and_ring_materials();
139 	make_scroll_titles();
140 
141 	level_objects.next_object = NULL;
142 	level_monsters.next_monster = NULL;
143 	player_init();
144 	ring_stats(0);
145 	return(0);
146 }
147 
148 static void
149 player_init(void)
150 {
151 	object *obj;
152 
153 	rogue.pack.next_object = NULL;
154 
155 	obj = alloc_object();
156 	get_food(obj, 1);
157 	(void)add_to_pack(obj, &rogue.pack, 1);
158 
159 	obj = alloc_object();		/* initial armor */
160 	obj->what_is = ARMOR;
161 	obj->which_kind = RINGMAIL;
162 	obj->class = RINGMAIL+2;
163 	obj->is_protected = 0;
164 	obj->d_enchant = 1;
165 	(void)add_to_pack(obj, &rogue.pack, 1);
166 	do_wear(obj);
167 
168 	obj = alloc_object();		/* initial weapons */
169 	obj->what_is = WEAPON;
170 	obj->which_kind = MACE;
171 	obj->damage = "2d3";
172 	obj->hit_enchant = obj->d_enchant = 1;
173 	obj->identified = 1;
174 	(void)add_to_pack(obj, &rogue.pack, 1);
175 	do_wield(obj);
176 
177 	obj = alloc_object();
178 	obj->what_is = WEAPON;
179 	obj->which_kind = BOW;
180 	obj->damage = "1d2";
181 	obj->hit_enchant = 1;
182 	obj->d_enchant = 0;
183 	obj->identified = 1;
184 	(void)add_to_pack(obj, &rogue.pack, 1);
185 
186 	obj = alloc_object();
187 	obj->what_is = WEAPON;
188 	obj->which_kind = ARROW;
189 	obj->quantity = get_rand(25, 35);
190 	obj->damage = "1d2";
191 	obj->hit_enchant = 0;
192 	obj->d_enchant = 0;
193 	obj->identified = 1;
194 	(void)add_to_pack(obj, &rogue.pack, 1);
195 }
196 
197 void
198 clean_up(const char *estr)
199 {
200 	if (save_is_interactive) {
201 		if (init_curses) {
202 			move(DROWS-1, 0);
203 			refresh();
204 			stop_window();
205 		}
206 		printf("\n%s\n", estr);
207 	}
208 	md_exit(0);
209 }
210 
211 void
212 start_window(void)
213 {
214 	cbreak();
215 	noecho();
216 #ifndef BAD_NONL
217 	nonl();
218 #endif
219 }
220 
221 void
222 stop_window(void)
223 {
224 	endwin();
225 }
226 
227 void
228 byebye(int dummy __unused)
229 {
230 	md_ignore_signals();
231 	if (ask_quit) {
232 		quit(1);
233 	} else {
234 		clean_up(byebye_string);
235 	}
236 	md_heed_signals();
237 }
238 
239 void
240 onintr(int dummy __unused)
241 {
242 	md_ignore_signals();
243 	if (cant_int) {
244 		did_int = 1;
245 	} else {
246 		check_message();
247 		messagef(1, "interrupt");
248 	}
249 	md_heed_signals();
250 }
251 
252 void
253 error_save(int dummy __unused)
254 {
255 	save_is_interactive = 0;
256 	save_into_file(error_file);
257 	clean_up("");
258 }
259 
260 static void
261 do_args(int argc, char *argv[])
262 {
263 	int i, j;
264 
265 	for (i = 1; i < argc; i++) {
266 		if (argv[i][0] == '-') {
267 			for (j = 1; argv[i][j]; j++) {
268 				switch(argv[i][j]) {
269 				case 's':
270 					score_only = 1;
271 					break;
272 				}
273 			}
274 		} else {
275 			rest_file = argv[i];
276 		}
277 	}
278 }
279 
280 static void
281 do_opts(void)
282 {
283 	char *eptr;
284 
285 	if ((eptr = md_getenv("ROGUEOPTS")) != NULL) {
286 		for (;;) {
287 			while ((*eptr) == ' ') {
288 				eptr++;
289 			}
290 			if (!(*eptr)) {
291 				break;
292 			}
293 			if (!strncmp(eptr, "fruit=", 6)) {
294 				eptr += 6;
295 				env_get_value(&fruit, eptr, 1);
296 			} else if (!strncmp(eptr, "file=", 5)) {
297 				eptr += 5;
298 				env_get_value(&save_file, eptr, 0);
299 			} else if (!strncmp(eptr, "jump", 4)) {
300 				jump = 1;
301 			} else if (!strncmp(eptr, "name=", 5)) {
302 				eptr += 5;
303 				env_get_value(&nick_name, eptr, 0);
304 			} else if (!strncmp(eptr, "noaskquit", 9)) {
305 				ask_quit = 0;
306 			} else if (!strncmp(eptr, "noskull", 5) ||
307 					!strncmp(eptr,"notomb", 6)) {
308 				no_skull = 1;
309 			} else if (!strncmp(eptr, "passgo", 5)) {
310 				passgo = 1;
311 			}
312 			while ((*eptr) && (*eptr != ',')) {
313 				eptr++;
314 			}
315 			if (!(*(eptr++))) {
316 				break;
317 			}
318 		}
319 	}
320 	/* If some strings have not been set through ROGUEOPTS, assign defaults
321 	 * to them so that the options editor has data to work with.
322 	 */
323 	init_str(&nick_name, login_name);
324 	init_str(&save_file, "rogue.save");
325 	init_str(&fruit, "slime-mold");
326 }
327 
328 static void
329 env_get_value(char **s, char *e, boolean add_blank)
330 {
331 	short i = 0;
332 	const char *t;
333 
334 	t = e;
335 
336 	while ((*e) && (*e != ',')) {
337 		if (*e == ':') {
338 			*e = ';';		/* ':' reserved for score file purposes */
339 		}
340 		e++;
341 		if (++i >= MAX_OPT_LEN) {
342 			break;
343 		}
344 	}
345 	/* note: edit_opts() in room.c depends on this being the right size */
346 	*s = md_malloc(MAX_OPT_LEN + 2);
347 	if (*s == NULL)
348 		clean_up("out of memory");
349 	(void)strncpy(*s, t, i);
350 	if (add_blank) {
351 		(*s)[i++] = ' ';
352 	}
353 	(*s)[i] = '\0';
354 }
355 
356 static void
357 init_str(char **str, const char *dflt)
358 {
359 	if (!(*str)) {
360 		/* note: edit_opts() in room.c depends on this size */
361 		*str = md_malloc(MAX_OPT_LEN + 2);
362 		if (*str == NULL)
363 			clean_up("out of memory");
364 		(void)strlcpy(*str, dflt, MAX_OPT_LEN + 2);
365 	}
366 }
367