xref: /netbsd-src/games/hack/hack.cmd.c (revision 2c0ecb1ab63c4e87a4abcff12e0a9e999ff836d9)
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