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

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