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