Source:Hack 1.0/hack.main.c

From NetHackWiki
Revision as of 22:25, 3 March 2008 by Kernigh bot (talk | contribs) (Hack 1.0/hack.main.c moved to Source:Hack 1.0/hack.main.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 hack.main.c from the source code of Hack 1.0. To link to a particular line, write [[Hack 1.0/hack.main.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.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2.    
3.    #include <stdio.h>
4.    #include <signal.h>
5.    #include <errno.h>
6.    #include "hack.h"
7.    
8.    extern char *getlogin();
9.    extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
10.   extern char *getenv();
11.   
12.   int (*afternmv)();
13.   
14.   int done1();
15.   int hangup();
16.   
17.   char safelock[] = "safelock";
18.   xchar locknum;				/* max num of players */
19.   char *catmore = "/bin/cat";		/* or e.g. /usr/ucb/more */
20.   char SAVEF[PL_NSIZ + 5] = "save/";
21.   char perm[] = "perm";
22.   char *hname;		/* name of the game (argv[0] of call) */
23.   char obuf[BUFSIZ];	/* BUFSIZ is defined in stdio.h */
24.   
25.   extern char *nomovemsg;
26.   extern long wailmsg;
27.   
28.   main(argc,argv)
29.   int argc;
30.   char *argv[];
31.   {
32.   	int fd;
33.   #ifdef NEWS
34.   	int nonews = 0;
35.   #endif NEWS
36.   	char *dir;
37.   
38.   	hname = argv[0];
39.   
40.   	/*
41.   	 * See if we must change directory to the playground.
42.   	 * (Perhaps hack runs suid and playground is inaccessible
43.   	 *  for the player.)
44.   	 * The environment variable HACKDIR is overridden by a
45.   	 *  -d command line option.
46.   	 */
47.   	dir = getenv("HACKDIR");
48.   	if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
49.   		argc--;
50.   		argv++;
51.   		dir = argv[0]+2;
52.   		if(*dir == '=' || *dir == ':') dir++;
53.   		if(!*dir && argc > 1) {
54.   			argc--;
55.   			argv++;
56.   			dir = argv[0];
57.   		}
58.   		if(!*dir)
59.   			error("Flag -d must be followed by a directory name.");
60.   	}
61.   
62.   	/*
63.   	 * Now we know the directory containing 'record' and
64.   	 * may do a prscore().
65.   	 */
66.   	if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
67.   		if(dir) chdirx(dir);
68.   		prscore(argc, argv);
69.   		exit(0);
70.   	}
71.   
72.   	/*
73.   	 * It seems he really wants to play. Find the creation date of
74.   	 * this game so as to avoid restoring outdated savefiles.
75.   	 */
76.   	gethdate(hname);
77.   
78.   	/*
79.   	 * We cannot do chdir earlier, otherwise gethdate will fail.
80.   	 */
81.   	if(dir) chdirx(dir);
82.   
83.   	/*
84.   	 * Who am i? Perhaps we should use $USER instead?
85.   	 */
86.   	(void) strncpy(plname, getlogin(), sizeof(plname)-1);
87.   
88.   	/*
89.   	 * Process options.
90.   	 */
91.   	while(argc > 1 && argv[1][0] == '-'){
92.   		argv++;
93.   		argc--;
94.   		switch(argv[0][1]){
95.   #ifdef WIZARD
96.   		case 'w':
97.   			if(!strcmp(getlogin(), WIZARD))
98.   				wizard = TRUE;
99.   			else printf("Sorry.\n");
100.  			break;
101.  #endif WIZARD
102.  #ifdef NEWS
103.  		case 'n':
104.  			nonews++;
105.  			break;
106.  #endif NEWS
107.  		case 'u':
108.  			if(argv[0][2])
109.  			  (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
110.  			else if(argc > 1) {
111.  			  argc--;
112.  			  argv++;
113.  			  (void) strncpy(plname, argv[0], sizeof(plname)-1);
114.  			} else
115.  				printf("Player name expected after -u\n");
116.  			break;
117.  		default:
118.  			printf("Unknown option: %s\n", *argv);
119.  		}
120.  	}
121.  
122.  	if(argc > 1)
123.  		locknum = atoi(argv[1]);
124.  	if(argc > 2)
125.  		catmore = argv[2];
126.  #ifdef WIZARD
127.  	if(wizard) (void) strcpy(plname, "wizard"); else
128.  #endif WIZARD
129.  	if(!*plname || !strncmp(plname, "player", 4)) askname();
130.  	plnamesuffix();		/* strip suffix from name */
131.  
132.  	setbuf(stdout,obuf);
133.   	(void) srand(getpid());
134.  	startup();
135.  	cls();
136.  	(void) signal(SIGHUP, hangup);
137.  #ifdef WIZARD
138.  	if(!wizard) {
139.  #endif WIZARD
140.  		(void) signal(SIGQUIT,SIG_IGN);
141.  		(void) signal(SIGINT,SIG_IGN);
142.  		if(locknum)
143.  			lockcheck();
144.  		else
145.  			(void) strcpy(lock,plname);
146.  #ifdef WIZARD
147.  	} else {
148.  		register char *sfoo;
149.  		(void) strcpy(lock,plname);
150.  		if(sfoo = getenv("MAGIC"))
151.  			while(*sfoo) {
152.  				switch(*sfoo++) {
153.  				case 'n': (void) srand(*sfoo++);
154.  					break;
155.  				}
156.  			}
157.  		if(sfoo = getenv("GENOCIDED")){
158.  			if(*sfoo == '!'){
159.  				extern struct permonst mons[CMNUM+2];
160.  				extern char genocided[], fut_geno[];
161.  				register struct permonst *pm = mons;
162.  				register char *gp = genocided;
163.  
164.  				while(pm < mons+CMNUM+2){
165.  					if(!index(sfoo, pm->mlet))
166.  						*gp++ = pm->mlet;
167.  					pm++;
168.  				}
169.  				*gp = 0;
170.  			} else
171.  				(void) strcpy(genocided, sfoo);
172.  			(void) strcpy(fut_geno, genocided);
173.  		}
174.  	}
175.  #endif WIZARD
176.  	u.uhp = 1;	/* prevent RIP on early quits */
177.  	u.ux = FAR;	/* prevent nscr() */
178.  	(void) strcat(SAVEF,plname);
179.  	if((fd = open(SAVEF,0)) >= 0 &&
180.  	   (uptodate(fd) || unlink(SAVEF) == 666)) {
181.  		(void) signal(SIGINT,done1);
182.  		puts("Restoring old save file...");
183.  		(void) fflush(stdout);
184.  		dorecover(fd);
185.  		flags.move = 0;
186.  	} else {
187.  #ifdef NEWS
188.  		if(!nonews)
189.  			if((fd = open(NEWS,0)) >= 0)
190.  				outnews(fd);
191.  #endif NEWS
192.  		flags.ident = 1;
193.  		init_objects();
194.  		u_init();
195.  		(void) signal(SIGINT,done1);
196.  		glo(1);
197.  		mklev();
198.  		u.ux = xupstair;
199.  		u.uy = yupstair;
200.  		(void) inshop();
201.  		setsee();
202.  		flags.botlx = 1;
203.  		makedog();
204.  		seemons();
205.  		docrt();
206.  		pickup();
207.  		read_engr_at(u.ux,u.uy);	/* superfluous ? */
208.  		flags.move = 1;
209.  		flags.cbreak = ON;
210.  		flags.echo = OFF;
211.  	}
212.  	setftty();
213.  #ifdef TRACK
214.  	initrack();
215.  #endif TRACK
216.  	for(;;) {
217.  		if(flags.move) {
218.  #ifdef TRACK
219.  			settrack();
220.  #endif TRACK
221.  			if(moves%2 == 0 ||
222.  			  (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
223.  				extern struct monst *makemon();
224.  				movemon();
225.  				if(!rn2(70))
226.  				    (void) makemon((struct permonst *)0, 0, 0);
227.  			}
228.  			if(Glib) glibr();
229.  			timeout();
230.  			++moves;
231.  			if(u.uhp < 1) {
232.  				pline("You die...");
233.  				done("died");
234.  			}
235.  			if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
236.  			    wailmsg = moves;
237.  			    if(u.uhp == 1)
238.  			    pline("You hear the wailing of the Banshee...");
239.  			    else
240.  			    pline("You hear the howling of the CwnAnnwn...");
241.  			}
242.  			if(u.uhp < u.uhpmax) {
243.  				if(u.ulevel > 9) {
244.  					if(Regeneration || !(moves%3)) {
245.  					    flags.botl = 1;
246.  					    u.uhp += rnd((int) u.ulevel-9);
247.  					    if(u.uhp > u.uhpmax)
248.  						u.uhp = u.uhpmax;
249.  					}
250.  				} else if(Regeneration ||
251.  					(!(moves%(22-u.ulevel*2)))) {
252.  					flags.botl = 1;
253.  					u.uhp++;
254.  				}
255.  			}
256.  			if(Teleportation && !rn2(85)) tele();
257.  			if(Searching && multi >= 0) (void) dosearch();
258.  			gethungry();
259.  			invault();
260.  		}
261.  		if(multi < 0) {
262.  			if(!++multi){
263.  				pline(nomovemsg ? nomovemsg :
264.  					"You can move again.");
265.  				nomovemsg = 0;
266.  				if(afternmv) (*afternmv)();
267.  				afternmv = 0;
268.  			}
269.  		}
270.  		flags.move = 1;
271.  		find_ac();
272.  #ifndef QUEST
273.  		if(!flags.mv || Blind)
274.  #endif QUEST
275.  		{
276.  			seeobjs();
277.  			seemons();
278.  			nscr();
279.  		}
280.  		if(flags.botl || flags.botlx) bot();
281.  		if(multi > 0) {
282.  #ifdef QUEST
283.  			if(flags.run >= 4) finddir();
284.  #endif QUEST
285.  			lookaround();
286.  			if(!multi) {	/* lookaround may clear multi */
287.  				flags.move = 0;
288.  				continue;
289.  			}
290.  			if(flags.mv) {
291.  				if(multi<COLNO && !--multi)
292.  					flags.mv = flags.run = 0;
293.  				domove();
294.  			} else {
295.  				--multi;
296.  				rhack(save_cm);
297.  			}
298.  		} else if(multi == 0)
299.  			rhack((char *) 0);
300.  	}
301.  }
302.  
303.  lockcheck()
304.  {
305.  	extern int errno;
306.  	register int i, fd;
307.  
308.  	/* we ignore QUIT and INT at this point */
309.  	if (link(perm,safelock) == -1)
310.  		error("Cannot link safelock. (Try again or rm safelock.)");
311.  
312.  	for(i = 0; i < locknum; i++) {
313.  		lock[0]= 'a' + i;
314.  		if((fd = open(lock,0)) == -1) {
315.  			if(errno == ENOENT) goto gotlock;    /* no such file */
316.  			(void) unlink(safelock);
317.  			error("Cannot open %s", lock);
318.  		}
319.  		(void) close(fd);
320.  	}
321.  	(void) unlink(safelock);
322.  	error("Too many hacks running now.");
323.  gotlock:
324.  	fd = creat(lock,FMASK);
325.  	if(fd == -1) {
326.  		error("cannot creat lock file.");
327.  	} else {
328.  		int pid;
329.  
330.  		pid = getpid();
331.  		if(write(fd, (char *) &pid, 2) != 2){
332.  			error("cannot write lock");
333.  		}
334.  		if(close(fd) == -1){
335.  			error("cannot close lock");
336.  		}
337.  	}
338.  	if(unlink(safelock) == -1){
339.  		error("Cannot unlink safelock");
340.  	}
341.  }
342.  
343.  /*VARARGS1*/
344.  error(s,a1,a2,a3,a4) char *s,*a1,*a2,*a3,*a4; {
345.  	printf("Error: ");
346.  	printf(s,a1,a2,a3,a4);
347.  	(void) putchar('\n');
348.  	exit(1);
349.  }
350.  
351.  glo(foo)
352.  register foo;
353.  {
354.  	/* construct the string  xlock.n  */
355.  	register char *tf;
356.  
357.  	tf = lock;
358.  	while(*tf && *tf!='.') tf++;
359.  	(void) sprintf(tf, ".%d", foo);
360.  }
361.  
362.  /*
363.   * plname is filled either by an option (-u Player  or  -uPlayer) or
364.   * explicitly (-w implies wizard) or by askname.
365.   * It may still contain a suffix denoting pl_character.
366.   */
367.  askname(){
368.  register int c,ct;
369.  	printf("\nWho are you? ");
370.  	ct = 0;
371.  	while((c = getchar()) != '\n'){
372.  		if(c == EOF) error("End of input\n");
373.  		if(c != '-')
374.  		if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
375.  		if(ct < sizeof(plname)-1) plname[ct++] = c;
376.  	}
377.  	plname[ct] = 0;
378.  	if(ct == 0) askname();
379.  #ifdef QUEST
380.  	else printf("Hello %s, welcome to quest!\n", plname);
381.  #else
382.  	else printf("Hello %s, welcome to hack!\n", plname);
383.  #endif QUEST
384.  }
385.  
386.  impossible(){
387.  	pline("Program in disorder - perhaps you'd better Quit");
388.  }
389.  
390.  #ifdef NEWS
391.  int stopnews;
392.  
393.  stopnws(){
394.  	(void) signal(SIGINT, SIG_IGN);
395.  	stopnews++;
396.  }
397.  
398.  outnews(fd) int fd; {
399.  int (*prevsig)();
400.  char ch;
401.  	prevsig = signal(SIGINT, stopnws);
402.  	while(!stopnews && read(fd,&ch,1) == 1)
403.  		(void) putchar(ch);
404.  	(void) putchar('\n');
405.  	(void) fflush(stdout);
406.  	(void) close(fd);
407.  	(void) signal(SIGINT, prevsig);
408.  	/* See whether we will ask TSKCFW: he might have told us already */
409.  	if(!stopnews && pl_character[0])
410.  		getret();
411.  }
412.  #endif NEWS
413.  
414.  chdirx(dir) char *dir; {
415.  	if(chdir(dir) < 0) {
416.  		perror(dir);
417.  		error("Cannot chdir to %s.", dir);
418.  	}
419.  }