home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / HACKSRC.ZIP / MAIN.C < prev    next >
C/C++ Source or Header  |  1985-10-16  |  13KB  |  596 lines

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