Home | History | Annotate | Line # | Download | only in hack
      1 /*	$NetBSD: hack.cmd.c,v 1.12 2011/08/06 20:42:43 dholland Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
      5  * Amsterdam
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions are
     10  * met:
     11  *
     12  * - Redistributions of source code must retain the above copyright notice,
     13  * this list of conditions and the following disclaimer.
     14  *
     15  * - Redistributions in binary form must reproduce the above copyright
     16  * notice, this list of conditions and the following disclaimer in the
     17  * documentation and/or other materials provided with the distribution.
     18  *
     19  * - Neither the name of the Stichting Centrum voor Wiskunde en
     20  * Informatica, nor the names of its contributors may be used to endorse or
     21  * promote products derived from this software without specific prior
     22  * written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35  */
     36 
     37 /*
     38  * Copyright (c) 1982 Jay Fenlason <hack (at) gnu.org>
     39  * All rights reserved.
     40  *
     41  * Redistribution and use in source and binary forms, with or without
     42  * modification, are permitted provided that the following conditions
     43  * are met:
     44  * 1. Redistributions of source code must retain the above copyright
     45  *    notice, this list of conditions and the following disclaimer.
     46  * 2. Redistributions in binary form must reproduce the above copyright
     47  *    notice, this list of conditions and the following disclaimer in the
     48  *    documentation and/or other materials provided with the distribution.
     49  * 3. The name of the author may not be used to endorse or promote products
     50  *    derived from this software without specific prior written permission.
     51  *
     52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
     55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     62  */
     63 
     64 #include <sys/cdefs.h>
     65 #ifndef lint
     66 __RCSID("$NetBSD: hack.cmd.c,v 1.12 2011/08/06 20:42:43 dholland Exp $");
     67 #endif				/* not lint */
     68 
     69 #include	"hack.h"
     70 #include	"extern.h"
     71 #include	"def.func_tab.h"
     72 
     73 static int doextcmd(void);
     74 
     75 static const struct func_tab cmdlist[] = {
     76 	{ '\020', doredotopl },
     77 	{ '\022', doredraw },
     78 	{ '\024', dotele },
     79 #ifdef SUSPEND
     80 	{ '\032', dosuspend },
     81 #endif	/* SUSPEND */
     82 	{ 'a', doapply },
     83 	/* 'A' : UNUSED */
     84 	/* 'b', 'B' : go sw */
     85 	{ 'c', ddocall },
     86 	{ 'C', do_mname },
     87 	{ 'd', dodrop },
     88 	{ 'D', doddrop },
     89 	{ 'e', doeat },
     90 	{ 'E', doengrave },
     91 	/* 'f', 'F' : multiple go (might become 'fight') */
     92 	/* 'g', 'G' : UNUSED */
     93 	/* 'h', 'H' : go west */
     94 	{ 'I', dotypeinv },		/* Robert Viduya */
     95 	{ 'i', ddoinv },
     96 	/* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
     97 	/* 'o', doopen,	 */
     98 	{ 'O', doset },
     99 	{ 'p', dopay },
    100 	{ 'P', dowearring },
    101 	{ 'q', dodrink },
    102 	{ 'Q', dodone },
    103 	{ 'r', doread },
    104 	{ 'R', doremring },
    105 	{ 's', dosearch },
    106 	{ 'S', dosave },
    107 	{ 't', dothrow },
    108 	{ 'T', doremarm },
    109 	/* 'u', 'U' : go ne */
    110 	{ 'v', doversion },
    111 	/* 'V' : UNUSED */
    112 	{ 'w', dowield },
    113 	{ 'W', doweararm },
    114 	/* 'x', 'X' : UNUSED */
    115 	/* 'y', 'Y' : go nw */
    116 	{ 'z', dozap },
    117 	/* 'Z' : UNUSED */
    118 	{ '<', doup },
    119 	{ '>', dodown },
    120 	{ '/', dowhatis },
    121 	{ '?', dohelp },
    122 #ifdef SHELL
    123 	{ '!', dosh },
    124 #endif	/* SHELL */
    125 	{ '.', donull },
    126 	{ ' ', donull },
    127 	{ ',', dopickup },
    128 	{ ':', dolook },
    129 	{ '^', doidtrap },
    130 	{ '\\', dodiscovered },	/* Robert Viduya */
    131 	{ WEAPON_SYM, doprwep },
    132 	{ ARMOR_SYM, doprarm },
    133 	{ RING_SYM, doprring },
    134 	{ '$', doprgold },
    135 	{ '#', doextcmd },
    136 	{ 0, 0 }
    137 };
    138 
    139 static const struct ext_func_tab extcmdlist[] = {
    140 	{ "dip", dodip },
    141 	{ "pray", dopray },
    142 	{ NULL, donull }
    143 };
    144 
    145 static char lowc(int);
    146 static char unctrl(int);
    147 
    148 void
    149 rhack(const char *cmd)
    150 {
    151 	const struct func_tab *tlist = cmdlist;
    152 	boolean         firsttime = FALSE;
    153 	int res;
    154 
    155 	if (!cmd) {
    156 		firsttime = TRUE;
    157 		flags.nopick = 0;
    158 		cmd = parse();
    159 	}
    160 	if (!*cmd || (*cmd & 0377) == 0377 ||
    161 	    (flags.no_rest_on_space && *cmd == ' ')) {
    162 		sound_bell();
    163 		flags.move = 0;
    164 		return;		/* probably we just had an interrupt */
    165 	}
    166 	if (movecmd(*cmd)) {
    167 walk:
    168 		if (multi)
    169 			flags.mv = 1;
    170 		domove();
    171 		return;
    172 	}
    173 	if (movecmd(lowc(*cmd))) {
    174 		flags.run = 1;
    175 rush:
    176 		if (firsttime) {
    177 			if (!multi)
    178 				multi = COLNO;
    179 			u.last_str_turn = 0;
    180 		}
    181 		flags.mv = 1;
    182 #ifdef QUEST
    183 		if (flags.run >= 4)
    184 			finddir();
    185 		if (firsttime) {
    186 			u.ux0 = u.ux + u.dx;
    187 			u.uy0 = u.uy + u.dy;
    188 		}
    189 #endif	/* QUEST */
    190 		domove();
    191 		return;
    192 	}
    193 	if ((*cmd == 'f' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
    194 		flags.run = 2;
    195 		goto rush;
    196 	}
    197 	if (*cmd == 'F' && movecmd(lowc(cmd[1]))) {
    198 		flags.run = 3;
    199 		goto rush;
    200 	}
    201 	if (*cmd == 'm' && movecmd(cmd[1])) {
    202 		flags.run = 0;
    203 		flags.nopick = 1;
    204 		goto walk;
    205 	}
    206 	if (*cmd == 'M' && movecmd(lowc(cmd[1]))) {
    207 		flags.run = 1;
    208 		flags.nopick = 1;
    209 		goto rush;
    210 	}
    211 #ifdef QUEST
    212 	if (*cmd == cmd[1] && (*cmd == 'f' || *cmd == 'F')) {
    213 		flags.run = 4;
    214 		if (*cmd == 'F')
    215 			flags.run += 2;
    216 		if (cmd[2] == '-')
    217 			flags.run += 1;
    218 		goto rush;
    219 	}
    220 #endif	/* QUEST */
    221 	while (tlist->f_char) {
    222 		if (*cmd == tlist->f_char) {
    223 			res = (*(tlist->f_funct)) ();
    224 			if (!res) {
    225 				flags.move = 0;
    226 				multi = 0;
    227 			}
    228 			return;
    229 		}
    230 		tlist++;
    231 	}
    232 	{
    233 		char            expcmd[10];
    234 		char  *cp = expcmd;
    235 		while (*cmd && cp - expcmd < (int)sizeof(expcmd) - 2) {
    236 			if (*cmd >= 040 && *cmd < 0177)
    237 				*cp++ = *cmd++;
    238 			else {
    239 				*cp++ = '^';
    240 				*cp++ = *cmd++ ^ 0100;
    241 			}
    242 		}
    243 		*cp++ = 0;
    244 		pline("Unknown command '%s'.", expcmd);
    245 	}
    246 	multi = flags.move = 0;
    247 }
    248 
    249 static int
    250 doextcmd(void)
    251 {				/* here after # - now read a full-word
    252 				 * command */
    253 	char            buf[BUFSZ];
    254 	const struct ext_func_tab *efp = extcmdlist;
    255 
    256 	pline("# ");
    257 	getlin(buf);
    258 	clrlin();
    259 	if (buf[0] == '\033')
    260 		return (0);
    261 	while (efp->ef_txt) {
    262 		if (!strcmp(efp->ef_txt, buf))
    263 			return ((*(efp->ef_funct)) ());
    264 		efp++;
    265 	}
    266 	pline("%s: unknown command.", buf);
    267 	return (0);
    268 }
    269 
    270 static char
    271 lowc(int sym)
    272 {
    273 	return ((sym >= 'A' && sym <= 'Z') ? sym + 'a' - 'A' : sym);
    274 }
    275 
    276 static char
    277 unctrl(int sym)
    278 {
    279 	return ((sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym);
    280 }
    281 
    282 /* 'rogue'-like direction commands */
    283 char            sdir[] = "hykulnjb><";
    284 schar           xdir[10] = {-1, -1, 0, 1, 1, 1, 0, -1, 0, 0};
    285 schar           ydir[10] = {0, -1, -1, -1, 0, 1, 1, 1, 0, 0};
    286 static schar    zdir[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, -1};
    287 
    288 int
    289 movecmd(int sym)		/* also sets u.dz, but returns false for <> */
    290 {
    291 	char  *dp;
    292 
    293 	u.dz = 0;
    294 	if (!(dp = strchr(sdir, sym)))
    295 		return (0);
    296 	u.dx = xdir[dp - sdir];
    297 	u.dy = ydir[dp - sdir];
    298 	u.dz = zdir[dp - sdir];
    299 	return (!u.dz);
    300 }
    301 
    302 int
    303 getdir(boolean s)
    304 {
    305 	char            dirsym;
    306 
    307 	if (s)
    308 		pline("In what direction?");
    309 	dirsym = readchar();
    310 	if (!movecmd(dirsym) && !u.dz) {
    311 		if (!strchr(quitchars, dirsym))
    312 			pline("What a strange direction!");
    313 		return (0);
    314 	}
    315 	if (Confusion && !u.dz)
    316 		confdir();
    317 	return (1);
    318 }
    319 
    320 void
    321 confdir(void)
    322 {
    323 	int x = rn2(8);
    324 	u.dx = xdir[x];
    325 	u.dy = ydir[x];
    326 }
    327 
    328 #ifdef QUEST
    329 int
    330 finddir(void)
    331 {
    332 	int    i, ui = u.di;
    333 	for (i = 0; i <= 8; i++) {
    334 		if (flags.run & 1)
    335 			ui++;
    336 		else
    337 			ui += 7;
    338 		ui %= 8;
    339 		if (i == 8) {
    340 			pline("Not near a wall.");
    341 			flags.move = multi = 0;
    342 			return (0);
    343 		}
    344 		if (!isroom(u.ux + xdir[ui], u.uy + ydir[ui]))
    345 			break;
    346 	}
    347 	for (i = 0; i <= 8; i++) {
    348 		if (flags.run & 1)
    349 			ui += 7;
    350 		else
    351 			ui++;
    352 		ui %= 8;
    353 		if (i == 8) {
    354 			pline("Not near a room.");
    355 			flags.move = multi = 0;
    356 			return (0);
    357 		}
    358 		if (isroom(u.ux + xdir[ui], u.uy + ydir[ui]))
    359 			break;
    360 	}
    361 	u.di = ui;
    362 	u.dx = xdir[ui];
    363 	u.dy = ydir[ui];
    364 	return 0;
    365 }
    366 
    367 int
    368 isroom(int x, int y)
    369 {				/* what about POOL? */
    370 	return (isok(x, y) && (levl[x][y].typ == ROOM ||
    371 			       (levl[x][y].typ >= LDOOR && flags.run >= 6)));
    372 }
    373 #endif	/* QUEST */
    374 
    375 int
    376 isok(int x, int y)
    377 {
    378 	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
    379 	return (x >= 1 && x <= COLNO - 1 && y >= 0 && y <= ROWNO - 1);
    380 }
    381