1*42ceebb3Sderaadt /* $OpenBSD: hack.main.c,v 1.10 2003/04/06 18:50:37 deraadt Exp $ */ 2d0b779f3Sniklas 3df930be7Sderaadt /* 4d25013f2Scamield * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, 5d25013f2Scamield * Amsterdam 6d25013f2Scamield * All rights reserved. 7d25013f2Scamield * 8d25013f2Scamield * Redistribution and use in source and binary forms, with or without 9d25013f2Scamield * modification, are permitted provided that the following conditions are 10d25013f2Scamield * met: 11d25013f2Scamield * 12d25013f2Scamield * - Redistributions of source code must retain the above copyright notice, 13d25013f2Scamield * this list of conditions and the following disclaimer. 14d25013f2Scamield * 15d25013f2Scamield * - Redistributions in binary form must reproduce the above copyright 16d25013f2Scamield * notice, this list of conditions and the following disclaimer in the 17d25013f2Scamield * documentation and/or other materials provided with the distribution. 18d25013f2Scamield * 19d25013f2Scamield * - Neither the name of the Stichting Centrum voor Wiskunde en 20d25013f2Scamield * Informatica, nor the names of its contributors may be used to endorse or 21d25013f2Scamield * promote products derived from this software without specific prior 22d25013f2Scamield * written permission. 23d25013f2Scamield * 24d25013f2Scamield * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 25d25013f2Scamield * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26d25013f2Scamield * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 27d25013f2Scamield * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 28d25013f2Scamield * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31d25013f2Scamield * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32d25013f2Scamield * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33d25013f2Scamield * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34d25013f2Scamield * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35d25013f2Scamield */ 36d25013f2Scamield 37d25013f2Scamield /* 38d25013f2Scamield * Copyright (c) 1982 Jay Fenlason <hack@gnu.org> 39d25013f2Scamield * All rights reserved. 40d25013f2Scamield * 41d25013f2Scamield * Redistribution and use in source and binary forms, with or without 42d25013f2Scamield * modification, are permitted provided that the following conditions 43d25013f2Scamield * are met: 44d25013f2Scamield * 1. Redistributions of source code must retain the above copyright 45d25013f2Scamield * notice, this list of conditions and the following disclaimer. 46d25013f2Scamield * 2. Redistributions in binary form must reproduce the above copyright 47d25013f2Scamield * notice, this list of conditions and the following disclaimer in the 48d25013f2Scamield * documentation and/or other materials provided with the distribution. 49d25013f2Scamield * 3. The name of the author may not be used to endorse or promote products 50d25013f2Scamield * derived from this software without specific prior written permission. 51d25013f2Scamield * 52d25013f2Scamield * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 53d25013f2Scamield * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 54d25013f2Scamield * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 55d25013f2Scamield * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 56d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 57d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 58d25013f2Scamield * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 59d25013f2Scamield * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 60d25013f2Scamield * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 61d25013f2Scamield * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62df930be7Sderaadt */ 63df930be7Sderaadt 64df930be7Sderaadt #ifndef lint 65*42ceebb3Sderaadt static char rcsid[] = "$OpenBSD: hack.main.c,v 1.10 2003/04/06 18:50:37 deraadt Exp $"; 66df930be7Sderaadt #endif /* not lint */ 67df930be7Sderaadt 68df930be7Sderaadt #include <stdio.h> 69df930be7Sderaadt #include <signal.h> 70df930be7Sderaadt #include "hack.h" 71df930be7Sderaadt 72df930be7Sderaadt #ifdef QUEST 73df930be7Sderaadt #define gamename "quest" 74df930be7Sderaadt #else 75df930be7Sderaadt #define gamename "hack" 76df930be7Sderaadt #endif 77df930be7Sderaadt 78df930be7Sderaadt extern char *getlogin(), *getenv(); 79df930be7Sderaadt extern char plname[PL_NSIZ], pl_character[PL_CSIZ]; 80df930be7Sderaadt extern struct permonst mons[CMNUM+2]; 81df930be7Sderaadt extern char genocided[], fut_geno[]; 82df930be7Sderaadt 83df930be7Sderaadt int (*afternmv)(); 84df930be7Sderaadt int (*occupation)(); 85df930be7Sderaadt char *occtxt; /* defined when occupation != NULL */ 86df930be7Sderaadt 87df930be7Sderaadt void done1(); 88df930be7Sderaadt void hangup(); 89df930be7Sderaadt 90df930be7Sderaadt int hackpid; /* current pid */ 91df930be7Sderaadt int locknum; /* max num of players */ 92df930be7Sderaadt #ifdef DEF_PAGER 93df930be7Sderaadt char *catmore; /* default pager */ 94df930be7Sderaadt #endif 95df930be7Sderaadt char SAVEF[PL_NSIZ + 11] = "save/"; /* save/99999player */ 96df930be7Sderaadt char *hname; /* name of the game (argv[0] of call) */ 97df930be7Sderaadt char obuf[BUFSIZ]; /* BUFSIZ is defined in stdio.h */ 98df930be7Sderaadt 99df930be7Sderaadt extern char *nomovemsg; 100df930be7Sderaadt extern long wailmsg; 101df930be7Sderaadt 102df930be7Sderaadt #ifdef CHDIR 103df930be7Sderaadt static void chdirx(); 104df930be7Sderaadt #endif 105df930be7Sderaadt 106df930be7Sderaadt main(argc,argv) 107df930be7Sderaadt int argc; 108df930be7Sderaadt char *argv[]; 109df930be7Sderaadt { 110df930be7Sderaadt register int fd; 111df930be7Sderaadt #ifdef CHDIR 112df930be7Sderaadt register char *dir; 113df930be7Sderaadt #endif 114df930be7Sderaadt 115df930be7Sderaadt hname = argv[0]; 116df930be7Sderaadt hackpid = getpid(); 117df930be7Sderaadt 118df930be7Sderaadt #ifdef CHDIR /* otherwise no chdir() */ 119df930be7Sderaadt /* 120df930be7Sderaadt * See if we must change directory to the playground. 121df930be7Sderaadt * (Perhaps hack runs suid and playground is inaccessible 122df930be7Sderaadt * for the player.) 123df930be7Sderaadt * The environment variable HACKDIR is overridden by a 124df930be7Sderaadt * -d command line option (must be the first option given) 125df930be7Sderaadt */ 126df930be7Sderaadt 127df930be7Sderaadt dir = getenv("HACKDIR"); 128df930be7Sderaadt if(argc > 1 && !strncmp(argv[1], "-d", 2)) { 129df930be7Sderaadt argc--; 130df930be7Sderaadt argv++; 131df930be7Sderaadt dir = argv[0]+2; 132df930be7Sderaadt if(*dir == '=' || *dir == ':') dir++; 133df930be7Sderaadt if(!*dir && argc > 1) { 134df930be7Sderaadt argc--; 135df930be7Sderaadt argv++; 136df930be7Sderaadt dir = argv[0]; 137df930be7Sderaadt } 138df930be7Sderaadt if(!*dir) 139df930be7Sderaadt error("Flag -d must be followed by a directory name."); 140df930be7Sderaadt } 141df930be7Sderaadt #endif 142df930be7Sderaadt 143df930be7Sderaadt /* 144df930be7Sderaadt * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS 145c7b2accbSmillert * 2. Use $LOGNAME or $USER (if 1. fails) 146df930be7Sderaadt * 3. Use getlogin() (if 2. fails) 147df930be7Sderaadt * The resulting name is overridden by command line options. 148df930be7Sderaadt * If everything fails, or if the resulting name is some generic 149df930be7Sderaadt * account like "games", "play", "player", "hack" then eventually 150df930be7Sderaadt * we'll ask him. 151df930be7Sderaadt * Note that we trust him here; it is possible to play under 152df930be7Sderaadt * somebody else's name. 153df930be7Sderaadt */ 154df930be7Sderaadt { register char *s; 155df930be7Sderaadt 156df930be7Sderaadt initoptions(); 157df930be7Sderaadt if(!*plname && (s = getenv("LOGNAME"))) 158df930be7Sderaadt (void) strncpy(plname, s, sizeof(plname)-1); 159c7b2accbSmillert if(!*plname && (s = getenv("USER"))) 160c7b2accbSmillert (void) strncpy(plname, s, sizeof(plname)-1); 161df930be7Sderaadt if(!*plname && (s = getlogin())) 162df930be7Sderaadt (void) strncpy(plname, s, sizeof(plname)-1); 163c7b2accbSmillert if(*plname) 164c7b2accbSmillert plname[sizeof(plname)-1] = '\0'; 165df930be7Sderaadt } 166df930be7Sderaadt 167df930be7Sderaadt /* 168df930be7Sderaadt * Now we know the directory containing 'record' and 169df930be7Sderaadt * may do a prscore(). 170df930be7Sderaadt */ 171df930be7Sderaadt if(argc > 1 && !strncmp(argv[1], "-s", 2)) { 172df930be7Sderaadt #ifdef CHDIR 173df930be7Sderaadt chdirx(dir,0); 174df930be7Sderaadt #endif 175df930be7Sderaadt prscore(argc, argv); 176df930be7Sderaadt exit(0); 177df930be7Sderaadt } 178df930be7Sderaadt 179df930be7Sderaadt /* 180df930be7Sderaadt * It seems he really wants to play. 181df930be7Sderaadt * Remember tty modes, to be restored on exit. 182df930be7Sderaadt */ 183df930be7Sderaadt gettty(); 184df930be7Sderaadt setbuf(stdout,obuf); 185a7a85d61Stholo umask(007); 186df930be7Sderaadt setrandom(); 187df930be7Sderaadt startup(); 188df930be7Sderaadt cls(); 189df930be7Sderaadt u.uhp = 1; /* prevent RIP on early quits */ 190df930be7Sderaadt u.ux = FAR; /* prevent nscr() */ 191df930be7Sderaadt (void) signal(SIGHUP, hangup); 192df930be7Sderaadt 193df930be7Sderaadt /* 194df930be7Sderaadt * Find the creation date of this game, 195df930be7Sderaadt * so as to avoid restoring outdated savefiles. 196df930be7Sderaadt */ 197df930be7Sderaadt gethdate(hname); 198df930be7Sderaadt 199df930be7Sderaadt /* 200df930be7Sderaadt * We cannot do chdir earlier, otherwise gethdate will fail. 201df930be7Sderaadt */ 202df930be7Sderaadt #ifdef CHDIR 203df930be7Sderaadt chdirx(dir,1); 204df930be7Sderaadt #endif 205df930be7Sderaadt 206df930be7Sderaadt /* 207df930be7Sderaadt * Process options. 208df930be7Sderaadt */ 209df930be7Sderaadt while(argc > 1 && argv[1][0] == '-'){ 210df930be7Sderaadt argv++; 211df930be7Sderaadt argc--; 212df930be7Sderaadt switch(argv[0][1]){ 213df930be7Sderaadt #ifdef WIZARD 214df930be7Sderaadt case 'D': 215df930be7Sderaadt /* if(!strcmp(getlogin(), WIZARD)) */ 216df930be7Sderaadt wizard = TRUE; 217df930be7Sderaadt /* else 218df930be7Sderaadt printf("Sorry.\n"); */ 219df930be7Sderaadt break; 220df930be7Sderaadt #endif 221df930be7Sderaadt #ifdef NEWS 222df930be7Sderaadt case 'n': 223df930be7Sderaadt flags.nonews = TRUE; 224df930be7Sderaadt break; 225df930be7Sderaadt #endif 226df930be7Sderaadt case 'u': 227c7b2accbSmillert if(argv[0][2]) { 228df930be7Sderaadt (void) strncpy(plname, argv[0]+2, sizeof(plname)-1); 229c7b2accbSmillert plname[sizeof(plname)-1] = '\0'; 230c7b2accbSmillert } else if(argc > 1) { 231df930be7Sderaadt argc--; 232df930be7Sderaadt argv++; 233df930be7Sderaadt (void) strncpy(plname, argv[0], sizeof(plname)-1); 234c7b2accbSmillert plname[sizeof(plname)-1] = '\0'; 235df930be7Sderaadt } else 236df930be7Sderaadt printf("Player name expected after -u\n"); 237df930be7Sderaadt break; 238df930be7Sderaadt default: 239df930be7Sderaadt /* allow -T for Tourist, etc. */ 240df930be7Sderaadt (void) strncpy(pl_character, argv[0]+1, 241df930be7Sderaadt sizeof(pl_character)-1); 242c7b2accbSmillert plname[sizeof(pl_character)-1] = '\0'; 243df930be7Sderaadt 244df930be7Sderaadt /* printf("Unknown option: %s\n", *argv); */ 245df930be7Sderaadt } 246df930be7Sderaadt } 247df930be7Sderaadt 248df930be7Sderaadt if(argc > 1) 249df930be7Sderaadt locknum = atoi(argv[1]); 250df930be7Sderaadt #ifdef MAX_NR_OF_PLAYERS 251df930be7Sderaadt if(!locknum || locknum > MAX_NR_OF_PLAYERS) 252df930be7Sderaadt locknum = MAX_NR_OF_PLAYERS; 253df930be7Sderaadt #endif 254df930be7Sderaadt #ifdef DEF_PAGER 255df930be7Sderaadt if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER"))) 256df930be7Sderaadt catmore = DEF_PAGER; 257df930be7Sderaadt #endif 258df930be7Sderaadt #ifdef MAIL 259df930be7Sderaadt getmailstatus(); 260df930be7Sderaadt #endif 261df930be7Sderaadt #ifdef WIZARD 262*42ceebb3Sderaadt if(wizard) (void) strlcpy(plname, "wizard", sizeof plname); else 263df930be7Sderaadt #endif 264df930be7Sderaadt if(!*plname || !strncmp(plname, "player", 4) 265df930be7Sderaadt || !strncmp(plname, "games", 4)) 266df930be7Sderaadt askname(); 267df930be7Sderaadt plnamesuffix(); /* strip suffix from name; calls askname() */ 268df930be7Sderaadt /* again if suffix was whole name */ 269df930be7Sderaadt /* accepts any suffix */ 270df930be7Sderaadt #ifdef WIZARD 271df930be7Sderaadt if(!wizard) { 272df930be7Sderaadt #endif 273df930be7Sderaadt /* 274df930be7Sderaadt * check for multiple games under the same name 275df930be7Sderaadt * (if !locknum) or check max nr of players (otherwise) 276df930be7Sderaadt */ 277df930be7Sderaadt (void) signal(SIGQUIT,SIG_IGN); 278df930be7Sderaadt (void) signal(SIGINT,SIG_IGN); 279df930be7Sderaadt if(!locknum) 280df930be7Sderaadt (void) strcpy(lock,plname); 281df930be7Sderaadt getlock(); /* sets lock if locknum != 0 */ 282df930be7Sderaadt #ifdef WIZARD 283df930be7Sderaadt } else { 284df930be7Sderaadt register char *sfoo; 285df930be7Sderaadt (void) strcpy(lock,plname); 286df930be7Sderaadt if(sfoo = getenv("MAGIC")) 287df930be7Sderaadt while(*sfoo) { 288df930be7Sderaadt switch(*sfoo++) { 289df930be7Sderaadt case 'n': (void) srandom(*sfoo++); 290df930be7Sderaadt break; 291df930be7Sderaadt } 292df930be7Sderaadt } 293df930be7Sderaadt if(sfoo = getenv("GENOCIDED")){ 294df930be7Sderaadt if(*sfoo == '!'){ 295df930be7Sderaadt register struct permonst *pm = mons; 296df930be7Sderaadt register char *gp = genocided; 297df930be7Sderaadt 298df930be7Sderaadt while(pm < mons+CMNUM+2){ 299180acc8fSmillert if(!strchr(sfoo, pm->mlet)) 300df930be7Sderaadt *gp++ = pm->mlet; 301df930be7Sderaadt pm++; 302df930be7Sderaadt } 303df930be7Sderaadt *gp = 0; 304df930be7Sderaadt } else 305df930be7Sderaadt (void) strcpy(genocided, sfoo); 306df930be7Sderaadt (void) strcpy(fut_geno, genocided); 307df930be7Sderaadt } 308df930be7Sderaadt } 309df930be7Sderaadt #endif 310df930be7Sderaadt setftty(); 311*42ceebb3Sderaadt (void) snprintf(SAVEF, sizeof SAVEF, "save/%u%s", getuid(), plname); 312df930be7Sderaadt regularize(SAVEF+5); /* avoid . or / in name */ 3136cd28e42Smillert if((fd = open(SAVEF, O_RDONLY)) >= 0 && 314df930be7Sderaadt (uptodate(fd) || unlink(SAVEF) == 666)) { 315df930be7Sderaadt (void) signal(SIGINT,done1); 316df930be7Sderaadt pline("Restoring old save file..."); 317df930be7Sderaadt (void) fflush(stdout); 318df930be7Sderaadt if(!dorecover(fd)) 319df930be7Sderaadt goto not_recovered; 320df930be7Sderaadt pline("Hello %s, welcome to %s!", plname, gamename); 321df930be7Sderaadt flags.move = 0; 322df930be7Sderaadt } else { 323df930be7Sderaadt not_recovered: 324df930be7Sderaadt fobj = fcobj = invent = 0; 325df930be7Sderaadt fmon = fallen_down = 0; 326df930be7Sderaadt ftrap = 0; 327df930be7Sderaadt fgold = 0; 328df930be7Sderaadt flags.ident = 1; 329df930be7Sderaadt init_objects(); 330df930be7Sderaadt u_init(); 331df930be7Sderaadt 332df930be7Sderaadt (void) signal(SIGINT,done1); 333df930be7Sderaadt mklev(); 334df930be7Sderaadt u.ux = xupstair; 335df930be7Sderaadt u.uy = yupstair; 336df930be7Sderaadt (void) inshop(); 337df930be7Sderaadt setsee(); 338df930be7Sderaadt flags.botlx = 1; 339df930be7Sderaadt makedog(); 340df930be7Sderaadt { register struct monst *mtmp; 341df930be7Sderaadt if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp); /* riv05!a3 */ 342df930be7Sderaadt } 343df930be7Sderaadt seemons(); 344df930be7Sderaadt #ifdef NEWS 345df930be7Sderaadt if(flags.nonews || !readnews()) 346df930be7Sderaadt /* after reading news we did docrt() already */ 347df930be7Sderaadt #endif 348df930be7Sderaadt docrt(); 349df930be7Sderaadt 350df930be7Sderaadt /* give welcome message before pickup messages */ 351df930be7Sderaadt pline("Hello %s, welcome to %s!", plname, gamename); 352df930be7Sderaadt 353df930be7Sderaadt pickup(1); 354df930be7Sderaadt read_engr_at(u.ux,u.uy); 355df930be7Sderaadt flags.move = 1; 356df930be7Sderaadt } 357df930be7Sderaadt 358df930be7Sderaadt flags.moonphase = phase_of_the_moon(); 359df930be7Sderaadt if(flags.moonphase == FULL_MOON) { 360df930be7Sderaadt pline("You are lucky! Full moon tonight."); 361df930be7Sderaadt u.uluck++; 362df930be7Sderaadt } else if(flags.moonphase == NEW_MOON) { 363df930be7Sderaadt pline("Be careful! New moon tonight."); 364df930be7Sderaadt } 365df930be7Sderaadt 366df930be7Sderaadt initrack(); 367df930be7Sderaadt 368df930be7Sderaadt for(;;) { 369df930be7Sderaadt if(flags.move) { /* actual time passed */ 370df930be7Sderaadt 371df930be7Sderaadt settrack(); 372df930be7Sderaadt 373df930be7Sderaadt if(moves%2 == 0 || 374df930be7Sderaadt (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { 375df930be7Sderaadt extern struct monst *makemon(); 376df930be7Sderaadt movemon(); 377df930be7Sderaadt if(!rn2(70)) 378df930be7Sderaadt (void) makemon((struct permonst *)0, 0, 0); 379df930be7Sderaadt } 380df930be7Sderaadt if(Glib) glibr(); 381df930be7Sderaadt timeout(); 382df930be7Sderaadt ++moves; 383df930be7Sderaadt if(flags.time) flags.botl = 1; 384df930be7Sderaadt if(u.uhp < 1) { 385df930be7Sderaadt pline("You die..."); 386df930be7Sderaadt done("died"); 387df930be7Sderaadt } 388df930be7Sderaadt if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){ 389df930be7Sderaadt wailmsg = moves; 390df930be7Sderaadt if(u.uhp == 1) 391df930be7Sderaadt pline("You hear the wailing of the Banshee..."); 392df930be7Sderaadt else 393df930be7Sderaadt pline("You hear the howling of the CwnAnnwn..."); 394df930be7Sderaadt } 395df930be7Sderaadt if(u.uhp < u.uhpmax) { 396df930be7Sderaadt if(u.ulevel > 9) { 397df930be7Sderaadt if(Regeneration || !(moves%3)) { 398df930be7Sderaadt flags.botl = 1; 399df930be7Sderaadt u.uhp += rnd((int) u.ulevel-9); 400df930be7Sderaadt if(u.uhp > u.uhpmax) 401df930be7Sderaadt u.uhp = u.uhpmax; 402df930be7Sderaadt } 403df930be7Sderaadt } else if(Regeneration || 404df930be7Sderaadt (!(moves%(22-u.ulevel*2)))) { 405df930be7Sderaadt flags.botl = 1; 406df930be7Sderaadt u.uhp++; 407df930be7Sderaadt } 408df930be7Sderaadt } 409df930be7Sderaadt if(Teleportation && !rn2(85)) tele(); 410df930be7Sderaadt if(Searching && multi >= 0) (void) dosearch(); 411df930be7Sderaadt gethungry(); 412df930be7Sderaadt invault(); 413df930be7Sderaadt amulet(); 414df930be7Sderaadt } 415df930be7Sderaadt if(multi < 0) { 416df930be7Sderaadt if(!++multi){ 417df930be7Sderaadt pline(nomovemsg ? nomovemsg : 418df930be7Sderaadt "You can move again."); 419df930be7Sderaadt nomovemsg = 0; 420df930be7Sderaadt if(afternmv) (*afternmv)(); 421df930be7Sderaadt afternmv = 0; 422df930be7Sderaadt } 423df930be7Sderaadt } 424df930be7Sderaadt 425df930be7Sderaadt find_ac(); 426df930be7Sderaadt #ifndef QUEST 427df930be7Sderaadt if(!flags.mv || Blind) 428df930be7Sderaadt #endif 429df930be7Sderaadt { 430df930be7Sderaadt seeobjs(); 431df930be7Sderaadt seemons(); 432df930be7Sderaadt nscr(); 433df930be7Sderaadt } 434df930be7Sderaadt if(flags.botl || flags.botlx) bot(); 435df930be7Sderaadt 436df930be7Sderaadt flags.move = 1; 437df930be7Sderaadt 438df930be7Sderaadt if(multi >= 0 && occupation) { 439df930be7Sderaadt if(monster_nearby()) 440df930be7Sderaadt stop_occupation(); 441df930be7Sderaadt else if ((*occupation)() == 0) 442df930be7Sderaadt occupation = 0; 443df930be7Sderaadt continue; 444df930be7Sderaadt } 445df930be7Sderaadt 446df930be7Sderaadt if(multi > 0) { 447df930be7Sderaadt #ifdef QUEST 448df930be7Sderaadt if(flags.run >= 4) finddir(); 449df930be7Sderaadt #endif 450df930be7Sderaadt lookaround(); 451df930be7Sderaadt if(!multi) { /* lookaround may clear multi */ 452df930be7Sderaadt flags.move = 0; 453df930be7Sderaadt continue; 454df930be7Sderaadt } 455df930be7Sderaadt if(flags.mv) { 456df930be7Sderaadt if(multi < COLNO && !--multi) 457df930be7Sderaadt flags.mv = flags.run = 0; 458df930be7Sderaadt domove(); 459df930be7Sderaadt } else { 460df930be7Sderaadt --multi; 461df930be7Sderaadt rhack(save_cm); 462df930be7Sderaadt } 463df930be7Sderaadt } else if(multi == 0) { 464df930be7Sderaadt #ifdef MAIL 465df930be7Sderaadt ckmailstatus(); 466df930be7Sderaadt #endif 467df930be7Sderaadt rhack((char *) 0); 468df930be7Sderaadt } 469df930be7Sderaadt if(multi && multi%7 == 0) 470df930be7Sderaadt (void) fflush(stdout); 471df930be7Sderaadt } 472df930be7Sderaadt } 473df930be7Sderaadt 474df930be7Sderaadt glo(foo) 475df930be7Sderaadt register foo; 476df930be7Sderaadt { 477df930be7Sderaadt /* construct the string xlock.n */ 478df930be7Sderaadt register char *tf; 479df930be7Sderaadt 480df930be7Sderaadt tf = lock; 481df930be7Sderaadt while(*tf && *tf != '.') tf++; 482df930be7Sderaadt (void) sprintf(tf, ".%d", foo); 483df930be7Sderaadt } 484df930be7Sderaadt 485df930be7Sderaadt /* 486df930be7Sderaadt * plname is filled either by an option (-u Player or -uPlayer) or 487df930be7Sderaadt * explicitly (-w implies wizard) or by askname. 488df930be7Sderaadt * It may still contain a suffix denoting pl_character. 489df930be7Sderaadt */ 490df930be7Sderaadt askname(){ 491df930be7Sderaadt register int c,ct; 492df930be7Sderaadt printf("\nWho are you? "); 493df930be7Sderaadt (void) fflush(stdout); 494df930be7Sderaadt ct = 0; 495df930be7Sderaadt while((c = getchar()) != '\n'){ 496df930be7Sderaadt if(c == EOF) error("End of input\n"); 497df930be7Sderaadt /* some people get confused when their erase char is not ^H */ 498df930be7Sderaadt if(c == '\010') { 499df930be7Sderaadt if(ct) ct--; 500df930be7Sderaadt continue; 501df930be7Sderaadt } 502df930be7Sderaadt if(c != '-') 503df930be7Sderaadt if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_'; 504df930be7Sderaadt if(ct < sizeof(plname)-1) plname[ct++] = c; 505df930be7Sderaadt } 506df930be7Sderaadt plname[ct] = 0; 507df930be7Sderaadt if(ct == 0) askname(); 508df930be7Sderaadt } 509df930be7Sderaadt 510df930be7Sderaadt /*VARARGS1*/ 511df930be7Sderaadt impossible(s,x1,x2) 512df930be7Sderaadt register char *s; 513df930be7Sderaadt { 514df930be7Sderaadt pline(s,x1,x2); 515df930be7Sderaadt pline("Program in disorder - perhaps you'd better Quit."); 516df930be7Sderaadt } 517df930be7Sderaadt 518df930be7Sderaadt #ifdef CHDIR 519df930be7Sderaadt static void 520df930be7Sderaadt chdirx(dir, wr) 521df930be7Sderaadt char *dir; 522df930be7Sderaadt boolean wr; 523df930be7Sderaadt { 524df930be7Sderaadt 525df930be7Sderaadt #ifdef SECURE 526df930be7Sderaadt if(dir /* User specified directory? */ 527df930be7Sderaadt #ifdef HACKDIR 528df930be7Sderaadt && strcmp(dir, HACKDIR) /* and not the default? */ 529df930be7Sderaadt #endif 530df930be7Sderaadt ) { 531161033a1Sderaadt /* revoke */ 532161033a1Sderaadt setegid(getgid()); 533161033a1Sderaadt setgid(getgid()); 534df930be7Sderaadt } 535df930be7Sderaadt #endif 536df930be7Sderaadt 537df930be7Sderaadt #ifdef HACKDIR 538df930be7Sderaadt if(dir == NULL) 539df930be7Sderaadt dir = HACKDIR; 540df930be7Sderaadt #endif 541df930be7Sderaadt 542df930be7Sderaadt if(dir && chdir(dir) < 0) { 543df930be7Sderaadt perror(dir); 544df930be7Sderaadt error("Cannot chdir to %s.", dir); 545df930be7Sderaadt } 546df930be7Sderaadt 547df930be7Sderaadt /* warn the player if he cannot write the record file */ 548df930be7Sderaadt /* perhaps we should also test whether . is writable */ 549df930be7Sderaadt /* unfortunately the access systemcall is worthless */ 550df930be7Sderaadt if(wr) { 551df930be7Sderaadt register fd; 552df930be7Sderaadt 553df930be7Sderaadt if(dir == NULL) 554df930be7Sderaadt dir = "."; 5556cd28e42Smillert if((fd = open(RECORD, O_RDWR)) < 0) { 556df930be7Sderaadt printf("Warning: cannot write %s/%s", dir, RECORD); 557df930be7Sderaadt getret(); 558df930be7Sderaadt } else 559df930be7Sderaadt (void) close(fd); 560df930be7Sderaadt } 561df930be7Sderaadt } 562df930be7Sderaadt #endif 563df930be7Sderaadt 564df930be7Sderaadt stop_occupation() 565df930be7Sderaadt { 566df930be7Sderaadt if(occupation) { 567df930be7Sderaadt pline("You stop %s.", occtxt); 568df930be7Sderaadt occupation = 0; 569df930be7Sderaadt } 570df930be7Sderaadt } 571