xref: /openbsd-src/games/hack/hack.cmd.c (revision aed906e4b20d9afbda31247cdb6acf6f29da8819)
1*aed906e4Smestre /*	$OpenBSD: hack.cmd.c,v 1.9 2016/01/09 18:33:15 mestre Exp $	*/
2d0b779f3Sniklas 
3df930be7Sderaadt /*
4d25013f2Scamield  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5d25013f2Scamield  * Amsterdam
6d25013f2Scamield  * All rights reserved.
7d25013f2Scamield  *
8d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
9d25013f2Scamield  * modification, are permitted provided that the following conditions are
10d25013f2Scamield  * met:
11d25013f2Scamield  *
12d25013f2Scamield  * - Redistributions of source code must retain the above copyright notice,
13d25013f2Scamield  * this list of conditions and the following disclaimer.
14d25013f2Scamield  *
15d25013f2Scamield  * - Redistributions in binary form must reproduce the above copyright
16d25013f2Scamield  * notice, this list of conditions and the following disclaimer in the
17d25013f2Scamield  * documentation and/or other materials provided with the distribution.
18d25013f2Scamield  *
19d25013f2Scamield  * - Neither the name of the Stichting Centrum voor Wiskunde en
20d25013f2Scamield  * Informatica, nor the names of its contributors may be used to endorse or
21d25013f2Scamield  * promote products derived from this software without specific prior
22d25013f2Scamield  * written permission.
23d25013f2Scamield  *
24d25013f2Scamield  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25d25013f2Scamield  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26d25013f2Scamield  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27d25013f2Scamield  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28d25013f2Scamield  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31d25013f2Scamield  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32d25013f2Scamield  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33d25013f2Scamield  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34d25013f2Scamield  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35d25013f2Scamield  */
36d25013f2Scamield 
37d25013f2Scamield /*
38d25013f2Scamield  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39d25013f2Scamield  * All rights reserved.
40d25013f2Scamield  *
41d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
42d25013f2Scamield  * modification, are permitted provided that the following conditions
43d25013f2Scamield  * are met:
44d25013f2Scamield  * 1. Redistributions of source code must retain the above copyright
45d25013f2Scamield  *    notice, this list of conditions and the following disclaimer.
46d25013f2Scamield  * 2. Redistributions in binary form must reproduce the above copyright
47d25013f2Scamield  *    notice, this list of conditions and the following disclaimer in the
48d25013f2Scamield  *    documentation and/or other materials provided with the distribution.
49d25013f2Scamield  * 3. The name of the author may not be used to endorse or promote products
50d25013f2Scamield  *    derived from this software without specific prior written permission.
51d25013f2Scamield  *
52d25013f2Scamield  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53d25013f2Scamield  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54d25013f2Scamield  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55d25013f2Scamield  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58d25013f2Scamield  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59d25013f2Scamield  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60d25013f2Scamield  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61d25013f2Scamield  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62df930be7Sderaadt  */
63df930be7Sderaadt 
644a5fbbc4Spjanzen #include <ctype.h>
65df930be7Sderaadt 
66*aed906e4Smestre #include "def.func_tab.h"
67*aed906e4Smestre #include "hack.h"
68*aed906e4Smestre 
69df930be7Sderaadt struct func_tab cmdlist[]={
704a5fbbc4Spjanzen 	{ '\020', doredotopl },
714a5fbbc4Spjanzen 	{ '\022', doredraw },
724a5fbbc4Spjanzen 	{ '\024', dotele },
73df930be7Sderaadt #ifdef SUSPEND
744a5fbbc4Spjanzen 	{ '\032', dosuspend },
7554da88e4Spjanzen #endif /* SUSPEND */
764a5fbbc4Spjanzen 	{ 'a', doapply },
77df930be7Sderaadt /*	'A' : UNUSED */
78df930be7Sderaadt /*	'b', 'B' : go sw */
794a5fbbc4Spjanzen 	{ 'c', ddocall },
804a5fbbc4Spjanzen 	{ 'C', do_mname },
814a5fbbc4Spjanzen 	{ 'd', dodrop },
824a5fbbc4Spjanzen 	{ 'D', doddrop },
834a5fbbc4Spjanzen 	{ 'e', doeat },
844a5fbbc4Spjanzen 	{ 'E', doengrave },
85df930be7Sderaadt /*	'f', 'F' : multiple go (might become 'fight') */
86df930be7Sderaadt /*	'g', 'G' : UNUSED */
87df930be7Sderaadt /*	'h', 'H' : go west */
884a5fbbc4Spjanzen 	{ 'I', dotypeinv },		/* Robert Viduya */
894a5fbbc4Spjanzen 	{ 'i', ddoinv },
90df930be7Sderaadt /*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
91df930be7Sderaadt /*	'o', doopen,	*/
924a5fbbc4Spjanzen 	{ 'O', doset },
934a5fbbc4Spjanzen 	{ 'p', dopay },
944a5fbbc4Spjanzen 	{ 'P', dowearring },
954a5fbbc4Spjanzen 	{ 'q', dodrink },
964a5fbbc4Spjanzen 	{ 'Q', done2 },
974a5fbbc4Spjanzen 	{ 'r', doread },
984a5fbbc4Spjanzen 	{ 'R', doremring },
994a5fbbc4Spjanzen 	{ 's', dosearch },
1004a5fbbc4Spjanzen 	{ 'S', dosave },
1014a5fbbc4Spjanzen 	{ 't', dothrow },
1024a5fbbc4Spjanzen 	{ 'T', doremarm },
103df930be7Sderaadt /*	'u', 'U' : go ne */
1044a5fbbc4Spjanzen 	{ 'v', doversion },
105df930be7Sderaadt /*	'V' : UNUSED */
1064a5fbbc4Spjanzen 	{ 'w', dowield },
1074a5fbbc4Spjanzen 	{ 'W', doweararm },
108df930be7Sderaadt /*	'x', 'X' : UNUSED */
109df930be7Sderaadt /*	'y', 'Y' : go nw */
1104a5fbbc4Spjanzen 	{ 'z', dozap },
111df930be7Sderaadt /*	'Z' : UNUSED */
1124a5fbbc4Spjanzen 	{ '<', doup },
1134a5fbbc4Spjanzen 	{ '>', dodown },
1144a5fbbc4Spjanzen 	{ '/', dowhatis },
1154a5fbbc4Spjanzen 	{ '?', dohelp },
116df930be7Sderaadt #ifdef SHELL
1174a5fbbc4Spjanzen 	{ '!', dosh },
11854da88e4Spjanzen #endif /* SHELL */
1194a5fbbc4Spjanzen 	{ '.', donull },
1204a5fbbc4Spjanzen 	{ ' ', donull },
1214a5fbbc4Spjanzen 	{ ',', dopickup },
1224a5fbbc4Spjanzen 	{ ':', dolook },
1234a5fbbc4Spjanzen 	{ '^', doidtrap },
1244a5fbbc4Spjanzen 	{ '\\', dodiscovered },		/* Robert Viduya */
1254a5fbbc4Spjanzen 	{ WEAPON_SYM,  doprwep },
1264a5fbbc4Spjanzen 	{ ARMOR_SYM,  doprarm },
1274a5fbbc4Spjanzen 	{ RING_SYM,  doprring },
1284a5fbbc4Spjanzen 	{ '$', doprgold },
1294a5fbbc4Spjanzen 	{ '#', doextcmd },
1304a5fbbc4Spjanzen 	{ '\0', NULL }
131df930be7Sderaadt };
132df930be7Sderaadt 
133df930be7Sderaadt struct ext_func_tab extcmdlist[] = {
1344a5fbbc4Spjanzen 	{ "dip", dodip },
1354a5fbbc4Spjanzen 	{ "pray", dopray },
1364a5fbbc4Spjanzen 	{ NULL, donull}
137df930be7Sderaadt };
138df930be7Sderaadt 
1394a5fbbc4Spjanzen extern char quitchars[];
140df930be7Sderaadt 
1414a5fbbc4Spjanzen static char unctrl(char);
1424a5fbbc4Spjanzen 
1434a5fbbc4Spjanzen void
rhack(char * cmd)1444a5fbbc4Spjanzen rhack(char *cmd)
145df930be7Sderaadt {
1464a5fbbc4Spjanzen 	struct func_tab *tlist = cmdlist;
147df930be7Sderaadt 	boolean firsttime = FALSE;
1484a5fbbc4Spjanzen 	int res;
149df930be7Sderaadt 
150df930be7Sderaadt 	if(!cmd) {
151df930be7Sderaadt 		firsttime = TRUE;
152df930be7Sderaadt 		flags.nopick = 0;
153df930be7Sderaadt 		cmd = parse();
154df930be7Sderaadt 	}
155df930be7Sderaadt 	if(!*cmd || (*cmd & 0377) == 0377 ||
156df930be7Sderaadt 	   (flags.no_rest_on_space && *cmd == ' ')){
1574a5fbbc4Spjanzen 		hackbell();
158df930be7Sderaadt 		flags.move = 0;
159df930be7Sderaadt 		return;		/* probably we just had an interrupt */
160df930be7Sderaadt 	}
161df930be7Sderaadt 	if(movecmd(*cmd)) {
162df930be7Sderaadt 	walk:
163df930be7Sderaadt 		if(multi) flags.mv = 1;
164df930be7Sderaadt 		domove();
165df930be7Sderaadt 		return;
166df930be7Sderaadt 	}
1675eb74ca3Smmcc 	if(movecmd(tolower((unsigned char)*cmd))) {
168df930be7Sderaadt 		flags.run = 1;
169df930be7Sderaadt 	rush:
170df930be7Sderaadt 		if(firsttime){
171df930be7Sderaadt 			if(!multi) multi = COLNO;
172df930be7Sderaadt 			u.last_str_turn = 0;
173df930be7Sderaadt 		}
174df930be7Sderaadt 		flags.mv = 1;
175df930be7Sderaadt #ifdef QUEST
176df930be7Sderaadt 		if(flags.run >= 4) finddir();
177df930be7Sderaadt 		if(firsttime){
178df930be7Sderaadt 			u.ux0 = u.ux + u.dx;
179df930be7Sderaadt 			u.uy0 = u.uy + u.dy;
180df930be7Sderaadt 		}
18154da88e4Spjanzen #endif /* QUEST */
182df930be7Sderaadt 		domove();
183df930be7Sderaadt 		return;
184df930be7Sderaadt 	}
185df930be7Sderaadt 	if((*cmd == 'f' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
186df930be7Sderaadt 		flags.run = 2;
187df930be7Sderaadt 		goto rush;
188df930be7Sderaadt 	}
1895eb74ca3Smmcc 	if(*cmd == 'F' && movecmd(tolower((unsigned char)cmd[1]))) {
190df930be7Sderaadt 		flags.run = 3;
191df930be7Sderaadt 		goto rush;
192df930be7Sderaadt 	}
193df930be7Sderaadt 	if(*cmd == 'm' && movecmd(cmd[1])) {
194df930be7Sderaadt 		flags.run = 0;
195df930be7Sderaadt 		flags.nopick = 1;
196df930be7Sderaadt 		goto walk;
197df930be7Sderaadt 	}
1985eb74ca3Smmcc 	if(*cmd == 'M' && movecmd(tolower((unsigned char)cmd[1]))) {
199df930be7Sderaadt 		flags.run = 1;
200df930be7Sderaadt 		flags.nopick = 1;
201df930be7Sderaadt 		goto rush;
202df930be7Sderaadt 	}
203df930be7Sderaadt #ifdef QUEST
204df930be7Sderaadt 	if(*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) {
205df930be7Sderaadt 		flags.run = 4;
206df930be7Sderaadt 		if(*cmd == 'F') flags.run += 2;
207df930be7Sderaadt 		if(cmd[2] == '-') flags.run += 1;
208df930be7Sderaadt 		goto rush;
209df930be7Sderaadt 	}
21054da88e4Spjanzen #endif /* QUEST */
211df930be7Sderaadt 	while(tlist->f_char) {
212df930be7Sderaadt 		if(*cmd == tlist->f_char){
213df930be7Sderaadt 			res = (*(tlist->f_funct))();
214df930be7Sderaadt 			if(!res) {
215df930be7Sderaadt 				flags.move = 0;
216df930be7Sderaadt 				multi = 0;
217df930be7Sderaadt 			}
218df930be7Sderaadt 			return;
219df930be7Sderaadt 		}
220df930be7Sderaadt 		tlist++;
221df930be7Sderaadt 	}
222df930be7Sderaadt 	{ char expcmd[10];
2234a5fbbc4Spjanzen 	  char *cp = expcmd;
224df930be7Sderaadt 	  while(*cmd && cp-expcmd < sizeof(expcmd)-2) {
225df930be7Sderaadt 		if(*cmd >= 040 && *cmd < 0177)
226df930be7Sderaadt 			*cp++ = *cmd++;
227df930be7Sderaadt 		else {
228df930be7Sderaadt 			*cp++ = '^';
229df930be7Sderaadt 			*cp++ = *cmd++ ^ 0100;
230df930be7Sderaadt 		}
231df930be7Sderaadt 	  }
232df930be7Sderaadt 	  *cp++ = 0;
233df930be7Sderaadt 	  pline("Unknown command '%s'.", expcmd);
234df930be7Sderaadt 	}
235df930be7Sderaadt 	multi = flags.move = 0;
236df930be7Sderaadt }
237df930be7Sderaadt 
2384a5fbbc4Spjanzen int
doextcmd(void)239*aed906e4Smestre doextcmd(void)	/* here after # - now read a full-word command */
240df930be7Sderaadt {
241df930be7Sderaadt 	char buf[BUFSZ];
2424a5fbbc4Spjanzen 	struct ext_func_tab *efp = extcmdlist;
243df930be7Sderaadt 
244df930be7Sderaadt 	pline("# ");
245df930be7Sderaadt 	getlin(buf);
246df930be7Sderaadt 	clrlin();
247df930be7Sderaadt 	if(buf[0] == '\033')
248df930be7Sderaadt 		return(0);
249df930be7Sderaadt 	while(efp->ef_txt) {
250df930be7Sderaadt 		if(!strcmp(efp->ef_txt, buf))
251df930be7Sderaadt 			return((*(efp->ef_funct))());
252df930be7Sderaadt 		efp++;
253df930be7Sderaadt 	}
254df930be7Sderaadt 	pline("%s: unknown command.", buf);
255df930be7Sderaadt 	return(0);
256df930be7Sderaadt }
257df930be7Sderaadt 
2584a5fbbc4Spjanzen static char
unctrl(char sym)2594a5fbbc4Spjanzen unctrl(char sym)
260df930be7Sderaadt {
261df930be7Sderaadt     return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym );
262df930be7Sderaadt }
263df930be7Sderaadt 
264df930be7Sderaadt /* 'rogue'-like direction commands */
265df930be7Sderaadt char sdir[] = "hykulnjb><";
266df930be7Sderaadt schar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 };
267df930be7Sderaadt schar ydir[10] = {  0,-1,-1,-1, 0, 1, 1, 1, 0, 0 };
268df930be7Sderaadt schar zdir[10] = {  0, 0, 0, 0, 0, 0, 0, 0, 1,-1 };
269df930be7Sderaadt 
2704a5fbbc4Spjanzen int
movecmd(char sym)2714a5fbbc4Spjanzen movecmd(char sym)	/* also sets u.dz, but returns false for <> */
272df930be7Sderaadt {
2734a5fbbc4Spjanzen 	char *dp;
274df930be7Sderaadt 
275df930be7Sderaadt 	u.dz = 0;
276180acc8fSmillert 	if(!(dp = strchr(sdir, sym))) return(0);
277df930be7Sderaadt 	u.dx = xdir[dp-sdir];
278df930be7Sderaadt 	u.dy = ydir[dp-sdir];
279df930be7Sderaadt 	u.dz = zdir[dp-sdir];
280df930be7Sderaadt 	return(!u.dz);
281df930be7Sderaadt }
282df930be7Sderaadt 
2834a5fbbc4Spjanzen int
getdir(boolean s)2844a5fbbc4Spjanzen getdir(boolean s)
285df930be7Sderaadt {
286df930be7Sderaadt 	char dirsym;
287df930be7Sderaadt 
288df930be7Sderaadt 	if(s) pline("In what direction?");
289df930be7Sderaadt 	dirsym = readchar();
290df930be7Sderaadt 	if(!movecmd(dirsym) && !u.dz) {
291180acc8fSmillert 		if(!strchr(quitchars, dirsym))
292df930be7Sderaadt 			pline("What a strange direction!");
293df930be7Sderaadt 		return(0);
294df930be7Sderaadt 	}
295df930be7Sderaadt 	if(Confusion && !u.dz)
296df930be7Sderaadt 		confdir();
297df930be7Sderaadt 	return(1);
298df930be7Sderaadt }
299df930be7Sderaadt 
3004a5fbbc4Spjanzen void
confdir(void)301*aed906e4Smestre confdir(void)
302df930be7Sderaadt {
3034a5fbbc4Spjanzen 	int x = rn2(8);
304df930be7Sderaadt 	u.dx = xdir[x];
305df930be7Sderaadt 	u.dy = ydir[x];
306df930be7Sderaadt }
307df930be7Sderaadt 
308df930be7Sderaadt #ifdef QUEST
3094a5fbbc4Spjanzen void
finddir(void)310*aed906e4Smestre finddir(void)
3114a5fbbc4Spjanzen {
3124a5fbbc4Spjanzen 	int i, ui = u.di;
3134a5fbbc4Spjanzen 
314df930be7Sderaadt 	for(i = 0; i <= 8; i++){
315df930be7Sderaadt 		if(flags.run & 1) ui++; else ui += 7;
316df930be7Sderaadt 		ui %= 8;
317df930be7Sderaadt 		if(i == 8){
318df930be7Sderaadt 			pline("Not near a wall.");
319df930be7Sderaadt 			flags.move = multi = 0;
3204a5fbbc4Spjanzen 			return;
321df930be7Sderaadt 		}
322df930be7Sderaadt 		if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
323df930be7Sderaadt 			break;
324df930be7Sderaadt 	}
325df930be7Sderaadt 	for(i = 0; i <= 8; i++){
326df930be7Sderaadt 		if(flags.run & 1) ui += 7; else ui++;
327df930be7Sderaadt 		ui %= 8;
328df930be7Sderaadt 		if(i == 8){
329df930be7Sderaadt 			pline("Not near a room.");
330df930be7Sderaadt 			flags.move = multi = 0;
3314a5fbbc4Spjanzen 			return;
332df930be7Sderaadt 		}
333df930be7Sderaadt 		if(isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
334df930be7Sderaadt 			break;
335df930be7Sderaadt 	}
336df930be7Sderaadt 	u.di = ui;
337df930be7Sderaadt 	u.dx = xdir[ui];
338df930be7Sderaadt 	u.dy = ydir[ui];
339df930be7Sderaadt }
340df930be7Sderaadt 
3414a5fbbc4Spjanzen int
isroom(int x,int y)3424a5fbbc4Spjanzen isroom(int x, int y)
3434a5fbbc4Spjanzen {		/* what about POOL? */
344df930be7Sderaadt 	return(isok(x,y) && (levl[x][y].typ == ROOM ||
345df930be7Sderaadt 				(levl[x][y].typ >= LDOOR && flags.run >= 6)));
346df930be7Sderaadt }
34754da88e4Spjanzen #endif /* QUEST */
348df930be7Sderaadt 
3494a5fbbc4Spjanzen int
isok(int x,int y)3504a5fbbc4Spjanzen isok(int x, int y)
3514a5fbbc4Spjanzen {
352df930be7Sderaadt 	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
353df930be7Sderaadt 	return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1);
354df930be7Sderaadt }
355