pc-hack

PC HACK 3.61 source code (archival)
git clone http://frotz.net/git/pc-hack.git
Log | Files | Refs

cmd.c (7907B)


      1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
      2 /* cmd.c - version 1.0.3 */
      3 
      4 #include	"hack.h"
      5 
      6 int doredraw(),doredotopl(),dodrop(),dodrink(),doread(),dosearch(),dopickup(),
      7 doversion(),doweararm(),dowearring(),doremarm(),doremring(),dopay(),doapply(),
      8 dosave(),dowield(),ddoinv(),dozap(),ddocall(),dowhatis(),doengrave(),dotele(),
      9 dohelp(),doeat(),doddrop(),do_mname(),doidtrap(),doprwep(),doprarm(),
     10 doprring(),doprgold(),dodiscovered(),dotypeinv(),dolook(),doset(),
     11 doup(), dodown(), done1(), donull(), dothrow(), doextcmd(), dodip(), dopray();
     12 #ifdef SHELL
     13 int dosh();
     14 #endif
     15 #ifdef SUSPEND
     16 int dosuspend();
     17 #endif
     18 
     19 # ifdef DGK
     20 extern int (*occupation)();
     21 extern int occtime;
     22 extern char *occtxt;			/* defined when occupation != NULL */
     23 int dotogglepickup(), doMSCversion();
     24 # ifdef DEBUG
     25 int dodebug();
     26 # endif
     27 static int (*timed_occ_fn)();
     28 
     29 /* Count down by decrementing multi */
     30 timed_occupation() {
     31 	(*timed_occ_fn)();
     32 	if (multi > 0)
     33 		multi--;
     34 	return (multi > 0);
     35 }
     36 
     37 /* If a time is given, use it to timeout this function, otherwise the
     38  * function times out by its own means.
     39  */
     40 void
     41 set_occupation(fn, txt, time)
     42 int (*fn)();
     43 char *txt;
     44 {
     45 	if (time) {
     46 		occupation = timed_occupation;
     47 		timed_occ_fn = fn;
     48 	} else
     49 		occupation = fn;
     50 	occtxt = txt;
     51 	occtime = 0;
     52 }
     53 
     54 # ifdef REDO
     55 /* Provide a means to redo the last command.  The flag `in_doagain' is set
     56  * to true while redoing the command.  This flag is tested in commands that
     57  * require additional input (like `throw' which requires a thing and a
     58  * direction), and the input prompt is not shown.  Also, while in_doagain is
     59  * TRUE, no keystrokes can be saved into the saveq.
     60  */
     61 #define BSIZE 20
     62 static char pushq[BSIZE], saveq[BSIZE];
     63 static int phead, ptail, shead, stail;
     64 int in_doagain;
     65 
     66 char
     67 popch() {
     68 	/* If occupied, return 0, letting tgetch know a character should
     69 	 * be read from the keyboard.  If the character read is not the
     70 	 * ABORT character (as checked in main.c), that character will be
     71 	 * pushed back on the pushq.
     72 	 */
     73 	if (occupation)
     74 		return 0;
     75 	if (in_doagain)
     76 		return ((shead != stail) ? saveq[stail++] : 0);
     77 	else
     78 		return ((phead != ptail) ? pushq[ptail++] : 0);
     79 }
     80 
     81 /* A ch == 0 resets the pushq */
     82 void
     83 pushch(ch)
     84 char ch;
     85 {
     86 	if (!ch)
     87 		phead = ptail = 0;
     88 	if (phead < BSIZE)
     89 		pushq[phead++] = ch;
     90 }
     91 
     92 /* A ch == 0 resets the saveq.  Only save keystrokes when not
     93  * replaying a previous command.
     94  */
     95 void
     96 savech(ch)
     97 char ch;
     98 {
     99 	if (!in_doagain) {
    100 		if (!ch)
    101 			phead = ptail = shead = stail = 0;
    102 		else if (shead < BSIZE)
    103 			saveq[shead++] = ch;
    104 	}
    105 }
    106 # endif /* REDO */
    107 #endif /* DGK */
    108 
    109 struct func_tab {
    110 	char f_char;
    111 	int (*f_funct)();
    112 	char *f_text;
    113 };
    114 
    115 struct ext_func_tab {
    116 	char *ef_txt;
    117 	int (*ef_funct)();
    118 };
    119 
    120 struct func_tab cmdlist[]={
    121 	{'\020', doredotopl},
    122 	{'\022', doredraw},
    123 	{'\024', dotele},
    124 #ifdef SUSPEND
    125 	{'\032', dosuspend},
    126 #endif
    127 	{'A', doapply},
    128 /*	'b', 'B' : go sw */
    129 	{'c', ddocall},
    130 	{'C', do_mname},
    131 	{'d', dodrop},
    132 	{'D', doddrop},
    133 	{'e', doeat},
    134 	{'E', doengrave},
    135 /* Soon to be
    136 	{'f', dofight, "fighting"},
    137 	{'F', doFight, "fighting"},
    138  */
    139 /*	'g', 'G' : multiple go */
    140 /*	'h', 'H' : go west */
    141 	{'I', dotypeinv}, 		/* Robert Viduya */
    142 	{'i', ddoinv},
    143 /*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
    144 /*	'o', doopen,	*/
    145 	{'O', doset},
    146 	{'p', dopay},
    147 	{'P', dowearring},
    148 	{'q', dodrink},
    149 	{'Q', done1},
    150 	{'r', doread},
    151 	{'R', doremring},
    152 	{'s', dosearch, "searching"},
    153 	{'S', dosave},
    154 	{'t', dothrow},
    155 	{'T', doremarm},
    156 /*	'u', 'U' : go ne */
    157 	{'v', doversion},
    158 /*	'V' : UNUSED */
    159 	{'w', dowield},
    160 	{'W', doweararm},
    161 /*	'x', 'X' : UNUSED */
    162 /*	'y', 'Y' : go nw */
    163 	{'z', dozap},
    164 /*	'Z' : UNUSED */
    165 	{'<', doup},
    166 	{'>', dodown},
    167 	{'/', dowhatis},
    168 	{'?', dohelp},
    169 #ifdef SHELL
    170 	{'!', dosh},
    171 #endif
    172 	{'.', donull, "waiting"},
    173 	{' ', donull, "waiting"},
    174 	{',', dopickup},
    175 	{':', dolook},
    176 	{'^', doidtrap},
    177 	{'\\', dodiscovered},		/* Robert Viduya */
    178 #ifdef DGK
    179 	{'@', dotogglepickup},
    180 	{'V', doMSCversion},
    181 # ifdef DEBUG
    182 	{'\004', dodebug},	/* generic debug function */
    183 # endif
    184 #endif
    185 	{WEAPON_SYM, doprwep},
    186 	{ARMOR_SYM, doprarm},
    187 	{RING_SYM, doprring},
    188 	{'$', doprgold},
    189 	{'#', doextcmd},
    190 	{0,0}
    191 };
    192 
    193 struct ext_func_tab extcmdlist[] = {
    194 	"dip", dodip,
    195 	"pray", dopray,
    196 	(char *) 0, donull
    197 };
    198 
    199 extern char *parse(), lowc(), unctrl(), quitchars[];
    200 
    201 rhack(cmd)
    202 register char *cmd;
    203 {
    204 	register struct func_tab *tlist = cmdlist;
    205 	boolean firsttime = FALSE;
    206 	register res;
    207 
    208 	if(!cmd) {
    209 		firsttime = TRUE;
    210 		flags.nopick = 0;
    211 		cmd = parse();
    212 	}
    213 #ifdef DGK
    214 # ifdef REDO
    215 	if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
    216 		in_doagain = TRUE;
    217 		stail = 0;
    218 		rhack((char *) 0);	/* read and execute command */
    219 		in_doagain = FALSE;
    220 		return;
    221 	}
    222 # endif
    223 
    224 	/* Special case of *cmd == ' ' handled better below */
    225 	if(!*cmd || *cmd == 0377) {
    226 #else
    227 	if(!*cmd || *cmd == 0377 || (flags.no_rest_on_space && *cmd == ' ')){
    228 #endif
    229 		bell();
    230 		flags.move = 0;
    231 		return 0;	/* probably we just had an interrupt */
    232 	}
    233 	if(movecmd(*cmd)) {
    234 	walk:
    235 		if(multi) flags.mv = 1;
    236 		domove();
    237 		return;
    238 	}
    239 	if(movecmd(lowc(*cmd))) {
    240 		flags.run = 1;
    241 	rush:
    242 		if(firsttime){
    243 			if(!multi) multi = COLNO;
    244 			u.last_str_turn = 0;
    245 		}
    246 		flags.mv = 1;
    247 		domove();
    248 		return;
    249 	}
    250 	if((*cmd == 'g' && movecmd(cmd[1])) || movecmd(unctrl(*cmd))) {
    251 		flags.run = 2;
    252 		goto rush;
    253 	}
    254 	if(*cmd == 'G' && movecmd(lowc(cmd[1]))) {
    255 		flags.run = 3;
    256 		goto rush;
    257 	}
    258 	if(*cmd == 'm' && movecmd(cmd[1])) {
    259 		flags.run = 0;
    260 		flags.nopick = 1;
    261 		goto walk;
    262 	}
    263 	if(*cmd == 'M' && movecmd(lowc(cmd[1]))) {
    264 		flags.run = 1;
    265 		flags.nopick = 1;
    266 		goto rush;
    267 	}
    268 	while(tlist->f_char) {
    269 		if(*cmd == tlist->f_char){
    270 #ifdef DGK
    271 			/* Special case of *cmd == ' ' handled here */
    272 			if (*cmd == ' ' && flags.no_rest_on_space)
    273 				break;
    274 
    275 			/* Now control-A can stop lengthy commands */
    276 			if (tlist->f_text && !occupation && multi)
    277 				set_occupation(tlist->f_funct, tlist->f_text,
    278 					multi);
    279 #endif
    280 			res = (*(tlist->f_funct))();
    281 			if(!res) {
    282 				flags.move = 0;
    283 				multi = 0;
    284 			}
    285 			return;
    286 		}
    287 		tlist++;
    288 	}
    289 	{ char expcmd[10];
    290 	  register char *cp = expcmd;
    291 	  while(*cmd && cp-expcmd < sizeof(expcmd)-2) {
    292 		if(*cmd >= 040 && *cmd < 0177)
    293 			*cp++ = *cmd++;
    294 		else {
    295 			*cp++ = '^';
    296 			*cp++ = *cmd++ ^ 0100;
    297 		}
    298 	  }
    299 	  *cp++ = 0;
    300 	  pline("Unknown command '%s'.", expcmd);
    301 	}
    302 	multi = flags.move = 0;
    303 }
    304 
    305 doextcmd()	/* here after # - now read a full-word command */
    306 {
    307 	char buf[BUFSZ];
    308 	register struct ext_func_tab *efp = extcmdlist;
    309 
    310 	pline("# ");
    311 	getlin(buf);
    312 	clrlin();
    313 	if(buf[0] == '\033')
    314 		return(0);
    315 	while(efp->ef_txt) {
    316 		if(!strcmp(efp->ef_txt, buf))
    317 			return((*(efp->ef_funct))());
    318 		efp++;
    319 	}
    320 	pline("%s: unknown command.", buf);
    321 	return(0);
    322 }
    323 
    324 char
    325 lowc(sym)
    326 char sym;
    327 {
    328     return( (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym );
    329 }
    330 
    331 char
    332 unctrl(sym)
    333 char sym;
    334 {
    335     return( (sym >= ('A' & 037) && sym <= ('Z' & 037)) ? sym + 0140 : sym );
    336 }
    337 
    338 /* 'rogue'-like direction commands */
    339 char sdir[] = "hykulnjb><";
    340 schar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 };
    341 schar ydir[10] = {  0,-1,-1,-1, 0, 1, 1, 1, 0, 0 };
    342 schar zdir[10] = {  0, 0, 0, 0, 0, 0, 0, 0, 1,-1 };
    343 
    344 movecmd(sym)	/* also sets u.dz, but returns false for <> */
    345 char sym;
    346 {
    347 	register char *dp;
    348 
    349 	u.dz = 0;
    350 	if(!(dp = index(sdir, sym))) return(0);
    351 	u.dx = xdir[dp-sdir];
    352 	u.dy = ydir[dp-sdir];
    353 	u.dz = zdir[dp-sdir];
    354 	return(!u.dz);
    355 }
    356 
    357 getdir(s)
    358 boolean s;
    359 {
    360 	char dirsym;
    361 
    362 #ifdef REDO
    363 	if (!in_doagain)
    364 #endif
    365 	if(s) pline("In what direction?");
    366 	dirsym = readchar();
    367 #ifdef REDO
    368 	savech(dirsym);
    369 #endif
    370 	if(!movecmd(dirsym) && !u.dz) {
    371 		if(!index(quitchars, dirsym))
    372 			pline("What a strange direction!");
    373 		return(0);
    374 	}
    375 	if(Confusion && !u.dz)
    376 		confdir();
    377 	return(1);
    378 }
    379 
    380 confdir()
    381 {
    382 	register x = rn2(8);
    383 	u.dx = xdir[x];
    384 	u.dy = ydir[x];
    385 }
    386 
    387 isok(x,y) register x,y; {
    388 	/* x corresponds to curx, so x==1 is the first column. Ach. %% */
    389 	return(x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1);
    390 }