home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d189 / nethack.lha / NetHack / eenaux.zoo / aux / unixmain.c < prev   
C/C++ Source or Header  |  1988-07-28  |  13KB  |  608 lines

  1. /*    SCCS Id: @(#)unixmain.c 2.3     88/01/21
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* main.c - (Unix) version */
  4.  
  5. #include <stdio.h>
  6. #include <signal.h>
  7. #include "hack.h"
  8.  
  9. #ifdef QUEST
  10. #define gamename    "NetQuest"
  11. #else
  12. #define gamename    "NetHack"
  13. #endif
  14.  
  15. extern char *getlogin(), *getenv();
  16. extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
  17.  
  18. int (*afternmv)();
  19. int (*occupation)();
  20.  
  21. int done1();
  22. int hangup();
  23.  
  24. int hackpid;                /* current pid */
  25. int locknum;                /* max num of players */
  26. #ifdef DEF_PAGER
  27. char *catmore;                /* default pager */
  28. #endif
  29. char SAVEF[PL_NSIZ + 11] = "save/";     /* save/99999player */
  30. char *hname;        /* name of the game (argv[0] of call) */
  31. char obuf[BUFSIZ];    /* BUFSIZ is defined in stdio.h */
  32.  
  33. extern char *nomovemsg;
  34. extern long wailmsg;
  35.  
  36. main(argc,argv)
  37. int argc;
  38. char *argv[];
  39. {
  40.     register int fd;
  41. #ifdef CHDIR
  42.     register char *dir;
  43. #endif
  44.  
  45.     hname = argv[0];
  46.     hackpid = getpid();
  47.  
  48. #ifdef CHDIR            /* otherwise no chdir() */
  49.     /*
  50.      * See if we must change directory to the playground.
  51.      * (Perhaps hack runs suid and playground is inaccessible
  52.      *  for the player.)
  53.      * The environment variable HACKDIR is overridden by a
  54.      *  -d command line option (must be the first option given)
  55.      */
  56.  
  57.     dir = getenv("HACKDIR");
  58.     if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
  59.         argc--;
  60.         argv++;
  61.         dir = argv[0]+2;
  62.         if(*dir == '=' || *dir == ':') dir++;
  63.         if(!*dir && argc > 1) {
  64.             argc--;
  65.             argv++;
  66.             dir = argv[0];
  67.         }
  68.         if(!*dir)
  69.             error("Flag -d must be followed by a directory name.");
  70.     }
  71. #endif /* CHDIR /**/
  72. #ifdef GRAPHICS
  73.     /* Set the default values of the presentation characters */
  74.     memcpy((char *) &showsyms, (char *) &defsyms, sizeof(struct symbols));
  75. #endif
  76. #ifdef HACKOPTIONS
  77.     initoptions();
  78. #endif
  79.     whoami();
  80.     /*
  81.      * Now we know the directory containing 'record' and
  82.      * may do a prscore().
  83.      */
  84.     if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
  85. #ifdef CHDIR
  86.         chdirx(dir,0);
  87. #endif
  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.     (void) signal(SIGHUP, hangup);
  105.  
  106.     /*
  107.      * Find the creation date of this game,
  108.      * so as to avoid restoring outdated savefiles.
  109.      */
  110.     gethdate(hname);
  111.  
  112.     /*
  113.      * We cannot do chdir earlier, otherwise gethdate will fail.
  114.      */
  115. #ifdef CHDIR
  116.     chdirx(dir,1);
  117. #endif
  118.  
  119.     /*
  120.      * Process options.
  121.      */
  122.     while(argc > 1 && argv[1][0] == '-'){
  123.         argv++;
  124.         argc--;
  125.         switch(argv[0][1]){
  126. #ifdef WIZARD
  127.         case 'D':
  128.             if(!strcmp(getlogin(), WIZARD))
  129.                 wizard = TRUE;
  130.             else {
  131.                 settty("Sorry, you can't operate in debug mode.\n");
  132.                 clearlocks();
  133.                 exit(0);
  134.             }
  135.             break;
  136. #endif
  137. #ifdef NEWS
  138.         case 'n':
  139.             flags.nonews = TRUE;
  140.             break;
  141. #endif
  142.         case 'u':
  143.             if(argv[0][2])
  144.               (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
  145.             else if(argc > 1) {
  146.               argc--;
  147.               argv++;
  148.               (void) strncpy(plname, argv[0], sizeof(plname)-1);
  149.             } else
  150.                 printf("Player name expected after -u\n");
  151.             break;
  152.         default:
  153.             /* allow -T for Tourist, etc. */
  154.             (void) strncpy(pl_character, argv[0]+1,
  155.                 sizeof(pl_character)-1);
  156.  
  157.             /* printf("Unknown option: %s\n", *argv); */
  158.         }
  159.     }
  160.  
  161.     if(argc > 1)
  162.         locknum = atoi(argv[1]);
  163. #ifdef MAX_NR_OF_PLAYERS
  164.     if(!locknum || locknum > MAX_NR_OF_PLAYERS)
  165.         locknum = MAX_NR_OF_PLAYERS;
  166. #endif
  167. #ifdef DEF_PAGER
  168.     if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER")))
  169.         catmore = DEF_PAGER;
  170. #endif
  171. #ifdef MAIL
  172.     getmailstatus();
  173. #endif
  174. #ifdef WIZARD
  175.     if(wizard) (void) strcpy(plname, "wizard"); else
  176. #endif
  177.     if(!*plname || !strncmp(plname, "player", 4)
  178.             || !strncmp(plname, "games", 4))
  179.         askname();
  180.     plnamesuffix();         /* strip suffix from name; calls askname() */
  181.                 /* again if suffix was whole name */
  182.                 /* accepts any suffix */
  183. #ifdef WIZARD
  184.     if(!wizard) {
  185. #endif
  186.         /*
  187.          * check for multiple games under the same name
  188.          * (if !locknum) or check max nr of players (otherwise)
  189.          */
  190.         (void) signal(SIGQUIT,SIG_IGN);
  191.         (void) signal(SIGINT,SIG_IGN);
  192.         if(!locknum)
  193.             (void) strcpy(lock,plname);
  194.         getlock();      /* sets lock if locknum != 0 */
  195. #ifdef WIZARD
  196.     } else {
  197.         register char *sfoo;
  198.         extern char genocided[], fut_geno[];
  199.         (void) strcpy(lock,plname);
  200.         if(sfoo = getenv("MAGIC"))
  201.             while(*sfoo) {
  202.                 switch(*sfoo++) {
  203.                 case 'n': (void) srand(*sfoo++);
  204.                     break;
  205.                 }
  206.             }
  207.         if(sfoo = getenv("GENOCIDED")){
  208.             if(*sfoo == '!'){
  209.                 extern struct permonst mons[CMNUM+2];
  210.                 register struct permonst *pm = mons;
  211.                 register char *gp = genocided;
  212.  
  213.                 while(pm < mons+CMNUM+2){
  214.                     if(!index(sfoo, pm->mlet))
  215.                         *gp++ = pm->mlet;
  216.                     pm++;
  217.                 }
  218.                 *gp = 0;
  219.             } else
  220.                 (void) strcpy(genocided, sfoo);
  221.             (void) strcpy(fut_geno, genocided);
  222.         }
  223.     }
  224. #endif /* WIZARD /**/
  225.     setftty();
  226.     (void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
  227.     regularize(SAVEF+5);            /* avoid . or / in name */
  228.     if((fd = open(SAVEF,0)) >= 0 &&
  229.        (uptodate(fd) || unlink(SAVEF) == 666)) {
  230.         (void) signal(SIGINT,done1);
  231.         pline("Restoring old save file...");
  232.         (void) fflush(stdout);
  233.         if(!dorecover(fd))
  234.             goto not_recovered;
  235.         pline("Hello %s%s, welcome to %s!",
  236.             (Badged) ? "Officer " : "", plname, gamename);
  237.         flags.move = 0;
  238.     } else {
  239. not_recovered:
  240.         newgame();
  241.         /* give welcome message before pickup messages */
  242.         pline("Hello %s, welcome to %s!", plname, gamename);
  243. #ifdef WIZARD
  244.         if (wizard)
  245. # ifdef STOOGES
  246. pline ("The wiz is at %d, the medusa is at %d, and the stooges are at %d",
  247.             u.wiz_level, u.medusa_level, u.stooge_level);
  248. # else
  249.             pline ("The wiz is at %d, and the medusa at %d",
  250.                u.wiz_level, u.medusa_level);
  251. # endif
  252. #endif
  253.         pickup(1);
  254.         read_engr_at(u.ux,u.uy);
  255.         flags.move = 1;
  256.     }
  257.  
  258.     flags.moonphase = phase_of_the_moon();
  259.     if(flags.moonphase == FULL_MOON) {
  260.         pline("You are lucky! Full moon tonight.");
  261.         if(!u.uluck) change_luck(1);
  262.     } else if(flags.moonphase == NEW_MOON) {
  263.         pline("Be careful! New moon tonight.");
  264.     }
  265.  
  266.     initrack();
  267.  
  268.     for(;;) {
  269.         if(flags.move) {        /* actual time passed */
  270.  
  271.             settrack();
  272.  
  273.             if(moves%2 == 0 ||
  274.               (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
  275.                 extern struct monst *makemon();
  276.                 movemon();
  277. #ifdef HARD
  278.                 if(!rn2(u.udemigod?25:(dlevel>30)?50:70))
  279. #else
  280.                 if(!rn2(70))
  281. #endif
  282.                     (void) makemon((struct permonst *)0, 0, 0);
  283.             }
  284.             if(Glib) glibr();
  285.             timeout();
  286.             ++moves;
  287. #ifdef PRAYERS
  288.             if (u.ublesscnt)  u.ublesscnt--;
  289. #endif
  290.             if(flags.time) flags.botl = 1;
  291. #ifdef KAA
  292.             if(u.mtimedone)
  293.                 if(u.mh < 1) rehumanize();
  294.             else
  295. #endif
  296.                 if(u.uhp < 1) {
  297.                 pline("You die...");
  298.                 done("died");
  299.                 }
  300.             if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
  301.                 wailmsg = moves;
  302. #ifdef KAA
  303.                 if(index("WEV", pl_character[0])) {
  304.                 if (u.uhp == 1)
  305.                 pline("%s is about to die.", pl_character);
  306.                 else
  307.                 pline("%s, your life force is running out.",
  308.                     pl_character);
  309.                 } else {
  310. #endif
  311.                 if(u.uhp == 1)
  312.                 pline("You hear the wailing of the Banshee...");
  313.                 else
  314.                 pline("You hear the howling of the CwnAnnwn...");
  315. #ifdef KAA
  316.                 }
  317. #endif
  318.             }
  319. #ifdef KAA
  320.             if (u.mtimedone) {
  321.                 if (u.mh < u.mhmax) {
  322.                 if (Regeneration || !(moves%20)) {
  323.                     flags.botl = 1;
  324.                     u.mh++;
  325.                 }
  326.                 }
  327.             }
  328. #endif
  329.             if(u.uhp < u.uhpmax) {
  330.                 if(u.ulevel > 9) {
  331.                     if(HRegeneration || !(moves%3)) {
  332.                         flags.botl = 1;
  333.                         u.uhp += rnd((int) u.ulevel-9);
  334.                         if(u.uhp > u.uhpmax)
  335.                         u.uhp = u.uhpmax;
  336.                     }
  337.                 } else if(HRegeneration ||
  338.                     (!(moves%(22-u.ulevel*2)))) {
  339.                     flags.botl = 1;
  340.                     u.uhp++;
  341.                 }
  342.             }
  343. #ifdef SPELLS
  344.             if ((u.uen<u.uenmax) && (!(moves%(21-u.ulevel/2)))) {
  345.                 u.uen += rn2(u.ulevel/4 + 1) + 1;
  346.                 if (u.uen > u.uenmax)  u.uen = u.uenmax;
  347.                 flags.botl = 1;
  348.             }
  349. #endif
  350.             if(Teleportation && !rn2(85)) tele();
  351. #if defined(KAA) && defined(BVH)
  352.             if(Polymorph && !rn2(100)) polyself();
  353. #endif
  354.             if(Searching && multi >= 0) (void) dosearch();
  355.             gethungry();
  356.             invault();
  357.             amulet();
  358. #ifdef HARD
  359.             if (!rn2(50+(u.ulevel*3))) u_wipe_engr(rnd(3));
  360.             if (u.udemigod) {
  361.  
  362.                 u.udg_cnt--;
  363.                 if(u.udg_cnt <= 0) {
  364.  
  365.                     intervene();
  366.                     u.udg_cnt = rn1(200, 50);
  367.                 }
  368.             }
  369. #endif
  370.         }
  371.         if(multi < 0) {
  372.             if(!++multi){
  373.                 pline(nomovemsg ? nomovemsg :
  374.                     "You can move again.");
  375.                 nomovemsg = 0;
  376.                 if(afternmv) (*afternmv)();
  377.                 afternmv = 0;
  378.             }
  379.         }
  380.  
  381.         find_ac();
  382. #ifndef QUEST
  383.         if(!flags.mv || Blind)
  384. #endif
  385.         {
  386.             seeobjs();
  387.             seemons();
  388.             nscr();
  389.         }
  390. #ifdef DGK
  391.         if(flags.time) flags.botl = 1;
  392. #endif
  393.         if(flags.botl || flags.botlx) bot();
  394.  
  395.         flags.move = 1;
  396.  
  397.         if(multi >= 0 && occupation) {
  398.  
  399.             if (monster_nearby())
  400.                 stop_occupation();
  401.             else if ((*occupation)() == 0)
  402.                 occupation = 0;
  403.             continue;
  404.         }
  405.  
  406.         if(multi > 0) {
  407. #ifdef QUEST
  408.             if(flags.run >= 4) finddir();
  409. #endif
  410.             lookaround();
  411.             if(!multi) {    /* lookaround may clear multi */
  412.                 flags.move = 0;
  413.                 continue;
  414.             }
  415.             if(flags.mv) {
  416.                 if(multi < COLNO && !--multi)
  417.                     flags.mv = flags.run = 0;
  418.                 domove();
  419.             } else {
  420.                 --multi;
  421.                 rhack(save_cm);
  422.             }
  423.         } else if(multi == 0) {
  424. #ifdef MAIL
  425.             ckmailstatus();
  426. #endif
  427.             rhack((char *) 0);
  428.         }
  429.         if(multi && multi%7 == 0)
  430.             (void) fflush(stdout);
  431.     }
  432. }
  433.  
  434. glo(foo)
  435. register foo;
  436. {
  437.     /* construct the string  xlock.n  */
  438.     register char *tf;
  439.  
  440.     tf = lock;
  441.     while(*tf && *tf != '.') tf++;
  442.     (void) sprintf(tf, ".%d", foo);
  443. }
  444.  
  445. /*
  446.  * plname is filled either by an option (-u Player  or  -uPlayer) or
  447.  * explicitly (-w implies wizard) or by askname.
  448.  * It may still contain a suffix denoting pl_character.
  449.  */
  450. askname(){
  451. register int c,ct;
  452.     printf("\nWho are you? ");
  453.     (void) fflush(stdout);
  454.     ct = 0;
  455.     while((c = getchar()) != '\n'){
  456.         if(c == EOF) error("End of input\n");
  457.         /* some people get confused when their erase char is not ^H */
  458.         if(c == '\010') {
  459.             if(ct) ct--;
  460.             continue;
  461.         }
  462.         if(c != '-')
  463.         if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
  464.         if(ct < sizeof(plname)-1) plname[ct++] = c;
  465.     }
  466.     plname[ct] = 0;
  467.     if(ct == 0) askname();
  468. }
  469.  
  470. /*VARARGS1*/
  471. impossible(s,x1,x2)
  472. register char *s;
  473. {
  474.     pline(s,x1,x2);
  475.     pline("Program in disorder - perhaps you'd better Quit.");
  476. }
  477.  
  478. #ifdef CHDIR
  479. static
  480. chdirx(dir, wr)
  481. char *dir;
  482. boolean wr;
  483. {
  484.  
  485. # ifdef SECURE
  486.     if(dir                                  /* User specified directory? */
  487. #  ifdef HACKDIR
  488.            && strcmp(dir, HACKDIR)          /* and not the default? */
  489. #  endif
  490.         ) {
  491.         (void) setuid(getuid());                /* Ron Wessels */
  492.         (void) setgid(getgid());
  493.     }
  494. # endif
  495.  
  496. # ifdef HACKDIR
  497.     if(dir == NULL)
  498.         dir = HACKDIR;
  499. # endif
  500.  
  501.     if(dir && chdir(dir) < 0) {
  502.         perror(dir);
  503.         error("Cannot chdir to %s.", dir);
  504.     }
  505.  
  506.     /* warn the player if he cannot write the record file */
  507.     /* perhaps we should also test whether . is writable */
  508.     /* unfortunately the access systemcall is worthless */
  509.     if(wr) {
  510.         register fd;
  511.  
  512.         if(dir == NULL)
  513.         dir = ".";
  514.         if((fd = open(RECORD, 2)) < 0) {
  515.         printf("Warning: cannot write %s/%s", dir, RECORD);
  516.         getret();
  517.         } else
  518.         (void) close(fd);
  519.     }
  520. }
  521. #endif /* CHDIR /**/
  522.  
  523. stop_occupation()
  524. {
  525.     extern void pushch();
  526.  
  527.     if(occupation) {
  528.         pline("You stop %s.", occtxt);
  529.         occupation = 0;
  530. #ifdef REDO
  531.         multi = 0;
  532.         pushch(0);
  533. #endif
  534.     }
  535. }
  536.  
  537. whoami() {
  538.     /*
  539.      * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS
  540.      *            2. Use $USER or $LOGNAME    (if 1. fails)
  541.      *            3. Use getlogin()               (if 2. fails)
  542.      * The resulting name is overridden by command line options.
  543.      * If everything fails, or if the resulting name is some generic
  544.      * account like "games", "play", "player", "hack" then eventually
  545.      * we'll ask him.
  546.      * Note that we trust him here; it is possible to play under
  547.      * somebody else's name.
  548.      */
  549.     register char *s;
  550.  
  551. #ifndef DGKMOD
  552.     initoptions();
  553. #endif
  554.     if(!*plname && (s = getenv("USER")))
  555.         (void) strncpy(plname, s, sizeof(plname)-1);
  556.     if(!*plname && (s = getenv("LOGNAME")))
  557.         (void) strncpy(plname, s, sizeof(plname)-1);
  558.     if(!*plname && (s = getlogin()))
  559.         (void) strncpy(plname, s, sizeof(plname)-1);
  560. }
  561.  
  562. newgame() {
  563.     extern struct monst *makedog();
  564.  
  565.     fobj = fcobj = invent = 0;
  566.     fmon = fallen_down = 0;
  567.     ftrap = 0;
  568.     fgold = 0;
  569.     flags.ident = 1;
  570.     init_objects();
  571.     u_init();
  572.  
  573.     (void) signal(SIGINT,done1);
  574.     mklev();
  575.     u.ux = xupstair;
  576.     u.uy = yupstair;
  577.     (void) inshop();
  578.     setsee();
  579.     flags.botlx = 1;
  580.     {
  581.         register struct monst *mtmp;
  582.  
  583.         /* Move the monster from under you or else
  584.          * makedog() will fail when it calls makemon().
  585.          *            - ucsfcgl!kneller
  586.          */
  587.         if (mtmp = m_at(u.ux, u.uy))  mnexto(mtmp);
  588.     }
  589.     (void) makedog();
  590.     seemons();
  591. #ifdef NEWS
  592.     if(flags.nonews || !readnews())
  593.         /* after reading news we did docrt() already */
  594. #endif
  595.         docrt();
  596.     return(0);
  597. }
  598.  
  599. #ifdef GENIX
  600. jhndist(x1,y1,x2,y2)
  601. {
  602.     int x,y;
  603.     x=x1-x2;
  604.     y=y1-y2;
  605.     return (x*x + y*y);
  606. }
  607. #endif
  608.