Source:NetHack 2.2a/pcmain.c

From NetHackWiki
Revision as of 02:33, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 2.2a/pcmain.c moved to Source:NetHack 2.2a/pcmain.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 pcmain.c from the source code of NetHack 2.2a. To link to a particular line, write [[NetHack 2.2a/pcmain.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: @(#)pcmain.c	2.1	87/10/18
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* main.c - (PC) version */
4.    
5.    #include <stdio.h>
6.    #include <signal.h>
7.    #include "hack.h"
8.    
9.    #ifdef QUEST
10.   #define	gamename	"PC NetQuest"
11.   #else
12.   #define	gamename	"PC NetHack"
13.   #endif
14.   
15.   char orgdir[PATHLEN], *getcwd();
16.   
17.   extern struct permonst mons[CMNUM+2];
18.   extern char genocided[], fut_geno[];
19.   extern char *getlogin(), *getenv();
20.   extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
21.   
22.   int (*afternmv)(), done1(), (*occupation)();
23.   
24.   char SAVEF[FILENAME];
25.   char *hname = gamename;
26.   char obuf[BUFSIZ];	/* BUFSIZ is defined in stdio.h */
27.   int hackpid;		/* not used anymore, but kept in for save files */
28.   
29.   extern char *nomovemsg;
30.   extern long wailmsg;
31.   
32.   main(argc,argv)
33.   int argc;
34.   char *argv[];
35.   {
36.   	register int fd;
37.   	register char *dir;
38.   #ifdef MSDOS
39.   	static void moveloop();	/* a helper function for MSC optimizer */
40.   
41.   	/* Save current directory and make sure it gets restored when
42.   	 * the game is exited.
43.   	 */
44.   	int (*funcp)();
45.   
46.   	if (getcwd(orgdir, sizeof orgdir) == NULL) {
47.   		xputs("hack: current directory path too long\n");
48.   		_exit(1);
49.   	}
50.   	funcp = exit;	/* Kludge to get around LINT_ARGS of signal.
51.   			 * This will produce a compiler warning, but that's OK.
52.   			 */
53.   	signal(SIGINT, funcp);	/* restore original directory */
54.   #endif
55.   
56.   #ifdef GRAPHICS
57.   	/* Set the default values of the presentation characters */
58.   	memcpy((char *) &showsyms, (char *) &defsyms, sizeof(struct symbols));
59.   #endif
60.   #ifdef DGK
61.   	if ((dir = getenv("HACKDIR")) != (char *) NULL) {
62.   		(void) strcpy(hackdir, dir);
63.   		chdirx (dir, 1);
64.   	}
65.   	zero_finfo();
66.   	initoptions();
67.   	if (!hackdir[0])
68.   		(void) strcpy(hackdir, orgdir);
69.   	dir = hackdir;
70.   #else
71.   	dir = getenv("HACKDIR");
72.   	if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
73.   		argc--;
74.   		argv++;
75.   		dir = argv[0]+2;
76.   		if(*dir == '=' || *dir == ':') dir++;
77.   		if(!*dir && argc > 1) {
78.   			argc--;
79.   			argv++;
80.   			dir = argv[0];
81.   		}
82.   		if(!*dir)
83.   		    error("Flag -d must be followed by a directory name.");
84.   	}
85.   #endif /* DGK */
86.   
87.   	/*
88.   	 * Now we know the directory containing 'record' and
89.   	 * may do a prscore().
90.   	 */
91.   	if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
92.   		chdirx(dir,0);
93.   		prscore(argc, argv);
94.   		exit(0);
95.   	}
96.   
97.   	/*
98.   	 * It seems he really wants to play.
99.   	 * Remember tty modes, to be restored on exit.
100.  	 */
101.  	gettty();
102.  	setbuf(stdout,obuf);
103.  	setrandom();
104.  	startup();
105.  	init_corpses();	/* initialize optional corpse names */
106.  	cls();
107.  	u.uhp = 1;	/* prevent RIP on early quits */
108.  	u.ux = FAR;	/* prevent nscr() */
109.  
110.  	/*
111.  	 * We cannot do chdir earlier, otherwise gethdate will fail.
112.  	 */
113.  	chdirx(dir,1);
114.  
115.  	/*
116.  	 * Process options.
117.  	 */
118.  	while(argc > 1 && argv[1][0] == '-'){
119.  		argv++;
120.  		argc--;
121.  		switch(argv[0][1]){
122.  #ifdef WIZARD
123.  		case 'D':
124.  # ifdef MSDOS
125.  			wizard = TRUE;
126.  # else
127.  			if(!strcmp(getlogin(), WIZARD))
128.  				wizard = TRUE;
129.  			else {
130.  				settty("Sorry, you can't operate in debug mode.\n");
131.  				clearlocks();
132.  				exit(0);
133.  			}
134.  			break;
135.  #endif
136.  		case 'u':
137.  			if(argv[0][2])
138.  			  (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
139.  			else if(argc > 1) {
140.  			  argc--;
141.  			  argv++;
142.  			  (void) strncpy(plname, argv[0], sizeof(plname)-1);
143.  			} else
144.  				printf("Player name expected after -u\n");
145.  			break;
146.  #ifdef DGK
147.  		/* Person does not want to use a ram disk
148.  		 */
149.  		case 'R':
150.  			ramdisk = FALSE;
151.  			break;
152.  #endif
153.  		default:
154.  			/* allow -T for Tourist, etc. */
155.  			(void) strncpy(pl_character, argv[0]+1,
156.  				sizeof(pl_character)-1);
157.  
158.  			/* printf("Unknown option: %s\n", *argv); */
159.  		}
160.  	}
161.  
162.  #ifdef DGK
163.  	set_lock_and_bones();
164.  	copybones(FROMPERM);
165.  #endif
166.  #ifdef WIZARD
167.  	if (wizard)
168.  		(void) strcpy(plname, "wizard");
169.  	else
170.  #endif
171.  	if (!*plname)
172.  		askname();
173.  	plnamesuffix();		/* strip suffix from name; calls askname() */
174.  				/* again if suffix was whole name */
175.  				/* accepts any suffix */
176.  #ifdef WIZARD
177.  	if(wizard) {
178.  		register char *sfoo;
179.  # ifndef DGK
180.  		/* lock is set in read_config_file */
181.  		(void) strcpy(lock,plname);
182.  # endif
183.  		if(sfoo = getenv("MAGIC"))
184.  			while(*sfoo) {
185.  				switch(*sfoo++) {
186.  				case 'n': (void) srand(*sfoo++);
187.  					break;
188.  				}
189.  			}
190.  		if(sfoo = getenv("GENOCIDED")){
191.  			if(*sfoo == '!'){
192.  				register struct permonst *pm = mons;
193.  				register char *gp = genocided;
194.  
195.  				while(pm < mons+CMNUM+2){
196.  					if(!index(sfoo, pm->mlet))
197.  						*gp++ = pm->mlet;
198.  					pm++;
199.  				}
200.  				*gp = 0;
201.  			} else
202.  				(void) strcpy(genocided, sfoo);
203.  			(void) strcpy(fut_geno, genocided);
204.  		}
205.  	}
206.  #endif /* WIZARD */
207.  	start_screen();
208.  #ifdef DGK
209.  	strncat(SAVEF, plname, 8);
210.  	strcat(SAVEF, ".sav");
211.  	cls();
212.  	if (saveDiskPrompt(1) && ((fd = open(SAVEF, 0)) >= 0) &&
213.  	   (uptodate(fd) || !unlink(SAVEF))) {
214.  #else 
215.  	(void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
216.  	regularize(SAVEF+5);		/* avoid . or / in name */
217.  	if((fd = open(SAVEF,0)) >= 0 &&
218.  	   (uptodate(fd) || unlink(SAVEF) == 666)) {
219.  #endif /* DGK */
220.  		(void) signal(SIGINT,done1);
221.  		pline("Restoring old save file...");
222.  		(void) fflush(stdout);
223.  		if(!dorecover(fd))
224.  			goto not_recovered;
225.  		pline("Hello %s, welcome to %s!", plname, hname);
226.  		flags.move = 0;
227.  	} else {
228.  not_recovered:
229.  #ifdef DGK
230.  		gameDiskPrompt();
231.  #endif
232.  		fobj = fcobj = invent = 0;
233.  		fmon = fallen_down = 0;
234.  		ftrap = 0;
235.  		fgold = 0;
236.  		flags.ident = 1;
237.  		init_objects();
238.  		u_init();
239.  
240.  		(void) signal(SIGINT,done1);
241.  		mklev();
242.  		u.ux = xupstair;
243.  		u.uy = yupstair;
244.  		(void) inshop();
245.  		setsee();
246.  		flags.botlx = 1;
247.  		/* Fix bug with dog not being made because a monster
248.  		 * was on the level 1 staircase
249.  		 */
250.  		{
251.  			struct monst *mtmp;
252.  
253.  			if (mtmp = m_at(u.ux, u.uy))
254.  				mnexto(mtmp);
255.  		}
256.  		makedog();
257.  		{ register struct monst *mtmp;
258.  		  if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp);	/* riv05!a3 */
259.  		}
260.  		seemons();
261.  		docrt();
262.  
263.  		/* give welcome message before pickup messages */
264.  		pline("Hello %s, welcome to %s!", plname, hname);
265.  
266.  		pickup(1);
267.  		read_engr_at(u.ux,u.uy);
268.  		flags.move = 1;
269.  	}
270.  	flags.moonphase = phase_of_the_moon();
271.  	if(flags.moonphase == FULL_MOON) {
272.  		pline("You are lucky! Full moon tonight.");
273.  		if(!u.uluck) u.uluck++;
274.  	} else if(flags.moonphase == NEW_MOON) {
275.  		pline("Be careful! New moon tonight.");
276.  	}
277.  
278.  	initrack();
279.  	(void) signal(SIGINT, SIG_IGN);
280.  #ifdef MSDOS
281.  	/* Help for Microsoft optimizer.  Otherwise main is too large -dgk*/
282.  	moveloop();
283.  }
284.  
285.  static void
286.  moveloop()
287.  {
288.  	char ch;
289.  	int abort;
290.  #endif /* MSDOS */
291.  	for(;;) {
292.  		if(flags.move) {	/* actual time passed */
293.  
294.  			settrack();
295.  
296.  			if(moves%2 == 0 ||
297.  			  (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
298.  				extern struct monst *makemon();
299.  				movemon();
300.  #ifdef HARD
301.  				if(!rn2(u.udemigod?25:(dlevel>30)?50:70))
302.  #else
303.  				if(!rn2(70))
304.  #endif
305.  				    (void) makemon((struct permonst *)0, 0, 0);
306.  			}
307.  			if(Glib) glibr();
308.  			timeout();
309.  			++moves;
310.  #ifdef PRAYERS
311.  			if (u.ublesscnt)  u.ublesscnt--;
312.  #endif
313.  #ifndef DGK
314.  			if(flags.time) flags.botl = 1;
315.  #endif
316.  #ifdef KAA
317.  			if(u.mtimedone)
318.  			    if(u.mh < 1) rehumanize();
319.  			else
320.  #endif
321.  			    if(u.uhp < 1) {
322.  				pline("You die...");
323.  				done("died");
324.  			    }
325.  			if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
326.  			    wailmsg = moves;
327.  #ifdef KAA
328.  				if(index("WEV", pl_character[0])) {
329.  					if (u.uhp == 1)
330.  					   pline("%s is about to die.", pl_character);
331.  					else
332.  					   pline("%s, your life force is running out.",
333.  						pl_character);
334.  				} else {
335.  #endif
336.  			    if(u.uhp == 1)
337.  			    pline("You hear the wailing of the Banshee...");
338.  			    else
339.  			    pline("You hear the howling of the CwnAnnwn...");
340.  #ifdef KAA
341.  				}
342.  #endif
343.  			}
344.  #ifdef KAA
345.  			if (u.mtimedone) {
346.  			    if (u.mh < u.mhmax) {
347.  				if (Regeneration || !(moves%20)) {
348.  					flags.botl = 1;
349.  					u.mh++;
350.  				}
351.  			    }
352.  			}
353.  #endif
354.  			if(u.uhp < u.uhpmax) {
355.  				if(u.ulevel > 9) {
356.  					if(HRegeneration || !(moves%3)) {
357.  					    flags.botl = 1;
358.  					    u.uhp += rnd((int) u.ulevel-9);
359.  					    if(u.uhp > u.uhpmax)
360.  						u.uhp = u.uhpmax;
361.  					}
362.  				} else if(HRegeneration ||
363.  					(!(moves%(22-u.ulevel*2)))) {
364.  					flags.botl = 1;
365.  					u.uhp++;
366.  				}
367.  			}
368.  #ifdef SPELLS
369.  			if ((u.uen<u.uenmax) && (!(moves%(21-u.ulevel/2)))) {
370.  				u.uen += rn2(u.ulevel/4 + 1) + 1;
371.  				if (u.uen > u.uenmax)  u.uen = u.uenmax;
372.  				flags.botl = 1;
373.  			}
374.  #endif
375.  			if(Teleportation && !rn2(85)) tele();
376.  #if defined(KAA) && defined(BVH)
377.  			if(Polymorph && !rn2(100)) polyself();
378.  #endif
379.  			if(Searching && multi >= 0) (void) dosearch();
380.  			gethungry();
381.  			invault();
382.  			amulet();
383.  #ifdef HARD
384.  			if (!rn2(50+(u.ulevel*3))) u_wipe_engr(rnd(3));
385.  			if (u.udemigod) {
386.  
387.  				u.udg_cnt--;
388.  				if(u.udg_cnt <= 0) {
389.  
390.  					intervene();
391.  					u.udg_cnt = rn1(200, 50);
392.  				}
393.  			}
394.  #endif
395.  		}
396.  		if(multi < 0) {
397.  			if(!++multi){
398.  				pline(nomovemsg ? nomovemsg :
399.  					"You can move again.");
400.  				nomovemsg = 0;
401.  				if(afternmv) (*afternmv)();
402.  				afternmv = 0;
403.  			}
404.  		}
405.  
406.  		find_ac();
407.  #ifndef QUEST
408.  		if(!flags.mv || Blind)
409.  #endif
410.  		{
411.  			seeobjs();
412.  			seemons();
413.  			nscr();
414.  		}
415.  #ifdef DGK
416.  		if(flags.time) flags.botl = 1;
417.  #endif
418.  		if(flags.botl || flags.botlx) bot();
419.  
420.  		flags.move = 1;
421.  
422.  		if(multi >= 0 && occupation) {
423.  #ifdef DGK
424.  			abort = 0;
425.  			if (kbhit()) {
426.  				if ((ch = getchar()) == ABORT)
427.  					abort++;
428.  # ifdef REDO
429.  				else
430.  					pushch(ch);
431.  # endif
432.  			}
433.  			if (abort || monster_nearby())
434.  				stop_occupation();
435.  			else if ((*occupation)() == 0)
436.  				occupation = 0;
437.  			if (!(++occtime % 7))
438.  				(void) fflush(stdout);
439.  #else
440.  			if (monster_nearby())
441.  				stop_occupation();
442.  			else if ((*occupation)() == 0)
443.  				occupation = 0;
444.  #endif
445.  			continue;
446.  		}
447.  
448.  		if(multi > 0) {
449.  #ifdef QUEST
450.  			if(flags.run >= 4) finddir();
451.  #endif
452.  			lookaround();
453.  			if(!multi) {	/* lookaround may clear multi */
454.  				flags.move = 0;
455.  				continue;
456.  			}
457.  			if(flags.mv) {
458.  				if(multi < COLNO && !--multi)
459.  					flags.mv = flags.run = 0;
460.  				domove();
461.  			} else {
462.  				--multi;
463.  				rhack(save_cm);
464.  			}
465.  		} else if(multi == 0) {
466.  			rhack((char *) 0);
467.  		}
468.  		if(multi && multi%7 == 0)
469.  			(void) fflush(stdout);
470.  	}
471.  }
472.  
473.  #ifndef DGK
474.  /* This function is unnecessary and incompatible with the #define
475.   * of glo(x) in config.h -dgk
476.   */
477.  glo(foo)
478.  register foo;
479.  {
480.  	/* construct the string  xlock.n  */
481.  	register char *tf;
482.  
483.  	tf = lock;
484.  	while(*tf && *tf != '.') tf++;
485.  	(void) sprintf(tf, ".%d", foo);
486.  }
487.  #endif
488.  
489.  /*
490.   * plname is filled either by an option (-u Player  or  -uPlayer) or
491.   * explicitly (-w implies wizard) or by askname.
492.   * It may still contain a suffix denoting pl_character.
493.   */
494.  askname(){
495.  register int c,ct;
496.  	printf("\nWho are you? ");
497.  	(void) fflush(stdout);
498.  	ct = 0;
499.  	while((c = getchar()) != '\n'){
500.  #ifdef MSDOS
501.  		msmsg("%c", c);
502.  #endif
503.  		if(c == EOF) error("End of input\n");
504.  		/* some people get confused when their erase char is not ^H */
505.  		if(c == '\010') {
506.  			if(ct) ct--;
507.  			continue;
508.  		}
509.  		if(c != '-')
510.  		if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
511.  		if(ct < sizeof(plname)-1) plname[ct++] = c;
512.  	}
513.  	plname[ct] = 0;
514.  	if(ct == 0) askname();
515.  }
516.  
517.  /*VARARGS1*/
518.  impossible(s,x1,x2)
519.  register char *s;
520.  {
521.  	pline(s,x1,x2);
522.  	pline("Program in disorder - perhaps you'd better Quit.");
523.  }
524.  
525.  #ifdef CHDIR
526.  chdirx(dir, wr)
527.  char *dir;
528.  boolean wr;
529.  {
530.  
531.  	if(dir && chdir(dir) < 0) {
532.  		error("Cannot chdir to %s.", dir);
533.  	}
534.  
535.  #ifdef DGK
536.  	/* Change the default drive as well.
537.  	 */
538.  	chdrive(dir);
539.  #endif
540.  
541.  	/* warn the player if he cannot write the record file */
542.  	/* perhaps we should also test whether . is writable */
543.  	/* unfortunately the access systemcall is worthless */
544.  	if(wr) {
545.  	    register fd;
546.  
547.  	    if(dir == NULL)
548.  		dir = ".";
549.  	    if((fd = open(RECORD, 2)) < 0) {
550.  #ifdef DGK
551.  		char tmp[PATHLEN];
552.  
553.  		strcpy(tmp, dir);
554.  		append_slash(tmp);
555.  		msmsg("Warning: cannot write %s%s\n", tmp, RECORD);
556.  		getreturn("to continue");
557.  #else
558.  		printf("Warning: cannot write %s/%s", dir, RECORD);
559.  		getret();
560.  #endif
561.  	    } else
562.  		(void) close(fd);
563.  	}
564.  }
565.  #endif /* CHDIR /**/
566.  
567.  stop_occupation()
568.  {
569.  	if(occupation) {
570.  		pline("You stop %s.", occtxt);
571.  		occupation = 0;
572.  #ifdef REDO
573.  		multi = 0;
574.  		pushch(0);		
575.  #endif
576.  	}
577.  }
578.  
579.  #ifdef DGK
580.  struct finfo	zfinfo = ZFINFO;
581.  
582.  zero_finfo() {	/* zero "fileinfo" array to prevent crashes on level change */
583.  	int i;
584.  
585.  	for (i = 0 ; i <= MAXLEVEL; i++)
586.  		fileinfo[i] = zfinfo;
587.  }
588.  #endif