1*2c0ecb1aSdholland /* $NetBSD: hack.cmd.c,v 1.12 2011/08/06 20:42:43 dholland Exp $ */
23ea4a95cSchristos
302ded532Smycroft /*
41c7f94e5Sjsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm * Amsterdam
61c7f94e5Sjsm * All rights reserved.
71c7f94e5Sjsm *
81c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm * met:
111c7f94e5Sjsm *
121c7f94e5Sjsm * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm * this list of conditions and the following disclaimer.
141c7f94e5Sjsm *
151c7f94e5Sjsm * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm *
191c7f94e5Sjsm * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm * promote products derived from this software without specific prior
221c7f94e5Sjsm * written permission.
231c7f94e5Sjsm *
241c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm */
361c7f94e5Sjsm
371c7f94e5Sjsm /*
381c7f94e5Sjsm * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm * All rights reserved.
401c7f94e5Sjsm *
411c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm * modification, are permitted provided that the following conditions
431c7f94e5Sjsm * are met:
441c7f94e5Sjsm * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm * notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm * derived from this software without specific prior written permission.
511c7f94e5Sjsm *
521c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
551c7f94e5Sjsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6202ded532Smycroft */
6302ded532Smycroft
643ea4a95cSchristos #include <sys/cdefs.h>
6502ded532Smycroft #ifndef lint
66*2c0ecb1aSdholland __RCSID("$NetBSD: hack.cmd.c,v 1.12 2011/08/06 20:42:43 dholland Exp $");
6702ded532Smycroft #endif /* not lint */
6861f28255Scgd
6961f28255Scgd #include "hack.h"
703ea4a95cSchristos #include "extern.h"
7161f28255Scgd #include "def.func_tab.h"
7261f28255Scgd
739b92b189Sdholland static int doextcmd(void);
749b92b189Sdholland
759b92b189Sdholland static const struct func_tab cmdlist[] = {
763ea4a95cSchristos { '\020', doredotopl },
773ea4a95cSchristos { '\022', doredraw },
783ea4a95cSchristos { '\024', dotele },
7961f28255Scgd #ifdef SUSPEND
803ea4a95cSchristos { '\032', dosuspend },
81d594ce93Scgd #endif /* SUSPEND */
823ea4a95cSchristos { 'a', doapply },
8361f28255Scgd /* 'A' : UNUSED */
8461f28255Scgd /* 'b', 'B' : go sw */
853ea4a95cSchristos { 'c', ddocall },
863ea4a95cSchristos { 'C', do_mname },
873ea4a95cSchristos { 'd', dodrop },
883ea4a95cSchristos { 'D', doddrop },
893ea4a95cSchristos { 'e', doeat },
903ea4a95cSchristos { 'E', doengrave },
9161f28255Scgd /* 'f', 'F' : multiple go (might become 'fight') */
9261f28255Scgd /* 'g', 'G' : UNUSED */
9361f28255Scgd /* 'h', 'H' : go west */
943ea4a95cSchristos { 'I', dotypeinv }, /* Robert Viduya */
953ea4a95cSchristos { 'i', ddoinv },
9661f28255Scgd /* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
9761f28255Scgd /* 'o', doopen, */
983ea4a95cSchristos { 'O', doset },
993ea4a95cSchristos { 'p', dopay },
1003ea4a95cSchristos { 'P', dowearring },
1013ea4a95cSchristos { 'q', dodrink },
1023ea4a95cSchristos { 'Q', dodone },
1033ea4a95cSchristos { 'r', doread },
1043ea4a95cSchristos { 'R', doremring },
1053ea4a95cSchristos { 's', dosearch },
1063ea4a95cSchristos { 'S', dosave },
1073ea4a95cSchristos { 't', dothrow },
1083ea4a95cSchristos { 'T', doremarm },
10961f28255Scgd /* 'u', 'U' : go ne */
1103ea4a95cSchristos { 'v', doversion },
11161f28255Scgd /* 'V' : UNUSED */
1123ea4a95cSchristos { 'w', dowield },
1133ea4a95cSchristos { 'W', doweararm },
11461f28255Scgd /* 'x', 'X' : UNUSED */
11561f28255Scgd /* 'y', 'Y' : go nw */
1163ea4a95cSchristos { 'z', dozap },
11761f28255Scgd /* 'Z' : UNUSED */
1183ea4a95cSchristos { '<', doup },
1193ea4a95cSchristos { '>', dodown },
1203ea4a95cSchristos { '/', dowhatis },
1213ea4a95cSchristos { '?', dohelp },
12261f28255Scgd #ifdef SHELL
1233ea4a95cSchristos { '!', dosh },
124d594ce93Scgd #endif /* SHELL */
1253ea4a95cSchristos { '.', donull },
1263ea4a95cSchristos { ' ', donull },
1273ea4a95cSchristos { ',', dopickup },
1283ea4a95cSchristos { ':', dolook },
1293ea4a95cSchristos { '^', doidtrap },
1303ea4a95cSchristos { '\\', dodiscovered }, /* Robert Viduya */
1313ea4a95cSchristos { WEAPON_SYM, doprwep },
1323ea4a95cSchristos { ARMOR_SYM, doprarm },
1333ea4a95cSchristos { RING_SYM, doprring },
1343ea4a95cSchristos { '$', doprgold },
1353ea4a95cSchristos { '#', doextcmd },
1363ea4a95cSchristos { 0, 0 }
13761f28255Scgd };
13861f28255Scgd
1399b92b189Sdholland static const struct ext_func_tab extcmdlist[] = {
1403ea4a95cSchristos { "dip", dodip },
1413ea4a95cSchristos { "pray", dopray },
142*2c0ecb1aSdholland { NULL, donull }
14361f28255Scgd };
14461f28255Scgd
1459b92b189Sdholland static char lowc(int);
1469b92b189Sdholland static char unctrl(int);
1479b92b189Sdholland
1483ea4a95cSchristos void
rhack(const char * cmd)1491fa8a9a6Sdholland rhack(const char *cmd)
15061f28255Scgd {
151ab8b6343Sjsm const struct func_tab *tlist = cmdlist;
15261f28255Scgd boolean firsttime = FALSE;
1533ea4a95cSchristos int res;
15461f28255Scgd
15561f28255Scgd if (!cmd) {
15661f28255Scgd firsttime = TRUE;
15761f28255Scgd flags.nopick = 0;
15861f28255Scgd cmd = parse();
15961f28255Scgd }
16061f28255Scgd if (!*cmd || (*cmd & 0377) == 0377 ||
16161f28255Scgd (flags.no_rest_on_space && *cmd == ' ')) {
16298eb8895Sroy sound_bell();
16361f28255Scgd flags.move = 0;
16461f28255Scgd return; /* probably we just had an interrupt */
16561f28255Scgd }
16661f28255Scgd if (movecmd(*cmd)) {
16761f28255Scgd walk:
1683ea4a95cSchristos if (multi)
1693ea4a95cSchristos flags.mv = 1;
17061f28255Scgd domove();
17161f28255Scgd return;
17261f28255Scgd }
17361f28255Scgd if (movecmd(lowc(*cmd))) {
17461f28255Scgd flags.run = 1;
17561f28255Scgd rush:
17661f28255Scgd if (firsttime) {
1773ea4a95cSchristos if (!multi)
1783ea4a95cSchristos multi = COLNO;
17961f28255Scgd u.last_str_turn = 0;
18061f28255Scgd }
18161f28255Scgd flags.mv = 1;
18261f28255Scgd #ifdef QUEST
1833ea4a95cSchristos if (flags.run >= 4)
1843ea4a95cSchristos finddir();
18561f28255Scgd if (firsttime) {
18661f28255Scgd u.ux0 = u.ux + u.dx;
18761f28255Scgd u.uy0 = u.uy + u.dy;
18861f28255Scgd }
1893ea4a95cSchristos #endif /* QUEST */
19061f28255Scgd domove();
19161f28255Scgd return;
19261f28255Scgd }
19361f28255Scgd if ((*cmd == 'f' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
19461f28255Scgd flags.run = 2;
19561f28255Scgd goto rush;
19661f28255Scgd }
19761f28255Scgd if (*cmd == 'F' && movecmd(lowc(cmd[1]))) {
19861f28255Scgd flags.run = 3;
19961f28255Scgd goto rush;
20061f28255Scgd }
20161f28255Scgd if (*cmd == 'm' && movecmd(cmd[1])) {
20261f28255Scgd flags.run = 0;
20361f28255Scgd flags.nopick = 1;
20461f28255Scgd goto walk;
20561f28255Scgd }
20661f28255Scgd if (*cmd == 'M' && movecmd(lowc(cmd[1]))) {
20761f28255Scgd flags.run = 1;
20861f28255Scgd flags.nopick = 1;
20961f28255Scgd goto rush;
21061f28255Scgd }
21161f28255Scgd #ifdef QUEST
21261f28255Scgd if (*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) {
21361f28255Scgd flags.run = 4;
2143ea4a95cSchristos if (*cmd == 'F')
2153ea4a95cSchristos flags.run += 2;
2163ea4a95cSchristos if (cmd[2] == '-')
2173ea4a95cSchristos flags.run += 1;
21861f28255Scgd goto rush;
21961f28255Scgd }
2203ea4a95cSchristos #endif /* QUEST */
22161f28255Scgd while (tlist->f_char) {
22261f28255Scgd if (*cmd == tlist->f_char) {
22361f28255Scgd res = (*(tlist->f_funct)) ();
22461f28255Scgd if (!res) {
22561f28255Scgd flags.move = 0;
22661f28255Scgd multi = 0;
22761f28255Scgd }
22861f28255Scgd return;
22961f28255Scgd }
23061f28255Scgd tlist++;
23161f28255Scgd }
2323ea4a95cSchristos {
2333ea4a95cSchristos char expcmd[10];
2343ea4a95cSchristos char *cp = expcmd;
2353c439f43Sdholland while (*cmd && cp - expcmd < (int)sizeof(expcmd) - 2) {
23661f28255Scgd if (*cmd >= 040 && *cmd < 0177)
23761f28255Scgd *cp++ = *cmd++;
23861f28255Scgd else {
23961f28255Scgd *cp++ = '^';
24061f28255Scgd *cp++ = *cmd++ ^ 0100;
24161f28255Scgd }
24261f28255Scgd }
24361f28255Scgd *cp++ = 0;
24461f28255Scgd pline("Unknown command '%s'.", expcmd);
24561f28255Scgd }
24661f28255Scgd multi = flags.move = 0;
24761f28255Scgd }
24861f28255Scgd
2499b92b189Sdholland static int
doextcmd(void)2501fa8a9a6Sdholland doextcmd(void)
2513ea4a95cSchristos { /* here after # - now read a full-word
2523ea4a95cSchristos * command */
25361f28255Scgd char buf[BUFSZ];
254ab8b6343Sjsm const struct ext_func_tab *efp = extcmdlist;
25561f28255Scgd
25661f28255Scgd pline("# ");
25761f28255Scgd getlin(buf);
25861f28255Scgd clrlin();
25961f28255Scgd if (buf[0] == '\033')
26061f28255Scgd return (0);
26161f28255Scgd while (efp->ef_txt) {
26261f28255Scgd if (!strcmp(efp->ef_txt, buf))
26361f28255Scgd return ((*(efp->ef_funct)) ());
26461f28255Scgd efp++;
26561f28255Scgd }
26661f28255Scgd pline("%s: unknown command.", buf);
26761f28255Scgd return (0);
26861f28255Scgd }
26961f28255Scgd
2709b92b189Sdholland static char
lowc(int sym)2711fa8a9a6Sdholland lowc(int sym)
27261f28255Scgd {
27361f28255Scgd return ((sym >= 'A' && sym <= 'Z') ? sym + 'a' - 'A' : sym);
27461f28255Scgd }
27561f28255Scgd
2769b92b189Sdholland static char
unctrl(int sym)2771fa8a9a6Sdholland unctrl(int sym)
27861f28255Scgd {
27961f28255Scgd return ((sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym);
28061f28255Scgd }
28161f28255Scgd
28261f28255Scgd /* 'rogue'-like direction commands */
28361f28255Scgd char sdir[] = "hykulnjb><";
28461f28255Scgd schar xdir[10] = {-1, -1, 0, 1, 1, 1, 0, -1, 0, 0};
28561f28255Scgd schar ydir[10] = {0, -1, -1, -1, 0, 1, 1, 1, 0, 0};
2869b92b189Sdholland static schar zdir[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, -1};
28761f28255Scgd
2883ea4a95cSchristos int
movecmd(int sym)2891fa8a9a6Sdholland movecmd(int sym) /* also sets u.dz, but returns false for <> */
29061f28255Scgd {
2913ea4a95cSchristos char *dp;
29261f28255Scgd
29361f28255Scgd u.dz = 0;
2943ea4a95cSchristos if (!(dp = strchr(sdir, sym)))
2953ea4a95cSchristos return (0);
29661f28255Scgd u.dx = xdir[dp - sdir];
29761f28255Scgd u.dy = ydir[dp - sdir];
29861f28255Scgd u.dz = zdir[dp - sdir];
29961f28255Scgd return (!u.dz);
30061f28255Scgd }
30161f28255Scgd
3023ea4a95cSchristos int
getdir(boolean s)3031fa8a9a6Sdholland getdir(boolean s)
30461f28255Scgd {
30561f28255Scgd char dirsym;
30661f28255Scgd
3073ea4a95cSchristos if (s)
3083ea4a95cSchristos pline("In what direction?");
30961f28255Scgd dirsym = readchar();
31061f28255Scgd if (!movecmd(dirsym) && !u.dz) {
3113ea4a95cSchristos if (!strchr(quitchars, dirsym))
31261f28255Scgd pline("What a strange direction!");
31361f28255Scgd return (0);
31461f28255Scgd }
31561f28255Scgd if (Confusion && !u.dz)
31661f28255Scgd confdir();
31761f28255Scgd return (1);
31861f28255Scgd }
31961f28255Scgd
3203ea4a95cSchristos void
confdir(void)3211fa8a9a6Sdholland confdir(void)
32261f28255Scgd {
3233ea4a95cSchristos int x = rn2(8);
32461f28255Scgd u.dx = xdir[x];
32561f28255Scgd u.dy = ydir[x];
32661f28255Scgd }
32761f28255Scgd
32861f28255Scgd #ifdef QUEST
3293ea4a95cSchristos int
finddir(void)3301fa8a9a6Sdholland finddir(void)
3313ea4a95cSchristos {
3323ea4a95cSchristos int i, ui = u.di;
33361f28255Scgd for (i = 0; i <= 8; i++) {
3343ea4a95cSchristos if (flags.run & 1)
3353ea4a95cSchristos ui++;
3363ea4a95cSchristos else
3373ea4a95cSchristos ui += 7;
33861f28255Scgd ui %= 8;
33961f28255Scgd if (i == 8) {
34061f28255Scgd pline("Not near a wall.");
34161f28255Scgd flags.move = multi = 0;
34261f28255Scgd return (0);
34361f28255Scgd }
34461f28255Scgd if (!isroom(u.ux + xdir[ui], u.uy + ydir[ui]))
34561f28255Scgd break;
34661f28255Scgd }
34761f28255Scgd for (i = 0; i <= 8; i++) {
3483ea4a95cSchristos if (flags.run & 1)
3493ea4a95cSchristos ui += 7;
3503ea4a95cSchristos else
3513ea4a95cSchristos ui++;
35261f28255Scgd ui %= 8;
35361f28255Scgd if (i == 8) {
35461f28255Scgd pline("Not near a room.");
35561f28255Scgd flags.move = multi = 0;
35661f28255Scgd return (0);
35761f28255Scgd }
35861f28255Scgd if (isroom(u.ux + xdir[ui], u.uy + ydir[ui]))
35961f28255Scgd break;
36061f28255Scgd }
36161f28255Scgd u.di = ui;
36261f28255Scgd u.dx = xdir[ui];
36361f28255Scgd u.dy = ydir[ui];
3643ea4a95cSchristos return 0;
36561f28255Scgd }
36661f28255Scgd
3673ea4a95cSchristos int
isroom(int x,int y)3681fa8a9a6Sdholland isroom(int x, int y)
3693ea4a95cSchristos { /* what about POOL? */
37061f28255Scgd return (isok(x, y) && (levl[x][y].typ == ROOM ||
37161f28255Scgd (levl[x][y].typ >= LDOOR && flags.run >= 6)));
37261f28255Scgd }
3733ea4a95cSchristos #endif /* QUEST */
37461f28255Scgd
3753ea4a95cSchristos int
isok(int x,int y)3761fa8a9a6Sdholland isok(int x, int y)
3773ea4a95cSchristos {
37861f28255Scgd /* x corresponds to curx, so x==1 is the first column. Ach. %% */
37961f28255Scgd return (x >= 1 && x <= COLNO - 1 && y >= 0 && y <= ROWNO - 1);
38061f28255Scgd }
381