home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume3 / nethack2.2 / part12 / unixmain.c < prev    next >
C/C++ Source or Header  |  1987-12-02  |  12KB  |  594 lines

  1. /*    SCCS Id: @(#)unixmain.c    2.1    87/10/18
  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, welcome to %s!", plname, gamename);
  236.         flags.move = 0;
  237.     } else {
  238. not_recovered:
  239.         newgame();
  240.         /* give welcome message before pickup messages */
  241.         pline("Hello %s, welcome to %s!", plname, gamename);
  242.  
  243.         pickup(1);
  244.         read_engr_at(u.ux,u.uy);
  245.         flags.move = 1;
  246.     }
  247.  
  248.     flags.moonphase = phase_of_the_moon();
  249.     if(flags.moonphase == FULL_MOON) {
  250.         pline("You are lucky! Full moon tonight.");
  251.         if(!u.uluck) u.uluck++;
  252.     } else if(flags.moonphase == NEW_MOON) {
  253.         pline("Be careful! New moon tonight.");
  254.     }
  255.  
  256.     initrack();
  257.  
  258.     for(;;) {
  259.         if(flags.move) {    /* actual time passed */
  260.  
  261.             settrack();
  262.  
  263.             if(moves%2 == 0 ||
  264.               (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
  265.                 extern struct monst *makemon();
  266.                 movemon();
  267. #ifdef HARD
  268.                 if(!rn2(u.udemigod?25:(dlevel>30)?50:70))
  269. #else
  270.                 if(!rn2(70))
  271. #endif
  272.                     (void) makemon((struct permonst *)0, 0, 0);
  273.             }
  274.             if(Glib) glibr();
  275.             timeout();
  276.             ++moves;
  277. #ifdef PRAYERS
  278.             if (u.ublesscnt)  u.ublesscnt--;
  279. #endif
  280.             if(flags.time) flags.botl = 1;
  281. #ifdef KAA
  282.             if(u.mtimedone)
  283.                 if(u.mh < 1) rehumanize();
  284.             else
  285. #endif
  286.                 if(u.uhp < 1) {
  287.                 pline("You die...");
  288.                 done("died");
  289.                 }
  290.             if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
  291.                 wailmsg = moves;
  292. #ifdef KAA
  293.                 if(index("WEV", pl_character[0])) {
  294.                 if (u.uhp == 1)
  295.                 pline("%s is about to die.", pl_character);
  296.                 else
  297.                 pline("%s, your life force is running out.",
  298.                     pl_character);
  299.                 } else {
  300. #endif
  301.                 if(u.uhp == 1)
  302.                 pline("You hear the wailing of the Banshee...");
  303.                 else
  304.                 pline("You hear the howling of the CwnAnnwn...");
  305. #ifdef KAA
  306.                 }
  307. #endif
  308.             }
  309. #ifdef KAA
  310.             if (u.mtimedone) {
  311.                 if (u.mh < u.mhmax) {
  312.                 if (Regeneration || !(moves%20)) {
  313.                     flags.botl = 1;
  314.                     u.mh++;
  315.                 }
  316.                 }
  317.             }
  318. #endif
  319.             if(u.uhp < u.uhpmax) {
  320.                 if(u.ulevel > 9) {
  321.                     if(HRegeneration || !(moves%3)) {
  322.                         flags.botl = 1;
  323.                         u.uhp += rnd((int) u.ulevel-9);
  324.                         if(u.uhp > u.uhpmax)
  325.                         u.uhp = u.uhpmax;
  326.                     }
  327.                 } else if(HRegeneration ||
  328.                     (!(moves%(22-u.ulevel*2)))) {
  329.                     flags.botl = 1;
  330.                     u.uhp++;
  331.                 }
  332.             }
  333. #ifdef SPELLS
  334.             if ((u.uen<u.uenmax) && (!(moves%(21-u.ulevel/2)))) {
  335.                 u.uen += rn2(u.ulevel/4 + 1) + 1;
  336.                 if (u.uen > u.uenmax)  u.uen = u.uenmax;
  337.                 flags.botl = 1;
  338.             }
  339. #endif
  340.             if(Teleportation && !rn2(85)) tele();
  341. #if defined(KAA) && defined(BVH)
  342.             if(Polymorph && !rn2(100)) polyself();
  343. #endif
  344.             if(Searching && multi >= 0) (void) dosearch();
  345.             gethungry();
  346.             invault();
  347.             amulet();
  348. #ifdef HARD
  349.             if (!rn2(50+(u.ulevel*3))) u_wipe_engr(rnd(3));
  350.             if (u.udemigod) {
  351.  
  352.                 u.udg_cnt--;
  353.                 if(u.udg_cnt <= 0) {
  354.  
  355.                     intervene();
  356.                     u.udg_cnt = rn1(200, 50);
  357.                 }
  358.             }
  359. #endif
  360.         }
  361.         if(multi < 0) {
  362.             if(!++multi){
  363.                 pline(nomovemsg ? nomovemsg :
  364.                     "You can move again.");
  365.                 nomovemsg = 0;
  366.                 if(afternmv) (*afternmv)();
  367.                 afternmv = 0;
  368.             }
  369.         }
  370.  
  371.         find_ac();
  372. #ifndef QUEST
  373.         if(!flags.mv || Blind)
  374. #endif
  375.         {
  376.             seeobjs();
  377.             seemons();
  378.             nscr();
  379.         }
  380. #ifdef DGK
  381.         if(flags.time) flags.botl = 1;
  382. #endif
  383.         if(flags.botl || flags.botlx) bot();
  384.  
  385.         flags.move = 1;
  386.  
  387.         if(multi >= 0 && occupation) {
  388.  
  389.             if (monster_nearby())
  390.                 stop_occupation();
  391.             else if ((*occupation)() == 0)
  392.                 occupation = 0;
  393.             continue;
  394.         }
  395.  
  396.         if(multi > 0) {
  397. #ifdef QUEST
  398.             if(flags.run >= 4) finddir();
  399. #endif
  400.             lookaround();
  401.             if(!multi) {    /* lookaround may clear multi */
  402.                 flags.move = 0;
  403.                 continue;
  404.             }
  405.             if(flags.mv) {
  406.                 if(multi < COLNO && !--multi)
  407.                     flags.mv = flags.run = 0;
  408.                 domove();
  409.             } else {
  410.                 --multi;
  411.                 rhack(save_cm);
  412.             }
  413.         } else if(multi == 0) {
  414. #ifdef MAIL
  415.             ckmailstatus();
  416. #endif
  417.             rhack((char *) 0);
  418.         }
  419.         if(multi && multi%7 == 0)
  420.             (void) fflush(stdout);
  421.     }
  422. }
  423.  
  424. glo(foo)
  425. register foo;
  426. {
  427.     /* construct the string  xlock.n  */
  428.     register char *tf;
  429.  
  430.     tf = lock;
  431.     while(*tf && *tf != '.') tf++;
  432.     (void) sprintf(tf, ".%d", foo);
  433. }
  434.  
  435. /*
  436.  * plname is filled either by an option (-u Player  or  -uPlayer) or
  437.  * explicitly (-w implies wizard) or by askname.
  438.  * It may still contain a suffix denoting pl_character.
  439.  */
  440. askname(){
  441. register int c,ct;
  442.     printf("\nWho are you? ");
  443.     (void) fflush(stdout);
  444.     ct = 0;
  445.     while((c = getchar()) != '\n'){
  446.         if(c == EOF) error("End of input\n");
  447.         /* some people get confused when their erase char is not ^H */
  448.         if(c == '\010') {
  449.             if(ct) ct--;
  450.             continue;
  451.         }
  452.         if(c != '-')
  453.         if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
  454.         if(ct < sizeof(plname)-1) plname[ct++] = c;
  455.     }
  456.     plname[ct] = 0;
  457.     if(ct == 0) askname();
  458. }
  459.  
  460. /*VARARGS1*/
  461. impossible(s,x1,x2)
  462. register char *s;
  463. {
  464.     pline(s,x1,x2);
  465.     pline("Program in disorder - perhaps you'd better Quit.");
  466. }
  467.  
  468. #ifdef CHDIR
  469. static
  470. chdirx(dir, wr)
  471. char *dir;
  472. boolean wr;
  473. {
  474.  
  475. # ifdef SECURE
  476.     if(dir                    /* User specified directory? */
  477. #  ifdef HACKDIR
  478.            && strcmp(dir, HACKDIR)        /* and not the default? */
  479. #  endif
  480.         ) {
  481.         (void) setuid(getuid());        /* Ron Wessels */
  482.         (void) setgid(getgid());
  483.     }
  484. # endif
  485.  
  486. # ifdef HACKDIR
  487.     if(dir == NULL)
  488.         dir = HACKDIR;
  489. # endif
  490.  
  491.     if(dir && chdir(dir) < 0) {
  492.         perror(dir);
  493.         error("Cannot chdir to %s.", dir);
  494.     }
  495.  
  496.     /* warn the player if he cannot write the record file */
  497.     /* perhaps we should also test whether . is writable */
  498.     /* unfortunately the access systemcall is worthless */
  499.     if(wr) {
  500.         register fd;
  501.  
  502.         if(dir == NULL)
  503.         dir = ".";
  504.         if((fd = open(RECORD, 2)) < 0) {
  505.         printf("Warning: cannot write %s/%s", dir, RECORD);
  506.         getret();
  507.         } else
  508.         (void) close(fd);
  509.     }
  510. }
  511. #endif /* CHDIR /**/
  512.  
  513. stop_occupation()
  514. {
  515.     if(occupation) {
  516.         pline("You stop %s.", occtxt);
  517.         occupation = 0;
  518. #ifdef REDO
  519.         multi = 0;
  520.         pushch(0);        
  521. #endif
  522.     }
  523. }
  524.  
  525. whoami() {
  526.     /*
  527.      * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS
  528.      *            2. Use $USER or $LOGNAME    (if 1. fails)
  529.      *            3. Use getlogin()        (if 2. fails)
  530.      * The resulting name is overridden by command line options.
  531.      * If everything fails, or if the resulting name is some generic
  532.      * account like "games", "play", "player", "hack" then eventually
  533.      * we'll ask him.
  534.      * Note that we trust him here; it is possible to play under
  535.      * somebody else's name.
  536.      */
  537.     register char *s;
  538.  
  539. #ifndef DGKMOD
  540.     initoptions();
  541. #endif
  542.     if(!*plname && (s = getenv("USER")))
  543.         (void) strncpy(plname, s, sizeof(plname)-1);
  544.     if(!*plname && (s = getenv("LOGNAME")))
  545.         (void) strncpy(plname, s, sizeof(plname)-1);
  546.     if(!*plname && (s = getlogin()))
  547.         (void) strncpy(plname, s, sizeof(plname)-1);
  548. }
  549.  
  550. newgame() {
  551.     fobj = fcobj = invent = 0;
  552.     fmon = fallen_down = 0;
  553.     ftrap = 0;
  554.     fgold = 0;
  555.     flags.ident = 1;
  556.     init_objects();
  557.     u_init();
  558.  
  559.     (void) signal(SIGINT,done1);
  560.     mklev();
  561.     u.ux = xupstair;
  562.     u.uy = yupstair;
  563.     (void) inshop();
  564.     setsee();
  565.     flags.botlx = 1;
  566.     {
  567.         register struct monst *mtmp;
  568.  
  569.         /* Move the monster from under you or else
  570.          * makedog() will fail when it calls makemon().
  571.          *             - ucsfcgl!kneller
  572.          */
  573.         if (mtmp = m_at(u.ux, u.uy))  mnexto(mtmp);
  574.     }
  575.     (void) makedog();
  576.     seemons();
  577. #ifdef NEWS
  578.     if(flags.nonews || !readnews())
  579.         /* after reading news we did docrt() already */
  580. #endif
  581.         docrt();
  582.     return(0);
  583. }
  584.  
  585. #ifdef GENIX
  586. jhndist(x1,y1,x2,y2)
  587. {
  588.     int x,y;
  589.     x=x1-x2;
  590.     y=y1-y2;
  591.     return (x*x + y*y);
  592. }
  593. #endif
  594.