comparison arogue7/main.c @ 125:adfa37e67084

Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Fri, 08 May 2015 15:24:40 -0400
parents
children b786053d2f37
comparison
equal deleted inserted replaced
124:d10fc4a065ac 125:adfa37e67084
1 /*
2 * main.c - setup code
3 *
4 * Advanced Rogue
5 * Copyright (C) 1984, 1985, 1986 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 <signal.h>
17 #ifdef BSD
18 #include <sys/time.h>
19 #else
20 #include <time.h>
21 #endif
22 #include "mach_dep.h"
23 #include "network.h"
24 #include "rogue.h"
25 #ifdef PC7300
26 #include "sys/window.h"
27 #include <ctype.h>
28 extern struct uwdata wdata, oldwin;
29 extern char oldtext[WTXTNUM][WTXTLEN];
30 #endif
31
32 main(argc, argv, envp)
33 char **argv;
34 char **envp;
35 {
36 register char *env;
37 int lowtime;
38 time_t now;
39 #ifdef PC7300
40 int hardwindow; /* Do we have a hardware window? */
41 #endif
42
43 md_init();
44
45 /*
46 * get home and options from environment
47 */
48
49 strncpy(home, md_gethomedir(), LINELEN);
50
51 /* Get default save file */
52 strcpy(file_name, home);
53 strcat(file_name, "arogue77.sav");
54
55 /* Get default score file */
56 strcpy(score_file, md_getroguedir());
57
58 if (*score_file)
59 strcat(score_file,"/");
60
61 strcat(score_file,"arogue77.scr");
62
63 if ((env = getenv("ROGUEOPTS")) != NULL)
64 parse_opts(env);
65
66 if (whoami[0] == '\0')
67 strucpy(whoami, md_getusername(), strlen(md_getusername()));
68
69 /*
70 * check for print-score option
71 */
72 if (argc == 2 && strcmp(argv[1], "-s") == 0)
73 {
74 waswizard = TRUE;
75 score(0, SCOREIT, 0);
76 exit(0);
77 }
78
79 #ifdef NUMNET
80 /*
81 * Check for a network update
82 */
83 if (argc == 2 && strcmp(argv[1], "-u") == 0) {
84 unsigned long netread();
85 int errcheck, errors = 0;
86 unsigned long amount;
87 short monster;
88
89 /* Read in the amount and monster values to pass to score */
90 amount = netread(&errcheck, sizeof(unsigned long), stdin);
91 if (errcheck) errors++;
92
93 monster = (short) netread(&errcheck, sizeof(short), stdin);
94 if (errcheck) errors++;
95
96 /* Now do the update if there were no errors */
97 if (errors) exit(1);
98 else {
99 score(amount, UPDATE, monster);
100 exit(0);
101 }
102 }
103 #endif
104
105 #ifdef WIZARD
106 /*
107 * Check to see if he is a wizard
108 */
109 if (argc >= 2 && argv[1][0] == '\0')
110 if (strcmp(PASSWD, md_crypt(md_getpass("Wizard's password: "), "mT")) == 0)
111 {
112 wizard = TRUE;
113 argv++;
114 argc--;
115 }
116 #endif
117
118 if (!wizard && !author() && !holiday()) {
119 printf("Sorry, %s, but you can't play during working hours.\n", whoami);
120 printf("Try again later.\n");
121 exit(1);
122 }
123 if (!wizard && !author() && too_much()) {
124 printf("Sorry, %s, but the system is too loaded now.\n", whoami);
125 printf("Try again later.\n");
126 exit(1);
127 }
128
129 #if NICE
130 if (!wizard)
131 nice(19); /* nice the max amount */
132 #endif
133
134 if (argc == 2)
135 if (!restore(argv[1], envp)) /* Note: restore will never return */
136 exit(1);
137 lowtime = (int) time(&now);
138 dnum = (wizard && getenv("SEED") != NULL ?
139 atoi(getenv("SEED")) :
140 lowtime + getpid());
141 if (wizard)
142 printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
143 else
144 printf("Hello %s, just a moment while I dig the dungeon...", whoami);
145 fflush(stdout);
146 seed = dnum;
147 md_srand(seed);
148
149 #ifdef PC7300
150 /* Store static window parameters */
151 hardwindow = ioctl(0, WIOCGETD, &wdata);
152 if (hardwindow >= 0) { /* We have a hardware window */
153 extern char **environ;
154
155 /* Make sure our window is the right size */
156 oldwin = wdata;
157 if ((wdata.uw_height / wdata.uw_vs) < 23 ||
158 (wdata.uw_width / wdata.uw_hs) < 75) {
159 wdata.uw_width = 80 * wdata.uw_hs;
160 wdata.uw_height = 24 * wdata.uw_vs;
161 wdata.uw_x = 0;
162 wdata.uw_y = wdata.uw_vs;
163 wdata.uw_uflags = NBORDER;
164
165 /* Make the change */
166 if (ioctl(1, WIOCSETD, &wdata) >= 0 && environ) {
167 char **eptr, *tptr, *nptr, *newenv, *lptr = 0, *cptr = 0;
168 int i, nlines = -1, ncols = -1, nlindig = 0, ncoldig = 0;
169 struct utdata labelbuf;
170
171 /* Save and change window-associated text */
172 for (i=0; i<WTXTNUM; i++) {
173 labelbuf.ut_num = i;
174 ioctl(1, WIOCGETTEXT, &labelbuf);
175 strncpy(oldtext[i], labelbuf.ut_text, WTXTLEN - 1);
176 if (*labelbuf.ut_text) {
177 *labelbuf.ut_text = '\0';
178 ioctl(1, WIOCSETTEXT, &labelbuf);
179 }
180 }
181
182 labelbuf.ut_num = WTXTLABEL;
183 strcpy(labelbuf.ut_text, "Advanced Rogue");
184 ioctl(1, WIOCSETTEXT, &labelbuf);
185
186 /* We have to change the TERMCAP entry */
187 eptr = environ;
188 while (*eptr) {
189 if (strncmp(*eptr, "TERMCAP=", 8) == 0) break;
190 else eptr++;
191 }
192
193 /* We found a TERMCAP entry */
194 if (*eptr) {
195 /* Search for li# and co# */
196 tptr = *eptr;
197 while (*tptr) {
198 switch (*tptr) {
199 case 'l':
200 if (nlines == -1 &&
201 strncmp(tptr, "li#", 3) == 0) {
202 tptr += 3;
203 lptr = tptr;
204 lines = atoi(tptr);
205 while (isdigit(*tptr)) {
206 nlindig++;;
207 tptr++;
208 }
209 }
210 else tptr++;
211 break;
212 case 'c':
213 if (ncols == -1 &&
214 strncmp(tptr, "co#", 3) == 0) {
215 tptr += 3;
216 cptr = tptr;
217 cols = atoi(tptr);
218 while (isdigit(*tptr)) {
219 ncoldig++;
220 tptr++;
221 }
222 }
223 else tptr++;
224 break;
225 default:
226 tptr++;
227 }
228 }
229
230 /* Change the entry */
231 if (ncoldig != 2 || nlindig != 2) {
232 int length;
233
234 /* Add in difference in num lengths plus NULL */
235 length = strlen(*eptr) - ncoldig - nlindig + 5;
236
237 if (ncoldig == 0) length += 4; /* For :co# */
238 if (nlindig == 0) length += 4; /* For :li# */
239
240 newenv = malloc(length);
241 tptr = *eptr;
242 nptr = newenv;
243
244 if (nlindig == 0 || ncoldig == 0) {
245 /* Copy up to the first : */
246 while (*tptr && *tptr != ':') *nptr++ = *tptr++;
247
248 /* Do we have to add a field? */
249 if (nlindig == 0) {
250 strcpy(nptr, ":li#24");
251 nptr += 6;
252 }
253 if (ncoldig == 0) {
254 strcpy(nptr, ":co#80");
255 nptr += 6;
256 }
257 }
258 while (*tptr) {
259 if (tptr == lptr) {
260 strcpy(nptr, "24");
261 nptr += 2;
262 tptr += nlindig;
263 }
264 else if (tptr == cptr) {
265 strcpy(nptr, "80");
266 nptr += 2;
267 tptr += ncoldig;
268 }
269 else *nptr++ = *tptr++;
270 }
271
272 *nptr = '\0';
273
274 /* Replace the old one */
275 free(*eptr);
276 *eptr = newenv;
277 }
278 else {
279 /* Just overwrite the old numbers */
280 *lptr++ = '2';
281 *lptr = '4';
282 *cptr++ = '8';
283 *cptr = '0';
284 }
285 }
286 }
287 }
288 }
289 #endif
290 init_things(); /* Set up probabilities of things */
291 init_colors(); /* Set up colors of potions */
292 init_stones(); /* Set up stone settings of rings */
293 init_materials(); /* Set up materials of wands */
294 initscr(); /* Start up cursor package */
295 init_names(); /* Set up names of scrolls */
296 init_misc(); /* Set up miscellaneous magic */
297 init_foods(); /* set up the food table */
298
299 cols = COLS;
300 lines = LINES;
301 if (cols > 85) cols = 85;
302 if (lines > 24) lines = 24;
303 if (lines < 23 || cols < 75) { /* give player a break if larger font used */
304 printf("\nERROR: screen size too small for rogue\n");
305 byebye(0);
306 }
307
308 /*
309 * Now that we have cols and lines, we can update our window
310 * structure for non-hardware windows.
311 */
312 #ifdef PC7300
313 if (hardwindow < 0) {
314 wdata.uw_x = 0;
315 wdata.uw_y = 0;
316 wdata.uw_width = COLS;
317 wdata.uw_height = LINES;
318 wdata.uw_uflags = 0;
319 wdata.uw_hs = 1;
320 wdata.uw_vs = 1;
321 wdata.uw_baseline = 0;
322 }
323 #endif
324 setup();
325 /*
326 * Set up windows
327 */
328 cw = newwin(lines, cols, 0, 0);
329 mw = newwin(lines, cols, 0, 0);
330 hw = newwin(lines, cols, 0, 0);
331 msgw = newwin(4, cols, 0, 0);
332 keypad(cw,TRUE);
333 keypad(msgw,TRUE);
334
335 init_player(); /* Roll up the rogue */
336 waswizard = wizard;
337
338 #ifdef WIZARD
339 /* A super wizard doesn't have to get equipped */
340 if (wizard && strcmp(getenv("SUPER"),"YES") == 0) {
341 level = 1;
342 new_level(NORMLEV);
343 }
344 else
345 #endif
346 new_level(STARTLEV); /* Draw current level */
347 /*
348 * Start up daemons and fuses
349 */
350 daemon(doctor, &player, AFTER);
351 fuse(swander, 0, WANDERTIME, AFTER);
352 if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER)
353 fuse(spell_recovery, 0, SPELLTIME, AFTER);
354 if (player.t_ctype == C_DRUID || player.t_ctype == C_RANGER)
355 fuse(chant_recovery, 0, SPELLTIME, AFTER);
356 if (player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN)
357 fuse(prayer_recovery, 0, SPELLTIME, AFTER);
358 daemon(stomach, 0, AFTER);
359 if (player.t_ctype == C_THIEF ||
360 player.t_ctype == C_ASSASIN ||
361 player.t_ctype == C_MONK)
362 daemon(trap_look, 0, AFTER);
363
364 /* Does this character have any special knowledge? */
365 switch (player.t_ctype) {
366 case C_ASSASIN:
367 /* Assassins automatically recognize poison */
368 p_know[P_POISON] = TRUE;
369 }
370
371 /* Choose a quest item */
372 quest_item = rnd(MAXRELIC);
373 draw(cw);
374 msg("You have been quested to retrieve the %s....",
375 rel_magic[quest_item].mi_name);
376 mpos = 0;
377 playit();
378 }
379
380 /*
381 * endit:
382 * Exit the program abnormally.
383 */
384
385 void
386 endit(sig)
387 int sig;
388 {
389 fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
390 }
391
392 /*
393 * fatal:
394 * Exit the program, printing a message.
395 */
396
397 fatal(s)
398 char *s;
399 {
400 clear();
401 move(lines-2, 0);
402 printw("%s", s);
403 draw(stdscr);
404 endwin();
405 #ifdef PC7300
406 endhardwin();
407 #endif
408 printf("\n"); /* So the curser doesn't stop at the end of the line */
409 exit(0);
410 }
411
412 /*
413 * rnd:
414 * Pick a very random number.
415 */
416 rnd(range)
417 register int range;
418 {
419 return(range <= 0 ? 0 : md_rand() % range);
420 }
421
422 /*
423 * roll:
424 * roll a number of dice
425 */
426
427 roll(number, sides)
428 register int number, sides;
429 {
430 register int dtotal = 0;
431
432 while(number--)
433 dtotal += rnd(sides)+1;
434 return dtotal;
435 }
436 # ifdef SIGTSTP
437 /*
438 * handle stop and start signals
439 */
440 void
441 tstp(sig)
442 int sig;
443 {
444 mvcur(0, cols - 1, lines - 1, 0);
445 endwin();
446 fflush(stdout);
447 kill(0, SIGTSTP);
448 signal(SIGTSTP, tstp);
449 raw();
450 noecho();
451 keypad(cw,1);
452 keypad(msgw,1);
453 clearok(curscr, TRUE);
454 touchwin(cw);
455 draw(cw);
456 md_flushinp();
457 }
458 # endif
459
460 setup()
461 {
462 #ifdef CHECKTIME
463 int checkout();
464
465 if (!author()) {
466 signal(SIGALRM, checkout);
467 alarm(CHECKTIME * 60);
468 }
469 #endif
470 /*
471 #ifndef DUMP
472 signal(SIGILL, bugkill);
473 #ifdef SIGTRAP
474 signal(SIGTRAP, bugkill);
475 #endif
476 #ifdef SIGIOT
477 signal(SIGIOT, bugkill);
478 #endif
479 #ifdef SIGEMT
480 signal(SIGEMT, bugkill);
481 #endif
482 signal(SIGFPE, bugkill);
483 #ifdef SIGBUS
484 signal(SIGBUS, bugkill);
485 #endif
486 signal(SIGSEGV, bugkill);
487 #ifdef SIGSYS
488 signal(SIGSYS, bugkill);
489 #endif
490 #ifdef SIGPIPE
491 signal(SIGPIPE, bugkill);
492 #endif
493 #endif
494 */
495 #ifdef SIGTSTP
496 signal(SIGTSTP, tstp);
497 #endif
498
499 #ifdef SIGHUP
500 signal(SIGHUP, auto_save);
501 #endif
502 signal(SIGTERM, auto_save);
503 signal(SIGINT, quit);
504 #ifdef SIGQUIT
505 signal(SIGQUIT, endit);
506 #endif
507 raw(); /* Cbreak mode */
508 noecho(); /* Echo off */
509 }
510
511 /*
512 * playit:
513 * The main loop of the program. Loop until the game is over,
514 * refreshing things and looking at the proper times.
515 */
516
517 playit()
518 {
519 register char *opts;
520
521
522 /*
523 * parse environment declaration of options
524 */
525 if ((opts = getenv("ROGUEOPTS")) != NULL)
526 parse_opts(opts);
527
528
529 player.t_oldpos = hero;
530 oldrp = roomin(&hero);
531 after = TRUE;
532 command(); /* Command execution */
533 endit(0);
534 }
535
536 /*
537 * see if the system is being used too much for this game
538 */
539 too_much()
540 {
541 #if MAXPROCESSES
542 if (loadav() > MAXPROCESSES)
543 return(TRUE);
544 #endif
545 #if MAXUSERS
546 if (ucount() > MAXUSERS)
547 return(TRUE);
548 #endif
549 return(FALSE);
550 }
551
552 /*
553 * author:
554 * See if a user is an author of the program
555 */
556 author()
557 {
558 switch (md_getuid()) {
559 #if AUTHOR
560 case AUTHOR:
561 #endif
562 case 0: /* always OK for root to play */
563 return TRUE;
564 default:
565 return FALSE;
566 }
567 }
568
569
570 #if CHECKTIME
571 static int num_checks = 0; /* times we've gone over in checkout() */
572
573 checkout()
574 {
575 static char *msgs[] = {
576 "The system is too loaded for games. Please leave in %d minutes",
577 "Please save your game. You have %d minutes",
578 "This is your last chance. You had better leave in %d minutes",
579 };
580 int checktime;
581
582 signal(SIGALRM, checkout);
583 if (!holiday() && !author()) {
584 msg("Game time is over. Your game is being saved.\n\n");
585 auto_save(); /* NO RETURN */
586 }
587 if (too_much()) {
588 if (num_checks >= 3)
589 fatal("You didn't listen, so now you are DEAD !!\n");
590 checktime = CHECKTIME / (num_checks + 1);
591 chmsg(msgs[num_checks++], checktime);
592 alarm(checktime * 60);
593 }
594 else {
595 if (num_checks) {
596 chmsg("The load has dropped. You have a reprieve.");
597 num_checks = 0;
598 }
599 alarm(CHECKTIME * 60);
600 }
601 }
602
603 /*
604 * checkout()'s version of msg. If we are in the middle of a shell, do a
605 * printf instead of a msg to avoid the refresh.
606 */
607 chmsg(fmt, arg)
608 char *fmt;
609 int arg;
610 {
611 if (in_shell) {
612 printf(fmt, arg);
613 putchar('\n');
614 fflush(stdout);
615 }
616 else
617 msg(fmt, arg);
618 }
619 #endif
620
621 #ifdef MAXPROCESSES
622
623 #include <fcntl.h>
624
625 loadav()
626 {
627 char *sarcmd = "sar -v | cut -c17-20 | tail -2";
628 char *gettycmd = "grep getty /etc/inittab | wc -l";
629 char sysbuffer[BUFSIZ];
630 char tempfile[50];
631 char inbuf[BUFSIZ];
632 int fd, nprocess, ngetty;
633
634 sprintf(tempfile, "/tmp/rg%d", getpid());
635 sprintf(sysbuffer, "%s > %s", sarcmd, tempfile);
636 if (system(sysbuffer) != 0) {
637 debug ("system() call failed");
638 return (MAXPROCESSES - 1);
639 }
640 if ((fd = open(tempfile, O_RDONLY)) == -1) {
641 debug ("open() call failed");
642 return (MAXPROCESSES - 1);
643 }
644 if (read(fd, inbuf, BUFSIZ) == -1) {
645 debug ("read() call failed");
646 return (MAXPROCESSES - 1);
647 }
648 close(fd);
649 sscanf(inbuf, "%d", &nprocess);
650 sprintf(sysbuffer, "%s > %s", gettycmd, tempfile);
651 if (system(sysbuffer) != 0) {
652 debug ("system() call failed");
653 return (MAXPROCESSES - 1);
654 }
655 if ((fd = open(tempfile, O_RDONLY)) == -1) {
656 debug ("open() call failed");
657 return (MAXPROCESSES - 1);
658 }
659 if (read(fd, inbuf, BUFSIZ) == -1) {
660 debug ("read() call failed");
661 return (MAXPROCESSES - 1);
662 }
663 close(fd);
664 sscanf(inbuf, "%d", &ngetty);
665 unlink(tempfile);
666 return(nprocess - ngetty);
667 }
668 #endif
669
670 #ifdef MAXUSERS
671 /*
672 * ucount:
673 * Count the number of people on the system
674 */
675 #include <sys/types.h>
676 #include <utmp.h>
677 struct utmp buf;
678 ucount()
679 {
680 reg struct utmp *up;
681 reg FILE *utmp;
682 reg int count;
683
684 if ((utmp = fopen(UTMP, "r")) == NULL)
685 return 0;
686
687 up = &buf;
688 count = 0;
689 while (fread(up, 1, sizeof (*up), utmp) > 0)
690 #ifdef BSD
691 if (buf.ut_line[0] == 't') /* On a tty */
692 #else
693 if (buf.ut_type == USER_PROCESS)
694 #endif
695 count++;
696 fclose(utmp);
697 return count;
698 }
699 #endif
700
701 /*
702 * holiday:
703 * Returns TRUE when it is a good time to play rogue
704 */
705 holiday()
706 {
707 #ifdef CHECKTIME
708 long now;
709 struct tm *localtime();
710 reg struct tm *ntime;
711
712
713 time(&now); /* get the current time */
714 ntime = localtime(&now);
715 if(ntime->tm_wday == 0 || ntime->tm_wday == 6)
716 return TRUE; /* OK on Sat & Sun */
717 if(ntime->tm_hour < 8 || ntime->tm_hour >= 18)
718 return TRUE; /* OK before 8AM & after 6PM */
719 if(ntime->tm_yday <= 7 || ntime->tm_yday >= 350)
720 return TRUE; /* OK during Christmas */
721 return FALSE; /* All other times are bad */
722 #else
723 return TRUE;
724 #endif
725 }