home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume2 / advsys / part03 / advexe.c < prev    next >
C/C++ Source or Header  |  1987-10-23  |  6KB  |  333 lines

  1.  
  2. /* advexe.c - adventure code executer */
  3. /*
  4.     Copyright (c) 1986, by David Michael Betz
  5.     All rights reserved
  6. */
  7.  
  8. #include "advint.h"
  9. #include "advdbs.h"
  10.  
  11. /* external variables */
  12. extern char line[];
  13. extern int nouns[],*adjectives[];
  14.  
  15. /* local variables */
  16. int pc,opcode,p2,p3,sts;
  17. int stack[STKSIZE],*sp,*fp,*top;
  18. long rseed = 1L;
  19.  
  20. /* external routines */
  21. extern long time();
  22.  
  23. /* execute - execute adventure code */
  24. int execute(code)
  25.   int code;
  26. {
  27.     /* setup initial program counter */
  28.     if ((pc = code) == NIL)
  29.     return (CHAIN);
  30.  
  31.     /* initialize */
  32.     sp = fp = top = stack + STKSIZE;
  33.  
  34.     /* execute the code */
  35.     for (sts = 0; sts == 0; )
  36.     exe_one();
  37.  
  38.     return (sts);
  39. }
  40.  
  41. /* exe_one - execute one instruction */
  42. exe_one()
  43. {
  44.     /* get the opcode */
  45.     opcode = getcbyte(pc); pc++;
  46.  
  47.     /* execute the instruction */
  48.     switch (opcode) {
  49.     case OP_CALL:
  50.         *--sp = getboperand();
  51.         *--sp = pc;
  52.         *--sp = (int)(top - fp);
  53.         fp = sp;
  54.         pc = getafield(fp[fp[2]+3],A_CODE);
  55.         break;
  56.     case OP_SEND:
  57.         *--sp = getboperand();
  58.         *--sp = pc;
  59.         *--sp = (int)(top - fp);
  60.         fp = sp;
  61.         if (p2 = fp[fp[2]+3])
  62.             p2 = getofield(p2,O_CLASS);
  63.         else
  64.             p2 = fp[fp[2]+2];
  65.         if (p2 && (p2 = getp(p2,fp[fp[2]+1]))) {
  66.             pc = getafield(p2,A_CODE);
  67.             break;
  68.         }
  69.         *sp = NIL;
  70.         /* return NIL if there is no method for this message */
  71.     case OP_RETURN:
  72.         if (fp == top)
  73.             sts = CHAIN;
  74.         else {
  75.             p2 = *sp;
  76.             sp = fp;
  77.             fp = top - *sp++;
  78.             pc = *sp++;
  79.             p3 = *sp++;
  80.             sp += p3;
  81.             *sp = p2;
  82.         }
  83.         break;
  84.     case OP_TSPACE:
  85.         sp -= getboperand();
  86.         break;
  87.     case OP_TMP:
  88.         p2 = getboperand();
  89.         *sp = fp[-p2-1];
  90.         break;
  91.     case OP_TSET:
  92.         p2 = getboperand();
  93.         fp[-p2-1] = *sp;
  94.         break;
  95.     case OP_ARG:
  96.         p2 = getboperand();
  97.         if (p2 >= fp[2])
  98.             error("too few arguments");
  99.         *sp = fp[p2+3];
  100.         break;
  101.     case OP_ASET:
  102.         p2 = getboperand();
  103.         if (p2 >= fp[2])
  104.             error("too few arguments");
  105.         fp[p2+3] = *sp;
  106.         break;
  107.     case OP_BRT:
  108.         pc = (*sp ? getwoperand() : pc+2);
  109.         break;
  110.     case OP_BRF:
  111.         pc = (*sp ? pc+2 : getwoperand());
  112.         break;
  113.     case OP_BR:
  114.         pc = getwoperand();
  115.         break;
  116.     case OP_T:
  117.         *sp = T;
  118.         break;
  119.     case OP_NIL:
  120.         *sp = NIL;
  121.         break;
  122.     case OP_PUSH:
  123.         *--sp = NIL;
  124.         break;
  125.     case OP_NOT:
  126.         *sp = (*sp ? NIL : T);
  127.         break;
  128.     case OP_ADD:
  129.         p2 = *sp++;
  130.         *sp += p2;
  131.         break;
  132.     case OP_SUB:
  133.         p2 = *sp++;
  134.         *sp -= p2;
  135.         break;
  136.     case OP_MUL:
  137.         p2 = *sp++;
  138.         *sp *= p2;
  139.         break;
  140.     case OP_DIV:
  141.         p2 = *sp++;
  142.         *sp = (p2 == 0 ? 0 : *sp / p2);
  143.         break;
  144.     case OP_REM:
  145.         p2 = *sp++;
  146.         *sp = (p2 == 0 ? 0 : *sp % p2);
  147.         break;
  148.     case OP_BAND:
  149.         p2 = *sp++;
  150.         *sp &= p2;
  151.         break;
  152.     case OP_BOR:
  153.         p2 = *sp++;
  154.         *sp |= p2;
  155.         break;
  156.     case OP_BNOT:
  157.         *sp = ~*sp;
  158.         break;
  159.     case OP_LT:
  160.         p2 = *sp++;
  161.         *sp = (*sp < p2 ? T : NIL);
  162.         break;
  163.     case OP_EQ:
  164.         p2 = *sp++;
  165.         *sp = (*sp == p2 ? T : NIL);
  166.         break;
  167.     case OP_GT:
  168.         p2 = *sp++;
  169.         *sp = (*sp > p2 ? T : NIL);
  170.         break;
  171.     case OP_LIT:
  172.         *sp = getwoperand();
  173.         break;
  174.     case OP_SPLIT:
  175.         *sp = getboperand();
  176.         break;
  177.     case OP_SNLIT:
  178.         *sp = -getboperand();
  179.         break;
  180.     case OP_VAR:
  181.         *sp = getvalue(getwoperand());
  182.         break;
  183.     case OP_SVAR:
  184.         *sp = getvalue(getboperand());
  185.         break;
  186.     case OP_SET:
  187.         setvalue(getwoperand(),*sp);
  188.         break;
  189.     case OP_SSET:
  190.         setvalue(getboperand(),*sp);
  191.         break;
  192.     case OP_GETP:
  193.         p2 = *sp++;
  194.         *sp = getp(*sp,p2);
  195.         break;
  196.     case OP_SETP:
  197.         p3 = *sp++;
  198.         p2 = *sp++;
  199.         *sp = setp(*sp,p2,p3);
  200.         break;
  201.     case OP_PRINT:
  202.         print(*sp);
  203.         break;
  204.     case OP_PNUMBER:
  205.             pnumber(*sp);
  206.             break;
  207.     case OP_PNOUN:
  208.         show_noun(*sp);
  209.         break;
  210.     case OP_TERPRI:
  211.         trm_chr('\n');
  212.         break;
  213.     case OP_FINISH:
  214.         sts = FINISH;
  215.         break;
  216.     case OP_CHAIN:
  217.         sts = CHAIN;
  218.         break;
  219.     case OP_ABORT:
  220.         sts = ABORT;
  221.         break;
  222.     case OP_EXIT:
  223. #ifdef MAC
  224.         macpause();
  225. #endif
  226.         trm_done();
  227.         exit();
  228.         break;
  229.     case OP_YORN:
  230.         trm_get(line);
  231.         *sp = (line[0] == 'Y' || line[0] == 'y' ? T : NIL);
  232.             break;
  233.     case OP_CLASS:
  234.         *sp = getofield(*sp,O_CLASS);
  235.         break;
  236.     case OP_MATCH:
  237.         p2 = *sp++;
  238.         *sp = (match(*sp,nouns[p2-1],adjectives[p2-1]) ? T : NIL);
  239.         break;
  240.     case OP_SAVE:
  241.         *sp = db_save();
  242.         break;
  243.     case OP_RESTORE:
  244.         *sp = db_restore();
  245.         break;
  246.     case OP_RESTART:
  247.         *sp = db_restart();
  248.         break;
  249.     case OP_RAND:
  250.         *sp = getrand(*sp);
  251.         break;
  252.     case OP_RNDMIZE:
  253.         setrand(time(0L));
  254.         *sp = NIL;
  255.         break;
  256.     default:
  257.         if (opcode >= OP_XVAR && opcode < OP_XSET)
  258.         *sp = getvalue(opcode - OP_XVAR);
  259.         else if (opcode >= OP_XSET && opcode < OP_XPLIT)
  260.         setvalue(opcode - OP_XSET,*sp);
  261.         else if (opcode >= OP_XPLIT && opcode < OP_XNLIT)
  262.         *sp = opcode - OP_XPLIT;
  263.         else if (opcode >= OP_XNLIT && opcode < 256)
  264.         *sp = OP_XNLIT - opcode;
  265.         else
  266.         trm_str("Bad opcode\n");
  267.         break;
  268.     }
  269. }
  270.  
  271. /* getboperand - get data byte */
  272. int getboperand()
  273. {
  274.     int data;
  275.     data = getcbyte(pc); pc += 1;
  276.     return (data);
  277. }
  278.  
  279. /* getwoperand - get data word */
  280. int getwoperand()
  281. {
  282.     int data;
  283.     data = getcword(pc); pc += 2;
  284.     return (data);
  285. }
  286.  
  287. /* print - print a message */
  288. print(msg)
  289.   int msg;
  290. {
  291.     int ch;
  292.  
  293.     msg_open(msg);
  294.     while (ch = msg_byte())
  295.     trm_chr(ch);
  296. }
  297.  
  298. /* pnumber - print a number */
  299. pnumber(n)
  300.   int n;
  301. {
  302.     char buf[10];
  303.  
  304.     sprintf(buf,"%d",n);
  305.     trm_str(buf);
  306. }
  307.  
  308. /* getrand - get a random number between 0 and n-1 */
  309. int getrand(n)
  310.   int n;
  311. {
  312.     long k1;
  313.  
  314.     /* make sure we don't get stuck at zero */
  315.     if (rseed == 0L) rseed = 1L;
  316.  
  317.     /* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
  318.     k1 = rseed / 127773L;
  319.     if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
  320.     rseed += 2147483647L;
  321.  
  322.     /* return a random number between 0 and n-1 */
  323.     return ((int)(rseed % (long)n));
  324. }
  325.  
  326. /* setrand - set the random number seed */
  327. setrand(n)
  328.   long n;
  329. {
  330.     rseed = n;
  331. }
  332.  
  333.