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 }