comparison arogue5/main.c @ 63:0ed67132cf10

Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 09 Aug 2012 22:58:48 +0000
parents
children a98834ce7e04
comparison
equal deleted inserted replaced
62:0ef99244acb8 63:0ed67132cf10
1 /*
2 * Rogue
3 *
4 * Advanced Rogue
5 * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
6 * All rights reserved.
7 *
8 * Based on "Rogue: Exploring the Dungeons of Doom"
9 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
10 * All rights reserved.
11 *
12 * See the file LICENSE.TXT for full copyright and licensing information.
13 */
14
15 #include "curses.h"
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 #include <limits.h>
19 #include <signal.h>
20 #include <time.h>
21 #include "mach_dep.h"
22 #include "network.h"
23 #include "rogue.h"
24
25 #ifdef CHECKTIME
26 static int num_checks; /* times we've gone over in checkout() */
27 #endif
28
29 /*
30 * fruits that you get at startup
31 */
32 static char *funfruit[] = {
33 "candleberry", "caprifig", "dewberry", "elderberry",
34 "gooseberry", "guanabana", "hagberry", "ilama",
35 "imbu", "jaboticaba", "jujube", "litchi",
36 "mombin", "pitanga", "prickly pear", "rambutan",
37 "sapodilla", "soursop", "sweetsop", "whortleberry",
38 "jellybean", "apple", "strawberry", "blueberry",
39 "peach", "banana"
40 };
41 #define NFRUIT (sizeof(funfruit) / sizeof (char *))
42
43 main(argc, argv, envp)
44 char **argv;
45 char **envp;
46 {
47 register char *env;
48 int lowtime;
49 time_t now;
50 char *roguedir = md_getroguedir();
51
52 md_init();
53
54 /*
55 * get home and options from environment
56 */
57
58 strncpy(home,md_gethomedir(),LINELEN);
59
60 /* Get default save file */
61 strcpy(file_name, home);
62 strcat(file_name, "arogue58.sav");
63
64 /* Get default score file */
65 strcpy(score_file, roguedir);
66
67 if (*score_file)
68 strcat(score_file,"/");
69
70 strcat(score_file, "arogue58.scr");
71
72 if ((env = getenv("ROGUEOPTS")) != NULL)
73 parse_opts(env);
74
75 if (whoami[0] == '\0')
76 strucpy(whoami, md_getusername(), strlen(md_getusername()));
77
78 if (env == NULL || fruit[0] == '\0') {
79 md_srand((long)(getpid()+time(0)));
80 strcpy(fruit, funfruit[rnd(NFRUIT)]);
81 }
82
83 /*
84 * check for print-score option
85 */
86 if (argc == 2 && strcmp(argv[1], "-s") == 0)
87 {
88 waswizard = TRUE;
89 score(0, SCOREIT, 0);
90 exit(0);
91 }
92
93 #ifdef NUMNET
94 /*
95 * Check for a network update
96 */
97 if (argc == 2 && strcmp(argv[1], "-u") == 0) {
98 unsigned long netread();
99 int errcheck, errors = 0;
100 unsigned long amount;
101 short monster;
102
103 /* Read in the amount and monster values to pass to score */
104 amount = netread(&errcheck, sizeof(unsigned long), stdin);
105 if (errcheck) errors++;
106
107 monster = (short) netread(&errcheck, sizeof(short), stdin);
108 if (errcheck) errors++;
109
110 /* Now do the update if there were no errors */
111 if (errors) exit(1);
112 else {
113 score(amount, UPDATE, monster);
114 exit(0);
115 }
116 }
117 #endif
118
119 #ifdef WIZARD
120 /*
121 * Check to see if he is a wizard
122 */
123 if (argc >= 2 && argv[1][0] == '\0')
124 if (strcmp(PASSWD, md_crypt(md_getpass("Wizard's password: "), "Si")) == 0)
125 {
126 printf("Hail Mighty Wizard\n");
127 wizard = TRUE;
128 argv++;
129 argc--;
130 }
131 #endif
132
133 #if MAXLOAD|MAXUSERS
134 if (too_much() && !wizard && !author())
135 {
136 printf("Sorry, %s, but the system is too loaded now.\n", whoami);
137 printf("Try again later. Meanwhile, why not enjoy a%s %s?\n",
138 vowelstr(fruit), fruit);
139 exit(1);
140 }
141 #endif
142 if (argc == 2)
143 if (!restore(argv[1], envp)) /* Note: restore will never return */
144 exit(1);
145 lowtime = (int) time(&now);
146 dnum = (wizard && getenv("SEED") != NULL ?
147 atoi(getenv("SEED")) :
148 lowtime + getpid());
149 if (wizard)
150 printf("Hello %s, welcome to dungeon #%d\n", whoami, dnum);
151 else
152 printf("Hello %s, just a moment while I dig the dungeon...\n", whoami);
153 fflush(stdout);
154 seed = dnum;
155 md_srand(seed);
156
157 init_things(); /* Set up probabilities of things */
158 init_colors(); /* Set up colors of potions */
159 init_stones(); /* Set up stone settings of rings */
160 init_materials(); /* Set up materials of wands */
161 initscr(); /* Start up cursor package */
162 init_names(); /* Set up names of scrolls */
163 init_misc(); /* Set up miscellaneous magic */
164 if (LINES < 24 || COLS < 80) {
165 printf("\nERROR: screen size to small for rogue\n");
166 byebye(-1);
167 }
168
169 if ((whoami == NULL) || (*whoami == '\0') || (strcmp(whoami,"dosuser")==0))
170 {
171 echo();
172 mvaddstr(23,2,"Rogue's Name? ");
173 wgetnstr(stdscr,whoami,LINELEN);
174 noecho();
175 }
176
177 if ((whoami == NULL) || (*whoami == '\0'))
178 strcpy(whoami,"Rodney");
179
180 setup();
181 /*
182 * Set up windows
183 */
184 cw = newwin(LINES, COLS, 0, 0);
185 mw = newwin(LINES, COLS, 0, 0);
186 hw = newwin(LINES, COLS, 0, 0);
187 msgw = newwin(4, COLS, 0, 0);
188 keypad(cw,1);
189 keypad(msgw,1);
190
191 init_player(); /* Roll up the rogue */
192 waswizard = wizard;
193 new_level(NORMLEV); /* Draw current level */
194 /*
195 * Start up daemons and fuses
196 */
197 daemon(doctor, &player, AFTER);
198 fuse(swander, 0, WANDERTIME, AFTER);
199 daemon(stomach, 0, AFTER);
200 daemon(runners, 0, AFTER);
201 if (player.t_ctype == C_THIEF)
202 daemon(trap_look, 0, AFTER);
203
204 /* Choose a quest item */
205 quest_item = rnd(MAXRELIC);
206 msg("You have been quested to retrieve the %s....",
207 rel_magic[quest_item].mi_name);
208 mpos = 0;
209 playit();
210 }
211
212 /*
213 * endit:
214 * Exit the program abnormally.
215 */
216 void
217 endit(int sig)
218 {
219 NOOP(sig);
220
221 fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
222 }
223
224 /*
225 * fatal:
226 * Exit the program, printing a message.
227 */
228
229 fatal(s)
230 char *s;
231 {
232 clear();
233 move(LINES-2, 0);
234 printw("%s", s);
235 draw(stdscr);
236 endwin();
237 printf("\n"); /* So the cursor doesn't stop at the end of the line */
238 exit(0);
239 }
240
241 /*
242 * rnd:
243 * Pick a very random number.
244 */
245
246 rnd(range)
247 register int range;
248 {
249 return(range == 0 ? 0 : md_rand() % range);
250 }
251
252 /*
253 * roll:
254 * roll a number of dice
255 */
256
257 roll(number, sides)
258 register int number, sides;
259 {
260 register int dtotal = 0;
261
262 while(number--)
263 dtotal += rnd(sides)+1;
264 return dtotal;
265 }
266 # ifdef SIGTSTP
267 /*
268 * handle stop and start signals
269 */
270 void
271 tstp(int a)
272 {
273 mvcur(0, COLS - 1, LINES - 1, 0);
274 endwin();
275 fflush(stdout);
276 kill(0, SIGTSTP);
277 signal(SIGTSTP, tstp);
278 raw();
279 noecho();
280 keypad(cw,1);
281 clearok(curscr, TRUE);
282 touchwin(cw);
283 draw(cw);
284 md_flushinp();
285 }
286 # endif
287
288 setup()
289 {
290 #ifdef CHECKTIME
291 int checkout();
292 #endif
293
294 #ifndef DUMP
295 #ifdef SIGHUP
296 signal(SIGHUP, auto_save);
297 #endif
298 signal(SIGILL, bugkill);
299 #ifdef SIGTRAP
300 signal(SIGTRAP, bugkill);
301 #endif
302 #ifdef SIGIOT
303 signal(SIGIOT, bugkill);
304 #endif
305 #if 0
306 signal(SIGEMT, bugkill);
307 signal(SIGFPE, bugkill);
308 signal(SIGBUS, bugkill);
309 signal(SIGSEGV, bugkill);
310 signal(SIGSYS, bugkill);
311 signal(SIGPIPE, bugkill);
312 #endif
313 signal(SIGTERM, auto_save);
314 #endif
315
316 signal(SIGINT, quit);
317 #ifndef DUMP
318 #ifdef SIGQUIT
319 signal(SIGQUIT, endit);
320 #endif
321 #endif
322 #ifdef SIGTSTP
323 signal(SIGTSTP, tstp);
324 #endif
325 #ifdef CHECKTIME
326 if (!author())
327 {
328 signal(SIGALRM, checkout);
329 alarm(CHECKTIME * 60);
330 num_checks = 0;
331 }
332 #endif
333 crmode(); /* Cbreak mode */
334 noecho(); /* Echo off */
335 }
336
337 /*
338 * playit:
339 * The main loop of the program. Loop until the game is over,
340 * refreshing things and looking at the proper times.
341 */
342
343 playit()
344 {
345 register char *opts;
346
347
348 /*
349 * parse environment declaration of options
350 */
351 if ((opts = getenv("ROGUEOPTS")) != NULL)
352 parse_opts(opts);
353
354
355 player.t_oldpos = hero;
356 oldrp = roomin(&hero);
357 after = TRUE;
358 while (playing)
359 command(); /* Command execution */
360 endit(0);
361 }
362
363 #if MAXLOAD|MAXUSERS
364 /*
365 * see if the system is being used too much for this game
366 */
367 too_much()
368 {
369 #ifdef MAXLOAD
370 double avec[3];
371 #endif
372
373 #ifdef MAXLOAD
374 loadav(avec);
375 return (avec[2] > (MAXLOAD / 10.0));
376 #else
377 return (ucount() > MAXUSERS);
378 #endif
379 }
380 #endif
381
382 /*
383 * author:
384 * See if a user is an author of the program
385 */
386 author()
387 {
388 switch (md_getuid()) {
389 #if AUTHOR
390 case AUTHOR:
391 #endif
392 case 0:
393 return TRUE;
394 default:
395 return FALSE;
396 }
397 }
398
399
400 #ifdef CHECKTIME
401 checkout()
402 {
403 static char *msgs[] = {
404 "The system is too loaded for games. Please leave in %d minutes",
405 "Please save your game. You have %d minutes",
406 "This is your last chance. You had better leave in %d minutes",
407 };
408 int checktime;
409
410 signal(SIGALRM, checkout);
411 if (!holiday() && !author()) {
412 wclear(cw);
413 mvwaddstr(cw, LINES / 2, 0,
414 "Game time is over. Your game is being saved.\n\n");
415 draw(cw);
416 auto_save(); /* NO RETURN */
417 }
418 if (too_much()) {
419 if (num_checks >= 3)
420 fatal("You didn't listen, so now you are DEAD !!\n");
421 checktime = CHECKTIME / (num_checks + 1);
422 chmsg(msgs[num_checks++], checktime);
423 alarm(checktime * 60);
424 }
425 else {
426 if (num_checks) {
427 chmsg("The load has dropped. You have a reprieve.");
428 num_checks = 0;
429 }
430 alarm(CHECKTIME * 60);
431 }
432 }
433
434 /*
435 * checkout()'s version of msg. If we are in the middle of a shell, do a
436 * printf instead of a msg to avoid the refresh.
437 */
438 chmsg(fmt, arg)
439 char *fmt;
440 int arg;
441 {
442 if (in_shell) {
443 printf(fmt, arg);
444 putchar('\n');
445 fflush(stdout);
446 }
447 else
448 msg(fmt, arg);
449 }
450 #endif
451
452 #ifdef LOADAV
453
454 #include <nlist.h>
455
456 struct nlist avenrun =
457 {
458 "_avenrun"
459 };
460
461 loadav(avg)
462 reg double *avg;
463 {
464 reg int kmem;
465
466 if ((kmem = open("/dev/kmem", 0)) < 0)
467 goto bad;
468 nlist(NAMELIST, &avenrun);
469 if (avenrun.n_type == 0) {
470 bad:
471 avg[0] = avg[1] = avg[2] = 0.0;
472 return;
473 }
474 lseek(kmem, (long) avenrun.n_value, 0);
475 read(kmem, avg, 3 * sizeof (double));
476 }
477 #endif
478
479 #ifdef UCOUNT
480 /*
481 * ucount:
482 * Count the number of people on the system
483 */
484 #include <sys/types.h>
485 #include <utmp.h>
486 struct utmp buf;
487 ucount()
488 {
489 reg struct utmp *up;
490 reg FILE *utmp;
491 reg int count;
492
493 if ((utmp = fopen(UTMP, "r")) == NULL)
494 return 0;
495
496 up = &buf;
497 count = 0;
498 while (fread(up, 1, sizeof (*up), utmp) > 0)
499 if (buf.ut_type == USER_PROCESS)
500 count++;
501 fclose(utmp);
502 return count;
503 }
504 #endif
505
506 /*
507 * holiday:
508 * Returns TRUE when it is a good time to play rogue
509 */
510 holiday()
511 {
512 time_t now;
513 struct tm *localtime();
514 reg struct tm *ntime;
515
516 time(&now); /* get the current time */
517 ntime = localtime(&now);
518 if(ntime->tm_wday == 0 || ntime->tm_wday == 6)
519 return TRUE; /* OK on Sat & Sun */
520 if(ntime->tm_hour < 8 || ntime->tm_hour >= 17)
521 return TRUE; /* OK before 8AM & after 5PM */
522 if(ntime->tm_yday <= 7 || ntime->tm_yday >= 350)
523 return TRUE; /* OK during Christmas */
524 #if 0 /* not for now */
525 if (access("/usr/tmp/.ryes",0) == 0)
526 return TRUE; /* if author permission */
527 #endif
528
529 return FALSE; /* All other times are bad */
530 }