games: Massive style(9) cleanup commit. Reduces differences to NetBSD.
[dragonfly.git] / games / hack / hack.cmd.c
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         { NULL, 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)
110                         flags.mv = 1;
111                 domove();
112                 return;
113         }
114         if (movecmd(lowc(*cmd))) {
115                 flags.run = 1;
116 rush:
117                 if (firsttime) {
118                         if (!multi)
119                                 multi = COLNO;
120                         u.last_str_turn = 0;
121                 }
122                 flags.mv = 1;
123 #ifdef QUEST
124                 if (flags.run >= 4)
125                         finddir();
126                 if (firsttime) {
127                         u.ux0 = u.ux + u.dx;
128                         u.uy0 = u.uy + u.dy;
129                 }
130 #endif /* QUEST */
131                 domove();
132                 return;
133         }
134         if ((*cmd == 'f' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
135                 flags.run = 2;
136                 goto rush;
137         }
138         if (*cmd == 'F' && movecmd(lowc(cmd[1]))) {
139                 flags.run = 3;
140                 goto rush;
141         }
142         if (*cmd == 'm' && movecmd(cmd[1])) {
143                 flags.run = 0;
144                 flags.nopick = 1;
145                 goto walk;
146         }
147         if (*cmd == 'M' && movecmd(lowc(cmd[1]))) {
148                 flags.run = 1;
149                 flags.nopick = 1;
150                 goto rush;
151         }
152 #ifdef QUEST
153         if (*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) {
154                 flags.run = 4;
155                 if (*cmd == 'F')
156                         flags.run += 2;
157                 if (cmd[2] == '-')
158                         flags.run += 1;
159                 goto rush;
160         }
161 #endif /* QUEST */
162         while (tlist->f_char) {
163                 if (*cmd == tlist->f_char) {
164                         res = (*(tlist->f_funct))();
165                         if (!res) {
166                                 flags.move = 0;
167                                 multi = 0;
168                         }
169                         return;
170                 }
171                 tlist++;
172         }
173         {
174                 char expcmd[10];
175                 char *cp = expcmd;
176                 while (*cmd && cp - expcmd < (int)sizeof(expcmd) - 2) {
177                         if (*cmd >= 040 && *cmd < 0177)
178                                 *cp++ = *cmd++;
179                         else {
180                                 *cp++ = '^';
181                                 *cp++ = *cmd++ ^ 0100;
182                         }
183                 }
184                 *cp++ = 0;
185                 pline("Unknown command '%s'.", expcmd);
186         }
187         multi = flags.move = 0;
188 }
189
190 static int
191 doextcmd(void)  /* here after # - now read a full-word command */
192 {
193         char buf[BUFSZ];
194         struct ext_func_tab *efp = extcmdlist;
195
196         pline("# ");
197         getlin(buf);
198         clrlin();
199         if (buf[0] == '\033')
200                 return (0);
201         while (efp->ef_txt) {
202                 if (!strcmp(efp->ef_txt, buf))
203                         return ((*(efp->ef_funct))());
204                 efp++;
205         }
206         pline("%s: unknown command.", buf);
207         return (0);
208 }
209
210 static char
211 lowc(char sym)
212 {
213         return ((sym >= 'A' && sym <= 'Z') ? sym + 'a' - 'A' : sym);
214 }
215
216 static char
217 unctrl(char sym)
218 {
219         return ((sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym);
220 }
221
222 /* 'rogue'-like direction commands */
223 char sdir[] = "hykulnjb><";
224 schar xdir[10] = { -1, -1, 0, 1, 1, 1, 0, -1, 0, 0 };
225 schar ydir[10] = { 0, -1, -1, -1, 0, 1, 1, 1, 0, 0 };
226 schar zdir[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, -1 };
227
228 bool
229 movecmd(char sym)       /* also sets u.dz, but returns false for <> */
230 {
231         char *dp;
232
233         u.dz = 0;
234         if (!(dp = strchr(sdir, sym)))
235                 return (0);
236         u.dx = xdir[dp - sdir];
237         u.dy = ydir[dp - sdir];
238         u.dz = zdir[dp - sdir];
239         return (!u.dz);
240 }
241
242 bool
243 getdir(bool s)
244 {
245         char dirsym;
246
247         if (s)
248                 pline("In what direction?");
249         dirsym = readchar();
250         if (!movecmd(dirsym) && !u.dz) {
251                 if (!strchr(quitchars, dirsym))
252                         pline("What a strange direction!");
253                 return (0);
254         }
255         if (Confusion && !u.dz)
256                 confdir();
257         return (1);
258 }
259
260 void
261 confdir(void)
262 {
263         int x = rn2(8);
264
265         u.dx = xdir[x];
266         u.dy = ydir[x];
267 }
268
269 #ifdef QUEST
270 void
271 finddir(void)
272 {
273         int i, ui = u.di;
274
275         for (i = 0; i <= 8; i++) {
276                 if (flags.run & 1)
277                         ui++;
278                 else
279                         ui += 7;
280                 ui %= 8;
281                 if (i == 8) {
282                         pline("Not near a wall.");
283                         flags.move = multi = 0;
284                         return;
285                 }
286                 if (!isroom(u.ux + xdir[ui], u.uy + ydir[ui]))
287                         break;
288         }
289         for (i = 0; i <= 8; i++) {
290                 if (flags.run & 1)
291                         ui += 7;
292                 else
293                         ui++;
294                 ui %= 8;
295                 if (i == 8) {
296                         pline("Not near a room.");
297                         flags.move = multi = 0;
298                         return;
299                 }
300                 if (isroom(u.ux + xdir[ui], u.uy + ydir[ui]))
301                         break;
302         }
303         u.di = ui;
304         u.dx = xdir[ui];
305         u.dy = ydir[ui];
306 }
307
308 static bool
309 isroom(int x, int y)
310 {               /* what about POOL? */
311         return (isok(x, y) && (levl[x][y].typ == ROOM ||
312                                (levl[x][y].typ >= LDOOR && flags.run >= 6)));
313 }
314 #endif /* QUEST */
315
316 bool
317 isok(int x, int y)
318 {
319         /* x corresponds to curx, so x==1 is the first column. Ach. %% */
320         return (x >= 1 && x <= COLNO - 1 && y >= 0 && y <= ROWNO - 1);
321 }
322
323 /*
324  * done2 is a function that fits into cmdlist[] (int func(void))
325  * and calls done1 which discards its argument.
326  */
327 static int
328 done2(void)
329 {
330         done1(0);
331         return (0);
332 }