xref: /dragonfly/games/hack/hack.cmd.c (revision 6b5c5d0d)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.cmd.c - version 1.0.3 */
3 /* $FreeBSD: src/games/hack/hack.cmd.c,v 1.4 1999/11/16 10:26:35 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.cmd.c,v 1.4 2006/08/21 19:45:32 pavalos Exp $ */
5 
6 #include	"hack.h"
7 #include	"def.func_tab.h"
8 
9 static int	doextcmd(void);
10 static char	lowc(char);
11 static char	unctrl(char);
12 #ifdef QUEST
13 static bool	isroom(int, int);
14 #endif
15 static int	done2(void);
16 
17 struct func_tab cmdlist[]={
18 	{ '\020', doredotopl },
19 	{ '\022', doredraw },
20 	{ '\024', dotele },
21 #ifdef SUSPEND
22 	{ '\032', dosuspend },
23 #endif /* SUSPEND */
24 	{ 'a', doapply },
25 /*	'A' : UNUSED */
26 /*	'b', 'B' : go sw */
27 	{ 'c', ddocall },
28 	{ 'C', do_mname },
29 	{ 'd', dodrop },
30 	{ 'D', doddrop },
31 	{ 'e', doeat },
32 	{ 'E', doengrave },
33 /*	'f', 'F' : multiple go (might become 'fight') */
34 /*	'g', 'G' : UNUSED */
35 /*	'h', 'H' : go west */
36 	{ 'I', dotypeinv },		/* Robert Viduya */
37 	{ 'i', ddoinv },
38 /*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
39 /*	'o', doopen,	*/
40 	{ 'O', doset },
41 	{ 'p', dopay },
42 	{ 'P', dowearring },
43 	{ 'q', dodrink },
44 	{ 'Q', done2 },
45 	{ 'r', doread },
46 	{ 'R', doremring },
47 	{ 's', dosearch },
48 	{ 'S', dosave },
49 	{ 't', dothrow },
50 	{ 'T', doremarm },
51 /*	'u', 'U' : go ne */
52 	{ 'v', doversion },
53 /*	'V' : UNUSED */
54 	{ 'w', dowield },
55 	{ 'W', doweararm },
56 /*	'x', 'X' : UNUSED */
57 /*	'y', 'Y' : go nw */
58 	{ 'z', dozap },
59 /*	'Z' : UNUSED */
60 	{ '<', doup },
61 	{ '>', dodown },
62 	{ '/', dowhatis },
63 	{ '?', dohelp },
64 #ifdef SHELL
65 	{ '!', dosh },
66 #endif /* SHELL */
67 	{ '.', donull },
68 	{ ' ', donull },
69 	{ ',', dopickup },
70 	{ ':', dolook },
71 	{ '^', doidtrap },
72 	{ '\\', dodiscovered },		/* Robert Viduya */
73 	{ WEAPON_SYM,  doprwep },
74 	{ ARMOR_SYM,  doprarm },
75 	{ RING_SYM,  doprring },
76 	{ '$', doprgold },
77 	{ '#', doextcmd },
78 	{ 0, 0 }
79 };
80 
81 struct ext_func_tab extcmdlist[] = {
82 	{ "dip", dodip },
83 	{ "pray", dopray },
84 	{ (char *) 0, donull }
85 };
86 
87 extern char quitchars[];
88 
89 void
90 rhack(const char *cmd)
91 {
92 	struct func_tab *tlist = cmdlist;
93 	boolean firsttime = FALSE;
94 	int res;
95 
96 	if(!cmd) {
97 		firsttime = TRUE;
98 		flags.nopick = 0;
99 		cmd = parse();
100 	}
101 	if(!*cmd || (*cmd & 0377) == 0377 ||
102 	   (flags.no_rest_on_space && *cmd == ' ')){
103 		bell();
104 		flags.move = 0;
105 		return;		/* probably we just had an interrupt */
106 	}
107 	if(movecmd(*cmd)) {
108 	walk:
109 		if(multi) flags.mv = 1;
110 		domove();
111 		return;
112 	}
113 	if(movecmd(lowc(*cmd))) {
114 		flags.run = 1;
115 	rush:
116 		if(firsttime){
117 			if(!multi) multi = COLNO;
118 			u.last_str_turn = 0;
119 		}
120 		flags.mv = 1;
121 #ifdef QUEST
122 		if(flags.run >= 4) finddir();
123 		if(firsttime){
124 			u.ux0 = u.ux + u.dx;
125 			u.uy0 = u.uy + u.dy;
126 		}
127 #endif /* QUEST */
128 		domove();
129 		return;
130 	}
131 	if((*cmd == 'f' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
132 		flags.run = 2;
133 		goto rush;
134 	}
135 	if(*cmd == 'F' && movecmd(lowc(cmd[1]))) {
136 		flags.run = 3;
137 		goto rush;
138 	}
139 	if(*cmd == 'm' && movecmd(cmd[1])) {
140 		flags.run = 0;
141 		flags.nopick = 1;
142 		goto walk;
143 	}
144 	if(*cmd == 'M' && movecmd(lowc(cmd[1]))) {
145 		flags.run = 1;
146 		flags.nopick = 1;
147 		goto rush;
148 	}
149 #ifdef QUEST
150 	if(*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) {
151 		flags.run = 4;
152 		if(*cmd == 'F') flags.run += 2;
153 		if(cmd[2] == '-') flags.run += 1;
154 		goto rush;
155 	}
156 #endif /* QUEST */
157 	while(tlist->f_char) {
158 		if(*cmd == tlist->f_char){
159 			res = (*(tlist->f_funct))();
160 			if(!res) {
161 				flags.move = 0;
162 				multi = 0;
163 			}
164 			return;
165 		}
166 		tlist++;
167 	}
168 	{ char expcmd[10];
169 	  char *cp = expcmd;
170 	  while(*cmd && cp-expcmd < (int)sizeof(expcmd)-2) {
171 		if(*cmd >= 040 && *cmd < 0177)
172 			*cp++ = *cmd++;
173 		else {
174 			*cp++ = '^';
175 			*cp++ = *cmd++ ^ 0100;
176 		}
177 	  }
178 	  *cp++ = 0;
179 	  pline("Unknown command '%s'.", expcmd);
180 	}
181 	multi = flags.move = 0;
182 }
183 
184 static int
185 doextcmd(void)	/* here after # - now read a full-word command */
186 {
187 	char buf[BUFSZ];
188 	struct ext_func_tab *efp = extcmdlist;
189 
190 	pline("# ");
191 	getlin(buf);
192 	clrlin();
193 	if(buf[0] == '\033')
194 		return(0);
195 	while(efp->ef_txt) {
196 		if(!strcmp(efp->ef_txt, buf))
197 			return((*(efp->ef_funct))());
198 		efp++;
199 	}
200 	pline("%s: unknown command.", buf);
201 	return(0);
202 }
203 
204 static char
205 lowc(char sym)
206 {
207     return( (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym );
208 }
209 
210 static char
211 unctrl(char sym)
212 {
213     return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym );
214 }
215 
216 /* 'rogue'-like direction commands */
217 char sdir[] = "hykulnjb><";
218 schar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 };
219 schar ydir[10] = {  0,-1,-1,-1, 0, 1, 1, 1, 0, 0 };
220 schar zdir[10] = {  0, 0, 0, 0, 0, 0, 0, 0, 1,-1 };
221 
222 bool
223 movecmd(char sym)	/* also sets u.dz, but returns false for <> */
224 {
225 	char *dp;
226 
227 	u.dz = 0;
228 	if(!(dp = index(sdir, sym))) return(0);
229 	u.dx = xdir[dp-sdir];
230 	u.dy = ydir[dp-sdir];
231 	u.dz = zdir[dp-sdir];
232 	return(!u.dz);
233 }
234 
235 bool
236 getdir(bool s)
237 {
238 	char dirsym;
239 
240 	if(s) pline("In what direction?");
241 	dirsym = readchar();
242 	if(!movecmd(dirsym) && !u.dz) {
243 		if(!index(quitchars, dirsym))
244 			pline("What a strange direction!");
245 		return(0);
246 	}
247 	if(Confusion && !u.dz)
248 		confdir();
249 	return(1);
250 }
251 
252 void
253 confdir(void)
254 {
255 	int x = rn2(8);
256 	u.dx = xdir[x];
257 	u.dy = ydir[x];
258 }
259 
260 #ifdef QUEST
261 void
262 finddir(void)
263 {
264 int i, ui = u.di;
265 	for(i = 0; i <= 8; i++){
266 		if(flags.run & 1) ui++; else ui += 7;
267 		ui %= 8;
268 		if(i == 8){
269 			pline("Not near a wall.");
270 			flags.move = multi = 0;
271 			return;
272 		}
273 		if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
274 			break;
275 	}
276 	for(i = 0; i <= 8; i++){
277 		if(flags.run & 1) ui += 7; else ui++;
278 		ui %= 8;
279 		if(i == 8){
280 			pline("Not near a room.");
281 			flags.move = multi = 0;
282 			return;
283 		}
284 		if(isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
285 			break;
286 	}
287 	u.di = ui;
288 	u.dx = xdir[ui];
289 	u.dy = ydir[ui];
290 }
291 
292 static bool
293 isroom(int x, int y)
294 {		/* what about POOL? */
295 	return(isok(x,y) && (levl[x][y].typ == ROOM ||
296 				(levl[x][y].typ >= LDOOR && flags.run >= 6)));
297 }
298 #endif /* QUEST */
299 
300 bool
301 isok(int x, int y)
302 {
303 	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
304 	return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1);
305 }
306 
307 /*
308  * done2 is a function that fits into cmdlist[] (int func(void))
309  * and calls done1 which discards its argument.
310  */
311 static int
312 done2(void)
313 {
314 	done1(0);
315 	return(0);
316 }
317