comparison rogue3/main.c @ 0:527e2150eaf0

Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author edwarj4
date Tue, 13 Oct 2009 13:33:34 +0000
parents
children b4856d4d4c4e
comparison
equal deleted inserted replaced
-1:000000000000 0:527e2150eaf0
1 /*
2 * @(#)main.c 3.27 (Berkeley) 6/15/81
3 *
4 * Rogue: Exploring the Dungeons of Doom
5 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
6 * All rights reserved.
7 *
8 * See the file LICENSE.TXT for full copyright and licensing information.
9 */
10
11 #include "curses.h"
12 #include <time.h>
13 #include <signal.h>
14 #include <limits.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <string.h>
18 #include "machdep.h"
19 #include "rogue.h"
20
21 int num_checks = 0; /* times we've gone over in checkout() */
22 WINDOW *cw; /* Window that the player sees */
23 WINDOW *hw; /* Used for the help command */
24 WINDOW *mw; /* Used to store mosnters */
25 FILE *scoreboard = NULL;
26
27 main(argc, argv, envp)
28 char **argv;
29 char **envp;
30 {
31 char *env;
32 struct linked_list *item;
33 struct object *obj;
34 int lowtime;
35 time_t now;
36
37 md_init(MD_STRIP_CTRL_KEYPAD);
38
39 open_score();
40
41 /*
42 * Drop setuid/setgid after opening the scoreboard file.
43 */
44
45 md_normaluser();
46
47 /*
48 * check for print-score option
49 */
50 if (argc == 2 && strcmp(argv[1], "-s") == 0)
51 {
52 waswizard = TRUE;
53 score(0, -1, 0);
54 exit(0);
55 }
56 /*
57 * Check to see if he is a wizard
58 */
59 if (argc >= 2 && argv[1][0] == '\0')
60 if (strcmp(PASSWD, crypt(md_getpass("Wizard's password: "), "mT")) == 0)
61 {
62 wizard = TRUE;
63 argv++;
64 argc--;
65 }
66
67 /*
68 * get home and options from environment
69 */
70 strcpy(home, md_gethomedir());
71
72 if (strlen(home) > PATH_MAX - strlen("rogue.save") - 1)
73 *home = 0;
74
75 strcpy(file_name, home);
76 strcat(file_name, "rogue.save");
77
78 if ((env = getenv("ROGUEOPTS")) != NULL)
79 parse_opts(env);
80 if (env == NULL || whoami[0] == '\0')
81 strucpy(whoami, md_getusername(), strlen(md_getusername()));
82 if (env == NULL || fruit[0] == '\0')
83 strcpy(fruit, "slime-mold");
84
85 if (too_much() && !wizard && !author())
86 {
87 printf("Sorry, %s, but the system is too loaded now.\n", whoami);
88 printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",
89 vowelstr(fruit), fruit);
90 exit(1);
91 }
92
93 if (argc == 2)
94 if (!restore(argv[1], envp)) /* Note: restore will never return */
95 exit(1);
96
97 time(&now);
98 lowtime = (int) now;
99
100 env = getenv("SEED");
101
102 if (env)
103 seed = atoi(env);
104 else
105 seed = 0;
106
107 if (seed > 0)
108 {
109 waswizard = 1; /* don't save scores if SEED specified */
110 dnum = seed;
111 }
112 else
113 dnum = lowtime + md_getpid();
114
115 if (wizard || env)
116 printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
117 else
118 printf("Hello %s, just a moment while I dig the dungeon...", whoami);
119
120 fflush(stdout);
121 seed = dnum;
122 init_player(); /* Roll up the rogue */
123 init_things(); /* Set up probabilities of things */
124 init_names(); /* Set up names of scrolls */
125 init_colors(); /* Set up colors of potions */
126 init_stones(); /* Set up stone settings of rings */
127 init_materials(); /* Set up materials of wands */
128 initscr(); /* Start up cursor package */
129
130 if (COLS < 70)
131 {
132 endwin();
133 printf("\n\nSorry, %s, but your terminal window has too few columns.\n", whoami);
134 printf("Your terminal has %d columns, needs 70.\n",COLS);
135 exit(1);
136 }
137 if (LINES < 22)
138 {
139 endwin();
140 printf("\n\nSorry, %s, but your terminal window has too few lines.\n", whoami);
141 printf("Your terminal has %d lines, needs 22.\n",LINES);
142 exit(1);
143 }
144
145
146 setup();
147 /*
148 * Set up windows
149 */
150 cw = newwin(LINES, COLS, 0, 0);
151 mw = newwin(LINES, COLS, 0, 0);
152 hw = newwin(LINES, COLS, 0, 0);
153 keypad(cw,1);
154 waswizard = wizard;
155 new_level(); /* Draw current level */
156 /*
157 * Start up daemons and fuses
158 */
159 start_daemon(doctor, 0, AFTER);
160 fuse(swander, 0, WANDERTIME, AFTER);
161 start_daemon(stomach, 0, AFTER);
162 start_daemon(runners, 0, AFTER);
163 /*
164 * Give the rogue his weaponry. First a mace.
165 */
166 item = new_item(sizeof *obj);
167 obj = (struct object *) ldata(item);
168 obj->o_type = WEAPON;
169 obj->o_which = MACE;
170 init_weapon(obj, MACE);
171 obj->o_hplus = 1;
172 obj->o_dplus = 1;
173 obj->o_flags |= ISKNOW;
174 add_pack(item, TRUE);
175 cur_weapon = obj;
176 /*
177 * Now a +1 bow
178 */
179 item = new_item(sizeof *obj);
180 obj = (struct object *) ldata(item);
181 obj->o_type = WEAPON;
182 obj->o_which = BOW;
183 init_weapon(obj, BOW);
184 obj->o_hplus = 1;
185 obj->o_dplus = 0;
186 obj->o_flags |= ISKNOW;
187 add_pack(item, TRUE);
188 /*
189 * Now some arrows
190 */
191 item = new_item(sizeof *obj);
192 obj = (struct object *) ldata(item);
193 obj->o_type = WEAPON;
194 obj->o_which = ARROW;
195 init_weapon(obj, ARROW);
196 obj->o_count = 25+rnd(15);
197 obj->o_hplus = obj->o_dplus = 0;
198 obj->o_flags |= ISKNOW;
199 add_pack(item, TRUE);
200 /*
201 * And his suit of armor
202 */
203 item = new_item(sizeof *obj);
204 obj = (struct object *) ldata(item);
205 obj->o_type = ARMOR;
206 obj->o_which = RING_MAIL;
207 obj->o_ac = a_class[RING_MAIL] - 1;
208 obj->o_flags |= ISKNOW;
209 cur_armor = obj;
210 add_pack(item, TRUE);
211 /*
212 * Give him some food too
213 */
214 item = new_item(sizeof *obj);
215 obj = (struct object *) ldata(item);
216 obj->o_type = FOOD;
217 obj->o_count = 1;
218 obj->o_which = 0;
219 add_pack(item, TRUE);
220 playit();
221 }
222
223 /*
224 * endit:
225 * Exit the program abnormally.
226 */
227
228 void
229 endit(int p)
230 {
231 fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
232 }
233
234 /*
235 * fatal:
236 * Exit the program, printing a message.
237 */
238
239 void
240 fatal(char *s)
241 {
242 clear();
243 move(LINES-2, 0);
244 printw("%s", s);
245 draw(stdscr);
246 endwin();
247 exit(0);
248 }
249
250 /*
251 * rnd:
252 * Pick a very random number.
253 */
254
255 int
256 rnd(int range)
257 {
258 return range == 0 ? 0 : abs(RN) % range;
259 }
260
261 /*
262 * roll:
263 * roll a number of dice
264 */
265
266 int
267 roll(int number, int sides)
268 {
269 int dtotal = 0;
270
271 while(number--)
272 dtotal += rnd(sides)+1;
273 return dtotal;
274 }
275 /*
276 * handle stop and start signals
277 */
278
279 void
280 tstp(int p)
281 {
282 #ifdef SIGTSTP
283 signal(SIGTSTP, SIG_IGN);
284 #endif
285 mvcur(0, COLS - 1, LINES - 1, 0);
286 endwin();
287 fflush(stdout);
288 #ifdef SIGTSTP
289 signal(SIGTSTP, SIG_DFL);
290 kill(0, SIGTSTP);
291 signal(SIGTSTP, tstp);
292 #endif
293 crmode();
294 noecho();
295 clearok(curscr, TRUE);
296 touchwin(cw);
297 draw(cw);
298 flush_type(); /* flush input */
299 }
300
301 void
302 setup()
303 {
304 #ifdef SIGHUP
305 signal(SIGHUP, auto_save);
306 #endif
307 signal(SIGILL, auto_save);
308 #ifdef SIGTRAP
309 signal(SIGTRAP, auto_save);
310 #endif
311 #ifdef SIGIOT
312 signal(SIGIOT, auto_save);
313 #endif
314 #ifdef SIGEMT
315 signal(SIGEMT, auto_save);
316 #endif
317 signal(SIGFPE, auto_save);
318 #ifdef SIGBUS
319 signal(SIGBUS, auto_save);
320 #endif
321 signal(SIGSEGV, auto_save);
322 #ifdef SIGSYS
323 signal(SIGSYS, auto_save);
324 #endif
325 #ifdef SIGPIPE
326 signal(SIGPIPE, auto_save);
327 #endif
328 signal(SIGTERM, auto_save);
329 signal(SIGINT, quit);
330 #ifdef SIGQUIT
331 signal(SIGQUIT, endit);
332 #endif
333 #ifdef SIGTSTP
334 signal(SIGTSTP, tstp);
335 #endif
336
337 if (!author())
338 {
339 #ifdef SIGALRM
340 signal(SIGALRM, checkout);
341 alarm(CHECKTIME * 60);
342 #endif
343 num_checks = 0;
344 }
345
346 crmode(); /* Cbreak mode */
347 noecho(); /* Echo off */
348 }
349
350 /*
351 * playit:
352 * The main loop of the program. Loop until the game is over,
353 * refreshing things and looking at the proper times.
354 */
355
356 void
357 playit()
358 {
359 char *opts;
360
361 /*
362 * set up defaults for slow terminals
363 */
364
365
366 if (baudrate() < 1200)
367 {
368 terse = TRUE;
369 jump = TRUE;
370 }
371
372 /*
373 * parse environment declaration of options
374 */
375 if ((opts = getenv("ROGUEOPTS")) != NULL)
376 parse_opts(opts);
377
378
379 oldpos = hero;
380 oldrp = roomin(&hero);
381 while (playing)
382 command(); /* Command execution */
383 endit(-1);
384 }
385
386 /*
387 * see if the system is being used too much for this game
388 */
389 int
390 too_much()
391 {
392 double avec[3];
393
394 if (md_loadav(avec) == 0)
395 return (avec[2] > (MAXLOAD / 10.0));
396 else
397 return (md_ucount() > MAXUSERS);
398 }
399
400 /*
401 * see if a user is an author of the program
402 */
403 int
404 author()
405 {
406 switch (md_getuid())
407 {
408 case AUTHORUID:
409 return TRUE;
410 default:
411 return FALSE;
412 }
413 }
414
415 void
416 checkout(int p)
417 {
418 static char *msgs[] = {
419 "The load is too high to be playing. Please leave in %d minutes",
420 "Please save your game. You have %d minutes",
421 "Last warning. You have %d minutes to leave",
422 };
423 int checktime;
424 #ifdef SIGALRM
425 signal(SIGALRM, checkout);
426 #endif
427 if (too_much())
428 {
429 if (num_checks >= 3)
430 fatal("Sorry. You took to long. You are dead\n");
431 checktime = CHECKTIME / (num_checks + 1);
432 if (num_checks < 3)
433 chmsg(msgs[num_checks++], checktime);
434 #ifdef SIGALRM
435 alarm(checktime * 60);
436 #endif
437 }
438 else
439 {
440 if (num_checks)
441 {
442 chmsg("The load has dropped back down. You have a reprieve.");
443 num_checks = 0;
444 }
445 #ifdef SIGALRM
446 alarm(CHECKTIME * 60);
447 #endif
448 }
449 }
450
451 /*
452 * checkout()'s version of msg. If we are in the middle of a shell, do a
453 * printf instead of a msg to avoid the refresh.
454 */
455 void
456 chmsg(char *fmt, ...)
457 {
458 va_list args;
459
460 if (in_shell)
461 {
462 va_start(args, fmt);
463 vprintf(fmt, args);
464 va_end(args);
465 putchar('\n');
466 fflush(stdout);
467 }
468 else
469 {
470 va_start(args, fmt);
471 doadd(fmt, args);
472 va_end(args);
473 endmsg();
474 }
475 }