Source:Hack 1.0/hack.main.c

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

1.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ 2.     3.    #include   4.    #include   5.    #include   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.  }