Source:NetHack 1.4f/pcmain.c

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