Source:NetHack 2.2a/unixmain.c

From NetHackWiki
Revision as of 02:56, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 2.2a/unixmain.c moved to Source:NetHack 2.2a/unixmain.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to unixmain.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/unixmain.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

Screenshots and source code from Hack are used under the CWI license.

1.    /*	SCCS Id: @(#)unixmain.c	2.1	87/10/18
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* main.c - (Unix) version */
4.    
5.    #include <stdio.h>
6.    #include <signal.h>
7.    #include "hack.h"
8.    
9.    #ifdef QUEST
10.   #define	gamename	"NetQuest"
11.   #else
12.   #define	gamename	"NetHack"
13.   #endif
14.   
15.   extern char *getlogin(), *getenv();
16.   extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
17.   
18.   int (*afternmv)();
19.   int (*occupation)();
20.   
21.   int done1();
22.   int hangup();
23.   
24.   int hackpid;				/* current pid */
25.   int locknum;				/* max num of players */
26.   #ifdef DEF_PAGER
27.   char *catmore;				/* default pager */
28.   #endif
29.   char SAVEF[PL_NSIZ + 11] = "save/";	/* save/99999player */
30.   char *hname;		/* name of the game (argv[0] of call) */
31.   char obuf[BUFSIZ];	/* BUFSIZ is defined in stdio.h */
32.   
33.   extern char *nomovemsg;
34.   extern long wailmsg;
35.   
36.   main(argc,argv)
37.   int argc;
38.   char *argv[];
39.   {
40.   	register int fd;
41.   #ifdef CHDIR
42.   	register char *dir;
43.   #endif
44.   
45.   	hname = argv[0];
46.   	hackpid = getpid();
47.   
48.   #ifdef CHDIR			/* otherwise no chdir() */
49.   	/*
50.   	 * See if we must change directory to the playground.
51.   	 * (Perhaps hack runs suid and playground is inaccessible
52.   	 *  for the player.)
53.   	 * The environment variable HACKDIR is overridden by a
54.   	 *  -d command line option (must be the first option given)
55.   	 */
56.   
57.   	dir = getenv("HACKDIR");
58.   	if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
59.   		argc--;
60.   		argv++;
61.   		dir = argv[0]+2;
62.   		if(*dir == '=' || *dir == ':') dir++;
63.   		if(!*dir && argc > 1) {
64.   			argc--;
65.   			argv++;
66.   			dir = argv[0];
67.   		}
68.   		if(!*dir)
69.   		    error("Flag -d must be followed by a directory name.");
70.   	}
71.   #endif /* CHDIR /**/
72.   #ifdef GRAPHICS
73.   	/* Set the default values of the presentation characters */
74.   	memcpy((char *) &showsyms, (char *) &defsyms, sizeof(struct symbols));
75.   #endif
76.   #ifdef HACKOPTIONS
77.   	initoptions();
78.   #endif
79.   	whoami();
80.   	/*
81.   	 * Now we know the directory containing 'record' and
82.   	 * may do a prscore().
83.   	 */
84.   	if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
85.   #ifdef CHDIR
86.   		chdirx(dir,0);
87.   #endif
88.   		prscore(argc, argv);
89.   		exit(0);
90.   	}
91.   
92.   	/*
93.   	 * It seems he really wants to play.
94.   	 * Remember tty modes, to be restored on exit.
95.   	 */
96.   	gettty();
97.   	setbuf(stdout,obuf);
98.   	setrandom();
99.   	startup();
100.  	init_corpses();	/* initialize optional corpse names */
101.  	cls();
102.  	u.uhp = 1;	/* prevent RIP on early quits */
103.  	u.ux = FAR;	/* prevent nscr() */
104.  	(void) signal(SIGHUP, hangup);
105.  
106.  	/*
107.  	 * Find the creation date of this game,
108.  	 * so as to avoid restoring outdated savefiles.
109.  	 */
110.  	gethdate(hname);
111.  
112.  	/*
113.  	 * We cannot do chdir earlier, otherwise gethdate will fail.
114.  	 */
115.  #ifdef CHDIR
116.  	chdirx(dir,1);
117.  #endif
118.  
119.  	/*
120.  	 * Process options.
121.  	 */
122.  	while(argc > 1 && argv[1][0] == '-'){
123.  		argv++;
124.  		argc--;
125.  		switch(argv[0][1]){
126.  #ifdef WIZARD
127.  		case 'D':
128.  			if(!strcmp(getlogin(), WIZARD))
129.  				wizard = TRUE;
130.  			else {
131.  				settty("Sorry, you can't operate in debug mode.\n");
132.  				clearlocks();
133.  				exit(0);
134.  			}
135.  			break;
136.  #endif
137.  #ifdef NEWS
138.  		case 'n':
139.  			flags.nonews = TRUE;
140.  			break;
141.  #endif
142.  		case 'u':
143.  			if(argv[0][2])
144.  			  (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
145.  			else if(argc > 1) {
146.  			  argc--;
147.  			  argv++;
148.  			  (void) strncpy(plname, argv[0], sizeof(plname)-1);
149.  			} else
150.  				printf("Player name expected after -u\n");
151.  			break;
152.  		default:
153.  			/* allow -T for Tourist, etc. */
154.  			(void) strncpy(pl_character, argv[0]+1,
155.  				sizeof(pl_character)-1);
156.  
157.  			/* printf("Unknown option: %s\n", *argv); */
158.  		}
159.  	}
160.  
161.  	if(argc > 1)
162.  		locknum = atoi(argv[1]);
163.  #ifdef MAX_NR_OF_PLAYERS
164.  	if(!locknum || locknum > MAX_NR_OF_PLAYERS)
165.  		locknum = MAX_NR_OF_PLAYERS;
166.  #endif
167.  #ifdef DEF_PAGER
168.  	if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER")))
169.  		catmore = DEF_PAGER;
170.  #endif
171.  #ifdef MAIL
172.  	getmailstatus();
173.  #endif
174.  #ifdef WIZARD
175.  	if(wizard) (void) strcpy(plname, "wizard"); else
176.  #endif
177.  	if(!*plname || !strncmp(plname, "player", 4)
178.  		    || !strncmp(plname, "games", 4))
179.  		askname();
180.  	plnamesuffix();		/* strip suffix from name; calls askname() */
181.  				/* again if suffix was whole name */
182.  				/* accepts any suffix */
183.  #ifdef WIZARD
184.  	if(!wizard) {
185.  #endif
186.  		/*
187.  		 * check for multiple games under the same name
188.  		 * (if !locknum) or check max nr of players (otherwise)
189.  		 */
190.  		(void) signal(SIGQUIT,SIG_IGN);
191.  		(void) signal(SIGINT,SIG_IGN);
192.  		if(!locknum)
193.  			(void) strcpy(lock,plname);
194.  		getlock();	/* sets lock if locknum != 0 */
195.  #ifdef WIZARD
196.  	} else {
197.  		register char *sfoo;
198.  		extern char genocided[], fut_geno[];
199.  		(void) strcpy(lock,plname);
200.  		if(sfoo = getenv("MAGIC"))
201.  			while(*sfoo) {
202.  				switch(*sfoo++) {
203.  				case 'n': (void) srand(*sfoo++);
204.  					break;
205.  				}
206.  			}
207.  		if(sfoo = getenv("GENOCIDED")){
208.  			if(*sfoo == '!'){
209.  				extern struct permonst mons[CMNUM+2];
210.  				register struct permonst *pm = mons;
211.  				register char *gp = genocided;
212.  
213.  				while(pm < mons+CMNUM+2){
214.  					if(!index(sfoo, pm->mlet))
215.  						*gp++ = pm->mlet;
216.  					pm++;
217.  				}
218.  				*gp = 0;
219.  			} else
220.  				(void) strcpy(genocided, sfoo);
221.  			(void) strcpy(fut_geno, genocided);
222.  		}
223.  	}
224.  #endif /* WIZARD /**/
225.  	setftty();
226.  	(void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
227.  	regularize(SAVEF+5);		/* avoid . or / in name */
228.  	if((fd = open(SAVEF,0)) >= 0 &&
229.  	   (uptodate(fd) || unlink(SAVEF) == 666)) {
230.  		(void) signal(SIGINT,done1);
231.  		pline("Restoring old save file...");
232.  		(void) fflush(stdout);
233.  		if(!dorecover(fd))
234.  			goto not_recovered;
235.  		pline("Hello %s, welcome to %s!", plname, gamename);
236.  		flags.move = 0;
237.  	} else {
238.  not_recovered:
239.  		newgame();
240.  		/* give welcome message before pickup messages */
241.  		pline("Hello %s, welcome to %s!", plname, gamename);
242.  
243.  		pickup(1);
244.  		read_engr_at(u.ux,u.uy);
245.  		flags.move = 1;
246.  	}
247.  
248.  	flags.moonphase = phase_of_the_moon();
249.  	if(flags.moonphase == FULL_MOON) {
250.  		pline("You are lucky! Full moon tonight.");
251.  		if(!u.uluck) u.uluck++;
252.  	} else if(flags.moonphase == NEW_MOON) {
253.  		pline("Be careful! New moon tonight.");
254.  	}
255.  
256.  	initrack();
257.  
258.  	for(;;) {
259.  		if(flags.move) {	/* actual time passed */
260.  
261.  			settrack();
262.  
263.  			if(moves%2 == 0 ||
264.  			  (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
265.  				extern struct monst *makemon();
266.  				movemon();
267.  #ifdef HARD
268.  				if(!rn2(u.udemigod?25:(dlevel>30)?50:70))
269.  #else
270.  				if(!rn2(70))
271.  #endif
272.  				    (void) makemon((struct permonst *)0, 0, 0);
273.  			}
274.  			if(Glib) glibr();
275.  			timeout();
276.  			++moves;</sp wailing of the Banshee...");
303.  				else
304.  				pline("You hear the howling of the CwnAnnwn...");
305.  #ifdef KAA
306.  			    }
307.  #endif
308.  			}
309.  #ifdef KAA
310.  			if (u.mtimedone) {
311.  			    if (u.mh < u.mhmax) {
312.  				if (Regeneration || !(moves%20)) {
313.  					flags.botl = 1;
314.  					u.mh++;
315.  				}
316.  			    }
317.  			}
318.  #endif
319.  			if(u.uhp < u.uhpmax) {
320.  				if(u.ulevel > 9) {
321.  					if(HRegeneration || !(moves%3)) {
322.  					    flags.botl = 1;
323.  					    u.uhp += rnd((int) u.ulevel-9);
324.  					    if(u.uhp > u.uhpmax)
325.  						u.uhp = u.uhpmax;
326.  					}
327.  				} else if(HRegeneration ||
328.  					(!(moves%(302">302.  				pline("You hear the wailing of the Banshee...");
303.  				else
304.  				pline("You hear the howling of the CwnAnnwn...");
305.  #ifdef KAA
306.  			    }
307.  #endif
308.  			}
309.  #ifdef KAA
310.  			if (u.mtimedone) {
311.  			    if (u.mh < u.mhmax) {
312.  				if (Regeneration || !(moves%20)) {
313.  					flags.botl = 1;
314.  					u.mh++;
315.  				}
316.  			    }
317.  			}
318.  #endif
319.  			if(u.uhp < u.uhpmax) {
320.  				if(u.ulevel > 9) {
321.  					if(HRegeneration || !(moves%3)) {
322.  					    flags.botl = 1;
323.  					    u.uhp += rnd((int) u.ulevel-9);
324.  					    if(u.uhp > u.uhpmax)
325.  						u.uhp = u.uhpmax;
326.  					}
327.  				} else if(HRegeneration ||
328.  					(!(moves%(22-u.ulevel*2)))) {
329.  					flags.botl = 1;
330.  					u.uhp++;
331.  				}
332.  			}
333.  #ifdef SPELLS
334.  			if ((u.uen<u.uenmax) && (!(moves%(21-u.ulevel/2)))) {
335.  				u.uen += rn2(u.ulevel/4 + 1) + 1;
336.  				if (u.uen > u.uenmax)  u.uen = u.uenmax;
337.  				flags.botl = 1;
338.  			}
339.  #endif
340.  			if(Teleportation && !rn2(85)) tele();
341.  #if defined(KAA) && defined(BVH)
342.  			if(Polymorph && !rn2(100)) polyself();
343.  #endif
344.  			if(Searching && multi >= 0) (void) dosearch();
345.  			gethungry();
346.  			invault();
347.  			amulet();
348.  #ifdef HARD
349.  			if (!rn2(50+(u.ulevel*3))) u_wipe_engr(rnd(3));
350.  			if (u.udemigod) {
351.  
352.  				u.udg_cnt--;
353.  				if(u.udg_cnt <= 0) {
354.  
355.  					intervene();
356.  					u.udg_cnt = rn1(200, 50);
357.  				}
358.  			}
359.  #endif
360.  		}
361.  		if(multi < 0) {
362.  			if(!++multi){
363.  				pline(nomovemsg ? nomovemsg :
364.  					"You can move again.");
365.  				nomovemsg = 0;
366.  				if(afternmv) (*afternmv)();
367.  				afternmv = 0;
368.  			}
369.  		}
370.  
371.  		find_ac();
372.  #ifndef QUEST
373.  		if(!flags.mv || Blind)
374.  #endif
375.  		{
376.  			seeobjs();
377.  			seemons();
378.  			nscr();
379.  		}
380.  #ifdef DGK
381.  		if(flags.time) flags.botl = 1;
382.  #endif
383.  		if(flags.botl || flags.botlx) bot();
384.  
385.  		flags.move = 1;
386.  
387.  		if(multi >= 0 && occupation) {
388.  
389.  			if (monster_nearby())
390.  				stop_occupation();
391.  			else if ((*occupation)() == 0)
392.  				occupation = 0;
393.  			continue;
394.  		}
395.  
396.  		if(multi > 0) {
397.  #ifdef QUEST
398.  			if(flags.run >= 4) finddir();
399.  #endif
400.  			lookaround();
401.  			if(!multi) {	/* lookaround may clear multi */
402.  				flags.move = 0;
403.  				continue;
404.  			}
405.  			if(flags.mv) {
406.  				if(multi < COLNO && !--multi)
407.  					flags.mv = flags.run = 0;
408.  				domove();
409.  			} else {
410.  				--multi;
411.  				rhack(save_cm);
412.  			}
413.  		} else if(multi == 0) {
414.  #ifdef MAIL
415.  			ckmailstatus();
416.  #endif
417.  			rhack((char *) 0);
418.  		}
419.  		if(multi && multi%7 == 0)
420.  			(void) fflush(stdout);
421.  	}
422.  }
423.  
424.  glo(foo)
425.  register foo;
426.  {
427.  	/* construct the string  xlock.n  */
428.  	register char *tf;
429.  
430.  	tf = lock;
431.  	while(*tf && *tf != '.') tf++;
432.  	(void) sprintf(tf, ".%d", foo);
433.  }
434.  
435.  /*
436.   * plname is filled either by an option (-u Player  or  -uPlayer) or
437.   * explicitly (-w implies wizard) or by askname.
438.   * It may still contain a suffix denoting pl_character.
439.   */
440.  askname(){
441.  register int c,ct;
442.  	printf("\nWho are you? ");
443.  	(void) fflush(stdout);
444.  	ct = 0;
445.  	while((c = getchar()) != '\n'){
446.  		if(c == EOF) error("End of input\n");
447.  		/* some people get confused when their erase char is not ^H */
448.  		if(c == '\010') {
449.  			if(ct) ct--;
450.  			continue;
451.  		}
452.  		if(c != '-')
453.  		if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
454.  		if(ct < sizeof(plname)-1) plname[ct++] = c;
455.  	}
456.  	plname[ct] = 0;
457.  	if(ct == 0) askname();
458.  }
459.  
460.  /*VARARGS1*/
461.  impossible(s,x1,x2)
462.  register char *s;
463.  {
464.  	pline(s,x1,x2);
465.  	pline("Program in disorder - perhaps you'd better Quit.");
466.  }
467.  
468.  #ifdef CHDIR
469.  static
470.  chdirx(dir, wr)
471.  char *dir;
472.  boolean wr;
473.  {
474.  
475.  # ifdef SECURE
476.  	if(dir					/* User specified directory? */
477.  #  ifdef HACKDIR
478.  	       && strcmp(dir, HACKDIR)		/* and not the default? */
479.  #  endif
480.  		) {
481.  		(void) setuid(getuid());		/* Ron Wessels */
482.  		(void) setgid(getgid());
483.  	}
484.  # endif
485.  
486.  # ifdef HACKDIR
487.  	if(dir == NULL)
488.  		dir = HACKDIR;
489.  # endif
490.  
491.  	if(dir && chdir(dir) < 0) {
492.  		perror(dir);
493.  		error("Cannot chdir to %s.", dir);
494.  	}
495.  
496.  	/* warn the player if he cannot write the record file */
497.  	/* perhaps we should also test whether . is writable */
498.  	/* unfortunately the access systemcall is worthless */
499.  	if(wr) {
500.  	    register fd;
501.  
502.  	    if(dir == NULL)
503.  		dir = ".";
504.  	    if((fd = open(RECORD, 2)) < 0) {
505.  		printf("Warning: cannot write %s/%s", dir, RECORD);
506.  		getret();
507.  	    } else
508.  		(void) close(fd);
509.  	}
510.  }
511.  #endif /* CHDIR /**/
512.  
513.  stop_occupation()
514.  {
515.  	if(occupation) {
516.  		pline("You stop %s.", occtxt);
517.  		occupation = 0;
518.  #ifdef REDO
519.  		multi = 0;
520.  		pushch(0);		
521.  #endif
522.  	}
523.  }
524.  
525.  whoami() {
526.  	/*
527.  	 * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS
528.  	 *			2. Use $USER or $LOGNAME	(if 1. fails)
529.  	 *			3. Use getlogin()		(if 2. fails)
530.  	 * The resulting name is overridden by command line options.
531.  	 * If everything fails, or if the resulting name is some generic
532.  	 * account like "games", "play", "player", "hack" then eventually
533.  	 * we'll ask him.
534.  	 * Note that we trust him here; it is possible to play under
535.  	 * somebody else's name.
536.  	 */
537.  	register char *s;
538.  
539.  #ifndef DGKMOD
540.  	initoptions();
541.  #endif
542.  	if(!*plname && (s = getenv("USER")))
543.  		(void) strncpy(plname, s, sizeof(plname)-1);
544.  	if(!*plname && (s = getenv("LOGNAME")))
545.  		(void) strncpy(plname, s, sizeof(plname)-1);
546.  	if(!*plname && (s = getlogin()))
547.  		(void) strncpy(plname, s, sizeof(plname)-1);
548.  }
549.  
550.  newgame() {
551.  	fobj = fcobj = invent = 0;
552.  	fmon = fallen_down = 0;
553.  	ftrap = 0;
554.  	fgold = 0;
555.  	flags.ident = 1;
556.  	init_objects();
557.  	u_init();
558.  
559.  	(void) signal(SIGINT,done1);
560.  	mklev();
561.  	u.ux = xupstair;
562.  	u.uy = yupstair;
563.  	(void) inshop();
564.  	setsee();
565.  	flags.botlx = 1;
566.  	{
567.  		register struct monst *mtmp;
568.  
569.  		/* Move the monster from under you or else
570.  		 * makedog() will fail when it calls makemon().
571.  		 * 			- ucsfcgl!kneller
572.  		 */
573.  		if (mtmp = m_at(u.ux, u.uy))  mnexto(mtmp);
574.  	}
575.  	(void) makedog();
576.  	seemons();
577.  #ifdef NEWS
578.  	if(flags.nonews || !readnews())
579.  		/* after reading news we did docrt() already */
580.  #endif
581.  		docrt();
582.  	return(0);
583.  }
584.  
585.  #ifdef GENIX
586.  jhndist(x1,y1,x2,y2)
587.  {
588.  	int x,y;
589.  	x=x1-x2;
590.  	y=y1-y2;
591.  	return (x*x + y*y);
592.  }
593.  #endif