#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include "hack.h"
#ifdef QUEST
#define gamename "quest"
#else
#define gamename "hack"
#endif
extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
extern struct permonst mons[CMNUM+2];
extern char genocided[60], fut_geno[60];
void (*afternmv)(void);
int (*occupation)(void);
char *occtxt;
int hackpid;
int locknum;
#ifdef DEF_PAGER
char *catmore;
#endif
char SAVEF[PL_NSIZ + 11] = "save/";
char obuf[BUFSIZ];
extern char *nomovemsg;
extern long wailmsg;
#ifdef CHDIR
static void chdirx(char *, boolean);
#endif
int
main(int argc, char **argv)
{
int fd;
#ifdef CHDIR
char *dir;
#endif
hackpid = getpid();
#ifdef CHDIR
dir = getenv("HACKDIR");
if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
argc--;
argv++;
dir = argv[0]+2;
if(*dir == '=' || *dir == ':') dir++;
if(!*dir && argc > 1) {
argc--;
argv++;
dir = argv[0];
}
if(!*dir)
error("Flag -d must be followed by a directory name.");
}
#endif
{ char *s;
initoptions();
if(!*plname && (s = getenv("LOGNAME")))
(void) strlcpy(plname, s, sizeof(plname));
if(!*plname && (s = getenv("USER")))
(void) strlcpy(plname, s, sizeof(plname));
if(!*plname && (s = getlogin()))
(void) strlcpy(plname, s, sizeof(plname));
}
if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
#ifdef CHDIR
chdirx(dir,0);
#endif
prscore(argc, argv);
return 0;
}
gettty();
setvbuf(stdout, obuf, _IOFBF, sizeof obuf);
umask(007);
startup();
cls();
u.uhp = 1;
u.ux = FAR;
(void) signal(SIGHUP, hackhangup);
#ifdef CHDIR
chdirx(dir,1);
#endif
while(argc > 1 && argv[1][0] == '-'){
argv++;
argc--;
switch(argv[0][1]){
#ifdef WIZARD
case 'D':
wizard = TRUE;
break;
#endif
#ifdef NEWS
case 'n':
flags.nonews = TRUE;
break;
#endif
case 'u':
if(argv[0][2]) {
(void) strlcpy(plname, argv[0]+2, sizeof(plname));
} else if(argc > 1) {
argc--;
argv++;
(void) strlcpy(plname, argv[0], sizeof(plname));
} else
printf("Player name expected after -u\n");
break;
default:
(void) strlcpy(pl_character, argv[0]+1, sizeof(pl_character));
}
}
if(argc > 1)
locknum = atoi(argv[1]);
#ifdef MAX_NR_OF_PLAYERS
if(!locknum || locknum > MAX_NR_OF_PLAYERS)
locknum = MAX_NR_OF_PLAYERS;
#endif
#ifdef DEF_PAGER
if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER")))
catmore = DEF_PAGER;
#endif
#ifdef MAIL
getmailstatus();
#endif
#ifdef WIZARD
if(wizard) (void) strlcpy(plname, "wizard", sizeof plname); else
#endif
if(!*plname || !strncmp(plname, "player", 4)
|| !strncmp(plname, "games", 4))
askname();
plnamesuffix();
#ifdef WIZARD
if(!wizard) {
#endif
(void) signal(SIGQUIT,SIG_IGN);
(void) signal(SIGINT,SIG_IGN);
if(!locknum)
(void) strlcpy(lock,plname,sizeof lock);
getlock();
#ifdef WIZARD
} else {
char *sfoo;
(void) strlcpy(lock,plname,sizeof lock);
if ((sfoo = getenv("MAGIC")))
while(*sfoo) {
switch(*sfoo++) {
case 'n': (void) srandom_deterministic(*sfoo++);
break;
}
}
if ((sfoo = getenv("GENOCIDED"))) {
if(*sfoo == '!'){
struct permonst *pm = mons;
char *gp = genocided;
while(pm < mons+CMNUM+2){
if(!strchr(sfoo, pm->mlet))
*gp++ = pm->mlet;
pm++;
}
*gp = 0;
} else
strlcpy(genocided, sfoo, sizeof genocided);
strlcpy(fut_geno, genocided, sizeof fut_geno);
}
}
#endif
setftty();
(void) snprintf(SAVEF, sizeof SAVEF, "save/%u%s", getuid(), plname);
regularize(SAVEF+5);
if((fd = open(SAVEF, O_RDONLY)) >= 0) {
(void) signal(SIGINT,done1);
pline("Restoring old save file...");
(void) fflush(stdout);
if(!dorecover(fd))
goto not_recovered;
pline("Hello %s, welcome to %s!", plname, gamename);
flags.move = 0;
} else {
not_recovered:
fobj = fcobj = invent = 0;
fmon = fallen_down = 0;
ftrap = 0;
fgold = 0;
flags.ident = 1;
init_objects();
u_init();
(void) signal(SIGINT,done1);
mklev();
u.ux = xupstair;
u.uy = yupstair;
(void) inshop();
setsee();
flags.botlx = 1;
makedog();
{ struct monst *mtmp;
if ((mtmp = m_at(u.ux, u.uy)))
mnexto(mtmp);
}
seemons();
#ifdef NEWS
if(flags.nonews || !readnews())
#endif
docrt();
pline("Hello %s, welcome to %s!", plname, gamename);
pickup(1);
read_engr_at(u.ux,u.uy);
flags.move = 1;
}
flags.moonphase = phase_of_the_moon();
if(flags.moonphase == FULL_MOON) {
pline("You are lucky! Full moon tonight.");
u.uluck++;
} else if(flags.moonphase == NEW_MOON) {
pline("Be careful! New moon tonight.");
}
initrack();
for(;;) {
if(flags.move) {
settrack();
if(moves%2 == 0 ||
(!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
movemon();
if(!rn2(70))
(void) makemon((struct permonst *)0, 0, 0);
}
if(Glib) glibr();
hacktimeout();
++moves;
if(flags.time) flags.botl = 1;
if(u.uhp < 1) {
pline("You die...");
done("died");
}
if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
wailmsg = moves;
if(u.uhp == 1)
pline("You hear the wailing of the Banshee...");
else
pline("You hear the howling of the CwnAnnwn...");
}
if(u.uhp < u.uhpmax) {
if(u.ulevel > 9) {
if(Regeneration || !(moves%3)) {
flags.botl = 1;
u.uhp += rnd((int) u.ulevel-9);
if(u.uhp > u.uhpmax)
u.uhp = u.uhpmax;
}
} else if(Regeneration ||
(!(moves%(22-u.ulevel*2)))) {
flags.botl = 1;
u.uhp++;
}
}
if(Teleportation && !rn2(85)) tele();
if(Searching && multi >= 0) (void) dosearch();
gethungry();
invault();
amulet();
}
if(multi < 0) {
if(!++multi){
pline("%s", nomovemsg ? nomovemsg :
"You can move again.");
nomovemsg = 0;
if(afternmv) (*afternmv)();
afternmv = 0;
}
}
find_ac();
#ifndef QUEST
if(!flags.mv || Blind)
#endif
{
seeobjs();
seemons();
nscr();
}
if(flags.botl || flags.botlx) bot();
flags.move = 1;
if(multi >= 0 && occupation) {
if(monster_nearby())
stop_occupation();
else if ((*occupation)() == 0)
occupation = 0;
continue;
}
if(multi > 0) {
#ifdef QUEST
if(flags.run >= 4) finddir();
#endif
lookaround();
if(!multi) {
flags.move = 0;
continue;
}
if(flags.mv) {
if(multi < COLNO && !--multi)
flags.mv = flags.run = 0;
domove();
} else {
--multi;
rhack(save_cm);
}
} else if(multi == 0) {
#ifdef MAIL
ckmailstatus();
#endif
rhack(NULL);
}
if(multi && multi%7 == 0)
(void) fflush(stdout);
}
}
void
glo(int foo)
{
char *tf;
tf = lock;
while(*tf && *tf != '.') tf++;
(void) snprintf(tf, lock + sizeof lock - tf, ".%d", foo);
}
void
askname(void)
{
int c,ct;
printf("\nWho are you? ");
(void) fflush(stdout);
ct = 0;
while((c = getchar()) != '\n'){
if(c == EOF) error("End of input\n");
if(c == '\010') {
if(ct) ct--;
continue;
}
if(c != '-')
if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
if(ct < sizeof(plname)-1) plname[ct++] = c;
}
plname[ct] = 0;
if(ct == 0) askname();
}
void
impossible(const char *s, ...)
{
va_list ap;
va_start(ap, s);
vpline(s, ap);
va_end(ap);
pline("Program in disorder - perhaps you'd better Quit.");
}
#ifdef CHDIR
static void
chdirx(char *dir, boolean wr)
{
gid_t gid;
#ifdef SECURE
if(dir
#ifdef HACKDIR
&& strcmp(dir, HACKDIR)
#endif
) {
gid = getgid();
setresgid(gid, gid, gid);
}
#endif
#ifdef HACKDIR
if(dir == NULL)
dir = HACKDIR;
#endif
if(dir && chdir(dir) == -1) {
perror(dir);
error("Cannot chdir to %s.", dir);
}
if(wr) {
int fd;
if(dir == NULL)
dir = ".";
if((fd = open(RECORD, O_RDWR | O_CREAT, FMASK)) == -1) {
printf("Warning: cannot write %s/%s", dir, RECORD);
getret();
} else
(void) close(fd);
if((fd = open(HLOCK, O_RDONLY | O_CREAT, FMASK)) == -1) {
printf("Warning: cannot read %s/%s", dir, HLOCK);
getret();
} else
(void) close(fd);
if(mkdir("save", 0770) && errno != EEXIST) {
printf("Warning: cannot create %s/save", dir);
getret();
}
}
}
#endif
void
stop_occupation(void)
{
if(occupation) {
pline("You stop %s.", occtxt);
occupation = 0;
}
}