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

  1. /*    SCCS Id: @(#)cmd.c    2.0    87/09/15
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  
  4. #include    "hack.h"
  5. #include    "func_tab.h"
  6.  
  7. int doredraw(),doredotopl(),dodrop(),dodrink(),doread(),dosearch(),dopickup(),
  8. doversion(),doweararm(),dowearring(),doremarm(),doddoremarm(),doremring(),
  9. dopay(),doapply(),dosave(),dowield(),ddoinv(),dozap(),ddocall(),dowhatis(),
  10. doengrave(),dotele(),dohelp(),doeat(),doddrop(),do_mname(),doidtrap(),
  11. doprwep(),doprarm(),doprring(),doprgold(),dodiscovered(),dotypeinv(),dolook(),
  12. doset(),doup(), dodown(), done1(), donull(), dothrow(), doextcmd(), dodip(),
  13. dopray(), doextlist();
  14. #ifdef WIZARD
  15. int wiz_wish(), wiz_identify();
  16. #endif
  17. #ifdef NEWCLASS
  18. int dosit(), doturn();
  19. #endif
  20. #ifdef SPELLS
  21. int docast(), dovspell(), doxcribe();
  22. #endif
  23. #ifdef SHELL
  24. int dosh();
  25. #endif
  26. #ifdef SUSPEND
  27. int dosuspend();
  28. #endif
  29. #ifdef KAA
  30. int doremove(), dobreathe();
  31. # ifdef KOPS
  32. int dowipe();
  33. # endif
  34. #endif
  35.  
  36. int rndobjsym(), rndmonsym();
  37. char *hcolor(), *rndmonnam(), *defmonnam();
  38.  
  39. extern char *occtxt;
  40. extern int (*occupation)();
  41.  
  42. #ifdef DGKMOD
  43. int dotogglepickup(), doMSCversion();
  44. # ifdef DEBUG
  45. int dodebug();
  46. # endif
  47.  
  48. static int (*timed_occ_fn)();
  49.  
  50. /* Count down by decrementing multi */
  51. timed_occupation() {
  52.     (*timed_occ_fn)();
  53.     if (multi > 0)
  54.         multi--;
  55.     return (multi > 0);
  56. }
  57.  
  58. /* If a time is given, use it to timeout this function, otherwise the
  59.  * function times out by its own means.
  60.  */
  61. void
  62. set_occupation(fn, txt, time)
  63. int (*fn)();
  64. char *txt;
  65. {
  66.     if (time) {
  67.         occupation = timed_occupation;
  68.         timed_occ_fn = fn;
  69.     } else
  70.         occupation = fn;
  71.     occtxt = txt;
  72.     occtime = 0;
  73. }
  74. #endif /* DGKMOD */
  75.  
  76. #ifdef REDO
  77. /* Provide a means to redo the last command.  The flag `in_doagain' is set
  78.  * to true while redoing the command.  This flag is tested in commands that
  79.  * require additional input (like `throw' which requires a thing and a
  80.  * direction), and the input prompt is not shown.  Also, while in_doagain is
  81.  * TRUE, no keystrokes can be saved into the saveq.
  82.  */
  83. #define BSIZE 20
  84. static char pushq[BSIZE], saveq[BSIZE];
  85. static int phead, ptail, shead, stail;
  86. extern int in_doagain;
  87.  
  88. char
  89. popch() {
  90.     /* If occupied, return 0, letting tgetch know a character should
  91.      * be read from the keyboard.  If the character read is not the
  92.      * ABORT character (as checked in main.c), that character will be
  93.      * pushed back on the pushq.
  94.      */
  95.     if (occupation) return(0);
  96.     if (in_doagain) return ((shead != stail) ? saveq[stail++] : 0);
  97.     else        return ((phead != ptail) ? pushq[ptail++] : 0);
  98. }
  99.  
  100. /* A ch == 0 resets the pushq */
  101. void
  102. pushch(ch)
  103. char ch;
  104. {
  105.     if (!ch)
  106.         phead = ptail = 0;
  107.     if (phead < BSIZE)
  108.         pushq[phead++] = ch;
  109. }
  110.  
  111. /* A ch == 0 resets the saveq.  Only save keystrokes when not
  112.  * replaying a previous command.
  113.  */
  114. void
  115. savech(ch)
  116. char ch;
  117. {
  118.     if (!in_doagain) {
  119.         if (!ch)
  120.             phead = ptail = shead = stail = 0;
  121.         else if (shead < BSIZE)
  122.             saveq[shead++] = ch;
  123.     }
  124. }
  125. #endif /* REDO */
  126.  
  127. struct func_tab cmdlist[]={
  128. #ifdef WIZARD
  129.     {'\011', wiz_identify},
  130. #endif
  131.     {'\020', doredotopl},
  132.     {'\022', doredraw},
  133.     {'\024', dotele},
  134. #ifdef WIZARD
  135.     {'\027', wiz_wish},
  136. #endif
  137. #ifdef SUSPEND
  138.     {'\032', dosuspend},
  139. #endif
  140.     {'a', doapply},
  141.     {'A', doddoremarm},
  142. /*    'b', 'B' : go sw */
  143.     {'c', ddocall},
  144.     {'C', do_mname},
  145.     {'d', dodrop},
  146.     {'D', doddrop},
  147.     {'e', doeat},
  148.     {'E', doengrave},
  149. /* Soon to be
  150.     {'f', dofight, "fighting"},
  151.     {'F', doFight, "fighting"},
  152.  */
  153. /*    'g', 'G' : multiple go */
  154. /*    'h', 'H' : go west */
  155.     {'I', dotypeinv},        /* Robert Viduya */
  156.     {'i', ddoinv},
  157. /*    'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
  158. /*    'o', doopen,    */
  159.     {'O', doset},
  160.     {'p', dopay},
  161.     {'P', dowearring},
  162.     {'q', dodrink},
  163.     {'Q', done1},
  164.     {'r', doread},
  165.     {'R', doremring},
  166.     {'s', dosearch, "searching"},
  167.     {'S', dosave},
  168.     {'t', dothrow},
  169.     {'T', doremarm},
  170. /*    'u', 'U' : go ne */
  171.     {'v', doversion},
  172.     {'w', dowield},
  173.     {'W', doweararm},
  174. #ifdef SPELLS
  175.     {'x', dovspell},            /* Mike Stephenson */
  176.     {'X', doxcribe},            /* Mike Stephenson */ 
  177. #endif
  178. /*    'y', 'Y' : go nw */
  179.     {'z', dozap},
  180. #ifdef SPELLS
  181.     {'Z', docast},
  182. #endif
  183.     {'<', doup},
  184.     {'>', dodown},
  185.     {'/', dowhatis},
  186.     {'?', dohelp},
  187. #ifdef SHELL
  188.     {'!', dosh},
  189. #endif
  190.     {'.', donull, "waiting"},
  191.     {' ', donull, "waiting"},
  192.     {',', dopickup},
  193.     {':', dolook},
  194.     {'^', doidtrap},
  195.     {'\\', dodiscovered},        /* Robert Viduya */
  196. #ifdef DGKMOD
  197.     {'@', dotogglepickup},
  198.     {'V', doMSCversion},
  199. # ifdef DEBUG_DOESNT_WORK
  200.     {'\004', dodebug},    /* generic debug function */
  201. # endif
  202. #endif
  203.     {WEAPON_SYM,  doprwep},
  204.     {ARMOR_SYM,  doprarm},
  205.     {RING_SYM,  doprring},
  206.     {GOLD_SYM, doprgold},
  207.     {'#', doextcmd},
  208.     {0,0,0}
  209. };
  210.  
  211. struct ext_func_tab extcmdlist[] = {
  212. #ifdef KAA
  213.     "breathe", "breathe like a dragon", dobreathe,
  214. #endif
  215. #ifdef SPELLS
  216.     "cast", "cast a spell", docast,
  217. #endif
  218.     "dip", "dip an object into something", dodip,
  219.     "pray", "pray to the gods for help", dopray,
  220. #ifdef KAA
  221.     "remove", "remove a cursed item", doremove,
  222. #endif
  223. #ifdef NEWCLASS
  224.     "sit", "sit down", dosit,
  225.     "turn", "turn undead", doturn,
  226. #endif
  227. #if defined(KOPS) && defined(KAA)
  228.     "wipe", "wipe your face off", dowipe,
  229. #endif
  230.     "?", "get this list of extended commands", doextlist,
  231.     (char *) 0, (char *) 0, donull
  232. };
  233.  
  234. extern char *parse(), lowc(), unctrl(), quitchars[];
  235.  
  236. rhack(cmd)
  237. register char *cmd;
  238. {
  239.     register struct func_tab *tlist = cmdlist;
  240.     boolean firsttime = FALSE;
  241.     register res;
  242.  
  243.     if(!cmd) {
  244.         firsttime = TRUE;
  245.         flags.nopick = 0;
  246.         cmd = parse();
  247.     }
  248. #ifdef REDO
  249.     if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
  250.         in_doagain = TRUE;
  251.         stail = 0;
  252.         rhack((char *) 0);    /* read and execute command */
  253.         in_doagain = FALSE;
  254.         return;
  255.     }
  256.  
  257.     /* Special case of *cmd == ' ' handled better below */
  258.     if(!*cmd || *cmd == (char)0377) {
  259. #else
  260.     if(!*cmd || *cmd == (char)0377 || (flags.no_rest_on_space && *cmd == ' ')){
  261. #endif
  262.         bell();
  263.         flags.move = 0;
  264.         return;        /* probably we just had an interrupt */
  265.     }
  266.     if(movecmd(*cmd)) {
  267.     walk:
  268.         if(multi) flags.mv = 1;
  269.         domove();
  270.         return;
  271.     }
  272.     if(movecmd(lowc(*cmd))) {
  273.         flags.run = 1;
  274.     rush:
  275.         if(firsttime){
  276.             if(!multi) multi = COLNO;
  277.             u.last_str_turn = 0;
  278.         }
  279.         flags.mv = 1;
  280. #ifdef QUEST
  281.         if(flags.run >= 4) finddir();
  282.         if(firsttime){
  283.             u.ux0 = u.ux + u.dx;
  284.             u.uy0 = u.uy + u.dy;
  285.         }
  286. #endif
  287.         domove();
  288.         return;
  289.     }
  290.     if((*cmd == 'g' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
  291.         flags.run = 2;
  292.         goto rush;
  293.     }
  294.     if(*cmd == 'G' && movecmd(lowc(cmd[1]))) {
  295.         flags.run = 3;
  296.         goto rush;
  297.     }
  298.     if(*cmd == 'm' && movecmd(cmd[1])) {
  299.         flags.run = 0;
  300.         flags.nopick = 1;
  301.         goto walk;
  302.     }
  303.     if(*cmd == 'M' && movecmd(lowc(cmd[1]))) {
  304.         flags.run = 1;
  305.         flags.nopick = 1;
  306.         goto rush;
  307.     }
  308. #ifdef QUEST
  309.     if(*cmd == cmd[1] && (*cmd == 'g' || *cmd == 'G')) {
  310.         flags.run = 4;
  311.         if(*cmd == 'G') flags.run += 2;
  312.         if(cmd[2] == '-') flags.run += 1;
  313.         goto rush;
  314.     }
  315. #endif
  316.     while(tlist->f_char) {
  317.         if(*cmd == tlist->f_char){
  318. #ifdef DGKMOD
  319.             /* Special case of *cmd == ' ' handled here */
  320.             if (*cmd == ' ' && flags.no_rest_on_space)
  321.                 break;
  322.  
  323.             /* Now control-A can stop lengthy commands */
  324.             if (tlist->f_text && !occupation && multi)
  325.                 set_occupation(tlist->f_funct, tlist->f_text,
  326.                     multi);
  327. #endif
  328.             res = (*(tlist->f_funct))();
  329.             if(!res) {
  330.                 flags.move = 0;
  331.                 multi = 0;
  332.             }
  333.             return;
  334.         }
  335.         tlist++;
  336.     }
  337.     { char expcmd[10];
  338.       register char *cp = expcmd;
  339.       while(*cmd && cp-expcmd < sizeof(expcmd)-2) {
  340.         if(*cmd >= 040 && *cmd < 0177)
  341.             *cp++ = *cmd++;
  342.         else {
  343.             *cp++ = '^';
  344.             *cp++ = *cmd++ ^ 0100;
  345.         }
  346.       }
  347.       *cp++ = 0;
  348.       pline("Unknown command '%s'.", expcmd);
  349.     }
  350.     multi = flags.move = 0;
  351.     return;
  352. }
  353.  
  354. doextcmd()    /* here after # - now read a full-word command */
  355. {
  356.     char buf[BUFSZ];
  357.     register struct ext_func_tab *efp = extcmdlist;
  358.  
  359.     pline("# ");
  360. #ifdef COM_COMPL
  361.     get_ext_cmd(buf);
  362. #else
  363.     getlin(buf);
  364. #endif
  365.     clrlin();
  366.     if(buf[0] == '\033')
  367.         return(0);
  368.     while(efp->ef_txt) {
  369.         if(!strcmp(efp->ef_txt, buf))
  370.             return((*(efp->ef_funct))());
  371.         efp++;
  372.     }
  373.     pline("%s: unknown command.", buf);
  374.     return(0);
  375. }
  376.  
  377. doextlist()    /* here after #? - now list all full-word commands */
  378. {
  379.     register struct ext_func_tab *efp = extcmdlist;
  380.     char     buf[BUFSZ];
  381.  
  382.     set_pager(0);
  383.     if(page_line("") ||
  384.        page_line("        Extended Command Set:") ||
  385.        page_line(""))                     goto quit;
  386.  
  387.     while(efp->ef_txt) {
  388.  
  389.         (void)sprintf(buf, "    %-8s  - %s.", efp->ef_txt, efp->ef_desc);
  390.         if(page_line(buf)) goto quit;
  391.         efp++;
  392.     }
  393.     set_pager(1);
  394.     return(0);
  395. quit:
  396.     set_pager(2);
  397.     return(0);
  398. }
  399.  
  400. char
  401. lowc(sym)
  402. char sym;
  403. {
  404.     return( (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym );
  405. }
  406.  
  407. char
  408. unctrl(sym)
  409. char sym;
  410. {
  411.     return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym );
  412. }
  413.  
  414. /* 'rogue'-like direction commands */
  415. char sdir[] = "hykulnjb><";
  416. schar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 };
  417. schar ydir[10] = {  0,-1,-1,-1, 0, 1, 1, 1, 0, 0 };
  418. schar zdir[10] = {  0, 0, 0, 0, 0, 0, 0, 0, 1,-1 };
  419.  
  420. movecmd(sym)    /* also sets u.dz, but returns false for <> */
  421. char sym;
  422. {
  423.     register char *dp;
  424.  
  425.     u.dz = 0;
  426.     if(!(dp = index(sdir, sym))) return(0);
  427.     u.dx = xdir[dp-sdir];
  428.     u.dy = ydir[dp-sdir];
  429.     u.dz = zdir[dp-sdir];
  430.     return(!u.dz);
  431. }
  432.  
  433. getdir(s)
  434. boolean s;
  435. {
  436.     char dirsym;
  437.  
  438. #ifdef REDO
  439.     if (!in_doagain)
  440. #endif
  441.         if(s) pline("In what direction?");
  442.     dirsym = readchar();
  443. #ifdef REDO
  444.     savech(dirsym);
  445. #endif
  446. #ifdef KAA
  447.     if(dirsym == '.' || dirsym == 's')
  448.         u.dx = u.dy = u.dz = 0;
  449.     else
  450. #endif
  451.     if(!movecmd(dirsym) && !u.dz) {
  452.         if(!index(quitchars, dirsym))
  453.             pline("What a strange direction!");
  454.         return(0);
  455.     }
  456.     if(Confusion && !u.dz) confdir();
  457.     return(1);
  458. }
  459.  
  460. confdir()
  461. {
  462.     register x = rn2(8);
  463.     u.dx = xdir[x];
  464.     u.dy = ydir[x];
  465. }
  466.  
  467. #ifdef QUEST
  468. finddir(){
  469. register int i, ui = u.di;
  470.     for(i = 0; i <= 8; i++){
  471.         if(flags.run & 1) ui++; else ui += 7;
  472.         ui %= 8;
  473.         if(i == 8){
  474.             pline("Not near a wall.");
  475.             flags.move = multi = 0;
  476.             return(0);
  477.         }
  478.         if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
  479.             break;
  480.     }
  481.     for(i = 0; i <= 8; i++){
  482.         if(flags.run & 1) ui += 7; else ui++;
  483.         ui %= 8;
  484.         if(i == 8){
  485.             pline("Not near a room.");
  486.             flags.move = multi = 0;
  487.             return(0);
  488.         }
  489.         if(isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
  490.             break;
  491.     }
  492.     u.di = ui;
  493.     u.dx = xdir[ui];
  494.     u.dy = ydir[ui];
  495. }
  496.  
  497. isroom(x,y)  register x,y; {        /* what about POOL? */
  498.     return(isok(x,y) && (levl[x][y].typ == ROOM ||
  499.                 (levl[x][y].typ >= LDOOR && flags.run >= 6)));
  500. }
  501. #endif /* QUEST /**/
  502.  
  503. isok(x,y) register x,y; {
  504.     /* x corresponds to curx, so x==1 is the first column. Ach. %% */
  505.     return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1);
  506. }
  507.  
  508. #ifdef WIZARD
  509. int wiz_wish()    /* Unlimited wishes for wizard mode by Paul Polderman */
  510. {
  511.     if (!wizard) {
  512.         pline("Alas! You are not allowed to make a wish.");
  513.         pline("Nice try though...");
  514.     } else
  515.         makewish();
  516.     return(0);
  517. }
  518.  
  519. int wiz_identify()
  520. {
  521.     struct obj *obj;
  522.  
  523.     if (!wizard)
  524.         pline("You don't have the proper identity!");
  525.     else {
  526.         for (obj = invent; obj; obj = obj->nobj)
  527.             if (!objects[obj->otyp].oc_name_known || !obj->known)
  528.                 identify(obj);
  529.     }
  530.     return(0);
  531. }
  532. #endif /* WIZARD */
  533.