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