home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource4
/
251_01
/
advexe.c
< prev
next >
Wrap
Text File
|
1987-10-29
|
6KB
|
332 lines
/* advexe.c - adventure code executer */
/*
Copyright (c) 1986, by David Michael Betz
All rights reserved
*/
#include "advint.h"
#include "advdbs.h"
/* external variables */
extern char line[];
extern int nouns[],*adjectives[];
/* local variables */
int pc,opcode,p2,p3,sts;
int stack[STKSIZE],*sp,*fp,*top;
long rseed = 1L;
/* external routines */
extern long time();
/* execute - execute adventure code */
int execute(code)
int code;
{
/* setup initial program counter */
if ((pc = code) == NIL)
return (CHAIN);
/* initialize */
sp = fp = top = stack + STKSIZE;
/* execute the code */
for (sts = 0; sts == 0; )
exe_one();
return (sts);
}
/* exe_one - execute one instruction */
exe_one()
{
/* get the opcode */
opcode = getcbyte(pc); pc++;
/* execute the instruction */
switch (opcode) {
case OP_CALL:
*--sp = getboperand();
*--sp = pc;
*--sp = (int)(top - fp);
fp = sp;
pc = getafield(fp[fp[2]+3],A_CODE);
break;
case OP_SEND:
*--sp = getboperand();
*--sp = pc;
*--sp = (int)(top - fp);
fp = sp;
if (p2 = fp[fp[2]+3])
p2 = getofield(p2,O_CLASS);
else
p2 = fp[fp[2]+2];
if (p2 && (p2 = getp(p2,fp[fp[2]+1]))) {
pc = getafield(p2,A_CODE);
break;
}
*sp = NIL;
/* return NIL if there is no method for this message */
case OP_RETURN:
if (fp == top)
sts = CHAIN;
else {
p2 = *sp;
sp = fp;
fp = top - *sp++;
pc = *sp++;
p3 = *sp++;
sp += p3;
*sp = p2;
}
break;
case OP_TSPACE:
sp -= getboperand();
break;
case OP_TMP:
p2 = getboperand();
*sp = fp[-p2-1];
break;
case OP_TSET:
p2 = getboperand();
fp[-p2-1] = *sp;
break;
case OP_ARG:
p2 = getboperand();
if (p2 >= fp[2])
error("too few arguments");
*sp = fp[p2+3];
break;
case OP_ASET:
p2 = getboperand();
if (p2 >= fp[2])
error("too few arguments");
fp[p2+3] = *sp;
break;
case OP_BRT:
pc = (*sp ? getwoperand() : pc+2);
break;
case OP_BRF:
pc = (*sp ? pc+2 : getwoperand());
break;
case OP_BR:
pc = getwoperand();
break;
case OP_T:
*sp = T;
break;
case OP_NIL:
*sp = NIL;
break;
case OP_PUSH:
*--sp = NIL;
break;
case OP_NOT:
*sp = (*sp ? NIL : T);
break;
case OP_ADD:
p2 = *sp++;
*sp += p2;
break;
case OP_SUB:
p2 = *sp++;
*sp -= p2;
break;
case OP_MUL:
p2 = *sp++;
*sp *= p2;
break;
case OP_DIV:
p2 = *sp++;
*sp = (p2 == 0 ? 0 : *sp / p2);
break;
case OP_REM:
p2 = *sp++;
*sp = (p2 == 0 ? 0 : *sp % p2);
break;
case OP_BAND:
p2 = *sp++;
*sp &= p2;
break;
case OP_BOR:
p2 = *sp++;
*sp |= p2;
break;
case OP_BNOT:
*sp = ~*sp;
break;
case OP_LT:
p2 = *sp++;
*sp = (*sp < p2 ? T : NIL);
break;
case OP_EQ:
p2 = *sp++;
*sp = (*sp == p2 ? T : NIL);
break;
case OP_GT:
p2 = *sp++;
*sp = (*sp > p2 ? T : NIL);
break;
case OP_LIT:
*sp = getwoperand();
break;
case OP_SPLIT:
*sp = getboperand();
break;
case OP_SNLIT:
*sp = -getboperand();
break;
case OP_VAR:
*sp = getvalue(getwoperand());
break;
case OP_SVAR:
*sp = getvalue(getboperand());
break;
case OP_SET:
setvalue(getwoperand(),*sp);
break;
case OP_SSET:
setvalue(getboperand(),*sp);
break;
case OP_GETP:
p2 = *sp++;
*sp = getp(*sp,p2);
break;
case OP_SETP:
p3 = *sp++;
p2 = *sp++;
*sp = setp(*sp,p2,p3);
break;
case OP_PRINT:
print(*sp);
break;
case OP_PNUMBER:
pnumber(*sp);
break;
case OP_PNOUN:
show_noun(*sp);
break;
case OP_TERPRI:
trm_chr('\n');
break;
case OP_FINISH:
sts = FINISH;
break;
case OP_CHAIN:
sts = CHAIN;
break;
case OP_ABORT:
sts = ABORT;
break;
case OP_EXIT:
#ifdef MAC
macpause();
#endif
trm_done();
exit();
break;
case OP_YORN:
trm_get(line);
*sp = (line[0] == 'Y' || line[0] == 'y' ? T : NIL);
break;
case OP_CLASS:
*sp = getofield(*sp,O_CLASS);
break;
case OP_MATCH:
p2 = *sp++;
*sp = (match(*sp,nouns[p2-1],adjectives[p2-1]) ? T : NIL);
break;
case OP_SAVE:
*sp = db_save();
break;
case OP_RESTORE:
*sp = db_restore();
break;
case OP_RESTART:
*sp = db_restart();
break;
case OP_RAND:
*sp = getrand(*sp);
break;
case OP_RNDMIZE:
setrand(time(0L));
*sp = NIL;
break;
default:
if (opcode >= OP_XVAR && opcode < OP_XSET)
*sp = getvalue(opcode - OP_XVAR);
else if (opcode >= OP_XSET && opcode < OP_XPLIT)
setvalue(opcode - OP_XSET,*sp);
else if (opcode >= OP_XPLIT && opcode < OP_XNLIT)
*sp = opcode - OP_XPLIT;
else if (opcode >= OP_XNLIT && opcode < 256)
*sp = OP_XNLIT - opcode;
else
trm_str("Bad opcode\n");
break;
}
}
/* getboperand - get data byte */
int getboperand()
{
int data;
data = getcbyte(pc); pc += 1;
return (data);
}
/* getwoperand - get data word */
int getwoperand()
{
int data;
data = getcword(pc); pc += 2;
return (data);
}
/* print - print a message */
print(msg)
int msg;
{
int ch;
msg_open(msg);
while (ch = msg_byte())
trm_chr(ch);
}
/* pnumber - print a number */
pnumber(n)
int n;
{
char buf[10];
sprintf(buf,"%d",n);
trm_str(buf);
}
/* getrand - get a random number between 0 and n-1 */
int getrand(n)
int n;
{
long k1;
/* make sure we don't get stuck at zero */
if (rseed == 0L) rseed = 1L;
/* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
k1 = rseed / 127773L;
if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
rseed += 2147483647L;
/* return a random number between 0 and n-1 */
return ((int)(rseed % (long)n));
}
/* setrand - set the random number seed */
setrand(n)
long n;
{
rseed = n;
}